Compare commits

...

34 Commits

Author SHA1 Message Date
edmondlang dbc57fdaac code update 2023-12-31 12:58:22 +08:00
edmondlang 9c9cf0f96e api and web response time log 2023-12-28 23:04:16 +08:00
edmondlang 8513309126 api response time logging 2023-12-28 22:50:19 +08:00
Dillon Ngo e0805a9601 Merge branch 'dillon/46-warehouse-storage-charges-2-merge-conflict' into 'master'
Emergency fix problem with group payment (reported by Eileen)

See merge request CIEFWorldwideSdnBhd/shipping-portal!184
2023-12-20 18:19:08 +00:00
Dillon Ngo 6f36c4b7ee Emergency fix problem with group payment (reported by Eileen) 2023-12-21 02:17:04 +08:00
Dillon Ngo 87194794f2 Merge branch 'dillon/46-warehouse-storage-charges-2-merge-conflict' into 'master'
Emergency fix problem with group payment (reported by Eileen)

See merge request CIEFWorldwideSdnBhd/shipping-portal!183
2023-12-20 16:06:34 +00:00
Dillon Ngo b4eca67a2f Emergency fix problem with group payment (reported by Eileen) 2023-12-20 23:58:56 +08:00
Dillon Ngo 1770b06498 Merge branch 'dillon/46-warehouse-storage-charges-2-merge-conflict' into 'master'
Emergency fix problem with group payment (reported by Eileen)

See merge request CIEFWorldwideSdnBhd/shipping-portal!182
2023-12-20 12:58:32 +00:00
Dillon Ngo 5c9fd6e2a6 Emergency fix problem with group payment (reported by Eileen) 2023-12-20 20:52:24 +08:00
Dillon Ngo ed7a636a18 Merge branch 'dillon/46-warehouse-storage-charges-2-merge-conflict' into 'master'
Fix a typo error

See merge request CIEFWorldwideSdnBhd/shipping-portal!181
2023-12-11 17:08:06 +00:00
Dillon Ngo 19bd548127 Fix a typo error 2023-12-12 01:07:06 +08:00
Dillon Ngo 55ac8064b1 Merge branch 'dillon/46-warehouse-storage-charges-2-merge-conflict' into 'master'
Warehouse Storage Charges - Effective From 11/12/2023 onwards

See merge request CIEFWorldwideSdnBhd/shipping-portal!180
2023-12-11 13:36:41 +00:00
Dillon Ngo e7279ec4d0 Merge branch 'master' into dillon/46-warehouse-storage-charges-2-merge-conflict 2023-12-11 21:29:06 +08:00
Dillon Ngo 782a5c33ad Merge branch 'dillon/48-feedback-form-improvement' into 'master'
Update title for public feedback form page requested by Omair

See merge request CIEFWorldwideSdnBhd/shipping-portal!179
2023-12-09 04:54:15 +00:00
Dillon Ngo 6d3a2d9259 Update title for public feedback form page requested by Omair 2023-12-09 12:50:12 +08:00
Dillon Ngo 730b3d439a Merge branch 'dillon/48-feedback-form-improvement' into 'master'
Feedback form improvement

See merge request CIEFWorldwideSdnBhd/shipping-portal!178
2023-12-08 12:23:51 +00:00
Dillon Ngo 6b09d5facc Minor update on question text 2023-12-08 13:41:00 +08:00
Omair Saleh 4c532deb4d debug yd address update 2023-11-28 22:44:36 +08:00
edmondlang 12f05b7aa6 add paymentUnknownOrderLog 2023-11-28 22:15:36 +08:00
edmondlang 5cdbc09c5b update packinglist measurement - add order number 2023-11-26 23:45:32 +08:00
edmondlang c9877bb53e update packinglist measurement - change from order number to packinglist number 2023-11-26 22:21:02 +08:00
edmondlang 0bf84fa7b1 update combined invoice and packinglist measurement 2023-11-26 22:01:02 +08:00
Dillon Ngo 4c9235cc53 Fix a tiny spelling mistake 2023-11-22 03:22:39 +08:00
Dillon Ngo babd492caa Questions should have order by just like answers 2023-11-22 03:14:36 +08:00
Dillon Ngo 3d1d1cce11 Fix feedback answer text not displaying correctly at admin dashboard 2023-11-21 19:41:30 +08:00
Dillon Ngo 820d96858f Feedback Form Improvement 2023-11-21 19:29:40 +08:00
Dillon Ngo 058ba592bf Merge branch 'dillon/48-feedback-form-improvement' into 'master'
Quick fix for feedback form entries cannot be downloaded

