Update invoice generate and regenerate business logic

This commit is contained in:
Dillon Ngo
2026-04-29 11:03:03 +08:00
parent ee84035966
commit 6ebc716350
9 changed files with 262 additions and 218 deletions
@@ -67,12 +67,7 @@ class ApprovePurchaseOrderLogic extends AbstractControllerLogic
$this->updatesTransactionStatus->execute($purchaseOrder, ApprovalStatus::APPROVED);
if($booking->invoice_status === ApprovalStatus::APPROVED){
$bookingOriginalStatus = ApprovalStatus::COMPLETED;
}
else{
$bookingOriginalStatus = $booking->status;
}
$this->createInvoiceTransactionProcessor->execute($booking, "", null, [
'generateEInvoice' => false,
@@ -92,7 +92,7 @@ class CreatePurchaseOrderFor1688OrderProcessor
'generateEInvoice' => false,
'generateEInvoiceWithNormalInvoiceTemplate' => false,
'generateEInvoiceRefund' => false,
'bookingOriginalStatus' => ApprovalStatus::COMPLETED
'bookingOriginalStatus' => ApprovalStatus::COMPLETED //cief todo: 151
]
);
}
@@ -52,15 +52,24 @@ class RegenerateInvoiceBookingV2Processor
public function execute(Booking $booking,
bool $eInvoiceWithNormalInvoiceTemplate = false,
bool $eInvoiceWithRefund = false, bool $eInvoiceTry = false)
bool $eInvoiceWithRefund = false,
bool $eInvoiceTry = false ////cief todo: 151 - getting ready to get rid of eInvoiceTry as a parameter
)
{
$bookingOriginalStatus = $booking->status;
if($eInvoiceTry){
if($booking->invoice_status === ApprovalStatus::APPROVED){
$bookingOriginalStatus = ApprovalStatus::COMPLETED;
}
}
// Log::info('E-invoice flags', [
// 'eInvoiceWithNormalInvoiceTemplate' => $eInvoiceWithNormalInvoiceTemplate,
// 'eInvoiceWithRefund' => $eInvoiceWithRefund,
// 'eInvoiceTry' => $eInvoiceTry,
// ]);
// if($eInvoiceTry){
// if($booking->invoice_status === ApprovalStatus::APPROVED){
// // cief todo: must make sure TransactionType::BILL has status Approved (2)
// $bookingOriginalStatus = ApprovalStatus::COMPLETED;
// }
// }
if(!$eInvoiceWithRefund){
$this->updatesBookingStatus->execute($booking, ApprovalStatus::APPROVED);
@@ -116,10 +125,12 @@ class RegenerateInvoiceBookingV2Processor
$this->deletesTransaction->execute($row);
}
if($latestInvoice){
$kvpCopies = $latestInvoice->attributesKVP->map(function ($kvp) {
return $kvp->replicate();
});
}
}
//for E-INVOICE
else {
$transaction = $booking->transactions()->whereIn('type', [TransactionType::SUPPLIER_DELIVER])->get();
@@ -17,7 +17,7 @@ class UpdatesBookingInvoiceStatus extends AbstractUpdateRecord
*/
public function execute(Booking $model, UpdateBookingInvoiceStatusObject $object)
{
$model->invoice_status = $object->getInvoiceStatus();
$model->invoice_status = $object->getInvoiceStatus(); //invoice_status first used on Export Sales Invoice Report
return $this->handler($model);
}
}
@@ -95,7 +95,7 @@ class CreatePaymentProofDocumentLogic extends AbstractControllerLogic
'generateEInvoice' => false,
'generateEInvoiceWithNormalInvoiceTemplate' => false,
'generateEInvoiceRefund' => false,
'bookingOriginalStatus' => ApprovalStatus::COMPLETED
'bookingOriginalStatus' => ApprovalStatus::COMPLETED //cief todo: 151
]
);
@@ -67,6 +67,10 @@ class CreateInvoiceDocumentProcessor
}
else{
$lastPaymentTransaction = $booking->transactions()->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::COMPLETED, ApprovalStatus::APPROVED])->latest()->first();
if(!$lastPaymentTransaction){
$lastPaymentTransaction = $booking->transactions()->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::REFUNDED])->latest()->first();
}
}
$documentDate = $lastPaymentTransaction->created_at;
@@ -115,6 +119,9 @@ class CreateInvoiceDocumentProcessor
}
else{
$payment = $booking->transactions()->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::COMPLETED, ApprovalStatus::APPROVED])->first();
if(!$payment){
$payment = $booking->transactions()->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::REFUNDED])->first();
}
}
$refundAmount = $payment->transactions()->refunds()->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED])->sum('amount');
@@ -14,7 +14,9 @@ use App\Classes\Modules\Bookings\Services\CalculatesBookingPaidAmount;
use App\Classes\Modules\Bookings\Services\CalculatesBookingCurrencyAverageRate;
use App\Classes\Modules\Companies\Services\FetchesCompany;
use App\Classes\Modules\Bookings\Services\UpdatesBookingStatus;
use App\Classes\Modules\Bookings\Services\UpdatesBookingInvoiceStatus;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject;
use App\Classes\Modules\Bookings\DataTransferObjects\UpdateBookingInvoiceStatusObject;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\SegmentConstants;
use App\Classes\ValueObjects\Constants\TransactionType;
@@ -53,6 +55,9 @@ class CreateInvoiceTransactionV2Processor
/** @var UpdatesBookingStatus */
private $updatesBookingStatus;
/** @var UpdatesBookingInvoiceStatus */
private $updatesBookingInvoiceStatus;
/** @var CreateInvoiceDocumentProcessor */
private $invoiceDocumentProcessor;
@@ -74,8 +79,9 @@ class CreateInvoiceTransactionV2Processor
* @param UpdatesBookingStatus $updatesBookingStatus
* @param CreateInvoiceDocumentProcessor $invoiceDocumentProcessor
* @param CalculatesBookingRefundAmount $calculatesBookingRefundAmount
* @param UpdatesBookingInvoiceStatus $updatesBookingInvoiceStatus
*/
public function __construct(ListsTransactions $listsTransactions, CreatesTransaction $createsTransaction, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CalculatesBookingPaidAmount $calculatesBookingPaidAmount, CalculatesBookingPayableAmount $calculatesBookingPayableAmount, CalculatesBookingTransferredAmount $calculatesBookingTransferredAmount, FetchesServiceConfigurations $fetchesServiceConfigurations, CalculatesBookingCurrencyAverageRate $calculatesBookingCurrencyAverageRate, FetchesCompany $fetchesCompany, UpdatesBookingStatus $updatesBookingStatus, CreateInvoiceDocumentProcessor $invoiceDocumentProcessor, CalculatesBookingRefundAmount $calculatesBookingRefundAmount)
public function __construct(ListsTransactions $listsTransactions, CreatesTransaction $createsTransaction, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CalculatesBookingPaidAmount $calculatesBookingPaidAmount, CalculatesBookingPayableAmount $calculatesBookingPayableAmount, CalculatesBookingTransferredAmount $calculatesBookingTransferredAmount, FetchesServiceConfigurations $fetchesServiceConfigurations, CalculatesBookingCurrencyAverageRate $calculatesBookingCurrencyAverageRate, FetchesCompany $fetchesCompany, UpdatesBookingStatus $updatesBookingStatus, CreateInvoiceDocumentProcessor $invoiceDocumentProcessor, CalculatesBookingRefundAmount $calculatesBookingRefundAmount, UpdatesBookingInvoiceStatus $updatesBookingInvoiceStatus)
{
$this->createsTransaction = $createsTransaction;
$this->generatesTransactionBillNumber = $generatesTransactionBillNumber;
@@ -87,6 +93,7 @@ class CreateInvoiceTransactionV2Processor
$this->updatesBookingStatus = $updatesBookingStatus;
$this->invoiceDocumentProcessor = $invoiceDocumentProcessor;
$this->calculatesBookingRefundAmount = $calculatesBookingRefundAmount;
$this->updatesBookingInvoiceStatus = $updatesBookingInvoiceStatus;
}
@@ -106,11 +113,15 @@ class CreateInvoiceTransactionV2Processor
$generateEInvoiceRefund = $options['generateEInvoiceRefund'] ?? false;
$bookingOriginalStatus = $options['bookingOriginalStatus'] ?? null;
$bookingOriginalStatus = null; //cief todo: 151 - getting ready to get rid of bookingOriginalStatus as an options parameter
// Log::info('CreateInvoiceTransactionV2Processor generateEInvoice:' . json_encode($generateEInvoice));
// Log::info('CreateInvoiceTransactionV2Processor generateEInvoiceWithNormalInvoiceTemplate: ' . json_encode($generateEInvoiceWithNormalInvoiceTemplate));
// Log::info('CreateInvoiceTransactionV2Processor generateEInvoiceRefund: ' . json_encode($generateEInvoiceRefund));
// Log::info('CreateInvoiceTransactionV2Processor bookingOriginalStatus: ' . json_encode($bookingOriginalStatus));
$proceed = true;
if ($booking->status === ApprovalStatus::COMPLETED && !$generateEInvoiceRefund) {
Log::info('CreateInvoiceTransactionV2Processor Check 1 Bypass New Business Logic Update for booking ' . $booking->id);
// return;
@@ -121,11 +132,14 @@ class CreateInvoiceTransactionV2Processor
$booking_amount = $booking->fix_amount;
if ((float) $booking_amount === (float) $refund_amount && !$generateEInvoiceRefund) {
return;
Log::info('CreateInvoiceTransactionV2Processor Check 3 Bypass New Business Logic Update for booking ' . $booking->id);
//return;
}
// confirm that booking amount has been fully paid
if ((float) $booking_amount > (float) $payable_amount) {
Log::info('CreateInvoiceTransactionV2Processor return 1');
$proceed = false;
return;
}
// confirm that all payments has been transferred
@@ -134,11 +148,20 @@ class CreateInvoiceTransactionV2Processor
// return;
}
$purchaseOrder = $booking->transactions()
$completedPurchaseOrder = $booking->transactions()
->where('type', TransactionType::PURCHASE_ORDER)
->complete()
->first();
$purchaseOrder = $completedPurchaseOrder;
if($this->calculatesBookingTransferredAmount->execute($booking) === $this->calculatesBookingPaidAmount->execute($booking) && $completedPurchaseOrder) {
$bookingOriginalStatus = ApprovalStatus::COMPLETED;
}
else{
$bookingOriginalStatus = ApprovalStatus::APPROVED;
}
if($proceed){
if(!$purchaseOrder && $generateEInvoiceRefund){
$purchaseOrder = $booking->transactions()
->where('type', TransactionType::PURCHASE_ORDER)
@@ -241,10 +264,6 @@ class CreateInvoiceTransactionV2Processor
$invoice_transaction = $this->createsTransaction->execute($purchaseOrder->booking ?? $booking, $transaction_object);
}
//Update booking table, used on Export Sales Invoice Report
$booking->invoice_status = ApprovalStatus::APPROVED;
$booking->save();
if ($kvpCopies) {
foreach ($kvpCopies as $kvp) {
$invoice_transaction->attributesKVP()->save($kvp);
@@ -303,9 +322,17 @@ class CreateInvoiceTransactionV2Processor
}
else{ // Special handling for refund cases (When a refund is deleted via DeleteRefundTransactionLogic, a booking payment transaction is set to ApprovalStatus::APPROVED)
$paymentTransactionTemp = $booking->transactions()->payments()->where('status', ApprovalStatus::APPROVED)->first();
// Lets check if there is a refund case
// Lets check if there is a full refund case
if(!$paymentTransactionTemp){
$paymentTransactionTemp = $booking->transactions()->payments()->where('status', ApprovalStatus::REFUNDED)->first();
Log::info('CreateInvoiceTransactionV2Processor full refund: ' . json_encode($paymentTransactionTemp));
}
// Lets check if there is a partial refund case
$refund = $paymentTransactionTemp->transactions()->refunds()->where('status', ApprovalStatus::APPROVED)->first();
if($refund){
Log::info('CreateInvoiceTransactionV2Processor partial refund: ' . json_encode($refund));
$transactionTypeBill = $paymentTransactionTemp->transactions()->where('type', TransactionType::BILL)->first();
}
else{
@@ -337,15 +364,19 @@ class CreateInvoiceTransactionV2Processor
$this->invoiceDocumentProcessor->execute($supplier_deliver_order_transaction, $purchaseOrder, $supplier, DocumentType::SUPPLIER_DELIVER_ORDER, null);
}
}
// update perfex crm
// if(config('perfexcrm.is_enabled') == 'true'){
// CreatePerfexCRMInvoice::dispatch($invoice_transaction, $purchaseOrder, $supplier);
// }
}
}
if($bookingOriginalStatus){
$this->updatesBookingStatus->execute($booking, $bookingOriginalStatus);
$this->updateStatuses($booking, $bookingOriginalStatus ?? 0);
}
//Update booking overall status and invoice status
public function updateStatuses(Booking $booking, int $bookingStatus){
$updateBookingInvoiceStatusObject = new UpdateBookingInvoiceStatusObject($booking->id, ApprovalStatus::APPROVED);
$this->updatesBookingInvoiceStatus->execute($booking, $updateBookingInvoiceStatusObject);
if($bookingStatus){
$this->updatesBookingStatus->execute($booking, $bookingStatus);
}
}
}
+1 -1
View File
@@ -683,7 +683,7 @@ class DummyDataSeeder extends Seeder
'generateEInvoice' => false,
'generateEInvoiceWithNormalInvoiceTemplate' => false,
'generateEInvoiceRefund' => false,
'bookingOriginalStatus' => ApprovalStatus::COMPLETED
'bookingOriginalStatus' => ApprovalStatus::COMPLETED //cief todo: 151
]
);
}
@@ -413,7 +413,7 @@
</div>
<div class="row m-t-15" v-if="$store.getters.isSuperAdmin && showGenerateEInvoiceRefundButton">
<div class="col-sm col-md-auto">
<div class="btn btn-sm btn block all-caps b-rad-none btn-danger pointer requestModal equal-width-button" data-type="regenerateEInvoiceRefund">Regenerate E-Invoice<br>(Refund)</div>
<div class="btn btn-sm btn block all-caps b-rad-none btn-danger pointer requestModal equal-width-button" data-type="regenerateEInvoiceRefund">Regen Norm Inv/E-Inv<br>(Refund)</div>
</div>
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="regenerateEInvoiceRefund">
<regenerate-e-invoice-refund-component :data="booking" :section="section" class="text-center"></regenerate-e-invoice-refund-component>
@@ -427,14 +427,14 @@
<regenerate-e-invoice-component :data="booking" :section="section" class="text-center"></regenerate-e-invoice-component>
</modal-component>
</div>
<div class="row m-t-15" v-if="booking.status === 2 && ($store.getters.isSuperAdmin) && this.$store.getters.getUserId && this.$store.getters.getUserId === 5436">
<!-- <div class="row m-t-15" v-if="booking.status === 2 && ($store.getters.isSuperAdmin) && this.$store.getters.getUserId && this.$store.getters.getUserId === 5436">
<div class="col-sm col-md-auto">
<div class="btn btn-sm btn block all-caps b-rad-none btn-danger pointer requestModal equal-width-button" data-type="regenerateEInvoice">Regenerate E-Inv (Try)</div>
</div>
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="regenerateEInvoice">
<regenerate-e-invoice-try-component :data="booking" :section="section" class="text-center"></regenerate-e-invoice-try-component>
</modal-component>
</div>
</div> -->
<div class="row m-t-15" v-if="booking.status === 3 && ($store.getters.isSuperAdmin || ($store.getters.isCustomer && $store.getters.getCompanyId === 199)) && booking.einvoice">
<div class="col-sm col-md-auto">
<div class="btn btn-sm btn block all-caps b-rad-none btn-danger pointer requestModal equal-width-button" data-type="regenerateNormalInvoiceEInvoice">Regenerate Normal Inv</div>