diff --git a/app/Classes/General/Eloquent/Filters/CompanySegmentsIn.php b/app/Classes/General/Eloquent/Filters/CompanySegmentsIn.php new file mode 100644 index 00000000..dd86d514 --- /dev/null +++ b/app/Classes/General/Eloquent/Filters/CompanySegmentsIn.php @@ -0,0 +1,24 @@ +whereHas('companyModules', function ($module) use ($value) { + $module->whereHas('connections', function ($connection) use ($value) { + $connection->whereHas('connectionSegments', function ($segment) use ($value) { + $segment->whereIn('segment_id', $value); + }); + }); + }); + } +} diff --git a/app/Classes/Jobs/FetchOrdersFromYDPortalJob.php b/app/Classes/Jobs/FetchOrdersFromYDPortalJob.php index 1ee59548..ef0276dc 100644 --- a/app/Classes/Jobs/FetchOrdersFromYDPortalJob.php +++ b/app/Classes/Jobs/FetchOrdersFromYDPortalJob.php @@ -13,6 +13,7 @@ use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; +use Illuminate\Support\Facades\Log; class FetchOrdersFromYDPortalJob implements ShouldQueue { @@ -29,12 +30,17 @@ class FetchOrdersFromYDPortalJob implements ShouldQueue */ public function handle() { + Log::info('FetchOrdersFromYDPortalJob starts'); + Log::info('FetchPackingListsFromYdPortalProcessor starts'); (App()->make(FetchPackingListsFromYdPortalProcessor::class))->execute(); + Log::info('FetchContainersFromYdPortalProcessor starts'); (App()->make(FetchContainersFromYdPortalProcessor::class))->execute(); + Log::info('FetchContainersUpdatesFromYdPortalProcessor starts'); (App()->make(FetchContainersUpdatesFromYdPortalProcessor::class))->execute(); + Log::info('FetchDeliveryUpdatesFromYdPortalProcessor starts'); (App()->make(FetchDeliveryUpdatesFromYdPortalProcessor::class))->execute(); - -// (App()->make(FetchOrderListsFromYdPortalProcessor::class))->execute(); + Log::info('FetchOrdersFromYDPortalJob ends'); + // (App()->make(FetchOrderListsFromYdPortalProcessor::class))->execute(); } } diff --git a/app/Classes/Modules/Companies/ControllersLogic/AssignCompanyConnectionToConnectionSegmentLogic.php b/app/Classes/Modules/Companies/ControllersLogic/AssignCompanyConnectionToConnectionSegmentLogic.php index cee72e84..8069663c 100644 --- a/app/Classes/Modules/Companies/ControllersLogic/AssignCompanyConnectionToConnectionSegmentLogic.php +++ b/app/Classes/Modules/Companies/ControllersLogic/AssignCompanyConnectionToConnectionSegmentLogic.php @@ -7,6 +7,8 @@ use App\Classes\General\Abstracts\AbstractControllerLogic; use App\Classes\Modules\Companies\Processors\AssignConnectionSegmentProcessor; use App\Classes\Modules\Companies\Services\FetchesCompany; use App\Classes\Modules\Companies\Services\FetchesCompanyConnection; +use App\Classes\Modules\Contacts\DataTransferObjects\ContactObject; +use App\Classes\Modules\Contacts\Processors\CreateContactProcessor; use App\Http\Resources\CompanyResource; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; @@ -33,17 +35,22 @@ class AssignCompanyConnectionToConnectionSegmentLogic extends AbstractController /** @var AssignConnectionSegmentProcessor */ private $assignCompanyConnectionToConnectionSegmentProcessor; + /** @var CreateContactProcessor */ + private $createContactProcessor; + /** * AssignCompanyToSegmentLogic constructor. * @param FetchesCompany $fetchesCompany * @param FetchesCompanyConnection $fetchesCompanyConnection * @param AssignConnectionSegmentProcessor $assignCompanyConnectionToConnectionSegmentProcessor + * @param CreateContactProcessor $createContactProcessor */ - public function __construct(FetchesCompany $fetchesCompany, FetchesCompanyConnection $fetchesCompanyConnection, AssignConnectionSegmentProcessor $assignCompanyConnectionToConnectionSegmentProcessor) + public function __construct(FetchesCompany $fetchesCompany, FetchesCompanyConnection $fetchesCompanyConnection, AssignConnectionSegmentProcessor $assignCompanyConnectionToConnectionSegmentProcessor, CreateContactProcessor $createContactProcessor) { $this->fetchesCompany = $fetchesCompany; $this->fetchesCompanyConnection = $fetchesCompanyConnection; $this->assignCompanyConnectionToConnectionSegmentProcessor = $assignCompanyConnectionToConnectionSegmentProcessor; + $this->createContactProcessor = $createContactProcessor; } /** @@ -62,6 +69,11 @@ class AssignCompanyConnectionToConnectionSegmentLogic extends AbstractController $this->assignCompanyConnectionToConnectionSegmentProcessor->execute($companyConnection, $request->input('segment_id')); + if ($request->input('segment_id') == 10 || $request->input('segment_id') == 11) { + $contactObject = new ContactObject('Whatsapp: ' . $request->input('name'), $request->input('phone'), null, null); + $this->createContactProcessor->execute($contactObject, $company); + } + return $this->resourceResponse(new CompanyResource($company)); } } \ No newline at end of file diff --git a/app/Classes/Modules/PackingLists/ControllersLogic/Containers/RescheduleContainerLogic.php b/app/Classes/Modules/PackingLists/ControllersLogic/Containers/RescheduleContainerLogic.php index b3638b90..268055de 100644 --- a/app/Classes/Modules/PackingLists/ControllersLogic/Containers/RescheduleContainerLogic.php +++ b/app/Classes/Modules/PackingLists/ControllersLogic/Containers/RescheduleContainerLogic.php @@ -56,27 +56,21 @@ class RescheduleContainerLogic extends AbstractControllerLogic */ public function logic(Request $request) : JsonResponse { - try { - $container = $this->fetchesContainer->execute(['id' => $request->route('id')]); - $transport = $container->transports()->first(); + $container = $this->fetchesContainer->execute(['id' => $request->route('id')]); + $transport = $container->transports()->first(); - $old_sechedule = $transport->schedules()->first(); + $old_schedule = $transport->schedules()->delete(); - $this->updatesScheduleStatus->execute($old_sechedule, ApprovalStatus::REJECTED); + // $this->updatesScheduleStatus->execute($old_schedule, ApprovalStatus::REJECTED); - $scheduleObject = new ScheduleObject( - Carbon::parse($request->input('etd')), - Carbon::parse($request->input('eta')), - ApprovalStatus::APPROVED - ); - $schedule = $this->createsSchedule->execute($transport, $scheduleObject); - - return $this->resourceResponse(new ContainerResource($container)); - - } catch (\Exception $exception){ - throw new ErrorException($exception->getMessage(), $exception->getCode()); - } + $scheduleObject = new ScheduleObject( + Carbon::parse($request->input('etd')), + Carbon::parse($request->input('eta')), + ApprovalStatus::APPROVED + ); + $schedule = $this->createsSchedule->execute($transport, $scheduleObject); + return $this->resourceResponse(new ContainerResource($container)); } } diff --git a/app/Classes/Modules/PackingLists/Processors/FetchDeliveryUpdatesFromYdPortalProcessor.php b/app/Classes/Modules/PackingLists/Processors/FetchDeliveryUpdatesFromYdPortalProcessor.php index 84c24561..a023673b 100644 --- a/app/Classes/Modules/PackingLists/Processors/FetchDeliveryUpdatesFromYdPortalProcessor.php +++ b/app/Classes/Modules/PackingLists/Processors/FetchDeliveryUpdatesFromYdPortalProcessor.php @@ -76,6 +76,7 @@ class FetchDeliveryUpdatesFromYdPortalProcessor try { $client = new \GuzzleHttp\Client(['cookies' => true, 'headers' => ['Cookie' => 'utc_offset=480']]); + Log::info('Delivery tracking sTrackingNo: '. $packingList->reference); $request = $client->request('get', 'https://main.universe.com.my/Tracking/User/Paging?sEcho=1&sTrackingNo='.$packingList->reference.'&sOrgId=sti', ['timeout' => 3]); $deliveryTracking = json_decode($request->getBody()->getContents()); foreach (array_reverse($deliveryTracking->aaData) as $trackingRow) { @@ -119,7 +120,7 @@ class FetchDeliveryUpdatesFromYdPortalProcessor } } - + Log::info('FetchDeliveryUpdatesFromYdPortalProcessor ends'); } } diff --git a/app/Classes/Modules/Transactions/Processors/CheckStorageInvoiceTransactionProcessor.php b/app/Classes/Modules/Transactions/Processors/CheckStorageInvoiceTransactionProcessor.php index dfe76267..0241961b 100644 --- a/app/Classes/Modules/Transactions/Processors/CheckStorageInvoiceTransactionProcessor.php +++ b/app/Classes/Modules/Transactions/Processors/CheckStorageInvoiceTransactionProcessor.php @@ -164,6 +164,7 @@ class CheckStorageInvoiceTransactionProcessor if ($transport) { $schedule = $transport->schedules->last(); if ($schedule) { + Log::channel('storage_invoices')->info('schedule: '.json_encode($schedule)); return $schedule->eta; } } @@ -177,11 +178,14 @@ class CheckStorageInvoiceTransactionProcessor $pricePerCBM = 3; $resultNumberOfDaysFree = 10; $dt1 = $eta->copy()->addDay()->startOfDay(); - $resultStartDate = $dt1->format('Y-m-d'); - $currentDatetime = Carbon::now(); - $dt2 = $currentDatetime->copy()->addDay()->startOfDay(); - $resultCurrentDate = $dt2->format('Y-m-d H:i:s'); + $dt2 = Carbon::now()->copy()->addDay()->startOfDay(); $interval = Carbon::parse($dt2)->diff($dt1); + Log::channel('storage_invoices')->info('eta: '.json_encode($eta)); + Log::channel('storage_invoices')->info('dt1: '.json_encode($dt1)); + Log::channel('storage_invoices')->info('dt2: '.json_encode($dt2)); + Log::channel('storage_invoices')->info('interval: '.json_encode($interval)); + Log::channel('storage_invoices')->info('Carbon now: '.json_encode(Carbon::now())); + $resultNumberOfDaysExceeded = $interval->days - $resultNumberOfDaysFree; $storageInvoice = $destinationWarehousePackage->transactions()->where('transactions.type', TransactionType::STORAGE_INVOICE)->first(); @@ -200,14 +204,13 @@ class CheckStorageInvoiceTransactionProcessor $taxPercentage = TaxPercentage::DEFAULT; $price_cbm = $pricePerCBM * $cbm * $resultNumberOfDaysExceeded; $dateToCompare = Carbon::parse(env('SST_START_DATE', '2024-04-01 00:00:00')); - $shippingInvoiceTransactionCreatedDate = Carbon::now(); - Log::channel('storage_invoices')->info('storageInvoice: '.json_encode($storageInvoice).', $transaction->status: '.$transaction->status); + Log::channel('storage_invoices')->info('dateToCompare: '.json_encode($dateToCompare)); if(!$storageInvoice && $resultNumberOfDaysExceeded > 0 && $transaction->status != ApprovalStatus::COMPLETED){ Log::channel('storage_invoices')->info('Created $transaction->id: '.$transaction->id); $billNumber = $this->generatesTransactionBillNumber->execute('STOR-'); - if ($shippingInvoiceTransactionCreatedDate->isAfter($dateToCompare)) { + if (Carbon::now()->isAfter($dateToCompare)) { $taxPercentage = TaxPercentage::SIX_PERCENT; $total_tax = $price_cbm * $taxPercentage / 100; $price_cbm = $price_cbm + $total_tax; @@ -228,13 +231,13 @@ class CheckStorageInvoiceTransactionProcessor $paymentStorageTransaction = $storageInvoice->transactions()->where('transactions.type', TransactionType::PAYMENT)->where('transactions.status', ApprovalStatus::APPROVED)->first(); if($paymentStorageTransaction){ $dateStorageInvoicePaid = $paymentStorageTransaction->created_at->copy()->addDay()->startOfDay(); - Log::channel('storage_invoices')->info('dateStorageInvoicePaid: '.$dateStorageInvoicePaid.', resultCurrentDate: '.$resultCurrentDate); + Log::channel('storage_invoices')->info('dateStorageInvoicePaid: '.$dateStorageInvoicePaid.', resultCurrentDate: '.$dt2->format('Y-m-d H:i:s')); $intervalRecalculate = Carbon::parse($dateStorageInvoicePaid)->diff($dt1); $resultNumberOfDaysExceeded = $intervalRecalculate->days - $resultNumberOfDaysFree; $price_cbm = $pricePerCBM * $cbm * $resultNumberOfDaysExceeded; } - if ($shippingInvoiceTransactionCreatedDate->isAfter($dateToCompare)) { + if (Carbon::now()->isAfter($dateToCompare)) { $taxPercentage = TaxPercentage::SIX_PERCENT; $total_tax = $price_cbm * $taxPercentage / 100; $price_cbm = $price_cbm + $total_tax; @@ -280,8 +283,8 @@ class CheckStorageInvoiceTransactionProcessor 'storageInvoiceId' => $storageInvoiceId, 'numberOfDaysExceeded' => $resultNumberOfDaysExceeded, 'numberOfDaysFree' => $resultNumberOfDaysFree, - 'startDate' => $resultStartDate, - 'currentDate' => $resultCurrentDate, + 'startDate' => $dt1->format('Y-m-d'), + 'currentDate' => $dt2->format('Y-m-d H:i:s'), 'cbm' => $cbm, 'pricePerCBM' => $pricePerCBM, 'storageInvoice' => new TransactionWithStorageResource($storageInvoice) diff --git a/app/Classes/Modules/Transactions/Processors/CreatePaymentTransactionOneTimeFixProcessor.php b/app/Classes/Modules/Transactions/Processors/CreatePaymentTransactionOneTimeFixProcessor.php new file mode 100644 index 00000000..3d648e76 --- /dev/null +++ b/app/Classes/Modules/Transactions/Processors/CreatePaymentTransactionOneTimeFixProcessor.php @@ -0,0 +1,188 @@ +generatesTransactionBillNumber = $generatesTransactionBillNumber; + $this->createsPaymentTransaction = $createsPaymentTransaction; + $this->createsBillplzBill = $createsBillplzBill; + $this->createsTransactionableTransaction = $createsTransactionableTransaction; + $this->updatesWalletBalance = $updatesWalletBalance; + $this->updateDoFromVTPortalProcessor = $updateDoFromVTPortalProcessor; + $this->updateDoFromYDPortalProcessor = $updateDoFromYDPortalProcessor; + $this->updatesTransactionStatus = $updatesTransactionStatus; + } + + /** + * @throws MalformedRequestException + */ + public function execute(Transaction $invoice, $payment_method, $bank_code, $date, $run = true) + { + $amount = $invoice->amount; + Log::info($invoice->owner); + $company_module = $invoice->owner->owner->companyModule()->first(); + $approvalStatus = ApprovalStatus::PENDING_SUBMISSION; + $billNumber = $this->generatesTransactionBillNumber->execute('PYMT-'); + $payment_reference = null; + + if ($payment_method == PaymentMethodType::PAYMENT_GATEWAY) { + + // create billplz transaction + $payment_method = PaymentMethodType::PAYMENT_GATEWAY; + $billPlzBill = $this->createsBillplzBill->execute( + $company_module->name, + (app()->environment(['production'])) ? $company_module->employees()->first()->email : 'uldvstar@gmail.com', + 'This payment is for the invoice number . ' . $billNumber, + $amount, + $billNumber, + $bank_code, + true + ); + + $payment_reference = $billPlzBill->id; + } + else if ($payment_method === PaymentMethodType::WALLET) { + /** @var Wallet $wallet */ + $wallet = $company_module->wallets()->first(); + + + // if((float) number_format(($wallet->amount - $amount),2) < 0){ + // throw new MalformedRequestException('Insufficient wallet balance. Please Top up your wallet.'); + // } + + $walletPaymentBillNumber = $this->generatesTransactionBillNumber->execute('PYMT-'); + + $transaction_object = new TransactionObject($walletPaymentBillNumber, TransactionType::PAYMENT, 1, $company_module->id, 1, PaymentMethodType::WALLET, $amount, $amount, 1, 1, 1, 0, 0, null, ApprovalStatus::APPROVED, [], ''); + $transaction = $this->createsTransactionableTransaction->execute($wallet, $transaction_object); + $transaction->created_at = $date; + $transaction->updated_at = $date; + $transaction->save(); + + $payment_reference = $walletPaymentBillNumber; + + $this->updatesWalletBalance->execute($wallet, ($amount * -1)); + + if($run) + { + $packingList = $invoice->owner; + $order = $packingList->owner; + $packingList->status = ApprovalStatus::APPROVED; + $packingList->save(); + + if(app()->environment('production')){ + $this->updateDoFromVTPortalProcessor->execute($packingList); + $this->updateDoFromYDPortalProcessor->execute($packingList); + } + } + + // later use this variabke to create a approved payment transaction + $approvalStatus = ApprovalStatus::APPROVED; + + // update invoice to completed + if($run){ + $this->updatesTransactionStatus->execute($invoice, ApprovalStatus::COMPLETED); + } + } + else { + $payment_method = PaymentMethodType::CASH; + } + + $object = new TransactionObject( + $billNumber, + TransactionType::PAYMENT, + $company_module->id, + 1, + 1, + $payment_method, + $amount, + $amount, + 1, + 1, + 0, + 0, + 0, + null, + $approvalStatus, + null, + $payment_reference + ); + + $payment_transaction = $this->createsPaymentTransaction->execute($invoice, $object); + + return $payment_transaction; + } +} diff --git a/app/Classes/Modules/Transactions/Processors/CreatePaymentTransactionProcessor.php b/app/Classes/Modules/Transactions/Processors/CreatePaymentTransactionProcessor.php index ad5e79ab..8ceb0100 100644 --- a/app/Classes/Modules/Transactions/Processors/CreatePaymentTransactionProcessor.php +++ b/app/Classes/Modules/Transactions/Processors/CreatePaymentTransactionProcessor.php @@ -114,7 +114,7 @@ class CreatePaymentTransactionProcessor /** @var Wallet $wallet */ $wallet = $company_module->wallets()->first(); - if((float) number_format(($wallet->amount - $amount),2) < 0){ + if((float) number_format(($wallet->amount - $amount),2) < -0.01){ throw new MalformedRequestException('Insufficient wallet balance. Please Top up your wallet.'); } diff --git a/app/Classes/Notifications/InvoiceIssuedEmail.php b/app/Classes/Notifications/InvoiceIssuedEmail.php index 8a5c90cc..bbd4271d 100644 --- a/app/Classes/Notifications/InvoiceIssuedEmail.php +++ b/app/Classes/Notifications/InvoiceIssuedEmail.php @@ -8,6 +8,7 @@ use App\Classes\ValueObjects\Constants\TransactionType; use App\Models\PackingList; use App\Models\User; use Illuminate\Notifications\Messages\MailMessage; +use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Storage; class InvoiceIssuedEmail extends AbstractEmail @@ -35,10 +36,14 @@ class InvoiceIssuedEmail extends AbstractEmail $invoice = $this->packingList->transactions()->where('type', TransactionType::SHIPPING_INVOICE)->where('status', ApprovalStatus::APPROVED)->first(); $invoiceDocument = $invoice->documents()->first()->files; + // $fileContent = Storage::disk('documents')->get($invoiceDocument->first()->file->file_info->original->file); + $filePath = storage_path('app/documents/' . $invoiceDocument->first()->file->file_info->original->file); + + Log::info('InvoiceIssuedEmail sent - Att: '.$this->user->name.' - Invoice for order no.'. $this->packingList->owner->reference); return (new MailMessage) ->subject('Att: '.$this->user->name.' - Invoice for order no.'. $this->packingList->owner->reference) - ->attach(Storage::disk('documents')->get($invoiceDocument->first()->file->file_info->original->file), [ + ->attach($filePath, [ 'as' => 'name.pdf', 'mime' => 'application/pdf', ])->view('emails.shipment.invoice', ['user' => $this->user, 'packingList' => $this->packingList]); diff --git a/app/Classes/Notifications/ShipmentDepartureEmail.php b/app/Classes/Notifications/ShipmentDepartureEmail.php index 44362d44..902ece25 100644 --- a/app/Classes/Notifications/ShipmentDepartureEmail.php +++ b/app/Classes/Notifications/ShipmentDepartureEmail.php @@ -9,6 +9,7 @@ use App\Models\PackingList; use App\Models\PasswordReset; use App\Models\User; use Illuminate\Notifications\Messages\MailMessage; +use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Storage; class ShipmentDepartureEmail extends AbstractEmail @@ -40,10 +41,14 @@ class ShipmentDepartureEmail extends AbstractEmail $invoiceDocument = $invoice->documents()->first()->files; + // $fileContent = Storage::disk('documents')->get($invoiceDocument->first()->file->file_info->original->file); + $filePath= storage_path('app/documents/' . $invoiceDocument->first()->file->file_info->original->file); + + Log::info('ShipmentDepartureEmail sent - Att: '.$this->user->name.' - Invoice for order no.'. $this->packingList->owner->reference); return (new MailMessage) ->subject('Your packages are on the way to malaysia - Invoice pending payment for order no.'. $this->packingList->owner->reference) - ->attach(Storage::disk('documents')->get($invoiceDocument->first()->file->file_info->original->file), [ + ->attach($filePath, [ 'as' => 'name.pdf', 'mime' => 'application/pdf', ])->bcc(['email_test@cief-malaysia.com'])->view('emails.shipment.ETD', ['user' => $this->user, 'packingList' => $this->packingList]); diff --git a/app/Console/Commands/FixApprovedPaymentFailedGroup.php b/app/Console/Commands/FixApprovedPaymentFailedGroup.php new file mode 100644 index 00000000..97dfac24 --- /dev/null +++ b/app/Console/Commands/FixApprovedPaymentFailedGroup.php @@ -0,0 +1,94 @@ +callbackBillplzProcessor = $callbackBillplzProcessor; + } + + /** + * Execute the console command. + * + * @return int + */ + public function handle() + { + ini_set('memory_limit', '-1'); + + $this->outputArray = []; + $start = new Carbon(); + + $groups = Group::whereNotIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]) + ->whereHas('payment', function ($query) { + $query->whereIn('status', [2, 3]); + })->get(); + + foreach ($groups as $group) { + $transaction = $group->payment; + + $response = Http::withBasicAuth(config('billplz.api_key') . ':', '')->get(config('billplz.base_url') . '/api/v3/bills/' . $transaction->payment_reference); + + dump($transaction->payment_reference); + + if ($response->successful()) { + $data = $response->json(); + if ($data['paid']) { + $status = ApprovalStatus::PENDING_VERIFICATION; + + if ($data['state'] === 'paid') { + $status = ApprovalStatus::APPROVED; + } + + $this->info(Carbon::now() . ' : Fixing ' . $transaction->payment_reference); + $this->callbackBillplzProcessor->execute($transaction, $status); + } + } else { + $this->info("billplz error
"); + } + } + + $end = new Carbon(); + $elapsedTime = $start->diff($end)->format('%H:%I:%S'); + + if ($groups) { + $this->info(Carbon::now() . ' : Done . ElapsedTime: ' . $elapsedTime); + } + } +} diff --git a/app/Console/Commands/OneTimeTransactionFixBillplzFailedCallback.php b/app/Console/Commands/OneTimeTransactionFixBillplzFailedCallback.php index f015e41b..9d4c648d 100644 --- a/app/Console/Commands/OneTimeTransactionFixBillplzFailedCallback.php +++ b/app/Console/Commands/OneTimeTransactionFixBillplzFailedCallback.php @@ -55,11 +55,12 @@ class OneTimeTransactionFixBillplzFailedCallback extends Command $this->outputArray = []; $start = new Carbon(); - //This transaction, 15205 has approve payment but not its owner, shipping invoice - $transaction = Transaction::whereIn('id', [15205])->first(); - $this->info(Carbon::now() . ' : One time fix failled callback from billplz for transaction with id 15205 cron started.'); + //Transaction fix with this one time fix command: 15205, 16803 + //This transaction, 16803 has approve payment but not its owner, shipping invoice + $transaction = Transaction::whereIn('id', [16803])->first(); + $this->info(Carbon::now() . ' : One time fix failled callback from billplz for transaction with id 16803 cron started.'); - if($transaction && $transaction->id == 15205){ + if($transaction && $transaction->id == 16803){ $status = ApprovalStatus::APPROVED; $this->callbackBillplzProcessor->execute($transaction, $status); @@ -68,6 +69,6 @@ class OneTimeTransactionFixBillplzFailedCallback extends Command $end = new Carbon(); $elapsedTime = $start->diff($end)->format('%H:%I:%S'); - $this->info(Carbon::now() . ' : One time fix failled callback from billplz for transaction with id 15205 cron ended. ElapsedTime: ' . $elapsedTime); + $this->info(Carbon::now() . ' : One time fix failled callback from billplz for transaction with id 16803 cron ended. ElapsedTime: ' . $elapsedTime); } } diff --git a/app/Http/Resources/CompanyResource.php b/app/Http/Resources/CompanyResource.php index d969ac0d..27a04166 100644 --- a/app/Http/Resources/CompanyResource.php +++ b/app/Http/Resources/CompanyResource.php @@ -40,7 +40,8 @@ class CompanyResource extends JsonResource 'last_order' => $companyModule->type === 7 ? new DeliveryOrderResource($companyModule->orders()->orderBy('id', 'DESC')->first()) : new OrderResource($companyModule->orders()->orderBy('id', 'DESC')->first()), 'order_count' => $companyModule->orders()->count(), 'identification' => new DocumentResource($this->documents->whereIn('document_type', DocumentType::IDENTIFICATION_DOCUMENTS)->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED])->first()), - 'created_at' => $this->created_at->format('d-m-Y') + 'created_at' => $this->created_at->format('d-m-Y'), + 'whatsapp' => new ContactResource($this->contacts()->where('reference', 'LIKE', '%Whatsapp%')->orderBy('created_at', 'DESC')->first()) ]; diff --git a/app/Http/Resources/GroupForOrderV2Resource.php b/app/Http/Resources/GroupForOrderV2Resource.php index cfd2f121..69cce0ed 100644 --- a/app/Http/Resources/GroupForOrderV2Resource.php +++ b/app/Http/Resources/GroupForOrderV2Resource.php @@ -26,7 +26,7 @@ class GroupForOrderV2Resource extends JsonResource 'original_currency' => new CurrencyResource($this->original_currency), 'issuer_name' => $this->issuerCompany->name, 'issuer_id' => $this->issuerCompany->id, - 'amount' => (float) $this->amount, //cief todo: 58 + 'amount' => (float) $this->amount, 'service_charge' => (float) $this->amount, 'currency' => new CurrencyResource($this->currency), 'created_at' => Carbon::parse($this->created_at)->format('d-m-Y h:i:s A'), diff --git a/app/Http/Resources/MappableTransactionWithDetailsResource.php b/app/Http/Resources/MappableTransactionWithDetailsResource.php index bf1fcf1d..c9f9bfad 100644 --- a/app/Http/Resources/MappableTransactionWithDetailsResource.php +++ b/app/Http/Resources/MappableTransactionWithDetailsResource.php @@ -32,9 +32,11 @@ class MappableTransactionWithDetailsResource extends JsonResource if ($this->type === TransactionType::PAYMENT) { $order = $this->owner->owner->owner; - $data['order_reference'] = $order->reference; - $data['debtor_code'] = $order->companyModule->company->debtor; - $data['created_at'] = $this->owner->created_at; // invoice date + if ($order) { + $data['order_reference'] = $order->reference; + $data['debtor_code'] = $order->companyModule->company->debtor; + $data['created_at'] = $this->owner->created_at; // invoice date + } } elseif (in_array($this->type, [TransactionType::GROUP_PAYMENT, TransactionType::TOP_UP])) { $connection = $this->owner->owner->inviters()->withPivot('invitee_reference')->first(); $data['marking'] = $connection ? $connection->pivot->invitee_reference : ''; @@ -48,17 +50,20 @@ class MappableTransactionWithDetailsResource extends JsonResource if ($payments->count()) { $data['payment_transactions'] = $payments->map(function ($payment) { $order = $payment->owner->owner->owner; - return [ - 'id' => $payment->id, - 'updated_at' => $payment->updated_at, - 'debtor_code' => $order->companyModule->company->debtor, - 'order_reference' => $order->reference, - 'bill_no' => null, - 'type' => $payment->type, - 'marking' => null, - 'amount' => $payment->amount, - 'created_at' => $this->created_at - ]; + + if ($order) { + return [ + 'id' => $payment->id, + 'updated_at' => $payment->updated_at, + 'debtor_code' => $order->companyModule->company->debtor, + 'order_reference' => $order->reference, + 'bill_no' => null, + 'type' => $payment->type, + 'marking' => null, + 'amount' => $payment->amount, + 'created_at' => $this->created_at + ]; + } })->toArray(); } else { $data['status'] = 'error'; diff --git a/app/Http/Resources/SegmentResource.php b/app/Http/Resources/SegmentResource.php index 2ec22145..85c61f61 100644 --- a/app/Http/Resources/SegmentResource.php +++ b/app/Http/Resources/SegmentResource.php @@ -18,7 +18,7 @@ class SegmentResource extends JsonResource $constant = $this->constants->where('reference', SegmentConstants::CUSTOM_PRICE)->first(); return [ 'id' => $this->id, - 'name' => $this->name, + 'name' => ucwords(str_replace('_', ' ', $this->name)), 'price' => $constant ? $constant->value[0] : 0 ]; } diff --git a/app/Http/Resources/TransactionResource.php b/app/Http/Resources/TransactionResource.php index 6a21f1d2..d8697f8a 100644 --- a/app/Http/Resources/TransactionResource.php +++ b/app/Http/Resources/TransactionResource.php @@ -52,7 +52,7 @@ class TransactionResource extends JsonResource 'documents' => $groupTransactions ? DocumentResource::collection($this->documents->where('status', ApprovalStatus::PENDING_VERIFICATION)) : DocumentResource::collection($this->documents), 'type' => (int) $this->type, 'bill_no' => $this->bill_no, - 'amount' => (double) $this->amount, //cief todo: 58 + 'amount' => (double) $this->amount, 'payment_method' => (int) $this->payment_method, 'payment_reference' => $this->payment_reference, 'outstanding' => (double) $this->amount - ($this->transactions()->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->sum('amount')), diff --git a/app/Http/Resources/TransactionWithStorageResource.php b/app/Http/Resources/TransactionWithStorageResource.php index fe71d674..52f35fdf 100644 --- a/app/Http/Resources/TransactionWithStorageResource.php +++ b/app/Http/Resources/TransactionWithStorageResource.php @@ -5,6 +5,7 @@ namespace App\Http\Resources; use App\Classes\ValueObjects\Constants\ApprovalStatus; use App\Classes\ValueObjects\Constants\TransactionType; use App\Models\Group; +use App\Models\PackingList; use App\Models\Transaction; use App\Models\Wallet; use Carbon\Carbon; @@ -27,7 +28,9 @@ class TransactionWithStorageResource extends JsonResource $groupPaymentAttemptsFiltered = []; $group_payment_expired = null; $group_payment_history = null; + $group_payment_history_query = null; $groupTotalAmount = 0; + $payment_history = null; if ($this->owner instanceof Transaction) { if ($this->owner) { @@ -43,7 +46,8 @@ class TransactionWithStorageResource extends JsonResource if($this->groups){ $group_payment_attempts = GroupForOrderV2Resource::collection($this->groups->whereNotIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])); $group_payment_expired = GroupForOrderV2Resource::collection($this->groupsWithTrashed->whereIn('status', [ApprovalStatus::EXPIRED])); - $group_payment_history = GroupForOrderV2Resource::collection($this->groups->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::REJECTED])); + $group_payment_history_query = $this->groups->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::REJECTED]); + $group_payment_history = GroupForOrderV2Resource::collection($group_payment_history_query); } } else { @@ -54,12 +58,16 @@ class TransactionWithStorageResource extends JsonResource } + $packingListReference = null; + if ($this->owner instanceof PackingList) { + $packingListReference = $this->owner->reference; + } $ts = $this->groups->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION])->last(); - if ($ts) { + if ($ts && $group_payment_history && $group_payment_attempts) { $paymentTransaction = Transaction::where('payment_reference', $ts->reference)->whereIn('status', [ApprovalStatus::PENDING_SUBMISSION])->first(); if($paymentTransaction){ - $groupTotalAmount = (double) $this->amount; //cief todo: 58 + $groupTotalAmount = (double) $this->amount; foreach ($group_payment_history as $key => $value) { if ($value->id === $ts->id && $value->reference === $ts->reference) { @@ -76,6 +84,21 @@ class TransactionWithStorageResource extends JsonResource } + $payment_history = TransactionResource::collection($this->transactions() + ->payments() + ->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::COMPLETED, ApprovalStatus::REJECTED]) + ->get()); + + //For 'Your Payment Proof' at frontend + + if($group_payment_history_query && count($group_payment_history_query) > 0){ + if($this->getReferenceForGroupPayment($group_payment_history_query)){ + foreach ($payment_history as $item) { + $item['payment_reference'] = $this->getReferenceForGroupPayment($group_payment_history_query); + } + } + } + return [ 'id' => $this->id, 'owner_type' => $this->owner_type, @@ -88,10 +111,10 @@ class TransactionWithStorageResource extends JsonResource 'documents' => $groupTransactions ? DocumentResource::collection($this->documents->where('status', ApprovalStatus::PENDING_VERIFICATION)) : DocumentResource::collection($this->documents), 'type' => (int) $this->type, 'bill_no' => $this->bill_no, - 'amount' => (double) $this->amount, //cief todo: 58 + 'amount' => (double) $this->amount, 'payment_method' => (int) $this->payment_method, 'payment_reference' => $this->payment_reference, - 'outstanding' => (double) $this->amount - ($this->transactions()->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->sum('amount')), //cief todo: 58 + 'outstanding' => (double) $this->amount - ($this->transactions()->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->sum('amount')), 'floating' => $group_payment_attempts ? $groupTotalAmount : (double) $this->transactions()->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::PENDING_SUBMISSION, ApprovalStatus::PENDING_VERIFICATION])->sum('amount'), 'service_charge' => (double) $this->service_charge, 'tax' => (double) $this->tax, @@ -112,13 +135,9 @@ class TransactionWithStorageResource extends JsonResource ->payments()->where('status', ApprovalStatus::EXPIRED) ->get() ), - 'payment_history' => TransactionResource::collection( - $this->transactions() - ->payments() - ->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::COMPLETED, ApprovalStatus::REJECTED]) - ->get() - ), + 'payment_history' => $payment_history, 'remarks' => RemarkResource::collection($this->remarks), + 'packing_list_reference' => $packingListReference, 'storages' => $this->storages ? $this->storages : null, //from middleware 'is_waived' => (int) $this->is_waived, 'expires_on' => Carbon::parse($this->expires_on)->format('d-m-Y h:i:s A'), @@ -126,4 +145,12 @@ class TransactionWithStorageResource extends JsonResource 'created_at' => Carbon::parse($this->created_at)->format('d-m-Y') ]; } + + private function getReferenceForGroupPayment($groups){ + if(count($groups)){ + $firstGroup = $groups[0]; + return $firstGroup['reference']; + } + return null; + } } diff --git a/app/Models/CompanyConnection.php b/app/Models/CompanyConnection.php index b382e237..894cdafc 100644 --- a/app/Models/CompanyConnection.php +++ b/app/Models/CompanyConnection.php @@ -69,4 +69,12 @@ class CompanyConnection extends AbstractModel return $this->belongsToMany(Segment::class, (new ConnectionSegment())->getTable(), 'company_connection_id', 'segment_id'); } + /** + * @return belongsToMany + */ + public function connectionSegments(): HasMany + { + return $this->hasMany(ConnectionSegment::class, 'company_connection_id'); + } + } diff --git a/app/Models/Group.php b/app/Models/Group.php index 276b0aa5..188b0fe5 100644 --- a/app/Models/Group.php +++ b/app/Models/Group.php @@ -84,4 +84,12 @@ class Group extends Model implements Documentable, Transactionable { return $this->BelongsTo(Currency::class, 'original_currency_id', 'id'); } + + /** + * @return hasOne + */ + public function payment() + { + return $this->hasOne(Transaction::class, 'payment_reference', 'reference'); + } } diff --git a/resources/assets/vue/components/companies/elements/CompanyComponent.vue b/resources/assets/vue/components/companies/elements/CompanyComponent.vue index 293bca54..2353102d 100644 --- a/resources/assets/vue/components/companies/elements/CompanyComponent.vue +++ b/resources/assets/vue/components/companies/elements/CompanyComponent.vue @@ -10,6 +10,10 @@
{{this.item.name}}
CIEF/{{this.item.company_module.marking}}
+
+
Whatsapp:
+
{{ this.item.whatsapp.reference.replace('Whatsapp:', '') }}: {{ this.item.whatsapp.phone }}
+
Orders
{{this.item.order_count}}
diff --git a/resources/assets/vue/components/companies/elements/CustomerPaymentBillingInnerComponent.vue b/resources/assets/vue/components/companies/elements/CustomerPaymentBillingInnerComponent.vue index 19ca390a..634550da 100644 --- a/resources/assets/vue/components/companies/elements/CustomerPaymentBillingInnerComponent.vue +++ b/resources/assets/vue/components/companies/elements/CustomerPaymentBillingInnerComponent.vue @@ -116,9 +116,10 @@ }, sumAmount () { var new_object = this.selectedInvoice; - return Object.keys(new_object).reduce(function(total, key) { - return total + Math.round(new_object[key].amount * 100) / 100; + var total = Object.keys(new_object).reduce(function(total, key) { + return total + new_object[key].amount; }, 0).toFixed(2); + return Math.round(total * 100) / 100; }, selectedIds () { return this.selectedInvoice.map(s=>s.id); diff --git a/resources/assets/vue/components/companies/elements/FulfilmentInterestedFormComponent.vue b/resources/assets/vue/components/companies/elements/FulfilmentInterestedFormComponent.vue new file mode 100644 index 00000000..28492048 --- /dev/null +++ b/resources/assets/vue/components/companies/elements/FulfilmentInterestedFormComponent.vue @@ -0,0 +1,115 @@ + + diff --git a/resources/assets/vue/components/companies/elements/NewServiceAnnouncementComponent.vue b/resources/assets/vue/components/companies/elements/NewServiceAnnouncementComponent.vue new file mode 100644 index 00000000..9f69a28e --- /dev/null +++ b/resources/assets/vue/components/companies/elements/NewServiceAnnouncementComponent.vue @@ -0,0 +1,119 @@ + + + diff --git a/resources/assets/vue/components/general/elements/ListPollingComponent.vue b/resources/assets/vue/components/general/elements/ListPollingComponent.vue index 03c58088..b5488cad 100644 --- a/resources/assets/vue/components/general/elements/ListPollingComponent.vue +++ b/resources/assets/vue/components/general/elements/ListPollingComponent.vue @@ -74,9 +74,6 @@ data(){ return { filters: this.options, - pollingInterval: null, - isPolling: false, - isFetchingResult: false, isLoading: false, } }, @@ -87,13 +84,26 @@ computed: { pendingList () { return this.$store.getters.isInCompleteQueue(this.section); - } + }, + getJob() { + return this.$store.getters.getJob(this.section); + }, + getJobAttemptCount() { + return this.$store.getters.getJobAttemptCount(this.section); + }, }, watch: { pendingList(inComplete){ if(inComplete){ this.fetchList(); } + }, + getJobAttemptCount(newValue, oldValue) { + // console.log('Old value:', JSON.stringify(oldValue)); + // console.log('New value:', JSON.stringify(newValue)); + if(this.getJob){ + this.fetchJobResult(this.getJob.isLastAttempt); + } } }, methods: { @@ -101,7 +111,7 @@ let listDecorators = this.$store.getters.getListDetails(this.section); let url = this.endpoint + '?page=' + listDecorators.page + '&filters=' + JSON.stringify(listDecorators.filters); this.isLoading = true; - this.submitJob(url); + this.$store.dispatch('submitJobRequest', {'url': url, 'name': this.section}); }, successHandler(response){ let result = JSON.parse(response.payload.data.result); @@ -118,83 +128,21 @@ to: result.meta.to, total: result.meta.total }; - - this.stopPolling(); this.$store.dispatch('completeList', {'name': this.section, 'data': result.data}); + this.$store.dispatch('stopPollingJobResultByJobId', {'jobId': this.getJob.jobId}); this.$refs.pagination.makePagination(result.meta, result.links); this.isLoading = false; }, errorHandler(error){ - this.isFetchingResult = false; - this.isPolling = false; + // console.log("Error: " + JSON.stringify(error)); + this.$store.dispatch('updatePollingJobResultByJobId', {'jobId': this.getJob.jobId, 'isPolling': false, 'isFetchingResult': false }); }, - startPolling(jobId, maxAttempts = 8) { - let attempts = 0; - let interval = 10000; // Initial interval - - const resetPollingInterval = (customInterval) => { - this.pollingInterval = setInterval(pollJobResult, customInterval); - }; - - const pollJobResult = () => { - if (this.isPolling || this.isFetchingResult) { - return; - } - this.isPolling = true; - - attempts++; - if(attempts === 1){ - this.stopPolling(); - resetPollingInterval(5000); - } - - if (attempts > maxAttempts) { - this.stopPolling(); - this.isLoading = false; - console.log(`Reached maximum attempts (${maxAttempts}). Polling stopped.`); - return; - } - - if(attempts === maxAttempts){ - this.fetchJobResult(jobId, true); - } - else{ - this.fetchJobResult(jobId); - } - }; - - // pollJobResult(); // Initial call - this.pollingInterval = setInterval(pollJobResult, interval); - }, - stopPolling() { - clearInterval(this.pollingInterval); - this.pollingInterval = null; - this.isPolling = false; - this.isFetchingResult = false; - }, - submitJob(url){ + fetchJobResult(isLastAttempt = false) { + this.$store.dispatch('updatePollingJobResultByJobId', {'jobId': this.getJob.jobId, 'isFetchingResult': true }); try { - this.$store.dispatch('crudRequestV2', {endpoint: url, method: 'get'}).then(response => { - let success = response.ok; - response.json().then(response => { - if(!success){return;} - let jobId = response.payload.data.job_id; - if(jobId){ - this.startPolling(jobId); - } - }); - }) - } catch (error) { - console.error('Error submitJob', error); - } - }, - fetchJobResult(jobId, isLastAttempt = false) { - // console.log('fetchJobResult: ', jobId); - this.isFetchingResult = true; - try { - let anotherEndpoint = route('api.job.fetch', jobId); + let anotherEndpoint = route('api.job.fetch', this.getJob.jobId); if(isLastAttempt){ - anotherEndpoint = route('api.job.fetch.last.attempt', jobId, isLastAttempt); + anotherEndpoint = route('api.job.fetch.last.attempt', this.getJob.jobId, isLastAttempt); } this.poll(anotherEndpoint, 'get', this.section, false, false); //cief todo: Uncaught (in promise) null } catch (error) { diff --git a/resources/assets/vue/components/orders/elements/UnclaimedPackinglistComponent.vue b/resources/assets/vue/components/orders/elements/UnclaimedPackinglistComponent.vue index b4b928c3..71bd5d72 100644 --- a/resources/assets/vue/components/orders/elements/UnclaimedPackinglistComponent.vue +++ b/resources/assets/vue/components/orders/elements/UnclaimedPackinglistComponent.vue @@ -17,7 +17,7 @@
- +
@@ -51,7 +51,7 @@
Cancel
-
Confirm
+
Confirm
@@ -78,6 +78,12 @@ diff --git a/resources/assets/vue/components/paymentsBilling/elements/CustomerPaymentsBillingComponent.vue b/resources/assets/vue/components/paymentsBilling/elements/CustomerPaymentsBillingComponent.vue index 244ba240..fcd25eb0 100644 --- a/resources/assets/vue/components/paymentsBilling/elements/CustomerPaymentsBillingComponent.vue +++ b/resources/assets/vue/components/paymentsBilling/elements/CustomerPaymentsBillingComponent.vue @@ -68,10 +68,10 @@ - +
+
+
+
+

Packinglist Reference

+
{{ item.packing_list_reference }}
+
+
+
+
@@ -179,7 +189,7 @@
MYR {{(Math.round((item.outstanding + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
-
+
Make Payment
@@ -238,6 +248,17 @@ latestComment() { let questions = this.item.remarks; return questions.slice().reverse()[0]; + }, + paymentPending(){ + if (Array.isArray(this.item.transactions)) { + for (let i = 0; i < this.item.transactions.length; i++) { + const status = this.item.transactions[i].status; + if (status === 1) { + return true; + } + } + } + return false; } }, created(){ diff --git a/resources/assets/vue/components/paymentsBilling/elements/PaymentHistoryComponent.vue b/resources/assets/vue/components/paymentsBilling/elements/PaymentHistoryComponent.vue index 8d5dee0f..e7a08882 100644 --- a/resources/assets/vue/components/paymentsBilling/elements/PaymentHistoryComponent.vue +++ b/resources/assets/vue/components/paymentsBilling/elements/PaymentHistoryComponent.vue @@ -92,6 +92,22 @@
+
+
+
Payment Method
+
+ {{ convertPaymentMethodToText(item.payment_method) }} +
+
+
+
Created At
+
{{ item.created_at }}
+
+
+
Updated At
+
{{ item.updated_at }}
+
+
-
-

Total CBM

-
{{ (parseFloat(cbm) + parseFloat(overweight)).toFixed(3) }}
-
-
-
-
- -
Invoice Details
- - -
-
-

Subtotal

-
{{ item.shipping_transaction.amount - item.shipping_transaction.service_charge - item.shipping_transaction.tax }}
-
-
-

Service Charges

-
{{ item.shipping_transaction.service_charge }}
-
-
-

Tax

-
{{ item.shipping_transaction.tax }}
-
-
-

Total

-
{{ item.shipping_transaction.amount }}
-
-
- - -
-
-
-
-
-
-
-
-
Payment Attempt
-
-
-
-
- -
-
-
-
-
-
-
-
-
Payment History
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Total Amount:
-
-
-
MYR {{(Math.round((item.shipping_transaction.amount + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
-
-
-
-
-
Paid Total:
-
-
- -
Paid Total
-
-
-
-
-
Floating Amount:
-
-
- -
Floating Amount
-
-
-
-
-
OutStanding Total:
-
-
-
MYR {{(Math.round((item.shipping_transaction.outstanding + Number.EPSILON) * 100) / 100).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}}
-
-
-
-
-
Make Payment
-
-
-
-
- - - -
-
-
-
- - - - diff --git a/resources/assets/vue/components/paymentsBilling/forms/PaymentFormComponent.vue b/resources/assets/vue/components/paymentsBilling/forms/PaymentFormComponent.vue index bd861a20..3ff38d1f 100644 --- a/resources/assets/vue/components/paymentsBilling/forms/PaymentFormComponent.vue +++ b/resources/assets/vue/components/paymentsBilling/forms/PaymentFormComponent.vue @@ -157,6 +157,7 @@ this.error = response.payload.data.message; } else{ + this.closeModal(); this.updateList(); } } diff --git a/resources/assets/vue/components/paymentsBilling/forms/PaymentVerificationFormComponent.vue b/resources/assets/vue/components/paymentsBilling/forms/PaymentVerificationFormComponent.vue index bb1df036..a60f6b14 100644 --- a/resources/assets/vue/components/paymentsBilling/forms/PaymentVerificationFormComponent.vue +++ b/resources/assets/vue/components/paymentsBilling/forms/PaymentVerificationFormComponent.vue @@ -76,9 +76,14 @@ files: this.files }; this.submit(this.route('api.transaction.payment.verification.create', this.data.id), 'post', this.section, true, true) - } + }, + successHandler(response){ + this.closeModal(); + this.formHandler(); + window.location.reload(); + }, }, mixins: [ModalFromHandler] } - \ No newline at end of file + diff --git a/resources/assets/vue/components/paymentsBilling/sections/AdminPaymentsBillingSectionComponent.vue b/resources/assets/vue/components/paymentsBilling/sections/AdminPaymentsBillingSectionComponent.vue index 190ebe17..6ab087a5 100644 --- a/resources/assets/vue/components/paymentsBilling/sections/AdminPaymentsBillingSectionComponent.vue +++ b/resources/assets/vue/components/paymentsBilling/sections/AdminPaymentsBillingSectionComponent.vue @@ -113,7 +113,7 @@
- +
diff --git a/resources/assets/vue/components/segments/elements/SegmentCompanyComponent.vue b/resources/assets/vue/components/segments/elements/SegmentCompanyComponent.vue new file mode 100644 index 00000000..573dec15 --- /dev/null +++ b/resources/assets/vue/components/segments/elements/SegmentCompanyComponent.vue @@ -0,0 +1,119 @@ + + + diff --git a/resources/assets/vue/components/settings/elements/SegmentComponent.vue b/resources/assets/vue/components/settings/elements/SegmentComponent.vue index ceb8ca29..000c3b54 100644 --- a/resources/assets/vue/components/settings/elements/SegmentComponent.vue +++ b/resources/assets/vue/components/settings/elements/SegmentComponent.vue @@ -34,6 +34,15 @@
+
+
+
+ + + +
+
+
diff --git a/resources/assets/vue/vuex/modules/jobPolling.js b/resources/assets/vue/vuex/modules/jobPolling.js new file mode 100644 index 00000000..1fc03d4c --- /dev/null +++ b/resources/assets/vue/vuex/modules/jobPolling.js @@ -0,0 +1,134 @@ + +const state = { + pollingJobResults: [] +}; + +export default { + state, + getters: { + getJob: (state) => (name) => { + return state.pollingJobResults.find(item => item.name === name);; + }, + getJobAttemptCount: (state) => (name) => { + let job = state.pollingJobResults.find(item => item.name === name); + return job ? job.pollingAttemptsCount : 0; + }, + }, + mutations: { + ADD_POLLING_JOB_RESULT(state, {jobId, name, pollingAttemptsCount, isPolling, isFetchingResult, maxAttempts, pollJobResult, interval}) { + let intervalId = setInterval(() => { + if (pollJobResult) { + pollJobResult(state); + } + }, interval); + state.pollingJobResults.push({ jobId, name, pollingAttemptsCount, isPolling, isFetchingResult, maxAttempts, intervalId}); + }, + UPDATE_POLLING_JOB_RESULT(state, { jobId, pollingAttemptsCount, isPolling, isFetchingResult, isLastAttempt}) { + const index = state.pollingJobResults.findIndex(s => s.jobId === jobId); + if (index !== -1) { + const updatedPollingJobResults = [...state.pollingJobResults]; + updatedPollingJobResults[index] = { ...updatedPollingJobResults[index], + jobId, + pollingAttemptsCount: pollingAttemptsCount !== undefined ? pollingAttemptsCount : updatedPollingJobResults[index].pollingAttemptsCount, + isPolling: isPolling !== undefined ? isPolling : updatedPollingJobResults[index].isPolling, + isFetchingResult: isFetchingResult !== undefined ? isFetchingResult : updatedPollingJobResults[index].isFetchingResult, + isLastAttempt: isLastAttempt !== undefined ? isLastAttempt : updatedPollingJobResults[index].isLastAttempt, + }; + state.pollingJobResults = updatedPollingJobResults; + } + }, + REMOVE_POLLING_JOB_RESULT_BY_JOBID(state, jobId) { + const index = state.pollingJobResults.findIndex(s => s.jobId === jobId); + if (index !== -1) { + clearInterval(state.pollingJobResults[index].intervalId); + state.pollingJobResults.splice(index, 1); + } + }, + // REMOVE_POLLING_JOB_RESULT_BY_JOBID_2(state, jobId) { + // const index = state.pollingJobResults.findIndex(s => s.jobId === jobId); + // if (index !== -1) { + // clearInterval(state.pollingJobResults[index].intervalId); + // //state.pollingJobResults.splice(index, 1); + // } + // }, + REMOVE_POLLING_JOB_RESULT_BY_NAME(state, name) { + const index = state.pollingJobResults.findIndex(s => s.name === name); + if (index !== -1) { + clearInterval(state.pollingJobResults[index].intervalId); + state.pollingJobResults.splice(index, 1); + } + }, + }, + actions: { + submitJobRequest({ dispatch }, { url, name }){ + dispatch('crudRequestV2', { + endpoint: url, + method: 'get', + + }).then(response => { + let success = response.ok; + response.json().then(response => { + if(!success){return;} + let jobId = response.payload.data.job_id; + if(jobId){ + let pollingAttemptsCount = 0; + dispatch('startPolling', { jobId, name, pollingAttemptsCount }); + } + }); + }) + }, + + stopPollingJobResultByJobId({ commit }, { jobId }){ + commit('REMOVE_POLLING_JOB_RESULT_BY_JOBID', jobId); + }, + + stopPollingJobResultByName({ commit }, { name }){ + commit('REMOVE_POLLING_JOB_RESULT_BY_NAME', name); + }, + + startPolling({ state, commit, dispatch }, { jobId, name, pollingAttemptsCount, maxAttempts = 8}) { + let interval = 10000; + + // console.log(`startPolling jobId: ${jobId}, pollingAttemptsCount: ${pollingAttemptsCount}, name: ${name}`); + + const pollJobResult = (state) => { + //console.log(`MONITOR state ${JSON.stringify(state)}`); + const index = state.pollingJobResults.findIndex(s => s.jobId === jobId); + if (index !== -1) { + pollingAttemptsCount = state.pollingJobResults[index].pollingAttemptsCount; + if (state.pollingJobResults[index].isPolling || state.pollingJobResults[index].isFetchingResult) { + return; + } + } + else{ + return; + } + + pollingAttemptsCount++; + if(pollingAttemptsCount === 1){ + commit("REMOVE_POLLING_JOB_RESULT_BY_JOBID", jobId ); + commit("ADD_POLLING_JOB_RESULT", { jobId, name, pollingAttemptsCount, isPolling: false, isFetchingResult: false, maxAttempts, pollJobResult, interval: 5000}); + } + + if (pollingAttemptsCount > maxAttempts) { + //console.log(`Reached maximum attempts (${maxAttempts}). Polling stopped.`); + commit("REMOVE_POLLING_JOB_RESULT_BY_JOBID", jobId ); + return; + } + + if(pollingAttemptsCount === maxAttempts){ + commit('UPDATE_POLLING_JOB_RESULT', { jobId, pollingAttemptsCount, isPolling: true, isFetchingResult: false, isLastAttempt: true }); + } + else{ + commit('UPDATE_POLLING_JOB_RESULT', { jobId, pollingAttemptsCount, isPolling: true, isFetchingResult: false, isLastAttempt: false}); + } + } + commit("ADD_POLLING_JOB_RESULT", { jobId, name, pollingAttemptsCount, isPolling: false, isFetchingResult: false, maxAttempts, pollJobResult, interval}); + + }, + + updatePollingJobResultByJobId({ commit }, { jobId, isPolling, isFetchingResult }){ + commit('UPDATE_POLLING_JOB_RESULT', { jobId, isPolling, isFetchingResult }); + } + } +} diff --git a/resources/assets/vue/vuex/store.js b/resources/assets/vue/vuex/store.js index ff10c673..907e20e4 100644 --- a/resources/assets/vue/vuex/store.js +++ b/resources/assets/vue/vuex/store.js @@ -7,6 +7,7 @@ import crudRequest from './modules/crudRequest' import crudRequestV2 from './modules/crudRequestV2' import authentication from './modules/authentication' import loadRequestQueue from './modules/loadRequestQueue' +import jobPolling from './modules/jobPolling' Vue.use(Vuex); @@ -18,6 +19,7 @@ export default new Vuex.Store({ createNotification, crudRequest, crudRequestV2, - authentication + authentication, + jobPolling } }) diff --git a/resources/views/layouts/base.blade.php b/resources/views/layouts/base.blade.php index 40e53d6c..166d0a64 100644 --- a/resources/views/layouts/base.blade.php +++ b/resources/views/layouts/base.blade.php @@ -4,10 +4,16 @@ @include('vendor/head') - - - + + + +
@yield('content')
diff --git a/resources/views/pages/paymentAndBilling2.blade.php b/resources/views/pages/paymentAndBilling2.blade.php index ac1de6b2..184b201e 100644 --- a/resources/views/pages/paymentAndBilling2.blade.php +++ b/resources/views/pages/paymentAndBilling2.blade.php @@ -131,7 +131,7 @@
-
+
diff --git a/resources/views/pages/segments/_tabs.blade.php b/resources/views/pages/segments/_tabs.blade.php new file mode 100644 index 00000000..1dba41c3 --- /dev/null +++ b/resources/views/pages/segments/_tabs.blade.php @@ -0,0 +1,134 @@ +
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
{{ __('Standard') }}
+
+
+
+
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
{{ __('Custom') }}
+
+
+
+
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
{{ __('Label') }}
+
+
+
+
+
+
diff --git a/resources/views/pages/segments/index.blade.php b/resources/views/pages/segments/index.blade.php new file mode 100644 index 00000000..61699bba --- /dev/null +++ b/resources/views/pages/segments/index.blade.php @@ -0,0 +1,12 @@ +@extends('layouts.base_portal') +@section('inner_content') +
+
+
+
+ +
+
+
+
+@endsection diff --git a/resources/views/partials/menu.blade.php b/resources/views/partials/menu.blade.php index f019d874..2e254332 100644 --- a/resources/views/partials/menu.blade.php +++ b/resources/views/partials/menu.blade.php @@ -180,6 +180,17 @@
Support
+
+
+ +
+
+
Segments
+
+
@@ -206,8 +217,8 @@
-
-
+
+
@@ -223,6 +234,9 @@
+
+ +
diff --git a/resources/views/vendor/head.blade.php b/resources/views/vendor/head.blade.php index f36a5b76..dd87bbda 100644 --- a/resources/views/vendor/head.blade.php +++ b/resources/views/vendor/head.blade.php @@ -1,11 +1,3 @@ - - - - @yield('title', 'IZYIM Shipping') diff --git a/routes/web.php b/routes/web.php index c95a958d..7a11b705 100644 --- a/routes/web.php +++ b/routes/web.php @@ -34,6 +34,7 @@ use Carbon\Carbon; use Illuminate\Http\Request; use Illuminate\Support\Facades\Crypt; use App\Models\Container; +use App\Models\Group; use App\Models\Transaction; use App\Models\Wallet; use Illuminate\Support\Facades\DB; @@ -1271,6 +1272,8 @@ Route::get('/payment-and-billing-2', function () { Route::get('/show-all-extra-payments', function () { ini_set('memory_limit', '-1'); + ini_set('max_execution_time', 0); + $transactionCounter = 0; $invoices = Transaction::where('type', TransactionType::SHIPPING_INVOICE) ->where('status', ApprovalStatus::COMPLETED) @@ -1300,6 +1303,7 @@ Route::get('/show-all-extra-payments', function () { if (($paidAmount <= $invoice->amount) || ($paidAmount - $invoice->amount < 0.01)) { continue; } + $transactionCounter += 1; echo ''; echo '' . $invoice->type . ''; @@ -1310,4 +1314,35 @@ Route::get('/show-all-extra-payments', function () { echo ''; } echo ''; + + echo'
Total: ' . $transactionCounter; +}); + +Route::get('/segments', function (Request $request) { + return view('pages.segments.index'); +})->name('segments'); + +Route::get('/group-transaction-with-completed-payments', function () { + $groups = Group::whereNotIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]) + ->whereHas('payment', function ($query) { + $query->whereIn('status', [2, 3]); + })->get(); + + foreach ($groups as $group) { + $groupPayment = $group->payment; + $order = $group->groupTransactions->first()->transaction->owner->owner; + $companyModule = $order->companyModule; + + $connection = $companyModule->connections()->first(); + $companyMarking = $connection ? $connection->invitee_reference : ''; + + dump([ + 'reference' => $group->reference, + 'groupPayment_id' => $groupPayment->id, + 'groupPayment_status' => $groupPayment->status, + 'order' => $order->reference, + 'companyMarking' => $companyMarking, + ]); + echo '' . $companyMarking . '
'; + } });