Merge branch 'dillon/51-vue-polling-experimental-2' into dillon/34-jenkins-vapor

This commit is contained in:
Dillon Ngo
2023-12-30 18:48:00 +08:00
69 changed files with 2047 additions and 486 deletions
@@ -0,0 +1,23 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class IsMappedFalseOrMappedButStatusIn implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->where(function($q) use ($value) {
$q->whereDoesntHave('owners');
$q->orwhereDoesntHave('owner_status');
});
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class OrderByIdDesc implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->orderBy('id', 'desc');
}
}
@@ -0,0 +1,19 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class RequestSignature implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->where('request_signature', $value);
}
}
@@ -0,0 +1,18 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class ResultNotNull implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->whereNotNull('result');
}
}
@@ -0,0 +1,18 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class StatementTransactionPostingEnd implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->whereDate('posting_date', '<=', date('Y-m-d',strtotime($value)));
}
}
@@ -0,0 +1,18 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class StatementTransactionPostingStart implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->whereDate('posting_date', '>=', date('Y-m-d',strtotime($value)));
}
}
@@ -0,0 +1,22 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class WhereHasOwnersAndNotNull implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->whereHas('owners', function ($query) use ($value) {
return $query->whereNotNull($value);
});
}
}
@@ -0,0 +1,22 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class WhereHasOwnersAndNull implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->whereHas('owners', function ($query) use ($value) {
return $query->whereNull($value);
});
}
}
@@ -62,7 +62,7 @@ class GroupApproveStatementTransactionLogic extends AbstractControllerLogic
$statementTransactions = $this->listsBankStatementTransactions->execute($filters);
foreach ($statementTransactions as $statementTransaction) {
$owners = $statementTransaction->owners;
$owners = $statementTransaction->owners()->where('status', ApprovalStatus::PENDING_VERIFICATION)->get();
if (count($owners)) {
$this->updatesBankStatementTransactionOwnerStatus->execute($owners->first(), ApprovalStatus::APPROVED);
@@ -157,7 +157,7 @@ class UpdateBankStatementDetailLogic extends AbstractControllerLogic
'owner_reference' => $owner_reference,
];
return $bankStatementTransaction->owners()->firstOrCreate($ownerData);
return $bankStatementTransaction->owners()->where('status','<>',ApprovalStatus::REJECTED)->firstOrCreate($ownerData);
}
private function editAccountMapped(StatementTransactionOwner $owner){
@@ -28,6 +28,7 @@ class CreateBankStatementTransactionOwnersProcessor
// $transactions = StatementTransaction::whereDoesntHave('owners')->where('amount', '<', 0)->get();
foreach ($transactions as $transaction) {
$mapped = false;
$keywords = array_filter(explode(" ", $transaction->transaction_description . " " . $transaction->transaction_description_2));
if($transaction->amount > 0){
@@ -36,7 +37,7 @@ class CreateBankStatementTransactionOwnersProcessor
$creditTransactions = $this->getTransactions($transaction->posting_date, $transaction->amount, TransactionType::PAYMENT, Booking::class, PaymentMethodType::WALLET, [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED], $keywords);
foreach ($creditTransactions as $creditTransaction) {
$isArray = is_array($creditTransaction);
$transaction->owners()->firstOrCreate([
$data = $transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::SALES,
'system' => 'EXCHANGE',
'owner_type' => Transaction::class,
@@ -45,12 +46,11 @@ class CreateBankStatementTransactionOwnersProcessor
]);
}
// Shipping Portal Sales
$creditTransactions = $this->getTransactionsFromShippingPortal($transaction->amount, $this->getDateRange($transaction->posting_date, 1), 2, PaymentMethodType::WALLET);
$creditTransactions = $this->getTransactionsFromShippingPortal($transaction->amount, $this->getDateRange($transaction->posting_date, 1), [2], PaymentMethodType::WALLET);
foreach ($creditTransactions as $creditTransaction) {
if($creditTransaction['owner_type'] === Wallet::class) continue;
$transaction->owners()->firstOrCreate([
$data = $transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::SALES,
'system' => 'SHIPPING_PORTAL',
'owner_type' => $creditTransaction['owner_type'],
@@ -63,7 +63,7 @@ class CreateBankStatementTransactionOwnersProcessor
$creditTransactions = $this->getTransactions($transaction->posting_date, $transaction->amount, TransactionType::TOP_UP, Wallet::class, null, [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED], $keywords);
foreach ($creditTransactions as $creditTransaction) {
$isArray = is_array($creditTransaction);
$transaction->owners()->firstOrCreate([
$data = $transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::WALLET_TOP_UP,
'system' => 'EXCHANGE',
'owner_type' => Transaction::class,
@@ -72,9 +72,9 @@ class CreateBankStatementTransactionOwnersProcessor
]);
}
$creditTransactions = $this->getTransactionsFromShippingPortal($transaction->amount, $this->getDateRange($transaction->posting_date, 1), 5, null);
$creditTransactions = $this->getTransactionsFromShippingPortal($transaction->amount, $this->getDateRange($transaction->posting_date, 1), [5,15], null);
foreach ($creditTransactions as $creditTransaction) {
$transaction->owners()->firstOrCreate([
$data = $transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::WALLET_TOP_UP,
'system' => 'SHIPPING_PORTAL',
'owner_type' => $creditTransaction['owner_type'],
@@ -85,7 +85,7 @@ class CreateBankStatementTransactionOwnersProcessor
// fpx charge refund
if($transaction->transaction_description === 'DUITNOW S/CHRG REFUND'){
$transaction->owners()->firstOrCreate([
$data = $transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::FPX_CHARGE_REFUND
]);
}
@@ -94,7 +94,7 @@ class CreateBankStatementTransactionOwnersProcessor
// INTERNAL_BANK_TRANSFER_IN
if(str_contains($transaction->transaction_description_2, 'CIEF WORLDWIDE')){
$transaction->owners()->firstOrCreate([
$data = $transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::INTERNAL_BANK_TRANSFER_IN
]);
}
@@ -119,7 +119,7 @@ class CreateBankStatementTransactionOwnersProcessor
->where('amount', '<=', (($transaction->amount * -1) + 0.01))->whereDate('created_at', '>=', $paymentDateStart)->whereDate('created_at', '<=', $paymentDateEnd)->get();
foreach ($debitTransactions as $debitTransaction) {
$transaction->owners()->firstOrCreate([
$data = $transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::SUPPLIER_PAYMENT,
'system' => 'EXCHANGE',
'owner_type' => Group::class,
@@ -135,7 +135,7 @@ class CreateBankStatementTransactionOwnersProcessor
$debitTransactions = $this->getTransactions($transaction->posting_date, $transaction->amount, TransactionType::DEBIT_NOTE, Wallet::class, null, [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED], $keywords);
foreach ($debitTransactions as $debitTransaction) {
$isArray = is_array($creditTransaction);
$transaction->owners()->firstOrCreate([
$data = $transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::WALLET_WITHDRAWAL,
'system' => 'EXCHANGE',
'owner_type' => Transaction::class,
@@ -148,50 +148,52 @@ class CreateBankStatementTransactionOwnersProcessor
// STATUTORY
if(str_contains($transaction->transaction_description_2, 'PEMBANGUNAN SUMBER') || str_contains($transaction->transaction_description_2, 'HASIL') || str_contains($transaction->transaction_description_2, 'PERTUBUHAN KESELAMAT') || str_contains($transaction->transaction_description_2, 'KUMPULAN WANG SIMPAN')){
$transaction->owners()->firstOrCreate([
$data = $transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::STATUTORY
]);
}
// FPX_CHARGE
if($transaction->transaction_description === 'DR DUITNOW S/CHRG' || str_contains($transaction->transaction_description, 'Manual FPX') || str_contains($transaction->transaction_description, 'CMS - DR FPX CHG')){
$transaction->owners()->firstOrCreate([
$data = $transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::FPX_CHARGE
]);
}
// BANK_CHARGE
if($transaction->transaction_description === 'CMS - DR CORP CHG' || $transaction->transaction_description === 'MONTHLY PROFIT DEBIT'){
$transaction->owners()->firstOrCreate([
$data = $transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::BANK_CHARGE
]);
}
// CREDIT_CARD_PAYMENT
if(str_contains($transaction->transaction_description_2, 'VISA CARD')){
$transaction->owners()->firstOrCreate([
$data = $transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::CREDIT_CARD_PAYMENT
]);
}
// INTERNAL_BANK_TRANSFER_OUT
if(str_contains($transaction->transaction_description_2, 'CIEF WORLDWIDE') || str_contains($transaction->transaction_description_2, 'CIEF WORLWIDE') || str_contains($transaction->transaction_description_2, 'IZYIM GLOBAL')){
$transaction->owners()->firstOrCreate([
$data = $transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::INTERNAL_BANK_TRANSFER_OUT
]);
}
// non-operational charges
if(str_contains($transaction->transaction_description_2, 'HIRE PURCHASE') || str_contains($transaction->transaction_description_2, 'TENAGA NASIONAL') || str_contains($transaction->transaction_description, 'CABLE CHARGE') || str_contains($transaction->transaction_description_2, 'CTOS DATA SYSTEMS') || str_contains($transaction->transaction_description_2, 'MAXIS')){
$transaction->owners()->firstOrCreate([
$data = $transaction->owners()->firstOrCreate([
'type' => StatementTransactionOwnerType::NON_OPERATIONAL
]);
}
}
if (isset($data) && $data->wasRecentlyCreated) $mapped = true;
$this->updateMappedRate($transaction, $mapped);
}
}
}
private function getTransactions($date, $amount, $type, $ownerType, $paymentMethod, $statuses, $keywords, $model = Transaction::class) {
private function getTransactions($date, $amount, $type, $ownerType, $paymentMethod, $statuses, $keywords, $model = Transaction::class) {
$dateRange = $this->getDateRange($date, 4);
if (App::environment(['production'])) {
$query = $model::whereIn('status', $statuses)
@@ -318,7 +320,7 @@ class CreateBankStatementTransactionOwnersProcessor
try{
$client = new \GuzzleHttp\Client(['verify' => false]);
$response = $client->request('GET', $url.'?api-key=510acd13d8d24375cf038ad626c282565451461a9c2399357e0b65365300787e&filters={"order_by":{"column":"id","DESC":true},"status_in":[2]'.$paymentMethodFilter.',"created_after":"'.$dateRange['start_date'].'","created_before":"'.$dateRange['end_date'].'","amount_exceed":'.($amount - 0.01).',"amount_short":'.($amount + 0.01).',"type_in":['.$type.']}');
$response = $client->request('GET', $url.'?api-key=510acd13d8d24375cf038ad626c282565451461a9c2399357e0b65365300787e&filters={"order_by":{"column":"id","DESC":true},"status_in":[2]'.$paymentMethodFilter.',"created_after":"'.$dateRange['start_date'].'","created_before":"'.$dateRange['end_date'].'","amount_exceed":'.($amount - 0.01).',"amount_short":'.($amount + 0.01).',"type_in":'.json_encode($type).'}');
$body = $response->getBody();
$data = json_decode($body, true);
$payload = $data['payload'];
@@ -345,4 +347,11 @@ class CreateBankStatementTransactionOwnersProcessor
'end_date' => $nextDay,
];
}
private function updateMappedRate($transaction, $mapped) {
$statement = $transaction->statement;
$statement->total_rows = StatementTransaction::where('account_statement_id',$transaction->account_statement_id)->count();
$statement->mapped_rows = $mapped ? $statement->mapped_rows+1 : $statement->mapped_rows;
$statement->save();
}
}
@@ -0,0 +1,57 @@
<?php
namespace App\Classes\Modules\Bookings\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Bookings\Services\FetchesBooking;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class ExpireBookingPaymentControllerLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Expire Payment',
'message' => 'You have successfully expire the Payment'
];
}
/** @var FetchesBooking */
private $fetchesBooking;
/**
* DeletePurchaseOrderPdfLogic constructor.
* @param FetchesBooking $fetchesBooking
*/
public function __construct(fetchesBooking $fetchesBooking)
{
$this->fetchesBooking = $fetchesBooking;
}
/**
* @param Request $request
* @return JsonResponse
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function logic(Request $request) : JsonResponse
{
$booking = $this->fetchesBooking->execute(['id' => $request->route('id')]);
$payment = $booking->transactions()
->payments()->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])
->first();
$payment->status = ApprovalStatus::EXPIRED;
$payment->save();
return $this->response([]);
}
}
@@ -5,12 +5,12 @@ namespace App\Classes\Modules\Bookings\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Jobs\ListBookingsJob;
use App\Classes\Modules\Bookings\Standards\Rules\CanListBookings;
use App\Classes\Modules\Jobs\DataTransferObjects\ListGenericJobObject;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Classes\Modules\Jobs\Services\CreatesJobResult;
class ListBookingJobLogic extends AbstractControllerLogic
{
@@ -24,6 +24,19 @@ class ListBookingJobLogic extends AbstractControllerLogic
];
}
/** @var CreatesJobResult */
private $createsJobResult;
/**
* ListPackingListsJobLogic constructor.
* @param CreatesJobResult $createsJobResult
*/
public function __construct(CreatesJobResult $createsJobResult)
{
$this->createsJobResult = $createsJobResult;
}
/**
* @param Request $request
* @return JsonResponse
@@ -34,13 +47,17 @@ class ListBookingJobLogic extends AbstractControllerLogic
$user = Auth::user();
$userInfo = (object) [
'email' => $user->email,
'type' => $user->type,
];
$userInfoJson = json_encode($userInfo);
$requestSignature = md5($userInfoJson . $request->fullUrl());
$listGenericJobObject = new ListGenericJobObject(
$request->fullUrl(),
$request->all(),
$requestSignature,
null,
$jobId,
$userInfo
);
@@ -50,6 +67,8 @@ class ListBookingJobLogic extends AbstractControllerLogic
$result = [];
$result['job_id'] = $jobId;
$this->createsJobResult->execute($listGenericJobObject);
return $this->response(['data' => $result]);
}
@@ -9,13 +9,16 @@ use App\Classes\Modules\Bookings\Services\UpdatesBookingStatus;
use App\Classes\Modules\Transactions\Services\DeletesTransaction;
use App\Classes\Modules\Documents\Services\DeletesDocument;
use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionProcessor;
use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionWithInvoiceNoProcessor;
use Illuminate\Support\Str;
use App\Classes\ValueObjects\Constants\DocumentType;
use App\Http\Resources\BookingResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Transaction;
use Illuminate\Support\Carbon;
class RegenerateInvoiceBookingLogic extends AbstractControllerLogic
{
@@ -23,7 +26,8 @@ class RegenerateInvoiceBookingLogic extends AbstractControllerLogic
/**
* @return array
*/
protected function notification():array {
protected function notification(): array
{
return [
'title' => 'Regenerate Booking Invoice',
'message' => 'You have successfully regenerate booking invoice'
@@ -48,6 +52,9 @@ class RegenerateInvoiceBookingLogic extends AbstractControllerLogic
/** @var CreateInvoiceTransactionProcessor */
private $createInvoiceTransactionProcessor;
/** @var CreateInvoiceTransactionWithInvoiceNoProcessor */
private $createInvoiceTransactionWithInvoiceNoProcessor;
/**
* FetchBookingLogic constructor.
* @param CanFetchBooking $canFetchBooking
@@ -56,6 +63,7 @@ class RegenerateInvoiceBookingLogic extends AbstractControllerLogic
* @param UpdatesBookingStatus $updatesBookingStatus
* @param DeletesDocument $deletesDocument
* @param CreateInvoiceTransactionProcessor $createInvoiceTransactionProcessor
* @param CreateInvoiceTransactionWithInvoiceNoProcessor $createInvoiceTransactionWithInvoiceNoProcessor
*/
public function __construct(
CanFetchBooking $canFetchBooking,
@@ -63,15 +71,16 @@ class RegenerateInvoiceBookingLogic extends AbstractControllerLogic
DeletesTransaction $deletesTransaction,
UpdatesBookingStatus $updatesBookingStatus,
DeletesDocument $deletesDocument,
CreateInvoiceTransactionProcessor $createInvoiceTransactionProcessor
)
{
CreateInvoiceTransactionProcessor $createInvoiceTransactionProcessor,
CreateInvoiceTransactionWithInvoiceNoProcessor $createInvoiceTransactionWithInvoiceNoProcessor
) {
$this->canFetchBooking = $canFetchBooking;
$this->fetchesBooking = $fetchesBooking;
$this->deletesTransaction = $deletesTransaction;
$this->updatesBookingStatus = $updatesBookingStatus;
$this->deletesDocument = $deletesDocument;
$this->createInvoiceTransactionProcessor = $createInvoiceTransactionProcessor;
$this->createInvoiceTransactionWithInvoiceNoProcessor = $createInvoiceTransactionWithInvoiceNoProcessor;
}
@@ -82,18 +91,45 @@ class RegenerateInvoiceBookingLogic extends AbstractControllerLogic
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
public function logic(Request $request) : JsonResponse
public function logic(Request $request): JsonResponse
{
$this->canFetchBooking->passes();
$booking = $this->fetchesBooking->execute([
'id' => $request->route('id'),
'status' => ApprovalStatus::COMPLETED,
'with_transactions' => true]
$booking = $this->fetchesBooking->execute(
[
'id' => $request->route('id'),
'status' => ApprovalStatus::COMPLETED,
'with_transactions' => true
]
);
$this->updatesBookingStatus->execute($booking, ApprovalStatus::APPROVED);
$firstInvoice = $booking->transactions()
->whereIn('type', [TransactionType::INVOICE])
->withTrashed()
->orderBy('created_at', 'asc')
->first();
// get the first bill_no
$firstBillNo = $firstInvoice->bill_no;
if (strpos($firstBillNo, '-deleted') !== false) {
$firstBillNo = substr($firstBillNo, 0, strpos($firstBillNo, '-deleted'));
}
// update currentInvoice bill_no to '-deleted-'
$currentInvoice = $booking->transactions()->where('type', TransactionType::INVOICE)->first();
$currentInvoice->bill_no = $currentInvoice->bill_no ."-deleted-" . (string)(Carbon::now()->timestamp);
$currentInvoice->save();
$transactionWithSameBillNo = Transaction::where('bill_no', $firstBillNo)->withTrashed()->get();
if ($transactionWithSameBillNo) {
foreach ($transactionWithSameBillNo as $transaction) {
$transaction->bill_no = $transaction->bill_no . "-deleted-" . Str::random(10);
$transaction->save();
}
}
$transaction = $booking->transactions()->whereIn('type', [TransactionType::INVOICE, TransactionType::SUPPLIER_DELIVER])->get();
foreach ($transaction as $key => $row) {
$this->deletesTransaction->execute($row);
@@ -104,9 +140,8 @@ class RegenerateInvoiceBookingLogic extends AbstractControllerLogic
$this->deletesDocument->execute($row);
}
$this->createInvoiceTransactionProcessor->execute($booking);
$this->createInvoiceTransactionWithInvoiceNoProcessor->execute($booking, $firstBillNo);
return $this->resourceResponse(new BookingResource($booking));
}
}
@@ -3,14 +3,10 @@
namespace App\Classes\Modules\Bookings\Processors;
use App\Classes\Modules\Bookings\Services\ListsBookings;
use App\Classes\Modules\Jobs\Services\CreatesJobResult;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Modules\Jobs\Processors\UpdateJobResultProcessor;
use App\Classes\General\Helper;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use App\Classes\Modules\Jobs\DataTransferObjects\ListGenericJobObject;
use Illuminate\Http\Resources\Json\ResourceCollection;
use App\Http\Resources\BookingResource;
use App\Http\Resources\ListBookingJobResource;
class ListBookingsJobProcessor
{
@@ -18,24 +14,25 @@ class ListBookingsJobProcessor
/** @var ListsBookings */
private $listsBookings;
/** @var CreatesJobResult */
private $createsJobResult;
/** @var UpdateJobResultProcessor */
private $updateJobResultProcessor;
/**
* ListBookingsJobProcessor constructor.
* @param ListsBookings $listsBookings
* @param CreatesJobResult $createsJobResult
* @param UpdateJobResultProcessor $updateJobResultProcessor
*/
public function __construct(ListsBookings $listsBookings, CreatesJobResult $createsJobResult)
public function __construct(ListsBookings $listsBookings, UpdateJobResultProcessor $updateJobResultProcessor)
{
$this->listsBookings = $listsBookings;
$this->createsJobResult = $createsJobResult;
$this->updateJobResultProcessor = $updateJobResultProcessor;
}
/**
* @param ListGenericJobObject $listGenericJobObject
* @return null|object
* @return void
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws \App\Classes\Exceptions\JobResourceNotFoundException
*/
public function execute(ListGenericJobObject $listGenericJobObject) {
@@ -43,15 +40,7 @@ class ListBookingsJobProcessor
foreach ($query->items() as &$item) {
$item['userInfo'] = $listGenericJobObject->getUserInfo();
}
//cief todo: remove comments
$result = Helper::collectionResponse(BookingResource::collection($query));
// $result = new JobBookingCollectionResponse($query, $listGenericJobObject->getuserInfo());
// $result = $this->collectionResponse(new BookingResourceCollection(BookingResource::collection($query), $listGenericJobObject->getuserInfo()));
$create = $this->createsJobResult->execute($listGenericJobObject, json_encode($result));
return $create;
$resultCurrent = Helper::collectionResponse(ListBookingJobResource::collection($query));
$this->updateJobResultProcessor->execute($listGenericJobObject, $resultCurrent);
}
}
@@ -4,15 +4,11 @@ namespace App\Classes\Modules\Documents\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Documents\Services\ListsDocuments;
use App\Classes\Modules\Jobs\Services\CreatesJobResult;
use App\Classes\Modules\Jobs\DataTransferObjects\ListGenericJobObject;
use App\Classes\Jobs\ListDocumentsJob;
use App\Http\Resources\DocumentResource;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use App\Classes\General\Helper;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Auth;
class ListDocumentJobLogic extends AbstractControllerLogic
@@ -28,6 +24,19 @@ class ListDocumentJobLogic extends AbstractControllerLogic
];
}
/** @var CreatesJobResult */
private $createsJobResult;
/**
* ListDocumentJobLogic constructor.
* @param CreatesJobResult $createsJobResult
*/
public function __construct(CreatesJobResult $createsJobResult)
{
$this->createsJobResult = $createsJobResult;
}
/**
* @param Request $request
* @return JsonResponse
@@ -42,33 +51,25 @@ class ListDocumentJobLogic extends AbstractControllerLogic
'type' => $user->type,
];
$userInfoJson = json_encode($userInfo);
$requestSignature = md5($userInfoJson . $request->fullUrl());
$listGenericJobObject = new ListGenericJobObject(
$request->fullUrl(),
$request->all(),
$requestSignature,
null,
$jobId,
$userInfo
);
ListDocumentsJob::dispatch($listGenericJobObject);
//cief todo: remove comments
// // Create your job instance with delay, so we can back here within delay and take control in our hands.
// $job = new ListDocuments($listGenericJobObject);
// $job->delay(now()->addSeconds(5));
// // Dispath your job with our custom_dispatch helper. This will return job id from jobs table
// // $jobId = $this->custom_dispatch($job);
$result = [];
$result['job_id'] = $jobId;
$this->createsJobResult->execute($listGenericJobObject);
return $this->response(['data' => $result]);
}
//cief todo: no longer need jobId
// function custom_dispatch($job): int {
// return app(\Illuminate\Contracts\Bus\Dispatcher::class)->dispatch($job);
// }
}
@@ -3,15 +3,10 @@
namespace App\Classes\Modules\Documents\Processors;
use App\Classes\Modules\Documents\Services\ListsDocuments;
use App\Classes\Modules\Jobs\Services\CreatesJobResult;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Modules\Jobs\Processors\UpdateJobResultProcessor;
use App\Classes\General\Helper;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use App\Classes\Modules\Jobs\DataTransferObjects\ListGenericJobObject;
use App\Http\Controllers\Documents\ListDocumentsController;
use Illuminate\Http\Resources\Json\ResourceCollection;
use App\Http\Resources\DocumentResource;
use App\Http\Resources\ListDocumentJobResource;
class ListDocumentsJobProcessor
{
@@ -19,24 +14,25 @@ class ListDocumentsJobProcessor
/** @var ListsDocuments */
private $listsDocuments;
/** @var CreatesJobResult */
private $createsJobResult;
/** @var UpdateJobResultProcessor */
private $updateJobResultProcessor;
/**
* ListDocumentsJobProcessor constructor.
* @param ListsDocuments $listsDocuments
* @param CreatesJobResult $createsJobResult
* @param UpdateJobResultProcessor $updateJobResultProcessor
*/
public function __construct(ListsDocuments $listsDocuments, CreatesJobResult $createsJobResult)
public function __construct(ListsDocuments $listsDocuments, UpdateJobResultProcessor $updateJobResultProcessor)
{
$this->listsDocuments = $listsDocuments;
$this->createsJobResult = $createsJobResult;
$this->updateJobResultProcessor = $updateJobResultProcessor;
}
/**
* @param ListGenericJobObject $listGenericJobObject
* @return null|object
* @return void
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws \App\Classes\Exceptions\JobResourceNotFoundException
*/
public function execute(ListGenericJobObject $listGenericJobObject) {
@@ -44,11 +40,8 @@ class ListDocumentsJobProcessor
foreach ($query->items() as &$item) {
$item['userInfo'] = $listGenericJobObject->getUserInfo();
}
$result = Helper::collectionResponse(DocumentResource::collection($query));
$create = $this->createsJobResult->execute($listGenericJobObject, json_encode($result));
return $create;
$resultCurrent = Helper::collectionResponse(ListDocumentJobResource::collection($query));
$this->updateJobResultProcessor->execute($listGenericJobObject, $resultCurrent);
}
}
@@ -39,7 +39,8 @@ class ExportsImportedInvoiceMappeds implements FromQuery, WithHeadings, WithHead
'Net Total',
'Cancelled',
'Mapped Status',
'Mapped Reference No'
'Mapped Reference No',
'MapPayment Received Date'
];
}
@@ -72,6 +73,7 @@ class ExportsImportedInvoiceMappeds implements FromQuery, WithHeadings, WithHead
Arr::get($data,'cancelled'),
Arr::get($data,'mapped_status'),
Arr::get($data,'mapped_result_reference'),
Arr::get($data,'payment_received_date'),
];
}
@@ -4,7 +4,6 @@ namespace App\Classes\Modules\Exports\Services;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\StatementTransactionOwnerType;
use App\Models\StatementTransactionOwner;
use App\Models\Transaction;
use Maatwebsite\Excel\Concerns\Exportable;
use Maatwebsite\Excel\Concerns\FromQuery;
@@ -18,6 +17,8 @@ use App\Classes\Modules\Accounting\Processors\ListShippingPortalTransactions;
use App\Classes\ValueObjects\Constants\ShippingTransactionType;
use App\Classes\ValueObjects\Constants\TransactionType;
use Illuminate\Support\Facades\Log;
use App\Classes\General\Eloquent\ApplyFiltersToQuery;
use App\Models\StatementTransaction;
class ExportsInvoiceTransactions implements FromQuery, WithHeadings, WithHeadingRow, WithMapping, ShouldAutoSize
{
@@ -33,19 +34,12 @@ class ExportsInvoiceTransactions implements FromQuery, WithHeadings, WithHeading
public function headings(): array
{
$header = [];
if ($this->request->input('type') == 'invoices') {
$header[] = 'DocNo';
$header[] = 'DocDate';
$header[] = 'DebtorCode';
} else {
$header[] = 'OrNo';
$header[] = 'OrDate';
$header[] = 'CreditorCode';
}
$header[] = 'Ref';
$header[] = ($this->request->input('type') == 'invoices' ? 'DebtorName' : 'CreditorName');
$header = array_merge($header, [
$header = [
'DocNo',
'DocDate',
'DebtorCode',
'Ref',
'DebtorName',
'CurrencyCode',
'ShipInfo',
'ItemCode',
@@ -55,7 +49,7 @@ class ExportsInvoiceTransactions implements FromQuery, WithHeadings, WithHeading
'UnitPrice',
'AccNo',
'DeptNo'
]);
];
return $header;
}
@@ -64,10 +58,9 @@ class ExportsInvoiceTransactions implements FromQuery, WithHeadings, WithHeading
*/
public function query()
{
$data = StatementTransactionOwner::whereNull('invoice_reference')
->whereIn('type', [StatementTransactionOwnerType::SALES, StatementTransactionOwnerType::WALLET_TOP_UP])
->whereIn('status', [ApprovalStatus::COMPLETED, ApprovalStatus::APPROVED]);
if ($this->request->has('bankStatementOwnerId')) $data = $data->whereIn('id',json_decode($this->request->input('bankStatementOwnerId')));
$data = (new ApplyFiltersToQuery())->execute(StatementTransaction::query(), json_decode($this->request->input('filter'), true));
if ($this->request->has('bankStatementTransactionId')) $data = $data->whereIn('id',json_decode($this->request->input('bankStatementTransactionId'), true));
return $data;
}
@@ -78,11 +71,12 @@ class ExportsInvoiceTransactions implements FromQuery, WithHeadings, WithHeading
*/
public function map($transaction): array
{
$statementTransactionOwner = $transaction->owners()->whereIn('status', [ApprovalStatus::APPROVED])->first();
$logArray = [
'counter' => $this->counter,
'system' => $transaction->system,
'StatementTransactionOwner_id' => $transaction->id,
'transaction_table_id' => $transaction->owner_id,
'system' => $statementTransactionOwner->system,
'StatementTransactionOwner_id' => $statementTransactionOwner->id,
'transaction_table_id' => $statementTransactionOwner->owner_id,
];
$this->counter += 1;
$logArray = json_encode($logArray);
@@ -92,8 +86,8 @@ class ExportsInvoiceTransactions implements FromQuery, WithHeadings, WithHeading
$textToAppend = Carbon::now()->format('[Y-m-d H:i:s]') . ' ' . $logArray . PHP_EOL;
file_put_contents($filePath, $textToAppend, FILE_APPEND);
if ($transaction->system == 'EXCHANGE') {
$row = (App()->make($transaction->owner_type))->where('id', $transaction->owner_id)->first();
if ($statementTransactionOwner->system == 'EXCHANGE') {
$row = (App()->make($statementTransactionOwner->owner_type))->where('id', $statementTransactionOwner->owner_id)->first();
$company = $row->type === TransactionType::PAYMENT ? $row->owner->company : $row->owner->owner;
$booking = $row->owner;
@@ -116,15 +110,15 @@ class ExportsInvoiceTransactions implements FromQuery, WithHeadings, WithHeading
];
} else {
$row = (App()->make(ListShippingPortalTransactions::class))->execute([
'id' => $transaction->owner_id,
'id' => $statementTransactionOwner->owner_id,
'with_company' => true,
]);
if (empty($row) || $row[0]['status'] != 'success') {
$textToAppend = Carbon::now()->format('[Y-m-d H:i:s]') . ' Fetch Shipping Transaction Fail ' . json_encode([
'id' => $transaction->owner_id,
'id' => $statementTransactionOwner->owner_id,
'with_company' => true,
'StatementTransactionOwner_id' => $transaction->id,
'StatementTransactionOwner_id' => $statementTransactionOwner->id,
]) . PHP_EOL;
file_put_contents($errorFilePath, $textToAppend, FILE_APPEND);
@@ -133,7 +127,24 @@ class ExportsInvoiceTransactions implements FromQuery, WithHeadings, WithHeading
Log::info('Error in Exports Invoice Transactions ' . $this->counter);
return [];
return [
'Transaction Not Found',
$transaction->posting_date->format('m/d/Y H:m'),
$transaction->transaction_description.' - '.$transaction->transaction_description_2,
$statementTransactionOwner->system,
'',
'',
'',
'',
'',
'',
0,
$transaction->amount,
'',
'',
'',
''
];
}
$row = $row[0];
@@ -0,0 +1,199 @@
<?php
namespace App\Classes\Modules\Exports\Services;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
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;
use Illuminate\Http\Request;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use App\Classes\General\Eloquent\ApplyFiltersToQuery;
use App\Models\StatementTransaction;
use App\Models\Company;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Concerns\WithCustomStartCell;
use Maatwebsite\Excel\Events\AfterSheet;
class ExportsReceiptTransactions implements FromQuery, WithHeadings, WithHeadingRow, WithMapping, ShouldAutoSize, WithEvents, WithCustomStartCell
{
use Exportable;
private $request;
private $counter = 1;
public function __construct(Request $request)
{
$this->request = $request;
}
public function startCell(): string
{
return 'A2';
}
public function registerEvents(): array {
return [
AfterSheet::class => function(AfterSheet $event) {
$sheet = $event->sheet;
$sheet->mergeCells('A1:A1');
$sheet->setCellValue('A1', '"');
$sheet->mergeCells('M1:Y1');
$sheet->setCellValue('M1', "Payment Detail Column");
$sheet->mergeCells('Z1:AB1');
$sheet->setCellValue('Z1', "Knock Off Detail");
$styleArray = [
'alignment' => [
'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
],
];
$cellRange = 'A1:AB1';
$event->sheet->getDelegate()->getStyle($cellRange)->applyFromArray($styleArray);
},
];
}
public function headings(): array
{
$header = [
[
' ',
'(20 chars)',
'(Date: dd/MM/yyyy)',
'(12 chars)',
'(40 chars)',
'(25 chars)',
'(10 chars)',
'(10 chars)',
'(5 chars)',
'(Number, use System Currency Rate Decimal)',
'(Number, use System Currency Rate Decimal)',
'(Rich Text)',
'(20 chars)',
'(20 chars)',
'(Number, use System Currency Decimal)',
'(Number, use System Currency Decimal)',
'(Number, use System Currency Rate Decimal)',
'(14 chars)',
'(30 chars)',
'(10 chars)',
'(10 chars)',
'(20 chars)',
'(Integer)',
'(Boolean. Indicate T for stock control or F for non stock control)',
'(Returned Cheque Date: dd/MM/yyyy)',
'(2 chars, RI for Invoice, RD for D/N)',
'',
'(Number, use System Currency Decimal)',
],
[
'DocNo',
'DocDate',
'DebtorCode',
'Description',
'DocNo2',
'ProjNo',
'DeptNo',
'CurrencyCode',
'ToHomeRate',
'ToDebtorRate',
'Note',
'PaymentMethod',
'ChequeNo',
'PaymentAmt',
'BankCharge',
'ToBankRate',
'BankChargeTaxType',
'BankChargeTaxRefNo',
'BankChargeProjNo',
'BankChargeDeptNo',
'PaymentBy',
'FloatDay',
'IsRCHQ',
'RCHQDate',
'KnockOffDocType',
'KnockOffDocNo',
'KnockOffAmt',
'',
]
];
return $header;
}
/**
* @return \Illuminate\Support\Collection|mixed
*/
public function query()
{
$data = (new ApplyFiltersToQuery())->execute(StatementTransaction::query(), json_decode($this->request->input('filter'), true));
if ($this->request->has('bankStatementTransactionId')) $data = $data->whereIn('id',json_decode($this->request->input('bankStatementTransactionId'), true));
return $data;
}
/**
* @param StatementTransaction $transaction
*
* @return array
*/
public function map($transaction): array
{
$statementTransactionOwner = $transaction->owners()->whereIn('status', [ApprovalStatus::APPROVED])->first();
$logArray = [
'counter' => $this->counter,
'system' => $statementTransactionOwner->system,
'StatementTransactionOwner_id' => $statementTransactionOwner->id,
'transaction_table_id' => $statementTransactionOwner->owner_id,
];
$this->counter += 1;
$logArray = json_encode($logArray);
$filePath = storage_path('logs/exports_receipt_transactions.log');
$errorFilePath = storage_path('logs/exports_receipt_transactions_error.log');
$textToAppend = Carbon::now()->format('[Y-m-d H:i:s]') . ' ' . $logArray . PHP_EOL;
file_put_contents($filePath, $textToAppend, FILE_APPEND);
$company = Company::where('name',$transaction->transaction_description_2)->first();
return [
'<<New>>',
Carbon::parse($transaction->posting_date)->format('d/m/Y'),
($company ? $company->debtor : null),
'Payment for '.$transaction->transaction_description,
'',
'',
'',
'MYR',
1,
1,
'',
'MBB',
'',
$transaction->amount,
'',
1,
'',
'',
'',
'',
'',
'0',
'',
'',
'RI',
$transaction->transaction_ref,
$transaction->amount,
'',
];
}
}
@@ -4,9 +4,8 @@ namespace App\Classes\Modules\Jobs\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Jobs\Services\FetchesJobResult;
use App\Classes\Modules\Jobs\Processors\FetchesJobResultProcessor;
use App\Http\Resources\JobResultResource;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -23,16 +22,16 @@ class FetchJobResultLogic extends AbstractControllerLogic
];
}
/** @var FetchesJobResult */
private $fetchesJobResult;
/** @var FetchesJobResultProcessor */
private $fetchesJobResultProcessor;
/**
* FetchJobResultLogic constructor.
* @param FetchesJobResult $fetchesJobResult
* @param FetchesJobResultProcessor $fetchesJobResultProcessor
*/
public function __construct(FetchesJobResult $fetchesJobResult)
public function __construct(FetchesJobResultProcessor $fetchesJobResultProcessor)
{
$this->fetchesJobResult = $fetchesJobResult;
$this->fetchesJobResultProcessor = $fetchesJobResultProcessor;
}
@@ -45,10 +44,8 @@ class FetchJobResultLogic extends AbstractControllerLogic
*/
public function logic(Request $request) : JsonResponse
{
$query = $this->fetchesJobResult->execute(['job_id' => $request->route('job_id')]);
$query = $this->fetchesJobResultProcessor->execute($request);
return $this->resourceResponse(new JobResultResource($query));
}
}
@@ -2,7 +2,6 @@
namespace App\Classes\Modules\Jobs\DataTransferObjects;
use Illuminate\Http\Request;
use App\Classes\General\Interfaces\DataTransferObject;
class ListGenericJobObject implements DataTransferObject
@@ -16,6 +15,12 @@ class ListGenericJobObject implements DataTransferObject
/** @var string */
private $jobId;
/** @var string */
private $requestSignature;
/** @var string */
private $resultSignature;
/** @var object */
private $userInfo;
@@ -25,11 +30,13 @@ class ListGenericJobObject implements DataTransferObject
/** @var string */
private $jobCommand;
public function __construct(string $name, array $payload, string $jobId, object $userInfo = null)
public function __construct(string $name, array $payload, string $requestSignature, ?string $resultSignature, string $jobId, object $userInfo = null)
{
$this->name = $name;
$this->payload = $payload;
$this->jobId = $jobId;
$this->requestSignature = $requestSignature;
$this->resultSignature = $resultSignature;
$this->userInfo = $userInfo;
}
@@ -57,6 +64,22 @@ class ListGenericJobObject implements DataTransferObject
return $this->jobId;
}
/**
* @return string
*/
public function getRequestSignature(): string
{
return $this->requestSignature;
}
/**
* @return string
*/
public function getResultSignature(): ?string
{
return $this->resultSignature;
}
/**
* @return object
*/
@@ -81,10 +104,6 @@ class ListGenericJobObject implements DataTransferObject
return $this->jobCommand;
}
// public function setJobId(int $jobId)
// {
// $this->jobId = $jobId;
// }
public function setJobCommandName(string $jobCommandName)
{
@@ -0,0 +1,60 @@
<?php
namespace App\Classes\Modules\Jobs\DataTransferObjects;
use App\Classes\General\Interfaces\DataTransferObject;
class UpdateJobResultObject implements DataTransferObject
{
/** @var string */
private $result;
/** @var string */
private $resultSignature;
/** @var string */
private $jobCommandName;
/** @var string */
private $jobCommand;
public function __construct(string $result, string $resultSignature, string $jobCommandName, string $jobCommand)
{
$this->result = $result;
$this->resultSignature = $resultSignature;
$this->jobCommandName = $jobCommandName;
$this->jobCommand = $jobCommand;
}
/**
* @return string
*/
public function getResult(): string
{
return $this->result;
}
/**
* @return array
*/
public function getResultSignature(): string
{
return $this->resultSignature;
}
/**
* @return string
*/
public function getJobCommandName(): string
{
return $this->jobCommandName;
}
/**
* @return string
*/
public function getJobCommand(): string
{
return $this->jobCommand;
}
}
@@ -0,0 +1,45 @@
<?php
namespace App\Classes\Modules\Jobs\Processors;
use App\Classes\Modules\Jobs\Services\FetchesJobResult;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
class FetchesJobResultProcessor
{
/** @var FetchesJobResult */
private $fetchesJobResult;
/**
* FetchesJobResultProcessor constructor.
* @param FetchesJobResult $fetchesJobResult
*/
public function __construct(FetchesJobResult $fetchesJobResult)
{
$this->fetchesJobResult = $fetchesJobResult;
}
/**
* @param Request $request
* @return Model
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws \App\Classes\Exceptions\JobResourceNotFoundException
* @throws \App\Classes\Exceptions\ResourceNotFoundException
*/
public function execute(Request $request){
$res1 = $this->fetchesJobResult->execute(['job_id' => $request->route('job_id')]);
if(!$res1->result){
Log::info('Job id: '.$request->route('job_id'));
$res2 = $this->fetchesJobResult->execute(['request_signature' => $res1->request_signature, 'result_not_null' => true, 'order_by_id_desc' => true]);
Log::info('Job id: '.$res2->id." , request_signature: ".$res2->request_signature);
return $res2;
}
return $res1;
}
}
@@ -0,0 +1,64 @@
<?php
namespace App\Classes\Modules\Jobs\Processors;
use App\Classes\Modules\Jobs\Services\UpdatesJobResult;
use App\Classes\Modules\Jobs\Services\FetchesJobResult;
use App\Classes\Exceptions\JobResourceNotFoundException;
use App\Classes\Modules\Jobs\DataTransferObjects\ListGenericJobObject;
use App\Classes\Modules\Jobs\DataTransferObjects\UpdateJobResultObject;
class UpdateJobResultProcessor
{
/** @var FetchesJobResult */
private $fetchesJobResult;
/** @var UpdatesJobResult */
private $updatesJobResult;
/**
* UpdateJobResultProcessor constructor.
* @param FetchesJobResult $fetchesJobResult
* @param UpdatesJobResult $updatesJobResult
*/
public function __construct(FetchesJobResult $fetchesJobResult, UpdatesJobResult $updatesJobResult)
{
$this->fetchesJobResult = $fetchesJobResult;
$this->updatesJobResult = $updatesJobResult;
}
/**
* @param ListGenericJobObject $listGenericJobObject
* @param array $resultCurrent
* @return void
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws \App\Classes\Exceptions\JobResourceNotFoundException
*/
public function execute(ListGenericJobObject $listGenericJobObject, $resultCurrent) {
$jobResultCurrent = $this->fetchesJobResult->execute(['job_id' => $listGenericJobObject->getJobId()]);
$resultCurrentJson = json_encode($resultCurrent);
$resultSignatureCurrent = md5($resultCurrentJson);
try{
$jobResultExisting = $this->fetchesJobResult->execute(['request_signature' => $jobResultCurrent->request_signature, 'result_not_null' => true, 'order_by_id_desc' => true]);
$resultSignatureExisting = $jobResultExisting->result_signature;
if($resultSignatureExisting != $resultSignatureCurrent){
$this->updateJobResult($jobResultCurrent, $resultCurrentJson, $resultSignatureCurrent, $listGenericJobObject->getJobCommandName(), $listGenericJobObject->getJobCommand());
}
} catch (JobResourceNotFoundException $exception){
$this->updateJobResult($jobResultCurrent, $resultCurrentJson, $resultSignatureCurrent, $listGenericJobObject->getJobCommandName(), $listGenericJobObject->getJobCommand());
}
}
private function updateJobResult($jobResultCurrent, $resultCurrentJson, $resultSignatureCurrent, $jobCommandName, $jobCommand){
$updateJobResultObject = new UpdateJobResultObject(
$resultCurrentJson,
$resultSignatureCurrent,
$jobCommandName,
$jobCommand
);
$create = $this->updatesJobResult->execute($jobResultCurrent, $updateJobResultObject);
}
}
@@ -10,18 +10,16 @@ class CreatesJobResult extends AbstractUpdateRecord
{
/**
* @param ListGenericJobObject $listGenericJobObject
* @param string $result
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(ListGenericJobObject $listGenericJobObject, string $result)
public function execute(ListGenericJobObject $listGenericJobObject)
{
$model = new JobResult();
$model->job_id = $listGenericJobObject->getJobId();
$model->result = $result;
$model->request_signature = $listGenericJobObject->getRequestSignature();
$model->result_signature = $listGenericJobObject->getResultSignature();
$model->url = $listGenericJobObject->getName();
$model->job_command_name = $listGenericJobObject->getJobCommandName();
$model->job_command = $listGenericJobObject->getJobCommand();
return $this->handler($model);
}
@@ -0,0 +1,33 @@
<?php
namespace App\Classes\Modules\Jobs\Services;
use App\Classes\General\Eloquent\AbstractListRecord;
use Illuminate\Database\Eloquent\Builder;
use App\Models\JobResult;
class ListsJobResult extends AbstractListRecord
{
/** @var JobResult */
private $repository;
/**
* ListsJobResult constructor.
* @param JobResult $repository
*/
public function __construct(JobResult $repository)
{
$this->repository = $repository;
}
/**
* @return Builder
*/
function getRepository(): Builder
{
return $this->repository->newQuery();
}
}
@@ -0,0 +1,28 @@
<?php
namespace App\Classes\Modules\Jobs\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Classes\Modules\Jobs\DataTransferObjects\UpdateJobResultObject;
use App\Models\JobResult;
class UpdatesJobResult extends AbstractUpdateRecord
{
/**
* @param JobResult $model
* @param UpdateJobResultObject $updateJobResultObject
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(JobResult $model, UpdateJobResultObject $updateJobResultObject) {
$model->result = $updateJobResultObject->getResult();
$model->result_signature = $updateJobResultObject->getResultSignature();
$model->job_command_name = $updateJobResultObject->getJobCommandName();
$model->job_command = $updateJobResultObject->getJobCommand();
return $this->handler($model);
}
}
@@ -5,10 +5,11 @@ namespace App\Classes\Modules\Transactions\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Jobs\ListTransactionsJob;
use App\Classes\Modules\Jobs\Services\CreatesJobResult;
use App\Classes\Modules\Jobs\DataTransferObjects\ListGenericJobObject;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class ListTransactionsJobLogic extends AbstractControllerLogic
{
@@ -22,6 +23,19 @@ class ListTransactionsJobLogic extends AbstractControllerLogic
];
}
/** @var CreatesJobResult */
private $createsJobResult;
/**
* ListTransactionsJobLogic constructor.
* @param CreatesJobResult $createsJobResult
*/
public function __construct(CreatesJobResult $createsJobResult)
{
$this->createsJobResult = $createsJobResult;
}
/**
* @param Request $request
* @return JsonResponse
@@ -30,10 +44,21 @@ class ListTransactionsJobLogic extends AbstractControllerLogic
{
$jobId = uniqid();
$user = Auth::user();
$userInfo = (object) [
'type' => $user->type,
];
$userInfoJson = json_encode($userInfo);
$requestSignature = md5($userInfoJson . $request->fullUrl());
$listGenericJobObject = new ListGenericJobObject(
$request->fullUrl(),
$request->all(),
$jobId
$requestSignature,
null,
$jobId,
$userInfo
);
ListTransactionsJob::dispatch($listGenericJobObject);
@@ -41,6 +66,8 @@ class ListTransactionsJobLogic extends AbstractControllerLogic
$result = [];
$result['job_id'] = $jobId;
$this->createsJobResult->execute($listGenericJobObject);
return $this->response(['data' => $result]);
}
@@ -21,7 +21,7 @@ use App\Classes\ValueObjects\Constants\DocumentType;
use App\Models\Booking;
use App\Models\SegmentConstant;
class CreateInvoiceTransactionProcessorWithInvoiceNo
class CreateInvoiceTransactionWithInvoiceNoProcessor
{
/** @var CreatesTransaction */
@@ -3,14 +3,10 @@
namespace App\Classes\Modules\Transactions\Processors;
use App\Classes\Modules\Transactions\Services\ListsTransactions;
use App\Classes\Modules\Jobs\Services\CreatesJobResult;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Modules\Jobs\Processors\UpdateJobResultProcessor;
use App\Classes\General\Helper;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use App\Classes\Modules\Jobs\DataTransferObjects\ListGenericJobObject;
use Illuminate\Http\Resources\Json\ResourceCollection;
use App\Http\Resources\TransactionResource;
use App\Http\Resources\ListTransactionJobResource;
class ListTransactionsJobProcessor
{
@@ -18,33 +14,32 @@ class ListTransactionsJobProcessor
/** @var ListsTransactions */
private $listsTransactions;
/** @var CreatesJobResult */
private $createsJobResult;
/** @var UpdateJobResultProcessor */
private $updateJobResultProcessor;
/**
* ListTransactionsJobProcessor constructor.
* @param ListsTransactions $listsTransactions
* @param CreatesJobResult $createsJobResult
* @param UpdateJobResultProcessor $updateJobResultProcessor
*/
public function __construct(ListsTransactions $listsTransactions, CreatesJobResult $createsJobResult)
public function __construct(ListsTransactions $listsTransactions, UpdateJobResultProcessor $updateJobResultProcessor)
{
$this->listsTransactions = $listsTransactions;
$this->createsJobResult = $createsJobResult;
$this->updateJobResultProcessor = $updateJobResultProcessor;
}
/**
* @param ListGenericJobObject $listGenericJobObject
* @return null|object
* @return void
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws \App\Classes\Exceptions\JobResourceNotFoundException
*/
public function execute(ListGenericJobObject $listGenericJobObject) {
$query = $this->listsTransactions->execute($this->listsTransactions->deserializeFilters($listGenericJobObject->getPayload()['filters']), ['page' => $listGenericJobObject->getPayload()['page']]);
$result = Helper::collectionResponse(TransactionResource::collection($query));
$create = $this->createsJobResult->execute($listGenericJobObject, json_encode($result));
return $create;
$resultCurrent = Helper::collectionResponse(ListTransactionJobResource::collection($query));
$this->updateJobResultProcessor->execute($listGenericJobObject, $resultCurrent);
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Http\Controllers\Bookings;
use App\Classes\Modules\Bookings\ControllersLogic\ExpireBookingPaymentControllerLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class ExpireBookingPaymentController
{
/**
* @param Request $request
* @param DeleteBookingPaymentControllerLogic $logic
* @return JsonResponse
*/
public function expire(Request $request, ExpireBookingPaymentControllerLogic $logic): JsonResponse {
return $logic->execute($request);
}
}
@@ -17,6 +17,7 @@ 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;
class ExportCustomersToExcelController
{
@@ -61,7 +62,14 @@ class ExportCustomersToExcelController
public function invoiceTransactions(Request $request){
$exportsTransactions = new ExportsInvoiceTransactions($request);
$response = $exportsTransactions->download(($request->input('type') == 'invoices' ? 'invoice-transactions' : 'receipt-transactions').'.xls', Excel::XLS, ['Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']);
$response = $exportsTransactions->download('invoice-transactions.xls', Excel::XLS, ['Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']);
ob_end_clean();
return $response;
}
public function receiptTransactions(Request $request){
$exportsTransactions = new ExportsReceiptTransactions($request);
$response = $exportsTransactions->download('receipt-transactions.xls', Excel::XLS, ['Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']);
ob_end_clean();
return $response;
}
@@ -34,99 +34,123 @@ class ImportStatementInvoiceController
$this->responseMessage = 'You have successfully imported invoice mapping';
}
public function mapping($row) {
// Shipping Info
// TOPUP -> map with transaction.bill_no
if (str_starts_with($row['shipping_info'], 'TOPUP')) {
// find in exchange first, if cannont then find in izyim
foreach (['exchange','izyim'] as $system) {
[$returnReference, $transactionDate] = $this->mappingTopUp($row, $system);
if ($returnReference) {
// $row['mapped_result_reference'] = $data['owner_reference'];
// $row['payment_received_date'] = date('Y-m-d', strtotime($data['created_at']));
$row['mapped_result_reference'] = $returnReference;
$row['payment_received_date'] = $transactionDate ? date('d-m-Y', strtotime($transactionDate)) : null;
$row['mapped_status'] = 'success';
return $row;
}
}
}
[$returnReference, $transactionDate] = $this->mappingExchange($row);
if ($returnReference) {
$row['mapped_result_reference'] = $returnReference;
$row['payment_received_date'] = date('d-m-Y', strtotime($transactionDate));
$row['mapped_status'] = 'success';
return $row;
}
// if still unable to map, will try to check the shipping_info without TOPUP
// foreach (['exchange','izyim'] as $system) {
// $returnReference = $this->mappingTopUp($row, $system);
// if ($returnReference) {
// $row['mapped_result_reference'] = $returnReference;
// $row['mapped_status'] = 'success';
// }
// }
return $row;
}
/**
* @param Request $request
* @return array
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function import(Request $request) : JsonResponse
{
ini_set('memory_limit', '-1');
$importDate = date('Y-m-d H:i:s');
$object = new DocumentObject('', $request->input('files'), '', ApprovalStatus::APPROVED, 'imports');
$file = json_decode($object->getFiles()[0])->file_info->original->file;
try {
ini_set('memory_limit', '-1');
$importDate = date('Y-m-d H:i:s');
$object = new DocumentObject('', $request->input('files'), '', ApprovalStatus::APPROVED, 'imports');
$file = json_decode($object->getFiles()[0])->file_info->original->file;
$import = new GenericImport();
Excel::import($import, $file);
$excelRows = $import->rows;
$excelRows = $excelRows->toArray();
$import = new GenericImport();
Excel::import($import, $file);
$excelRows = $import->rows;
$excelRows = $excelRows->toArray();
$data = [];
foreach ($excelRows as $row) {
$row['mapped_result_reference'] = null;
$row['payment_received_date'] = null;
$row['mapped_status'] = 'failed';
$row['date'] = in_array(gettype($row['date']), ['integer', 'double']) ? $this->changeExcelDate($row['date']) : date('Y-m-d', strtotime($row['date']));
$row = $this->mapping($row);
TransactionMappingLog::create([
'imported_date'=>$importDate,
'data'=>$row,
]);
array_push($data, $row);
// if 5 digits -> exchange booking reference
// find transation
// find statement_transaction_owners, and fill up the details
// if <5 digits, find the transaction id (order number in izyim), find the payment in izyim
// find transation
// find statement_transaction_owners, and fill up the details
// dd([
// 'type' => $statementTransactionOwnerType,
// 'system' => $system,
// // 'owner_type' => Transaction::class,
// // todo-new: make sure owner_type is a class
// 'owner_type' => $owner_type,
// 'owner_id' => $owner_id,
// 'owner_reference' => $owner_reference
// ]);
// $bankStatementTransaction->owners()->firstOrCreate([
// 'type' => $statementTransactionOwnerType,
// 'system' => $system,
// // 'owner_type' => Transaction::class,
// // todo-new: make sure owner_type is a class
// 'owner_type' => $owner_type,
// 'owner_id' => $owner_id,
// 'owner_reference' => $owner_reference
// ]);
$data = [];
foreach ($excelRows as $row) {
$row['mapped_result_reference'] = null;
$row['mapped_status'] = 'failed';
$row['date'] = $this->changeExcelDate($row['date']);
// Shipping Info
// TOPUP -> map with transaction.bill_no
if (str_starts_with($row['shipping_info'], 'TOPUP')) {
// find in exchange first, if cannont then find in izyim
foreach (['exchange','izyim'] as $system) {
$returnReference = $this->mappingTopUp($row, $system);
if ($returnReference) {
$row['mapped_result_reference'] = $returnReference;
$row['mapped_status'] = 'success';
}
}
} else {
$returnReference = $this->mappingExchange($row);
if ($returnReference) {
$row['mapped_result_reference'] = $returnReference;
$row['mapped_status'] = 'success';
}
}
TransactionMappingLog::create([
'imported_date'=>$importDate,
'data'=>$row,
]);
array_push($data, $row);
// if 5 digits -> exchange booking reference
// find transation
// find statement_transaction_owners, and fill up the details
// if <5 digits, find the transaction id (order number in izyim), find the payment in izyim
// find transation
// find statement_transaction_owners, and fill up the details
// dd([
// 'type' => $statementTransactionOwnerType,
// 'system' => $system,
// // 'owner_type' => Transaction::class,
// // todo-new: make sure owner_type is a class
// 'owner_type' => $owner_type,
// 'owner_id' => $owner_id,
// 'owner_reference' => $owner_reference
// ]);
// $bankStatementTransaction->owners()->firstOrCreate([
// 'type' => $statementTransactionOwnerType,
// 'system' => $system,
// // 'owner_type' => Transaction::class,
// // todo-new: make sure owner_type is a class
// 'owner_type' => $owner_type,
// 'owner_id' => $owner_id,
// 'owner_reference' => $owner_reference
// ]);
return $this->response($this->responseTitle, $this->responseMessage, HttpStatus::OK_WITH_MESSAGE, ['data'=>$data,'importedDate'=>$importDate]);
} catch (\Exception $exception){
return $this->response('import invoice failed',$exception->getMessage(), ($exception->getCode()? $exception->getCode() : HttpStatus::SERVER_ERROR));
}
return $this->response(['data'=>$data,'importedDate'=>$importDate]);
}
public function response(?array $data = []) : JsonResponse {
return (new ApiResponseObject($this->responseTitle,
$this->responseMessage,
HttpStatus::OK_WITH_MESSAGE, $data))->handler();
public function response(String $responseTitle, String $responseMessage, int $httpStatus, ?array $data = []) : JsonResponse {
return (new ApiResponseObject($responseTitle, $responseMessage, $httpStatus, $data))->handler();
}
private function mappingTopUp(Array $row, String $system) {
try {
if ($data = (App()->make(ChecksBillNumber::class))->execute($row['shipping_info'], $system)) {
if ($system == 'izyim' && isset($data['owner_reference'])) return $data['owner_reference'];
// if ($system == 'izyim' && isset($data['owner_reference'])) return $data;
if ($system == 'izyim' && isset($data['owner_reference'])) return [$data['owner_reference'], null];
if ($system == 'exchange') return $this->updateTransactionOwnerReference($data, $row['doc_no']);
}
@@ -137,33 +161,32 @@ class ImportStatementInvoiceController
private function mappingExchange(Array $row) {
$date = $row['date'];
$transactions = Transaction::where('original_amount', $row['net_total'])->whereRaw("DATE(created_at) = '$date'")
->whereHas('receiverCompany', function($q) use($row) {
$q->where('debtor',$row['debtor_code']);
})->get();
if ($transactions && $transactions->count() == 0) {
$transactions = Transaction::where(DB::raw('FLOOR(original_amount)'), floor($row['net_total']))->whereRaw("DATE(created_at) = '$date'")
->whereHas('receiverCompany', function($q) use($row) {
$q->where('debtor',$row['debtor_code']);
})->get();
$transaction = Transaction::getReceiverWithJoinStatementTransactionAndOwner($row)->select('transactions.*')->where('owner_reference', $row['shipping_info'])->first();
if ($transaction && $transaction->count() == 0) {
$transaction = Transaction::getReceiverWithJoinStatementTransactionAndOwner($row)->select('transactions.*')->where('statement_transactions.amount', $row['net_total'])->whereRaw("DATE(posting_date) = '$date'")->first();
}
if ($transactions && $transactions->count() == 1) {
foreach ($transactions as $key => $transaction) {
return $this->updateTransactionOwnerReference($transaction, $row['doc_no']);
}
if ($transaction && $transaction->count() == 0) {
$transaction = Transaction::getReceiverWithJoinStatementTransactionAndOwner($row)->select('transactions.*')->where(DB::raw('FLOOR(statement_transactions.amount)'), floor($row['net_total']))->whereRaw("DATE(posting_date) = '$date'")->first();
}
return false;
if ($transaction && $transaction->count() > 0) {
return $this->updateTransactionOwnerReference($transaction, $row['doc_no']);
}
return [false, false];
}
public function updateTransactionOwnerReference($transaction, String $docNo) {
$transactionOwner = $transaction->transaction_owner;
if ($transactionOwner) {
$transactionOwner->update(['invoice_reference'=>$docNo]);
return $transactionOwner->owner_reference;
$transactionOwner->update([
'invoice_reference'=>$docNo,
'status'=>ApprovalStatus::COMPLETED
]);
return [$transactionOwner->owner_reference, $transaction->created_at];
}
return false;
return [false, false];
}
public function changeExcelDate($date)
@@ -2,31 +2,35 @@
namespace App\Http\Controllers\Imports;
use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject;
use App\Classes\Modules\Imports\Services\GenericImport;
use App\Classes\Modules\Segments\DataTransferObjects\SeasonalSegmentObject;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Models\Segment;
use App\Models\User;
use Carbon\Carbon;
use DateTime;
use Carbon\Carbon;
use App\Models\User;
use App\Models\Company;
use App\Models\Segment;
use App\Models\Transaction;
use Illuminate\Http\Request;
use App\Models\SeasonalSegment;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\DB;
use Maatwebsite\Excel\Facades\Excel;
use App\Models\TransactionMappingLog;
use App\Models\StatementTransactionOwner;
use App\Classes\ValueObjects\Constants\HttpStatus;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\Modules\Imports\Services\GenericImport;
use App\Classes\ValueObjects\Response\ApiResponseObject;
use App\Classes\Modules\Segments\Services\CreatesSeasonalSegment;
use App\Classes\Modules\Companies\Processors\AssignSegmentProcessor;
use App\Models\Company;
use App\Models\SeasonalSegment;
use App\Models\Transaction;
use App\Models\TransactionMappingLog;
use App\Classes\ValueObjects\Response\ApiResponseObject;
use App\Classes\ValueObjects\Constants\HttpStatus;
use Illuminate\Http\JsonResponse;
use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject;
use App\Classes\Modules\Segments\DataTransferObjects\SeasonalSegmentObject;
class ImportStatementReceiptsController
{
private $responseTitle;
private $responseMessage;
private $removeStr = 'Payment for ';
public function __construct() {
$this->responseTitle = 'Import Receipt Mapping';
$this->responseMessage = 'You have successfully imported receipt mapping';
@@ -39,63 +43,68 @@ class ImportStatementReceiptsController
*/
public function import(Request $request)
{
$importDate = date('Y-m-d H:i:s');
$object = new DocumentObject('', $request->input('files'), '', ApprovalStatus::APPROVED, 'imports');
$file = json_decode($object->getFiles()[0])->file_info->original->file;
try {
$importDate = date('Y-m-d H:i:s');
$object = new DocumentObject('', $request->input('files'), '', ApprovalStatus::APPROVED, 'imports');
$file = json_decode($object->getFiles()[0])->file_info->original->file;
$import = new GenericImport();
Excel::import($import, $file);
$excelRows = $import->rows;
$excelRows = $excelRows->toArray();
$import = new GenericImport();
Excel::import($import, $file);
$excelRows = $import->rows;
$excelRows = $excelRows->toArray();
$data = [];
foreach ($excelRows as $row) {
$row['mapped_result_reference'] = null;
$row['mapped_status'] = 'failed';
$row['date'] = $this->changeExcelDate($row['doc_date']);
$data = [];
foreach ($excelRows as $row) {
$row['mapped_result_reference'] = null;
$row['mapped_status'] = 'failed';
$row['date'] = in_array(gettype($row['doc_date']), ['integer', 'double']) ? $this->changeExcelDate($row['doc_date']) : date('Y-m-d', strtotime($row['doc_date']));
$returnReference = $this->mappingExchange($row);
if ($returnReference) {
$row['mapped_result_reference'] = $returnReference;
$row['mapped_status'] = 'success';
}
if ($invRefer = $this->getInvoiceReference($row['description'])) {
$returnReference = $this->mappingExchange($invRefer, $row['doc_no']);
if ($returnReference) {
$row['mapped_result_reference'] = $returnReference;
$row['mapped_status'] = 'success';
}
}
TransactionMappingLog::create([
'imported_date'=>$importDate,
'data'=>$row,
]);
array_push($data, $row);
}
return $this->response(['data'=>$data,'importedDate'=>$importDate]);
}
public function response(?array $data = []) : JsonResponse {
return (new ApiResponseObject($this->responseTitle,
$this->responseMessage,
HttpStatus::OK_WITH_MESSAGE, $data))->handler();
}
private function mappingExchange(Array $row) {
$date = $row['date'];
$transactions = Transaction::where('original_amount', $row['local_payment_amount'])->whereRaw("DATE(created_at) = '$date'")
->whereHas('issuerCompany', function($q) use($row) {
$q->where('debtor',$row['debtor_code']);
})
->get();
if ($transactions && $transactions->count() == 1) {
foreach ($transactions as $key => $transaction) {
return $this->updateTransactionOwnerReference($transaction, $row['doc_no']);
TransactionMappingLog::create([
'imported_date'=>$importDate,
'data'=>$row,
]);
array_push($data, $row);
}
return $this->response($this->responseTitle, $this->responseMessage, HttpStatus::OK_WITH_MESSAGE, ['data'=>$data,'importedDate'=>$importDate]);
} catch (\Exception $exception){
return $this->response('import invoice failed',$exception->getMessage(), ($exception->getCode()? $exception->getCode() : HttpStatus::SERVER_ERROR));
}
}
private function getInvoiceReference($invRefer) {
$arrStr = explode($this->removeStr, $invRefer);
if (isset($arrStr[1])) return $arrStr[1];
return null;
}
public function response(String $responseTitle, String $responseMessage, int $httpStatus, ?array $data = []) : JsonResponse {
return (new ApiResponseObject($responseTitle, $responseMessage, $httpStatus, $data))->handler();
}
private function mappingExchange($invRefer, $docNo) {
$transactionOwner = StatementTransactionOwner::where('invoice_reference',$invRefer)->whereNull('receipt_reference')->where('status', ApprovalStatus::COMPLETED)->first();
if ($transactionOwner) {
return $this->updateTransactionOwnerReference($transactionOwner, $docNo);
}
return false;
}
public function updateTransactionOwnerReference($transaction, String $docNo) {
$transactionOwner = $transaction->transaction_owner;
public function updateTransactionOwnerReference($transactionOwner, String $docNo) {
if ($transactionOwner) {
$transactionOwner->update(['receipt_reference'=>$docNo]);
$transactionOwner->update([
'receipt_reference'=>$docNo,
'status'=>ApprovalStatus::COMPLETED
]);
return $transactionOwner->owner_reference;
}
return false;
@@ -34,7 +34,8 @@ class BankStatementTransactionResource extends JsonResource
'owners' => [
'approved' => BankStatementTransactionOwnerResource::collection($this->owners()->whereIn('status', [ApprovalStatus::APPROVED])->get()),
'pending_verification' => BankStatementTransactionOwnerResource::collection($this->owners()->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION])->get()),
'rejected' => BankStatementTransactionOwnerResource::collection($this->owners()->whereIn('status', [ApprovalStatus::REJECTED])->get())
'rejected' => BankStatementTransactionOwnerResource::collection($this->owners()->whereIn('status', [ApprovalStatus::REJECTED])->get()),
'completed' => BankStatementTransactionOwnerResource::collection($this->owners()->whereIn('status', [ApprovalStatus::COMPLETED])->get()),
]
];
}
-10
View File
@@ -11,19 +11,9 @@ use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\ValueObjects\Constants\DocumentType;
use Carbon\Carbon;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
use Illuminate\Support\Facades\Log;
class BookingResource extends JsonResource
{
private $userInfo;
public function __construct($resource, $userInfo = null)
{
parent::__construct($resource);
$this->userInfo = $userInfo ?? ($resource->userInfo ?? null);
}
/**
* Transform the resource into an array.
*
-1
View File
@@ -15,7 +15,6 @@ use App\Models\SegmentConstant;
use Carbon\Carbon;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
class CompanyResource extends JsonResource
{
-3
View File
@@ -3,10 +3,7 @@
namespace App\Http\Resources;
use App\Models\Booking;
use App\Models\Company;
use App\Models\Document;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Auth;
@@ -0,0 +1,81 @@
<?php
namespace App\Http\Resources;
use App\Classes\Modules\Bookings\Services\CalculatesBookingFloatingAmount;
use App\Classes\Modules\Bookings\Services\CalculatesBookingOutstanding;
use App\Classes\Modules\Bookings\Services\CalculatesBookingPayableAmount;
use App\Classes\Modules\Bookings\Services\CalculatesBookingRefundAmount;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\ValueObjects\Constants\DocumentType;
use Carbon\Carbon;
use Illuminate\Http\Resources\Json\JsonResource;
class ListBookingJobResource extends JsonResource
{
private $userInfo;
public function __construct($resource, $userInfo = null)
{
parent::__construct($resource);
$this->userInfo = $userInfo ?? ($resource->userInfo ?? null);
}
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
* @throws \Illuminate\Contracts\Container\BindingResolutionException
*/
public function toArray($request)
{
return [
'id' => $this->id,
'company' => new CompanyResource($this->company, $this->userInfo),
'bank' => new BankResource($this->bank),
'service' => new ServiceTypeResource($this->service),
'marking' => $this->marking,
'amount' => $this->fix_amount,
'floating_amount' => floatval((App()->make(CalculatesBookingFloatingAmount::class))->execute($this->resource, $this->fix_currency_id)),
'paid_amount' => floatval((App()->make(CalculatesBookingPayableAmount::class))->execute($this->resource, $this->fix_currency_id)) - floatval((App()->make(CalculatesBookingRefundAmount::class))->execute($this->resource, $this->fix_currency_id)),
'outstanding_amount' => floatval((App()->make(CalculatesBookingOutstanding::class))->execute($this->resource)) - floatval((App()->make(CalculatesBookingRefundAmount::class))->execute($this->resource, $this->fix_currency_id)),
'fixed_currency' => new CurrencyResource($this->fixedCurrency),
'convertible_currency' => new CurrencyResource($this->convertibleCurrency),
'conversion_currency' => new CurrencyResource($this->conversionCurrency),
'documents' => [
'purchase_order' => new DocumentResource($this->documents()->where('document_type', DocumentType::PURCHASE_ORDER)->first()),
'delivery_order' => new DocumentResource($this->documents()->where('document_type', DocumentType::DELIVER_ORDER)->first()),
'invoice' => new DocumentResource($this->documents()->where('document_type', DocumentType::INVOICE)->first()),
'supplier_delivery_order' => new DocumentResource($this->documents()->where('document_type', DocumentType::SUPPLIER_DELIVER_ORDER)->first()),
'proforma_invoice' => new DocumentResource($this->documents()->where('document_type', DocumentType::PROFORMA_INVOICE)->whereNotIn('status', [ApprovalStatus::REJECTED, ApprovalStatus::EXPIRED])->orderByDesc('id')->first()),
'ecommerce_purchase_order' => new DocumentResource($this->documents()->where('document_type', DocumentType::ECOMMERCE_PURCHASE_ORDER)->first()),
],
'status' => $this->status,
'created_at' => Carbon::parse($this->created_at)->format('d-m-Y'),
'created_at_with_time' => Carbon::parse($this->created_at)->format('d-m-Y h:i:s A'),
$this->mergeWhen($this->relationLoaded('transactions'), [
'purchase_order' => new TransactionResource($this->transactions()->where('type', TransactionType::PURCHASE_ORDER)->first()),
'payment_attempts' => TransactionResource::collection(
$this->transactions()
->payments()->where('status', ApprovalStatus::PENDING_SUBMISSION)
->whereDate('expires_on', '>=', Carbon::now())
->get()
),
'expired_payment_attempts' => TransactionResource::collection($this->transactions()->payments()->where('status', ApprovalStatus::PENDING_SUBMISSION)->whereDate('expires_on', '>=', Carbon::now())->where('expires_on', '>', Carbon::now()->toTimeString())->get()),
'payment_history' => TransactionResource::collection($this->transactions()->where(function($query){
$query->where(function($query){
$query->payments()->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::COMPLETED, ApprovalStatus::REJECTED]);
})->orWhere(function($query){
$query->where(function($query){
$query->where('type', TransactionType::REFUND)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::REJECTED, ApprovalStatus::COMPLETED]);
})->orWhere(function($query){
$query->where('type', TransactionType::CREDIT_NOTE)->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]);
});
});
})->latest()->get())
])
];
}
}
@@ -0,0 +1,31 @@
<?php
namespace App\Http\Resources;
use App\Models\Booking;
use Carbon\Carbon;
use Illuminate\Http\Resources\Json\JsonResource;
use App\Http\Resources\V2\BookingV2Resource;
use App\Http\Resources\V2\CompanyV2Resource;
class ListDocumentJobResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'reference' => $this->reference,
'status' => (int) $this->status,
'document_type' => $this->document_type,
'owner' => $this->relationLoaded('owner') ? ($this->owner instanceof Booking ? new BookingV2Resource($this->owner, $this->userInfo) : new CompanyV2Resource($this->owner, $this->userInfo)) : null,
'files' => FileResource::collection($this->files),
'created_at' => Carbon::parse($this->created_at)->format('d-m-Y h:i:s A')
];
}
}
@@ -0,0 +1,54 @@
<?php
namespace App\Http\Resources;
use App\Classes\ValueObjects\Constants\TransactionType;
use Carbon\Carbon;
use Illuminate\Http\Resources\Json\JsonResource;
class ListTransactionJobResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
$booking = in_array((int)$this->type, [TransactionType::BILL, TransactionType::REFUND])? $this->owner->owner : $this->owner;
$days = $this->created_at->endOfDay()->addWeekdays($booking->service_id === 3 ? 3 : 1);
return [
'id' => $this->id,
'booking' => new BookingResource($booking),
'type' => (int) $this->type,
'bill_no' => $this->bill_no,
'payment_reference' => $this->payment_reference,
'payment_method' => (float) $this->payment_method,
'recipient_bank_account' => new BankResource($booking->bank),
'issuer_name' => $this->issuerCompany->name,
'issuer_id' => $this->issuerCompany->id,
'amount' => (double) $this->amount,
'original_amount' => (double) $this->original_amount,
'currency' => new CurrencyResource($this->currency),
'original_currency' => new CurrencyResource($this->original_currency),
'service_charge' => (double) $this->service_charge,
'tax' => (double) $this->tax,
'currency_rate' => (double) $this->currency_rate,
'status' => (int) $this->status,
'details' => TransactionDetailResource::collection($this->transactionDetails),
'documents' => new DocumentResource($this->documents()->first()),
'transaction_bill' => new TransactionResource($this->when((int) $this->type === TransactionType::PAYMENT, $this->transactions()->bills()->first())),
'transaction_refunds' => TransactionResource::collection($this->when((int) $this->type === TransactionType::PAYMENT, $this->transactions()->refunds()->get())),
'expires_on' => Carbon::parse($this->expires_on)->format('d-m-Y h:i:s A'),
'updated_at' => Carbon::parse($this->updated_at)->format('d-m-Y h:i:s A'),
'interval' => [
'value' => $days->gt(Carbon::now()) ? '+' : '-',
'duration' => $days->diff(Carbon::now())->format('%d'),
],
'redemption' => new VoucherRedemptionResource($this->voucherRedemption)
];
}
}
@@ -0,0 +1,82 @@
<?php
namespace App\Http\Resources\V2;
use App\Classes\Modules\Bookings\Services\CalculatesBookingFloatingAmount;
use App\Classes\Modules\Bookings\Services\CalculatesBookingOutstanding;
use App\Classes\Modules\Bookings\Services\CalculatesBookingPayableAmount;
use App\Classes\Modules\Bookings\Services\CalculatesBookingRefundAmount;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\ValueObjects\Constants\DocumentType;
use Carbon\Carbon;
use Illuminate\Http\Resources\Json\JsonResource;
use App\Http\Resources as V1;
class BookingV2Resource extends JsonResource
{
private $userInfo;
public function __construct($resource, $userInfo = null)
{
parent::__construct($resource);
$this->userInfo = $userInfo ?? ($resource->userInfo ?? null);
}
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
* @throws \Illuminate\Contracts\Container\BindingResolutionException
*/
public function toArray($request)
{
return [
'id' => $this->id,
'company' => new CompanyV2Resource($this->company, $this->userInfo),
'bank' => new V1\BankResource($this->bank),
'service' => new V1\ServiceTypeResource($this->service),
'marking' => $this->marking,
'amount' => $this->fix_amount,
'floating_amount' => floatval((App()->make(CalculatesBookingFloatingAmount::class))->execute($this->resource, $this->fix_currency_id)),
'paid_amount' => floatval((App()->make(CalculatesBookingPayableAmount::class))->execute($this->resource, $this->fix_currency_id)) - floatval((App()->make(CalculatesBookingRefundAmount::class))->execute($this->resource, $this->fix_currency_id)),
'outstanding_amount' => floatval((App()->make(CalculatesBookingOutstanding::class))->execute($this->resource)) - floatval((App()->make(CalculatesBookingRefundAmount::class))->execute($this->resource, $this->fix_currency_id)),
'fixed_currency' => new V1\CurrencyResource($this->fixedCurrency),
'convertible_currency' => new V1\CurrencyResource($this->convertibleCurrency),
'conversion_currency' => new V1\CurrencyResource($this->conversionCurrency),
'documents' => [
'purchase_order' => new V1\DocumentResource($this->documents()->where('document_type', DocumentType::PURCHASE_ORDER)->first()),
'delivery_order' => new V1\DocumentResource($this->documents()->where('document_type', DocumentType::DELIVER_ORDER)->first()),
'invoice' => new V1\DocumentResource($this->documents()->where('document_type', DocumentType::INVOICE)->first()),
'supplier_delivery_order' => new V1\DocumentResource($this->documents()->where('document_type', DocumentType::SUPPLIER_DELIVER_ORDER)->first()),
'proforma_invoice' => new V1\DocumentResource($this->documents()->where('document_type', DocumentType::PROFORMA_INVOICE)->whereNotIn('status', [ApprovalStatus::REJECTED, ApprovalStatus::EXPIRED])->orderByDesc('id')->first()),
'ecommerce_purchase_order' => new V1\DocumentResource($this->documents()->where('document_type', DocumentType::ECOMMERCE_PURCHASE_ORDER)->first()),
],
'status' => $this->status,
'created_at' => Carbon::parse($this->created_at)->format('d-m-Y'),
'created_at_with_time' => Carbon::parse($this->created_at)->format('d-m-Y h:i:s A'),
$this->mergeWhen($this->relationLoaded('transactions'), [
'purchase_order' => new V1\TransactionResource($this->transactions()->where('type', TransactionType::PURCHASE_ORDER)->first()),
'payment_attempts' => V1\TransactionResource::collection(
$this->transactions()
->payments()->where('status', ApprovalStatus::PENDING_SUBMISSION)
->whereDate('expires_on', '>=', Carbon::now())
->get()
),
'expired_payment_attempts' => V1\TransactionResource::collection($this->transactions()->payments()->where('status', ApprovalStatus::PENDING_SUBMISSION)->whereDate('expires_on', '>=', Carbon::now())->where('expires_on', '>', Carbon::now()->toTimeString())->get()),
'payment_history' => V1\TransactionResource::collection($this->transactions()->where(function($query){
$query->where(function($query){
$query->payments()->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::COMPLETED, ApprovalStatus::REJECTED]);
})->orWhere(function($query){
$query->where(function($query){
$query->where('type', TransactionType::REFUND)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::REJECTED, ApprovalStatus::COMPLETED]);
})->orWhere(function($query){
$query->where('type', TransactionType::CREDIT_NOTE)->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]);
});
});
})->latest()->get())
])
];
}
}
+100
View File
@@ -0,0 +1,100 @@
<?php
namespace App\Http\Resources\V2;
use App\Classes\Modules\Companies\Services\FetchesCompanyServices;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\BankAccountType;
use App\Classes\ValueObjects\Constants\BusinessType;
use App\Classes\ValueObjects\Constants\DocumentType;
use App\Classes\ValueObjects\Constants\RoleTypes;
use App\Classes\ValueObjects\Constants\SegmentConstants;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Currency;
use App\Models\SegmentConstant;
use Carbon\Carbon;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Facades\Auth;
use App\Http\Resources as V1;
class CompanyV2Resource extends JsonResource
{
private $userInfo;
public function __construct($resource, $userInfo = null)
{
parent::__construct($resource);
$this->userInfo = $userInfo;
}
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
$lastPayment = $this->transactions()->where('transactions.type', TransactionType::PAYMENT)->whereIn('transactions.status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->orderBy('id', 'DESC')->first();
$totalPayments = $this->transactions()->where('transactions.type', TransactionType::PAYMENT)->whereIn('transactions.status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->sum('amount');
$segment = SegmentConstant::where('reference', SegmentConstants::SUPPLIER_CURRENCIES)->where('detail->id', $this->id)->first();
$serviceCharge = SegmentConstant::where('reference', SegmentConstants::SERVICE_CHARGE)->where('detail->id', $this->id)->first();
$userResource = null;
$userInfoEmail = $this->userInfo && isset($this->userInfo->email) ? $this->userInfo->email : null;
$userInfoType = $this->userInfo && isset($this->userInfo->type) ? $this->userInfo->type : null;
if(!$userInfoEmail && Auth::user()){
$userInfoEmail = Auth::user()->email;
}
if(!$userInfoType && Auth::user()){
$userInfoType = Auth::user()->type;
}
if(!is_null($userInfoEmail) && !is_null($userInfoType)){
$userResource = new V1\UserResource($userInfoType === RoleTypes::USER ? $this->employees()->where('email', '=', $userInfoEmail)->first() : $this->employees()->orderBy('id', 'DESC')->first());
}
return [
'id' => $this->id,
'name' => $this->name,
'reference' => $this->reference,
'debtor' => $this->debtor,
'type' => (int) $this->type,
'business_type' => (int) $this->business_type,
'status' => (int) $this->status,
'contact' => new V1\ContactResource ($this->when($this->has('contacts'), $this->contacts->first())),
'address' => new V1\AddressResource($this->when($this->has('addresses'), $this->addresses->where('billing', true)->first())),
'employee' => $userResource,
'identification' => new V1\DocumentResource($this->documents->whereIn('document_type', DocumentType::IDENTIFICATION_DOCUMENTS)->first()),
'bookings' => $this->whenLoaded('bookings', $this->bookings()->orderBy('id', 'DESC')->get(), []),
'confirmed_bookings' => $this->bookings()->whereHas('transactions', function ($query){
$query->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]);
})->count(),
'total_payments' => (float) $totalPayments,
'average_spending_per_day' => (float) $totalPayments / ($this->created_at->diff(Carbon::now())->days === 0 ? 1 : $this->created_at->diff(Carbon::now())->days),
'average_spending_per_booking' => (float) $totalPayments > 0 ? $totalPayments / $this->bookings()->whereHas('transactions', function ($query){
$query->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]);
})->count() : $totalPayments,
'last_payment' => $lastPayment ? $lastPayment->created_at->diffForHumans() : 'No Payments',
'personal_banks' => V1\BankResource::collection($this->banks->where('type', BankAccountType::PERSONAL)),
'recipient_banks' => [
'accounts' => V1\BankResource::collection($this->banks->where('type', BankAccountType::EXTERNAL)),
'default' => new V1\BankResource($this->banks->where('type', BankAccountType::EXTERNAL)->where('default', true)->first())
],
'segments' => V1\SegmentResource::collection($this->segments),
'seasonalSegment' => $this->whenLoaded('seasonalSegments', V1\SeasonalSegmentResource::collection($this->seasonalSegments)),
'services' => (new FetchesCompanyServices())->getServices($this->servicesConfigurations()),
'wallet' => $this->whenLoaded('wallets', new V1\WalletResource($this->wallets()->with('transactions')->first()), new V1\WalletResource($this->wallets()->first())),
'created_at' => $this->created_at->format('d-m-Y'),
$this->mergeWhen($this->business_type === BusinessType::CURRENCY_VENDOR, [
'currencies' => $segment ? V1\CurrencyResource::collection(Currency::whereIn('id', $segment->detail->currencies)->get()) : [],
'service_charge' => $serviceCharge
])
];
}
}
+2
View File
@@ -16,6 +16,8 @@ class AccountStatement extends Model
'total_amount',
'begin_balance',
'end_balance',
'total_rows',
'mapped_rows',
];
protected $casts = [
+19 -7
View File
@@ -109,7 +109,7 @@ class Company extends AbstractModel implements Documentable
{
return $this->hasManyDeep(Transaction::class, [Booking::class], ['company_id', 'owner_id'], ['id', 'id']);
}
/**
* @return HasMany
*/
@@ -130,13 +130,25 @@ class Company extends AbstractModel implements Documentable
* @return Builder
*/
public function services(): Builder {
return ServiceType::where('status', ApprovalStatus::APPROVED)->whereHas('constants', function($query) {
$query->Where(function($query){
$query->where('reference', SegmentConstants::SERVICE_TYPE)->where('detail->is_active', true);
})->orWhere(function($query) {
$query->where('reference', SegmentConstants::CUSTOM_SERVICE_TYPE)->where('detail->is_active', true)->whereIn('segment_id', $this->segments->pluck('id'));
if ($this->business_type === 3) {
return ServiceType::where('status', ApprovalStatus::APPROVED)->whereHas('constants', function($query) {
$query->where(function($query) {
$query->where('reference', SegmentConstants::SERVICE_TYPE)->where('detail->is_active', true);
})->orWhere(function($query) {
$query->where('reference', SegmentConstants::CUSTOM_SERVICE_TYPE)->where('detail->is_active', true);
});
});
});
} else {
// Existing logic for other company types
return ServiceType::where('status', ApprovalStatus::APPROVED)->whereHas('constants', function($query) {
$query->Where(function($query){
$query->where('reference', SegmentConstants::SERVICE_TYPE)->where('detail->is_active', true);
})->orWhere(function($query) {
$query->where('reference', SegmentConstants::CUSTOM_SERVICE_TYPE)->where('detail->is_active', true)->whereIn('segment_id', $this->segments->pluck('id'));
});
});
}
}
public function servicesConfigurations(): Collection {
+5
View File
@@ -49,6 +49,11 @@ class StatementTransaction extends Model
return $this->hasMany(StatementTransactionOwner::class);
}
public function owner_status()
{
return $this->owners()->whereIn('status',[ApprovalStatus::APPROVED,ApprovalStatus::COMPLETED,ApprovalStatus::PENDING_VERIFICATION]);
}
public function scopeDoesntMapStatement($query)
{
$query->whereDoesntHave('owners', function($query){
+1
View File
@@ -5,6 +5,7 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphTo;
class StatementTransactionOwner extends Model
{
+16
View File
@@ -221,6 +221,22 @@ class Transaction extends AbstractModel implements Documentable, Transactionable
return $query->whereIn('status', [ApprovalStatus::APPROVED]);
}
/**
* @param Builder $query
* @return Builder
*/
public function scopeGetReceiverWithJoinStatementTransactionAndOwner(Builder $query, Array $row) {
$query->join('companies',function($q) use ($row) {
$q->on('companies.id','=','transactions.receiver');
$q->where('debtor',$row['debtor_code']);
})
->join('statement_transaction_owners', function ($q) {
$q->on('statement_transaction_owners.owner_id','=','transactions.id');
$q->where('statement_transaction_owners.owner_type','=',Transaction::class);
})
->join('statement_transactions','statement_transactions.id','=','statement_transaction_owners.statement_transaction_id');
}
/**
* @return MorphMany
*/
@@ -16,7 +16,7 @@ class CreateJobResultsTable extends Migration
Schema::create('job_results', function (Blueprint $table) {
$table->id();
$table->string('job_id', 50);
$table->longText('result');
$table->longText('result')->nullable();
$table->timestamps();
// $table->foreign('job_id')->references('id')->on('jobs')->onDelete('cascade');
@@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddMappedRateToAccountStatementsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('account_statements', function (Blueprint $table) {
$table->integer('total_rows')->unsigned()->default(0)->after('end_balance');
$table->integer('mapped_rows')->unsigned()->default(0)->after('end_balance');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('account_statements', function (Blueprint $table) {
$table->dropColumn('total_rows');
$table->dropColumn('mapped_rows');
});
}
}
@@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddNewColumn2ToJobResultsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('job_results', function (Blueprint $table) {
$table->string('request_signature')->after('job_id')->nullable();
$table->string('result_signature')->after('request_signature')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('job_results', function (Blueprint $table) {
$table->dropColumn('request_signature');
$table->dropColumn('result_signature');
});
}
}
@@ -4,6 +4,8 @@
<div class="row p-b-10 b-b b-grey">
<div class="col-2">{{ item.posting_date }}</div>
<div class="col-2">{{ item.transaction_description_1 + ' - ' + item.transaction_description_2 }}</div>
<!-- Mapping Approval tab -->
<div class="col-5" v-if="item.owners.pending_verification.length === 1">
<div class="row">
<div class="col">{{item.owners.pending_verification[0].system}}</div>
@@ -51,6 +53,7 @@
</div>
</div>
<!-- Mapping Review tab -->
<div class="col-5" v-if="item.owners.pending_verification.length > 1">
<div class="row">
<div class="col">
@@ -93,6 +96,7 @@
</div>
</div>
<!-- unknow tab -->
<div class="col-5" v-if="!item.owners.pending_verification.length && !item.owners.approved.length">
<div class="row">
<div class="col">
@@ -126,7 +130,7 @@
<!-- Pending Export tab for checkbox here -->
<div class="col-1" v-if="item.owners.approved.length === 1">
<input type="checkbox" class="request_export_item" v-model="selectAll" :value="item.owners.approved[0].id">
<input type="checkbox" class="request_export_item" v-model="selectAll" :value="item.id">
</div>
<div class="col-1 text-danger" v-if="!item.owners.approved.length">Pending...</div>
@@ -6,11 +6,11 @@
<div class="col-2">{{ item.transaction_description_1 + ' - ' + item.transaction_description_2 }}</div>
<div class="col-7">
<div class="row">
<div class="col">{{item.owners.approved[0].system}}</div>
<div class="col">{{ typeString(item.owners.approved[0].type) }}</div>
<div class="col"><a :href="item.owners.approved[0].reference_link" target="_blank">{{item.owners.approved[0].reference}}</a></div>
<div class="col">{{item.owners.approved[0].invoice_reference}}</div>
<div class="col">{{item.owners.approved[0].receipt_reference}}</div>
<div class="col">{{item.owners.completed[0].system}}</div>
<div class="col">{{ typeString(item.owners.completed[0].type) }}</div>
<div class="col"><a :href="item.owners.completed[0].reference_link" target="_blank">{{item.owners.completed[0].reference}}</a></div>
<div class="col">{{item.owners.completed[0].invoice_reference}}</div>
<div class="col">{{item.owners.completed[0].receipt_reference}}</div>
</div>
</div>
@@ -8,6 +8,11 @@
<div class="card">
<div class="card-header">
<h3>{{ componentTitle }}</h3>
<div class="row m-b-10 animate__animated animate__fadeInUpBig animate__fast" v-if="error">
<div class="col">
<small class="bold fs-10 text-danger">{{error}}</small>
</div>
</div>
<div class="text-right">
<button class="btn btn-xs btn-outline-success b-rad-none m-r-5" @click="downloadInvoiceMapped">
Download Invoices Mapped
@@ -34,6 +39,7 @@
<td>{{item.cancelled}}</td>
<td>{{item.mapped_status}}</td>
<td>{{item.mapped_result_reference}}</td>
<td>{{item.payment_received_date}}</td>
</tr>
</tbody>
</table>
@@ -69,6 +75,7 @@
data() {
return {
isLoading: false,
error: '',
importedDate: null,
}
},
@@ -95,7 +102,7 @@
},
appendComponentTableHeader() {
if (this.section == 'importInvoiceMapping') {
this.tableHeaders = ['No','Doc No','Date','Debtor Code','Debtor Name','Shipping Info','Net Total','Cancelled','Mapped Status','Mapped Reference No'];
this.tableHeaders = ['No','Doc No','Date','Debtor Code','Debtor Name','Shipping Info','Net Total','Cancelled','Mapped Status','Mapped Reference No','Payment Received Date'];
} else {
this.tableHeaders = ['No','OR No','Date','Creditor Code','Creditor Name','Shipping Info','Net Total','Cancelled','Mapped Status','Mapped Reference No'];
}
@@ -114,6 +121,11 @@
this.isLoading = false;
},
errorHandler(error){
this.isLoading = false;
this.error = error.message;
},
downloadInvoiceMapped() {
var arrDateTime = this.importedDate.split(" ");
const fileName = this.section == 'importInvoiceMapping' ? 'InvoiceMapped' : 'ReceiptMapped';
@@ -57,7 +57,7 @@
},
methods: {
getReportFilter() {
this.filter = {min_amount: 0, is_mapped: true, statement_transaction_owner_type_in: [1, 2], statement_transaction_owner_status_in: [2], statement_transaction_owner_invoice_or_receipt_ref_not_null: true, per_page: 100, order_by: {column: 'posting_date', DESC: true}};
this.filter = {min_amount: 0, is_mapped: true, statement_transaction_owner_type_in: [1, 2], statement_transaction_owner_status_in: [3], per_page: 100, order_by: {column: 'posting_date', DESC: true}};
this.step = 1
}
@@ -74,6 +74,32 @@
</general-confirmation-form-component>
</modal-component>
</div>
<!-- filter for Pending Export tab -->
<div v-if="stage === 4">
<div class="row pt-3 pb-3">
<div class="col-5 col-md-3 ">
<validation-wrapper-component :validator="$v.parameters.startDate">
<label class="all-caps">Start Date</label>
<date-picker-component :parameters="parameters" v-model.lazy="parameters.startDate"></date-picker-component>
</validation-wrapper-component>
</div>
<div class="col-5 col-md-3 ">
<validation-wrapper-component :validator="$v.parameters.endDate">
<label class="all-caps">End Date</label>
<date-picker-component :parameters="parameters" v-model.lazy="parameters.endDate"></date-picker-component>
</validation-wrapper-component>
</div>
<div class="col-2 col-md-auto">
<div class="btn btn-lg btn-primary fs-11 w-100 h-100 d-flex justify-content-center align-items-center" @click="startMapping(4)">
<span>
Search
</span>
</div>
</div>
</div>
</div>
<div class="row m-t-10 m-b-10">
<div class="col">
<div class="row p-t-10 p-b-10 b-b b-grey text-master-light">
@@ -202,6 +228,10 @@ export default {
data(){
return {
parameters: {
startDate: '',
endDate: '',
},
type: null,
stage: null,
exportStage: 0,
@@ -215,6 +245,14 @@ export default {
}
},
validations: {
parameters: {
startDate: {
required
},
endDate: {
required
},
},
files: {
// required // todo-new: set required if is pdf section
}
@@ -227,17 +265,33 @@ export default {
this.mappedTrue = true;
},
exportInvoiceToAutoCount(){
window.open(this.route('invoiceTransactions.export')+'?bankStatementOwnerId='+this.getCheckedStatementOwners()+'&type=invoices', '_blank');
const checkedStatementTransactions = this.getCheckedStatementOwners();
let route = this.route('invoiceTransactions.export')+'?filter='+JSON.stringify(this.filter);
if (checkedStatementTransactions) {
route += '&bankStatementTransactionId='+checkedStatementTransactions;
}
window.open(route, '_blank');
},
exportReceiptToAutoCount(){
window.open(this.route('invoiceTransactions.export')+'?bankStatementOwnerId='+this.getCheckedStatementOwners()+'&type=receipts', '_blank');
const checkedStatementTransactions = this.getCheckedStatementOwners();
this.filter['where_has_owners_and_null'] = 'statement_transaction_owners.receipt_reference';
this.filter['where_has_owners_and_not_null'] = 'statement_transaction_owners.invoice_reference';
let route = this.route('receiptTransactions.export')+'?filter='+JSON.stringify(this.filter);
if (checkedStatementTransactions) {
route += '&bankStatementTransactionId='+checkedStatementTransactions;
}
window.open(route, '_blank');
},
getCheckedStatementOwners() {
let bankStatementOwnerId = [];
let bankStatementTransactionId = [];
$('.request_export_item:checked').each(function() {
bankStatementOwnerId.push($(this).val());
bankStatementTransactionId.push($(this).val());
});
return JSON.stringify(bankStatementOwnerId);
return (bankStatementTransactionId.length > 0 ? JSON.stringify(bankStatementTransactionId) : null);
},
successHandler(){
this.step += 1;
@@ -259,10 +313,14 @@ export default {
this.filter = {min_amount: 0, is_mapped: true, is_mapped_with_multiple: true, statement_transaction_owner_type_in: [1, 2], statement_transaction_owner_status_in: [1], per_page: 100, order_by: {column: 'posting_date', DESC: true}}
break;
case 3:
this.filter = {min_amount: 0, is_mapped: false, per_page: 100, order_by: {column: 'posting_date', DESC: true}}
this.filter = {min_amount: 0, is_mapped_false_or_mapped_but_status_in: [4], per_page: 100, order_by: {column: 'posting_date', DESC: true}}
break;
case 4:
this.filter = {min_amount: 0, is_mapped: true, statement_transaction_owner_type_in: [1, 2], statement_transaction_owner_status_in: [2], per_page: 100, order_by: {column: 'posting_date', DESC: true}}
if (typeof this.parameters.startDate != 'undefined' && this.parameters.startDate != '') this.filter = {...this.filter, ...{statement_transaction_posting_start: this.parameters.startDate}};
if (typeof this.parameters.endDate != 'undefined' && this.parameters.endDate != '') this.filter = {...this.filter, ...{statement_transaction_posting_end:this.parameters.endDate}};
break;
}
}
@@ -280,6 +338,11 @@ export default {
break;
case 4:
this.filter = {max_amount: 0, is_mapped: true, statement_transaction_owner_type_in: [3, 5], statement_transaction_owner_status_in: [2], per_page: 100, order_by: {column: 'posting_date', DESC: true}}
if (typeof this.parameters.startDate != 'undefined' && this.parameters.startDate != '') this.filter = {...this.filter, ...{statement_transaction_posting_start: this.parameters.startDate}};
if (typeof this.parameters.endDate != 'undefined' && this.parameters.endDate != '') this.filter = {...this.filter, ...{statement_transaction_posting_end:this.parameters.endDate}};
break;
}
}
@@ -22,7 +22,7 @@
</div>
</div>
</div>
<div class="col d-none d-lg-block" v-if="$store.getters.isAdmin">
<div class="col-auto d-none d-lg-block" v-if="$store.getters.isAdmin">
<div class="font-heading fs-10 muted all-caps">Marking</div>
<div class="font-heading">
<a :href="route('customer.profile', item.company.reference)">{{this.item.company.reference}}</a>
@@ -34,7 +34,7 @@
<span class="flag-icon" :class="'flag-icon-'+item.convertible_currency.country.short_code.toLowerCase()"></span> {{this.item.convertible_currency.short_code}}
</div>
</div>
<div class="col-auto d-none d-lg-block">
<div class="col-3 d-none d-lg-block">
<div class="font-heading fs-10 muted all-caps">Transfer Type</div>
<div class="font-heading fs-12">{{this.item.service.name}}</div>
</div>
File diff suppressed because one or more lines are too long
@@ -289,6 +289,22 @@
<regenerate-booking-invoices-component :data="booking" :section="section" class="text-center"></regenerate-booking-invoices-component>
</modal-component>
</div>
<div class="row m-t-10" v-if="$store.getters.isSuperAdmin">
<div class="col-sm col-md-auto">
<div class="btn btn-sm btn block all-caps b-rad-none btn-danger pointer requestModal" data-type="deleteTransfer">Delete Transfer</div>
</div>
<modal-component class="animate__animated animate__fast animate__fadeIn" type="deleteTransfer">
<general-confirmation-form-component
contentText="Are you sure you want to delete this Order?"
modalType="delete"
class="text-center"
:apiRoute="route('api.booking.payment.expire', booking.id)"
apiMethod="post"
:section="section"
>
</general-confirmation-form-component>
</modal-component>
</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>
@@ -117,6 +117,12 @@
</div>
<div class="row">
<div class="col">
<!-- CIEF TODO: For easy revert to old code -->
<!-- <list-component ref="pendingOrdersList" section="pendingOrdersSection" :endpoint="route('api.transaction.list')" :options="{per_page: 5, status: 2, owner_type: 'App\\Models\\Booking', type: 1, original_currency_id_in: [selectedCurrency.id], transaction_service_id: selectedService.id}">
<template slot="list" slot-scope="{data}">
<supplier-pending-order-component :data="data" v-on:input="updateOrder($event)"></supplier-pending-order-component>
</template>
</list-component> -->
<list-polling-component ref="pendingOrdersList" section="pendingOrdersSection" :endpoint="route('api.transaction.list.job')" :options="{per_page: 5, status: 2, owner_type: 'App\\Models\\Booking', type: 1, original_currency_id_in: [selectedCurrency.id], transaction_service_id: selectedService.id}">
<template slot="list" slot-scope="{data}">
<supplier-pending-order-component :data="data" v-on:input="updateOrder($event)"></supplier-pending-order-component>
@@ -99,6 +99,7 @@
updateFilters(filters){
this.filters = filters;
this.setDecoratorDefault();
this.$store.dispatch('updateListQueue', {'name': this.section, 'page': 1, 'filters': this.filters});
this.submit(this.endpoint + '?page=1&filters=' + JSON.stringify(this.filters), 'get', this.section, false, false)
},
successHandler(response){
+49
View File
@@ -0,0 +1,49 @@
export default {
methods: {
poll(url, method, section, successNotification = true, errorNotification = true){
if(!this.validate()){ return; }
if (section) {
this.$store.dispatch('toggleLoading', {name: section, status: true})
}
this.$store.dispatch('crudRequestV2', {
endpoint: url,
method: method,
parameters: this.parameters
}).then(response => {
let statusCode = response.status,
success = response.ok;
response.json().then(response => {
if(!success){
this.openModal();
errorNotification ? this.$store.dispatch('createNotification', {title: response.title, message: response.message, type: 'error'}): null;
this.errorHandler(response, statusCode); return;
}
successNotification ? this.$store.dispatch('createNotification', {title: response.title, message: response.message, type: 'success'}): null;
this.successHandler(response)
});
}).catch((error) => {
this.$store.dispatch('createNotification', {title: 'Unexpected Error', message: 'An unexpected error has occurred. Try again!', type: 'error'});
}).then(() => {
if (section) {
this.$store.dispatch('toggleLoading', {name: section, status: false})
}
})
},
validate() {
if(this.$v){
this.$v.$touch();
return !this.$v.$invalid;
}
return true;
},
successHandler(response){},
errorHandler(response){}
}
}
+24
View File
@@ -0,0 +1,24 @@
export default {
data() {
return {
activeTab: null,
displayedTabs: [],
};
},
methods: {
setActiveTab(event) {
const tabName = event.currentTarget.getAttribute('tab-name');
// console.log(`Tab "${tabName}" clicked`);
this.activeTab = tabName;
if (!this.displayedTabs.includes(tabName)) {
this.displayedTabs.push(tabName);
}
},
isActiveTab(tabName) {
return this.activeTab === tabName;
},
showTabContent(tabName) {
return this.displayedTabs.includes(tabName);
},
},
}
+51
View File
@@ -0,0 +1,51 @@
export default {
actions: {
crudRequestV2({getters, dispatch}, {endpoint, method, parameters}){
return dispatch('ensureReCaptchaIsSet').then(function () {
const queryDomain = endpoint.split('?')[0];
let encodedParams = endpoint.split('?')[1];
let decodedParams = fullyDecodeURI(encodedParams);
const queryParams = encodeURIComponent(decodedParams);
encodedParams = queryParams.toString();
let filteredEncodedParams = encodedParams.replace(/%3D/g,'=');
filteredEncodedParams = filteredEncodedParams.replace(/%26/g,'&');
let combinedAbsoluteUrl = queryDomain;
if(filteredEncodedParams !== undefined && filteredEncodedParams !== 'undefined'){
combinedAbsoluteUrl = queryDomain + '?' + filteredEncodedParams;
}
// return fetch(endpoint, {
return fetch(combinedAbsoluteUrl, {
method: method,
responseType: 'json',
body: parameters ? JSON.stringify(parameters):null,
headers: {
'content-type': 'application/json',
'Authorization': 'Bearer '+getters.getAccessToken,
'captcha-token': getters.getReCaptcha
}
}).then(response => {
if(response.status === 401 && window.location.href !== route('login')){
dispatch('userAuthentication', {access_token: '', redirect_url: '/'});
}
return response;
})
});
}
}
}
function isEncoded(uri) {
uri = uri || '';
return uri !== decodeURIComponent(uri);
}
function fullyDecodeURI(uri){
while (isEncoded(uri)){
uri = decodeURIComponent(uri);
}
return uri;
}
+3 -1
View File
@@ -4,6 +4,7 @@ import toggleSection from './modules/toggleSection'
import toggleLoading from './modules/toggleLoading'
import createNotification from './modules/createNotification'
import crudRequest from './modules/crudRequest'
import crudRequestV2 from './modules/crudRequestV2'
import authentication from './modules/authentication'
import loadRequestQueue from './modules/loadRequestQueue'
@@ -16,6 +17,7 @@ export default new Vuex.Store({
loadRequestQueue,
createNotification,
crudRequest,
crudRequestV2,
authentication
}
})
})
File diff suppressed because one or more lines are too long
+1
View File
@@ -20,6 +20,7 @@ Route::group(['prefix' => 'booking', 'as' => 'booking.', 'namespace' => 'Booking
Route::post('create', 'CreateBookingPaymentController@create')->name('create');
Route::post('{payment_id}/verification/create', 'CreatePaymentVerificationController@create')->name('verification.create');
Route::put('/{payment_id}/approval/{status}', 'ApprovePaymentVerificationController@approve')->where('status', 'approve|reject')->name('approval');
Route::post('delete', 'ExpireBookingPaymentController@expire')->name('expire');
});
Route::group(['prefix' => '{id}/refund', 'as' => 'refund.'], function () {
+80 -2
View File
@@ -26,7 +26,7 @@ use Webklex\PDFMerger\Facades\PDFMergerFacade as PDFMerger;
use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject;
use App\Classes\Modules\Bookings\Processors\CreatePurchaseOrderFor1688OrderProcessor;
use App\Classes\Modules\Documents\Services\DeletesDocument;
use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionProcessorWithInvoiceNo;
use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionWithInvoiceNoProcessor;
use App\Classes\Modules\Transactions\Services\DeletesTransaction;
use Illuminate\Support\Facades\Log;
@@ -261,6 +261,7 @@ Route::get('/export/payment-transactions/f614e339d7058904a831aad742e24d55', 'Exp
Route::get('/export/wallet-transactions/f614e339d7058904a831aad742e24d55', 'Exports\ExportCustomersToExcelController@walletTransactions')->name('walletTransactions.export');
Route::get('/export/booking-transactions', 'Exports\ExportCustomersToExcelController@bookingTransactions')->name('export.transactions.booking');
Route::get('/export/invoice-transactions/f614e339d7058904a831aad742e24d55', 'Exports\ExportCustomersToExcelController@invoiceTransactions')->name('invoiceTransactions.export');
Route::get('/export/receipt-transactions/f614e339d7058904a831aad742e24d55', 'Exports\ExportCustomersToExcelController@receiptTransactions')->name('receiptTransactions.export');
Route::get('/export/imported-invoice-mapped', 'Exports\ExportCustomersToExcelController@importedInvoiceMapped')->name('importedInvoiceMapped.export');
Route::get('/products', function (\App\Classes\Modules\Exports\Services\ExportsProducts $exportsProducts) {
@@ -545,7 +546,7 @@ Route::get('/invoice/fix', function(){
$existing_invoice_bill_no->forceDelete();
}
(App()->make(CreateInvoiceTransactionProcessorWithInvoiceNo::class))->execute($booking, $bill_no);
(App()->make(CreateInvoiceTransactionWithInvoiceNoProcessor::class))->execute($booking, $bill_no);
dump('regenerated invoice. Booking Marking - ' . $booking->marking . '. Bill_no - ' . $bill_no . '. Old bill_no - ' . $deletedInvoice->bill_no);
Log::channel('regenerateInvoice')->info('regenerated invoice. Booking Marking - ' . $booking->marking . '. Bill_no - ' . $bill_no . '. Old bill_no - ' . $deletedInvoice->bill_no);
} else {
@@ -776,3 +777,80 @@ Route::get('/token', function (Request $request) {
echo $token;
});
Route::get('/invoice/{marking}/{started_at}/{ended_at}/fix', function($marking, $started_at, $ended_at) {
set_time_limit(14400);
$processed_invoice = 1;
if (is_null($marking) || empty($marking)) {
return 'Error - Marking is empty';
}
if (is_null($started_at) || empty($started_at)) {
return 'Error - Start Date is empty';
}
if (is_null($ended_at) || empty($ended_at)) {
return 'Error - End Date is empty';
}
$company = Company::where('reference', $marking)->first();
if (!$company) {
return 'Error - Marking not found';
}
dump('Company Id - ' . $company->id);
// dd($marking, $started_at, $ended_at);
$bookings = $company->bookings()
->where('status', ApprovalStatus::COMPLETED)
->whereDate('created_at', '>=', Carbon::parse($started_at))
->whereDate('created_at', '<=', Carbon::parse($ended_at))
->orderBy('id')
->chunk(100, function ($bookings) use (&$processed_invoice) {
foreach ($bookings as $booking) {
Log::channel('regenerateInvoice')->info('Counter ' . $processed_invoice);
dump('Counter ' . $processed_invoice);
dump('Marking ' . $booking->marking);
$processed_invoice += 1;
$booking->status = ApprovalStatus::APPROVED;
$booking->save();
$firstInvoice = $booking->transactions()
->whereIn('type', [TransactionType::INVOICE])
->withTrashed()
->orderBy('created_at', 'asc')
->first();
// get the first bill_no
$firstBillNo = $firstInvoice->bill_no;
if (strpos($firstBillNo, '-deleted') !== false) {
$firstBillNo = substr($firstBillNo, 0, strpos($firstBillNo, '-deleted'));
}
// update currentInvoice bill_no to '-deleted-'
$currentInvoice = $booking->transactions()->where('type', TransactionType::INVOICE)->first();
$currentInvoice->bill_no = $currentInvoice->bill_no ."-deleted-" . Str::random(10);
$currentInvoice->save();
$transactionWithSameBillNo = Transaction::where('bill_no', $firstBillNo)->withTrashed()->get();
if ($transactionWithSameBillNo) {
foreach ($transactionWithSameBillNo as $transaction) {
$transaction->bill_no = $transaction->bill_no . "-deleted-" . Str::random(10);
$transaction->save();
}
}
$booking->transactions()->whereIn('transactions.type', [TransactionType::INVOICE, TransactionType::SUPPLIER_DELIVER])->delete();
$booking->documents()->whereIn('document_type', [DocumentType::INVOICE, DocumentType::PURCHASE_ORDER, DocumentType::DELIVER_ORDER, DocumentType::SUPPLIER_DELIVER_ORDER])->delete();
(App()->make(CreateInvoiceTransactionWithInvoiceNoProcessor::class))->execute($booking, $firstBillNo);
dump('regenerated invoice. Booking Marking - ' . $booking->marking . '. Bill_no - ' . $firstBillNo . '. Old bill_no - ' . $currentInvoice->bill_no);
Log::channel('regenerateInvoice')->info('regenerated invoice. Booking Marking - ' . $booking->marking . '. Bill_no - ' . $firstBillNo . '. Old bill_no - ' . $currentInvoice->bill_no);
}
}
);
})->name('invoice.fix.byCustomerMarking');