From 8559332d343083ea2683550b3e0ee12f978a7563 Mon Sep 17 00:00:00 2001
From: Dillon Ngo TIN {{parameters.tin}} MSIC Code {{parameters.msic_code}} Billing Address {{parameters.street_one}} {{parameters.street_two}}, {{districts[parseFloat(parameters.district_id) - 1].city}} {{parameters.post_code}} {{districts[parseFloat(parameters.district_id) - 1].state.name}}, {{districts[parseFloat(parameters.district_id) - 1].country.name}} TIN {{ eInvoiceData.tin }} MSIC Code {{ eInvoiceData.msic_code }} Billing Address {{ isEditRecipientBankDetailsCollapsed ? '< Back' : 'Change recipient bank details' }} {{ isEditRecipientBankDetailsCollapsed ? '< Back' : 'Show edited recipient bank details on payment' }} Online Banking Wallet Credit (Better Rate) Manual Transfer Cheque Maybank2u CimbClicks Maybank2E BizChannel change the payment method?
- ", $result->messages()));
+ }
+
$voucherCode = $request->input('voucher_code');
$booking = Booking::find($request->route('id'));
diff --git a/app/Classes/Modules/Companies/ControllersLogic/FetchCompanyEInvoiceInfoLogic.php b/app/Classes/Modules/Companies/ControllersLogic/FetchCompanyEInvoiceInfoLogic.php
new file mode 100644
index 00000000..ebb2d275
--- /dev/null
+++ b/app/Classes/Modules/Companies/ControllersLogic/FetchCompanyEInvoiceInfoLogic.php
@@ -0,0 +1,68 @@
+ 'Retrieved Company E-Invoice Info',
+ 'message' => 'You have successfully retrieved a Company E-Invoice Info'
+ ];
+ }
+
+ /** @var CanFetchCompany */
+ private $canFetchCompany;
+
+ /** @var FetchesCompany */
+ private $fetchesCompany;
+
+ /**
+ * FetchCompanyEInvoiceInfoLogic constructor.
+ * @param CanFetchCompany $canFetchCompany
+ * @param FetchesCompany $fetchesCompany
+ */
+ public function __construct(CanFetchCompany $canFetchCompany, FetchesCompany $fetchesCompany)
+ {
+ $this->canFetchCompany = $canFetchCompany;
+ $this->fetchesCompany = $fetchesCompany;
+ }
+
+
+ /**
+ * @param Request $request
+ * @return JsonResponse
+ * @throws \App\Classes\Exceptions\AccessForbiddenException
+ * @throws \App\Classes\Exceptions\RequestValidationException
+ */
+ public function logic(Request $request) : JsonResponse
+ {
+ $this->canFetchCompany->passes();
+
+ $company = $this->fetchesCompany->execute(['id' => $request->route('id')]);
+ $eInvoiceInfo = $company->addresses()->where('billing', '=', false)->where('e_invoice', '=', true)->latest()->first();
+
+ if($eInvoiceInfo){
+ $eInvoiceInfo->tin = $company->tin;
+ $eInvoiceInfo->msic_code = $company->msic_code;
+ $eInvoiceInfo->e_invoice = $company->e_invoice;
+ }
+ else{
+ return $this->response([]);
+ }
+
+ return $this->resourceResponse(new EInvoiceInfoResource($eInvoiceInfo));
+ }
+}
diff --git a/app/Classes/Modules/Companies/ControllersLogic/UpdateCompanyDetailsLogic.php b/app/Classes/Modules/Companies/ControllersLogic/UpdateCompanyDetailsLogic.php
new file mode 100644
index 00000000..7cb9c3c8
--- /dev/null
+++ b/app/Classes/Modules/Companies/ControllersLogic/UpdateCompanyDetailsLogic.php
@@ -0,0 +1,132 @@
+ 'Update Company Details',
+ 'message' => 'You have successfully updated the Company Details'
+ ];
+ }
+ /** @var CanUpdateCompany */
+ private $canUpdateCompany;
+
+ /** @var UpdatesCompany */
+ private $updatesCompany;
+
+ /** @var FetchesCompany */
+ private $fetchesCompany;
+
+ /** @var UpdatesCompanyDebtor */
+ private $updatesCompanyDebtor;
+
+ /** @var CanCreateAddress */
+ private $canCreateAddress;
+
+ /** @var FetchesDistrict */
+ private $fetchesDistrict;
+
+ /** @var UpsertsAddress */
+ private $upsertsAddress;
+
+ /** @var UpdatesCompanyEInvoiceInfo */
+ private $updatesCompanyEInvoiceInfo;
+
+ /** @var UpdatesAddressMetadata */
+ private $updatesAddressMetadata;
+
+
+ /**
+ * UpdateCompanyDetailsLogic constructor.
+ * @param CanUpdateCompany $canUpdateCompany
+ * @param UpdatesCompany $updatesCompany
+ * @param FetchesCompany $fetchesCompany
+ * @param UpdatesCompanyDebtor $updatesCompanyDebtor
+ * @param CanCreateAddress $canCreateAddress
+ * @param FetchesDistrict $fetchesDistrict
+ * @param FetchesCompany $fetchesCompany
+ * @param UpsertsAddress $upsertsAddress
+ * @param UpdatesCompanyEInvoiceInfo $updatesCompanyEInvoiceInfo;
+ * @param UpdatesAddressMetadata $updatesAddressMetadata
+ */
+ public function __construct(
+ CanUpdateCompany $canUpdateCompany,
+ UpdatesCompany $updatesCompany,
+ FetchesCompany $fetchesCompany,
+ UpdatesCompanyDebtor $updatesCompanyDebtor,
+ CanCreateAddress $canCreateAddress,
+ FetchesDistrict $fetchesDistrict,
+ UpsertsAddress $upsertsAddress,
+ UpdatesCompanyEInvoiceInfo $updatesCompanyEInvoiceInfo,
+ UpdatesAddressMetadata $updatesAddressMetadata
+ )
+ {
+ $this->canUpdateCompany = $canUpdateCompany;
+ $this->updatesCompany = $updatesCompany;
+ $this->fetchesCompany = $fetchesCompany;
+ $this->updatesCompanyDebtor = $updatesCompanyDebtor;
+ $this->canCreateAddress = $canCreateAddress;
+ $this->fetchesDistrict = $fetchesDistrict;
+ $this->fetchesCompany = $fetchesCompany;
+ $this->upsertsAddress = $upsertsAddress;
+ $this->updatesCompanyEInvoiceInfo = $updatesCompanyEInvoiceInfo;
+ $this->updatesAddressMetadata = $updatesAddressMetadata;
+ }
+
+ /**
+ * @param Request $request
+ * @return JsonResponse
+ * @throws ErrorException
+ */
+ public function logic(Request $request) : JsonResponse
+ {
+ $dto = new UpdateCompanyDetailsDTO($request->all());
+
+ $company = $this->fetchesCompany->execute(['id' => $request->route('id')]);
+ $object = new CompanyObject($dto->name, $dto->reference, $company->business_type, $dto->type);
+
+ $this->canUpdateCompany->passes($object);
+
+ //Update Name and Debtor
+ $company = $this->updatesCompany->execute($company, $object);
+ if ($dto->debtor|| $company->first()->debtor !== null) {
+ $this->updatesCompanyDebtor->execute($company, $dto->debtor);
+ }
+
+ //Update EInvoice Related Info
+ if($company->e_invoice){
+ $district = $this->fetchesDistrict->execute(['id' => $dto->districtId]);
+ $addObj = new AddressObject($dto->streetOne, $dto->streetTwo, $district->country_id, $district->state_id, $district->id, $dto->postCode);
+ $this->canCreateAddress->passes($addObj);
+
+ $address = $this->upsertsAddress->execute($company, $addObj, $dto->addressId);
+ $query = $this->updatesAddressMetadata->execute($address, false, true);
+ $this->updatesCompanyEInvoiceInfo->execute($company, $dto->tin, $dto->msicCode);
+ }
+
+ return $this->resourceResponse(new CompanyResource($company));
+ }
+}
+
diff --git a/app/Classes/Modules/Companies/ControllersLogic/UpdateCompanyEInvoiceInfoLogic.php b/app/Classes/Modules/Companies/ControllersLogic/UpdateCompanyEInvoiceInfoLogic.php
new file mode 100644
index 00000000..9978006f
--- /dev/null
+++ b/app/Classes/Modules/Companies/ControllersLogic/UpdateCompanyEInvoiceInfoLogic.php
@@ -0,0 +1,112 @@
+ 'EInvoice Info Update',
+ 'message' => 'You have successfully updated company E-Invoice information'
+ ];
+ }
+
+ /** @var CanCreateAddress */
+ private $canCreateAddress;
+
+ /** @var FetchesDistrict */
+ private $fetchesDistrict;
+
+ /** @var FetchesCompany */
+ private $fetchesCompany;
+
+ /** @var CreatesAddress */
+ private $createsAddress;
+
+ /** @var RuleEvaluator */
+ private $ruleEvaluator;
+
+ /** @var UpdatesCompanyEInvoiceInfo */
+ private $updatesCompanyEInvoiceInfo;
+
+ /** @var UpdatesAddressMetadata */
+ private $updatesAddressMetadata;
+
+ /**
+ * UpdateCompanyEInvoiceInfoLogic constructor.
+ * @param CanCreateAddress $canCreateAddress
+ * @param FetchesDistrict $fetchesDistrict
+ * @param FetchesCompany $fetchesCompany
+ * @param CreatesAddress $createsAddress
+ * @param RuleEvaluator $ruleEvaluator;
+ * @param UpdatesCompanyEInvoiceInfo $updatesCompanyEInvoiceInfo;
+ * @param UpdatesAddressMetadata $updatesAddressMetadata
+ */
+ public function __construct(CanCreateAddress $canCreateAddress, FetchesDistrict $fetchesDistrict, FetchesCompany $fetchesCompany, CreatesAddress $createsAddress, RuleEvaluator $ruleEvaluator, UpdatesCompanyEInvoiceInfo $updatesCompanyEInvoiceInfo, UpdatesAddressMetadata $updatesAddressMetadata)
+ {
+ $this->canCreateAddress = $canCreateAddress;
+ $this->fetchesDistrict = $fetchesDistrict;
+ $this->fetchesCompany = $fetchesCompany;
+ $this->createsAddress = $createsAddress;
+ $this->ruleEvaluator = $ruleEvaluator;
+ $this->updatesCompanyEInvoiceInfo = $updatesCompanyEInvoiceInfo;
+ $this->updatesAddressMetadata = $updatesAddressMetadata;
+ }
+
+ /**
+ * @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 EInvoiceInfoDTO($request->all());
+ $result = $this->ruleEvaluator->evaluate([
+ App()->make(CanProceedEInvoicePromptedRule::class),
+ ], $dto);
+
+ if ($result->failed()) {
+ throw new CriteriaNotFulfilledException("- " . implode("
- ", $result->messages()));
+ }
+
+ $district = $this->fetchesDistrict->execute(['id' => $dto->districtId]);
+ $object = new AddressObject($dto->streetOne, $dto->streetTwo, $district->country_id, $district->state_id, $district->id, $dto->postCode);
+
+ //Update Address
+ $this->canCreateAddress->passes($object);
+ $company = $this->fetchesCompany->execute(['id' => $dto->companyId]);
+ $address = $this->createsAddress->execute($company, $object);
+ $query = $this->updatesAddressMetadata->execute($address, false, true);
+
+ //Update tin, msic code
+ $this->updatesCompanyEInvoiceInfo->execute($company, $dto->tin, $dto->msicCode);
+
+ $query->tin = $dto->tin;
+ $query->msic_code = $dto->msicCode;
+
+ return $this->response([]);
+ }
+}
diff --git a/app/Classes/Modules/Companies/ControllersLogic/UpdateCompanyEInvoiceRequestLogic.php b/app/Classes/Modules/Companies/ControllersLogic/UpdateCompanyEInvoiceRequestLogic.php
new file mode 100644
index 00000000..86051447
--- /dev/null
+++ b/app/Classes/Modules/Companies/ControllersLogic/UpdateCompanyEInvoiceRequestLogic.php
@@ -0,0 +1,59 @@
+ 'Updated EInvoice Request',
+ 'message' => 'You have successfully updated company E-Invoice request'
+ ];
+ }
+
+ /** @var FetchesCompany */
+ private $fetchesCompany;
+
+ /** @var UpdatesCompanyEInvoiceRequest */
+ private $updatesCompanyEInvoiceRequest;
+
+
+ /**
+ * UpdateCompanyEInvoiceRequestLogic constructor.
+ * @param FetchesCompany $fetchesCompany
+ * @param UpdatesCompanyEInvoiceRequest $updatesCompanyEInvoiceRequest
+ */
+ public function __construct(FetchesCompany $fetchesCompany, UpdatesCompanyEInvoiceRequest $updatesCompanyEInvoiceRequest)
+ {
+ $this->fetchesCompany = $fetchesCompany;
+ $this->updatesCompanyEInvoiceRequest = $updatesCompanyEInvoiceRequest;
+ }
+
+ /**
+ * @param Request $request
+ * @return JsonResponse
+ * @throws \App\Classes\Exceptions\AccessForbiddenException
+ * @throws \App\Classes\Exceptions\MalformedRequestException
+ * @throws \App\Classes\Exceptions\RequestValidationException
+ */
+ public function logic(Request $request) : JsonResponse
+ {
+ $dto = new EInvoiceRequestDTO($request->all());
+ $company = $this->fetchesCompany->execute(['id' => $dto->companyId]);
+ $this->updatesCompanyEInvoiceRequest->execute($company, $dto->eInvoiceRequest);
+
+ return $this->response([]);
+ }
+}
diff --git a/app/Classes/Modules/Companies/ControllersLogic/UpdateCompanyNameAndDebtorLogic.php b/app/Classes/Modules/Companies/ControllersLogic/UpdateCompanyNameAndDebtorLogic.php
index 05fb0746..5a110d85 100644
--- a/app/Classes/Modules/Companies/ControllersLogic/UpdateCompanyNameAndDebtorLogic.php
+++ b/app/Classes/Modules/Companies/ControllersLogic/UpdateCompanyNameAndDebtorLogic.php
@@ -20,8 +20,8 @@ class UpdateCompanyNameAndDebtorLogic extends AbstractControllerLogic
*/
protected function notification():array {
return [
- 'title' => 'Update Company Account Status',
- 'message' => 'You have successfully updated the Company Account Status'
+ 'title' => 'Update Company Details',
+ 'message' => 'You have successfully updated the Company Details'
];
}
/** @var CanUpdateCompany */
@@ -77,6 +77,4 @@ class UpdateCompanyNameAndDebtorLogic extends AbstractControllerLogic
return $this->resourceResponse(new CompanyResource($query));
}
-
}
-
diff --git a/app/Classes/Modules/Companies/DataTransferObjects/UpdateCompanyDetailsDTO.php b/app/Classes/Modules/Companies/DataTransferObjects/UpdateCompanyDetailsDTO.php
new file mode 100644
index 00000000..5a16f12c
--- /dev/null
+++ b/app/Classes/Modules/Companies/DataTransferObjects/UpdateCompanyDetailsDTO.php
@@ -0,0 +1,61 @@
+id = (int) ($data['id'] ?? 0);
+ $this->name = (string) ($data['name'] ?? '');
+ $this->debtor = (string) ($data['debtor'] ?? '');
+ $this->reference = (string) ($data['reference'] ?? '');
+ $this->type = (int) ($data['type'] ?? 0);
+
+ $this->tin = (int) ($data['tin'] ?? 0);
+ $this->msicCode = (int) ($data['msic_code'] ?? 0);
+ $this->addressId = (int) ($data['address_id'] ?? 0);
+ $this->districtId = (int) ($data['district_id'] ?? 0);
+ $this->companyId = (int) ($data['company_id'] ?? 0);
+ $this->streetOne = (string) ($data['street_one'] ?? '');
+ $this->streetTwo = (string) ($data['street_two'] ?? '');
+ $this->postCode = (int) ($data['post_code'] ?? 0);
+ }
+
+ public function toArray(): array
+ {
+ return [
+ 'id' => $this->id,
+ 'name' => $this->name,
+ 'debtor' => $this->debtor,
+ 'reference' => $this->reference,
+ 'type' => $this->type,
+
+ 'tin' => $this->tin,
+ 'msic_code' => $this->msicCode,
+ 'address_id' => $this->addressId,
+ 'district_id' => $this->districtId,
+ 'company_id' => $this->companyId,
+ 'street_one' => $this->streetOne,
+ 'street_two' => $this->streetTwo,
+ 'post_code' => $this->postCode,
+ ];
+ }
+}
diff --git a/app/Classes/Modules/Companies/Services/UpdatesCompanyEInvoiceInfo.php b/app/Classes/Modules/Companies/Services/UpdatesCompanyEInvoiceInfo.php
new file mode 100644
index 00000000..0a2c5cc5
--- /dev/null
+++ b/app/Classes/Modules/Companies/Services/UpdatesCompanyEInvoiceInfo.php
@@ -0,0 +1,25 @@
+tin = $tin;
+ $model->msic_code = $msicCode;
+
+ return $this->handler($model);
+ }
+}
diff --git a/app/Classes/Modules/Companies/Services/UpdatesCompanyEInvoiceRequest.php b/app/Classes/Modules/Companies/Services/UpdatesCompanyEInvoiceRequest.php
new file mode 100644
index 00000000..780f8150
--- /dev/null
+++ b/app/Classes/Modules/Companies/Services/UpdatesCompanyEInvoiceRequest.php
@@ -0,0 +1,27 @@
+e_invoice) && is_null($model->e_invoice_requested_at)) {
+ $model->e_invoice_requested_at = now();
+ }
+ $model->e_invoice = $eInvoice;
+
+ return $this->handler($model);
+ }
+}
diff --git a/app/Classes/Modules/Exports/Services/ExportsEInvoiceDebtorSummary.php b/app/Classes/Modules/Exports/Services/ExportsEInvoiceDebtorSummary.php
index 69e237fb..7edf2d72 100644
--- a/app/Classes/Modules/Exports/Services/ExportsEInvoiceDebtorSummary.php
+++ b/app/Classes/Modules/Exports/Services/ExportsEInvoiceDebtorSummary.php
@@ -57,7 +57,8 @@ class ExportsEInvoiceDebtorSummary implements FromQuery, WithHeadings, WithHeadi
public function query()
{
return Company::where(function($query){
- $query->whereNull('debtor')->orWhere('debtor', '');
+ // $query->whereNull('debtor')->orWhere('debtor', '');
+ $query->whereNotNull('e_invoice');
})->whereNotIn('id', [2207, 2248, 2029])->where('business_type', BusinessType::IMPORTER)->where('status', ApprovalStatus::APPROVED)->where(function($query){
$query->whereHas('transactions', function($query){
return $query->whereIn('type', [TransactionType::PAYMENT, TransactionType::TOP_UP])->whereIn('transactions.status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED, ApprovalStatus::PENDING_VERIFICATION]);
@@ -76,9 +77,9 @@ class ExportsEInvoiceDebtorSummary implements FromQuery, WithHeadings, WithHeadi
{
return [
'<
- ", $result->messages()));
+ }
+
+ return $this->resourceResponse(new RuleResource((object)$result));
+ }
+}
diff --git a/app/Classes/Modules/Rules/ControllersLogic/CheckPurchaseOrderRuleLogic.php b/app/Classes/Modules/Rules/ControllersLogic/CheckPurchaseOrderRuleLogic.php
new file mode 100644
index 00000000..577e4618
--- /dev/null
+++ b/app/Classes/Modules/Rules/ControllersLogic/CheckPurchaseOrderRuleLogic.php
@@ -0,0 +1,62 @@
+ 'Rule Check Purchase Order',
+ 'message' => 'You have successfully passed all rules evaluated'
+ ];
+ }
+
+ /** @var RuleEvaluator */
+ private $ruleEvaluator;
+
+ /**
+ * CheckPurchaseOrderRuleLogic constructor.
+ */
+ public function __construct(RuleEvaluator $ruleEvaluator)
+ {
+ $this->ruleEvaluator = $ruleEvaluator;
+ }
+
+ /**
+ * @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 CheckPurchaseOrderRuleDTO($request->all());
+
+ $result = $this->ruleEvaluator->evaluate([
+ App()->make(CanProceedEInvoicePromptedRule::class),
+ App()->make(CanProceedPurchaseOrderRule::class),
+ ], $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/CheckEInvoiceRuleDTO.php b/app/Classes/Modules/Rules/DataTransferObjects/CheckEInvoiceRuleDTO.php
new file mode 100644
index 00000000..75726e47
--- /dev/null
+++ b/app/Classes/Modules/Rules/DataTransferObjects/CheckEInvoiceRuleDTO.php
@@ -0,0 +1,22 @@
+companyId = $data['company_id'];
+ }
+
+ public function toArray(): array
+ {
+ return [
+ 'company_id' => $this->companyId,
+ ];
+ }
+}
diff --git a/app/Classes/Modules/Rules/DataTransferObjects/CheckPurchaseOrderRuleDTO.php b/app/Classes/Modules/Rules/DataTransferObjects/CheckPurchaseOrderRuleDTO.php
new file mode 100644
index 00000000..2c5c2ab5
--- /dev/null
+++ b/app/Classes/Modules/Rules/DataTransferObjects/CheckPurchaseOrderRuleDTO.php
@@ -0,0 +1,25 @@
+bookingId = $data['booking_id'];
+ $this->companyId = $data['company_id'];
+ }
+
+ public function toArray(): array
+ {
+ return [
+ 'booking_id' => $this->bookingId,
+ 'company_id' => $this->companyId,
+ ];
+ }
+}
diff --git a/app/Classes/Modules/Rules/DataTransferObjects/ConfirmBookingDTO.php b/app/Classes/Modules/Rules/DataTransferObjects/ConfirmBookingDTO.php
new file mode 100644
index 00000000..2c154833
--- /dev/null
+++ b/app/Classes/Modules/Rules/DataTransferObjects/ConfirmBookingDTO.php
@@ -0,0 +1,25 @@
+bookingId = $data['booking_id'];
+ $this->companyId = $data['company_id'];
+ }
+
+ public function toArray(): array
+ {
+ return [
+ 'booking_id' => $this->bookingId,
+ 'company_id' => $this->companyId,
+ ];
+ }
+}
diff --git a/app/Classes/Modules/Rules/DataTransferObjects/EInvoiceInfoDTO.php b/app/Classes/Modules/Rules/DataTransferObjects/EInvoiceInfoDTO.php
new file mode 100644
index 00000000..f768b2c1
--- /dev/null
+++ b/app/Classes/Modules/Rules/DataTransferObjects/EInvoiceInfoDTO.php
@@ -0,0 +1,40 @@
+tin = (int) ($data['tin'] ?? '');
+ $this->msicCode = (int) ($data['msic_code'] ?? '');
+ $this->districtId = (int) ($data['district_id'] ?? '');
+ $this->companyId = (int) ($data['company_id'] ?? '');
+ $this->streetOne = (string) ($data['street_one'] ?? '');
+ $this->streetTwo = (string) ($data['street_two'] ?? '');
+ $this->postCode = (int) ($data['post_code'] ?? '');
+ }
+
+ public function toArray(): array
+ {
+ return [
+ 'tin' => $this->tin,
+ 'msic_code' => $this->msicCode,
+ 'district_id' => $this->districtId,
+ 'company_id' => $this->companyId,
+ 'street_one' => $this->streetOne,
+ 'street_two' => $this->streetTwo,
+ 'post_code' => $this->postCode,
+ ];
+ }
+}
diff --git a/app/Classes/Modules/Rules/DataTransferObjects/EInvoiceRequestDTO.php b/app/Classes/Modules/Rules/DataTransferObjects/EInvoiceRequestDTO.php
new file mode 100644
index 00000000..cbc2b0ea
--- /dev/null
+++ b/app/Classes/Modules/Rules/DataTransferObjects/EInvoiceRequestDTO.php
@@ -0,0 +1,25 @@
+eInvoiceRequest = $data['e_invoice_request'];
+ $this->companyId = $data['company_id'];
+ }
+
+ public function toArray(): array
+ {
+ return [
+ 'e_invoice_request' => $this->eInvoiceRequest,
+ 'company_id' => $this->companyId,
+ ];
+ }
+}
diff --git a/app/Classes/Modules/Rules/Services/RuleEvaluator.php b/app/Classes/Modules/Rules/Services/RuleEvaluator.php
new file mode 100644
index 00000000..ac248a25
--- /dev/null
+++ b/app/Classes/Modules/Rules/Services/RuleEvaluator.php
@@ -0,0 +1,44 @@
+passes($object)) {
+ $success = false;
+ $messages[] = get_class($rule) . ' failed without exception';
+ }
+ } catch (AccessForbiddenException | RequestValidationException | CriteriaNotFulfilledException $e) {
+ $success = false;
+ $messages[] = $e->getMessage();
+ } catch (\Exception $e) {
+ $success = false;
+ $messages[] = 'Unexpected error in ' . get_class($rule) . ': ' . $e->getMessage();
+ }
+ }
+
+ return new RuleEvaluationResult($success, $messages);
+ }
+
+}
diff --git a/app/Classes/Modules/Rules/Standards/Rules/CanProceedEInvoicePromptedRule.php b/app/Classes/Modules/Rules/Standards/Rules/CanProceedEInvoicePromptedRule.php
new file mode 100644
index 00000000..dcddbcdd
--- /dev/null
+++ b/app/Classes/Modules/Rules/Standards/Rules/CanProceedEInvoicePromptedRule.php
@@ -0,0 +1,56 @@
+fetchesCompany = $fetchesCompany;
+ }
+
+ /**
+ * @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 account requires E-Invoice
+ $company = $this->fetchesCompany->execute(['id' => $object->companyId]);
+ if($company->e_invoice === null){
+ throw new CriteriaNotFulfilledException("Please refresh page to answer question related to E-Invoice.");
+ }
+ return true;
+ }
+
+}
diff --git a/app/Classes/Modules/Rules/Standards/Rules/CanProceedPurchaseOrderRule.php b/app/Classes/Modules/Rules/Standards/Rules/CanProceedPurchaseOrderRule.php
new file mode 100644
index 00000000..f9483835
--- /dev/null
+++ b/app/Classes/Modules/Rules/Standards/Rules/CanProceedPurchaseOrderRule.php
@@ -0,0 +1,96 @@
+fetchesBooking = $fetchesBooking;
+ $this->fetchesCompany = $fetchesCompany;
+ }
+
+ /**
+ * @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 the transfer/booking already has purchase order filled
+ $booking = $this->fetchesBooking->execute(['id' => $object->bookingId]);
+ $purchaseOrder = $booking->transactions()->where('type', TransactionType::PURCHASE_ORDER)->first();
+
+ $isPOEmptyException = false;
+ if (!$purchaseOrder || $purchaseOrder->status === ApprovalStatus::PENDING_SUBMISSION) {
+ $isPOEmptyException = true;
+ }
+
+ if($isPOEmptyException){ //If PO is indeed empty, there are some scenarios where PO actually can be left empty
+ $ids = ServiceType::whereIn('name', [
+ ServiceTypeNameConstants::PAYMENT_1688,
+ ServiceTypeNameConstants::VIP_1688,
+ ])->get()->pluck('id');
+
+ //It can be left empty when booking is of type 1688: specifcally: 1688 Payment and 1688 VIP
+ if (in_array($booking->service_id, $ids->all())) {
+ $isPOEmptyException = false;
+ }
+
+ //However when the customer falls under the segment '1688 Manual PO Periodic', even if their booking is of type 1688 (1688 Payment and 1688 VIP),
+ //they still must fill up the PO. Confusing?? IKR
+ $company = $this->fetchesCompany->execute(['id' => $object->companyId]);
+ $filteredSegments = $company->segments()->where('name', SegmentNameConstants::MANUAL_PO_PERIODIC_1688)->get();
+ if(!$isPOEmptyException){
+ if (!$filteredSegments->isEmpty()) {
+ $isPOEmptyException = true;
+ }
+ }
+ }
+
+ if($isPOEmptyException){
+ throw new CriteriaNotFulfilledException("Please complete the purchase order form.");
+ }
+ return true;
+ }
+}
diff --git a/app/Classes/Modules/Rules/Standards/Rules/CanProceedTINRule.php b/app/Classes/Modules/Rules/Standards/Rules/CanProceedTINRule.php
new file mode 100644
index 00000000..a4adc674
--- /dev/null
+++ b/app/Classes/Modules/Rules/Standards/Rules/CanProceedTINRule.php
@@ -0,0 +1,55 @@
+fetchesCompany = $fetchesCompany;
+ }
+
+ /**
+ * @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 TIN already provided if account requires E-Invoice
+ $company = $this->fetchesCompany->execute(['id' => $object->companyId]);
+ if($company->e_invoice === 1 && !$company->tin){
+ throw new CriteriaNotFulfilledException("Please provide all requested E-Invoice Info.");
+ }
+ return true;
+ }
+
+}
diff --git a/app/Classes/ValueObjects/Constants/SegmentNameConstants.php b/app/Classes/ValueObjects/Constants/SegmentNameConstants.php
new file mode 100644
index 00000000..a8e881d7
--- /dev/null
+++ b/app/Classes/ValueObjects/Constants/SegmentNameConstants.php
@@ -0,0 +1,7 @@
+success = $success;
+ $this->messages = $messages;
+ }
+
+ public function failed(): bool
+ {
+ return ! $this->success;
+ }
+
+ public function passed(): bool
+ {
+ return $this->success;
+ }
+
+ public function messages(): array
+ {
+ return $this->messages;
+ }
+}
diff --git a/app/Http/Controllers/Companies/FetchCompanyEInvoiceInfoController.php b/app/Http/Controllers/Companies/FetchCompanyEInvoiceInfoController.php
new file mode 100644
index 00000000..d506e24e
--- /dev/null
+++ b/app/Http/Controllers/Companies/FetchCompanyEInvoiceInfoController.php
@@ -0,0 +1,20 @@
+execute($request);
+ }
+}
diff --git a/app/Http/Controllers/Companies/UpdateCompanyDetailsController.php b/app/Http/Controllers/Companies/UpdateCompanyDetailsController.php
new file mode 100644
index 00000000..e8cbfd1c
--- /dev/null
+++ b/app/Http/Controllers/Companies/UpdateCompanyDetailsController.php
@@ -0,0 +1,21 @@
+execute($request);
+ }
+}
diff --git a/app/Http/Controllers/Companies/UpdateCompanyEInvoiceInfoController.php b/app/Http/Controllers/Companies/UpdateCompanyEInvoiceInfoController.php
new file mode 100644
index 00000000..9157e9de
--- /dev/null
+++ b/app/Http/Controllers/Companies/UpdateCompanyEInvoiceInfoController.php
@@ -0,0 +1,29 @@
+execute($request);
+ }
+
+ /**
+ * @param Request $request
+ * @param UpdateCompanyEInvoiceRequestLogic $logic
+ * @return JsonResponse
+ */
+ public function updateRequest(Request $request, UpdateCompanyEInvoiceRequestLogic $logic): JsonResponse {
+ return $logic->execute($request);
+ }
+}
diff --git a/app/Http/Controllers/Rules/CheckRuleController.php b/app/Http/Controllers/Rules/CheckRuleController.php
new file mode 100644
index 00000000..881c6abe
--- /dev/null
+++ b/app/Http/Controllers/Rules/CheckRuleController.php
@@ -0,0 +1,29 @@
+execute($request);
+ }
+
+ /**
+ * @param Request $request
+ * @param CheckPurchaseOrderRuleLogic $logic
+ * @return JsonResponse
+ */
+ public function checkPurchaseOrderRule(Request $request, CheckPurchaseOrderRuleLogic $logic): JsonResponse {
+ return $logic->execute($request);
+ }
+}
diff --git a/app/Http/Resources/CompanyResource.php b/app/Http/Resources/CompanyResource.php
index 82b4cf3e..4e3ac2f0 100644
--- a/app/Http/Resources/CompanyResource.php
+++ b/app/Http/Resources/CompanyResource.php
@@ -37,11 +37,15 @@ class CompanyResource extends JsonResource
'name' => $this->name,
'reference' => $this->reference,
'debtor' => $this->debtor,
+ 'e_invoice' => $this->e_invoice,
+ 'tin' => $this->tin,
+ 'msic_code' => $this->msic_code,
'type' => (int) $this->type,
'business_type' => (int) $this->business_type,
'status' => (int) $this->status,
'contact' => new ContactResource ($this->when($this->has('contacts'), $this->contacts->first())),
'address' => new AddressResource($this->when($this->has('addresses'), $this->addresses->where('billing', true)->first())),
+ 'address_einvoice' => $this->e_invoice ? new AddressResource($this->when($this->has('addresses'), $this->addresses->where('billing', false)->where('e_invoice', true)->sortByDesc('created_at')->first())) : null,
'employee' => new UserResource(Auth::user()->type === RoleTypes::USER ? $this->employees()->where('email', '=', Auth::user()->email)->first() : $this->employees()->orderBy('id', 'DESC')->first()),
'identification' => new DocumentResource($this->documents->whereIn('document_type', DocumentType::IDENTIFICATION_DOCUMENTS)->first()),
'bookings' => $this->whenLoaded('bookings', $this->bookings()->orderBy('id', 'DESC')->get(), []),
diff --git a/app/Http/Resources/EInvoiceInfoResource.php b/app/Http/Resources/EInvoiceInfoResource.php
new file mode 100644
index 00000000..9bf8c8c1
--- /dev/null
+++ b/app/Http/Resources/EInvoiceInfoResource.php
@@ -0,0 +1,31 @@
+ $this->id,
+ 'street_one' => $this->street_one,
+ 'street_two' => $this->street_two,
+ 'district' => $this->district,
+ 'state' => $this->state,
+ 'post_code' => $this->postcode,
+ 'country' => $this->country,
+ 'billing' => (int) $this->billing,
+ 'msic_code' => (int) $this->msic_code,
+ 'tin' => (int) $this->tin,
+ 'e_invoice' => (int) $this->e_invoice,
+ ];
+ }
+}
diff --git a/app/Http/Resources/RuleResource.php b/app/Http/Resources/RuleResource.php
new file mode 100644
index 00000000..1fb42181
--- /dev/null
+++ b/app/Http/Resources/RuleResource.php
@@ -0,0 +1,22 @@
+ $this->success,
+ 'messages' => $this->messages,
+ ];
+ }
+}
diff --git a/database/migrations/2025_05_04_150726_add_einvoice_to_addresses_table.php b/database/migrations/2025_05_04_150726_add_einvoice_to_addresses_table.php
new file mode 100644
index 00000000..990a9e1c
--- /dev/null
+++ b/database/migrations/2025_05_04_150726_add_einvoice_to_addresses_table.php
@@ -0,0 +1,32 @@
+boolean('e_invoice')->default(false)->after('billing');
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::table('addresses', function (Blueprint $table) {
+ $table->dropColumn('e_invoice');
+ });
+ }
+}
diff --git a/database/migrations/2025_05_04_150735_add_tin_to_companies_table.php b/database/migrations/2025_05_04_150735_add_tin_to_companies_table.php
new file mode 100644
index 00000000..ed5f2c58
--- /dev/null
+++ b/database/migrations/2025_05_04_150735_add_tin_to_companies_table.php
@@ -0,0 +1,38 @@
+string('tin')->nullable()->after('debtor');
+ $table->string('msic_code')->nullable()->after('debtor')->comment("5-digit code representing business activity");
+ $table->timestamp('e_invoice_requested_at')->nullable()->after('debtor');
+ $table->boolean('e_invoice')->nullable()->default(null)->after('debtor');
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::table('companies', function (Blueprint $table) {
+ $table->dropColumn('tin');
+ $table->dropColumn('msic_code');
+ $table->dropColumn('e_invoice_requested_at');
+ $table->dropColumn('e_invoice');
+ });
+ }
+}
diff --git a/resources/assets/vue/components/address/forms/EInvoiceInfoFormComponent.vue b/resources/assets/vue/components/address/forms/EInvoiceInfoFormComponent.vue
new file mode 100644
index 00000000..5478b2f3
--- /dev/null
+++ b/resources/assets/vue/components/address/forms/EInvoiceInfoFormComponent.vue
@@ -0,0 +1,213 @@
+
+ E-Invoice Info
+
+
+
+
+
+
+
+
+
{{ this.calculation.receive_date }}You don't have sufficient credit in your wallet to complete this transaction. Please Reload your wallet.
+
+
+ {{ booking.company.e_invoice
+ ? (booking.company.tin ? booking.company.tin : 'INCOMPLETE E-INVOICE INFO')
+ : 'NOT PROVIDED' }}
+
+ View E-Invoice Info
+
+