diff --git a/app/Classes/Jobs/Commands/V2/CreateInvoiceTransactionV2CommandJob.php b/app/Classes/Jobs/Commands/V2/CreateInvoiceTransactionV2CommandJob.php
new file mode 100644
index 00000000..08576f16
--- /dev/null
+++ b/app/Classes/Jobs/Commands/V2/CreateInvoiceTransactionV2CommandJob.php
@@ -0,0 +1,42 @@
+booking = $booking;
+ }
+
+ public function handle()
+ {
+ Log::info(Carbon::now() . ': Start job - Creating invoice for single booking.');
+ $start = new Carbon();
+
+ (App()->make(CreateInvoiceTransactionV2Processor::class))->execute($this->booking);
+
+ $end = new Carbon();
+ $elapsedTime = $start->diff($end)->format('%H:%I:%S');
+ Log::info(Carbon::now() . ': End job - Creating invoice for single booking. ElapsedTime: ' . $elapsedTime . '.');
+ }
+
+}
diff --git a/app/Classes/Modules/Billplzs/ControllersLogic/CallbackBillplzLogic.php b/app/Classes/Modules/Billplzs/ControllersLogic/CallbackBillplzLogic.php
index b6537420..42726384 100644
--- a/app/Classes/Modules/Billplzs/ControllersLogic/CallbackBillplzLogic.php
+++ b/app/Classes/Modules/Billplzs/ControllersLogic/CallbackBillplzLogic.php
@@ -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);
// }
diff --git a/app/Classes/Modules/Bookings/ControllersLogic/ApprovePurchaseOrderLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/ApprovePurchaseOrderLogic.php
index 7422d6ca..3360946a 100644
--- a/app/Classes/Modules/Bookings/ControllersLogic/ApprovePurchaseOrderLogic.php
+++ b/app/Classes/Modules/Bookings/ControllersLogic/ApprovePurchaseOrderLogic.php
@@ -67,7 +67,13 @@ class ApprovePurchaseOrderLogic extends AbstractControllerLogic
$this->updatesTransactionStatus->execute($purchaseOrder, ApprovalStatus::APPROVED);
- $this->createInvoiceTransactionProcessor->execute($booking);
+ $this->createInvoiceTransactionProcessor->execute($booking, "", null, [
+ 'generateEInvoice' => false,
+ 'generateEInvoiceWithNormalInvoiceTemplate' => false,
+ 'generateEInvoiceRefund' => false,
+ 'bookingOriginalStatus' => $booking->status
+ ]
+ );
return $this->response([]);
}
diff --git a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingPaymentLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingPaymentLogic.php
index f67fa669..e8c31bae 100644
--- a/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingPaymentLogic.php
+++ b/app/Classes/Modules/Bookings/ControllersLogic/CreateBookingPaymentLogic.php
@@ -5,6 +5,7 @@ namespace App\Classes\Modules\Bookings\ControllersLogic;
use App\Classes\Exceptions\CriteriaNotFulfilledException;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\General\Abstracts\AbstractControllerLogic;
+use App\Classes\Jobs\Commands\V2\CreateInvoiceTransactionV2CommandJob;
use App\Classes\Modules\Bookings\Services\CalculatesBookingOutstanding;
use App\Classes\Modules\Bookings\Services\FetchesBookingQuotation;
use App\Classes\Modules\Companies\Services\FetchesCompanyPaymentAttemptLimit;
@@ -238,6 +239,10 @@ class CreateBookingPaymentLogic extends AbstractControllerLogic
$this->createReceiptVoucherTransactionProcessor->execute($booking, $transaction);
}
+ if($booking){
+ CreateInvoiceTransactionV2CommandJob::dispatch($booking);
+ }
+
return $this->resourceResponse(new TransactionResource($transaction));
}
diff --git a/app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingAmountLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingAmountLogic.php
index fd4af7f8..73985848 100644
--- a/app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingAmountLogic.php
+++ b/app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingAmountLogic.php
@@ -2,25 +2,24 @@
namespace App\Classes\Modules\Bookings\ControllersLogic;
+use App\Classes\Exceptions\MalformedRequestException;
+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\Bookings\Services\CalculatesBookingOutstanding;
-
-use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
-use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
class UpdateBookingAmountLogic extends AbstractControllerLogic
@@ -52,6 +51,12 @@ class UpdateBookingAmountLogic extends AbstractControllerLogic
/** @var UpdatesTransactionStatus */
private $updatesTransactionStatus;
+ /** @var UpdatesBookingInvoiceStatus */
+ private $updatesBookingInvoiceStatus;
+
+ /** @var CreateInvoiceTransactionV2Processor */
+ private $createInvoiceTransactionProcessor;
+
/**
* UpdateBookingAmountLogic constructor.
* @param CanUpdateBooking $canUpdateBooking
@@ -59,14 +64,18 @@ class UpdateBookingAmountLogic extends AbstractControllerLogic
* @param FetchesBooking $fetchesBooking
* @param CalculatesBookingOutstanding $calculatesBookingOutstanding
* @param UpdatesTransactionStatus $updatesTransactionStatus
+ * @param UpdatesBookingInvoiceStatus $updatesBookingInvoiceStatus
+ * @param CreateInvoiceTransactionV2Processor $createInvoiceTransactionProcessor
*/
- public function __construct(CanUpdateBooking $canUpdateBooking, UpdatesBookingFixedAmount $updatesBookingFixedAmount, FetchesBooking $fetchesBooking, CalculatesBookingOutstanding $calculatesBookingOutstanding, UpdatesTransactionStatus $updatesTransactionStatus)
+ public function __construct(CanUpdateBooking $canUpdateBooking, UpdatesBookingFixedAmount $updatesBookingFixedAmount, FetchesBooking $fetchesBooking, CalculatesBookingOutstanding $calculatesBookingOutstanding, UpdatesTransactionStatus $updatesTransactionStatus, UpdatesBookingInvoiceStatus $updatesBookingInvoiceStatus, CreateInvoiceTransactionV2Processor $createInvoiceTransactionProcessor)
{
$this->canUpdateBooking = $canUpdateBooking;
$this->updatesBookingFixedAmount = $updatesBookingFixedAmount;
$this->fetchesBooking = $fetchesBooking;
$this->calculatesBookingOutstanding = $calculatesBookingOutstanding;
$this->updatesTransactionStatus = $updatesTransactionStatus;
+ $this->updatesBookingInvoiceStatus = $updatesBookingInvoiceStatus;
+ $this->createInvoiceTransactionProcessor = $createInvoiceTransactionProcessor;
}
/**
@@ -81,7 +90,7 @@ class UpdateBookingAmountLogic extends AbstractControllerLogic
$input_amount = number_format( floatval(str_replace(',', '', $request->input('fix_amount', $booking->fix_amount))), 5, '.', '');
$minimum_amount = $booking->fix_amount - $this->calculatesBookingOutstanding->execute($booking);
-
+
if (((float)$input_amount + 0.01) < (float)$minimum_amount) {
$input_amount = 0;
// throw new MalformedRequestException('Booking Amount cannot be less than '. $minimum_amount .'.');
@@ -97,7 +106,15 @@ 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));
}
-}
\ No newline at end of file
+}
diff --git a/app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingAmountOnHoldLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingAmountOnHoldLogic.php
index 39dc6674..3588909f 100644
--- a/app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingAmountOnHoldLogic.php
+++ b/app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingAmountOnHoldLogic.php
@@ -14,6 +14,7 @@ use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Accounts\DataTransferObjects\KeyValuePairObject;
+use App\Classes\ValueObjects\Constants\KVPKey;
use App\Http\Resources\BookingResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -90,9 +91,8 @@ class UpdateBookingAmountOnHoldLogic extends AbstractControllerLogic
throw new MalformedRequestException('Booking Amount cannot be less than '. $minimum_amount .'.');
}
- $key = "BOOKING_AMOUNT_UPDATE";
- $keyValuePairObject = new KeyValuePairObject($key, $input_amount);
- $metadata = $booking->attributesKVP()->where('key', $key)->first();
+ $keyValuePairObject = new KeyValuePairObject(KVPKey::BOOKING_AMOUNT_UPDATE, $input_amount);
+ $metadata = $booking->attributesKVP()->where('key', KVPKey::BOOKING_AMOUNT_UPDATE)->first();
if($metadata){
$this->updatesKeyValuePair->execute($metadata, $keyValuePairObject);
}
diff --git a/app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingAmountWithPOLogic.php b/app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingAmountWithPOLogic.php
index 4def81f7..48cc7d94 100644
--- a/app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingAmountWithPOLogic.php
+++ b/app/Classes/Modules/Bookings/ControllersLogic/UpdateBookingAmountWithPOLogic.php
@@ -10,6 +10,11 @@ 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\KVPKey;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Http\Resources\BookingResource;
use App\Models\Booking;
@@ -45,6 +50,12 @@ class UpdateBookingAmountWithPOLogic extends AbstractControllerLogic
/** @var CalculatesBookingRefundAmount */
private $calculatesBookingRefundAmount;
+ /** @var UpdatesBookingInvoiceStatus */
+ private $updatesBookingInvoiceStatus;
+
+ /** @var CreateInvoiceTransactionV2Processor */
+ private $createInvoiceTransactionProcessor;
+
/**
* UpdateBookingAmountWithPOLogic constructor.
* @param FetchesBooking $fetchesBooking
@@ -52,14 +63,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;
}
/**
@@ -74,7 +89,7 @@ class UpdateBookingAmountWithPOLogic extends AbstractControllerLogic
/** @var Booking $booking */
$booking = $this->fetchesBooking->execute(['id' => $request->route('id') ?? $id]);
$outstandingAmount = $this->calculatesBookingOutstanding->execute($booking);
- $bookingAttribute = $booking->attributesKVP()->where('key', "BOOKING_AMOUNT_UPDATE")->first();
+ $bookingAttribute = $booking->attributesKVP()->where('key', KVPKey::BOOKING_AMOUNT_UPDATE)->first();
// cief todo: 90 - BEFORE REVERT
@@ -110,6 +125,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();
diff --git a/app/Classes/Modules/Bookings/DataTransferObjects/UpdateBookingInvoiceStatusObject.php b/app/Classes/Modules/Bookings/DataTransferObjects/UpdateBookingInvoiceStatusObject.php
new file mode 100644
index 00000000..6b04a695
--- /dev/null
+++ b/app/Classes/Modules/Bookings/DataTransferObjects/UpdateBookingInvoiceStatusObject.php
@@ -0,0 +1,42 @@
+id = $id;
+ $this->invoiceStatus = $invoiceStatus;
+ }
+
+ /**
+ * @return int
+ */
+ public function getId(): int
+ {
+ return $this->id;
+ }
+
+ /**
+ * @return int
+ */
+ public function getInvoiceStatus(): int
+ {
+ return $this->invoiceStatus;
+ }
+}
diff --git a/app/Classes/Modules/Bookings/Processors/CreatePurchaseOrderFor1688OrderProcessor.php b/app/Classes/Modules/Bookings/Processors/CreatePurchaseOrderFor1688OrderProcessor.php
index 8a24a5ab..83b25386 100644
--- a/app/Classes/Modules/Bookings/Processors/CreatePurchaseOrderFor1688OrderProcessor.php
+++ b/app/Classes/Modules/Bookings/Processors/CreatePurchaseOrderFor1688OrderProcessor.php
@@ -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
+ ]
+ );
}
}
diff --git a/app/Classes/Modules/Bookings/Services/UpdatesBookingInvoiceStatus.php b/app/Classes/Modules/Bookings/Services/UpdatesBookingInvoiceStatus.php
new file mode 100644
index 00000000..97342170
--- /dev/null
+++ b/app/Classes/Modules/Bookings/Services/UpdatesBookingInvoiceStatus.php
@@ -0,0 +1,23 @@
+invoice_status = $object->getInvoiceStatus();
+ return $this->handler($model);
+ }
+}
diff --git a/app/Classes/Modules/Companies/ControllersLogic/FetchCompanyEInvoiceInfoLogic.php b/app/Classes/Modules/Companies/ControllersLogic/FetchCompanyEInvoiceInfoLogic.php
index ebb2d275..2d886967 100644
--- a/app/Classes/Modules/Companies/ControllersLogic/FetchCompanyEInvoiceInfoLogic.php
+++ b/app/Classes/Modules/Companies/ControllersLogic/FetchCompanyEInvoiceInfoLogic.php
@@ -58,6 +58,7 @@ class FetchCompanyEInvoiceInfoLogic extends AbstractControllerLogic
$eInvoiceInfo->tin = $company->tin;
$eInvoiceInfo->msic_code = $company->msic_code;
$eInvoiceInfo->e_invoice = $company->e_invoice;
+ $eInvoiceInfo->e_invoice_requested_at = $company->e_invoice_requested_at;
}
else{
return $this->response([]);
diff --git a/app/Classes/Modules/Exports/Services/ExportsSalesInvoiceReport.php b/app/Classes/Modules/Exports/Services/ExportsSalesInvoiceReport.php
index 3142441b..a7c170b7 100644
--- a/app/Classes/Modules/Exports/Services/ExportsSalesInvoiceReport.php
+++ b/app/Classes/Modules/Exports/Services/ExportsSalesInvoiceReport.php
@@ -2,6 +2,7 @@
namespace App\Classes\Modules\Exports\Services;
+use App\Classes\Jobs\Commands\V2\CreateInvoiceTransactionV2CommandJob;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Models\Booking;
@@ -71,7 +72,8 @@ class ExportsSalesInvoiceReport implements FromQuery, WithHeadings, WithHeadingR
'transactions.voucherRedemption',
'transactions.voucherRedemption.voucher.campaign'
])
- ->where('status', ApprovalStatus::COMPLETED)
+ // ->whereIn('status', [ApprovalStatus::COMPLETED])
+ ->whereIn('invoice_status', [ApprovalStatus::APPROVED])
->whereHas('transactions', function ($query) use ($startDate, $endDate) {
$query->payments()
->complete()
@@ -115,6 +117,11 @@ class ExportsSalesInvoiceReport implements FromQuery, WithHeadings, WithHeadingR
}
$invoiceTransaction = $booking->transactions->where('type', TransactionType::INVOICE)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->first();
+ if(!$invoiceTransaction){
+ Log::info('ExportsSalesInvoiceReport booking with NO invoice: ' . json_encode($booking));
+ // CreateInvoiceTransactionV2CommandJob::dispatch($booking);
+ return $records;
+ }
$currencyId = $booking->fix_currency_id;
diff --git a/app/Classes/Modules/Rules/ControllersLogic/CheckEInvoiceAmountLimitLogic.php b/app/Classes/Modules/Rules/ControllersLogic/CheckEInvoiceAmountLimitLogic.php
new file mode 100644
index 00000000..bc9f18ae
--- /dev/null
+++ b/app/Classes/Modules/Rules/ControllersLogic/CheckEInvoiceAmountLimitLogic.php
@@ -0,0 +1,67 @@
+ 'Rule Check E-Invoice Amount Limit',
+ 'message' => 'You have successfully passed all rules evaluated'
+ ];
+ }
+
+ /** @var RuleEvaluator */
+ private $ruleEvaluator;
+
+
+ /** @var CanPassMustEInvoiceAmountLimitRule */
+ private $canPassMustEInvoiceAmountLimitRule;
+
+ /**
+ * CheckEInvoiceAmountLimitLogic constructor.
+ * @param RuleEvaluator $ruleEvaluator
+ * @param CanPassMustEInvoiceAmountLimitRule $canPassMustEInvoiceAmountLimitRule
+ */
+ public function __construct(RuleEvaluator $ruleEvaluator, CanPassMustEInvoiceAmountLimitRule $canPassMustEInvoiceAmountLimitRule)
+ {
+ $this->ruleEvaluator = $ruleEvaluator;
+ $this->canPassMustEInvoiceAmountLimitRule = $canPassMustEInvoiceAmountLimitRule;
+ }
+
+ /**
+ * @param Request $request
+ * @return JsonResponse
+ * @throws \App\Classes\Exceptions\AccessForbiddenException
+ * @throws \App\Classes\Exceptions\MalformedRequestException
+ * @throws \App\Classes\Exceptions\RequestValidationException
+ * @throws \App\Classes\Exceptions\CriteriaNotFulfilledException
+ */
+ public function logic(Request $request) : JsonResponse
+ {
+ $dto = new CheckEInvoiceAmountLimitRuleDTO($request->all());
+
+ $result = $this->ruleEvaluator->evaluate([
+ $this->canPassMustEInvoiceAmountLimitRule
+ ], $dto);
+
+ if ($result->failed()) {
+ throw new CriteriaNotFulfilledException("- " . implode("
- ", $result->messages()));
+ }
+
+ return $this->resourceResponse(new RuleResource((object)$result));
+ }
+}
diff --git a/app/Classes/Modules/Rules/DataTransferObjects/CheckEInvoiceAmountLimitRuleDTO.php b/app/Classes/Modules/Rules/DataTransferObjects/CheckEInvoiceAmountLimitRuleDTO.php
new file mode 100644
index 00000000..b28e78f1
--- /dev/null
+++ b/app/Classes/Modules/Rules/DataTransferObjects/CheckEInvoiceAmountLimitRuleDTO.php
@@ -0,0 +1,36 @@
+bookingId = $data['booking_id'];
+ $this->companyId = $data['company_id'];
+
+ $this->amount = $data['amount'] ?? null;
+ $this->paymentMethod = $data['payment_method'] ?? null;
+ $this->voucherCode = $data['voucherCode'] ?? null;
+ }
+
+ public function toArray(): array
+ {
+ return [
+ 'booking_id' => $this->bookingId,
+ 'company_id' => $this->companyId,
+ 'amount' => $this->amount,
+ 'payment_method' => $this->paymentMethod,
+ 'voucher_code' => $this->voucherCode,
+ ];
+ }
+}
diff --git a/app/Classes/Modules/Rules/Standards/Rules/CanPassMustEInvoiceAmountLimitRule.php b/app/Classes/Modules/Rules/Standards/Rules/CanPassMustEInvoiceAmountLimitRule.php
new file mode 100644
index 00000000..d077aab7
--- /dev/null
+++ b/app/Classes/Modules/Rules/Standards/Rules/CanPassMustEInvoiceAmountLimitRule.php
@@ -0,0 +1,102 @@
+fetchesBooking = $fetchesBooking;
+ $this->fetchesBookingQuotation = $fetchesBookingQuotation;
+ $this->calculatesBookingOutstanding = $calculatesBookingOutstanding;
+ }
+
+ /**
+ * @return bool
+ */
+ protected function authorized($object): bool
+ {
+ return true;
+
+ }
+
+ /**
+ * @return bool
+ */
+ protected function validators($object): bool
+ {
+ return true;
+
+ }
+
+
+ /**
+ * @return bool
+ */
+ protected function criteria($object): bool
+ {
+ //Check if booking amount is RM10,000 or more, than must opt-in E-Invoice
+ $booking = $this->fetchesBooking->execute(['id' => $object->bookingId]);
+ $company = $booking->company;
+
+ // $totalPayments = 0;
+
+ // if(isset($object->amount)){
+ // $totalPayments = $booking->transactions()->payments()->whereIn('transactions.status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->sum('amount');
+
+ // $conversionObject = new CurrencyConversionObject(floatval(str_replace(',', '', floatval(str_replace(',', '', $object->amount)))), $booking->convertible_currency_id, $booking->service_id, $booking->fix_currency_id === 1 ? 0:1, PaymentMethodType::PAYMENT_METHODS[$object->paymentMethod]);
+ // $voucherCode = $object->voucherCode ?? null;
+ // $configurations = $this->fetchesBookingQuotation->execute($booking->company, $conversionObject, $voucherCode, null, $booking);
+ // }
+ // else{
+ // $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);
+ // }
+
+ // $bookingAmountInMYR = $configurations->getTotal();
+ // $bookingAmountInMYR = $bookingAmountInMYR + $totalPayments;
+
+ // if($bookingAmountInMYR >= 10000 && (!$company->e_invoice || !$company->tin) ){
+ // throw new CriteriaNotFulfilledException("RM10,000 and above must opt-in for E-Invoice.");
+ // }
+
+ //1 MYR, 2 CNY, 3 USD
+ if((($booking->fix_amount >= 9000 && $booking->fix_currency_id === 1) ||
+ ($booking->fix_amount >= 12600 && $booking->fix_currency_id === 2) ||
+ ($booking->fix_amount >= 1920 && $booking->fix_currency_id === 3))
+ && (!$company->e_invoice || !$company->tin) ){
+ throw new CriteriaNotFulfilledException("Booking amount above limit, must opt-in for E-Invoice.");
+ }
+
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/app/Classes/Modules/Transactions/ControllersLogic/CreatePaymentProofDocumentLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/CreatePaymentProofDocumentLogic.php
index fdaf5e75..a1d12768 100644
--- a/app/Classes/Modules/Transactions/ControllersLogic/CreatePaymentProofDocumentLogic.php
+++ b/app/Classes/Modules/Transactions/ControllersLogic/CreatePaymentProofDocumentLogic.php
@@ -90,7 +90,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
+ ]
+ );
// send email to customer
// todo: a function to send a proof to the receipiant, they have to give us a email of the receipiant and also need to submiited purchase order
diff --git a/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionV2Processor.php b/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionV2Processor.php
index 5684ba18..230296e4 100644
--- a/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionV2Processor.php
+++ b/app/Classes/Modules/Transactions/Processors/CreateInvoiceTransactionV2Processor.php
@@ -104,14 +104,20 @@ 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($generateEInvoiceRefund){
$generateEInvoice = true; //With or without refund, these 2 flags are meant to Generate E-Invoice, so cannot have opposite indicator
}
- if ($booking->status === ApprovalStatus::COMPLETED && !$generateEInvoice) {
- return;
+ if ($booking->status === ApprovalStatus::COMPLETED && !$generateEInvoiceRefund) {
+ Log::info('CreateInvoiceTransactionV2Processor Check 1 Bypass New Business Logic Update for booking ' . $booking->id);
+ // return;
}
$payable_amount = $this->calculatesBookingPayableAmount->execute($booking, $booking->fix_currency_id, $generateEInvoiceRefund);
@@ -128,31 +134,27 @@ class CreateInvoiceTransactionV2Processor
}
// confirm that all payments has been transferred
if ($this->calculatesBookingTransferredAmount->execute($booking) !== $this->calculatesBookingPaidAmount->execute($booking)) {
- return;
+ Log::info('CreateInvoiceTransactionV2Processor Check 2 Bypass New Business Logic Update for booking ' . $booking->id);
+ // return;
}
- if($generateEInvoiceRefund){
+ $purchaseOrder = $booking->transactions()
+ ->where('type', TransactionType::PURCHASE_ORDER)
+ ->complete()
+ ->first();
+
+ if(!$purchaseOrder){
+ //was use for $generateEInvoiceRefund true
$purchaseOrder = $booking->transactions()
->where('type', TransactionType::PURCHASE_ORDER)
->where('status', ApprovalStatus::PENDING_SUBMISSION)
->first();
}
- else{
- $purchaseOrder = $booking->transactions()
- ->where('type', TransactionType::PURCHASE_ORDER)
- ->complete()
- ->first();
- }
$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)
@@ -163,7 +165,8 @@ class CreateInvoiceTransactionV2Processor
$eInvoice = false;
$eInvoiceStartDate = Carbon::parse(env('E_INVOICE_START_DATE', '2025-07-01 00:00:00'));
$bookingCreatedDate = Carbon::parse($booking->created_at);
- if ($bookingCreatedDate->isAfter($eInvoiceStartDate) && $supplier->e_invoice === 1) {
+ $eInvoiceRequestedDate = Carbon::parse($supplier->e_invoice_requested_at);
+ if ($bookingCreatedDate->isAfter($eInvoiceStartDate) && $bookingCreatedDate->isAfter($eInvoiceRequestedDate) && $supplier->e_invoice === 1) {
$eInvoice = true;
}
$kvp = $booking->attributesKVP()->where('key', KVPKey::BOOKING_EINVOICE_ELIGIBLE)->first();
@@ -211,84 +214,20 @@ class CreateInvoiceTransactionV2Processor
->sum('tax');
}
-
-
- $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 ($kvpCopies) {
- foreach ($kvpCopies as $kvp) {
- $invoice_transaction->attributesKVP()->save($kvp);
- }
+ $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();
}
- $voucherRedemption = $transaction->voucherRedemption;
-
- // 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);
- }
- }
- // 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();
- }
- else{ // Special handling for refund cases (When a refund is deleted via DeleteRefundTransactionLogic, a booking payment transaction is set to ApprovalStatus::APPROVED)
- $temp = $booking->transactions()->payments()->where('status', ApprovalStatus::APPROVED)->first();
- // Lets check if there is a refund case
- $refund = $temp->transactions()->refunds()->where('status', ApprovalStatus::APPROVED)->first();
- if($refund){
- $transaction = $temp;
- }
- else{
- throw new Exception("No payment found for booking '$booking->id'.");
- }
- }
-
+ if(!$invoice_transaction) {
$transaction_object = new TransactionObject(
$billNumber,
- TransactionType::SUPPLIER_DELIVER,
+ TransactionType::INVOICE,
$transaction->issuer,
$transaction->receiver,
$transaction->recipient_bank_account_id,
@@ -303,19 +242,101 @@ class CreateInvoiceTransactionV2Processor
null,
ApprovalStatus::APPROVED
);
- $supplier_deliver_order_transaction = $this->createsTransaction->execute($purchaseOrder->booking, $transaction_object);
+ $invoice_transaction = $this->createsTransaction->execute($purchaseOrder->booking ?? $booking, $transaction_object);
+ }
- // supply deliver order
- $this->invoiceDocumentProcessor->execute($supplier_deliver_order_transaction, $purchaseOrder, $supplier, DocumentType::SUPPLIER_DELIVER_ORDER, null);
+ //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);
+ }
+ }
+
+ $voucherRedemption = $transaction->voucherRedemption;
+
+ if($purchaseOrder){
+ // 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);
+ }
+ }
+ // 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);
+ }
+ }
+
+ // 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);
- // }
}
}
diff --git a/app/Classes/Modules/Transactions/Processors/CreateSupplierTransactionProcessor.php b/app/Classes/Modules/Transactions/Processors/CreateSupplierTransactionProcessor.php
index b514b404..42a21d71 100644
--- a/app/Classes/Modules/Transactions/Processors/CreateSupplierTransactionProcessor.php
+++ b/app/Classes/Modules/Transactions/Processors/CreateSupplierTransactionProcessor.php
@@ -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();
diff --git a/app/Classes/ValueObjects/Constants/ApprovalStatus.php b/app/Classes/ValueObjects/Constants/ApprovalStatus.php
index ba7660d4..987dbc6a 100644
--- a/app/Classes/ValueObjects/Constants/ApprovalStatus.php
+++ b/app/Classes/ValueObjects/Constants/ApprovalStatus.php
@@ -29,5 +29,5 @@ final class ApprovalStatus {
self::SUSPENDED => "Suspended",
self::EXPIRED => "Expired",
self::REFUNDED => "Refunded",
- ];
+ ];
}
diff --git a/app/Classes/ValueObjects/Constants/KVPKey.php b/app/Classes/ValueObjects/Constants/KVPKey.php
index bc889729..958d1710 100644
--- a/app/Classes/ValueObjects/Constants/KVPKey.php
+++ b/app/Classes/ValueObjects/Constants/KVPKey.php
@@ -30,4 +30,7 @@ class KVPKey
public const CHATGPT_PROMPT_PREFIX = 'CHATGPT_PROMPT_';
public const CLAUDE_PROMPT_PREFIX = 'CLAUDE_PROMPT_';
+
+ public const BOOKING_AMOUNT_UPDATE = 'BOOKING_AMOUNT_UPDATE';
+
}
diff --git a/app/Console/Commands/V2/OneTimeProcessBookingForEInvoiceV2Command.php b/app/Console/Commands/V2/OneTimeProcessBookingForEInvoiceV2Command.php
new file mode 100644
index 00000000..c001f69b
--- /dev/null
+++ b/app/Console/Commands/V2/OneTimeProcessBookingForEInvoiceV2Command.php
@@ -0,0 +1,62 @@
+get();
+
+ $count = 0;
+ foreach ($bookings as $booking) {
+ ProcessBookingForEInvoiceV2CommandJob::dispatch($booking);
+ $count++;
+ Log::info('Processed: ' . $count);
+ Log::info('Booking ID: ' . $booking->marking . ' for E-Invoice ');
+ }
+ }
+}
diff --git a/app/Http/Controllers/Rules/CheckRuleController.php b/app/Http/Controllers/Rules/CheckRuleController.php
index 59b24cd0..b0a175c1 100644
--- a/app/Http/Controllers/Rules/CheckRuleController.php
+++ b/app/Http/Controllers/Rules/CheckRuleController.php
@@ -5,6 +5,7 @@ namespace App\Http\Controllers\Rules;
use App\Classes\Modules\Rules\ControllersLogic\CheckEInvoiceRuleLogic;
use App\Classes\Modules\Rules\ControllersLogic\CheckPurchaseOrderRuleLogic;
use App\Classes\Modules\Rules\ControllersLogic\CheckTransferRuleLogic;
+use App\Classes\Modules\Rules\ControllersLogic\CheckEInvoiceAmountLimitLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -36,4 +37,13 @@ class CheckRuleController
public function checkTransferRule(Request $request, CheckTransferRuleLogic $logic): JsonResponse {
return $logic->execute($request);
}
+
+ /**
+ * @param Request $request
+ * @param CheckEInvoiceAmountLimitLogic $logic
+ * @return JsonResponse
+ */
+ public function checkEInvoiceAmountLimitRule(Request $request, CheckEInvoiceAmountLimitLogic $logic): JsonResponse {
+ return $logic->execute($request);
+ }
}
diff --git a/app/Http/Resources/BookingResource.php b/app/Http/Resources/BookingResource.php
index fef78809..e118f2e9 100644
--- a/app/Http/Resources/BookingResource.php
+++ b/app/Http/Resources/BookingResource.php
@@ -13,6 +13,7 @@ use App\Classes\ValueObjects\Constants\DocumentType;
use App\Classes\ValueObjects\Constants\KVPKey;
use Carbon\Carbon;
use Illuminate\Http\Resources\Json\JsonResource;
+use Illuminate\Support\Facades\Log;
class BookingResource extends JsonResource
{
@@ -30,7 +31,7 @@ class BookingResource extends JsonResource
$bookingCreatedDate = Carbon::parse($this->created_at);
$eInvoiceRequestedDate = Carbon::parse($this->company->e_invoice_requested_at);
//cief todo: 90 - for testing
- if ($bookingCreatedDate->isAfter($eInvoiceStartDate) && $this->company->e_invoice === 1) { //&& $bookingCreatedDate->diffInMinutes($eInvoiceRequestedDate) <= 480 cief todo: 90
+ if ($bookingCreatedDate->isAfter($eInvoiceStartDate) && $bookingCreatedDate->isAfter($eInvoiceRequestedDate) && $this->company->e_invoice === 1) { //&& $bookingCreatedDate->diffInMinutes($eInvoiceRequestedDate) <= 480 cief todo: 90
$eInvoice = true;
}
@@ -58,15 +59,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,6 +99,7 @@ class BookingResource extends JsonResource
})->latest()->get())
]),
'einvoice' => $eInvoice,
+ 'invoice_status' => $this->invoice_status,
];
}
}
diff --git a/app/Http/Resources/EInvoiceInfoResource.php b/app/Http/Resources/EInvoiceInfoResource.php
index 97483dd3..a4126eef 100644
--- a/app/Http/Resources/EInvoiceInfoResource.php
+++ b/app/Http/Resources/EInvoiceInfoResource.php
@@ -2,6 +2,7 @@
namespace App\Http\Resources;
+use Carbon\Carbon;
use Illuminate\Http\Resources\Json\JsonResource;
class EInvoiceInfoResource extends JsonResource
@@ -26,6 +27,7 @@ class EInvoiceInfoResource extends JsonResource
'msic_code' => (string) $this->msic_code,
'tin' => (string) $this->tin,
'e_invoice' => (int) $this->e_invoice,
+ 'e_invoice_requested_date' => $this->e_invoice_requested_at ? Carbon::parse($this->e_invoice_requested_at)->format('d-m-Y') : null,
];
}
}
diff --git a/database/migrations/2025_11_27_120102_add_invoice_status_to_bookings_table.php b/database/migrations/2025_11_27_120102_add_invoice_status_to_bookings_table.php
new file mode 100644
index 00000000..124800b4
--- /dev/null
+++ b/database/migrations/2025_11_27_120102_add_invoice_status_to_bookings_table.php
@@ -0,0 +1,37 @@
+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');
+ });
+ }
+}
diff --git a/database/migrations/2025_11_27_120102_add_is_invoice_generated_to_bookings_table.php b/database/migrations/2025_11_27_120102_add_is_invoice_generated_to_bookings_table.php
new file mode 100644
index 00000000..b2af1a22
--- /dev/null
+++ b/database/migrations/2025_11_27_120102_add_is_invoice_generated_to_bookings_table.php
@@ -0,0 +1,37 @@
+boolean('is_invoice_generated')
+ ->default(false)
+ ->after('status');
+
+ $table->index('is_invoice_generated', 'bookings_is_invoice_generated_index');
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::table('bookings', function (Blueprint $table) {
+ $table->dropIndex('bookings_is_invoice_generated_index');
+ $table->dropColumn('is_invoice_generated');
+ });
+ }
+}
diff --git a/database/migrations/2025_11_27_121256_add_invoice_status_to_booking_logs_table.php b/database/migrations/2025_11_27_121256_add_invoice_status_to_booking_logs_table.php
new file mode 100644
index 00000000..d0b21f09
--- /dev/null
+++ b/database/migrations/2025_11_27_121256_add_invoice_status_to_booking_logs_table.php
@@ -0,0 +1,34 @@
+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');
+ });
+ }
+}
diff --git a/database/migrations/2025_11_27_121256_add_is_invoice_generated_to_booking_logs_table.php b/database/migrations/2025_11_27_121256_add_is_invoice_generated_to_booking_logs_table.php
new file mode 100644
index 00000000..e04b01d0
--- /dev/null
+++ b/database/migrations/2025_11_27_121256_add_is_invoice_generated_to_booking_logs_table.php
@@ -0,0 +1,34 @@
+boolean('is_invoice_generated')
+ ->default(false)
+ ->after('status');
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::table('booking_logs', function (Blueprint $table) {
+ $table->dropColumn('is_invoice_generated');
+ });
+ }
+}
diff --git a/database/seeds/DummyDataSeeder.php b/database/seeds/DummyDataSeeder.php
index a752ee6f..328dcc15 100644
--- a/database/seeds/DummyDataSeeder.php
+++ b/database/seeds/DummyDataSeeder.php
@@ -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
+ ]
+ );
}
}
diff --git a/resources/assets/vue/components/accounts/forms/RegistrationFormComponent.vue b/resources/assets/vue/components/accounts/forms/RegistrationFormComponent.vue
index d6f05b1b..a046a7eb 100644
--- a/resources/assets/vue/components/accounts/forms/RegistrationFormComponent.vue
+++ b/resources/assets/vue/components/accounts/forms/RegistrationFormComponent.vue
@@ -169,6 +169,7 @@
+<
diff --git a/resources/assets/vue/components/bookings/forms/confirmBookingComponent.vue b/resources/assets/vue/components/bookings/forms/confirmBookingComponent.vue
index d0a92e59..6fc7e203 100644
--- a/resources/assets/vue/components/bookings/forms/confirmBookingComponent.vue
+++ b/resources/assets/vue/components/bookings/forms/confirmBookingComponent.vue
@@ -11,6 +11,7 @@
+ @endif
+@endpush
\ No newline at end of file
diff --git a/routes/rule.php b/routes/rule.php
index d5330176..4918b4d0 100644
--- a/routes/rule.php
+++ b/routes/rule.php
@@ -9,4 +9,5 @@ Route::prefix('rule')
Route::post('/check/eInvoice', [CheckRuleController::class, 'checkEInvoiceRule'])->name('check.einvoice');
Route::post('/check/purchase-order', [CheckRuleController::class, 'checkPurchaseOrderRule'])->name('check.purchase.order');
Route::post('/check/tranfer', [CheckRuleController::class, 'checkTransferRule'])->name('check.transfer');
+ Route::post('/check/e-invoice/amount-limit', [CheckRuleController::class, 'checkEInvoiceAmountLimitRule'])->name('check.einvoice.amount-limit');
});