diff --git a/app/Classes/Modules/Bookings/ControllersLogic/BatchBookingsGenerateEInvoiceLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/BatchBookingsGenerateEInvoiceLogic.php index 703fe348..9d44e244 100644 --- a/app/Classes/Modules/Bookings/ControllersLogic/BatchBookingsGenerateEInvoiceLogic.php +++ b/app/Classes/Modules/Bookings/ControllersLogic/BatchBookingsGenerateEInvoiceLogic.php @@ -82,7 +82,13 @@ class BatchBookingsGenerateEInvoiceLogic extends AbstractControllerLogic $endDate = $endDate ? Carbon::parse($endDate)->endOfDay() : Carbon::now(); $bookings = Booking::where('status', ApprovalStatus::COMPLETED) - ->whereBetween('created_at', [$startDate, $endDate]) + // ->whereBetween('created_at', [$startDate, $endDate]) + ->whereHas('transactions', function ($query) use ($startDate, $endDate) { + $query->payments() + ->complete() + ->whereBetween('created_at', [$startDate, $endDate]) + ->latest('created_at'); + }) ->whereHas('attributesKVP', function (Builder $query) { $query->where('key', KVPKey::AUTOCOUNT_DOCNO); }) @@ -92,7 +98,7 @@ class BatchBookingsGenerateEInvoiceLogic extends AbstractControllerLogic ->get(); foreach ($bookings as $booking) { - // $autocountValue = optional($booking->attributesKVP->first())->value; + //$autocountValue = optional($booking->attributesKVP->first())->value; //Log::info('Booking ID: ' . $booking->marking . ' | AUTOCOUNT_DOCNO: ' . $autocountValue); // $this->regenerateInvoiceBookingProcessor->execute($booking); ProcessBookingForEInvoiceV2CommandJob::dispatch($booking); diff --git a/app/Classes/Modules/Exports/Services/ExportsReceivePaymentDepositEntryReport.php b/app/Classes/Modules/Exports/Services/ExportsReceivePaymentDepositEntryReport.php new file mode 100644 index 00000000..995b1e78 --- /dev/null +++ b/app/Classes/Modules/Exports/Services/ExportsReceivePaymentDepositEntryReport.php @@ -0,0 +1,99 @@ +startDate = $startDate ? Carbon::parse($startDate)->startOfDay() : Carbon::now()->subMonths(1); + $this->endDate = $endDate ? Carbon::parse($endDate)->endOfDay() : Carbon::now(); + } + + public function headings(): array + { + return [ + 'DocNo', + 'DocDate', + 'DebtorCode', + 'Description', + 'DeptNo', + 'DepositPaymentMethod', + 'PaymentMethod', + 'PaymentAmt', + ]; + } + + /** + * @return \Illuminate\Support\Collection|mixed + */ + public function query() + { + $type = TransactionType::PAYMENT; + $query = Transaction::query(); + // $query->where('owner_type', '!=', Wallet::class); + $query->where('type', $type); + $query->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + $query->whereBetween('created_at', [$this->startDate, $this->endDate]); + + return $query; + } + + /** + * @param Transaction $transaction + * @return array + */ + public function map($transaction): array + { + $formattedDocumentDate = Carbon::parse($transaction->created_at)->format('m/d/Y'); + $owner = $transaction->owner; + $booking = null; + if($owner instanceof Booking){ + $booking = $owner; + $company = $booking->company; + } + else{ + $company = $owner->owner; + } + + $paymentMethod = ''; + if($transaction->payment_method == PaymentMethodType::WALLET){ + $paymentMethod = 'WALLET DEPOSIT - EXC'; + if($owner instanceof Booking){ + return[]; + } + } + else{ + $paymentMethod = 'MBB'; + } + + return [ + '<>', //DocNo + $formattedDocumentDate, //DocDate + $company ? $company->debtor : '', //DebtorCode + $booking ? $booking->marking : '', //Description + 'C', //DeptNo + 'SALES DEPOSIT - EXC', //DepositPaymentMethod + $paymentMethod, //PaymentMethod + number_format($transaction->amount, 2), //PaymentAmt + ]; + } +} diff --git a/app/Classes/Modules/Exports/Services/ExportsReceivePaymentForBookingReport.php b/app/Classes/Modules/Exports/Services/ExportsReceivePaymentForBookingReport.php new file mode 100644 index 00000000..32d6e86d --- /dev/null +++ b/app/Classes/Modules/Exports/Services/ExportsReceivePaymentForBookingReport.php @@ -0,0 +1,108 @@ +startDate = $startDate ? Carbon::parse($startDate)->startOfDay() : Carbon::now()->subMonths(1); + $this->endDate = $endDate ? Carbon::parse($endDate)->endOfDay() : Carbon::now(); + } + + public function headings(): array + { + return [ + 'DocNo', + 'Docdate', + 'DebtorCode', + 'Description', + 'DeptNo', + 'PaymentMethod', + 'PaymentAmt', + 'KnockOffDocType', + 'KnockOffDocNo', + 'KnockOffAmt', + ]; + } + + /** + * @return \Illuminate\Support\Collection|mixed + */ + public function query() + { + $type = TransactionType::PAYMENT; + $query = Transaction::query(); + // $query->where('owner_type', '!=', Wallet::class); + $query->where('type', $type); + $query->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + $query->whereBetween('created_at', [$this->startDate, $this->endDate]); + + return $query; + } + + /** + * @param Transaction $transaction + * @return array + */ + public function map($transaction): array + { + $autoCountSalesInvoiceId = null; + $formattedDocumentDate = Carbon::parse($transaction->created_at)->format('m/d/Y'); + $owner = $transaction->owner; + $booking = null; + if($owner instanceof Booking){ + $booking = $owner; + $company = $booking->company; + } + else{ + $company = $owner->owner; + } + + if($booking){ + $metadata = $booking->attributesKVP()->where('key', KVPKey::AUTOCOUNT_DOCNO)->first(); + if($metadata){ + $autoCountSalesInvoiceId = $metadata->value; + } + } + + if($transaction->payment_method == PaymentMethodType::WALLET){ + if($owner instanceof Wallet){ + return[]; + } + } + + return [ + '<>', //DocNo + $formattedDocumentDate, //DocDate + $company ? $company->debtor : '', //DebtorCode + 'Payment for ' . $autoCountSalesInvoiceId ?? '', //Description + 'C', //DeptNo + 'SALES DEPOSIT - EXC', //PaymentMethod + number_format($transaction->amount, 2), //PaymentAmt + 'RI', //KnockOffDocType + $autoCountSalesInvoiceId ?? '', //KnockOffDocNo + number_format($transaction->amount, 2), //KnockOffAmt + ]; + } +} diff --git a/app/Classes/Modules/Exports/Services/ExportsSalesInvoiceReport.php b/app/Classes/Modules/Exports/Services/ExportsSalesInvoiceReport.php index 74598a8d..5ecc250c 100644 --- a/app/Classes/Modules/Exports/Services/ExportsSalesInvoiceReport.php +++ b/app/Classes/Modules/Exports/Services/ExportsSalesInvoiceReport.php @@ -14,7 +14,6 @@ use Maatwebsite\Excel\Concerns\WithMapping; use App\Classes\Modules\Bookings\Services\CalculatesBookingRefundAmount; use App\Classes\Modules\Bookings\Services\CalculatesBookingRefundServiceCharge; use Carbon\Carbon; -use Illuminate\Support\Facades\Log; class ExportsSalesInvoiceReport implements FromQuery, WithHeadings, WithHeadingRow, WithMapping, ShouldAutoSize { @@ -60,7 +59,17 @@ class ExportsSalesInvoiceReport implements FromQuery, WithHeadings, WithHeadingR // $query->where('type', TransactionType::PURCHASE_ORDER)->complete(); // }); - return Booking::where('status', ApprovalStatus::COMPLETED)->whereBetween('created_at', [$this->startDate, $this->endDate]); + // return Booking::where('status', ApprovalStatus::COMPLETED)->whereBetween('created_at', [$this->startDate, $this->endDate]); + + $startDate = $this->startDate; + $endDate = $this->endDate; + return Booking::where('status', ApprovalStatus::COMPLETED) + ->whereHas('transactions', function ($query) use ($startDate, $endDate) { + $query->payments() + ->complete() + ->whereBetween('created_at', [$startDate, $endDate]) + ->latest('created_at'); + }); } /** @@ -76,12 +85,22 @@ class ExportsSalesInvoiceReport implements FromQuery, WithHeadings, WithHeadingR $purchaseOrder = $booking->transactions()->where('type', TransactionType::PURCHASE_ORDER)->first(); $company = $booking->company()->first(); - $lastPaymentTransaction = $booking->transactions()->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::COMPLETED, ApprovalStatus::APPROVED])->latest()->first(); + + $lastPaymentTransaction = $booking->transactions()->payments()->complete()->latest()->first(); if(!$lastPaymentTransaction){ return $records; } - $invoiceTransaction = $booking->transactions()->where('type', TransactionType::INVOICE)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->first(); + $documentDate = $lastPaymentTransaction->created_at; + if ($documentDate < $this->startDate || $documentDate > $this->endDate) { + return $records; + } + + if($company->e_invoice === 1){ + $documentDate = $documentDate->copy()->endOfMonth(); + } + + $invoiceTransaction = $booking->transactions()->where('type', TransactionType::INVOICE)->complete()->first(); $currencyId = $booking->fix_currency_id; @@ -114,10 +133,6 @@ class ExportsSalesInvoiceReport implements FromQuery, WithHeadings, WithHeadingR $totalPayment = $paymentSum - $refundedAmount - $refundedServiceCharge; } - $documentDate = $lastPaymentTransaction->created_at; - // if(Carbon::parse($booking->updated_at)->isAfter($lastPaymentTransaction->created_at)){ //cief todo: 90 - Report E-Invoice date incorrect - // $documentDate = $booking->updated_at; - // } $formattedDocumentDate = Carbon::parse($documentDate)->format('m/d/Y'); $firstItem = true; diff --git a/app/Classes/Modules/Imports/ControllersLogic/ImportExcelLogic.php b/app/Classes/Modules/Imports/ControllersLogic/ImportExcelLogic.php index c9b43488..22eb7eb4 100644 --- a/app/Classes/Modules/Imports/ControllersLogic/ImportExcelLogic.php +++ b/app/Classes/Modules/Imports/ControllersLogic/ImportExcelLogic.php @@ -12,6 +12,7 @@ use App\Classes\Modules\Accounts\DataTransferObjects\KeyValuePairObject; use App\Classes\ValueObjects\Constants\ApprovalStatus; use App\Classes\ValueObjects\Constants\KVPKey; use App\Models\Booking; +use App\Models\KeyValuePair; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Support\Facades\Log; @@ -55,10 +56,19 @@ class ImportExcelLogic extends AbstractControllerLogic */ public function logic(Request $request) : JsonResponse { + $result = []; + $reportType = $request->input('report_type'); $object = new DocumentObject('', $request->input('files'), '', ApprovalStatus::APPROVED, 'imports'); - foreach ($object->getFiles() as $file){ + + $files = $object->getFiles(); + + if (count($files) > 1) { + throw new MalformedRequestException('Import function can only process one file at a time.'); + } + + foreach ($files as $file) { $collection = Excel::toCollection(null, json_decode($file)->file_info->original->file, null, null, true); $sheet = $collection->first(); @@ -75,6 +85,15 @@ class ImportExcelLogic extends AbstractControllerLogic 'businessactivitydesc', 'debtorcode', 'tradename', 'address', 'postcode', 'phone', 'emailaddress', 'city', 'countrycode', 'statecode' ]; + $paymentReportHeader = [ + 'docno', + 'docdate', + 'debtorcode', + 'description', + 'paymentmethod', + 'paymentamt', + 'knockoffdocno' + ]; if ($reportType === 'Sales Invoice Report') { $optionalColumn = 'einvoicevalidationlink'; @@ -89,57 +108,28 @@ class ImportExcelLogic extends AbstractControllerLogic } elseif ($reportType === 'Customers Report' && $normalizedHeader !== $customersReportHeader) { throw new MalformedRequestException('Uploaded Excel file format is incorrect. Column headers do not match expected format.'); } + elseif ($reportType === '01R - RECEIVE PAYMENT (FULL PAYMENT) [AR RECEIVE PAYMENT]' && $normalizedHeader !== $paymentReportHeader) { + throw new MalformedRequestException('Uploaded Excel file format is incorrect. Column headers do not match expected format.'); + } - $rows = $sheet->skip(1); - - foreach ($rows as $index => $details) { - $docNo = $details[0] ?? null; - $docDate = $details[1] ?? null; - $debtorCode = $details[2] ?? null; - $ref = $details[3] ?? null; - $shipInfo = $details[4] ?? null; - $accNo = $details[5] ?? null; - $detailDescription = $details[6] ?? null; - $furtherDescription = $details[7] ?? null; - $classification = $details[8] ?? null; - $deptNo = $details[9] ?? null; - $qty = $details[10] ?? null; - $unitPrice = $details[11] ?? null; - $submitEinvoice = $details[12] ?? null; - $consolidatedEinvoice = $details[13] ?? null; - $eInvoiceValidationLink = $details[14] ?? null; // Safe access for the new column - - Log::info("Row {$index} Details:", [ - 'DocNo' => $docNo, - 'DocDate' => $docDate, - 'DebtorCode' => $debtorCode, - 'Ref' => $ref, - 'ShipInfo' => $shipInfo, - 'AccNo' => $accNo, - 'DetailDescription' => $detailDescription, - 'FurtherDescription' => $furtherDescription, - 'Classification' => $classification, - 'DeptNo' => $deptNo, - 'Qty' => $qty, - 'UnitPrice' => $unitPrice, - 'SubmitEinvoice' => $submitEinvoice, - 'ConsolidatedEinvoice' => $consolidatedEinvoice, - 'EInvoiceValidationLink' => $eInvoiceValidationLink, - ]); - - $booking = Booking::where('marking', $ref)->first(); - if($booking){ - if($docNo != "" && $docNo != "<>"){ - $this->updateOrCreateKeyValuePair($booking, KVPKey::AUTOCOUNT_DOCNO, $docNo); - } - if($eInvoiceValidationLink){ - $this->updateOrCreateKeyValuePair($booking, KVPKey::AUTOCOUNT_EINVOICE_VALIDATION_LINK, $eInvoiceValidationLink); - } - } + if ($reportType === 'Sales Invoice Report') { + $this->processSalesInvoiceReport($sheet); + } + else if ($reportType === '01R - RECEIVE PAYMENT (FULL PAYMENT) [AR RECEIVE PAYMENT]'){ + $result = $this->processPaymentReport($sheet); + $result = [ + 'message' => empty($result) + ? '' + : 'Some data are unprocessed: ', + 'data' => $result + ]; + } + else{ + throw new MalformedRequestException('Cannot process report type: ' . $reportType); } } - return $this->response([]); + return $this->response($result); } private function updateOrCreateKeyValuePair($booking, $key, $value) @@ -153,4 +143,103 @@ class ImportExcelLogic extends AbstractControllerLogic $this->createsKeyValuePair->execute($booking, $keyValuePairObject); } } + + private function processSalesInvoiceReport($sheet){ + $rows = $sheet->skip(1); + + foreach ($rows as $index => $details) { + $docNo = $details[0] ?? null; + $docDate = $details[1] ?? null; + $debtorCode = $details[2] ?? null; + $ref = $details[3] ?? null; + $shipInfo = $details[4] ?? null; + $accNo = $details[5] ?? null; + $detailDescription = $details[6] ?? null; + $furtherDescription = $details[7] ?? null; + $classification = $details[8] ?? null; + $deptNo = $details[9] ?? null; + $qty = $details[10] ?? null; + $unitPrice = $details[11] ?? null; + $submitEinvoice = $details[12] ?? null; + $consolidatedEinvoice = $details[13] ?? null; + $eInvoiceValidationLink = $details[14] ?? null; // Safe access for the new column + + Log::info("Row {$index} Details:", [ + 'DocNo' => $docNo, + 'DocDate' => $docDate, + 'DebtorCode' => $debtorCode, + 'Ref' => $ref, + 'ShipInfo' => $shipInfo, + 'AccNo' => $accNo, + 'DetailDescription' => $detailDescription, + 'FurtherDescription' => $furtherDescription, + 'Classification' => $classification, + 'DeptNo' => $deptNo, + 'Qty' => $qty, + 'UnitPrice' => $unitPrice, + 'SubmitEinvoice' => $submitEinvoice, + 'ConsolidatedEinvoice' => $consolidatedEinvoice, + 'EInvoiceValidationLink' => $eInvoiceValidationLink, + ]); + + $booking = Booking::where('marking', $ref)->first(); + if($booking){ + if($docNo != "" && $docNo != "<>"){ + $this->updateOrCreateKeyValuePair($booking, KVPKey::AUTOCOUNT_DOCNO, $docNo); + } + if($eInvoiceValidationLink){ + $this->updateOrCreateKeyValuePair($booking, KVPKey::AUTOCOUNT_EINVOICE_VALIDATION_LINK, $eInvoiceValidationLink); + } + } + } + } + + private function processPaymentReport($sheet){ + $unprocessedKnockOffs = []; + $rows = $sheet->skip(1); + + foreach ($rows as $index => $details) { + $docNo = $details[0] ?? null; + $docDate = $details[1] ?? null; + $debtorCode = $details[2] ?? null; + $description = $details[3] ?? null; + $paymentMethod = $details[4] ?? null; + $paymentAmt = $details[5] ?? null; + $knockOffDocNo = $details[6] ?? null; + + Log::info("Row {$index} Payment Details:", [ + 'DocNo' => $docNo, + 'DocDate' => $docDate, + 'DebtorCode' => $debtorCode, + 'Description' => $description, + 'PaymentMethod' => $paymentMethod, + 'PaymentAmt' => $paymentAmt, + 'KnockOffDocNo' => $knockOffDocNo, + ]); + + if($knockOffDocNo) + { + $kvp = KeyValuePair::where('key', KVPKey::AUTOCOUNT_DOCNO)->where('value', $knockOffDocNo)->first(); + if($kvp){ + $booking = $kvp->owner; + if($booking){ + if($docNo != "" && $docNo != "<>"){ + $this->updateOrCreateKeyValuePair($booking, KVPKey::AUTOCOUNT_OFFICIAL_RECEIPT_DOCNO, $docNo); + } + // if($eInvoiceValidationLink){ + // $this->updateOrCreateKeyValuePair($booking, KVPKey::AUTOCOUNT_EINVOICE_VALIDATION_LINK, $eInvoiceValidationLink); + // } + } + else{ + $unprocessedKnockOffs[] = $knockOffDocNo; + } + } + else{ + $unprocessedKnockOffs[] = $knockOffDocNo; + } + } + } + + return $unprocessedKnockOffs; + } } diff --git a/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionProcessor.php b/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionProcessor.php index 44f0dbbf..799032ab 100644 --- a/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionProcessor.php +++ b/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionProcessor.php @@ -18,6 +18,7 @@ use App\Classes\ValueObjects\Constants\ApprovalStatus; use App\Classes\ValueObjects\Constants\SegmentConstants; use App\Classes\ValueObjects\Constants\TransactionType; use App\Classes\ValueObjects\Constants\DocumentType; +use App\Classes\ValueObjects\Constants\KVPKey; use App\Models\Booking; use App\Models\SegmentConstant; use Carbon\Carbon; @@ -136,7 +137,10 @@ class CreateInvoiceTransactionProcessor if ($bookingCreatedDate->isAfter($eInvoiceStartDate) && $supplier->e_invoice === 1) { $eInvoice = true; } - // $eInvoice = true; //cief todo: 90 - for testing + $kvp = $booking->attributesKVP()->where('key', KVPKey::BOOKING_EINVOICE_ELIGIBLE)->first(); + if($kvp){ + $eInvoice = true; + } if($isAllowNormalInvoice){ $invoiceNo = ""; //July 2025 workaround generate normal invoice instead of E-Invoice diff --git a/app/Classes/ValueObjects/Constants/KVPKey.php b/app/Classes/ValueObjects/Constants/KVPKey.php index a15f7d91..b2943b4c 100644 --- a/app/Classes/ValueObjects/Constants/KVPKey.php +++ b/app/Classes/ValueObjects/Constants/KVPKey.php @@ -8,10 +8,14 @@ class KVPKey public const AUTOCOUNT_DOCNO = 'AUTOCOUNT_DOCNO'; + public const AUTOCOUNT_OFFICIAL_RECEIPT_DOCNO = 'AUTOCOUNT_OR_DOCNO'; + public const AUTOCOUNT_EINVOICE_VALIDATION_LINK = 'AUTOCOUNT_EINVOICE_VALIDATION_LINK'; public const CREDIT_NOTE_APPROVAL_DATE = 'CREDIT_NOTE_APPROVAL_DATE'; public const TRANSACTION_MODEL_CLASS = 'App\Models\Transaction'; + public const BOOKING_EINVOICE_ELIGIBLE = 'BOOKING_EINVOICE_ELIGIBLE'; + } diff --git a/app/Http/Controllers/Exports/ExportController.php b/app/Http/Controllers/Exports/ExportController.php index 3b4836a3..3e482509 100644 --- a/app/Http/Controllers/Exports/ExportController.php +++ b/app/Http/Controllers/Exports/ExportController.php @@ -10,113 +10,77 @@ use Illuminate\Support\Facades\Storage; use App\Classes\General\AWSS3Helper; use App\Classes\Modules\Exports\Services\ExportsARCreditNoteReport; use App\Classes\Modules\Exports\Services\ExportsCompanies; +use App\Classes\Modules\Exports\Services\ExportsReceivePaymentDepositEntryReport; +use App\Classes\Modules\Exports\Services\ExportsReceivePaymentForBookingReport; use Carbon\Carbon; class ExportController { public function salesInvoices(Request $request){ - $validated = $request->validate([ - 'startDate' => 'nullable|date_format:d-m-Y', - 'endDate' => 'nullable|date_format:d-m-Y|after_or_equal:startDate', - ]); - - $startDate = null; - $endDate = null; - - if (isset($validated['startDate']) && $validated['startDate']) { - $startDate = Carbon::createFromFormat('d-m-Y', $validated['startDate'])->startOfDay(); - } else { - $startDate = Carbon::now()->subMonths(1)->startOfDay(); - } - - if (isset($validated['endDate']) && $validated['endDate']) { - $endDate = Carbon::createFromFormat('d-m-Y', $validated['endDate'])->endOfDay(); - } else { - $endDate = Carbon::now()->endOfDay(); - } - - - $exportsTransactions = new ExportsSalesInvoiceReport($startDate, $endDate); - - $exportFileName = 'Exchange - Sales Invoice Report.xls'; - $filesystemDriver = Storage::getDefaultDriver(); - if($filesystemDriver === 's3'){ - return response([ 'src' => AWSS3Helper::S3Exportable($exportFileName, $exportsTransactions) ]); - } - else{ - $response = $exportsTransactions->download($exportFileName, Excel::XLS, ['Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']); - ob_end_clean(); - } - return $response; + [$startDate, $endDate] = $this->getValidatedDates($request); + $exporter = new ExportsSalesInvoiceReport($startDate, $endDate); + return $this->handleExport($exporter, 'Exchange - Sales Invoice Report.xls'); } public function companies(Request $request){ + [$startDate, $endDate] = $this->getValidatedDates($request); + $exporter = new ExportsCompanies($startDate, $endDate); + return $this->handleExport($exporter, 'Exchange - Customers Data Report.xls'); + } + + public function arCreditNote(Request $request){ + [$startDate, $endDate] = $this->getValidatedDates($request); + $exporter = new ExportsARCreditNoteReport($startDate, $endDate); + return $this->handleExport($exporter, 'Exchange - AR Credit Note Report.xls'); + } + + public function receivePaymentDepositEntry(Request $request){ + [$startDate, $endDate] = $this->getValidatedDates($request); + $exporter = new ExportsReceivePaymentDepositEntryReport($startDate, $endDate); + return $this->handleExport($exporter, '01D - EXCHANGE - RECEIVE PAYMENT (FULL PAYMENT) [AR DEPOSIT ENTRY].xls'); + } + + public function receivePaymentDepositForBooking(Request $request){ + [$startDate, $endDate] = $this->getValidatedDates($request); + $exporter = new ExportsReceivePaymentForBookingReport($startDate, $endDate); + return $this->handleExport($exporter, '01R- RECEIVE PAYMENT (FULL PAYMENT) [AR RECEIVE PAYMENT].xls'); + } + + private function getValidatedDates(Request $request): array + { $validated = $request->validate([ 'startDate' => 'nullable|date_format:d-m-Y', 'endDate' => 'nullable|date_format:d-m-Y|after_or_equal:startDate', ]); - $startDate = null; - $endDate = null; + $startDate = isset($validated['startDate']) && $validated['startDate'] + ? Carbon::createFromFormat('d-m-Y', $validated['startDate'])->startOfDay() + : Carbon::now()->subMonth()->startOfDay(); - if (isset($validated['startDate']) && $validated['startDate']) { - $startDate = Carbon::createFromFormat('d-m-Y', $validated['startDate'])->startOfDay(); - } else { - $startDate = Carbon::now()->subMonths(1)->startOfDay(); - } + $endDate = isset($validated['endDate']) && $validated['endDate'] + ? Carbon::createFromFormat('d-m-Y', $validated['endDate'])->endOfDay() + : Carbon::now()->endOfDay(); - if (isset($validated['endDate']) && $validated['endDate']) { - $endDate = Carbon::createFromFormat('d-m-Y', $validated['endDate'])->endOfDay(); - } else { - $endDate = Carbon::now()->endOfDay(); - } - - $exportsCompanies = new ExportsCompanies($startDate, $endDate); - - $exportFileName = 'Exchange - Customers Data Report.xls'; - $filesystemDriver = Storage::getDefaultDriver(); - if($filesystemDriver === 's3'){ - return response([ 'src' => AWSS3Helper::S3Exportable($exportFileName, $exportsCompanies) ]); - } - else{ - $response = $exportsCompanies->download($exportFileName, Excel::XLS, ['Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']); - ob_end_clean(); - } - return $response; + return [$startDate, $endDate]; } - public function arCreditNote(Request $request){ - $validated = $request->validate([ - 'startDate' => 'nullable|date_format:d-m-Y', - 'endDate' => 'nullable|date_format:d-m-Y|after_or_equal:startDate', - ]); - - $startDate = null; - $endDate = null; - - if (isset($validated['startDate']) && $validated['startDate']) { - $startDate = Carbon::createFromFormat('d-m-Y', $validated['startDate'])->startOfDay(); - } else { - $startDate = Carbon::now()->subMonths(1)->startOfDay(); - } - - if (isset($validated['endDate']) && $validated['endDate']) { - $endDate = Carbon::createFromFormat('d-m-Y', $validated['endDate'])->endOfDay(); - } else { - $endDate = Carbon::now()->endOfDay(); - } - - $exportsTransactions = new ExportsARCreditNoteReport($startDate, $endDate); - - $exportFileName = 'Exchange - AR Credit Note Report.xls'; + private function handleExport($exporter, string $exportFileName) + { $filesystemDriver = Storage::getDefaultDriver(); - if($filesystemDriver === 's3'){ - return response([ 'src' => AWSS3Helper::S3Exportable($exportFileName, $exportsTransactions) ]); - } - else{ - $response = $exportsTransactions->download($exportFileName, Excel::XLS, ['Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']); - ob_end_clean(); + + if ($filesystemDriver === 's3') { + return response([ + 'src' => AWSS3Helper::S3Exportable($exportFileName, $exporter) + ]); } + + $response = $exporter->download( + $exportFileName, + Excel::XLS, + ['Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'] + ); + + ob_end_clean(); // prevent corrupt download in some environments return $response; } } diff --git a/app/Http/Controllers/Imports/ImportController.php b/app/Http/Controllers/Imports/ImportController.php index 02f364b6..5e045b03 100644 --- a/app/Http/Controllers/Imports/ImportController.php +++ b/app/Http/Controllers/Imports/ImportController.php @@ -9,9 +9,13 @@ use Illuminate\Http\Request; class ImportController extends Controller { - public function salesInvoices(Request $request, ImportExcelLogic $logic): JsonResponse { return $logic->execute($request); } + + public function officialReceipt(Request $request, ImportExcelLogic $logic): JsonResponse + { + return $logic->execute($request); + } } diff --git a/app/Http/Resources/BookingResource.php b/app/Http/Resources/BookingResource.php index 449c6a59..dbb11d0c 100644 --- a/app/Http/Resources/BookingResource.php +++ b/app/Http/Resources/BookingResource.php @@ -10,6 +10,7 @@ use App\Classes\ValueObjects\Constants\ApprovalStatus; use App\Classes\ValueObjects\Constants\BookingAttributeNames; use App\Classes\ValueObjects\Constants\TransactionType; use App\Classes\ValueObjects\Constants\DocumentType; +use App\Classes\ValueObjects\Constants\KVPKey; use Carbon\Carbon; use Illuminate\Http\Resources\Json\JsonResource; @@ -32,9 +33,12 @@ class BookingResource extends JsonResource if ($bookingCreatedDate->isAfter($eInvoiceStartDate) && $this->company->e_invoice === 1) { //&& $bookingCreatedDate->diffInMinutes($eInvoiceRequestedDate) <= 480 cief todo: 90 $eInvoice = true; } - // if ($this->company->e_invoice === 1) { - // $eInvoice = true; - // } + + $kvp = $this->attributesKVP()->where('key', KVPKey::BOOKING_EINVOICE_ELIGIBLE)->first(); + if($kvp){ + $eInvoice = true; + } + return [ 'id' => $this->id, 'company' => new CompanyResource($this->company), diff --git a/resources/assets/vue/components/bookings/elements/DownloadUploadComponent.vue b/resources/assets/vue/components/bookings/elements/DownloadUploadComponent.vue index 1461d0c6..c43d73dc 100644 --- a/resources/assets/vue/components/bookings/elements/DownloadUploadComponent.vue +++ b/resources/assets/vue/components/bookings/elements/DownloadUploadComponent.vue @@ -33,14 +33,18 @@
- +
@@ -69,6 +73,9 @@
+
+ {{error}} +
@@ -88,6 +95,7 @@ export default { }, data(){ return { + error: '', parameters: { startDate: '', endDate: '', @@ -95,6 +103,10 @@ export default { }, isDownloading: false, generateEInvoicesUrl: null, + allowedReportTypes: [ + 'Sales Invoice Report', + '01R - RECEIVE PAYMENT (FULL PAYMENT) [AR RECEIVE PAYMENT]', + ] } }, validations: { @@ -110,23 +122,40 @@ export default { }, } }, + computed: { + importUrl() { + const reportType = this.parameters.reportType; + + const importRoutesMap = { + 'Sales Invoice Report': route('api.import.sales_invoices'), + '01R - RECEIVE PAYMENT (FULL PAYMENT) [AR RECEIVE PAYMENT]': route('api.import.official_receipt'), + }; + + return importRoutesMap[reportType] || ''; + } + }, methods: { options() { return [ 'Sales Invoice Report', 'Customers Report', - 'AR Credit Note Report', + '01D - RECEIVE PAYMENT (FULL PAYMENT) [AR DEPOSIT ENTRY]', + '01R - RECEIVE PAYMENT (FULL PAYMENT) [AR RECEIVE PAYMENT]', + 'Credit Note Report', ]; }, handleExportClick(){ + this.error = ''; if (!this.validate()) return; const reportType = this.parameters.reportType; const routesMap = { - 'Sales Invoice Report': route('api.export.bookings.sales-invoices'), - 'Customers Report': route('api.export.companies.customers-data'), - 'AR Credit Note Report': route('api.export.transactions.ar-credit-note'), + 'Sales Invoice Report': route('api.export.bookings.sales_invoices'), + 'Customers Report': route('api.export.companies.customers_data'), + '01D - RECEIVE PAYMENT (FULL PAYMENT) [AR DEPOSIT ENTRY]': route('api.export.transactions.receive_payment_deposit_entry'), + '01R - RECEIVE PAYMENT (FULL PAYMENT) [AR RECEIVE PAYMENT]': route('api.export.transactions.receive_payment_for_booking'), + 'Credit Note Report': route('api.export.transactions.ar_credit_note'), }; let url = `${routesMap[reportType]}?startDate=${this.parameters.startDate}&endDate=${this.parameters.endDate}`; @@ -140,6 +169,7 @@ export default { } }, handleGenerateEInvoiceClick(){ + this.error = ''; if (!this.validate()) return; const reportType = this.parameters.reportType; @@ -170,7 +200,11 @@ export default { }, errorHandler(error) { this.isDownloading = false; + this.error = error.message + '. Please try again with a shorter date span between the two date filters.'; }, + importSuccess(payload) { + this.error = payload.message + payload.data; + } }, mixins: [componentHandler] }; diff --git a/resources/assets/vue/components/bookings/elements/UploadComponent.vue b/resources/assets/vue/components/bookings/elements/UploadComponent.vue index 3803d89f..2eeceba8 100644 --- a/resources/assets/vue/components/bookings/elements/UploadComponent.vue +++ b/resources/assets/vue/components/bookings/elements/UploadComponent.vue @@ -58,6 +58,10 @@ type: String, required: true }, + url: { + type: String, + required: true + }, }, data(){ return { @@ -77,8 +81,15 @@ report_type: this.reportType }; - this.submit(this.route('api.import.sales-invoices'), 'post', this.section, true, true); - } + this.submit(this.url, 'post', this.section, true, true); + }, + successHandler(response) { + this.closeModal(); + this.formHandler(); + if(this.url === route('api.import.official_receipt')){ + this.$emit('importSuccess', response.payload); + } + }, }, mixins: [ModalFromHandler] diff --git a/routes/export.php b/routes/export.php index 4801bc4e..4b1c2576 100644 --- a/routes/export.php +++ b/routes/export.php @@ -7,16 +7,19 @@ use Illuminate\Support\Facades\Route; Route::group(['prefix' => 'export', 'as' => 'export.', 'namespace' => 'Exports'], function () { Route::group(['prefix' => 'bookings', 'as' => 'bookings.'], function () { - Route::get('/sales-invoices', [ExportController::class, 'salesInvoices'])->name('sales-invoices'); + Route::get('/sales-invoices', [ExportController::class, 'salesInvoices'])->name('sales_invoices'); }); Route::group(['prefix' => 'companies', 'as' => 'companies.'], function () { - Route::get('/customers-data', [ExportController::class, 'companies'])->name('customers-data'); + Route::get('/customers-data', [ExportController::class, 'companies'])->name('customers_data'); }); Route::group(['prefix' => 'transactions', 'as' => 'transactions.'], function () { - Route::get('/ar-credit-note', [ExportController::class, 'arCreditNote'])->name('ar-credit-note'); + Route::get('/ar-credit-note', [ExportController::class, 'arCreditNote'])->name('ar_credit_note'); + Route::get('/receive-payment-deposit-entry', [ExportController::class, 'receivePaymentDepositEntry'])->name('receive_payment_deposit_entry'); + Route::get('/receive-payment-for-booking', [ExportController::class, 'receivePaymentDepositForBooking'])->name('receive_payment_for_booking'); }); }); Route::group(['prefix' => 'import', 'as' => 'import.', 'namespace' => 'Imports'], function () { - Route::post('/import', [ImportController::class, 'salesInvoices'])->name('sales-invoices'); + Route::post('/import/sales-invoice', [ImportController::class, 'salesInvoices'])->name('sales_invoices'); + Route::post('/import/offical-receipt', [ImportController::class, 'officialReceipt'])->name('official_receipt'); });