@php // Scaling is restricted to regular sales invoices, not proformas or cash documents. $allowsPdfScaling = !($isProforma ?? false) && ($sale->mode ?? null) === 'bill' && ($sale->bill_type ?? null) === 'bill'; $pdfScale = $allowsPdfScaling && in_array($pdfScale ?? 100, [50, 60, 70, 80, 90, 100], true) ? $pdfScale : 100; $scaleRatio = $pdfScale / 100; $scaledPaddingY = number_format(2 * $scaleRatio, 1, '.', ''); $scaledPaddingX = number_format(4 * $scaleRatio, 1, '.', ''); @endphp
@php // Determine if inter-state (IGST) or intra-state (CGST+SGST) // SEZ buyers are always treated as inter-state supply under GST → always IGST. $companyState = strtolower(trim($company->state ?? 'Maharashtra')); $partyState = strtolower(trim($sale->party->state ?? '')); $isInterState = ($companyState !== $partyState && !empty($partyState)) || ($sale->party->is_sez ?? false); // Get state code from GSTIN if available (first 2 digits) $companyStateCode = $company->state_code ?? (strlen($company->gstin ?? '') >= 2 ? substr($company->gstin, 0, 2) : '27'); $partyStateCode = strlen($sale->party->gst_number ?? '') >= 2 ? substr($sale->party->gst_number, 0, 2) : ''; // State code mapping $stateCodes = [ '01' => 'Jammu and Kashmir', '02' => 'Himachal Pradesh', '03' => 'Punjab', '04' => 'Chandigarh', '05' => 'Uttarakhand', '06' => 'Haryana', '07' => 'Delhi', '08' => 'Rajasthan', '09' => 'Uttar Pradesh', '10' => 'Bihar', '11' => 'Sikkim', '12' => 'Arunachal Pradesh', '13' => 'Nagaland', '14' => 'Manipur', '15' => 'Mizoram', '16' => 'Tripura', '17' => 'Meghalaya', '18' => 'Assam', '19' => 'West Bengal', '20' => 'Jharkhand', '21' => 'Odisha', '22' => 'Chhattisgarh', '23' => 'Madhya Pradesh', '24' => 'Gujarat', '26' => 'Dadra and Nagar Haveli', '27' => 'Maharashtra', '29' => 'Karnataka', '30' => 'Goa', '31' => 'Lakshadweep', '32' => 'Kerala', '33' => 'Tamil Nadu', '34' => 'Puducherry', '35' => 'Andaman and Nicobar', '36' => 'Telangana', '37' => 'Andhra Pradesh', '38' => 'Ladakh', ]; // Get default bank account for the company $bankAccount = $company->defaultBankAccount(); $pfAmt = $sale->pf_amount ?? 0; $pfTax = $sale->pf_tax_amount ?? 0; // Adjusted tax analysis including P&F $adjTaxAnalysis = $taxAnalysis->values()->toArray(); if ($pfAmt > 0 && count($adjTaxAnalysis) > 0) { $adjTaxAnalysis[0]['taxable_value'] += $pfAmt; $adjTaxAnalysis[0]['total_tax'] += $pfTax; if (!$isInterState) { $adjTaxAnalysis[0]['cgst_amount'] += $pfTax / 2; $adjTaxAnalysis[0]['sgst_amount'] += $pfTax / 2; } } $taxTableTotal = collect($adjTaxAnalysis)->sum('total_tax'); // Pagination: split items into page chunks // Page 1 has company+buyer header = fewer item rows (~15) // Page 2+ has only compact header = more item rows (~30) // Both pages have full header, so same item capacity $shipSameAsBilling = !$sale->shippingAddress || ( trim((string) $sale->shippingAddress->address) === trim((string) $sale->party->billing_address) && (string) $sale->shippingAddress->pincode === (string) $sale->party->pincode ); $allItems = $sale->items->values(); $totalItems = $allItems->count(); $itemsPerPage1 = (int) floor(($allItems->count() > 20 ? 30 : 18) / $scaleRatio); // When a separate Ship to block is rendered on page 1, it consumes ~3 rows of vertical space if (!$shipSameAsBilling) { $itemsPerPage1 = max(1, $itemsPerPage1 - 3); } $itemsPerPage2 = (int) floor(18 / $scaleRatio); $itemPages = []; if ($totalItems <= $itemsPerPage1) { $itemPages[] = $allItems; } else { $itemPages[] = $allItems->slice(0, $itemsPerPage1)->values(); $remaining = $allItems->slice($itemsPerPage1)->values(); while ($remaining->count() > 0) { $itemPages[] = $remaining->slice(0, $itemsPerPage2)->values(); $remaining = $remaining->slice($itemsPerPage2)->values(); } } $totalPages = count($itemPages); @endphp @php $copyLabels = ($isProforma ?? false) ? ['(NOT A TAX INVOICE)'] : ['(ORIGINAL FOR RECIPIENT)', '(DUPLICATE FOR SUPPLIER)']; @endphp @foreach($copyLabels as $copyIndex => $copyLabel) @if($copyIndex > 0) @endif @for($pageNum = 0; $pageNum < $totalPages; $pageNum++) @php $pageItems = $itemPages[$pageNum]; $isFirstPage = ($pageNum === 0); $isLastPage = ($pageNum === $totalPages - 1); $startIndex = $isFirstPage ? 0 : $itemsPerPage1 + (($pageNum - 1) * $itemsPerPage2); // Filler rows for last page $maxSlots = $isFirstPage ? $itemsPerPage1 : $itemsPerPage2; $usedSlots = 0; foreach ($pageItems as $itm) { $nameLen = strlen($itm->product->name ?? 'Product'); $usedSlots += $nameLen > 30 ? 2 : 1; } $fillerRows = $isLastPage ? max(0, $maxSlots - $usedSlots) : 0; @endphp @if($pageNum > 0) @endif {{-- Header --}}| {{ ($isProforma ?? false) ? 'PROFORMA INVOICE' : 'GST INVOICE' }} | {{ $copyLabel }} | |
|
(SUPPLY MEANT FOR EXPORT/SUPPLY TO SEZ UNIT OR SEZ DEVELOPER FOR AUTHORISED OPERATIONS UNDER BOND OR LETTER OF UNDERTAKING WITHOUT PAYMENT OF IGST)
@if($sale->arn_no)
ARN No: {{ $sale->arn_no }} @endif |
||
|
{{-- Company Details --}}
@if(!empty($logoBase64))
{{-- Buyer Details --}}
{{ $company->legal_name ?? $company->name }}
{{ $company->billing_address }}
GSTIN: {{ $company->gstin }} | State: {{ $company->state ?? 'Maharashtra' }}
Ph: {{ $company->phone }} | {{ $company->email }}@if($company->website) | {{ $company->website }}@endif
@if($sale->party->is_sez)
@php $companyLut = $company->activeLutOn($sale->invoice_date); @endphp
@if($companyLut)
LUT No. : {{ $companyLut->lut_number }} From: {{ $companyLut->valid_from->format('d-m-Y') }} To: {{ $companyLut->valid_to->format('d-m-Y') }}
@endif
@endif
@if($company->msme_number)
MSME/Udyam : {{ $company->msme_number }}
@endif
Buyer (Bill to)
{{-- Ship To — only shown if a separate shipping address differs from billing --}}
@if(!$shipSameAsBilling)
{{ $sale->party->name }}
{{ $sale->party->billing_address }}
{{ $sale->party->state }} - {{ $sale->party->pincode }}, India
GSTIN/UIN : {{ $sale->party->gst_number ?? 'Unregistered' }} State Name : {{ $sale->party->state ?? '' }}
Contact : {{ $sale->party->mobile }}@if($sale->party->contact_person) Contact Person : {{ $sale->party->contact_person }}@endif
@if($sale->party->msme_number)
MSME/Udyam No. : {{ $sale->party->msme_number }}
@endif
Ship to
@endif
{{ $sale->shippingAddress->address }}
@if($sale->shippingAddress->pincode)
Pincode: {{ $sale->shippingAddress->pincode }}
@endif
@if($sale->shippingAddress->contact_person || $sale->shippingAddress->mobile)
@if($sale->shippingAddress->contact_person)Contact : {{ $sale->shippingAddress->contact_person }}@endif
@if($sale->shippingAddress->mobile) Mob : {{ $sale->shippingAddress->mobile }}@endif
@endif
|
|
||||||||||||
| Sl | Description of Goods | HSN/SAC | GST% | Quantity | Rate | Rate (Incl. Tax) |
Amount |
|---|---|---|---|---|---|---|---|
| {{ $startIndex + $loop->iteration }} | {{ $item->product->name ?? 'Product' }} | {{ $itemHsn }} | {{ indian_number($itemTaxPercent, 0) }}% | {{ indian_number($item->qty, 0) }} {{ $itemUnit }} | {{ indian_number($item->rate, 2) }} | {{ indian_number($rateInclTax, 2) }} | {{ indian_number($item->line_amount, 2) }} |
| Continued on next page... | {{ indian_number($pageItems->sum('line_amount'), 2) }} | ||||||
| Sub Total | {{ indian_number($sale->amount_total, 2) }} | ||||||
| P&F | {{ indian_number($pfAmt, 2) }} | ||||||
| IGST | {{ indian_number($sale->tax_total + $pfTax, 2) }} | ||||||
| CGST | {{ indian_number($totalCgst, 2) }} | ||||||
| SGST | {{ indian_number($totalSgst, 2) }} | ||||||
| Discount | {{ $sale->discount > 0 ? '(-)' : '(+)' }}{{ indian_number(abs($sale->discount), 2) }} | ||||||
| R.Off | {{ $sale->roundoff < 0 ? '(-)' : '' }}{{ indian_number(abs($sale->roundoff), 2) }} | ||||||
| Total | {{ indian_number($sale->items->sum('qty'), 0) }} {{ $totalUnit }} | ₹ {{ indian_number($sale->grand_total, 2) }} | |||||
|
Amount Chargeable (in words) Indian Rupees {{ $amountInWords }} Only |
E. & O.E |
|
@if(!empty($qrBase64))
Scan to pay
@elseif($company->qr_code_path)
Scan to pay
@else
QR
@endif
|
|
||||||||||||||||||||||||||||||||||
|
Declaration
We declare that this invoice shows the actual price of the goods described and that all particulars are true and correct. Not responsible for transit damage/loss. Report within 15 days. Debit notes without intimation attract 15% penalty. |
@if($bankAccount)
Company's Bank Details
@endif
for {{ $company->name }}
Authorised Signatory |