Compare commits

...

12 Commits

Author SHA1 Message Date
edmondlang 4faf3064d1 cief coins 2024-09-01 23:15:42 +08:00
edmondlang 7b89a8bff8 cief coins 2024-09-01 22:01:25 +08:00
edmondlang cc246046b5 cief coins 2024-09-01 21:55:37 +08:00
edmondlang f3d502ea9b cief coins 2024-09-01 21:19:41 +08:00
edmondlang 8f626230eb cief coins 2024-09-01 21:02:46 +08:00
edmondlang d7ef783443 cief coins 2024-09-01 20:49:46 +08:00
edmondlang b7c6c13bde fix payment-and-billing vue console error 2024-09-01 19:58:51 +08:00
edmondlang 01d666d92a fix payment-and-billing vue console error 2024-09-01 19:48:44 +08:00
Dillon Ngo b3973b52d1 Merge branch 'dillon/46.15-onhold-list-anomaly-fix' into 'master'
Data patch for a problem reported about an item not suppose to appear in ...

See merge request CIEFWorldwideSdnBhd/shipping-portal!236
2024-08-17 00:41:10 +00:00
Dillon Ngo 694876c31f Data patch for a problem reported about an item not suppose to appear in export/on-hold-packing-list 2024-08-17 08:39:19 +08:00
edmondlang 499782bbec update /export/aging-list, add 'is credit term customer' column 2024-08-04 00:39:15 +08:00
edmondlang f3eca3dd89 Export Group Transactions CSV 2024-08-03 23:04:47 +08:00
21 changed files with 493 additions and 138 deletions
@@ -0,0 +1,24 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class MarkingIn implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->whereHas('companyModules', function ($module) use ($value) {
$module->whereHas('connections', function ($connection) use ($value) {
$connection->whereIn('invitee_reference', $value);
});
});
}
}
@@ -0,0 +1,140 @@
<?php
namespace App\Classes\Modules\Billplzs\Processors;
use Illuminate\Http\Request;
use App\Models\Wallet;
use App\Models\Group;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\Modules\Transactions\Processors\CreatePaymentTransactionProcessor;
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;
use App\Classes\Modules\Orders\Processors\UpdateDoFromYDPortalProcessor;
use Illuminate\Support\Facades\Log;
//Date: 20240817
//This Processor is used for one time data patching with OneTimeTransactionFixBillplzFailedCallback.php
class CallbackBillplzDataPatchProcessor
{
/** @var UpdatesTransactionStatus */
private $updatesTransactionStatus;
/** @var UpdateDoFromVTPortalProcessor */
private $updateDoFromVTPortalProcessor;
/** @var UpdateDoFromYDPortalProcessor */
private $updateDoFromYDPortalProcessor;
/** @var UpdatesWalletBalance */
private $updatesWalletBalance;
/** @var CreatePaymentTransactionProcessor */
private $createPaymentTransactionProcessor;
/** @var ReleaseGoodsToCustomerProcessor */
private $releaseGoodsToCustomerProcessor;
/**
* CallbackBillplzDataPatchProcessor constructor.
* @param UpdatesTransactionStatus $updatesTransactionStatus
* @param UpdateDoFromVTPortalProcessor $updateDoFromVTPortalProcessor
* @param UpdateDoFromYDPortalProcessor $updateDoFromYDPortalProcessor
* @param UpdatesWalletBalance $updatesWalletBalance
* @param CreatePaymentTransactionProcessor $createPaymentTransactionProcessor
* @param ReleaseGoodsToCustomerProcessor $releaseGoodsToCustomerProcessor
*/
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->releaseGoodsToCustomerProcessor = $releaseGoodsToCustomerProcessor;
}
/**
* @param Request $request
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute($transaction, $status)
{
$invoice = $transaction->owner;
$packingList = $invoice->owner;
$proceed = $this->checkForGroupPayment($transaction);
if(!$proceed) return false;
$this->updatesTransactionStatus->execute($transaction, $status);
Log::info('CallbackBillplzDataPatchProcessor 1');
// check if is wallet top up
if ($transaction->owner instanceof Wallet && $status === ApprovalStatus::APPROVED) {
Log::info('CallbackBillplzDataPatchProcessor 2');
$this->updatesWalletBalance->execute($transaction->owner, $transaction->amount);
$group = Group::where('reference', $transaction->payment_reference)->first();
// check if is group payment
if ($group) {
foreach ($group->groupTransactions as $groupTransaction) {
$invoice = $groupTransaction->transaction;
Log::info('CallbackBillplzDataPatchProcessor 3: '.json_encode($invoice));
//if($invoice->status !== ApprovalStatus::COMPLETED){
// $paymentTransaction = $this->createPaymentTransactionProcessor->execute($invoice, PaymentMethodType::WALLET, null, false);
// if($paymentTransaction && $paymentTransaction->status == ApprovalStatus::APPROVED){
$pL = $invoice->owner;
$this->releaseGoodsToCustomerProcessor->execute($pL, $invoice, true);
//}
//}
}
$group->status = $status;
$group->save();
}
}
if (!$transaction->owner instanceof Wallet) {
Log::info('CallbackBillplzDataPatchProcessor 3');
$this->releaseGoodsToCustomerProcessor->execute($packingList, $invoice);
}
return true;
}
private function checkForGroupPayment($transaction){
//This check is targetting group payment that expired and soft deleted
//command:check-storage-invoices must already run for this part of the code to work properly
$group = Group::withTrashed()->where('reference', $transaction->payment_reference)->first();
if ($group) {
$totalAmountToBePaid = 0;
$actualAmountPaid = $transaction->amount;
foreach ($group->groupTransactions as $groupTransaction) {
$invoice = $groupTransaction->transaction;
if($invoice->status !== ApprovalStatus::COMPLETED){
$totalAmountToBePaid += $invoice->amount;
}
}
if(($totalAmountToBePaid - $actualAmountPaid) < 0.01){
}
else{
Log::channel('storage_invoices')->info('Total amount from current transaction: '.$totalAmountToBePaid); //cief todo: to be removed
Log::channel('storage_invoices')->info('Total amount from paid transaction: '.$transaction->amount); //cief todo: to be removed
return false;
}
}
return true;
}
}
@@ -36,7 +36,7 @@ class CallbackBillplzProcessor
private $releaseGoodsToCustomerProcessor;
/**
* CreateUserProcessor constructor.
* CallbackBillplzProcessor constructor.
* @param UpdatesTransactionStatus $updatesTransactionStatus
* @param UpdateDoFromVTPortalProcessor $updateDoFromVTPortalProcessor
* @param UpdateDoFromYDPortalProcessor $updateDoFromYDPortalProcessor
@@ -39,6 +39,7 @@ class ExportsAgingList implements WithHeadings, WithHeadingRow, WithMapping, Sho
'Invoice Date',
'Days',
'Amount',
'Credit Term Customer',
];
}
@@ -55,9 +56,16 @@ class ExportsAgingList implements WithHeadings, WithHeadingRow, WithMapping, Sho
$invDate = 'n/a';
$invNo = 'n/a';
$days = 'n/a';
$isCreditTermCustomer = false;
if ($list->owner instanceof Order) {
$inviterPivotInviteeReference = $list->owner->companyModule->inviters()->withPivot('invitee_reference')->first();
$companyModule = $list->owner->companyModule;
$segment = $companyModule->connections()->first()->segments()->where('name', 'Credit Term Customer')->first();
if ($segment) {
$isCreditTermCustomer = true;
}
if ($inviterPivotInviteeReference) {
$marking = $inviterPivotInviteeReference->pivot->invitee_reference;
@@ -87,6 +95,7 @@ class ExportsAgingList implements WithHeadings, WithHeadingRow, WithMapping, Sho
$invDate,
$days,
$amt,
$isCreditTermCustomer ? 'TRUE' : 'FALSE',
];
}
@@ -0,0 +1,108 @@
<?php
namespace App\Classes\Modules\Exports\Services;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Models\Group;
use App\Models\Transaction;
use Maatwebsite\Excel\Concerns\Exportable;
use Maatwebsite\Excel\Concerns\FromQuery;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
use Illuminate\Http\Request;
use Carbon\Carbon;
class ExportsGroupTransactions implements
FromQuery,
WithHeadings,
WithHeadingRow,
WithMapping,
ShouldAutoSize
{
use Exportable;
private $request;
public function __construct(Request $request)
{
$this->request = $request;
}
public function headings(): array
{
return [
'DocNo',
'DocDate',
'PaymentDate',
'DebtorCode',
'Ref',
'ShipInfo',
'AccNo',
'DetailDescription',
'FurtherDescription',
'ProjNo',
'DeptNo',
'Qty',
'UnitPrice',
'TaxType',
'TaxableAmt',
'TaxRate'
];
}
public function query()
{
$start_date = $this->parseDate($this->request->input('startDate'));
$end_date = $this->parseDate($this->request->input('endDate'));
return Group::when($start_date && $end_date, function ($query) use ($start_date, $end_date) {
$query->whereBetween('created_at', [
$start_date->startOfDay(),
$end_date->endOfDay()
]);
})
->when($start_date && !$end_date, function ($query) use ($start_date) {
$query->where('created_at', '>=', $start_date->startOfDay());
})
->when(!$start_date && $end_date, function ($query) use ($end_date) {
$query->where('created_at', '<=', $end_date->endOfDay());
});
}
private function parseDate($date)
{
return $date ? Carbon::parse($date)->startOfDay() : null;
}
public function map($transaction): array
{
$company = $transaction->receiverCompany;
return [
'<<New>>', //'DocNo',
'', //'DocDate',
$transaction->created_at->format('m/d/Y H:m'), //'PaymentDate',
$company->debtor, //'DebtorCode',
$company->referece, //'Ref',
$company->referece, //'ShipInfo',
'500-0000', //'AccNo',
'X1 Freight Service Charge', //'DetailDescription',
'FurtherDescription', //'FurtherDescription',
'M3', //'ProjNo',
'CIEF', //'DeptNo',
'', //'Qty',
'', //'UnitPrice',
'', //'TaxType',
floatval($transaction->tax) > 0 ? number_format($transaction->tax, 2) : '0.00', //'TaxableAmt',
'', //'TaxRate'
];
}
private function getTaxType($tax_percentage)
{
return floatval($tax_percentage) > 0 ? 'SV-6' : '';
}
}
@@ -21,6 +21,7 @@ use App\Classes\Modules\Orders\Processors\UpdateDoFromVTPortalProcessor;
use App\Classes\Modules\Orders\Processors\UpdateDoFromYDPortalProcessor;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use Illuminate\Support\Facades\Log;
use App\Classes\Modules\Wallets\Processors\CreditWalletProcessor;
class CreatePaymentTransactionProcessor
{
@@ -49,6 +50,9 @@ class CreatePaymentTransactionProcessor
/** @var UpdatesTransactionStatus */
private $updatesTransactionStatus ;
/** @var CreditWalletProcessor */
private $creditWalletProcessor ;
/**
* @param FetchesTransaction $fetchesTransaction,
* @param GeneratesTransactionBillNumber $generatesTransactionBillNumber,
@@ -60,6 +64,7 @@ class CreatePaymentTransactionProcessor
* @param UpdateDoFromVTPortalProcessor $updateDoFromVTPortalProcessor
* @param UpdateDoFromYDPortalProcessor $updateDoFromYDPortalProcessor
* @param UpdatesTransactionStatus $updatesTransactionStatus
* @param CreditWalletProcessor $creditWalletProcessor
*/
public function __construct(
GeneratesTransactionBillNumber $generatesTransactionBillNumber,
@@ -69,6 +74,7 @@ class CreatePaymentTransactionProcessor
UpdatesWalletBalance $updatesWalletBalance,
UpdateDoFromVTPortalProcessor $updateDoFromVTPortalProcessor,
UpdateDoFromYDPortalProcessor $updateDoFromYDPortalProcessor,
CreditWalletProcessor $creditWalletProcessor,
UpdatesTransactionStatus $updatesTransactionStatus
)
{
@@ -79,6 +85,7 @@ class CreatePaymentTransactionProcessor
$this->updatesWalletBalance = $updatesWalletBalance;
$this->updateDoFromVTPortalProcessor = $updateDoFromVTPortalProcessor;
$this->updateDoFromYDPortalProcessor = $updateDoFromYDPortalProcessor;
$this->creditWalletProcessor = $creditWalletProcessor;
$this->updatesTransactionStatus = $updatesTransactionStatus;
}
@@ -174,6 +181,11 @@ class CreatePaymentTransactionProcessor
$payment_transaction = $this->createsPaymentTransaction->execute($invoice, $object);
// cief coins
if ($approvalStatus == ApprovalStatus::APPROVED) {
$wallet = $this->creditWalletProcessor->execute($company_module, transactionType::CIEF_COINS_CREDIT, $amount, 'Cief Coins Credit', 3); // TODO-cief-coins: pls confirm the reference
}
return $payment_transaction;
}
}
@@ -44,24 +44,33 @@ class ReleaseGoodsToCustomerProcessor
/**
* @param $packingList
* @param $invoice
* @param $processCompletedInvoices
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute($packingList, $invoice = null)
public function execute($packingList, $invoice = null, $processCompletedInvoices = false)
{
$result = false;
$totalInvoicesAmountPaid = 0.00;
$totalInvoicesAmount = 0.00;
$invoiceTransactions = $packingList->transactions()->where('status', [ApprovalStatus::APPROVED])->whereIn('type', [TransactionType::SHIPPING_INVOICE, TransactionType::STORAGE_INVOICE])->get();
if($processCompletedInvoices){
//processCompletedInvoices, for manual processing of invoices, e.g. incomplete payment gateway finish with storage invoice
$invoiceTransactions = $packingList->transactions()->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->whereIn('type', [TransactionType::SHIPPING_INVOICE, TransactionType::STORAGE_INVOICE])->get();
}
else{
$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
//Part 1: Process each single invoice type and get the total of all invoices (STORAGE + SHIPPING)
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){
Log::channel('storage_invoices')->info('ReleaseGoodsToCustomerProcessor updatesTransactionStatus');
$this->updatesTransactionStatus->execute($invoice, ApprovalStatus::COMPLETED);
if($invoice->type == TransactionType::STORAGE_INVOICE){
//cief todo: remove the following if block
if($invoice->type === TransactionType::STORAGE_INVOICE){
Log::channel('storage_invoices')->info('ReleaseGoodsToCustomerProcessor createStorageInvoiceDocTransactionProcessor');
$this->createStorageInvoiceDocTransactionProcessor->execute($packingList);
}
}
@@ -3,16 +3,12 @@
namespace App\Classes\Modules\Wallets\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Wallets\DataTransferObjects\WalletObject;
use App\Classes\Modules\Wallets\Services\ListsWallet;
use App\Classes\Modules\Wallets\Standards\Rules\CanListWallet;
use App\Http\Resources\WalletResource;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use App\Classes\Modules\Wallets\Services\ListsWallets;
class ListWalletLogic extends AbstractControllerLogic
{
@@ -26,8 +22,8 @@ class ListWalletLogic extends AbstractControllerLogic
];
}
/** @var ListWallet */
private $listsWallet;
/** @var ListsWallets */
private $listsWallets;
/** @var CanCreateCompanyWallet */
private $canListWallet;
@@ -38,10 +34,10 @@ class ListWalletLogic extends AbstractControllerLogic
* @param GeneratesWalletCode $generatesWalletCode
* @param CanCreateCompanyWallet $canCreateCompanyWallet
*/
public function __construct(CanListWallet $canListWallet, ListsWallet $listsWallet)
public function __construct(CanListWallet $canListWallet, ListsWallets $listsWallets)
{
$this->canListWallet = $canListWallet;
$this->listsWallet = $listsWallet;
$this->listsWallets = $listsWallets;
}
/**
@@ -53,7 +49,7 @@ class ListWalletLogic extends AbstractControllerLogic
{
//$this->canListWallet->passes();
$query = $this->listsWallet->execute($this->listsWallet->deserializeFilters($request->input('filters')));
$query = $this->listsWallets->execute($this->listsWallets->deserializeFilters($request->input('filters')));
return $this->collectionResponse(WalletResource::collection($query));
}
@@ -79,19 +79,40 @@ class CreditWalletProcessor
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(CompanyModule $companyModule, int $transactionType, float $amount, string $reference)
public function execute(CompanyModule $companyModule, int $transactionType, float $amount, string $reference, ?int $currencyId = 1)
{
if (!$companyModule->wallets()->first()) {
$object = new WalletObject($companyModule->id, 1, $this->generatesWalletCode->execute());
/** @var Wallet $wallet */
$wallet = $companyModule->wallets()->where('currency_id', $currencyId)->first();
if (!$wallet) {
$object = new WalletObject($companyModule->id, $currencyId, $this->generatesWalletCode->execute());
$this->createsWallet->execute($object, $companyModule);
$wallet = $companyModule->wallets()->where('currency_id', $currencyId)->first();
}
/** @var Wallet $wallet */
$wallet = $companyModule->wallets()->first();
$billNumberPrefix = null;
$transaction_object_transaction_type = $transactionType;
switch ($transactionType) {
case TransactionType::PAYMENT:
$billNumberPrefix = 'DEBIT-NOTE-';
$transaction_object_transaction_type = TransactionType::DEBIT_NOTE;
break;
case TransactionType::CIEF_COINS_CREDIT:
$billNumberPrefix = 'COINS-CREDIT-'; // TODO-cief-coins: pls confirm the prefix
break;
case TransactionType::CIEF_COINS_DEBIT:
$billNumberPrefix = 'COINS-DEBIT-'; // TODO-cief-coins: pls confirm the prefix
break;
default:
$billNumberPrefix = 'CREDIT-NOTE-';
$transaction_object_transaction_type = TransactionType::CREDIT_NOTE;
break;
}
$billNumber = $this->generatesTransactionBillNumber->execute($transactionType === 2 ? 'DEBIT-NOTE-' : 'CREDIT-NOTE-');
$billNumber = $this->generatesTransactionBillNumber->execute($billNumberPrefix);
$transaction_object = new TransactionObject($billNumber, $transaction_object_transaction_type, 1, $wallet->owner->id, 1, PaymentMethodType::CASH, $amount, $amount, 1, 1, 1, 0, 0, null, ApprovalStatus::APPROVED, [], $reference);
$transaction_object = new TransactionObject($billNumber, $transactionType === 2 ? TransactionType::DEBIT_NOTE : TransactionType::CREDIT_NOTE, 1, $wallet->owner->id, 1, PaymentMethodType::CASH, $amount, $amount, 1, 1, 1, 0, 0, null, ApprovalStatus::APPROVED, [], $reference);
$transaction = $this->createsTransactionableTransaction->execute($wallet, $transaction_object);
$this->updatesWalletBalance->execute($wallet, $transaction->amount);
@@ -2,28 +2,31 @@
namespace App\Classes\Modules\Wallets\Services;
use Illuminate\Database\Eloquent\Builder;
use App\Classes\General\Eloquent\AbstractListRecord;
use Illuminate\Database\Eloquent\Builder;
use App\Models\Wallet;
class ListsWallet extends AbstractListRecord
class ListsWallets extends AbstractListRecord
{
/** @var Booking */
/** @var Wallet */
private $repository;
/**
* ListsBookings constructor.
* @param Booking $repository
* Wallet constructor.
* @param Wallet $repository
*/
public function __construct(Wallet $repository)
{
$this->repository = $repository;
}
/**
* @return Builder
*/
public function getRepository(): Builder
function getRepository(): Builder
{
return $this->repository->newQuery();
}
@@ -27,11 +27,15 @@ class UpdatesWalletBalance extends AbstractUpdateRecord
foreach ($model->transactions as $transaction) {
if (!in_array((int) $transaction->status, [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])) continue;
if ((int) $transaction->type === TransactionType::TOP_UP) $topups += (float) $transaction->amount;
if ((int) $transaction->type === TransactionType::GROUP_PAYMENT) $topups += (float) $transaction->amount;
if ((int) $transaction->type === TransactionType::CREDIT_NOTE) $credit += (float) $transaction->amount;
if ((int) $transaction->type === TransactionType::PAYMENT) $payments += (float) $transaction->amount;
if ((int) $transaction->type === TransactionType::DEBIT_NOTE) $debit += (float) $transaction->amount;
if ((int) $transaction->type === TransactionType::TOP_UP) $topups += (float) $transaction->amount;
if ((int) $transaction->type === TransactionType::GROUP_PAYMENT) $topups += (float) $transaction->amount;
if ((int) $transaction->type === TransactionType::CREDIT_NOTE) $credit += (float) $transaction->amount;
if ((int) $transaction->type === TransactionType::PAYMENT) $payments += (float) $transaction->amount;
if ((int) $transaction->type === TransactionType::DEBIT_NOTE) $debit += (float) $transaction->amount;
// cief coins
if ((int) $transaction->type === TransactionType::CIEF_COINS_CREDIT) $credit += (float) $transaction->amount;
if ((int) $transaction->type === TransactionType::CIEF_COINS_DEBIT) $debit += (float) $transaction->amount;
}
$auditBalance = ($topups + $credit) - ($payments + $debit);
@@ -42,4 +42,9 @@ final class TransactionType {
];
public const STORAGE_INVOICE = 16;
public const CIEF_COINS_DEBIT = 17;
public const CIEF_COINS_CREDIT = 18;
}
@@ -4,6 +4,7 @@ namespace App\Console\Commands;
use App\Classes\Modules\Billplzs\Processors\CallbackBillplzProcessor;
use App\Classes\Modules\Billplzs\Processors\CallbackBillplzDataPatchProcessor;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Models\Transaction;
use Carbon\Carbon;
@@ -32,15 +33,19 @@ class OneTimeTransactionFixBillplzFailedCallback extends Command
/** @var CallbackBillplzProcessor */
private $callbackBillplzProcessor;
/** @var CallbackBillplzDataPatchProcessor */
private $callbackBillplzDataPatchProcessor;
/**
* Create a new command instance.
*
* @return void
*/
public function __construct(CallbackBillplzProcessor $callbackBillplzProcessor)
public function __construct(CallbackBillplzProcessor $callbackBillplzProcessor, CallbackBillplzDataPatchProcessor $callbackBillplzDataPatchProcessor)
{
parent::__construct();
$this->callbackBillplzProcessor = $callbackBillplzProcessor;
$this->callbackBillplzDataPatchProcessor = $callbackBillplzDataPatchProcessor;
}
/**
@@ -55,20 +60,22 @@ class OneTimeTransactionFixBillplzFailedCallback extends Command
$this->outputArray = [];
$start = new Carbon();
//Transaction fix with this one time fix command: 15205, 16803
//Transaction fix with this one time fix command: 15205, 16803, 17310
//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.');
$transaction = Transaction::whereIn('id', [17310])->first();
$this->info(Carbon::now() . ' : One time fix failled callback from billplz for transaction with id 17310 cron started.');
if($transaction && $transaction->id == 16803){
if($transaction && $transaction->id == 17310){
$this->info(Carbon::now() . ' : 17310.');
$status = ApprovalStatus::APPROVED;
$this->callbackBillplzProcessor->execute($transaction, $status);
// $this->callbackBillplzProcessor->execute($transaction, $status);
$this->callbackBillplzDataPatchProcessor->execute($transaction, $status);
}
$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 16803 cron ended. ElapsedTime: ' . $elapsedTime);
$this->info(Carbon::now() . ' : One time fix failled callback from billplz for transaction with id 17310 cron ended. ElapsedTime: ' . $elapsedTime);
}
}
@@ -5,6 +5,7 @@ namespace App\Http\Controllers\Exports;
use App\Classes\Modules\Exports\Services\ExportsCustomersOrderLatestDate;
use App\Classes\Modules\Exports\Services\ExportsCustomerTotalOrderByYear;
use App\Classes\Modules\Exports\Services\ExportsGroupTransactions;
use App\Classes\Modules\Exports\Services\ExportsPaymentTransactions;
use App\Models\User;
use Illuminate\Http\Request;
@@ -33,6 +34,13 @@ class ExportCustomersToExcelController
return $response;
}
public function groupTransaction(Request $request){
$exportsTransactions = new ExportsGroupTransactions($request);
$response = $exportsTransactions->download('group-transactions.xls', Excel::XLS, ['Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']);
ob_end_clean();
return $response;
}
public function totalOrders(Request $request){
$exportsTotalOrders = new ExportsCustomerTotalOrderByYear($request);
$response = $exportsTotalOrders->download('total-orders-' . $request->route('year') . '.xls', Excel::XLS, ['Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']);
@@ -26,11 +26,11 @@
</div>
<div class="col" v-if="['customerPaidInvoiceComponent', 'customerPaidGroupInvoiceComponent'].includes(section)">
<p class="no-margin fs-10 all-caps">Payment Date</p>
<div>{{ item.payment_history[item.payment_history.length-1].created_at }}</div>
<div>{{ item.payment_history && item.payment_history.length > 0 ? item.payment_history[item.payment_history.length - 1].created_at : '-' }}</div>
</div>
<div class="col" v-if="['customerPaidInvoiceComponent', 'customerPaidGroupInvoiceComponent'].includes(section)">
<p class="no-margin fs-10 all-caps">Bill Number</p>
<div>{{ item.payment_history[item.payment_history.length-1].payment_reference }}</div>
<div>{{ item.payment_history && item.payment_history.length > 0 ? item.payment_history[item.payment_history.length - 1].payment_reference : '-' }}</div>
</div>
<div class="col-auto">
<div v-if="item.documents.length">
@@ -69,6 +69,9 @@ export default {
case 'walletsReportSection':
apiRoute = route('walletTransactions.export');
break;
case 'groupTransactionSection':
apiRoute = route('groupTransaction.export');
break;
}
window.open(apiRoute + '?startDate=' + this.parameters.startDate + '&endDate=' + this.parameters.endDate, '_blank');
},
@@ -155,7 +155,7 @@
export default {
props: {
sumAmount: {
type: String,
type: Number,
required: true
},
section:{
@@ -1,119 +1,94 @@
<template>
<div class="w-100">
<validation-wrapper-component
selectable
:validator="$v.parameters.id"
>
<label>Segment</label>
<selectable-component
:endpoint="
route('api.segment.list')
"
:section="section"
:value="3"
valueColumn="id"
:labelColumn="['name']"
v-model="parameters.id"
@input="onSelect"
></selectable-component>
</validation-wrapper-component>
<list-component
v-if="parameters.id"
class="mt-4"
:key="parameters.id"
:section="`segments_${parameters.id}`"
:endpoint="route('api.company.list')"
:options="{
company_segments_in: [parameters.id],
// with_total_payments: true,
// recency: '2022-02-15',
// frequency: 15,
// business_type: 2,
// with_bookings: true,
// order_by: { column: 'total_payments', DESC: true },
}"
>
<template slot="list" slot-scope="{ data }">
<company-component :data="data"></company-component>
</template>
</list-component>
<div v-else>
<div
class="row align-items-center justify-content-center p-t-50 p-b-50"
style=""
>
<div class="col-10">
<div
class="row align-items-center justify-content-center hint-text"
>
<div class="col-4 hint-text">
<img
src="/images/2829248.png"
class="w-100 hint-text"
/>
</div>
<div class="row m-b-20" @keyup.enter="downloadReport()">
<div class="col">
<div class="row m-l-0 m-r-0">
<div class="col p-l-0 p-r-0">
<validation-wrapper-component selectable :validator="$v.parameters.id">
<label>Segment</label>
<selectable-component :endpoint="route('api.segment.list')" :section="section" :value="3"
valueColumn="id" :labelColumn="['name']" v-model="parameters.id"
@input="onSelect"></selectable-component>
</validation-wrapper-component>
</div>
<div class="row text-center">
<div class="col">
<div class="row m-t-20">
<div class="col">
<p
class="all-caps no-margin fs-11"
style="letter-spacing: 2px"
>
Please Select a Segment
</p>
</div>
</div>
<div class="col p-l-0 p-r-0">
<validation-wrapper-component :validator="$v.parameters.company_marking">
<label class="text-primary">Company Marking</label>
<input type="text" class="form-control fs-12" v-model.trim="parameters.company_marking">
</validation-wrapper-component>
</div>
<div class="col-auto p-l-0 p-r-0">
<div class="btn btn-lg btn-primary fs-11 w-100 h-100 d-flex justify-content-center align-items-center"
@click="downloadReport()">
<span>
Search
</span>
</div>
</div>
</div>
</div>
</div>
<list-component class="mt-4" :key="parameters.vueKey" section="listSegmentSection"
:endpoint="route('api.company.list')" :options="options">
<template #list="{ data }">
<company-component :data="data"></company-component>
</template>
</list-component>
</div>
</template>
<script>
import componentHandler from "../../../general/mixins/componentHandler";
export default {
props: {
section: {
type: String,
required: true,
},
type: {
type: Number,
required: true,
},
id: {
type: Number,
default: null,
}
section: String,
type: Number,
id: { type: Number, default: null },
},
data() {
return {
parameters: {
id: null,
},
company_marking: null,
vueKey: 1,
}
};
},
validations: {
parameters: {
id: {},
company_marking: {},
}
},
computed: {
options() {
const options = {
company_segments_in: [this.parameters.id]
};
if (this.parameters.company_marking) {
options.marking_in = [this.parameters.company_marking];
}
return options;
},
},
methods: {
onSelect(val) {
this.parameters.id = val
this.parameters.id = val;
},
},
created(){
const id = new URL(location.href).searchParams.get('id')
if(id){
this.parameters.id = id
}
downloadReport() {
this.parameters.vueKey++;
console.log(this.parameters.vueKey);
},
},
created() {
const id = new URL(location.href).searchParams.get('id');
if (id) this.parameters.id = id;
},
mixins: [componentHandler],
};
</script>
</script>
@@ -3,7 +3,7 @@
<div class="col">
<loading-component style="height: 300px; top: 0;" key="1" color="success" v-show="isLoading" ></loading-component>
<!-- <div class="row parentContainer" v-if="item.status === 2"> -->
<div class="row parentContainer" v-if="!isLoading">
<div class="row parentContainer" v-if="!isLoading && wallet.cashWallet">
<div class="col">
<div class="row" v-if="!reload && section !== 'customerPaidInvoiceComponent'">
<div class="col">
@@ -11,7 +11,7 @@
<div class="row align-items-end">
<div class="col-auto">
<div class="text-primary-lighter fs-10 text-uppercase">Wallet Balance</div>
<h5 class="text-white no-margin bold">MYR {{ wallet ? (Math.round((wallet.amount + Number.EPSILON) * 100) / 100).toFixed(2) : '0.00'}}</h5>
<h5 class="text-white no-margin bold">MYR {{ wallet.cashWallet ? (Math.round((wallet.cashWallet.amount + Number.EPSILON) * 100) / 100).toFixed(2) : '0.00'}}</h5>
</div>
</div>
<div class="row m-t-10 d-flex align-items-center">
@@ -19,9 +19,9 @@
<div class="btn btn-xs p-l-15 p-r-20 b-rad-none font-heading btn-rounded bg-white" @click="reload = true"><i class="fa fa-plus fs-8 m-r-5"></i> Reload</div>
</div>
<div class="col-auto p-l-0" v-else="$store.getters.isSuperAdmin"></div>
<div class="col-auto p-l-0" v-if="!mini && wallet && section!=='CompanyWalletTransactionSection'">
<!-- <a class="text-white fs-10" :href="route('wallet.details', wallet.company_module_marking)" target="_blank">Transaction History<i class="fa fa-angle-right p-l-5"></i></a> -->
<a class="text-white fs-10" :href="route('wallet.details', wallet.company_module_marking)">Transaction History<i class="fa fa-angle-right p-l-5"></i></a>
<div class="col-auto p-l-0" v-if="!mini && wallet.cashWallet && section!=='CompanyWalletTransactionSection'">
<!-- <a class="text-white fs-10" :href="route('wallet.details', wallet.cashWallet.company_module_marking)" target="_blank">Transaction History<i class="fa fa-angle-right p-l-5"></i></a> -->
<a class="text-white fs-10" :href="route('wallet.details', wallet.cashWallet.company_module_marking)">Transaction History<i class="fa fa-angle-right p-l-5"></i></a>
</div>
</div>
</div>
@@ -34,7 +34,25 @@
<label class="fs-10 text-white m-b-0 text-uppercase cursor" @click="reload = false"><i class="fa fa-angle-left p-r-15"></i>Top Up Wallet</label>
</div>
</div>
<wallet-top-up-form-component :company_module_id="company_module_id" :amount="(!wallet ? amount : (Math.round((((amount - wallet.amount) < '0.00' ? '0.00' : (amount - wallet.amount)) + Number.EPSILON) * 100) / 100).toFixed(2))" :creditable="creditable"></wallet-top-up-form-component>
<wallet-top-up-form-component :company_module_id="company_module_id" :amount="(!wallet.cashWallet ? amount : (Math.round((((amount - wallet.cashWallet.amount) < '0.00' ? '0.00' : (amount - wallet.cashWallet.amount)) + Number.EPSILON) * 100) / 100).toFixed(2))" :creditable="creditable"></wallet-top-up-form-component>
</div>
</div>
</div>
</div>
<br>
<div class="row parentContainer" v-if="!isLoading && wallet.coinWallet">
<div class="col">
<div class="row" v-if="!reload && section !== 'customerPaidInvoiceComponent'">
<div class="col">
<div style="background-color:#1fa67a !important" :class="[{'padding-25': !mini}, {'padding-15': mini}]">
<div class="row align-items-end">
<div class="col-auto">
<div class="text-primary-lighter fs-10 text-uppercase">Coins Balance</div>
<h5 class="text-white no-margin bold"><i class="fa fa-creative-commons m-r-5"></i> {{ wallet.coinWallet ? wallet.coinWallet.amount : '0.00'}}</h5>
</div>
</div>
</div>
</div>
</div>
</div>
@@ -99,12 +117,18 @@
methods: {
fetchCompany(){
this.isLoading = true;
this.submit(route('api.wallet.company_module.show', this.company_module_id), 'get', this.section, false, false);
var filters = {'owner_id': this.company_module_id};
this.submit(route('api.wallet.list') + '?filters=' + JSON.stringify(filters), 'get', this.section, false, false);
// this.submit(route('api.wallet.company_module.show', this.company_module_id), 'get', this.section, false, false);
},
successHandler(response){
this.$store.dispatch('completeList', {'name': this.section, 'data': []});
this.isLoading = false;
this.wallet = response.payload.data;
this.wallet = response.payload.data.reduce((acc, item) => {
if (item.currency_id === 1) acc.cashWallet = item;
else if (item.currency_id === 3) acc.coinWallet = item;
return acc;
}, {});
},
errorHandler(error){
this.isLoading = false;
@@ -131,6 +131,12 @@
</div>
</div>
</div>
<div class="row m-t-15 m-b-15">
<div class="col-8 p-l-0">
<small class="all-caps muted">Export Group Transactions CSV</small>
<download-billing-with-dates-component section="groupTransactionSection"></download-billing-with-dates-component>
</div>
</div>
<div class="row">
<div class="col">
<admin-payments-billing-section-component></admin-payments-billing-section-component>
+1
View File
@@ -579,6 +579,7 @@ Route::get('billplz/bills/{bill_no}', function($bill_no){
Route::get('/export/null-debtor/f614e339d7058904a831aad742e24d55', 'Exports\ExportCustomersToExcelController@nullDebtor')->name('newDebtor.export');
Route::get('/export/payment-transactions/{section}/f614e339d7058904a831aad742e24d55', 'Exports\ExportCustomersToExcelController@paymentTransactions')->name('paymentTransactions.export');
Route::get('/export/group-transactions/f614e339d7058904a831aad742e24d55', 'Exports\ExportCustomersToExcelController@groupTransaction')->name('groupTransaction.export');
Route::get('/delayed_container/customers', function(){
$containers = Container::whereHas('transports', function($query){