diff --git a/app/Http/Controllers/Api/ExcelController.php b/app/Http/Controllers/Api/ExcelController.php index b24f9fb..6a38e08 100644 --- a/app/Http/Controllers/Api/ExcelController.php +++ b/app/Http/Controllers/Api/ExcelController.php @@ -3,14 +3,207 @@ namespace App\Http\Controllers\Api; use App\Http\Controllers\Controller; +use App\Models\Invoice; +use App\Models\Payment; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use PhpOffice\PhpSpreadsheet\Shared\Date; +use PhpOffice\PhpSpreadsheet\Spreadsheet; +use PhpOffice\PhpSpreadsheet\Style\Alignment; +use PhpOffice\PhpSpreadsheet\Style\Border; +use PhpOffice\PhpSpreadsheet\Style\NumberFormat\Wizard\Currency; +use PhpOffice\PhpSpreadsheet\Style\NumberFormat\Wizard\CurrencyBase; +use PhpOffice\PhpSpreadsheet\Style\NumberFormat\Wizard\Number; +use PhpOffice\PhpSpreadsheet\Worksheet\PageSetup; +use PhpOffice\PhpSpreadsheet\Writer\Xlsx; class ExcelController extends Controller { + protected string $from; + protected string $end; + protected Xlsx $writer; + + protected CurrencyBase $currencyMask; + public function export(Request $request): JsonResponse { - return response()->json($request->all()); + $requestData = $request->validate([ + 'from' => 'required|date', + 'end' => 'required|date', + 'report' => 'required|in:invoice,payment', + ]); + + $this->from = $requestData['from']; + $this->end = $requestData['end']; + $this->currencyMask = new Currency( + '€', + 2, + Number::WITH_THOUSANDS_SEPARATOR, + Currency::TRAILING_SYMBOL, + Currency::SYMBOL_WITH_SPACING + ); + + switch ($requestData['report']) { + case 'invoice': + $this->invoice(); + break; + case 'payment': + $this->payment(); + break; + } + return response()->json($this->writer->save('php://output')); + } + + protected function invoice(): void + { + $from = $this->from . ' 00:00:00'; + $end = $this->end . ' 23:59:59'; + $net = []; + $tax = []; + $gross = []; + + $invoices = Invoice::whereBetween('created_at', [$from, $end])->where('status', '!=', 'created')->with(['address', 'customer'])->orderBy('created_at', 'desc')->get(); + $spreadsheet = new Spreadsheet(); + $worksheet = $spreadsheet->getActiveSheet(); + $worksheet->setTitle(__('invoice.Invoices')); + $worksheet->getPageSetup()->setOrientation(PageSetup::ORIENTATION_LANDSCAPE); + $worksheet->getHeaderFooter()->setEvenHeader(__('invoice.Invoices from to', ['from' => $this->from, 'end' => $this->end])); + $worksheet->getHeaderFooter()->setOddHeader(__('invoice.Invoices from to', ['from' => $this->from, 'end' => $this->end])); + + $worksheet->setCellValue('A1', __('invoice.Invoice Number')); + $worksheet->setCellValue('B1', __('customer.Customer')); + $worksheet->setCellValue('C1', __('common.Name')); + $worksheet->setCellValue('D1', __('invoice.Net')); + $worksheet->setCellValue('E1', __('invoice.Tax')); + $worksheet->setCellValue('F1', __('invoice.Gross')); + $worksheet->setCellValue('G1', __('common.Created at')); + $worksheet->getStyle('A1:G1')->getBorders()->getBottom()->applyFromArray(['borderStyle' => Border::BORDER_DOUBLE]); + $worksheet->getStyle('A1:G1')->getFont()->setBold(true); + $worksheet->getStyle('D1:G1')->getAlignment()->applyFromArray(['horizontal' => Alignment::HORIZONTAL_RIGHT]); + + $row = 2; + foreach ($invoices as $invoice) { + foreach ($invoice->items as $item) { + if (!isset($net[$item->tax])) { + $net[$item->tax] = 0; + $tax[$item->tax] = 0; + $gross[$item->tax] = 0; + } + $net[$item->tax] += $item->amount * $item->price; + $tax[$item->tax] += $item->amount * $item->price * $item->tax / 100; + $gross[$item->tax] += $item->total; + } + $worksheet->setCellValue('A' . $row, $invoice->number); + $worksheet->setCellValue('B' . $row, $invoice->customer->name); + $worksheet->setCellValue('C' . $row, $invoice->address->name); + $worksheet->getCell('D' . $row)->getStyle()->getNumberFormat()->setFormatCode($this->currencyMask); + $worksheet->setCellValue('D' . $row, $invoice->sum - $invoice->tax); + $worksheet->getCell('E' . $row)->getStyle()->getNumberFormat()->setFormatCode($this->currencyMask); + $worksheet->setCellValue('E' . $row, $invoice->tax); + $worksheet->getCell('F' . $row)->getStyle()->getNumberFormat()->setFormatCode($this->currencyMask); + $worksheet->setCellValue('F' . $row, $invoice->sum); + $worksheet->setCellValue('G' . $row, Date::PHPToExcel(\DateTime::createFromFormat('!d.m.Y', $invoice->created))); + $worksheet->getCell('G' . $row)->getStyle()->getNumberFormat()->setFormatCode('dd.mm.yyyy'); + $row++; + } + + $worksheet->getStyle('A' . $row - 1 . ':G' . $row - 1)->getBorders()->getBottom()->applyFromArray(['borderStyle' => Border::BORDER_DOUBLE]); + + foreach ($net as $tax_value => $amount) { + $worksheet->getStyle('A' . $row . ':G' . $row)->getFont()->setBold(true); + $worksheet->getStyle('D' . $row . ':G' . $row)->getAlignment()->applyFromArray(['horizontal' => Alignment::HORIZONTAL_RIGHT]); + $worksheet->setCellValue('B' . $row, __('invoice.Sails from vat', ['tax' => \Illuminate\Support\Number::percentage($tax_value)])); + $worksheet->getCell('D' . $row)->getStyle()->getNumberFormat()->setFormatCode($this->currencyMask); + $worksheet->setCellValue('D' . $row, $amount); + $worksheet->getCell('E' . $row)->getStyle()->getNumberFormat()->setFormatCode($this->currencyMask); + $worksheet->setCellValue('E' . $row, $tax[$tax_value]); + $worksheet->getCell('F' . $row)->getStyle()->getNumberFormat()->setFormatCode($this->currencyMask); + $worksheet->setCellValue('F' . $row, $gross[$tax_value]); + + $row++; + } + + foreach ($worksheet->getColumnIterator() as $column) { + $worksheet->getColumnDimension($column->getColumnIndex())->setAutoSize(true); + } + + $this->writer = new Xlsx($spreadsheet); + } + + protected function payment(): void + { + $net = []; + $tax = []; + $gross = []; + + $payments = Payment::whereBetween('payment_date', [$this->from, $this->end])->with(['invoice'])->orderBy('payment_date', 'desc')->get(); + $spreadsheet = new Spreadsheet(); + $worksheet = $spreadsheet->getActiveSheet(); + $worksheet->setTitle(__('invoice.Payments')); + $worksheet->getPageSetup()->setOrientation(PageSetup::ORIENTATION_LANDSCAPE); + $worksheet->getHeaderFooter()->setEvenHeader(__('invoice.Payments from to', ['from' => $this->from, 'end' => $this->end])); + $worksheet->getHeaderFooter()->setOddHeader(__('invoice.Payments from to', ['from' => $this->from, 'end' => $this->end])); + + $worksheet->setCellValue('A1', __('invoice.Invoice Number')); + $worksheet->setCellValue('B1', __('customer.Customer')); + $worksheet->setCellValue('C1', __('common.Name')); + $worksheet->setCellValue('D1', __('invoice.Net')); + $worksheet->setCellValue('E1', __('invoice.Tax')); + $worksheet->setCellValue('F1', __('invoice.Gross')); + $worksheet->setCellValue('G1', __('invoice.Paid at')); + $worksheet->getStyle('A1:G1')->getBorders()->getBottom()->applyFromArray(['borderStyle' => Border::BORDER_DOUBLE]); + $worksheet->getStyle('A1:G1')->getFont()->setBold(true); + $worksheet->getStyle('D1:G1')->getAlignment()->applyFromArray(['horizontal' => Alignment::HORIZONTAL_RIGHT]); + + $row = 2; + foreach ($payments as $payment) { + $invoice = $payment->invoice; + foreach ($invoice->items as $item) { + if (!isset($net[$item->tax])) { + $net[$item->tax] = 0; + $tax[$item->tax] = 0; + $gross[$item->tax] = 0; + } + $net[$item->tax] += $item->amount * $item->price * $payment->paid_amount / $invoice->sum; + $tax[$item->tax] += $item->amount * $item->price * $item->tax * $payment->paid_amount / ($invoice->sum * 100); + $gross[$item->tax] += $item->total * $payment->paid_amount / ($invoice->sum); + } + $worksheet->setCellValue('A' . $row, $invoice->number); + $worksheet->setCellValue('B' . $row, $invoice->customer->name); + $worksheet->setCellValue('C' . $row, $invoice->address->name); + $worksheet->getCell('D' . $row)->getStyle()->getNumberFormat()->setFormatCode($this->currencyMask); + $worksheet->setCellValue('D' . $row, ($invoice->sum - $invoice->tax) / ($invoice->sum / $payment->paid_amount)); + $worksheet->getCell('E' . $row)->getStyle()->getNumberFormat()->setFormatCode($this->currencyMask); + $worksheet->setCellValue('E' . $row, $invoice->tax / ($invoice->sum / $payment->paid_amount)); + $worksheet->getCell('F' . $row)->getStyle()->getNumberFormat()->setFormatCode($this->currencyMask); + $worksheet->setCellValue('F' . $row, $payment->paid_amount); + $worksheet->setCellValue('G' . $row, Date::PHPToExcel(\DateTime::createFromFormat('!Y-m-d', $payment->payment_date))); + $worksheet->getCell('G' . $row)->getStyle()->getNumberFormat()->setFormatCode('dd.mm.yyyy'); + $row++; + } + + $worksheet->getStyle('A' . $row - 1 . ':G' . $row - 1)->getBorders()->getBottom()->applyFromArray(['borderStyle' => Border::BORDER_DOUBLE]); + + foreach ($net as $tax_value => $amount) { + $worksheet->getStyle('A' . $row . ':G' . $row)->getFont()->setBold(true); + $worksheet->getStyle('D' . $row . ':G' . $row)->getAlignment()->applyFromArray(['horizontal' => Alignment::HORIZONTAL_RIGHT]); + $worksheet->setCellValue('B' . $row, __('invoice.Sails from vat', ['tax' => \Illuminate\Support\Number::percentage($tax_value)])); + $worksheet->getCell('D' . $row)->getStyle()->getNumberFormat()->setFormatCode($this->currencyMask); + $worksheet->setCellValue('D' . $row, $amount); + $worksheet->getCell('E' . $row)->getStyle()->getNumberFormat()->setFormatCode($this->currencyMask); + $worksheet->setCellValue('E' . $row, $tax[$tax_value]); + $worksheet->getCell('F' . $row)->getStyle()->getNumberFormat()->setFormatCode($this->currencyMask); + $worksheet->setCellValue('F' . $row, $gross[$tax_value]); + + $row++; + } + + foreach ($worksheet->getColumnIterator() as $column) { + $worksheet->getColumnDimension($column->getColumnIndex())->setAutoSize(true); + } + + $this->writer = new Xlsx($spreadsheet); + } } diff --git a/lang/de/invoice.php b/lang/de/invoice.php index a20fdfb..1d353c0 100644 --- a/lang/de/invoice.php +++ b/lang/de/invoice.php @@ -37,6 +37,7 @@ return [ 'Invoice Number short' => 'Rechnung-Nr.', 'Sum' => 'Summe', 'Net' => 'Nettobetrag', + 'Gross' => 'Gesamtbetrag', 'From' => 'Von', 'End' => 'Bis', 'Enter your invoice items. Click add for an additional invoice item.' => 'Gib Deine Rechnungspositionen ein. Klicke auf "Hinzufügen" für weitere Rechnungspositionen.', @@ -77,5 +78,8 @@ return [ 'Payment amount' => 'Zahlungsbetrag', 'Existing payments for invoice' => 'Bestehende Teilzahlungen für Rechnung', 'Paid at' => 'Bezahlt am', + 'Sails from vat' => 'Umsätze aus :tax Mehrwertsteuer', + 'Invoices from to' => 'Rechnungen vom :from bis :end', + 'Payments from to' => 'Zahlungseingänge vom :from bis :end', ]; diff --git a/resources/views/excel.blade.php b/resources/views/excel.blade.php index 0da424b..fc7f0f0 100644 --- a/resources/views/excel.blade.php +++ b/resources/views/excel.blade.php @@ -18,6 +18,8 @@
{{ __("excel.Choose data hint") }}
+ +