Merge branch 'dillon/90-e-invoice-e' into vapor/development

This commit is contained in:
Dillon Ngo
2025-12-12 13:10:50 +08:00
18 changed files with 357 additions and 144 deletions
@@ -2,31 +2,32 @@
namespace App\Classes\Modules\Billplzs\ControllersLogic;
use App\Classes\Modules\Wallets\DataTransferObjects\WalletObject;
use App\Classes\Modules\Wallets\Services\UpdatesWallet;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ResourceNotFoundException;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Jobs\Commands\V2\CreateInvoiceTransactionV2CommandJob;
use App\Classes\Modules\Billplzs\DataTransferObjects\BillplzXSignatureObject;
use App\Classes\Modules\Billplzs\Services\GetBillplzBill;
use App\Classes\Modules\Transactions\Processors\CreateCashBackTransactionProcessor;
use App\Classes\Modules\Transactions\Processors\CreateReceiptVoucherTransactionProcessor;
use App\Classes\Exceptions\ResourceNotFoundException;
use App\Classes\Modules\Transactions\Services\FetchesTransaction;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use App\Classes\Modules\Wallets\DataTransferObjects\WalletObject;
use App\Classes\Modules\Wallets\Services\RecalculatesWalletBalance;
use App\Classes\Modules\Wallets\Services\UpdatesWallet;
use App\Classes\Modules\Wallets\Services\UpdatesWalletBalance;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Http\Resources\TransactionResource;
use App\Models\Booking;
use App\Models\User;
use App\Models\Wallet;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\Modules\Billplzs\Services\GetBillplzBill;
use App\Classes\Modules\Billplzs\DataTransferObjects\BillplzXSignatureObject;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Transactions\Services\FetchesTransaction;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use App\Classes\Modules\Wallets\Services\RecalculatesWalletBalance;
class CallbackBillplzLogic
{
@@ -117,6 +118,10 @@ class CallbackBillplzLogic
$this->createReceiptVoucherTransactionProcessor->execute($booking, $transaction);
}
if($booking){
CreateInvoiceTransactionV2CommandJob::dispatch($booking);
}
// if ($transaction->type == TransactionType::PAYMENT) {
// $cash_back_transaction = $this->createCashBackTransactionProcessor->execute($transaction);
// }
@@ -72,7 +72,8 @@ class ApprovePurchaseOrderLogic extends AbstractControllerLogic
'generateEInvoiceWithNormalInvoiceTemplate' => false,
'generateEInvoiceRefund' => false,
'bookingOriginalStatus' => $booking->status
]);
]
);
return $this->response([]);
}
@@ -2,28 +2,29 @@
namespace App\Classes\Modules\Bookings\ControllersLogic;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\CriteriaNotFulfilledException;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Jobs\Commands\V2\CreateInvoiceTransactionV2CommandJob;
use App\Classes\Modules\Bookings\DataTransferObjects\BookingObject;
use App\Classes\Modules\Bookings\DataTransferObjects\UpdateBookingInvoiceStatusObject;
use App\Classes\Modules\Bookings\Services\CalculatesBookingOutstanding;
use App\Classes\Modules\Bookings\Services\FetchesBooking;
use App\Classes\Modules\Bookings\Services\UpdatesBookingInvoiceStatus;
use App\Classes\Modules\Bookings\Services\UpdatesBookingFixedAmount;
use App\Classes\Modules\Bookings\Standards\Rules\CanUpdateBooking;
use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionV2Processor;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Http\Resources\BookingResource;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Bookings\Services\FetchesBooking;
use App\Classes\Modules\Bookings\Standards\Rules\CanUpdateBooking;
use App\Classes\Modules\Bookings\DataTransferObjects\BookingObject;
use App\Classes\Modules\Rules\DataTransferObjects\CheckTransferPeriodLockRuleVariant2DTO;
use App\Classes\Modules\Bookings\Services\CalculatesBookingOutstanding;
use App\Classes\Modules\Rules\Services\RuleEvaluator;
use App\Classes\Modules\Rules\Standards\Rules\CanPassTransferPeriodLockRule;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\CriteriaNotFulfilledException;
use Illuminate\Support\Facades\Log;
class UpdateBookingAmountLogic extends AbstractControllerLogic
@@ -61,6 +62,12 @@ class UpdateBookingAmountLogic extends AbstractControllerLogic
/** @var CanPassTransferPeriodLockRule */
private $canPassTransferPeriodLockRule;
/** @var UpdatesBookingInvoiceStatus */
private $updatesBookingInvoiceStatus;
/** @var CreateInvoiceTransactionV2Processor */
private $createInvoiceTransactionProcessor;
/**
* UpdateBookingAmountLogic constructor.
* @param CanUpdateBooking $canUpdateBooking
@@ -70,8 +77,10 @@ class UpdateBookingAmountLogic extends AbstractControllerLogic
* @param UpdatesTransactionStatus $updatesTransactionStatus
* @param RuleEvaluator $ruleEvaluator
* @param CanPassTransferPeriodLockRule $canPassTransferPeriodLockRule
* @param UpdatesBookingInvoiceStatus $updatesBookingInvoiceStatus
* @param CreateInvoiceTransactionV2Processor $createInvoiceTransactionProcessor
*/
public function __construct(CanUpdateBooking $canUpdateBooking, UpdatesBookingFixedAmount $updatesBookingFixedAmount, FetchesBooking $fetchesBooking, CalculatesBookingOutstanding $calculatesBookingOutstanding, UpdatesTransactionStatus $updatesTransactionStatus, RuleEvaluator $ruleEvaluator, CanPassTransferPeriodLockRule $canPassTransferPeriodLockRule)
public function __construct(CanUpdateBooking $canUpdateBooking, UpdatesBookingFixedAmount $updatesBookingFixedAmount, FetchesBooking $fetchesBooking, CalculatesBookingOutstanding $calculatesBookingOutstanding, UpdatesTransactionStatus $updatesTransactionStatus, RuleEvaluator $ruleEvaluator, CanPassTransferPeriodLockRule $canPassTransferPeriodLockRule, UpdatesBookingInvoiceStatus $updatesBookingInvoiceStatus, CreateInvoiceTransactionV2Processor $createInvoiceTransactionProcessor)
{
$this->canUpdateBooking = $canUpdateBooking;
$this->updatesBookingFixedAmount = $updatesBookingFixedAmount;
@@ -80,6 +89,8 @@ class UpdateBookingAmountLogic extends AbstractControllerLogic
$this->updatesTransactionStatus = $updatesTransactionStatus;
$this->ruleEvaluator = $ruleEvaluator;
$this->canPassTransferPeriodLockRule = $canPassTransferPeriodLockRule;
$this->updatesBookingInvoiceStatus = $updatesBookingInvoiceStatus;
$this->createInvoiceTransactionProcessor = $createInvoiceTransactionProcessor;
}
/**
@@ -124,6 +135,14 @@ class UpdateBookingAmountLogic extends AbstractControllerLogic
$booking = $this->updatesBookingFixedAmount->execute($booking, $input_amount);
if($booking->invoice_status === ApprovalStatus::APPROVED){
$updateBookingInvoiceStatusObject = new UpdateBookingInvoiceStatusObject($booking->id, ApprovalStatus::PENDING_VERIFICATION);
$this->updatesBookingInvoiceStatus->execute($booking, $updateBookingInvoiceStatusObject);
}
else{
$this->createInvoiceTransactionProcessor->execute($booking);
}
return $this->resourceResponse(new BookingResource($booking));
}
@@ -91,6 +91,7 @@ class UpdateBookingAmountOnHoldLogic extends AbstractControllerLogic
}
$key = "BOOKING_AMOUNT_UPDATE";
$keyValuePairObject = new KeyValuePairObject($key, $input_amount);
$metadata = $booking->attributesKVP()->where('key', $key)->first();
if($metadata){
@@ -10,6 +10,10 @@ use App\Classes\Modules\Bookings\Services\UpdatesBookingFixedAmount;
use App\Classes\Modules\Bookings\Services\CalculatesBookingOutstanding;
use App\Classes\Modules\Bookings\Services\CalculatesBookingPayableAmount;
use App\Classes\Modules\Bookings\Services\CalculatesBookingRefundAmount;
use App\Classes\Modules\Bookings\Services\UpdatesBookingInvoiceStatus;
use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionV2Processor;
use App\Classes\Modules\Bookings\DataTransferObjects\UpdateBookingInvoiceStatusObject;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Http\Resources\BookingResource;
use App\Models\Booking;
@@ -45,6 +49,12 @@ class UpdateBookingAmountWithPOLogic extends AbstractControllerLogic
/** @var CalculatesBookingRefundAmount */
private $calculatesBookingRefundAmount;
/** @var UpdatesBookingInvoiceStatus */
private $updatesBookingInvoiceStatus;
/** @var CreateInvoiceTransactionV2Processor */
private $createInvoiceTransactionProcessor;
/**
* UpdateBookingAmountWithPOLogic constructor.
* @param FetchesBooking $fetchesBooking
@@ -52,14 +62,18 @@ class UpdateBookingAmountWithPOLogic extends AbstractControllerLogic
* @param CalculatesBookingOutstanding $calculatesBookingOutstanding
* @param CalculatesBookingPayableAmount $calculatesBookingPayableAmount
* @param CalculatesBookingRefundAmount $calculatesBookingRefundAmount
* @param UpdatesBookingInvoiceStatus $updatesBookingInvoiceStatus
* @param CreateInvoiceTransactionV2Processor $createInvoiceTransactionProcessor
*/
public function __construct(FetchesBooking $fetchesBooking, UpdatesBookingFixedAmount $updatesBookingFixedAmount, CalculatesBookingOutstanding $calculatesBookingOutstanding, CalculatesBookingPayableAmount $calculatesBookingPayableAmount, CalculatesBookingRefundAmount $calculatesBookingRefundAmount)
public function __construct(FetchesBooking $fetchesBooking, UpdatesBookingFixedAmount $updatesBookingFixedAmount, CalculatesBookingOutstanding $calculatesBookingOutstanding, CalculatesBookingPayableAmount $calculatesBookingPayableAmount, CalculatesBookingRefundAmount $calculatesBookingRefundAmount, UpdatesBookingInvoiceStatus $updatesBookingInvoiceStatus, CreateInvoiceTransactionV2Processor $createInvoiceTransactionProcessor)
{
$this->fetchesBooking = $fetchesBooking;
$this->updatesBookingFixedAmount = $updatesBookingFixedAmount;
$this->calculatesBookingOutstanding = $calculatesBookingOutstanding;
$this->calculatesBookingPayableAmount = $calculatesBookingPayableAmount;
$this->calculatesBookingRefundAmount = $calculatesBookingRefundAmount;
$this->updatesBookingInvoiceStatus = $updatesBookingInvoiceStatus;
$this->createInvoiceTransactionProcessor = $createInvoiceTransactionProcessor;
}
/**
@@ -110,6 +124,14 @@ class UpdateBookingAmountWithPOLogic extends AbstractControllerLogic
$booking->transactions()->where('type', TransactionType::PROFORMA)->delete();
$booking = $this->updatesBookingFixedAmount->execute($booking, $bookingAmountUpdate);
if($booking->invoice_status === ApprovalStatus::APPROVED){
$updateBookingInvoiceStatusObject = new UpdateBookingInvoiceStatusObject($booking->id, ApprovalStatus::PENDING_VERIFICATION);
$this->updatesBookingInvoiceStatus->execute($booking, $updateBookingInvoiceStatusObject);
}
else{
$this->createInvoiceTransactionProcessor->execute($booking);
}
$request->merge(['is_privilleged_update' => true]);
$bookingAttribute->delete();
@@ -0,0 +1,42 @@
<?php
namespace App\Classes\Modules\Bookings\DataTransferObjects;
use App\Classes\General\Interfaces\DataTransferObject;
class UpdateBookingInvoiceStatusObject implements DataTransferObject
{
/** @var int */
private $id;
/** @var int */
private $invoiceStatus;
/**
* UpdateBookingInvoiceStatusObject constructor.
* @param int $id
* @param int $invoiceStatus
*/
public function __construct(int $id, int $invoiceStatus)
{
$this->id = $id;
$this->invoiceStatus = $invoiceStatus;
}
/**
* @return int
*/
public function getId(): int
{
return $this->id;
}
/**
* @return int
*/
public function getInvoiceStatus(): int
{
return $this->invoiceStatus;
}
}
@@ -88,7 +88,13 @@ class CreatePurchaseOrderFor1688OrderProcessor
if($purchaseOrder->amount === $booking->fix_amount){
$this->updatesTransactionStatus->execute($purchaseOrder, ApprovalStatus::APPROVED);
$this->createInvoiceTransactionProcessor->execute($booking);
$this->createInvoiceTransactionProcessor->execute($booking, "", null, [
'generateEInvoice' => false,
'generateEInvoiceWithNormalInvoiceTemplate' => false,
'generateEInvoiceRefund' => false,
'bookingOriginalStatus' => ApprovalStatus::COMPLETED
]
);
}
}
@@ -0,0 +1,23 @@
<?php
namespace App\Classes\Modules\Bookings\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Classes\Modules\Bookings\DataTransferObjects\UpdateBookingInvoiceStatusObject;
use App\Models\Booking;
class UpdatesBookingInvoiceStatus extends AbstractUpdateRecord
{
/**
* @param Booking $model
* @param UpdateBookingInvoiceStatusObject $object
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(Booking $model, UpdateBookingInvoiceStatusObject $object)
{
$model->invoice_status = $object->getInvoiceStatus();
return $this->handler($model);
}
}
@@ -73,7 +73,7 @@ class ExportsSalesInvoiceReport implements FromQuery, WithHeadings, WithHeadingR
'transactions.voucherRedemption.voucher.campaign'
])
// ->whereIn('status', [ApprovalStatus::COMPLETED])
->where('is_invoice_generated', 1)
->whereIn('invoice_status', [ApprovalStatus::APPROVED])
->whereHas('transactions', function ($query) use ($startDate, $endDate) {
$query->payments()
->complete()
@@ -91,7 +91,13 @@ class CreatePaymentProofDocumentLogic extends AbstractControllerLogic
$this->updatesTransactionStatus->execute($transaction, ApprovalStatus::APPROVED);
$this->createInvoiceTransactionProcessor->execute($transaction->owner->booking);
$this->createInvoiceTransactionProcessor->execute($transaction->owner->booking, "", null, [
'generateEInvoice' => false,
'generateEInvoiceWithNormalInvoiceTemplate' => false,
'generateEInvoiceRefund' => false,
'bookingOriginalStatus' => ApprovalStatus::COMPLETED
]
);
//cief todo: Prototype Period Lock - Starts
$this->updateOrCreateKeyValuePair($transaction->owner->booking, KVPKey::BOOKING_IS_LOCKED, 1);
@@ -104,7 +104,12 @@ class CreateInvoiceTransactionV2Processor
$generateEInvoice = $options['generateEInvoice'] ?? false;
$generateEInvoiceWithNormalInvoiceTemplate = $options['generateEInvoiceWithNormalInvoiceTemplate'] ?? false;
$generateEInvoiceRefund = $options['generateEInvoiceRefund'] ?? false;
$bookingOriginalStatus = $options['bookingOriginalStatus'] ?? ApprovalStatus::COMPLETED;
$bookingOriginalStatus = $options['bookingOriginalStatus'] ?? ApprovalStatus::APPROVED;
// 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));
if ($booking->status === ApprovalStatus::COMPLETED && !$generateEInvoiceRefund) {
Log::info('CreateInvoiceTransactionV2Processor Check 1 Bypass New Business Logic Update for booking ' . $booking->id);
@@ -133,6 +138,7 @@ class CreateInvoiceTransactionV2Processor
->where('type', TransactionType::PURCHASE_ORDER)
->complete()
->first();
if(!$purchaseOrder && $generateEInvoiceRefund){
$purchaseOrder = $booking->transactions()
->where('type', TransactionType::PURCHASE_ORDER)
@@ -141,14 +147,9 @@ class CreateInvoiceTransactionV2Processor
}
$constants = SegmentConstant::where('reference', SegmentConstants::SERVICE_TYPE)->where('detail->id', $booking->service->id)->first();
if ($constants->detail->is_billable && !$purchaseOrder && !$generateEInvoiceRefund) {
return;
}
// $transaction = $booking->transactions()
// ->where('type', TransactionType::PAYMENT)
// ->first();
// if ($constants->detail->is_billable && !$purchaseOrder && !$generateEInvoiceRefund) {
// return;
// }
$transaction = $booking->transactions()
->where('type', TransactionType::PAYMENT)
@@ -207,29 +208,39 @@ class CreateInvoiceTransactionV2Processor
->sum('tax');
}
$invoice_transaction = null;
if($booking->status === ApprovalStatus::APPROVED){
//NEW INVOICE for non-einvoice user applicable only when booking is completed
$invoice_transaction = $booking->transactions()
->where('type', TransactionType::INVOICE)
->complete()
->latest()
->first();
}
$transaction_object = new TransactionObject(
$billNumber,
TransactionType::INVOICE,
$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
);
$invoice_transaction = $this->createsTransaction->execute($purchaseOrder->booking ?? $booking, $transaction_object);
if(!$invoice_transaction) {
$transaction_object = new TransactionObject(
$billNumber,
TransactionType::INVOICE,
$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
);
$invoice_transaction = $this->createsTransaction->execute($purchaseOrder->booking ?? $booking, $transaction_object);
}
//Update booking table, used on Export Sales Invoice Report
$booking->is_invoice_generated = true;
$booking->invoice_status = ApprovalStatus::APPROVED;
$booking->save();
if ($kvpCopies) {
@@ -240,7 +251,7 @@ class CreateInvoiceTransactionV2Processor
$voucherRedemption = $transaction->voucherRedemption;
if($generateEInvoiceRefund){
if($generateEInvoiceRefund){
$metadata = $booking->attributesKVP()->where('key', KVPKey::AUTOCOUNT_DOCNO_INVOICE)->first();
if($metadata){
$generateEInvoice = true;
@@ -253,84 +264,86 @@ class CreateInvoiceTransactionV2Processor
}
}
// purchase order
if(!$generateEInvoiceRefund){
$this->invoiceDocumentProcessor->execute($invoice_transaction, $purchaseOrder, $supplier, DocumentType::PURCHASE_ORDER, $voucherRedemption, $generateEInvoiceWithNormalInvoiceTemplate);
}
// deliver order
if(!$generateEInvoiceRefund){
$this->invoiceDocumentProcessor->execute($invoice_transaction, $purchaseOrder, $supplier, DocumentType::DELIVER_ORDER, $voucherRedemption, $generateEInvoiceWithNormalInvoiceTemplate);
}
// e-invoice
if ($eInvoice)
{
if($generateEInvoice){
$this->invoiceDocumentProcessor->execute($invoice_transaction, $purchaseOrder, $supplier, DocumentType::EINVOICE, $voucherRedemption, $generateEInvoiceWithNormalInvoiceTemplate, $generateEInvoiceRefund);
if($purchaseOrder){
// purchase order
if(!$generateEInvoiceRefund){
$this->invoiceDocumentProcessor->execute($invoice_transaction, $purchaseOrder, $supplier, DocumentType::PURCHASE_ORDER, $voucherRedemption, $generateEInvoiceWithNormalInvoiceTemplate);
}
}
// invoice
else
{
$this->invoiceDocumentProcessor->execute($invoice_transaction, $purchaseOrder, $supplier, DocumentType::INVOICE, $voucherRedemption, $generateEInvoiceWithNormalInvoiceTemplate, $generateEInvoiceRefund);
}
if(!$generateEInvoiceRefund){
$billNumber = $this->generatesTransactionBillNumber->execute('SPDO-');
$booking_currency_average_rate = $this->calculatesBookingCurrencyAverageRate->execute($booking, TransactionType::BILL, $generateEInvoiceRefund);
$paymentTransaction = $booking->transactions()->payments()->where('status', ApprovalStatus::COMPLETED)->first();
$transaction = null;
if($paymentTransaction){
$transaction = $paymentTransaction->transactions()->where('type', TransactionType::BILL)->first();
// deliver order
if(!$generateEInvoiceRefund){
$this->invoiceDocumentProcessor->execute($invoice_transaction, $purchaseOrder, $supplier, DocumentType::DELIVER_ORDER, $voucherRedemption, $generateEInvoiceWithNormalInvoiceTemplate);
}
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
$refund = $paymentTransactionTemp->transactions()->refunds()->where('status', ApprovalStatus::APPROVED)->first();
if($refund){
$transaction = $paymentTransactionTemp->transactions()->where('type', TransactionType::BILL)->first();
// e-invoice
if ($eInvoice)
{
if($generateEInvoice){
$this->invoiceDocumentProcessor->execute($invoice_transaction, $purchaseOrder, $supplier, DocumentType::EINVOICE, $voucherRedemption, $generateEInvoiceWithNormalInvoiceTemplate, $generateEInvoiceRefund);
}
else{
Log::info("CreateInvoiceTransactionV2Processor NO completed payment transaction, refund transaction found for booking '$booking->id'.");
}
// invoice
else
{
$this->invoiceDocumentProcessor->execute($invoice_transaction, $purchaseOrder, $supplier, DocumentType::INVOICE, $voucherRedemption, $generateEInvoiceWithNormalInvoiceTemplate, $generateEInvoiceRefund);
}
if(!$generateEInvoiceRefund){
$billNumber = $this->generatesTransactionBillNumber->execute('SPDO-');
$booking_currency_average_rate = $this->calculatesBookingCurrencyAverageRate->execute($booking, TransactionType::BILL, $generateEInvoiceRefund);
$paymentTransaction = $booking->transactions()->payments()->where('status', ApprovalStatus::COMPLETED)->first();
$transactionTypeBill= null;
if($paymentTransaction){
$transactionTypeBill = $paymentTransaction->transactions()->where('type', TransactionType::BILL)->first();
}
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
$refund = $paymentTransactionTemp->transactions()->refunds()->where('status', ApprovalStatus::APPROVED)->first();
if($refund){
$transactionTypeBill = $paymentTransactionTemp->transactions()->where('type', TransactionType::BILL)->first();
}
else{
Log::info("CreateInvoiceTransactionV2Processor NO completed payment transaction nor refund transaction found for booking '$booking->id'.");
}
}
if($transactionTypeBill){
$transaction_object = new TransactionObject(
$billNumber,
TransactionType::SUPPLIER_DELIVER,
$transactionTypeBill->issuer,
$transactionTypeBill->receiver,
$transactionTypeBill->recipient_bank_account_id,
$transactionTypeBill->payment_method,
$payable_amount,
$booking_amount,
$transactionTypeBill->currency_id,
$transactionTypeBill->original_currency_id,
$booking_currency_average_rate,
$total_tax,
$total_service_charge,
null,
ApprovalStatus::APPROVED
);
$supplier_deliver_order_transaction = $this->createsTransaction->execute($purchaseOrder->booking, $transaction_object);
// supply deliver order
$this->invoiceDocumentProcessor->execute($supplier_deliver_order_transaction, $purchaseOrder, $supplier, DocumentType::SUPPLIER_DELIVER_ORDER, null);
}
}
if($transaction){
$transaction_object = new TransactionObject(
$billNumber,
TransactionType::SUPPLIER_DELIVER,
$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
);
$supplier_deliver_order_transaction = $this->createsTransaction->execute($purchaseOrder->booking, $transaction_object);
//if(!$generateEInvoiceRefund){
$this->updatesBookingStatus->execute($booking, $bookingOriginalStatus);
//}
// supply deliver order
$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(!$generateEInvoiceRefund){
$this->updatesBookingStatus->execute($booking, $bookingOriginalStatus);
//}
// update perfex crm
// if(config('perfexcrm.is_enabled') == 'true'){
// CreatePerfexCRMInvoice::dispatch($invoice_transaction, $purchaseOrder, $supplier);
// }
}
}
@@ -86,6 +86,7 @@ class CreateSupplierTransactionProcessor
$original_amount_after_refund = $payment->original_amount - $totalRefund;
$this->updatesTransactionStatus->execute($payment, ApprovalStatus::COMPLETED);
$billNumber = $this->generatesTransactionBillNumber->execute('SPLR-');
$constant = SegmentConstant::where('reference', SegmentConstants::SERVICE_CHARGE)->where('detail->id', $supplier->id)->first();
@@ -29,5 +29,5 @@ final class ApprovalStatus {
self::SUSPENDED => "Suspended",
self::EXPIRED => "Expired",
self::REFUNDED => "Refunded",
];
];
}
+7 -9
View File
@@ -58,15 +58,13 @@ class BookingResource extends JsonResource
'convertible_currency' => new CurrencyResource($this->convertibleCurrency),
'conversion_currency' => new CurrencyResource($this->conversionCurrency),
'documents' => [
'purchase_order' => new DocumentResource($this->documents()->where('document_type', DocumentType::PURCHASE_ORDER)->first()),
'delivery_order' => new DocumentResource($this->documents()->where('document_type', DocumentType::DELIVER_ORDER)->first()),
'invoice' => new DocumentResource($this->documents()->where('document_type', DocumentType::INVOICE)->first()),
'purchase_order' => new DocumentResource($this->documents()->where('document_type', DocumentType::PURCHASE_ORDER)->latest()->first()),
'delivery_order' => new DocumentResource($this->documents()->where('document_type', DocumentType::DELIVER_ORDER)->latest()->first()),
'invoice' => new DocumentResource($this->documents()->where('document_type', DocumentType::INVOICE)->latest()->first()),
'e_invoice' => new DocumentResource($this->documents()->where('document_type', DocumentType::EINVOICE)->latest()->first()),
'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()),
'supplier_delivery_order' => new DocumentResource($this->documents()->where('document_type', DocumentType::SUPPLIER_DELIVER_ORDER)->latest()->first()),
'proforma_invoice' => new DocumentResource($this->documents()->where('document_type', DocumentType::PROFORMA_INVOICE)->whereNotIn('status', [ApprovalStatus::REJECTED, ApprovalStatus::EXPIRED])->latest()->first()),
'ecommerce_purchase_order' => new DocumentResource($this->documents()->where('document_type', DocumentType::ECOMMERCE_PURCHASE_ORDER)->latest()->first()),
],
'order_reference_no' => $this->modelAttributes()->where('name', BookingAttributeNames::ORDER_REFERENCE_NO)->get()->map(function ($attr) {
return [
@@ -100,7 +98,7 @@ class BookingResource extends JsonResource
})->latest()->get())
]),
'einvoice' => $eInvoice,
'is_invoice_generated' => $this->is_invoice_generated,
'invoice_status' => $this->invoice_status,
];
}
}
@@ -0,0 +1,37 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddInvoiceStatusToBookingsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('bookings', function (Blueprint $table) {
$table->unsignedTinyInteger('invoice_status')
->default(0)
->after('status');
$table->index('invoice_status', 'bookings_invoice_status_index');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('bookings', function (Blueprint $table) {
$table->dropIndex('bookings_invoice_status_index');
$table->dropColumn('invoice_status');
});
}
}
@@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddInvoiceStatusToBookingLogsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('booking_logs', function (Blueprint $table) {
$table->boolean('invoice_status')
->default(false)
->after('status');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('booking_logs', function (Blueprint $table) {
$table->dropColumn('invoice_status');
});
}
}
+7 -2
View File
@@ -679,8 +679,13 @@ class DummyDataSeeder extends Seeder
// once the invoice is generated the transaction table will include 2 new transaction type TransactionType::INVOICE, TransactionType::SUPPLIER_DELIVERY
// and for documents will be generated and attached to the booking.
// once this process is complete the booking status will update to ApprovalStatus::COMPLETED
$this->createInvoiceTransactionProcessor->execute($booking);
$this->createInvoiceTransactionProcessor->execute($booking, "", null, [
'generateEInvoice' => false,
'generateEInvoiceWithNormalInvoiceTemplate' => false,
'generateEInvoiceRefund' => false,
'bookingOriginalStatus' => ApprovalStatus::COMPLETED
]
);
}
}
@@ -21,7 +21,7 @@
<div class="col-md col-sm-12 m-b-20">
<div class="row" v-if="booking">
<div class="col" v-if="showDownloadPDFButtons">
<div class="row m-b-50" v-if="(booking.status === 3 || booking.is_invoice_generated) || isBookingWithAFullRefund">
<div class="row m-b-50" v-if="(booking.status === 3 || booking.invoice_status === 2) || isBookingWithAFullRefund">
<div class="col no-padding">
<div class="row">
<div class="col">