Skip to content

অধ্যায় ৭: পিডিএফ ইনভয়েস তৈরি করা

আমাদের প্যাকেজ এখন ইনভয়েসের ডেটা ডাটাবেসে সংরক্ষণ করতে পারে। কিন্তু একজন ব্যবহারকারীর জন্য চূড়ান্ত লক্ষ্য হলো এই ইনভয়েসটি গ্রাহককে পাঠানো। এর জন্য সবচেয়ে পেশাদার এবং স্ট্যান্ডার্ড ফরম্যাট হলো PDF। এই অধ্যায়ে আমরা শিখব কীভাবে আমাদের প্যাকেজের মাধ্যমে একটি ইনভয়েসের সুন্দর পিডিএফ সংস্করণ তৈরি এবং ডাউনলোড করা যায়।

৭.১ লক্ষ্য: ইনভয়েসের পিডিএফ তৈরি ও ডাউনলোড

আমাদের লক্ষ্য হলো:

  1. পিডিএফ তৈরির জন্য একটি জনপ্রিয় লাইব্রেরি (mpdf/mpdf) ইনস্টল করা।
  2. পিডিএফ তৈরির লজিক পরিচালনা করার জন্য একটি PdfGeneratorService তৈরি করা।
  3. পিডিএফের জন্য একটি বিশেষ, প্রিন্ট-ফ্রেন্ডলি ব্লেড ভিউ তৈরি করা।
  4. একটি "Download PDF" বাটন যোগ করা, যা ক্লিক করলে ব্যবহারকারী ইনভয়েসের পিডিএফ ফাইলটি ডাউনলোড করতে পারবে।

৭.২ Step 1: mPDF লাইব্রেরি ইনস্টল করা

প্রথমে, আমাদের প্যাকেজের composer.json ফাইলে mpdf/mpdf লাইব্রেরিটি require সেকশনে যোগ করতে হবে।

json
// packages/DevMaster/InvoiceBuilder/composer.json
"require": {
    "php": "^8.1",
    "illuminate/support": "^10.0|^11.0",
    "mpdf/mpdf": "^8.1"
},

ফাইলটি সেভ করার পর, আপনার প্যাকেজের রুট ডিরেক্টরি থেকে composer update কমান্ডটি চালান।

৭.৩ Step 2: PdfGeneratorService তৈরি

পিডিএফ তৈরির সমস্ত লজিক আমরা একটি ডেডিকেটেড সার্ভিস ক্লাসে রাখব। src/Services/PdfGeneratorService.php ফাইলটি তৈরি করুন:

php
<?php

namespace DevMaster\InvoiceBuilder\Services;

use DevMaster\InvoiceBuilder\Models\Invoice;
use Mpdf\Mpdf;

class PdfGeneratorService
{
    public function generate(Invoice $invoice): string
    {
        // ইনভয়েসের ডেটা এবং আইটেমগুলো লোড করা
        $invoice->load('items');

        // ব্লেড ভিউকে HTML স্ট্রিং-এ রেন্ডার করা
        $html = view('invoice-builder::pdf.invoice', ['invoice' => $invoice])->render();

        // mPDF অবজেক্ট তৈরি করা
        $mpdf = new Mpdf();

        // HTML থেকে পিডিএফ তৈরি করা
        $mpdf->WriteHTML($html);

        // পিডিএফ কনটেন্টকে স্ট্রিং হিসেবে রিটার্ন করা
        return $mpdf->Output('', 'S');
    }
}
  • Output('', 'S'): এই মেথডটি mPDF-কে বলে যে, পিডিএফ ফাইলটি ব্রাউজারে দেখানোর পরিবর্তে এর কনটেন্টকে একটি স্ট্রিং হিসেবে রিটার্ন করতে হবে।

৭.৪ Step 3: পিডিএফের জন্য ব্লেড ভিউ তৈরি

আমাদের ওয়েব ভিউতে অনেক অপ্রয়োজনীয় জিনিস (যেমন বাটন, মেনু) থাকতে পারে যা আমরা পিডিএফে চাই না। তাই আমরা পিডিএফের জন্য একটি আলাদা, পরিচ্ছন্ন ভিউ তৈরি করব।

resources/views/pdf ডিরেক্টরি এবং তার ভেতরে invoice.blade.php ফাইল তৈরি করুন:

bash
mkdir -p resources/views/pdf
touch resources/views/pdf/invoice.blade.php

invoice.blade.php ফাইলে নিচের কোডটি লিখুন:

