loadMissing('creator:id,name'); $phpWord = new PhpWord; $phpWord->setDefaultFontName('B Nazanin'); $phpWord->setDefaultFontSize(11); $section = $phpWord->addSection([ 'pageSizeW' => Converter::cmToTwip(21), 'pageSizeH' => Converter::cmToTwip(29.7), 'marginTop' => Converter::cmToTwip(1.2), 'marginRight' => Converter::cmToTwip(1.2), 'marginBottom' => Converter::cmToTwip(1.2), 'marginLeft' => Converter::cmToTwip(1.2), ]); $rtl = ['alignment' => 'right', 'bidi' => true, 'spaceAfter' => 0]; $center = ['alignment' => 'center', 'bidi' => true, 'spaceAfter' => 0]; $font = ['name' => 'B Nazanin', 'size' => 11]; $bold = $font + ['bold' => true]; $heading = $font + ['bold' => true, 'size' => 17, 'color' => '172554']; $headerCell = ['bgColor' => '172554', 'valign' => 'center']; $borderCell = ['borderSize' => 4, 'borderColor' => '94A3B8', 'valign' => 'center']; $section->addText('فاکتور فروش', $heading, $center); $section->addTextBreak(1); $meta = $section->addTable(['alignment' => JcTable::CENTER, 'width' => 100 * 50, 'unit' => 'pct', 'borderSize' => 4, 'borderColor' => '94A3B8']); $meta->addRow(520); $this->addLabelValue($meta, 'شماره فاکتور', $invoice->number ?: '—', $headerCell, $borderCell, $font, $bold); $this->addLabelValue($meta, 'تاریخ صدور', $this->date($invoice->issued_at ?? $invoice->created_at), $headerCell, $borderCell, $font, $bold); $this->addSectionTitle($section, 'مشخصات فروشنده', $headerCell, $bold); $this->addPartyTable($section, $invoice->seller_snapshot ?: ['name' => $invoice->creator?->name], $font, $bold, $borderCell); $this->addSectionTitle($section, 'مشخصات خریدار', $headerCell, $bold); $this->addPartyTable($section, $invoice->customer_snapshot ?: [], $font, $bold, $borderCell); $this->addSectionTitle($section, 'مشخصات کالا یا خدمات', $headerCell, $bold); $items = $section->addTable(['alignment' => JcTable::CENTER, 'width' => 100 * 50, 'unit' => 'pct', 'borderSize' => 4, 'borderColor' => '94A3B8']); $items->addRow(520); foreach (['ردیف', 'شرح کالا یا خدمت', 'واحد', 'تعداد', 'مبلغ واحد', 'مبلغ کل'] as $index => $label) { $widths = [700, 4300, 900, 900, 1600, 1800]; $items->addCell($widths[$index], $headerCell)->addText($label, $bold + ['color' => 'FFFFFF'], $center); } foreach (array_values($invoice->items ?: []) as $index => $item) { $items->addRow(500); $values = [ $index + 1, $item['description'] ?? '—', $item['unit'] ?? 'عدد', $this->number($item['quantity'] ?? 0), $this->money($item['unit_price'] ?? 0), $this->money($item['line_total'] ?? 0), ]; foreach ($values as $column => $value) { $widths = [700, 4300, 900, 900, 1600, 1800]; $items->addCell($widths[$column], $borderCell)->addText((string) $value, $font, $column === 1 ? $rtl : $center); } } $section->addTextBreak(1); $totals = $section->addTable(['alignment' => JcTable::END, 'width' => 55 * 50, 'unit' => 'pct', 'borderSize' => 4, 'borderColor' => '94A3B8']); foreach ([ 'جمع اقلام' => $invoice->subtotal, 'تخفیف' => $invoice->discount, 'مالیات و عوارض' => $invoice->tax, 'مبلغ نهایی' => $invoice->total, 'پرداخت‌شده' => $invoice->paid_amount, 'مانده قابل پرداخت' => max(0, (float) $invoice->total - (float) $invoice->paid_amount), ] as $label => $value) { $totals->addRow(480); $totals->addCell(2400, $headerCell)->addText($label, $bold + ['color' => 'FFFFFF'], $rtl); $totals->addCell(2600, $borderCell)->addText($this->money($value).' ریال', $bold, $rtl); } if ($invoice->payment_terms) { $this->addSectionTitle($section, 'شرایط پرداخت', $headerCell, $bold); $section->addText($invoice->payment_terms, $font, $rtl); } if ($invoice->notes) { $this->addSectionTitle($section, 'توضیحات', $headerCell, $bold); $section->addText($invoice->notes, $font, $rtl); } $section->addTextBreak(2); $signature = $section->addTable(['alignment' => JcTable::CENTER, 'width' => 100 * 50, 'unit' => 'pct']); $signature->addRow(900); $signature->addCell(5000)->addText('مهر و امضای فروشنده', $bold, $center); $signature->addCell(5000)->addText('مهر و امضای خریدار', $bold, $center); Storage::disk('local')->makeDirectory('invoice-exports'); $filename = "invoice-{$invoice->number}.docx"; $path = Storage::disk('local')->path('invoice-exports/'.uniqid('invoice-', true).'.docx'); $phpWord->save($path, 'Word2007'); return compact('path', 'filename'); } private function addSectionTitle($section, string $title, array $cellStyle, array $font): void { $section->addTextBreak(1); $table = $section->addTable(['width' => 100 * 50, 'unit' => 'pct']); $table->addRow(440); $table->addCell(10000, $cellStyle)->addText($title, $font + ['color' => 'FFFFFF'], ['alignment' => 'center', 'bidi' => true, 'spaceAfter' => 0]); } private function addPartyTable($section, array $party, array $font, array $bold, array $cell): void { $table = $section->addTable(['alignment' => JcTable::CENTER, 'width' => 100 * 50, 'unit' => 'pct', 'borderSize' => 4, 'borderColor' => '94A3B8']); $fields = [ ['نام', $party['name'] ?? '—', 'نام/شرکت', $party['company'] ?? $party['name'] ?? '—'], ['شناسه/کد ملی', $party['national_code'] ?? $party['national_id'] ?? '—', 'کد اقتصادی', $party['economic_code'] ?? '—'], ['تلفن', $party['phone'] ?? '—', 'کد پستی', $party['postal_code'] ?? '—'], ['نشانی', $party['address'] ?? '—', 'ایمیل', $party['email'] ?? '—'], ]; foreach ($fields as [$label1, $value1, $label2, $value2]) { $table->addRow(480); foreach ([[$label1, $value1], [$label2, $value2]] as [$label, $value]) { $table->addCell(1500, $cell + ['bgColor' => 'E2E8F0'])->addText($label, $bold, ['alignment' => 'right', 'bidi' => true, 'spaceAfter' => 0]); $table->addCell(3500, $cell)->addText((string) $value, $font, ['alignment' => 'right', 'bidi' => true, 'spaceAfter' => 0]); } } } private function addLabelValue($table, string $label, string $value, array $headerCell, array $cell, array $font, array $bold): void { $table->addCell(1800, $headerCell)->addText($label, $bold + ['color' => 'FFFFFF'], ['alignment' => 'right', 'bidi' => true, 'spaceAfter' => 0]); $table->addCell(3200, $cell)->addText($value, $font, ['alignment' => 'right', 'bidi' => true, 'spaceAfter' => 0]); } private function money(mixed $value): string { return number_format((float) $value, 0, '.', ','); } private function number(mixed $value): string { return rtrim(rtrim(number_format((float) $value, 2, '.', ''), '0'), '.'); } private function date($value): string { return $value ? $value->format('Y/m/d') : '—'; } }