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

This commit is contained in:
Dillon Ngo
2025-05-10 16:51:31 +08:00
59 changed files with 2964 additions and 53 deletions
@@ -0,0 +1,14 @@
<?php
namespace App\Classes\Exceptions;
use App\Classes\ValueObjects\Constants\HttpStatus;
final class CriteriaNotFulfilledException extends ServiceApiException {
public function __construct(?string $message = null) {
parent::__construct(
$message ?? 'One or more required criteria were not fulfilled.',
HttpStatus::VALIDATION_FAILED
);
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\General\Abstracts;
use App\Classes\Exceptions\AccessForbiddenException;
use App\Classes\Exceptions\CriteriaNotFulfilledException;
use App\Classes\Exceptions\RequestValidationException;
use App\Classes\General\Interfaces\DataTransferObject;
@@ -23,6 +24,7 @@ abstract class AbstractRule
* @return bool
* @throws AccessForbiddenException
* @throws RequestValidationException
* @throws CriteriaNotFulfilledException
*/
public function passes(?DataTransferObject $object = null): bool {
try {
@@ -35,12 +37,14 @@ abstract class AbstractRule
return true;
} catch(AccessForbiddenException $exception){
throw new AccessForbiddenException('You don\'t have permission to perform this action');
} catch(CriteriaNotFulfilledException $exception){
throw new CriteriaNotFulfilledException($exception->getMessage());
} catch(\Exception $exception){
throw new RequestValidationException($exception->getMessage());
}
}
}
@@ -0,0 +1,19 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class IsEInvoice implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->where('e_invoice', $value);
}
}
@@ -50,10 +50,10 @@ class ListAddressesLogic extends AbstractControllerLogic
public function logic(Request $request) : JsonResponse
{
try {
$this->canListAddresses->passes();
$query = $this->listsAddresses->execute($this->listsAddresses->deserializeFilters($request->input('filters')));
$query = $this->listsAddresses->execute(
array_merge($this->listsAddresses->deserializeFilters($request->input('filters')), ['is_e_invoice' => false])); //exclude all addresses meant for e_invoice
return $this->collectionResponse(AddressResource::collection($query));
@@ -63,4 +63,4 @@ class ListAddressesLogic extends AbstractControllerLogic
}
}
}
@@ -0,0 +1,25 @@
<?php
namespace App\Classes\Modules\Addresses\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Models\Address;
class UpdatesAddressMetadata extends AbstractUpdateRecord
{
/**
* @param Address $model
* @param bool $billing
* @param bool $eInvoice
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(Address $model, bool $billing, bool $eInvoice) {
$model->billing = $billing;
$model->e_invoice = $eInvoice;
return $this->handler($model);
}
}
@@ -0,0 +1,36 @@
<?php
namespace App\Classes\Modules\Addresses\Services;
use App\Classes\General\Eloquent\AbstractUpdateRelationshipRecord;
use App\Classes\Modules\Addresses\DataTransferObjects\AddressObject;
use App\Models\Address;
use App\Models\Company;
class UpsertsAddress extends AbstractUpdateRelationshipRecord
{
/**
* Create or update the company's address.
*
* @param Company $company
* @param AddressObject $object
* @param int $id
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(Company $company, AddressObject $object, int $id)
{
//Create new or update?
$model = $company->addresses()->where('id', $id)->first() ?? new Address();
$model->street_one = $object->getStreetOne();
$model->street_two = $object->getStreetTwo();
$model->country_id = $object->getCountryId();
$model->state_id = $object->getStateId();
$model->district_id = $object->getDistrictId();
$model->postcode = $object->getPostCode();
return $this->handler($company->addresses(), $model);
}
}
@@ -2,7 +2,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\Modules\Bookings\DataTransferObjects\CalculationObject;
@@ -17,9 +17,14 @@ use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use App\Classes\Modules\Wallets\Services\UpdatesWalletBalance;
use App\Classes\Modules\Currencies\DataTransferObjects\CurrencyConversionObject;
use App\Classes\Modules\Bookings\Services\CalculatesBookingRefundAmount;
use App\Classes\Modules\Rules\DataTransferObjects\ConfirmBookingDTO;
use App\Classes\Modules\Rules\Standards\Rules\CanProceedEInvoicePromptedRule;
use App\Classes\Modules\Rules\Standards\Rules\CanProceedPurchaseOrderRule;
use App\Classes\Modules\Rules\Standards\Rules\CanProceedTINRule;
use App\Classes\Modules\Transactions\Processors\CreateCashBackTransactionProcessor;
use App\Classes\Modules\Vouchers\Processors\Voucherify\BookingToVoucherifyProcessor;
use App\Classes\Modules\Wallets\Services\RecalculatesWalletBalance;
use App\Classes\Modules\Rules\Services\RuleEvaluator;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\ValueObjects\Constants\TransactionType;
@@ -78,6 +83,9 @@ class CreateBookingPaymentLogic extends AbstractControllerLogic
/** @var CalculatesBookingRefundAmount */
private $calculatesBookingRefundAmount;
/** @var RuleEvaluator */
private $ruleEvaluator;
/**
* @param FetchesBookingQuotation $fetchBookingQuotation
* @param FetchesCompanyPaymentAttemptLimit $fetchesCompanyPaymentAttemptLimit
@@ -90,8 +98,9 @@ class CreateBookingPaymentLogic extends AbstractControllerLogic
* @param RecalculatesWalletBalance $recalculatesWalletBalance
* @param BookingToVoucherifyProcessor $bookingToVoucherifyProcessor
* @param CalculatesBookingRefundAmount $calculatesBookingRefundAmount
* @param RuleEvaluator $ruleEvaluator
*/
public function __construct(FetchesBookingQuotation $fetchBookingQuotation, FetchesCompanyPaymentAttemptLimit $fetchesCompanyPaymentAttemptLimit, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreatesTransaction $createsTransaction, CalculatesBookingOutstanding $calculatesBookingOutstanding, CreatesBillplzBill $createsBillplzBill, UpdatesWalletBalance $updatesWalletBalance, UpdatesTransactionStatus $updatesTransactionStatus, CreateCashBackTransactionProcessor $createCashBackTransactionProcessor, RecalculatesWalletBalance $recalculatesWalletBalance, BookingToVoucherifyProcessor $bookingToVoucherifyProcessor, CalculatesBookingRefundAmount $calculatesBookingRefundAmount)
public function __construct(FetchesBookingQuotation $fetchBookingQuotation, FetchesCompanyPaymentAttemptLimit $fetchesCompanyPaymentAttemptLimit, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreatesTransaction $createsTransaction, CalculatesBookingOutstanding $calculatesBookingOutstanding, CreatesBillplzBill $createsBillplzBill, UpdatesWalletBalance $updatesWalletBalance, UpdatesTransactionStatus $updatesTransactionStatus, CreateCashBackTransactionProcessor $createCashBackTransactionProcessor, RecalculatesWalletBalance $recalculatesWalletBalance, BookingToVoucherifyProcessor $bookingToVoucherifyProcessor, CalculatesBookingRefundAmount $calculatesBookingRefundAmount, RuleEvaluator $ruleEvaluator)
{
$this->fetchBookingQuotation = $fetchBookingQuotation;
$this->fetchesCompanyPaymentAttemptLimit = $fetchesCompanyPaymentAttemptLimit;
@@ -104,10 +113,28 @@ class CreateBookingPaymentLogic extends AbstractControllerLogic
$this->recalculatesWalletBalance = $recalculatesWalletBalance;
$this->bookingToVoucherifyProcessor = $bookingToVoucherifyProcessor;
$this->calculatesBookingRefundAmount = $calculatesBookingRefundAmount;
$this->ruleEvaluator = $ruleEvaluator;
}
/**
* @param Request $request
* @return JsonResponse
* @throws MalformedRequestException
* @throws CriteriaNotFulfilledException
*/
public function logic(Request $request) : JsonResponse
{
$dto = new ConfirmBookingDTO($request->all());
$result = $this->ruleEvaluator->evaluate([
App()->make(CanProceedEInvoicePromptedRule::class),
App()->make(CanProceedTINRule::class),
App()->make(CanProceedPurchaseOrderRule::class),
], $dto);
if ($result->failed()) {
throw new CriteriaNotFulfilledException("- " . implode("<br>- ", $result->messages()));
}
$voucherCode = $request->input('voucher_code');
$booking = Booking::find($request->route('id'));
@@ -7,6 +7,7 @@ use App\Classes\Modules\Bookings\DataTransferObjects\CalculationObject;
use App\Classes\Modules\Currencies\DataTransferObjects\CurrencyConversionObject;
use App\Http\Resources\BankResource;
use App\Models\Bank;
use App\Models\Currency;
use Carbon\Carbon;
use Carbon\CarbonInterval;
@@ -44,6 +45,8 @@ class GeneratesBookingQuotation
->format('4:00 \P\M, jS M, Y \G\M\T T');
}
$foreign_currency = Currency::find($calculationObject->getConversionObject()->getCurrencyId());
$foreign_currency_short_code = $foreign_currency->short_code ?? 'CNY';
return [
'bank' => new BankResource(Bank::find($calculationObject->getConfigurations()->getBankId())),
@@ -61,6 +64,7 @@ class GeneratesBookingQuotation
'payment_attempt_limit' => CarbonInterval::days($days)->hours($hours)->minutes($minutes)->forHumans(),
'voucher_discount_amount' => $calculationObject->getVoucherDiscountAmount(),
'voucher_code' => $calculationObject->getVoucherCode(),
'foreign_currency' => $foreign_currency_short_code,
];
}
}
@@ -0,0 +1,68 @@
<?php
namespace App\Classes\Modules\Companies\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Companies\Services\FetchesCompany;
use App\Classes\Modules\Companies\Standards\Rules\CanFetchCompany;
use App\Http\Resources\EInvoiceInfoResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class FetchCompanyEInvoiceInfoLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => '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));
}
}
@@ -0,0 +1,132 @@
<?php
namespace App\Classes\Modules\Companies\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Companies\DataTransferObjects\CompanyObject;
use App\Classes\Modules\Companies\Services\FetchesCompany;
use App\Classes\Modules\Companies\Services\UpdatesCompany;
use App\Classes\Modules\Companies\Services\UpdatesCompanyDebtor;
use App\Classes\Modules\Addresses\Services\UpsertsAddress;
use App\Classes\Modules\Addresses\Services\FetchesDistrict;
use App\Classes\Modules\Addresses\Services\UpdatesAddressMetadata;
use App\Classes\Modules\Addresses\Standards\Rules\CanCreateAddress;
use App\Classes\Modules\Addresses\DataTransferObjects\AddressObject;
use App\Classes\Modules\Companies\Services\UpdatesCompanyEInvoiceInfo;
use App\Classes\Modules\Companies\Standards\Rules\CanUpdateCompany;
use App\Classes\Modules\Companies\DataTransferObjects\UpdateCompanyDetailsDTO;
use App\Http\Resources\CompanyResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class UpdateCompanyDetailsLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => '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));
}
}
@@ -0,0 +1,112 @@
<?php
namespace App\Classes\Modules\Companies\ControllersLogic;
use App\Classes\Exceptions\CriteriaNotFulfilledException;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Addresses\Services\CreatesAddress;
use App\Classes\Modules\Addresses\Services\FetchesDistrict;
use App\Classes\Modules\Addresses\Services\UpdatesAddressMetadata;
use App\Classes\Modules\Addresses\Standards\Rules\CanCreateAddress;
use App\Classes\Modules\Addresses\DataTransferObjects\AddressObject;
use App\Classes\Modules\Companies\Services\FetchesCompany;
use App\Classes\Modules\Companies\Services\UpdatesCompanyEInvoiceInfo;
use App\Classes\Modules\Rules\DataTransferObjects\EInvoiceInfoDTO;
use App\Classes\Modules\Rules\Services\RuleEvaluator;
use App\Classes\Modules\Rules\Standards\Rules\CanProceedEInvoicePromptedRule;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class UpdateCompanyEInvoiceInfoLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => '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("<br>- ", $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([]);
}
}
@@ -0,0 +1,59 @@
<?php
namespace App\Classes\Modules\Companies\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Companies\Services\UpdatesCompanyEInvoiceRequest;
use App\Classes\Modules\Companies\Services\FetchesCompany;
use App\Classes\Modules\Rules\DataTransferObjects\EInvoiceRequestDTO;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class UpdateCompanyEInvoiceRequestLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => '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([]);
}
}
@@ -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));
}
}
@@ -0,0 +1,61 @@
<?php
namespace App\Classes\Modules\Companies\DataTransferObjects;
use App\Classes\General\Interfaces\DataTransferObject;
class UpdateCompanyDetailsDTO implements DataTransferObject
{
public int $id;
public string $name;
public string $debtor;
public string $reference;
public int $type;
public int $tin;
public int $msicCode;
public int $addressId;
public int $districtId;
public int $companyId;
public string $streetOne;
public string $streetTwo;
public int $postCode;
public function __construct(array $data)
{
$this->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,
];
}
}
@@ -0,0 +1,25 @@
<?php
namespace App\Classes\Modules\Companies\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Models\Company;
class UpdatesCompanyEInvoiceInfo extends AbstractUpdateRecord
{
/**
* @param Company $model
* @param string $tin
* @param string $msicCode
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(Company $model, string $tin, string $msicCode)
{
$model->tin = $tin;
$model->msic_code = $msicCode;
return $this->handler($model);
}
}
@@ -0,0 +1,27 @@
<?php
namespace App\Classes\Modules\Companies\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Models\Company;
class UpdatesCompanyEInvoiceRequest extends AbstractUpdateRecord
{
/**
* @param Company $model
* @param bool $eInvoice
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(Company $model, bool $eInvoice)
{
if (is_null($model->e_invoice) && is_null($model->e_invoice_requested_at)) {
$model->e_invoice_requested_at = now();
}
$model->e_invoice = $eInvoice;
return $this->handler($model);
}
}
@@ -0,0 +1,106 @@
<?php
namespace App\Classes\Modules\Exports\Services;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\BusinessType;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Company;
use Maatwebsite\Excel\Concerns\Exportable;
use Maatwebsite\Excel\Concerns\FromQuery;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
class ExportsEInvoiceDebtorSummary implements FromQuery, WithHeadings, WithHeadingRow, WithMapping, ShouldAutoSize
{
use Exportable;
public function headings(): array
{
return [
'Code',
'Need Tax INV?',
'Request Date',
'TIN NO.',
'DebtorControlAcc',
'ControlAccount',
'CompanyName',
'Desc2',
'DebtorType',
'DisplayTerm',
'CurrencyCode',
'RegisterNo',
'Address1',
'Address2',
'Address3',
'PostCode',
'DeliverAddr1',
'DeliverAddr2',
'DeliverAddr3',
'DeliverPostCode',
'EmailAddress',
'Attention',
'Phone1',
'Phone2',
'Fax1'
];
}
/**
* @return \Illuminate\Support\Collection|mixed
*/
public function query()
{
return Company::where(function($query){
// $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]);
})->orWhereHas('wallets', function($query){
return $query->whereHas('transactions');
});
});
}
/**
* @param Company $company
*
* @return array
*/
public function map($company): array
{
return [
'<<New>>', // Code
$company->e_invoice, // Need Tax INV?
$company->e_invoice_requested_at, // Request Date
$company->tin, // TIN NO.
'300-0000', // DebtorControlAcc
'300-0000', // ControlAccount
$company->name.' (PURCHASE)', // CompanyName
$company->reference, // Desc2
'', // DebtorType
'PIA', // DisplayTerm
'MYR', // CurrencyCode
'', // RegisterNo
'', // Address1
'', // Address2
'', // Address3
'', // PostCode
'', // DeliverAddr1
'', // DeliverAddr2
'', // DeliverAddr3
'', // DeliverPostCode
'', // EmailAddress
'', // Attention
'', // Phone1
'', // Phone2
'', // Fax1
];
}
}
@@ -94,7 +94,8 @@ class ExportsInvoiceTransactions implements FromQuery, WithHeadings, WithHeading
return [
'<<New>>',
$row->updated_at->format('m/d/Y H:m'),
// $row->updated_at->format('m/d/Y H:m'),
$row->updated_at->format('m/d/Y'),
$company->debtor,
$row->type === TransactionType::PAYMENT ? $booking->marking : $company->reference,
'',
@@ -129,7 +130,8 @@ class ExportsInvoiceTransactions implements FromQuery, WithHeadings, WithHeading
return [
'<<New>>',
Carbon::parse($row['created_at'])->format('m/d/Y H:m'),
// Carbon::parse($row['created_at'])->format('m/d/Y H:m'),
Carbon::parse($row['created_at'])->format('m/d/Y'),
$row['debtor_code'],
$row['type'] === ShippingTransactionType::PAYMENT ? $row['order_reference'] : $row['marking'],
'',
@@ -149,7 +151,8 @@ class ExportsInvoiceTransactions implements FromQuery, WithHeadings, WithHeading
return [
'Transaction Not Found',
$transaction->posting_date->format('m/d/Y H:m'),
// $transaction->posting_date->format('m/d/Y H:m'),
$transaction->posting_date->format('m/d/Y'),
$transaction->transaction_description.' - '.$transaction->transaction_description_2,
$statementTransactionOwner->system,
'',
@@ -72,28 +72,28 @@ class ExportsNullDebtors implements FromQuery, WithHeadings, WithHeadingRow, Wit
public function map($company): array
{
return [
'<<New>>',
'300-0000',
'300-0000',
$company->name.' (PURCHASE)',
$company->reference,
'',
'PIA',
'MYR',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',//EmailAddress
'',
'',
'',
''
'<<New>>', // Code
'300-0000', // DebtorControlAcc
'300-0000', // ControlAccount
$company->name.' (PURCHASE)', // CompanyName
$company->reference, // Desc2
'', // DebtorType
'PIA', // DisplayTerm
'MYR', // CurrencyCode
'', // RegisterNo
'', // Address1
'', // Address2
'', // Address3
'', // PostCode
'', // DeliverAddr1
'', // DeliverAddr2
'', // DeliverAddr3
'', // DeliverPostCode
'', // EmailAddress
'', // Attention
'', // Phone1
'', // Phone2
'', // Fax1
];
}
}
}
@@ -0,0 +1,62 @@
<?php
namespace App\Classes\Modules\Rules\ControllersLogic;
use App\Classes\Exceptions\CriteriaNotFulfilledException;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Rules\DataTransferObjects\CheckEInvoiceRuleDTO;
use App\Classes\Modules\Rules\Services\RuleEvaluator;
use App\Classes\Modules\Rules\Standards\Rules\CanProceedEInvoicePromptedRule;
use App\Classes\Modules\Rules\Standards\Rules\CanProceedTINRule;
use App\Http\Resources\RuleResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class CheckEInvoiceRuleLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Rule Check E-Invoice',
'message' => 'You have successfully passed all rules evaluated'
];
}
/** @var RuleEvaluator */
private $ruleEvaluator;
/**
* CheckEInvoiceRuleLogic 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 CheckEInvoiceRuleDTO($request->all());
$result = $this->ruleEvaluator->evaluate([
App()->make(CanProceedEInvoicePromptedRule::class),
App()->make(CanProceedTINRule::class),
], $dto);
if ($result->failed()) {
throw new CriteriaNotFulfilledException("- " . implode("<br>- ", $result->messages()));
}
return $this->resourceResponse(new RuleResource((object)$result));
}
}
@@ -0,0 +1,62 @@
<?php
namespace App\Classes\Modules\Rules\ControllersLogic;
use App\Classes\Exceptions\CriteriaNotFulfilledException;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Rules\DataTransferObjects\CheckPurchaseOrderRuleDTO;
use App\Classes\Modules\Rules\Services\RuleEvaluator;
use App\Classes\Modules\Rules\Standards\Rules\CanProceedEInvoicePromptedRule;
use App\Classes\Modules\Rules\Standards\Rules\CanProceedPurchaseOrderRule;
use App\Http\Resources\RuleResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class CheckPurchaseOrderRuleLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => '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("<br>- ", $result->messages()));
}
return $this->resourceResponse(new RuleResource((object)$result));
}
}
@@ -0,0 +1,22 @@
<?php
namespace App\Classes\Modules\Rules\DataTransferObjects;
use App\Classes\General\Interfaces\DataTransferObject;
class CheckEInvoiceRuleDTO implements DataTransferObject
{
public int $companyId;
public function __construct(array $data)
{
$this->companyId = $data['company_id'];
}
public function toArray(): array
{
return [
'company_id' => $this->companyId,
];
}
}
@@ -0,0 +1,25 @@
<?php
namespace App\Classes\Modules\Rules\DataTransferObjects;
use App\Classes\General\Interfaces\DataTransferObject;
class CheckPurchaseOrderRuleDTO implements DataTransferObject
{
public int $bookingId;
public int $companyId;
public function __construct(array $data)
{
$this->bookingId = $data['booking_id'];
$this->companyId = $data['company_id'];
}
public function toArray(): array
{
return [
'booking_id' => $this->bookingId,
'company_id' => $this->companyId,
];
}
}
@@ -0,0 +1,25 @@
<?php
namespace App\Classes\Modules\Rules\DataTransferObjects;
use App\Classes\General\Interfaces\DataTransferObject;
class ConfirmBookingDTO implements DataTransferObject
{
public int $bookingId;
public int $companyId;
public function __construct(array $data)
{
$this->bookingId = $data['booking_id'];
$this->companyId = $data['company_id'];
}
public function toArray(): array
{
return [
'booking_id' => $this->bookingId,
'company_id' => $this->companyId,
];
}
}
@@ -0,0 +1,40 @@
<?php
namespace App\Classes\Modules\Rules\DataTransferObjects;
use App\Classes\General\Interfaces\DataTransferObject;
class EInvoiceInfoDTO implements DataTransferObject
{
public int $tin;
public int $msicCode;
public int $districtId;
public int $companyId;
public string $streetOne;
public string $streetTwo;
public int $postCode;
public function __construct(array $data)
{
$this->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,
];
}
}
@@ -0,0 +1,25 @@
<?php
namespace App\Classes\Modules\Rules\DataTransferObjects;
use App\Classes\General\Interfaces\DataTransferObject;
class EInvoiceRequestDTO implements DataTransferObject
{
public bool $eInvoiceRequest;
public int $companyId;
public function __construct(array $data)
{
$this->eInvoiceRequest = $data['e_invoice_request'];
$this->companyId = $data['company_id'];
}
public function toArray(): array
{
return [
'e_invoice_request' => $this->eInvoiceRequest,
'company_id' => $this->companyId,
];
}
}
@@ -0,0 +1,44 @@
<?php
namespace App\Classes\Modules\Rules\Services;
use App\Classes\General\Abstracts\AbstractRule;
use App\Classes\General\Interfaces\DataTransferObject;
use App\Classes\Exceptions\AccessForbiddenException;
use App\Classes\Exceptions\CriteriaNotFulfilledException;
use App\Classes\Exceptions\RequestValidationException;
use App\Classes\ValueObjects\Response\RuleEvaluationResult;
class RuleEvaluator //For using AbstractRule
{
/**
* Evaluate multiple rules.
*
* @param AbstractRule[] $rules
* @param DataTransferObject|null $object
* @return RuleEvaluationResult
*/
public function evaluate(array $rules, ?DataTransferObject $object = null): RuleEvaluationResult
{
$messages = [];
$success = true;
foreach ($rules as $rule) {
try {
if (!$rule->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);
}
}
@@ -0,0 +1,56 @@
<?php
namespace App\Classes\Modules\Rules\Standards\Rules;
use App\Classes\Exceptions\CriteriaNotFulfilledException;
use App\Classes\General\Abstracts\AbstractRule;
use App\Classes\Modules\Companies\Services\FetchesCompany;
class CanProceedEInvoicePromptedRule extends AbstractRule
{
/** @var FetchesCompany */
private $fetchesCompany;
/**
* CanProceedEInvoicePromptedRule constructor.
* @param FetchesCompany $fetchesCompany
*/
public function __construct(FetchesCompany $fetchesCompany)
{
$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 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;
}
}
@@ -0,0 +1,96 @@
<?php
namespace App\Classes\Modules\Rules\Standards\Rules;
use App\Classes\Exceptions\CriteriaNotFulfilledException;
use App\Classes\General\Abstracts\AbstractRule;
use App\Classes\Modules\Bookings\Services\FetchesBooking;
use App\Classes\Modules\Companies\Services\FetchesCompany;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\SegmentNameConstants;
use App\Classes\ValueObjects\Constants\ServiceTypeNameConstants;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\ServiceType;
use Illuminate\Support\Facades\Log;
class CanProceedPurchaseOrderRule extends AbstractRule
{
/** @var FetchesBooking */
private $fetchesBooking;
/** @var FetchesCompany */
private $fetchesCompany;
/**
* CanProceedPurchaseOrderRule constructor.
* @param FetchesBooking $fetchesBooking
* @param FetchesCompany $fetchesCompany
*/
public function __construct(FetchesBooking $fetchesBooking, FetchesCompany $fetchesCompany)
{
$this->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;
}
}
@@ -0,0 +1,55 @@
<?php
namespace App\Classes\Modules\Rules\Standards\Rules;
use App\Classes\Exceptions\CriteriaNotFulfilledException;
use App\Classes\General\Abstracts\AbstractRule;
use App\Classes\Modules\Companies\Services\FetchesCompany;
class CanProceedTINRule extends AbstractRule
{
/** @var FetchesCompany */
private $fetchesCompany;
/**
* CanProceedTINRule constructor.
* @param FetchesCompany $fetchesCompany
*/
public function __construct(FetchesCompany $fetchesCompany)
{
$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 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;
}
}
@@ -0,0 +1,7 @@
<?php
namespace App\Classes\ValueObjects\Constants;
final class SegmentNameConstants {
public const MANUAL_PO_PERIODIC_1688 = "1688 Manual PO Periodic";
}
@@ -0,0 +1,9 @@
<?php
namespace App\Classes\ValueObjects\Constants;
final class ServiceTypeNameConstants {
public const PAYMENT_1688 = '1688 PAYMENT';
public const VIP_1688 = '1688 VIP';
}
@@ -0,0 +1,30 @@
<?php
namespace App\Classes\ValueObjects\Response;
class RuleEvaluationResult
{
public bool $success = true;
public array $messages = [];
public function __construct(bool $success = true, array $messages = [])
{
$this->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;
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Http\Controllers\Companies;
use App\Classes\Modules\Companies\ControllersLogic\FetchCompanyEInvoiceInfoLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class FetchCompanyEInvoiceInfoController
{
/**
* @param Request $request
* @param FetchCompanyEInvoiceInfoLogic $logic
* @return JsonResponse
*/
public function fetch(Request $request, FetchCompanyEInvoiceInfoLogic $logic): JsonResponse {
return $logic->execute($request);
}
}
@@ -0,0 +1,21 @@
<?php
namespace App\Http\Controllers\Companies;
use App\Classes\Modules\Companies\ControllersLogic\UpdateCompanyDetailsLogic;
use App\Http\Controllers\Controller;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class UpdateCompanyDetailsController extends Controller
{
/**
* @param Request $request
* @param UpdateCompanyDetailsLogic $logic
* @return JsonResponse
*/
public function update(Request $request, UpdateCompanyDetailsLogic $logic) : JsonResponse
{
return $logic->execute($request);
}
}
@@ -0,0 +1,29 @@
<?php
namespace App\Http\Controllers\Companies;
use App\Classes\Modules\Companies\ControllersLogic\UpdateCompanyEInvoiceInfoLogic;
use App\Classes\Modules\Companies\ControllersLogic\UpdateCompanyEInvoiceRequestLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class UpdateCompanyEInvoiceInfoController
{
/**
* @param Request $request
* @param UpdateCompanyEInvoiceInfoLogic $logic
* @return JsonResponse
*/
public function updateInfo(Request $request, UpdateCompanyEInvoiceInfoLogic $logic): JsonResponse {
return $logic->execute($request);
}
/**
* @param Request $request
* @param UpdateCompanyEInvoiceRequestLogic $logic
* @return JsonResponse
*/
public function updateRequest(Request $request, UpdateCompanyEInvoiceRequestLogic $logic): JsonResponse {
return $logic->execute($request);
}
}
@@ -13,15 +13,16 @@ use App\Classes\Modules\Exports\Services\ExportsNullDebtors;
use App\Classes\Modules\Exports\Services\ExportsPaymentTransactions;
use App\Classes\Modules\Exports\Services\ExportsWalletTransactions;
use App\Classes\Modules\Exports\Services\ExportsInvoiceTransactions;
use App\Classes\Modules\Exports\Services\ExportsReceiptTransactions;
use App\Classes\Modules\Exports\Services\ExportsImportedReceiptMappeds;
use App\Classes\Modules\Exports\Services\ExportsWhiteFormTransactions;
use App\Classes\Modules\Exports\Services\ExportsImportedInvoiceMappeds;
use App\Classes\Modules\Exports\Services\ExportsEInvoiceDebtorSummary;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Maatwebsite\Excel\Excel;
use App\Classes\Modules\Exports\Services\ExportsImportedInvoiceMappeds;
use App\Models\TransactionMappingLog;
use App\Classes\Modules\Exports\Services\ExportsReceiptTransactions;
use App\Classes\Modules\Exports\Services\ExportsImportedReceiptMappeds;
use App\Classes\Modules\Exports\Services\ExportsWhiteFormTransactions;
use Illuminate\Support\Facades\Storage;
use App\Classes\General\AWSS3Helper;
use Illuminate\Support\Carbon;
@@ -241,5 +242,17 @@ class ExportCustomersToExcelController
return $response;
}
}
}
public function eInvoiceDebtorSummary(ExportsEInvoiceDebtorSummary $exportsEInvoiceDebtorSummary, Request $request){
$exportFileName = 'EINV_DEBTOR_SUMMARY.xls';
$filesystemDriver = Storage::getDefaultDriver();
if($filesystemDriver === 's3'){
return response([ 'src' => AWSS3Helper::S3Exportable($exportFileName, $exportsEInvoiceDebtorSummary) ]);
}
else{
$response = $exportsEInvoiceDebtorSummary->download($exportFileName, Excel::XLS, ['Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']);
ob_end_clean();
return $response;
}
}
}
@@ -0,0 +1,29 @@
<?php
namespace App\Http\Controllers\Rules;
use App\Classes\Modules\Rules\ControllersLogic\CheckEInvoiceRuleLogic;
use App\Classes\Modules\Rules\ControllersLogic\CheckPurchaseOrderRuleLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class CheckRuleController
{
/**
* @param Request $request
* @param CheckEInvoiceRuleLogic $logic
* @return JsonResponse
*/
public function checkEInvoiceRule(Request $request, CheckEInvoiceRuleLogic $logic): JsonResponse {
return $logic->execute($request);
}
/**
* @param Request $request
* @param CheckPurchaseOrderRuleLogic $logic
* @return JsonResponse
*/
public function checkPurchaseOrderRule(Request $request, CheckPurchaseOrderRuleLogic $logic): JsonResponse {
return $logic->execute($request);
}
}
+4
View File
@@ -38,11 +38,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() && 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(), []),
@@ -0,0 +1,31 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class EInvoiceInfoResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'id' => $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,
];
}
}
+22
View File
@@ -0,0 +1,22 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class RuleResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'isPassed' => $this->success,
'messages' => $this->messages,
];
}
}
@@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddEinvoiceToAddressesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('addresses', function (Blueprint $table) {
$table->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');
});
}
}
@@ -0,0 +1,38 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddTinToCompaniesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('companies', function (Blueprint $table) {
$table->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');
});
}
}
@@ -0,0 +1,213 @@
<template>
<div class="row p-t-25 text-left">
<div class="col bg-white padding-40 b-rad-lg">
<div class="row" v-if="step === 1">
<div class="col">
<div class="row">
<div class="col">
<div class="row m-b-15">
<div class="col text-danger">
Please check carefully, you will not be able to edit this after confirm
</div>
</div>
<div class="row m-b-15">
<div class="col-6 p-r-5">
<validation-wrapper-component :validator="$v.parameters.tin">
<label>TIN</label>
<input class="form-control" name="tin" v-model="parameters.tin">
</validation-wrapper-component>
</div>
<div class="col-6 p-l-5">
<validation-wrapper-component :validator="$v.parameters.msic_code" v-money="integer">
<label>
MSIC Code
<a href="https://sdk.myinvois.hasil.gov.my/codes/msic-codes/" target="_blank" rel="noopener noreferrer">
(View List)
</a>
</label>
<input class="form-control" name="msic_code" v-model="parameters.msic_code">
</validation-wrapper-component>
</div>
</div>
<div class="row m-b-15">
<div class="col">
<validation-wrapper-component :validator="$v.parameters.street_one">
<label>Address Line 1</label>
<input class="form-control" name="street_one" v-model="parameters.street_one">
</validation-wrapper-component>
</div>
</div>
<div class="row m-b-15">
<div class="col">
<validation-wrapper-component :validator="$v.parameters.street_two">
<label>Address Line 2</label>
<input class="form-control" name="street_two" v-model="parameters.street_two">
</validation-wrapper-component>
</div>
</div>
<div class="row m-b-15">
<div class="col-7 p-r-5">
<validation-wrapper-component selectable :validator="$v.parameters.district_id">
<label>District</label>
<selectable-component :endpoint="route('api.address.district.list')" section="districtListSection" valueColumn="id" :labelColumn="['city']" v-model="parameters.district_id"></selectable-component>
</validation-wrapper-component>
</div>
<div class="col-5 p-l-5">
<validation-wrapper-component :validator="$v.parameters.post_code" v-money="integer">
<label>Post Code</label>
<input class="form-control" name="post_code" v-model="parameters.post_code">
</validation-wrapper-component>
</div>
</div>
</div>
</div>
<div class="row m-b-15">
<div class="col">
<div class="row">
<div class="col text-right">
<button type="button"
class="btn btn-success btn-block b-rad-none"
@click="updateStep(2)">Update E-Invoice Info</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row" v-if="step === 2">
<div class="col">
<div class="row m-b-15">
<div class="col">
<div class="row m-b-15">
<div class="col text-danger">
Please check carefully, you will not be able to edit this after confirm
</div>
</div>
<div class="row">
<div class="col">
<div class="padding-15 bg-master-lightest">
<p class="muted">TIN</p>
<p class="m-b-0">{{parameters.tin}}</p>
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="padding-15 bg-master-lightest">
<p class="muted">MSIC Code</p>
<p class="m-b-0">{{parameters.msic_code}}</p>
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="padding-15 bg-master-lightest">
<p class="muted">Billing Address</p>
<p class="m-b-0">{{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}}</p>
</div>
</div>
</div>
</div>
</div>
<div class="row m-b-15">
<div class="col">
<div class="row">
<div class="col-auto p-r-5">
<button type="button" class="btn bg-master-lighter b-rad-none" @click="updateStep(1)">Edit E-Invoice Info</button>
</div>
<div class="col p-l-0">
<button type="button" class="btn btn-success btn-block b-rad-none" @click="submitForm()">Confirm E-Invoice Info</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import ModalFormHandler from '../../../general/mixins/modalFormHandler';
import { required, helpers } from 'vuelidate/lib/validators'
function notZero(value) {
return value !== 0 && value !== '0' && value !== null && value !== undefined
}
export default {
props: {
id: {
type: Number,
required: true
},
},
watch: {
'id': function() {
this.parameters.company_id = this.id;
},
'eInvoiceData': function() {
this.resetForm();
this.parameters = {
company_id: this.id,
street_one: this.eInvoiceData.street_one,
street_two: this.eInvoiceData.street_two,
district_id: this.eInvoiceData.district.id,
post_code: this.eInvoiceData.post_code,
tin: this.eInvoiceData.tin,
msic_code: this.eInvoiceData.msic_code,
}
}
},
computed: {
districts () {
return this.$store.getters.getSelectableList('original_districtListSection');
}
},
data() {
return {
step: 1,
parameters : {
company_id: this.id,
street_one: '',
street_two: '',
district_id: '',
post_code: 0,
tin: '',
msic_code: 0,
}
}
},
validations: {
parameters: {
street_one: { required },
street_two: {},
district_id: { required },
post_code: {
required,
notZero
},
tin: { required },
msic_code: {
required,
notZero
}
}
},
methods:{
updateStep(step){
if(step === 2){
if(!this.validate()){ return; }
}
this.step = step
},
submitForm(){
this.submit((this.route('api.company.einvoice.info.update')), 'post', this.section, true, true);
},
successHandler(response){
this.$emit('eInvoiceInfoUpdated', response.payload.data);
this.closeModal();
}
},
mixins: [ModalFormHandler],
}
</script>
@@ -0,0 +1,68 @@
<template>
<div class="row p-t-20 text-left">
<div class="col bg-white padding-30 b-rad-lg">
<div class="row">
<div class="col text-center">
<h3>E-Invoice Info</h3>
</div>
</div>
<div class="row" v-if="eInvoiceData && eInvoiceData.district">
<div class="col">
<div class="padding-15 bg-master-lightest m-b-10">
<p class="muted">TIN</p>
<p class="m-b-0">{{ eInvoiceData.tin }}</p>
</div>
<div class="padding-15 bg-master-lightest m-b-10">
<p class="muted">MSIC Code</p>
<p class="m-b-0">{{ eInvoiceData.msic_code }}</p>
</div>
<div class="padding-15 bg-master-lightest">
<p class="muted">Billing Address</p>
<p class="mb-0">
<a class="ml-2" data-toggle="collapse" href="#billingDetails" role="button" aria-expanded="false" aria-controls="billingDetails">
{{eInvoiceData.street_one}} {{eInvoiceData.street_two}}, {{eInvoiceData.district.name}}, {{eInvoiceData.post_code}} {{eInvoiceData.state.name}}, {{eInvoiceData.country.name}}
</a>
</p>
<div class="collapse mt-2" id="billingDetails">
<ul class="list-unstyled mb-0">
<li><strong>Street 1:</strong> {{eInvoiceData.street_one}}</li>
<li><strong>Street 2:</strong> {{eInvoiceData.street_two}}</li>
<li><strong>District:</strong> {{eInvoiceData.district.name}}</li>
<li><strong>Postcode:</strong> {{eInvoiceData.post_code}}</li>
<li><strong>State:</strong> {{eInvoiceData.state.name}}</li>
<li><strong>Country:</strong> {{eInvoiceData.country.name}}</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
companyId: {
type: Number,
required: true
}
},
data(){
return {
eInvoiceData: null,
}
},
created(){
this.fetchData();
},
methods: {
fetchData(){
this.submit(route('api.company.einvoice.info', this.companyId), 'get', 'eInvoiceInfoViewOnlySection', false, true)
},
successHandler(response){
this.eInvoiceData = response.payload.data;
}
}
}
</script>
@@ -96,7 +96,7 @@
<p class="no-margin" v-if="serviceType.id === 1">The recipient can expect to receive the transfer within <span class="text-success bold">3-5 working days</span>. Explore our BANK TRANSFER (SAVER) option for a better rate!</p>
<p class="no-margin" v-if="serviceType.id === 3">Enjoy a <span class="bold text-underline">better rate</span> with this option! The recipient will receive the transfer after <span class="text-success bold">5-7 working days</span>.</p>
<p class="no-margin" v-if="serviceType.id === 12">You can request Pay-on-Behalf via Alipay for platforms like Taobao, 1688, Pinduoduo, or any Alipay-supported platform. <br><span class="text-danger">Please use Alipay account "2766384544@QQ.com" to apply for Daifu. This account may change, so always confirm the latest Alipay account before placing an order.</span></p>
<p class="no-margin text-danger" v-if="[1, 3].includes(serviceType.id)">Please ensure is a PERSONAL bank account details. Company bank account details only allow to use as E2E service.</p>
<p class="no-margin text-danger" v-if="[1, 3].includes(serviceType.id) && serviceType.selectedCurrency.id !== 3">Please ensure is a PERSONAL bank account details. Company bank account details only allow to use as E2E service.</p>
<p class="no-margin text-danger" v-if="serviceType.id === 5">Cancellation of E2E service are strictly NO refund on the 2% transfer fee charge.</p>
</div>
</div>
File diff suppressed because one or more lines are too long
@@ -111,7 +111,11 @@
section: {
type: String,
required: true
}
},
companyId: {
type: Number,
required: true
},
},
data(){
return {
@@ -121,14 +125,16 @@
amount: this.amount,
bank_code: this.bank_code,
voucher_code: this.calculation.voucher_code,
voucher_discount_amount: this.calculation.voucher_discount_amount
voucher_discount_amount: this.calculation.voucher_discount_amount,
booking_id: this.id,
company_id: this.companyId,
}
}
},
methods: {
submitForm(){
this.isLoading = true;
this.submit(route('api.booking.payment.create', this.id), 'post', this.section, false, false);
this.submit(route('api.booking.payment.create', this.id), 'post', this.section, false, true);
},
successHandler(response){
if (response.payload.data.payment_method === 5) {
@@ -99,7 +99,7 @@
<div class="col-1 p-r-25" >
<i class="fa fa-exchange bg-white text-complete fs-16 p-t-5 p-b-5" style="margin-left: -4px;"></i>
</div>
<div class="col p-l-0 fs-14 bold lh-20 text-complete">1 MYR = {{(Math.round((this.calculation.rate + Number.EPSILON) * 100000) / 100000).toFixed(5)}} RMB</div>
<div class="col p-l-0 fs-14 bold lh-20 text-complete">1 MYR = {{(Math.round((this.calculation.rate + Number.EPSILON) * 100000) / 100000).toFixed(5)}} {{ this.calculation.foreign_currency }}</div>
</div>
</div>
</div>
@@ -180,6 +180,21 @@
{{booking.company.contact ? booking.company.contact.phone: ''}}
</p>
</div>
<div class="col-auto">
<div class="font-heading fs-10 muted all-caps">TIN</div>
<p class="m-b-0 fs-12">
<span :class="[{'text-danger bold': !booking.company.e_invoice && !booking.company.tin }]">
{{ booking.company.e_invoice
? (booking.company.tin ? booking.company.tin : 'INCOMPLETE E-INVOICE INFO')
: 'NOT PROVIDED' }}
</span><br />
<a v-if="booking.company.e_invoice && booking.company.tin" class="pointer requestModal" data-type="eInvoiceInfo">View E-Invoice Info
</a>
</p>
<modal-component class="animate__animated animate__fast animate__fadeIn" v-if="booking.company.tin" styleType="fill-in" type="eInvoiceInfo">
<e-invoice-info-component :company-id="booking.company.id"></e-invoice-info-component>
</modal-component>
</div>
</div>
</div>
</div>
@@ -313,7 +328,8 @@
</div>
</div>
<div class="col-12 col-sm-12 col-md-5 mt-3 mt-sm-0">
<booking-payment-quotation-component :data="booking" :section="section"></booking-payment-quotation-component>
<!-- <booking-payment-quotation-component :data="booking" :section="section"></booking-payment-quotation-component> -->
<booking-payment-quotation-v2-component :data="booking" :section="section"></booking-payment-quotation-v2-component>
<div class="row m-t-20" v-if="booking.payment_attempts.length">
<div class="col">
<div class="row m-b-10">
@@ -14,7 +14,8 @@
<div class="row">
<div class="col">
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="changeCustomerName">
<change-customer-name-form-component :section="'customerProfileSection'" :data="item"></change-customer-name-form-component>
<!-- <change-customer-name-form-component :section="'customerProfileSection'" :data="item"></change-customer-name-form-component> -->
<change-customer-company-details-form-component :section="'customerProfileSection'" :data="item"></change-customer-company-details-form-component>
</modal-component>
<div class="font-heading fs-14 bold">
{{item.name}}
@@ -0,0 +1,147 @@
<template>
<div class="row" style="width: 450px; margin: auto;" @keyup.enter="submitForm">
<div class="col bg-white padding-40 b-rad-lg">
<div class="row m-b-10">
<div class="col text-center">
<h3>Edit Company Details</h3>
</div>
</div>
<div class="row m-b-15">
<div class="col">
<validation-wrapper-component :validator="$v.parameters.name">
<label class="text-primary">Name</label>
<input class="form-control" v-model="parameters.name">
</validation-wrapper-component>
</div>
</div>
<div class="row m-b-15">
<div class="col">
<validation-wrapper-component :validator="$v.parameters.debtor">
<label class="text-primary">Debtor Code</label>
<input class="form-control" v-model="parameters.debtor">
</validation-wrapper-component>
</div>
</div>
<div class="row m-b-5" v-if="data.e_invoice && data.tin">
<div class="col">
E-Invoice Info
<div class="row m-b-15">
<div class="col-6 p-r-5">
<validation-wrapper-component :validator="$v.parameters.tin">
<label class="text-primary">TIN</label>
<input class="form-control" v-model="parameters.tin">
</validation-wrapper-component>
</div>
<div class="col-6 p-l-5">
<validation-wrapper-component :validator="$v.parameters.msic_code">
<label class="text-primary">
MSIC Code
<a href="https://sdk.myinvois.hasil.gov.my/codes/msic-codes/" target="_blank" rel="noopener noreferrer">
(View List)
</a>
</label>
<input class="form-control" name="msic_code" v-model="parameters.msic_code">
</validation-wrapper-component>
</div>
</div>
<div class="row m-b-15">
<div class="col">
<validation-wrapper-component :validator="$v.parameters.street_one">
<label class="text-primary">Address Line 1</label>
<input class="form-control" name="street_one" v-model="parameters.street_one">
</validation-wrapper-component>
</div>
</div>
<div class="row m-b-15">
<div class="col">
<validation-wrapper-component :validator="$v.parameters.street_two">
<label class="text-primary">Address Line 2</label>
<input class="form-control" name="street_two" v-model="parameters.street_two">
</validation-wrapper-component>
</div>
</div>
<div class="row m-b-15">
<div class="col-7 p-r-5">
<validation-wrapper-component selectable :validator="$v.parameters.district_id">
<label class="text-primary">District</label>
<selectable-component :endpoint="route('api.address.district.list')" section="districtListSection" valueColumn="id" :labelColumn="['city']" v-model="parameters.district_id"></selectable-component>
</validation-wrapper-component>
</div>
<div class="col-5 p-l-5">
<validation-wrapper-component :validator="$v.parameters.post_code">
<label class="text-primary">Post Code</label>
<input class="form-control" v-model="parameters.post_code">
</validation-wrapper-component>
</div>
</div>
</div>
</div>
<div class="row m-t-15">
<div class="col-auto p-r-5">
<div class="btn btn-lg btn-default b-rad-none" data-dismiss="modal">Cancel</div>
</div>
<div class="col p-l-5">
<div class="btn btn-primary w-100 btn-lg" @click="submitForm">Confirm</div>
</div>
</div>
</div>
</div>
</template>
<script>
import modalFormHandler from '../../../general/mixins/modalFormHandler';
import { required, minLength } from "vuelidate/lib/validators";
export default {
validations: {
parameters: {
name: {
required,
},
debtor: {},
tin: {},
msic_code: {},
address_id: {},
street_one: {},
street_two: {},
district_id: {},
post_code: {},
}
},
created() {
if (this.data) {
if (this.data.address_einvoice) {
this.parameters.address_id = this.data.address_einvoice.id;
this.parameters.street_one = this.data.address_einvoice.street_one;
this.parameters.street_two = this.data.address_einvoice.street_two;
this.parameters.district_id = this.data.address_einvoice.district.id;
this.parameters.post_code = this.data.address_einvoice.post_code;
}
}
},
watch: {
'data': function(newData) {
if (newData && newData.address_einvoice) {
this.parameters.address_id = newData.address_einvoice.id;
this.parameters.street_one = newData.address_einvoice.street_one;
this.parameters.street_two = newData.address_einvoice.street_two;
this.parameters.district_id = newData.address_einvoice.district.id;
this.parameters.post_code = newData.address_einvoice.post_code;
}
}
},
methods: {
successHandler(response) {
// window.location.replace(this.route('customers', response.payload.data.reference));
this.$emit('e-invoice-info', this.parameters);
this.closeModal();
},
submitForm() {
this.submit(this.route('api.company.update.details', this.data.id), 'put', this.section, true, true)
}
},
mixins: [modalFormHandler]
}
</script>
@@ -0,0 +1,65 @@
<template>
<div class="row">
<div class="col bg-white padding-40 b-rad-lg">
<loading-component style="height: 300px; top: 0;" key="1" color="success" v-show="isLoading" />
<div class="row justify-content-center" v-show="!isLoading">
<div class="col">
<div class="row m-b-20">
<div class="col">
<h3 class="all-caps">Do you need E-Invoice?</h3>
<div class="fs-11">You won't be able to request one after clicking 'No'.</div>
</div>
</div>
<div class="row">
<div class="col p-r-5">
<div class="btn btn-sm btn-block b-rad-none btn-danger" @click="handleChoice(false)">No</div>
</div>
<div class="col p-l-5">
<div class="btn btn-sm btn-block b-rad-none btn-success" @click="handleChoice(true)">Yes</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import componentHandler from '../../../general/mixins/componentHandler';
import ModalFormHandler from '../../../general/mixins/modalFormHandler';
export default {
props: {
section: {
type: String,
required: false
},
companyId: {
type: Number,
required: true
}
},
data() {
return {
parameters : {
company_id: this.companyId,
}
}
},
methods: {
handleChoice(choice) {
this.parameters.e_invoice_request = choice ? true : false;
this.$emit('choice-made', { choice, params: this.parameters });
this.submitForm();
},
submitForm() {
return this.submit(route('api.company.einvoice.request.update'), 'post', this.section, true, true);
},
successHandler() {
this.closeModal();
this.formHandler();
}
},
mixins: [componentHandler, ModalFormHandler]
}
</script>
+3 -3
View File
@@ -20,7 +20,7 @@ export default {
if (!success) {
this.openModal();
errorNotification ? this.$store.dispatch('createNotification', { title: response.title, message: response.message, type: 'error' }) : null;
this.errorHandler(response, statusCode); return;
this.errorHandler(response, statusCode, section); return;
}
successNotification ? this.$store.dispatch('createNotification', { title: response.title, message: response.message, type: 'success' }) : null;
@@ -29,7 +29,7 @@ export default {
link.href = window.URL.createObjectURL(response);
link.download = fileName.trim();
link.click();
this.successHandler(response)
this.successHandler(response, section)
});
} else {
response.json().then(response => {
@@ -41,7 +41,7 @@ export default {
}
successNotification ? this.$store.dispatch('createNotification', { title: response.title, message: response.message, type: 'success' }) : null;
this.successHandler(response, section);
this.successHandler(response, section)
});
@@ -66,9 +66,34 @@
<show-white-form-transactions-component></show-white-form-transactions-component>
</div>
<div class="col-md-6">
<div class="card mb-3">
<div class="card-body d-flex justify-content-between align-items-center">
<div>
<span>nullDebtor.xls</span>
<p class="text-muted mb-0">New Debtors Report from <a href="{{route('settings')}}" target="_blank">settings page</a></p>
</div>
<open-link-in-new-tab-component custom-class="btn btn-primary" :url="route('newDebtor.export')">
<i class="fa fa-download"></i> Download
</open-link-in-new-tab-component>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="card mb-3">
<div class="card-body d-flex justify-content-between align-items-center">
<div>
<span>EINV_DEBTOR_SUMMARY.xls</span>
<p class="text-muted mb-0">e-Invoice Debtor Summary Report</p>
</div>
<open-link-in-new-tab-component custom-class="btn btn-primary" :url="route('eInvoiceDebtorSummary.export')">
<i class="fa fa-download"></i> Download
</open-link-in-new-tab-component>
</div>
</div>
</div>
</div>
</div>
<!-- Group 2: XXX Downloads -->
+1
View File
@@ -94,6 +94,7 @@ Route::group(['middleware' => 'api', 'prefix' => 'v1', 'as' => 'api.'], function
require __DIR__ . '/questionnaires.php';
require __DIR__ . '/admin_workflow.php';
require __DIR__ . '/rule.php';
// require __DIR__ . '/rate.php';
// require __DIR__ . '/receipt.php';
+7
View File
@@ -1,5 +1,8 @@
<?php
use App\Http\Controllers\Companies\FetchCompanyEInvoiceInfoController;
use App\Http\Controllers\Companies\UpdateCompanyDetailsController;
use App\Http\Controllers\Companies\UpdateCompanyEInvoiceInfoController;
use Illuminate\Support\Facades\Route;
Route::group(['prefix' => 'company', 'as' => 'company.', 'namespace' => 'Companies'], function () {
@@ -37,4 +40,8 @@ Route::group(['prefix' => 'company', 'as' => 'company.', 'namespace' => 'Compani
Route::put('/{document_id}/approval/{status}', 'ApproveIdentificationDocumentController@approve')->where('status', 'approve|reject')->name('approval');
});
Route::put('/details/update/{id}', [UpdateCompanyDetailsController::class, 'update'])->name('update.details');
Route::get('/e-invoice/info/{id}', [FetchCompanyEInvoiceInfoController::class, 'fetch'])->name('einvoice.info');
Route::post('/e-invoice/info/update', [UpdateCompanyEInvoiceInfoController::class, 'updateInfo'])->name('einvoice.info.update');
Route::post('/e-invoice/request/update', [UpdateCompanyEInvoiceInfoController::class, 'updateRequest'])->name('einvoice.request.update');
});
+11
View File
@@ -0,0 +1,11 @@
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\Rules\CheckRuleController;
Route::prefix('rule')
->as('rule.')
->group(function () {
Route::post('/check/eInvoice', [CheckRuleController::class, 'checkEInvoiceRule'])->name('check.einvoice');
Route::post('/check/purchase-order', [CheckRuleController::class, 'checkPurchaseOrderRule'])->name('check.purchase.order');
});
+2 -1
View File
@@ -330,6 +330,7 @@ Route::get('/export/analytic/booking', 'Exports\ExportAnalyticToExcelController@
Route::get('/export/analytic/bills', 'Exports\ExportAnalyticToExcelController@billingData')->name('billingData.export');;
Route::get('/export/customers/leads', 'Exports\ExportCustomersToExcelController@leadsData')->name('leads.export');
route::get('/export/excel/{id}', 'Exports\ExportCustomersToExcelController@exportCurrencyVendorOrder')->name('group.excel');
Route::get('/export/einv-debtor/f614e339d7058904a831aad742e24d55', 'Exports\ExportCustomersToExcelController@eInvoiceDebtorSummary')->name('eInvoiceDebtorSummary.export');
Route::get('/products', function (\App\Classes\Modules\Exports\Services\ExportsProducts $exportsProducts) {
$bookings = Booking::where(function($query){
@@ -920,7 +921,7 @@ Route::get('/statements/{account}/transactions', function ($account) {
})->name('statements.account.transactions');
Route::get('/statements/{statement}', [BankStatementController::class, 'show'])->name('statements.show');
Route::get('/statements/mapping/rerun', [BankStatementController::class, 'rerun'])->name('statements.rerun');
Route::get('/statements/{statement}/download', 'StatementController@download')->name('statements.download');
// Route::get('/statements/{statement}/download', 'StatementController@download')->name('statements.download');
Route::get('/bank-record', 'Imports\ImportBankRecordController@import');
Route::get('/po/outsource/check', function(){