See merge request CIEFWorldwideSdnBhd/shipping-portal!177
2023-11-21 08:41:54 +00:00
Dillon Ngo d950ee3d68 Quick fix for feedback form entries cannot be downloaded 2023-11-21 16:34:32 +08:00
edmondlang da6ec00dbd cleanup 2023-10-27 16:13:43 +08:00
edmondlang 412dbd64d5 fix-payment-status-updated-but-failed-update-invoice 2023-10-27 16:12:31 +08:00
edmondlang 496df549f6 remove code 2023-10-27 10:10:02 +08:00
edmondlang 97eaefa45a regenerate single invoice 2023-10-27 09:16:23 +08:00
edmondlang 68c9e0451a update admin geenrate invoice view 2023-10-27 08:55:54 +08:00
JiaSheng 671c7a54fb fix delivery order in shipping invoice 2023-10-26 22:31:10 +08:00
39 changed files with 1068 additions and 133 deletions
@@ -6,10 +6,9 @@ use Illuminate\Http\Request;
use App\Models\Wallet;
use App\Models\Group;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\Modules\Transactions\Processors\CreatePaymentTransactionProcessor;
use App\Classes\Modules\Transactions\Processors\CreateStorageInvoiceDocTransactionProcessor;
use App\Classes\Modules\Transactions\Processors\ReleaseGoodsToCustomerProcessor;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use App\Classes\Modules\Wallets\Services\UpdatesWalletBalance;
use App\Classes\Modules\Orders\Processors\UpdateDoFromVTPortalProcessor;
@@ -33,8 +32,8 @@ class CallbackBillplzProcessor
/** @var CreatePaymentTransactionProcessor */
private $createPaymentTransactionProcessor;
/** @var CreateStorageInvoiceDocTransactionProcessor */
private $ceateStorageInvoiceDocTransactionProcessor;
/** @var ReleaseGoodsToCustomerProcessor */
private $releaseGoodsToCustomerProcessor;
/**
* CreateUserProcessor constructor.
@@ -43,16 +42,16 @@ class CallbackBillplzProcessor
* @param UpdateDoFromYDPortalProcessor $updateDoFromYDPortalProcessor
* @param UpdatesWalletBalance $updatesWalletBalance
* @param CreatePaymentTransactionProcessor $createPaymentTransactionProcessor
* @param CreateStorageInvoiceDocTransactionProcessor $ceateStorageInvoiceDocTransactionProcessor
* @param ReleaseGoodsToCustomerProcessor $releaseGoodsToCustomerProcessor
*/
public function __construct(UpdatesTransactionStatus $updatesTransactionStatus, UpdateDoFromVTPortalProcessor $updateDoFromVTPortalProcessor, UpdateDoFromYDPortalProcessor $updateDoFromYDPortalProcessor, UpdatesWalletBalance $updatesWalletBalance, CreatePaymentTransactionProcessor $createPaymentTransactionProcessor, CreateStorageInvoiceDocTransactionProcessor $ceateStorageInvoiceDocTransactionProcessor)
public function __construct(UpdatesTransactionStatus $updatesTransactionStatus, UpdateDoFromVTPortalProcessor $updateDoFromVTPortalProcessor, UpdateDoFromYDPortalProcessor $updateDoFromYDPortalProcessor, UpdatesWalletBalance $updatesWalletBalance, CreatePaymentTransactionProcessor $createPaymentTransactionProcessor, ReleaseGoodsToCustomerProcessor $releaseGoodsToCustomerProcessor)
{
$this->updatesTransactionStatus = $updatesTransactionStatus;
$this->updateDoFromVTPortalProcessor = $updateDoFromVTPortalProcessor;
$this->updateDoFromYDPortalProcessor = $updateDoFromYDPortalProcessor;
$this->updatesWalletBalance = $updatesWalletBalance;
$this->createPaymentTransactionProcessor = $createPaymentTransactionProcessor;
$this->ceateStorageInvoiceDocTransactionProcessor = $ceateStorageInvoiceDocTransactionProcessor;
$this->releaseGoodsToCustomerProcessor = $releaseGoodsToCustomerProcessor;
}
@@ -82,11 +81,11 @@ class CallbackBillplzProcessor
foreach ($group->groupTransactions as $groupTransaction) {
$invoice = $groupTransaction->transaction;
$paymentTransaction = $this->createPaymentTransactionProcessor->execute($invoice, PaymentMethodType::WALLET, null);
$paymentTransaction = $this->createPaymentTransactionProcessor->execute($invoice, PaymentMethodType::WALLET, null, false);
if($paymentTransaction && $paymentTransaction->status == ApprovalStatus::APPROVED){
$pL = $invoice->owner;
$this->processPackingListAndInvoice($pL, $invoice);
$this->releaseGoodsToCustomerProcessor->execute($pL, $invoice);
}
}
@@ -96,7 +95,7 @@ class CallbackBillplzProcessor
}
if (!$transaction->owner instanceof Wallet) {
$this->processPackingListAndInvoice($packingList, $invoice);
$this->releaseGoodsToCustomerProcessor->execute($packingList, $invoice);
}
return true;
@@ -126,49 +125,4 @@ class CallbackBillplzProcessor
}
return true;
}
private function processPackingListAndInvoice($packingList, $invoice = null){
$result = false;
$totalInvoicesAmountPaid = 0.00;
$totalInvoicesAmount = 0.00;
$invoiceTransactions = $packingList->transactions()->where('status', [ApprovalStatus::APPROVED])->whereIn('type', [TransactionType::SHIPPING_INVOICE, TransactionType::STORAGE_INVOICE])->get();
//Part 1: Process each single invoice type and get the total of all invoices
foreach($invoiceTransactions as $invoiceTransaction){
$totalInvoiceAmountPaid = $invoiceTransaction->transactions->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->sum('amount');
if ($invoice && $invoice->type == $invoiceTransaction->type) {
if(($invoice->amount - $totalInvoiceAmountPaid) < 0.01){
$this->updatesTransactionStatus->execute($invoice, ApprovalStatus::COMPLETED);
if($invoice->type == TransactionType::STORAGE_INVOICE){
$this->ceateStorageInvoiceDocTransactionProcessor->execute($packingList);
}
}
}
$totalInvoicesAmount = $totalInvoicesAmount + $invoiceTransaction->amount;
$totalInvoicesAmountPaid = $totalInvoicesAmountPaid + $totalInvoiceAmountPaid;
}
Log::channel('storage_invoices')->info('Total invoice amount paid 1: '.$totalInvoicesAmount); //cief todo: to be removed
Log::channel('storage_invoices')->info('Total invoice amount paid 2: '.$totalInvoicesAmountPaid); //cief todo: to be removed
//Part 2: Based on the collected info for all the total of all invoices
if (($totalInvoicesAmount - $totalInvoicesAmountPaid) < 0.01) {
Log::channel('storage_invoices')->info('Total invoice amount paid 3: '.$totalInvoicesAmountPaid); //cief todo: to be removed
$packingList->status = ApprovalStatus::APPROVED;
$packingList->save();
if (app()->environment('production')) {
$this->updateDoFromVTPortalProcessor->execute($packingList);
$this->updateDoFromYDPortalProcessor->execute($packingList);
}
$result = true;
}
return $result;
}
}
@@ -20,9 +20,11 @@ class ExportsFeedback implements FromQuery, WithHeadings, WithHeadingRow, WithMa
public function headings(): array
{
return [
'Version',
'Question Set',
'Question Text',
'Answer',
'Answer Text',
'Answer Value',
'Source System',
'Source Marking',
'Source Email',
@@ -38,7 +40,7 @@ class ExportsFeedback implements FromQuery, WithHeadings, WithHeadingRow, WithMa
return QAUserAnswerSelected::whereHas('question', function ($query) {
$query->whereHas('questionnaire', function ($innerQuery) {
$innerQuery->where('group', 'feedback');
})->where('created_at', '>', Carbon::now()->subMonths(1));
}); //->where('created_at', '>', Carbon::now()->subMonths(1));
})->orderBy('created_at', 'desc');
}
@@ -56,11 +58,14 @@ class ExportsFeedback implements FromQuery, WithHeadings, WithHeadingRow, WithMa
$companyModule = $user->companyModule()->first();
$user_marking = $companyModule ? $companyModule->inviters()->withPivot('invitee_reference')->first()->pivot->invitee_reference : "";
}
$answer = $userAnswer->answer;
return [
$userAnswer->question->questionnaire->version,
$userAnswer->question->questionnaire->description,
$userAnswer->question->question_text,
$userAnswer->free_text_answer,
$answer->display_text,
$answer->value,
$user ? QASystemSourceType::getText(QASystemSourceType::IZYIM) : QASystemSourceType::getText($source->system),
$user ? $user_marking : $source->marking,
$user ? $user->email : $source->email,
@@ -59,7 +59,7 @@ class ListQuestionsQALogic extends AbstractControllerLogic
$delimiter = "|";
$parts = explode($delimiter, $decriptedToken);
$questionSet = $parts[3];
$query = $this->listsHelpMenuQuestions->execute(['questionnaire_set_id' => $questionSet]);
$query = $this->listsHelpMenuQuestions->execute(['questionnaire_set_id' => $questionSet, 'order_by' => (object)['column' => 'order','DESC' => false]]);
return $this->collectionResponse(HelpMenuQuestionResource::collection($query));
}
@@ -38,6 +38,7 @@ class UpdateDoFromYDPortalProcessor
*/
public function execute(PackingList $packingList) {
Log::info('Trying to Call UpdateDoFromYDPortalProcessor');
Log::channel('storage_invoices')->info('UpdateDoFromYDPortalProcessor: '.json_encode($packingList));
if(!app()->environment(['production'])){
return;
@@ -72,6 +73,7 @@ class UpdateDoFromYDPortalProcessor
} catch (\Exception $exception){
log::debug($exception);
throw new InternalServerErrorException('failed to approve address due to an error related to YD portal');
}
}
@@ -21,6 +21,8 @@ use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Models\GroupTransaction;
use App\Http\Resources\WalletTransactionResource;
use App\Models\Wallet;
use App\Classes\Modules\Transactions\Processors\ReleaseGoodsToCustomerProcessor;
class CreateGroupsLogic extends AbstractControllerLogic
{
@@ -55,13 +57,18 @@ class CreateGroupsLogic extends AbstractControllerLogic
/** @var CreatesGroup */
private $createsGroup;
/** @var ReleaseGoodsToCustomerProcessor */
private $releaseGoodsToCustomerProcessor;
public function __construct(
FetchesTransaction $fetchesTransaction,
GeneratesTransactionBillNumber $generatesTransactionBillNumber,
FetchesTransaction $fetchesTransaction,
GeneratesTransactionBillNumber $generatesTransactionBillNumber,
FetchesCompanyModule $fetchesCompanyModule,
CreateWalletTopUpTransactionProcessor $createWalletTopUpTransactionProcessor,
CreatePaymentTransactionProcessor $createPaymentTransactionProcessor,
CreatesGroup $createsGroup
CreatesGroup $createsGroup,
ReleaseGoodsToCustomerProcessor $releaseGoodsToCustomerProcessor
)
{
$this->fetchesTransaction = $fetchesTransaction;
@@ -70,6 +77,7 @@ class CreateGroupsLogic extends AbstractControllerLogic
$this->createWalletTopUpTransactionProcessor = $createWalletTopUpTransactionProcessor;
$this->createPaymentTransactionProcessor = $createPaymentTransactionProcessor;
$this->createsGroup = $createsGroup;
$this->releaseGoodsToCustomerProcessor = $releaseGoodsToCustomerProcessor;
}
public function logic(Request $request) : JsonResponse
@@ -146,7 +154,12 @@ class CreateGroupsLogic extends AbstractControllerLogic
foreach ($invoices as $invoice) {
if ($payment_method == PaymentMethodType::WALLET) {
$this->createPaymentTransactionProcessor->execute($invoice, PaymentMethodType::WALLET, $request->input('bank_code'));
$paymentTransaction = $this->createPaymentTransactionProcessor->execute($invoice, PaymentMethodType::WALLET, $request->input('bank_code'), false);
if($paymentTransaction && $paymentTransaction->status == ApprovalStatus::APPROVED){
$pL = $invoice->owner;
$this->releaseGoodsToCustomerProcessor->execute($pL, $invoice);
}
}
$issuer = $invoice->issuer;
@@ -10,6 +10,8 @@ use App\Http\Resources\TransactionResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use App\Classes\Modules\Transactions\Processors\CreatePaymentTransactionProcessor;
use App\Classes\Modules\Transactions\Processors\ReleaseGoodsToCustomerProcessor;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
class CreatePaymentTransactionLogic extends AbstractControllerLogic
{
@@ -30,13 +32,18 @@ class CreatePaymentTransactionLogic extends AbstractControllerLogic
/** @var CreatePaymentTransactionProcessor */
private $createPaymentTransactionProcessor;
/** @var ReleaseGoodsToCustomerProcessor */
private $releaseGoodsToCustomerProcessor;
public function __construct(
FetchesTransaction $fetchesTransaction,
CreatePaymentTransactionProcessor $createPaymentTransactionProcessor
CreatePaymentTransactionProcessor $createPaymentTransactionProcessor,
ReleaseGoodsToCustomerProcessor $releaseGoodsToCustomerProcessor
)
{
$this->fetchesTransaction = $fetchesTransaction;
$this->createPaymentTransactionProcessor = $createPaymentTransactionProcessor;
$this->releaseGoodsToCustomerProcessor = $releaseGoodsToCustomerProcessor;
}
public function logic(Request $request) : JsonResponse
@@ -45,7 +52,12 @@ class CreatePaymentTransactionLogic extends AbstractControllerLogic
$invoice_transaction = $this->fetchesTransaction->execute(['id' => $request->input('transaction_id')]);
$payment_transaction = $this->createPaymentTransactionProcessor->execute($invoice_transaction, $payment_method , $request->input('bank_code'));
$payment_transaction = $this->createPaymentTransactionProcessor->execute($invoice_transaction, $payment_method , $request->input('bank_code'), false);
if($payment_transaction && $payment_transaction->status == ApprovalStatus::APPROVED){
$pL = $invoice_transaction->owner;
$this->releaseGoodsToCustomerProcessor->execute($pL, $invoice_transaction);
}
//cief todo: at exchange there is a transition step - starts
// if(PaymentMethodType::PAYMENT_METHODS[$request->input('payment_method')] == PaymentMethodType::PAYMENT_GATEWAY){
@@ -63,4 +75,7 @@ class CreatePaymentTransactionLogic extends AbstractControllerLogic
return $this->resourceResponse(new TransactionResource($payment_transaction));
}
}
@@ -0,0 +1,76 @@
<?php
namespace App\Classes\Modules\Transactions\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\DocumentType;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Order;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Mccarlosen\LaravelMpdf\Facades\LaravelMpdf;
use App\Classes\Modules\Documents\Services\CreatesDocument;
use App\Classes\Modules\Documents\Services\CreatesFiles;
use App\Classes\Modules\Transactions\Services\FetchesTransaction;
use App\Models\Document;
class RegenerateSingleShippingInvoiceTransactionLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Regenerate Shipping Invoice',
'message' => 'You have successfully regenerated shipping invoice'
];
}
/** @var CreatesDocument */
private $createsDocument;
/** @var CreatesFiles */
private $createsFiles;
/** @var FetchesTransaction */
private $fetchesTransaction;
/**
* @param CreatesDocument $createsDocument
*/
public function __construct(CreatesDocument $createsDocument, CreatesFiles $createsFiles, FetchesTransaction $fetchesTransaction)
{
$this->createsDocument = $createsDocument;
$this->createsFiles = $createsFiles;
$this->fetchesTransaction = $fetchesTransaction;
}
public function logic(Request $request) : JsonResponse
{
$invoice = $this->fetchesTransaction->execute(['id' => $request->route('invoice_id')]);
$invoice->documents()->delete();
$transaction_invoice_pdf = LaravelMpdf::loadView('pages.pdfs.shipping_invoice', ['invoice_transaction' => $invoice]);
$document_object = new DocumentObject(
DocumentType::SHIPPING_INVOICE,
[chunk_split('data:application/pdf;base64,'.base64_encode($transaction_invoice_pdf->output()))],
'',
ApprovalStatus::COMPLETED,
'shipping_invoice'
);
$document =$this->createsDocument->execute($invoice, $document_object);
$this->createsFiles->execute($document, $document_object);
// dump($document);
return $this->response([]);
}
}
@@ -85,7 +85,7 @@ class CreatePaymentTransactionProcessor
/**
* @throws MalformedRequestException
*/
public function execute(Transaction $invoice, $payment_method, $bank_code)
public function execute(Transaction $invoice, $payment_method, $bank_code, $run = true)
{
$amount = $invoice->amount;
Log::info($invoice->owner);
@@ -127,22 +127,26 @@ class CreatePaymentTransactionProcessor
$this->updatesWalletBalance->execute($wallet, ($amount * -1));
// $packingList = $invoice->owner;
// $order = $packingList->owner;
// $packingList->status = ApprovalStatus::APPROVED;
// $packingList->save();
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);
// }
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
// $this->updatesTransactionStatus->execute($invoice, ApprovalStatus::COMPLETED);
if($run){
$this->updatesTransactionStatus->execute($invoice, ApprovalStatus::COMPLETED);
}
}
else {
$payment_method = PaymentMethodType::CASH;
@@ -0,0 +1,94 @@
<?php
namespace App\Classes\Modules\Transactions\Processors;
use Illuminate\Http\Request;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\Modules\Transactions\Processors\CreateStorageInvoiceDocTransactionProcessor;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use App\Classes\Modules\Orders\Processors\UpdateDoFromVTPortalProcessor;
use App\Classes\Modules\Orders\Processors\UpdateDoFromYDPortalProcessor;
use Illuminate\Support\Facades\Log;
class ReleaseGoodsToCustomerProcessor
{
/** @var UpdatesTransactionStatus */
private $updatesTransactionStatus;
/** @var UpdateDoFromVTPortalProcessor */
private $updateDoFromVTPortalProcessor;
/** @var UpdateDoFromYDPortalProcessor */
private $updateDoFromYDPortalProcessor;
/** @var CreateStorageInvoiceDocTransactionProcessor */
private $createStorageInvoiceDocTransactionProcessor;
/**
* ReleaseGoodsToCustomerProcessor constructor.
* @param UpdatesTransactionStatus $updatesTransactionStatus
* @param UpdateDoFromVTPortalProcessor $updateDoFromVTPortalProcessor
* @param UpdateDoFromYDPortalProcessor $updateDoFromYDPortalProcessor
* @param CreateStorageInvoiceDocTransactionProcessor $createStorageInvoiceDocTransactionProcessor
*/
public function __construct(UpdatesTransactionStatus $updatesTransactionStatus, UpdateDoFromVTPortalProcessor $updateDoFromVTPortalProcessor, UpdateDoFromYDPortalProcessor $updateDoFromYDPortalProcessor, CreateStorageInvoiceDocTransactionProcessor $createStorageInvoiceDocTransactionProcessor)
{
$this->updatesTransactionStatus = $updatesTransactionStatus;
$this->updateDoFromVTPortalProcessor = $updateDoFromVTPortalProcessor;
$this->updateDoFromYDPortalProcessor = $updateDoFromYDPortalProcessor;
$this->createStorageInvoiceDocTransactionProcessor = $createStorageInvoiceDocTransactionProcessor;
}
/**
* @param $packingList
* @param $invoice
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute($packingList, $invoice = null)
{
$result = false;
$totalInvoicesAmountPaid = 0.00;
$totalInvoicesAmount = 0.00;
$invoiceTransactions = $packingList->transactions()->where('status', [ApprovalStatus::APPROVED])->whereIn('type', [TransactionType::SHIPPING_INVOICE, TransactionType::STORAGE_INVOICE])->get();
//Part 1: Process each single invoice type and get the total of all invoices
foreach($invoiceTransactions as $invoiceTransaction){
$totalInvoiceAmountPaid = $invoiceTransaction->transactions->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->sum('amount');
if ($invoice && $invoice->type == $invoiceTransaction->type) {
if(($invoice->amount - $totalInvoiceAmountPaid) < 0.01){
$this->updatesTransactionStatus->execute($invoice, ApprovalStatus::COMPLETED);
if($invoice->type == TransactionType::STORAGE_INVOICE){
$this->createStorageInvoiceDocTransactionProcessor->execute($packingList);
}
}
}
$totalInvoicesAmount = $totalInvoicesAmount + $invoiceTransaction->amount;
$totalInvoicesAmountPaid = $totalInvoicesAmountPaid + $totalInvoiceAmountPaid;
}
Log::channel('storage_invoices')->info('Total invoice amount paid 1: '.$totalInvoicesAmount); //cief todo: to be removed
Log::channel('storage_invoices')->info('Total invoice amount paid 2: '.$totalInvoicesAmountPaid); //cief todo: to be removed
//Part 2: Based on the collected info for all the total of all invoices
if (($totalInvoicesAmount - $totalInvoicesAmountPaid) < 0.01 && $totalInvoicesAmountPaid > 0.01) {
Log::channel('storage_invoices')->info('Total invoice amount paid 3: '.$totalInvoicesAmountPaid); //cief todo: to be removed
$packingList->status = ApprovalStatus::APPROVED;
$packingList->save();
if (app()->environment('production')) {
$this->updateDoFromVTPortalProcessor->execute($packingList);
$this->updateDoFromYDPortalProcessor->execute($packingList);
}
$result = true;
}
return $result;
}
}
@@ -16,7 +16,7 @@ class CheckStorageInvoicesGroupTransactions extends Command
*
* @var string
*/
protected $signature = 'command:check-storage-invoices-group-transactions';
protected $signature = 'check-storage-invoices-group-transactions';
/**
* The console command description.
@@ -17,7 +17,7 @@ class CheckStorageInvoicesOrders extends Command
*
* @var string
*/
protected $signature = 'command:check-storage-invoices-orders';
protected $signature = 'check-storage-invoices-orders';
/**
* The console command description.
@@ -0,0 +1,83 @@
<?php
namespace App\Console\Commands;
use App\Classes\Modules\Transactions\Services\FetchesGroup;
use App\Classes\Modules\Transactions\Processors\ReleaseGoodsToCustomerProcessor;
use Carbon\Carbon;
use Illuminate\Console\Command;
class FixGroupPaymentProblem extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'fix-group-payment-problem';
/**
* The console command description.
*
* @var string
*/
protected $description = 'This is a one time data patch for a problem result from Storage Invoice Implementation';
/** @var FetchesGroup */
private $fetchesGroup;
/** @var ReleaseGoodsToCustomerProcessor */
private $releaseGoodsToCustomerProcessor;
/**
* Create a new command instance.
*
* @return void
*/
public function __construct(FetchesGroup $fetchesGroup, ReleaseGoodsToCustomerProcessor $releaseGoodsToCustomerProcessor)
{
parent::__construct();
$this->fetchesGroup = $fetchesGroup;
$this->releaseGoodsToCustomerProcessor = $releaseGoodsToCustomerProcessor;
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
ini_set('memory_limit', '-1');
$this->info(Carbon::now() . ': Start data patch.');
$start = new Carbon();
$group = $this->fetchesGroup->execute(['id' => 325]);
$this->info('FixGroupPaymentProblem group: '.json_encode($group));
if ($group) {
foreach ($group->groupTransactions as $groupTransaction) {
$invoice = $groupTransaction->transaction;
$this->info('FixGroupPaymentProblem group: '.json_encode($invoice));
//$paymentTransaction = $this->createPaymentTransactionProcessor->execute($invoice, PaymentMethodType::WALLET, null);
//if($paymentTransaction && $paymentTransaction->status == ApprovalStatus::APPROVED){
$pL = $invoice->owner;
$this->releaseGoodsToCustomerProcessor->execute($pL, $invoice);
//}
}
// $group->status = $status;
// $group->save();
}
$end = new Carbon();
$elapsedTime = $start->diff($end)->format('%H:%I:%S');
$this->info(Carbon::now() . ': Done data patch. ElapsedTime: ' . $elapsedTime . '.');
}
}
@@ -0,0 +1,21 @@
<?php
namespace App\Http\Controllers\Transactions;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use App\Classes\Modules\Transactions\ControllersLogic\RegenerateSingleShippingInvoiceTransactionLogic;
class RegenerateSingleShippingInvoiceTransactionController
{
/**
* @param Request $request
* @param RegenerateShippingInvoiceTransactionLogic $logic
* @return JsonResponse
*/
public function regenerate(Request $request, RegenerateSingleShippingInvoiceTransactionLogic $logic) : JsonResponse {
return $logic->execute($request);
}
}
+2
View File
@@ -38,11 +38,13 @@ class Kernel extends HttpKernel
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\WebResponseTimeLog::class,
],
'api' => [
'throttle:300,1',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\ApiResponseTimeLog::class,
],
'apipub' => [
@@ -0,0 +1,29 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
class ApiResponseTimeLog
{
public function handle(Request $request, Closure $next)
{
// Get route information
$route = $request->route();
$routeName = $route ? $route->getName() : 'undefined';
$uri = $request->getPathInfo();
$startTime = microtime(true); // Start time
$response = $next($request); // Handle the request
$endTime = microtime(true); // End time
$responseTime = $endTime - $startTime; // Calculate the response time
Log::channel('apiResponseTimeLog')->info("\nRequest to route: {$uri} \nRoute name: {$routeName} \nTime Taken: " . number_format($responseTime * 1000, 2) . "ms\n");
return $response;
}
}
@@ -0,0 +1,29 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
class WebResponseTimeLog
{
public function handle(Request $request, Closure $next)
{
// Get route information
$route = $request->route();
$routeName = $route ? $route->getName() : 'undefined';
$uri = $request->getPathInfo();
$startTime = microtime(true); // Start time
$response = $next($request); // Handle the request
$endTime = microtime(true); // End time
$responseTime = $endTime - $startTime; // Calculate the response time
Log::channel('webResponseTimeLog')->info("\nRequest to route: {$uri} \nRoute name: {$routeName} \nTime Taken: " . number_format($responseTime * 1000, 2) . "ms\n");
return $response;
}
}
@@ -34,7 +34,7 @@ class HelpMenuQuestionResource extends JsonResource
'question_number' => $q->question_number,
'question_text' => $q->question_text,
'question_type' => $q->question_type,
'question_answers' => HelpMenuAnswerOptionsResource::collection(QAAnswerOptions::where('question_number', $q->question_number)->where('questionnaire_set_id', $q->questionnaire_set_id)->get()),
'question_answers' => HelpMenuAnswerOptionsResource::collection(QAAnswerOptions::where('question_number', $q->question_number)->where('questionnaire_set_id', $q->questionnaire_set_id)->orderBy('order', 'ASC')->get()),
'questionnaire_set_id' => $q->questionnaire_set_id,
'next_nested_question' => $q->next_nested_question,
'next_main_question' => $q->next_main_question,
@@ -18,6 +18,7 @@ class HelpMenuQuestionnaireSetsResource extends JsonResource
'name' => $this->name,
'description' => $this->description,
'group' => $this->group,
'version' => $this->version,
];
}
}
@@ -4,6 +4,7 @@ namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
use App\Classes\ValueObjects\Constants\QASystemSourceType;
use App\Models\QAAnswerOptions;
use App\Models\QAQuestions;
use Carbon\Carbon;
@@ -20,6 +21,7 @@ class HelpMenuQuestionsAnswersResource extends JsonResource
$question = QAQuestions::where('id', $this->question_id)->first();
$source = new HelpMenuUserSourceResource($this->userSource);
$user = $this->source_id === 0 ? new UserResource($this->user) : null;
$answerOption = QAAnswerOptions::where('id', $this->answer_option_id)->first();
$user_marking = '';
if($user){
@@ -31,7 +33,8 @@ class HelpMenuQuestionsAnswersResource extends JsonResource
'question_id' => $this->question_id,
'questionnaire' => new HelpMenuQuestionnaireSetsResource($this->question->questionnaire),
'question_text' => $question ? $question->question_text : null,
'free_text_answer' => $this->free_text_answer,
'free_text_answer' => $answerOption ? $answerOption->display_text : null,
'answer_value' => $answerOption ? $answerOption->value : null,
'source_system' => $user ? QASystemSourceType::getText(QASystemSourceType::IZYIM) : QASystemSourceType::getText($source->system),
'source_marking' => $user ? $user_marking : $source->marking,
'source_email' => $user ? $user->email : $source->email,
@@ -33,12 +33,14 @@ class WalletTransactionResource extends JsonResource
case TransactionType::PAYMENT:
$invoice = Transaction::where('payment_reference', $this->bill_no)->first();
if(!$invoice) {
Log::channel('paymentUnknownOrderLog')->info('ID: ' . $this->id);
$description = 'Payment for unknown invoice, please contact tech support.';
break;
}
$order = $invoice->owner->owner->owner;
if(!$order) {
Log::channel('paymentUnknownOrderLog')->info('ID: ' . $this->id);
$description = 'Payment for unknown order, please contact tech support.';
break;
}
+9
View File
@@ -46,4 +46,13 @@ class QAUserAnswerSelected extends AbstractModel implements Documentable
return $this->BelongsTo(QAQuestions::class, 'question_id', 'id');
}
/**
* @return BelongsTo
*/
public function answer(): BelongsTo
{
return $this->BelongsTo(QAAnswerOptions::class, 'answer_option_id', 'id');
}
}
+18
View File
@@ -106,6 +106,24 @@ return [
'emergency' => [
'path' => storage_path('logs/laravel.log'),
],
'paymentUnknownOrderLog' => [
'driver' => 'single',
'path' => storage_path('logs/paymentUnknownOrderLog.log'),
'level' => 'info',
],
'apiResponseTimeLog' => [
'driver' => 'single',
'path' => storage_path('logs/apiResponseTime.log'),
'level' => 'info',
],
'webResponseTimeLog' => [
'driver' => 'single',
'path' => storage_path('logs/webResponseTimeLog.log'),
'level' => 'info',
],
],
];
+5
View File
@@ -26,7 +26,12 @@ class DatabaseSeeder extends Seeder
// $this->call(QAQuestionsDemoSeeder::class); //DEMO POC
// $this->call(QAAnswerOptionsDemoSeeder::class); //DEMO POC
// 20230928 Set 1 to Set 3
// $this->call(QAQuestionsSeeder::class);
// $this->call(QAAnswerOptionsSeeder::class);
// 20231121 Set 4 to Set 6
// $this->call(QAQuestions2Seeder::class);
// $this->call(QAAnswerOptions2Seeder::class);
}
}
+395
View File
@@ -0,0 +1,395 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\QAAnswerOptions;
class QAAnswerOptions2Seeder extends Seeder
{
public function run()
{
// Set 1
// Option 1 for Question 10
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "Very Dissatisfied";
$answerOption->value = "1";
$answerOption->order = 1;
$answerOption->question_number = 10;
$answerOption->questionnaire_set_id = 4;
$answerOption->save();
// Option 2 for Question 10
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "Dissatisfied";
$answerOption->value = "2";
$answerOption->order = 2;
$answerOption->question_number = 10;
$answerOption->questionnaire_set_id = 4;
$answerOption->save();
// Option 3 for Question 10
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "Neutral";
$answerOption->value = "3";
$answerOption->order = 3;
$answerOption->question_number = 10;
$answerOption->questionnaire_set_id = 4;
$answerOption->save();
// Option 4 for Question 10
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "Satisfied";
$answerOption->value = "4";
$answerOption->order = 4;
$answerOption->question_number = 10;
$answerOption->questionnaire_set_id = 4;
$answerOption->save();
// Option 5 for Question 10
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "Very Satisfied";
$answerOption->value = "5";
$answerOption->order = 5;
$answerOption->question_number = 10;
$answerOption->questionnaire_set_id = 4;
$answerOption->save();
// Set 1
// Option 1 for Question 20
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "Yes";
$answerOption->value = "3";
$answerOption->order = 3;
$answerOption->question_number = 20;
$answerOption->questionnaire_set_id = 4;
$answerOption->save();
// Option 2 for Question 20
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "Partially";
$answerOption->value = "2";
$answerOption->order = 2;
$answerOption->question_number = 20;
$answerOption->questionnaire_set_id = 4;
$answerOption->save();
// Option 3 for Question 20
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "No";
$answerOption->value = "1";
$answerOption->order = 1;
$answerOption->question_number = 20;
$answerOption->questionnaire_set_id = 4;
$answerOption->save();
// Set 1
// Option 1 for Question 30
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "Very Clear";
$answerOption->value = "5";
$answerOption->order = 5;
$answerOption->question_number = 30;
$answerOption->questionnaire_set_id = 4;
$answerOption->save();
// Option 2 for Question 30
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "Clear";
$answerOption->value = "4";
$answerOption->order = 4;
$answerOption->question_number = 30;
$answerOption->questionnaire_set_id = 4;
$answerOption->save();
// Option 3 for Question 30
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "Neutral";
$answerOption->value = "3";
$answerOption->order = 3;
$answerOption->question_number = 30;
$answerOption->questionnaire_set_id = 4;
$answerOption->save();
// Option 4 for Question 30
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "Unclear";
$answerOption->value = "2";
$answerOption->order = 2;
$answerOption->question_number = 30;
$answerOption->questionnaire_set_id = 4;
$answerOption->save();
// Option 5 for Question 30
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "Very Unclear";
$answerOption->value = "1";
$answerOption->order = 1;
$answerOption->question_number = 30;
$answerOption->questionnaire_set_id = 4;
$answerOption->save();
// Set 2
// Option 1 for Question 10
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "Yes";
$answerOption->value = "3";
$answerOption->order = 3;
$answerOption->question_number = 10;
$answerOption->questionnaire_set_id = 5;
$answerOption->save();
// Option 2 for Question 10
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "Somewhat";
$answerOption->value = "2";
$answerOption->order = 2;
$answerOption->question_number = 10;
$answerOption->questionnaire_set_id = 5;
$answerOption->save();
// Option 3 for Question 10
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "No";
$answerOption->value = "1";
$answerOption->order = 1;
$answerOption->question_number = 10;
$answerOption->questionnaire_set_id = 5;
$answerOption->save();
// Set 2
// Option 1 for Question 20
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "Exceeded Expectations";
$answerOption->value = "3";
$answerOption->order = 3;
$answerOption->question_number = 20;
$answerOption->questionnaire_set_id = 5;
$answerOption->save();
// Option 2 for Question 20
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "Met Expectations";
$answerOption->value = "2";
$answerOption->order = 2;
$answerOption->question_number = 20;
$answerOption->questionnaire_set_id = 5;
$answerOption->save();
// Option 3 for Question 20
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "Below Expectations";
$answerOption->value = "1";
$answerOption->order = 1;
$answerOption->question_number = 20;
$answerOption->questionnaire_set_id = 5;
$answerOption->save();
// Set 2
// Option 1 for Question 30
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "Very Dissatisfied";
$answerOption->value = "1";
$answerOption->order = 1;
$answerOption->question_number = 30;
$answerOption->questionnaire_set_id = 5;
$answerOption->save();
// Option 2 for Question 30
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "Dissatisfied";
$answerOption->value = "2";
$answerOption->order = 2;
$answerOption->question_number = 30;
$answerOption->questionnaire_set_id = 5;
$answerOption->save();
// Option 3 for Question 30
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "Neutral";
$answerOption->value = "3";
$answerOption->order = 3;
$answerOption->question_number = 30;
$answerOption->questionnaire_set_id = 5;
$answerOption->save();
// Option 4 for Question 30
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "Satisfied";
$answerOption->value = "4";
$answerOption->order = 4;
$answerOption->question_number = 30;
$answerOption->questionnaire_set_id = 5;
$answerOption->save();
// Option 5 for Question 30
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "Very Satisfied";
$answerOption->value = "5";
$answerOption->order = 5;
$answerOption->question_number = 30;
$answerOption->questionnaire_set_id = 5;
$answerOption->save();
// Set 3
// Option 1 for Question 10
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "Immediately";
$answerOption->value = "5";
$answerOption->order = 5;
$answerOption->question_number = 10;
$answerOption->questionnaire_set_id = 6;
$answerOption->save();
// Option 2 for Question 10
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "Within a few hours";
$answerOption->value = "4";
$answerOption->order = 4;
$answerOption->question_number = 10;
$answerOption->questionnaire_set_id = 6;
$answerOption->save();
// Option 3 for Question 10
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "Within a day";
$answerOption->value = "3";
$answerOption->order = 3;
$answerOption->question_number = 10;
$answerOption->questionnaire_set_id = 6;
$answerOption->save();
// Option 4 for Question 10
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "More than a day";
$answerOption->value = "2";
$answerOption->order = 2;
$answerOption->question_number = 10;
$answerOption->questionnaire_set_id = 6;
$answerOption->save();
// Option 5 for Question 10
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "Never received a response";
$answerOption->value = "1";
$answerOption->order = 1;
$answerOption->question_number = 10;
$answerOption->questionnaire_set_id = 6;
$answerOption->save();
// Set 3
// Option 1 for Question 20
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "Very Clear";
$answerOption->value = "5";
$answerOption->order = 5;
$answerOption->question_number = 20;
$answerOption->questionnaire_set_id = 6;
$answerOption->save();
// Option 2 for Question 20
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "Clear";
$answerOption->value = "4";
$answerOption->order = 4;
$answerOption->question_number = 20;
$answerOption->questionnaire_set_id = 6;
$answerOption->save();
// Option 3 for Question 20
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "Neutral";
$answerOption->value = "3";
$answerOption->order = 3;
$answerOption->question_number = 20;
$answerOption->questionnaire_set_id = 6;
$answerOption->save();
// Option 4 for Question 20
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "Unclear";
$answerOption->value = "2";
$answerOption->order = 2;
$answerOption->question_number = 20;
$answerOption->questionnaire_set_id = 6;
$answerOption->save();
// Option 5 for Question 20
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "Very Unclear";
$answerOption->value = "1";
$answerOption->order = 1;
$answerOption->question_number = 20;
$answerOption->questionnaire_set_id = 6;
$answerOption->save();
// Set 3
// Option 1 for Question 30
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "Very Likely";
$answerOption->value = "5";
$answerOption->order = 5;
$answerOption->question_number = 30;
$answerOption->questionnaire_set_id = 6;
$answerOption->save();
// Option 2 for Question 30
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "Likely";
$answerOption->value = "4";
$answerOption->order = 4;
$answerOption->question_number = 30;
$answerOption->questionnaire_set_id = 6;
$answerOption->save();
// Option 3 for Question 30
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "Neutral";
$answerOption->value = "3";
$answerOption->order = 3;
$answerOption->question_number = 30;
$answerOption->questionnaire_set_id = 6;
$answerOption->save();
// Option 4 for Question 30
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "Unlikely";
$answerOption->value = "2";
$answerOption->order = 2;
$answerOption->question_number = 30;
$answerOption->questionnaire_set_id = 6;
$answerOption->save();
// Option 5 for Question 30
$answerOption = new QAAnswerOptions;
$answerOption->display_text = "Very Unlikely";
$answerOption->value = "1";
$answerOption->order = 1;
$answerOption->question_number = 30;
$answerOption->questionnaire_set_id = 6;
$answerOption->save();
}
}
+148
View File
@@ -0,0 +1,148 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\QAQuestionnaireSet;
use App\Models\QAQuestions;
use App\Classes\ValueObjects\Constants\QAType;
class QAQuestions2Seeder extends Seeder
{
public function run()
{
$questionnaireSets = [
[
'name' => 'Set 1',
'description' => 'Customer Support Satisfaction Survey',
'group' => 'feedback',
'version' => 2
],
[
'name' => 'Set 2',
'description' => 'First Order Experience Feedback',
'group' => 'feedback',
'version' => 2
],
[
'name' => 'Set 3',
'description' => 'Sales Inquiry Experience',
'group' => 'feedback',
'version' => 2
],
];
foreach ($questionnaireSets as $set) {
$questionnaireSet = QAQuestionnaireSet::create([
'name' => $set['name'],
'description' => $set['description'],
'group' => $set['group'],
'version' => $set['version'],
]);
$questions = [];
switch ($set['name']) {
case 'Set 1':
$questions = [
[
'question_number' => 10,
'question_text' => 'How satisfied are you with the time it took to receive a response?',
'question_type' => QAType::MULTIPLE_CHOICES,
'is_start' => true,
'is_end' => false,
],
[
'question_number' => 20,
'question_text' => 'Was your issue resolved during this interaction?',
'question_type' => QAType::MULTIPLE_CHOICES,
'is_start' => false,
'is_end' => false,
],
[
'question_number' => 30,
'question_text' => 'How clear and understandable was the communication from the support team?',
'question_type' => QAType::MULTIPLE_CHOICES,
'is_start' => false,
'is_end' => true,
]
];
break;
case 'Set 2':
$questions = [
[
'question_number' => 10,
'question_text' => 'Did you find what you were looking for without any issues?',
'question_type' => QAType::MULTIPLE_CHOICES,
'is_start' => true,
'is_end' => false,
],
[
'question_number' => 20,
'question_text' => 'Did the service meet your expectations?',
'question_type' => QAType::MULTIPLE_CHOICES,
'is_start' => false,
'is_end' => false,
],
[
'question_number' => 30,
'question_text' => 'How satisfied are you with the delivery time?',
'question_type' => QAType::MULTIPLE_CHOICES,
'is_start' => false,
'is_end' => true,
]
];
break;
case 'Set 3':
$questions = [
[
'question_number' => 10,
'question_text' => 'How quickly did our sales team respond to your inquiry?',
'question_type' => QAType::MULTIPLE_CHOICES,
'is_start' => true,
'is_end' => false,
],
[
'question_number' => 20,
'question_text' => 'Was the information provided by our sales team clear and easy to understand?',
'question_type' => QAType::MULTIPLE_CHOICES,
'is_start' => false,
'is_end' => false,
],
[
'question_number' => 30,
'question_text' => 'After interacting with our sales team, how likely are you to use our service?',
'question_type' => QAType::MULTIPLE_CHOICES,
'is_start' => false,
'is_end' => true,
]
];
break;
}
foreach ($questions as $key => $questionData) {
$question = new QAQuestions;
$question->question_number = $questionData['question_number'];
$question->question_text = $questionData['question_text'];
$question->question_type = $questionData['question_type'];
$question->questionnaire_set_id = $questionnaireSet->id;
if (isset($questionData['next_nested_question'])) {
$question->next_nested_question = $questionData['next_nested_question'];
}
if (isset($questionData['next_main_question'])) {
$question->next_main_question = $questionData['next_main_question'];
}
$question->is_start = $questionData['is_start'];
$question->is_end = $questionData['is_end'];
if (isset($questionData['end_text'])) {
$question->end_text = $questionData['end_text'];
}
$question->order = $key + 1;
$question->save();
}
}
}
}
@@ -1,7 +1,7 @@
<template>
<div class="row">
<div class="col">
<div v-if="$store.getters.isAdmin" class="btn btn-sm btn-danger pointer m-t-10 m-b-15 d-none" @click="submit(route('api.transaction.invoice.company.regenerate', company_module_id), 'post', section, true , true)">Regenerate Invoice</div>
<div v-if="$store.getters.isAdmin" class="btn btn-sm btn-danger pointer m-t-10 m-b-15" @click="submit(route('api.transaction.invoice.company.regenerate', company_module_id), 'post', section, true , true)">Regenerate Invoice</div>
<div class="row flex-nowrap">
<div class="col">
<div class="row tabsContainer">
@@ -7,7 +7,7 @@
<div class="col">
<div class="row align-items-center justify-content-center m-b-10">
<div class="col-auto p-r-10">
<h5 class="light">Welcome Abroad <span class="text-primary">{{$store.getters.getUserName}}</span>, we provide logistics services.</h5>
<h5 class="light">Welcome Aboard <span class="text-primary">{{$store.getters.getUserName}}</span>, we provide logistics services.</h5>
</div>
<div class="col-auto b-a b-thick b-primary padding-5">
<h5 class="light no-margin">Powered by technology, delivered by experts.</h5>
@@ -99,4 +99,4 @@
</div>
</div>
</div>
</template>
</template>
@@ -1,8 +1,10 @@
<template>
<div class="row parentContainer">
<div class="col-1">{{ item.questionnaire.version }}</div>
<div class="col-1">{{ item.questionnaire.description }}</div>
<div class="col-2"> <p>{{ item.question_text }}</p> </div>
<div class="col-1">{{ item.free_text_answer }}</div>
<div class="col-1">{{ item.answer_value }}</div>
<div class="col-1">{{ item.source_system }}</div>
<div class="col-1">{{ item.source_marking }}</div>
<div class="col-2">{{ item.source_email }}</div>
@@ -13,7 +13,7 @@
<div class="col-12 col-md-8">
<validation-wrapper-component selectable class="m-b-15" :validator="$v.parameters.question_set">
<label class="text-primary">Question Set</label>
<select-component :options="[{'id': 1, 'text': 'Customer Support Satisfaction Survey'}, {'id': 2, 'text': 'First Order Experience Feedback'}, {'id': 3, 'text': 'Sales Inquiry Experience'}]" v-model="parameters.question_set"></select-component>
<select-component :options="[{'id': 4, 'text': 'Customer Support Satisfaction Survey'}, {'id': 5, 'text': 'First Order Experience Feedback'}, {'id': 6, 'text': 'Sales Inquiry Experience'}]" v-model="parameters.question_set"></select-component>
</validation-wrapper-component>
</div>
@@ -84,6 +84,20 @@
<address-form-component :id="item.order.company_module.id" :section="section" :type=1></address-form-component>
</modal-component>
</div>
<div class="row" v-if="item.order.company_module.billingAddress">
<div class="col">
<div class="col-auto requestModal pointer" data-type="editBillingAddress">
<i class="fa fa-edit pointer fa-fw m-l-5"></i> Edit billing Address
</div>
<modal-component class="animate__animated animate__fast animate__fadeIn" size="extra-large" styleType="fill-in" type="editBillingAddress">
<div class="row">
<div class="col bg-white">
<address-form-component :id="item.order.company_module.id" :data="item.order.company_module.billingAddress" section="editBillingAddress"></address-form-component>
</div>
</div>
</modal-component>
</div>
</div>
<div v-if="!item.order.address.post_code_area">
<div class="btn btn-xs btn-primary pointer m-t-10 requestModal btn-block" data-type="defineLocation">Define Location</div>
<modal-component class="animate_animated animatefast animate_fadeIn" styleType="fill-in" type="defineLocation">
@@ -110,34 +124,6 @@
</modal-component>
</div>
</div>
<div class="row text-center parentContainer m-t-10" v-if="['Pending Invoice', 'Pending Approval'].includes(invoice_status)" >
<div class="col" v-if="item.order">
<div class="row" v-if="!item.order.company_module.billingAddress">
<div class="col">
<div>
<div class="btn btn-primary btn-xs pointer requestModal btn-block" data-type="billingAddressComponent">Add Billing Address</div>
<modal-component class="animate__animated animate__fast animate__fadeIn" size="extra-large" styleType="fill-in" type="billingAddressComponent">
<address-form-component :id="item.order.company_module.id" :section="section" :type=1></address-form-component>
</modal-component>
</div>
</div>
</div>
<div class="row" v-if="item.order.company_module.billingAddress">
<div class="col">
<div class="col-auto requestModal pointer" data-type="editBillingAddress">
<i class="fa fa-edit pointer fa-fw m-l-5"></i> Edit billing Address
</div>
<modal-component class="animate__animated animate__fast animate__fadeIn" size="extra-large" styleType="fill-in" type="editBillingAddress">
<div class="row">
<div class="col bg-white">
<address-form-component :id="item.order.company_module.id" :data="item.order.company_module.billingAddress" section="editBillingAddress"></address-form-component>
</div>
</div>
</modal-component>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@@ -64,6 +64,21 @@
</div>
</div>
<div class="col-auto p-l-0 p-r-0 d-flex justify-content-center align-items-center" v-if="$store.getters.isSuperAdmin">
<span class="d-inline-block m-r-15 text-primary bold text-underline pointer requestModal" data-type="regenerateInvoice">
<i class="fa fa-repeat"></i>
</span>
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="regenerateInvoice">
<general-confirmation-form-component
contentText="Are you sure you want to regenerate this Invoice?"
modalType="delete"
buttonText="Regenerate"
class="text-center"
:apiRoute="route('api.transaction.invoice.regenerate', item.id)"
apiMethod="post"
:section="section"
>
</general-confirmation-form-component>
</modal-component>
<span class="d-inline-block m-r-15 text-primary bold text-underline pointer requestModal" data-type="deleteInvoice">
<i class="fa fa-close"></i>
</span>
@@ -10,7 +10,7 @@
<div class="col">
<div class="row align-items-center justify-content-center m-b-10">
<div class="col-auto p-r-10">
<h5 class="light">Welcome Abroad, we provide logistics services.</h5>
<h5 class="light">Welcome Aboard, we provide logistics services.</h5>
</div>
<div class="col-auto b-a b-thick b-primary padding-5">
<h5 class="light no-margin">Powered by technology, delivered by experts.</h5>
@@ -310,4 +310,4 @@
</template>
</list-component>
</div>
</div>
</div>
+3 -1
View File
@@ -25,9 +25,11 @@
</button>
</anchor-link-component>
<div class="row align-items-center m-t-10 p-t-10 p-b-10 b-t b-grey muted all-caps fs-10">
<div class="col-1">Version</div>
<div class="col-1">Question Set</div>
<div class="col-2">Question Text</div>
<div class="col-1">Answer</div>
<div class="col-1">Answer Text</div>
<div class="col-1">Answer Value</div>
<div class="col-1">Source System</div>
<div class="col-1">Source Marking</div>
<div class="col-2">Source Email</div>
@@ -1,4 +1,5 @@
@extends('layouts.base_no_login')
@section('title', 'Share Your Feedback - CIEF Customer Service')
@section('inner_content')
<feedback-customer-section-component token="{{$token}}"></feedback-customer-section-component>
@endsection
@@ -42,10 +42,13 @@
</tr>
</thead>
<tbody>
@php
$packages = $invoice_transaction->owner->packages;
@php
$billable_packing_list = $invoice_transaction->owner->packingLists()->first();
$billable_packing_list = $billable_packing_list ? $billable_packing_list : $invoice_transaction->owner;
$packages = $billable_packing_list->packages;
$totalCBM = 0;
$totalQty = 0;
$order_reference = $invoice_transaction->owner->owner ? $invoice_transaction->owner->owner->reference : null;
@endphp
@foreach ($packages as $key => $package)
@php
@@ -57,7 +60,8 @@
@endphp
<tr>
<td width="5%" class="center top">{{ $key + 1 }}</td>
<td class="description">{!! $package->description !!}</td>
<!-- <td class="description">{!! $package->description !!}</td> -->
<td class="description">{!! $order_reference . '<br>' . $billable_packing_list->owner->reference !!}</td>
<td width="15%" class="center top" style="text-align: center">
{!! $measurement !!}
</td>
@@ -129,6 +129,8 @@ $grandSubTotal = 0;
@foreach ($invoice_transactions as $transaction)
<pagebreak />
@include('pages.pdfs.shipping_invoice_inner', ['invoice_transaction' => $transaction])
<pagebreak />
@include('pages.pdfs.packing_list_measurement', ['invoice_transaction' => $transaction])
@endforeach
+2 -2
View File
@@ -8,7 +8,7 @@
<meta http-equiv="content-type" content="text/html;charset=UTF-8"/>
<meta charset="utf-8"/>
<title>IZYIM Shipping</title>
<title>@yield('title', 'IZYIM Shipping')</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, shrink-to-fit=no"/>
<link rel="apple-touch-icon" sizes="57x57" href="{{asset('images/favicon/apple-icon-57x57.png')}}">
<link rel="apple-touch-icon" sizes="60x60" href="{{asset('images/favicon/apple-icon-60x60.png')}}">
@@ -28,4 +28,4 @@
<meta name="theme-color" content="#ffffff">
<meta name="csrf-token" content="{{ csrf_token() }}">
<link href="{{ asset('css/vendor.css') }}" rel="stylesheet" type="text/css"/>
<link href="{{ asset('css/site.css') }}" rel="stylesheet" type="text/css"/>
<link href="{{ asset('css/site.css') }}" rel="stylesheet" type="text/css"/>
+1
View File
@@ -9,6 +9,7 @@ Route::group(['prefix' => 'transactions', 'namespace' => 'Transactions', 'as' =>
Route::delete('/delete/{id}', 'DeleteTransactionController@delete')->name('delete');
Route::delete('/delete-payment/{id}', 'DeletePaymentTransactionController@delete')->name('payment.delete');
Route::put('{id}/status/update/{status}', 'UpdateTransactionStatusController@update')->where('status', 'approve|expire|reject')->name('update');
route::post('/{invoice_id}/regenerate', 'RegenerateSingleShippingInvoiceTransactionController@regenerate')->name('invoice.regenerate');
Route::get('wallet/list', 'ListWalletTransactionsController@list')->name('wallet.list');
+27 -13
View File
@@ -1,11 +1,8 @@
<?php
use App\Classes\Exceptions\InternalServerErrorException;
use App\Classes\Jobs\FetchContainersStatusUpdateFromVTPortalJob;
use App\Classes\Jobs\FetchDeliveryListFromVTPortalJob;
use App\Classes\Jobs\FetchLoadedContainersFromVTPortalJob;
use App\Classes\Jobs\FetchOrdersFromYDPortalJob;
use App\Classes\Jobs\FetchPackingListFromVTPortalJob;
use App\Classes\Jobs\FetchWarehouseReceiveListFromVTPortalJob;
use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject;
use App\Classes\Modules\Documents\Services\CreatesDocument;
@@ -16,12 +13,9 @@ use App\Classes\Modules\PackingLists\Processors\FetchContainersFromYdPortalProce
use App\Classes\Modules\PackingLists\Processors\FetchContainersUpdatesFromYdPortalProcessor;
use App\Classes\Modules\PackingLists\Processors\FetchDeliveryUpdatesFromYdPortalProcessor;
use App\Classes\Modules\PackingLists\Processors\FetchLoadedContainersFromVTPortalProcessor;
use App\Classes\Modules\PackingLists\Processors\FetchOrderListsFromYdPortalProcessor;
use App\Classes\Modules\PackingLists\Processors\FetchPackingListFromVTPortalProcessor;
use App\Classes\Modules\PackingLists\Processors\FetchPackingListsFromYdPortalProcessor;
use App\Classes\Modules\PackingLists\Services\ListsPackingLists;
use App\Classes\Modules\Transactions\Processors\ApproveShippingInvoiceTransactionProcessor;
use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionProcessor;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\BusinessType;
use App\Classes\ValueObjects\Constants\DocumentType;
@@ -30,7 +24,6 @@ use App\Classes\ValueObjects\Constants\PackageType;
use App\Classes\ValueObjects\Constants\PackingListType;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Http\Resources\CompanyResource;
use App\Models\CompanyConnection;
use App\Models\CompanyModule;
use App\Models\Document;
@@ -1227,10 +1220,31 @@ Route::get('/wallets/active', function(){
echo '</table>';
});
Route::get('/accident-approve-invoice', function(){
$invoices = Transaction::where('type', TransactionType::SHIPPING_INVOICE)->whereDate('updated_at', '2023-10-12')->get();
Route::get('fix-payment-status-updated-but-failed-update-invoice', function (UpdatesTransactionStatus $updatesTransactionStatus, UpdateDoFromVTPortalProcessor $updateDoFromVTPortalProcessor, UpdateDoFromYDPortalProcessor $updateDoFromYDPortalProcessor) {
$invoices = Transaction::where('type', TransactionType::SHIPPING_INVOICE)->whereIn('status', [2])
->whereHas('transactions', function ($query) {
$query->where('type', TransactionType::PAYMENT)
->whereIn('status', [2, 3]);
})->get();
foreach ($invoices as $invoice) {
$orderMarking = $invoice->owner->owner->reference;
echo '<a href="'.route('order.v2.show', $orderMarking).'" target="_blank">'.$orderMarking.'</a><br>';
echo "Fixing" . $invoice->owner->owner->reference . '<br>';
$totalPaidAmount = $invoice->transactions->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->sum('amount');
if (($invoice->amount - $totalPaidAmount) < 0.01) {
$updatesTransactionStatus->execute($invoice, ApprovalStatus::COMPLETED);
$packingList = $invoice->owner;
$packingList->status = ApprovalStatus::APPROVED;
$packingList->save();
if (app()->environment('production')) {
$updateDoFromVTPortalProcessor->execute($packingList);
$updateDoFromYDPortalProcessor->execute($packingList);
}
echo 'done fix ' . $invoice->owner->owner->reference . '<br>';
}
}
});
});