diff --git a/app/Classes/General/Helper.php b/app/Classes/General/Helper.php index 8b5061ec..074eb26e 100644 --- a/app/Classes/General/Helper.php +++ b/app/Classes/General/Helper.php @@ -84,7 +84,7 @@ class Helper $ringgitWords = $numberTransformer->toWords((int)$ringgit); $centsWords = $numberTransformer->toWords((int)$cents); - return strtoupper('ringgit ' . $ringgitWords . ' and ' . $centsWords . ' cents only'); + return strtoupper('ringgit malaysia ' . $ringgitWords . ' and ' . $centsWords . ' cents only'); } public static function getLHDNStateCodeByName($name) diff --git a/app/Classes/Modules/Bookings/ControllersLogic/CreateBankingInvoiceTransactionLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/CreateBankingInvoiceTransactionLogic.php new file mode 100644 index 00000000..884614fe --- /dev/null +++ b/app/Classes/Modules/Bookings/ControllersLogic/CreateBankingInvoiceTransactionLogic.php @@ -0,0 +1,71 @@ + 'Create Banking Invoice Transaction', + 'message' => 'You have successfully create banking invoice transaction' + ]; + } + + /** @var CanFetchBooking */ + private $canFetchBooking; + + /** @var FetchesBooking */ + private $fetchesBooking; + + /** @var CreateBankingInvoiceTransactionProcessor */ + private $createBankingInvoiceTransactionProcessor; + + /** + * CreateBankingInvoiceTransactionLogic constructor. + * @param CanFetchBooking $canFetchBooking + * @param FetchesBooking $fetchesBooking + * @param CreateBankingInvoiceTransactionProcessor $createBankingInvoiceTransactionProcessor + */ + public function __construct( + CanFetchBooking $canFetchBooking, + FetchesBooking $fetchesBooking, + CreateBankingInvoiceTransactionProcessor $createBankingInvoiceTransactionProcessor + ) + { + $this->canFetchBooking = $canFetchBooking; + $this->fetchesBooking = $fetchesBooking; + $this->createBankingInvoiceTransactionProcessor = $createBankingInvoiceTransactionProcessor; + } + + + /** + * @param Request $request + * @return JsonResponse + * @throws \App\Classes\Exceptions\AccessForbiddenException + * @throws \App\Classes\Exceptions\MalformedRequestException + * @throws \App\Classes\Exceptions\RequestValidationException + */ + public function logic(Request $request) : JsonResponse + { + // $this->canFetchBooking->passes(); + + $booking = $this->fetchesBooking->execute(['id' => $request->route('id')]); + + $this->createBankingInvoiceTransactionProcessor->execute($booking); + + return $this->resourceResponse(new BookingResource($booking)); + } + +} diff --git a/app/Classes/Modules/Transactions/Processors/CreateBankingInvoiceTransactionProcessor.php b/app/Classes/Modules/Transactions/Processors/CreateBankingInvoiceTransactionProcessor.php new file mode 100644 index 00000000..eb3c3819 --- /dev/null +++ b/app/Classes/Modules/Transactions/Processors/CreateBankingInvoiceTransactionProcessor.php @@ -0,0 +1,233 @@ +createsTransaction = $createsTransaction; + $this->generatesTransactionBillNumber = $generatesTransactionBillNumber; + $this->fetchesCompany = $fetchesCompany; + $this->createsDocument = $createsDocument; + $this->createsFile = $createsFile; + $this->calculatesBookingOutstanding = $calculatesBookingOutstanding; + $this->fetchesBookingQuotation = $fetchesBookingQuotation; + $this->fetchesCompanyPaymentAttemptLimit = $fetchesCompanyPaymentAttemptLimit; + } + + + /** + * @param Booking $booking + * @return void + * @throws \App\Classes\Exceptions\MalformedRequestException + */ + public function execute(Booking $booking) + { + $po_order_transaction = $booking->transactions() + ->where('type', TransactionType::PURCHASE_ORDER) + ->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED]) + ->first(); + + $transaction = $booking->transactions() + ->where('type', TransactionType::PAYMENT) + ->whereNotIn('status', [ApprovalStatus::SUSPENDED]) + ->first(); + + if (!$transaction) { + $outstanding = $this->calculatesBookingOutstanding->execute($booking); + + $conversionObject = new CurrencyConversionObject(floatval(str_replace(',', '', $outstanding)), $booking->convertible_currency_id, $booking->service_id, $booking->fix_currency_id === 1 ? 0 : 1, PaymentMethodType::CASH); + + $configurations = $this->fetchesBookingQuotation->execute($booking->company, $conversionObject); //cief todo: 76 + + $paymentAttemptLimit = $this->fetchesCompanyPaymentAttemptLimit->execute($booking->company); + + $billNumber = $this->generatesTransactionBillNumber->execute('PYMT-'); + + $object = new TransactionObject( + $billNumber, + TransactionType::PAYMENT, + 1, + $booking->company->id, + $configurations->getConfigurations()->getBankId(), + $configurations->getConversionObject()->getPaymentMethod(), + $configurations->getTotal(), + $configurations->getForeignTotal(), + 1, + $configurations->getConversionObject()->getCurrencyId(), + $configurations->getConfigurations()->getRate(), + $configurations->getTax(), + $configurations->getServiceCharge(), + Carbon::now()->addMinutes($paymentAttemptLimit), + ApprovalStatus::PENDING_SUBMISSION, + [], + isset($billPlzBill) ? $billPlzBill->id : NULL + ); + + $this->createsTransaction->execute($booking, $object); + } + + $billNumber = $this->generatesTransactionBillNumber->execute('BI-'); + + $payable_amount = $booking->transactions()->payments()->where(function ($query) { + return $query->where(function ($query) { + // return $query->where('status', ApprovalStatus::PENDING_SUBMISSION)->whereDate('expires_on', '>=', Carbon::now())->where('expires_on', '>', Carbon::now()->toTimeString()); + return $query->where('status', ApprovalStatus::PENDING_SUBMISSION)->where('expires_on', '>=', Carbon::now()); + })->orWhere(function ($query) { + return $query->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + }); + })->sum('amount'); + $booking_amount = $booking->fix_amount; + + $transaction = $booking->transactions() + ->where('type', TransactionType::PAYMENT) + ->first(); + + $paymentAmount = $booking->transactions()->payments()->where(function ($query) { + return $query->where(function ($query) { + return $query->where('status', ApprovalStatus::PENDING_SUBMISSION)->where('expires_on', '>=', Carbon::now()); + })->orWhere(function ($query) { + return $query->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]); + }); + })->selectRaw('sum(amount - service_charge - tax) as sub_total')->get()->sum('sub_total'); + + $booking_currency_average_rate = $booking_amount / $paymentAmount; + + $total_service_charge = $booking->transactions() + ->where('type', TransactionType::PAYMENT) + ->whereNotIn('status', [ApprovalStatus::REJECTED, ApprovalStatus::SUSPENDED]) + ->sum('service_charge'); + + $total_tax = $booking->transactions() + ->where('type', TransactionType::PAYMENT) + ->whereIn('status', [ApprovalStatus::REJECTED, ApprovalStatus::SUSPENDED]) + ->sum('tax'); + + // delete prev banking transactions + $booking->transactions() + ->where('type', TransactionType::BANKING) + ->delete(); + + $transaction_object = new TransactionObject( + $billNumber, + TransactionType::BANKING, + $transaction->issuer, + $transaction->receiver, + $transaction->recipient_bank_account_id, + $transaction->payment_method, + $payable_amount, + $booking_amount, + $transaction->currency_id, + $transaction->original_currency_id, + $booking_currency_average_rate, + $total_tax, + $total_service_charge, + null, + ApprovalStatus::APPROVED + ); + + $banking_transaction = $this->createsTransaction->execute($po_order_transaction->booking, $transaction_object); + + $supplier = $this->fetchesCompany->execute(['id' => $transaction->receiver]); + $brn = $supplier->documents()->where('document_type', DocumentType::SSM_REGISTRATION)->latest()->first(); + + // PDF 1 - Banking Invoice + $purchase_order_pdf = LaravelMpdf::loadView('pages.pdfs.banking_invoice', + [ + 'transaction' => $banking_transaction, + 'po_order_transaction' => $po_order_transaction, + 'supplier' => $supplier, + 'brn' => $brn, + ]); + $document_object = new DocumentObject( + DocumentType::BANKING_INVOICE, + [chunk_split('data:application/pdf;base64,' . base64_encode($purchase_order_pdf->output()))], + '', + ApprovalStatus::COMPLETED, + 'banking_invoices' + ); + + /** @var Document $document */ + $document = $this->createsDocument->execute($po_order_transaction->booking, $document_object); + $this->createsFile->execute($document, $document_object); + + // PDF 2 - Banking Delivery Order + $purchase_order_pdf = LaravelMpdf::loadView('pages.pdfs.deliver_order_banking', + [ + 'transaction' => $banking_transaction, + 'po_order_transaction' => $po_order_transaction, + 'supplier' => $supplier, + 'brn' => $brn, + ]); + $document_object = new DocumentObject( + DocumentType::DELIVER_ORDER_BANKING, + [chunk_split('data:application/pdf;base64,' . base64_encode($purchase_order_pdf->output()))], + '', + ApprovalStatus::COMPLETED, + 'banking_invoices' + ); + + /** @var Document $document */ + $document = $this->createsDocument->execute($po_order_transaction->booking, $document_object); + $this->createsFile->execute($document, $document_object); + } +} diff --git a/app/Classes/ValueObjects/Constants/DocumentType.php b/app/Classes/ValueObjects/Constants/DocumentType.php index 91ff84bb..8da383d4 100644 --- a/app/Classes/ValueObjects/Constants/DocumentType.php +++ b/app/Classes/ValueObjects/Constants/DocumentType.php @@ -30,4 +30,7 @@ final class DocumentType { public const RECEIPT_VOUCHER = 'RECEIPT_VOUCHER'; public const EINVOICE = 'E_INVOICE'; + + public const BANKING_INVOICE = 'BANKING_INVOICE'; + public const DELIVER_ORDER_BANKING = 'DELIVER_ORDER_BANKING'; } diff --git a/app/Classes/ValueObjects/Constants/TransactionType.php b/app/Classes/ValueObjects/Constants/TransactionType.php index efb11f5c..e02ec0ad 100644 --- a/app/Classes/ValueObjects/Constants/TransactionType.php +++ b/app/Classes/ValueObjects/Constants/TransactionType.php @@ -40,6 +40,8 @@ final class TransactionType { public const RECEIPT_VOUCHER = 17; + public const BANKING = 18; + public const ID_TO_NAME = [ self::PAYMENT_ATTEMPT => "PAYMENT_ATTEMPT", self::PAYMENT => "PAYMENT", @@ -57,6 +59,7 @@ final class TransactionType { self::CASH_BACK => "CASH_BACK", self::SUPPLIER_PAYMENT => "SUPPLIER_PAYMENT", self::SUPPLIER_REFUND => "SUPPLIER_REFUND", + self::BANKING => "BANKING", ]; } diff --git a/app/Http/Controllers/Bookings/CreateBankingInvoiceTransactionController.php b/app/Http/Controllers/Bookings/CreateBankingInvoiceTransactionController.php new file mode 100644 index 00000000..dc1636aa --- /dev/null +++ b/app/Http/Controllers/Bookings/CreateBankingInvoiceTransactionController.php @@ -0,0 +1,20 @@ +execute($request); + } + +} diff --git a/app/Http/Resources/BookingResource.php b/app/Http/Resources/BookingResource.php index 9c6edf96..fef78809 100644 --- a/app/Http/Resources/BookingResource.php +++ b/app/Http/Resources/BookingResource.php @@ -65,6 +65,8 @@ class BookingResource extends JsonResource 'supplier_delivery_order' => new DocumentResource($this->documents()->where('document_type', DocumentType::SUPPLIER_DELIVER_ORDER)->first()), 'proforma_invoice' => new DocumentResource($this->documents()->where('document_type', DocumentType::PROFORMA_INVOICE)->whereNotIn('status', [ApprovalStatus::REJECTED, ApprovalStatus::EXPIRED])->orderByDesc('id')->first()), 'ecommerce_purchase_order' => new DocumentResource($this->documents()->where('document_type', DocumentType::ECOMMERCE_PURCHASE_ORDER)->first()), + 'banking_invoice' => new DocumentResource($this->documents()->where('document_type', DocumentType::BANKING_INVOICE)->whereNotIn('status', [ApprovalStatus::REJECTED, ApprovalStatus::EXPIRED])->orderByDesc('id')->first()), + 'delivery_order_banking' => new DocumentResource($this->documents()->where('document_type', DocumentType::DELIVER_ORDER_BANKING)->orderByDesc('id')->first()), ], 'order_reference_no' => $this->modelAttributes()->where('name', BookingAttributeNames::ORDER_REFERENCE_NO)->get()->map(function ($attr) { return [ diff --git a/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue b/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue index 8e6959e0..471a44d2 100644 --- a/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue +++ b/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue @@ -181,31 +181,18 @@ -
-
-
-
- - - - -
-
+ + +
+
-
-