blade
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Invoice #{{ $invoice->number }}</title>
    <style>
        body { font-family: sans-serif; font-size: 12px; }
        h1 { font-size: 18px; }
        table { width: 100%; border-collapse: collapse; }
        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
        th { background-color: #f2f2f2; }
        .text-right { text-align: right; }
    </style>
</head>
<body>
    <h1>Invoice #{{ $invoice->number }}</h1>
    <p><strong>Status:</strong> {{ ucfirst($invoice->status) }}</p>
    <p><strong>Date:</strong> {{ $invoice->created_at->format('Y-m-d') }}</p>
    <hr>
    <h3>Items</h3>
    <table>
        <thead>
            <tr>
                <th>Item</th>
                <th>Price</th>
            </tr>
        </thead>
        <tbody>
            @foreach($invoice->items as $item)
                <tr>
                    <td>{{ $item->description }}</td>
                    <td class="text-right">${{ number_format($item->unit_price, 2) }}</td>
                </tr>
            @endforeach
        </tbody>
    </table>
    <h2 class="text-right">Total: ${{ number_format($invoice->total, 2) }}</h2>
</body>
</html>

৭.৫ Step 4: সার্ভিস এবং রাউট রেজিস্টার করা

১. সার্ভিস বাইন্ড করুন:InvoiceBuilderServiceProvider-এর register() মেথডে PdfGeneratorService-কে বাইন্ড করুন। এটি একটি স্টেটলেস সার্ভিস, তাই singleton ব্যবহার করা যেতে পারে।

php
// InvoiceBuilderServiceProvider.php -> register()
use DevMaster\InvoiceBuilder\Services\PdfGeneratorService;

// ...
$this->app->singleton(PdfGeneratorService::class, function () {
    return new PdfGeneratorService();
});

২. ডাউনলোড রাউট এবং কন্ট্রোলার মেথড যোগ করুন:

  • routes/web.php ফাইলে নতুন রাউট যোগ করুন:
php
// routes/web.php
Route::get('/{invoice}/download', [InvoiceController::class, 'download'])->name('invoices.download');
  • InvoiceController-এ PdfGeneratorService ইনজেক্ট করুন এবং download মেথডটি তৈরি করুন:
php
<?php
// InvoiceController.php
namespace DevMaster\InvoiceBuilder\Http\Controllers;

use DevMaster\InvoiceBuilder\Models\Invoice;
use DevMaster\InvoiceBuilder\Services\PdfGeneratorService; // ইম্পোর্ট করুন
use Illuminate\Routing\Controller;

class InvoiceController extends Controller
{
    protected PdfGeneratorService $pdfService;

    // কনস্ট্রাক্টরে সার্ভিস ইনজেক্ট করুন
    public function __construct(PdfGeneratorService $pdfService)
    {
        $this->pdfService = $pdfService;
    }

    // ... index() and store() methods

    public function download(Invoice $invoice)
    {
        // পলিসি চেক (যদি থাকে)
        // $this->authorize('view', $invoice);

        $pdfContent = $this->pdfService->generate($invoice);

        return response($pdfContent)
            ->header('Content-Type', 'application/pdf')
            ->header('Content-Disposition', 'attachment; filename="invoice-'.$invoice->number.'.pdf"');
    }
}
  • response($pdfContent): আমরা পিডিএফের স্ট্রিং কনটেন্টকে একটি রেসপন্সের বডি হিসেবে পাঠাচ্ছি।
  • header(): আমরা দুটি গুরুত্বপূর্ণ HTTP হেডার সেট করছি। Content-Type ব্রাউজারকে বলে যে এটি একটি পিডিএফ ফাইল এবং Content-Disposition ফাইলটির নাম কী হবে এবং এটিকে অ্যাটাচমেন্ট হিসেবে ডাউনলোড করতে হবে তা বলে দেয়।

৭.৬ Step 5: ভিউতে ডাউনলোড লিংক যোগ করা

সবশেষে, আমাদের index.blade.php ভিউতে প্রতিটি ইনভয়েসের পাশে একটি ডাউনলোড লিংক যোগ করতে হবে।

resources/views/index.blade.php-এর টেবিল অংশটি আপডেট করুন:

blade
// ... <thead> section
<tbody>
    @forelse ($invoices as $invoice)
        <tr>
            <td>{{ $invoice->number }}</td>
            <td>${{ $invoice->total }}</td>
            <td>{{ $invoice->status }}</td>
            <td>{{ $invoice->created_at->format('Y-m-d') }}</td>
            <td>
                <a href="{{ route('invoices.download', $invoice) }}">Download PDF</a>
            </td>
        </tr>
    @empty
        <tr>
            <td colspan="5">No invoices found.</td>
        </tr>
    @endforelse
</tbody>

নোট: টেবিল হেডার এবং colspan-এ একটি নতুন কলাম (<td>) যোগ করতে ভুলবেন না।

যাচাইকরণ:

  • ব্রাউজারে /invoices পেজটি রিলোড করুন।
  • একটি ইনভয়েসের পাশের "Download PDF" লিঙ্কে ক্লিক করুন।
  • আপনার ব্রাউজার স্বয়ংক্রিয়ভাবে invoice-INV-....pdf নামে একটি ফাইল ডাউনলোড শুরু করবে। ফাইলটি খুললে আপনি আপনার তৈরি করা ইনভয়েসের পিডিএফ সংস্করণ দেখতে পাবেন।

আপনি সফলভাবে আপনার প্যাকেজে পিডিএফ তৈরির মতো একটি জটিল এবং অত্যন্ত গুরুত্বপূর্ণ ফিচার যুক্ত করেছেন।

পরবর্তী অধ্যায়ে আমরা কাস্টম artisan কমান্ড তৈরি করা শিখব, যা দিয়ে আমরা প্যাকেজ ইনস্টলেশনকে স্বয়ংক্রিয় করব।