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..201bad8b --- /dev/null +++ b/app/Classes/Modules/Rules/Standards/Rules/CanPassMustEInvoiceAmountLimitRule.php @@ -0,0 +1,87 @@ +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; + + if(isset($object->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(); + + if($bookingAmountInMYR >= 10000 && (!$company->e_invoice || !$company->tin) ){ + throw new CriteriaNotFulfilledException("RM10,000 and above must opt-in for E-Invoice."); + } + return true; + } +} 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/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationV2Component.vue b/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationV2Component.vue index 7dd9adc0..363a6d1f 100644 --- a/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationV2Component.vue +++ b/resources/assets/vue/components/bookings/forms/BookingPaymentQuotationV2Component.vue @@ -162,29 +162,6 @@ - - - - - - - @@ -622,7 +599,7 @@ + @click.prevent="checkEInvoiceAmountLimitRule">Lock Booking @@ -630,6 +607,31 @@ + + + + + + + + + @@ -740,6 +742,9 @@ $('#confirm-booking-modal').modal('show'); } } + else if(section === this.section + 'CheckEInvoiceAmountLimitRule'){ + this.checkPurchaseOrderRule(); + } else if(section === this.section + 'ChangeOfMind'){ this.$store.dispatch('reloadList', {'name': "bookingDetailSection"}); } @@ -767,6 +772,14 @@ if(section === this.section + 'CheckEInvoiceRule' && statusCode === 422){ $('#modal-einvoice-info').modal('show'); } + else if(section === this.section + 'CheckEInvoiceAmountLimitRule' && statusCode === 422){ + if(!this.data.company.e_invoice){ + $('#modal-einvoice-request').modal('show'); + } + else if(!this.data.company.tin){ + $('#modal-einvoice-info').modal('show'); + } + } this.error = error.message; }, makePayment(){ //E-Invoice @@ -837,6 +850,17 @@ }; this.submit(route('api.rule.check.einvoice'), 'post', this.section + 'CheckEInvoiceRule', false, true); }, + checkEInvoiceAmountLimitRule(){ + this.error = ''; + this.parameters = { + booking_id: this.data.id, + company_id: this.data.company.id, + payment_method: this.paymentMethod.id, + voucherCode: this.voucherCode, + amount: this.amount + }; + this.submit(route('api.rule.check.einvoice.amount-limit'), 'post', this.section + 'CheckEInvoiceAmountLimitRule', false, true); + }, checkPurchaseOrderRule(){ this.error = ''; this.parameters = { diff --git a/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue b/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue index a96af8fc..2f546bd4 100644 --- a/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue +++ b/resources/assets/vue/components/bookings/forms/PurchaseOrderFormComponent.vue @@ -432,6 +432,9 @@ this.checkEInvoiceRule(); } else if(section === this.section + 'CheckEInvoiceRule'){ + this.checkEInvoiceAmountLimitRule(); + } + else if(section === this.section + 'CheckEInvoiceAmountLimitRule'){ if(response.payload.data.isPassed){ if(this.data.service.id === 14 || this.data.service.id === 15 || this.data.service.id === 16 || this.data.service.id === 17 || this.data.service.id === 18 || this.data.service.id === 19){ this.submit(route('api.booking.banking.create', this.data.id), 'post', this.section, true, true); @@ -452,6 +455,14 @@ if(section === this.section + 'CheckEInvoiceRule' && statusCode === 422){ $('#modal-einvoice-info').modal('show'); } + else if(section === this.section + 'CheckEInvoiceAmountLimitRule' && statusCode === 422){ + if(!this.data.company.e_invoice){ + $('#modal-einvoice-request').modal('show'); + } + else if(!this.data.company.tin){ + $('#modal-einvoice-info').modal('show'); + } + } }, addProduct(){ this.products.push({ @@ -518,6 +529,14 @@ }; this.submit(route('api.rule.check.einvoice'), 'post', this.section + 'CheckEInvoiceRule', false, true); }, + checkEInvoiceAmountLimitRule(){ + this.error = ''; + this.parameters = { + booking_id: this.data.id, + company_id: this.data.company.id, + }; + this.submit(route('api.rule.check.einvoice.amount-limit'), 'post', this.section + 'CheckEInvoiceAmountLimitRule', false, true); + }, updatedEInvoiceInfo(info){ this.$store.dispatch('reloadList', {'name': "bookingDetailSection"}); }, 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'); });