Compare commits

..

105 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 a7d4299897 Fix a typo error 2023-12-10 22:59:49 +08:00
Dillon Ngo 2b507d1006 Fix a typo error 2023-12-10 22:56:05 +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
Dillon Ngo 138a4f1cf6 Deleted some lines of codes 2023-12-07 17:17:39 +08:00
Dillon Ngo b54d897060 Remove <br> from payment transaction exported to excel file 2023-12-07 16:50:05 +08:00
Dillon Ngo c12959b4a8 Deleted some lines of codes 2023-12-07 16:44:06 +08:00
Dillon Ngo f94f380c16 Deleted some lines of codes 2023-12-07 16:42:52 +08:00
Dillon Ngo f46ec19f01 Update effective date for warehouse storage charges + commands to check for storage invoices 2023-12-07 16:35:51 +08:00
Omair Saleh c7a6a5b020 remove the 2 days delay for the ETA 2023-12-06 16:42:22 +08:00
Omair Saleh 8f64769214 remove the 2 days delay for the ETA 2023-12-06 16:38:57 +08:00
Dillon Ngo cb74228a68 Fix a problem reported by Yien where storage invoice number of days kept updated even though storage invoice already paid 2023-12-05 13:19:45 +08:00
Dillon Ngo b22cc0f7e3 Yien requested for some text description in invoice to be updated 2023-11-30 16:00:43 +08:00
Dillon Ngo 2e8ba4f630 Fix an error to export payment transaction in excel file 2023-11-30 13:56:35 +08:00
Dillon Ngo e987838d5a Fix 2 problem with generating storage invoice and export payment transaction in excel by date range 2023-11-30 13:36:38 +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
Dillon Ngo 48fa67ae8c Fix a problem with starting date should be done on arrival date of goods to china warehouse 2023-11-27 19:29:13 +08:00
Dillon Ngo 1e9e94b581 Fix a problem with starting date should be done on arrival date of goods to china warehouse 2023-11-27 19:20:45 +08:00
Dillon Ngo 67653b60fb Fix a problem with starting date should be done on arrival date of goods to china warehouse 2023-11-27 19:14:32 +08:00
Dillon Ngo 26fffb8af1 Fix decimal number to lengthy 2023-11-27 09:35:34 +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 fb0c74d645 Handling of dispute for warehouse storage fee 2023-11-24 13:44:28 +08:00
Dillon Ngo 53293f26d6 Amendment for Yien to do testing at dev environment 2023-11-24 02:29:05 +08:00
Dillon Ngo 56fe5520ad Amendment for Yien to do testing at dev environment 2023-11-24 00:33:07 +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
Dillon Ngo 61c801e216 Fix storage invoice with outdated info 2023-11-17 14:43:22 +08:00
Dillon Ngo 6f0acec390 Rename file, function + disable delete function for expired group payment 2023-11-17 14:16:02 +08:00
Dillon Ngo 76e3668563 20231109 Meeting Feedback 1 Fixes for warehouse storage charges 2023-11-16 22:40:26 +08:00
Dillon Ngo ce94dd1393 Fix for invoice status update using common function 2023-11-09 12:08:43 +08:00
Dillon Ngo c1ea087c58 Fix for storage invoice get to be generated even when the packingList not yet have APPROVED status 2023-11-09 08:34:03 +08:00
Dillon Ngo 8595d0987f Typo fix 2023-11-04 17:12:42 +08:00
Dillon Ngo 48d0460eef Debug billplz callback 2023-11-04 16:41:23 +08:00
Dillon Ngo 06751fdc78 New Warehouse Storage Fee 2023-11-04 14:58:50 +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
Dillon Ngo b5bcd5c553 Quick test on dev server 2023-10-27 04:18:39 +08:00
JiaSheng 671c7a54fb fix delivery order in shipping invoice 2023-10-26 22:31:10 +08:00
edmondlang 2a28183426 hide wallet result not found 2023-10-24 01:04:41 +08:00
edmondlang 0ebea79750 Merge branch 'wallet-new-feature' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal 2023-10-24 00:51:16 +08:00
edmondlang a701242646 fix wallet audit 2023-10-24 00:49:07 +08:00
edmondlang 4bdeae997d Merge branch 'wallet-audit' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal 2023-10-23 23:54:19 +08:00
edmondlang 36809f34cc Merge branch 'steve/aging-listing' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal 2023-10-23 23:53:35 +08:00
edmondlang 032171bb18 update aging listing 2023-10-23 23:53:10 +08:00
JiaSheng d41bd3db39 fix bug when packing list is deleted 2023-10-23 22:00:31 +08:00
JiaSheng 56bba0eaaf wallet pagination, export 2023-10-22 23:46:09 +08:00
edmondlang af8444e0d9 Merge branch 'wallet-audit' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal 2023-10-20 16:30:33 +08:00
edmondlang b2a7d1f73d update group payment 2023-10-20 16:26:18 +08:00
edmondlang 9d2ff3fafa update cash payment method 2023-10-20 16:22:19 +08:00
edmondlang 487d07e28c update design for approve payment 2023-10-20 16:02:04 +08:00
edmondlang 4176e09ea3 fix bug upload receipt modal not showing 2023-10-20 15:46:59 +08:00
edmondlang c44bf46a42 update web route for active wallet 2023-10-20 15:14:29 +08:00
edmondlang e687dd2b9a deletes payment 2023-10-19 22:54:21 +08:00
edmondlang 59951c4efd updater delete group transaction 2023-10-19 22:02:14 +08:00
edmondlang c00a4712a0 revert 2023-10-19 21:41:48 +08:00
edmondlang 1bb07e9402 revert 2023-10-19 21:38:24 +08:00
edmondlang 683bdec1f7 revert 2023-10-19 21:27:19 +08:00
edmondlang ee53a9438a temporary show all invoice 2023-10-19 21:25:44 +08:00
edmondlang 2e2087f16e temporary show all invoice 2023-10-19 21:23:15 +08:00
edmondlang 998b0b4da5 update delete group transaction 2023-10-19 20:48:22 +08:00
edmondlang dcf5c2e455 show billplz failed callback command 2023-10-19 20:14:59 +08:00
edmondlang 156b1dee07 update logic, for group payment, wallet must be credited first, then make group payment 2023-10-19 13:50:59 +08:00
edmondlang 544d7907c3 Merge branch 'master' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into wallet-audit 2023-10-19 13:43:53 +08:00
edmondlang 5b77f7baa6 add group payment in top up history 2023-10-19 11:44:25 +08:00
Jia Sheng Lee b33016aac4 only super admin can use the manual transfer for group payment 2023-10-18 15:28:12 +08:00
Jia Sheng Lee 2788e349ae manual transfer for admin to upload for bulk invoice payment 2023-10-18 15:06:46 +08:00
Steve Ng 04af87f640 csv download aging report 2023-10-18 08:48:30 +08:00
edmondlang 5b190d5334 revert ExportPendingArrangementPackingListV2Controller 2023-10-16 13:48:58 +08:00
Dillon Ngo 8f32769656 Merge branch 'dillon/44-quick-undo' into 'master'
Quick undo experimental security check

See merge request CIEFWorldwideSdnBhd/shipping-portal!176
2023-10-16 05:33:40 +00:00
Dillon 0e79bbfd6a Quick undo experimental security check 2023-10-16 13:24:30 +08:00
Dillon Ngo 3a411e8b9a Merge branch 'dillon/44-customer-satisfaction-feedback-project-b' into 'master'
Preparation for help menu

See merge request CIEFWorldwideSdnBhd/shipping-portal!175
2023-10-15 17:16:57 +00:00
Dillon bffe438455 Disable help menu 2023-10-16 01:09:24 +08:00
Dillon Ngo d17beda04b Merge branch 'dillon/44-customer-satisfaction-feedback-project' into 'master'
New Feedback Form for gathering feedback from customer

See merge request CIEFWorldwideSdnBhd/shipping-portal!174
2023-10-15 10:19:13 +00:00
Jia Sheng Lee 2d175f4acc recalculate wallet balance 2023-10-14 15:57:22 +08:00
Jia Sheng Lee 782aed06e4 add callback processor 2023-10-09 13:51:15 +08:00
Dillon f5482a29e4 New exception handling for all PerfexCRM services 2023-10-08 17:23:55 +08:00
Dillon 5584d22376 Improvement to log capture thrown by custom exception (ConnectionErrorException), to evaluate if need to extend to other custom exception as well 2023-10-05 19:58:07 +08:00
Dillon 42b6140df7 UX update when system failed to open a support ticket via help menu 2023-10-05 17:30:29 +08:00
Dillon 619fc25605 Merge branch 'dillon/44-customer-satisfaction-feedback-project' into dillon/44-customer-satisfaction-feedback-project-b 2023-10-05 17:04:41 +08:00
Dillon 5c24b6f81e Relocate help menu and make dynamic questionnaire set generation 2023-10-01 00:32:40 +08:00
141 changed files with 4285 additions and 479 deletions
@@ -0,0 +1,20 @@
<?php
namespace App\Classes\Exceptions;
use App\Classes\ValueObjects\Constants\HttpStatus;
use Illuminate\Support\Facades\Log;
final class ConnectionErrorException extends ServiceApiException {
public function __construct(?string $message = null, ?string $exceptionMessage = null, ?string $payload = null, ?string $exceptionTrace = null) {
Log::error($message. ": ". $exceptionMessage);
if($payload){
Log::error('Payload: '.$payload);
}
if($exceptionTrace){
Log::error($exceptionTrace);
}
parent::__construct($message ?? 'A connection error has occurred. Please check application logs for more information.',
HttpStatus::SERVER_ERROR);
}
}
@@ -0,0 +1,23 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
class CreatedAfterOrEqual implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value)
{
$table = $builder->getModel()->getTable();
$startDate = Carbon::createFromFormat('d-m-Y', $value)->startOfDay();
return $builder->where("{$table}.created_at", '>=', $startDate);
}
}
@@ -0,0 +1,22 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
class CreatedBeforeOrEqual implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value)
{
$table = $builder->getModel()->getTable();
$endDate = Carbon::createFromFormat('d-m-Y', $value)->endOfDay();
return $builder->where("{$table}.created_at", '<=', $endDate);
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class OrderByIdDesc implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->orderBy('id', 'desc');
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class OrderByUpdatedAtDesc implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->orderBy('updated_at', 'desc');
}
}
@@ -14,7 +14,8 @@ class OwnerId implements Filter
*/
public static function apply(Builder $builder, $value)
{
return $builder->where('owner_id', $value);
$table = $builder->getModel()->getTable();
return $builder->where("{$table}.owner_id", $value);
}
}
@@ -0,0 +1,21 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class OwnerType implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
$table = $builder->getModel()->getTable();
return $builder->where("{$table}.owner_type", $value);
}
}
@@ -14,7 +14,8 @@ class StatusIn implements Filter
*/
public static function apply(Builder $builder, $value)
{
return $builder->whereIn('status', $value);
$table = $builder->getModel()->getTable();
return $builder->whereIn("{$table}.status", $value);
}
}
@@ -0,0 +1,30 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Database\Eloquent\Builder;
class WithAgingColumn implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value)
{
$today = Carbon::now();
return $builder->select('packing_lists.*')
->addSelect(DB::raw("DATEDIFF('$today', transactions.updated_at) as days_over_duedate"))
->addSelect(DB::raw("CASE
WHEN DATEDIFF('$today', transactions.updated_at) <= 0 THEN 0
WHEN DATEDIFF('$today', transactions.updated_at) > 0 AND DATEDIFF('$today', transactions.updated_at) <= 30 THEN 1
WHEN DATEDIFF('$today', transactions.updated_at) > 30 AND DATEDIFF('$today', transactions.updated_at) <= 60 THEN 2
WHEN DATEDIFF('$today', transactions.updated_at) > 60 AND DATEDIFF('$today', transactions.updated_at) <= 90 THEN 3
ELSE 4
END AS due_date_number"));
}
}
@@ -0,0 +1,27 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class WithOrderReferenceLike implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->join('transactions as t2', 't2.payment_reference', '=', 'transactions.bill_no')
->join('transactions as t3', 't3.id', '=', 't2.owner_id')
->join('packing_lists', 'packing_lists.id', '=', 't3.owner_id')
->join('orders', function ($join) use ($value) {
$join->on('orders.id', '=', 'packing_lists.owner_id')
->where('orders.reference', 'LIKE', '%'.$value.'%');
})
->addSelect(['transactions.*', 't2.id as paymentTransactionId', 't3.id as invoiceTransactionId', 'packing_lists.id as packingListId', 'orders.reference as orderReference']);
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class WithTrashed implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->withTrashed();
}
}
@@ -14,14 +14,17 @@ use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\Modules\Billplzs\Services\GetBillplzBill;
use App\Classes\Modules\Billplzs\DataTransferObjects\BillplzXSignatureObject;
use App\Classes\Modules\Billplzs\Processors\CallbackBillplzProcessor;
use App\Classes\Modules\Transactions\Services\FetchesTransaction;
use App\Classes\Modules\Transactions\Processors\CreatePaymentTransactionProcessor;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use App\Classes\Modules\Transactions\Processors\CheckStorageInvoiceTransactionProcessor;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Group;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
class CallbackBillplzLogic
{
@@ -46,6 +49,12 @@ class CallbackBillplzLogic
/** @var CreatePaymentTransactionProcessor */
private $createPaymentTransactionProcessor;
/** @var CallbackBillplzProcessor */
private $callbackBillplzProcessor;
/** @var CheckStorageInvoiceTransactionProcessor */
private $storageInvoiceTransactionProcessor;
/**
* CallbackBillplzLogic constructor.
* @param GetBillplzBill $getBillplzBill
@@ -54,8 +63,10 @@ class CallbackBillplzLogic
* @param UpdateDoFromVTPortalProcessor $updateDoFromVTPortalProcessor
* @param UpdateDoFromYDPortalProcessor $updateDoFromYDPortalProcessor
* @param CreatePaymentTransactionProcessor $createPaymentTransactionProcessor
* @param CallbackBillplzProcessor $callbackBillplzProcessor
* @param CheckStorageInvoiceTransactionProcessor $storageInvoiceTransactionProcessor
*/
public function __construct(GetBillplzBill $getBillplzBill, FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, UpdateDoFromVTPortalProcessor $updateDoFromVTPortalProcessor, UpdateDoFromYDPortalProcessor $updateDoFromYDPortalProcessor, UpdatesWalletBalance $updatesWalletBalance, CreatePaymentTransactionProcessor $createPaymentTransactionProcessor)
public function __construct(GetBillplzBill $getBillplzBill, FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, UpdateDoFromVTPortalProcessor $updateDoFromVTPortalProcessor, UpdateDoFromYDPortalProcessor $updateDoFromYDPortalProcessor, UpdatesWalletBalance $updatesWalletBalance, CreatePaymentTransactionProcessor $createPaymentTransactionProcessor, CallbackBillplzProcessor $callbackBillplzProcessor, CheckStorageInvoiceTransactionProcessor $storageInvoiceTransactionProcessor)
{
$this->getBillplzBill = $getBillplzBill;
$this->fetchesTransaction = $fetchesTransaction;
@@ -64,6 +75,8 @@ class CallbackBillplzLogic
$this->updateDoFromYDPortalProcessor = $updateDoFromYDPortalProcessor;
$this->updatesWalletBalance = $updatesWalletBalance;
$this->createPaymentTransactionProcessor = $createPaymentTransactionProcessor;
$this->callbackBillplzProcessor = $callbackBillplzProcessor;
$this->storageInvoiceTransactionProcessor = $storageInvoiceTransactionProcessor;
}
@@ -103,44 +116,13 @@ class CallbackBillplzLogic
$status = $billplzXSignatureObject->getStatus() === 'failed' ? ApprovalStatus::REJECTED : ApprovalStatus::PENDING_VERIFICATION;
}
Log::info('Debug billPlz status: '.$status);
$token = Auth::fromUser(User::find(1));
$request->headers->set('Authorization', 'Bearer '.$token);
// check if is wallet top up
if($transaction->owner instanceof Wallet && $status === ApprovalStatus::APPROVED &&!in_array($transaction->status, [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])) {
$this->updatesWalletBalance->execute($transaction->owner, $transaction->amount);
}
// group payment
if ($transaction->type == TransactionType::GROUP_PAYMENT && $status === ApprovalStatus::APPROVED &&!in_array($transaction->status, [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])) {
$group = Group::where('reference', $billplzXSignatureObject->getBillPlzId())->first();
foreach($group->groupTransactions as $groupTransaction) {
$invoice = $groupTransaction->transaction;
$this->createPaymentTransactionProcessor->execute($invoice, PaymentMethodType::WALLET, null);
}
$group->status = $status;
$group->save();
}
$this->updatesTransactionStatus->execute($transaction, $status);
if (!$transaction->owner instanceof Wallet) {
$totalPaidAmount = $invoice->transactions->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->sum('amount');
if(($invoice->amount - $totalPaidAmount) < 0.01) {
$this->updatesTransactionStatus->execute($invoice, ApprovalStatus::COMPLETED);
$packingList->status = ApprovalStatus::APPROVED;
$packingList->save();
if(app()->environment('production')){
$this->updateDoFromVTPortalProcessor->execute($packingList);
$this->updateDoFromYDPortalProcessor->execute($packingList);
}
}
}
$this->storageInvoiceBackDoorPreventionCheck($transaction, $status);
$result = $this->callbackBillplzProcessor->execute($transaction, $status);
$company_module_marking = $transaction->owner->owner->connections? $transaction->owner->owner->connections->first()->invitee_reference: null;
@@ -151,6 +133,22 @@ class CallbackBillplzLogic
$company_module_marking = $order->companyModule->connections? $order->companyModule->connections->first()->invitee_reference: null;
}
return $request->method() === 'POST' ? true : view('pages.payments_redirect', ['marking' => $order->reference ?? null, 'company_module_marking' => $company_module_marking ?? null, 'transaction' => $transaction, 'status' => $status]);
return $request->method() === 'POST' ? true : view('pages.payments_redirect', ['marking' => $order->reference ?? null, 'company_module_marking' => $company_module_marking ?? null, 'transaction' => $transaction, 'status' => $status, 'result' => $result]);
}
private function storageInvoiceBackDoorPreventionCheck($transaction, $status){
if ($transaction->owner instanceof Wallet && $status === ApprovalStatus::APPROVED) {
$group = Group::where('reference', $transaction->payment_reference)->first();
if ($group) {
foreach ($group->groupTransactions as $groupTransaction) {
$invoice = $groupTransaction->transaction;
$pL = $invoice->owner;
$order = $pL->owner;
if($order){
$this->storageInvoiceTransactionProcessor->executeOrder($order, false); //original was set true here so that no group is soft deleted or billplz bill got deleted
}
}
}
}
}
}
@@ -0,0 +1,128 @@
<?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;
class CallbackBillplzProcessor
{
/** @var UpdatesTransactionStatus */
private $updatesTransactionStatus;
/** @var UpdateDoFromVTPortalProcessor */
private $updateDoFromVTPortalProcessor;
/** @var UpdateDoFromYDPortalProcessor */
private $updateDoFromYDPortalProcessor;
/** @var UpdatesWalletBalance */
private $updatesWalletBalance;
/** @var CreatePaymentTransactionProcessor */
private $createPaymentTransactionProcessor;
/** @var ReleaseGoodsToCustomerProcessor */
private $releaseGoodsToCustomerProcessor;
/**
* CreateUserProcessor 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);
// check if is wallet top up
if ($transaction->owner instanceof Wallet && $status === ApprovalStatus::APPROVED) {
$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;
$paymentTransaction = $this->createPaymentTransactionProcessor->execute($invoice, PaymentMethodType::WALLET, null, false);
if($paymentTransaction && $paymentTransaction->status == ApprovalStatus::APPROVED){
$pL = $invoice->owner;
$this->releaseGoodsToCustomerProcessor->execute($pL, $invoice);
}
}
$group->status = $status;
$group->save();
}
}
if (!$transaction->owner instanceof Wallet) {
$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;
$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;
}
}
@@ -0,0 +1,34 @@
<?php
namespace App\Classes\Modules\Billplzs\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
class DeletesBillplzBill
{
/**
* @param string $billID
* @throws MalformedRequestException
*/
public function execute(string $billID) {
try{
$response = Http::withBasicAuth(config('billplz.api_key').':', '')->delete(config('billplz.base_url').'/api/v3/bills/'.$billID);
Log::channel('storage_invoices')->info('DeletesBillplzBill response: '.json_encode($response));
if($response->successful()){
$data = $response->json();
// $data['url'] = $data['url'].'?auto_submit=true';
return (object) $data;
}else{
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from billplz server: ' . $exception->getMessage());
}
}
}
@@ -0,0 +1,98 @@
<?php
namespace App\Classes\Modules\Exports\Services;
use App\Models\Order;
use App\Models\PackingList;
use Maatwebsite\Excel\Concerns\FromQuery;
use Maatwebsite\Excel\Concerns\Exportable;
use Maatwebsite\Excel\Concerns\WithMapping;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use App\Classes\General\Eloquent\ApplyFiltersToQuery;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use DateTime;
class ExportsAgingList implements WithHeadings, WithHeadingRow, WithMapping, ShouldAutoSize, FromQuery
{
use Exportable;
private $filters;
public function __construct()
{
$this->filters = [
"has_invoice_status_in" => [2],
"packing_list_ordered_by_invoice_date" => true,
"with_aging_column" => true
];
}
public function headings(): array
{
return [
'Company Name',
'Customer Marking',
'Order Number',
'Invoice No',
'Invoice Date',
'Days',
'Amount',
];
}
public function query()
{
return (new ApplyFiltersToQuery())->execute(PackingList::query(), $this->filters);
}
public function map($list): array
{
$marking = null;
$orderNo = null;
$name = null;
$invDate = 'n/a';
$invNo = 'n/a';
$days = 'n/a';
if ($list->owner instanceof Order) {
$inviterPivotInviteeReference = $list->owner->companyModule->inviters()->withPivot('invitee_reference')->first();
if ($inviterPivotInviteeReference) {
$marking = $inviterPivotInviteeReference->pivot->invitee_reference;
$orderNo = $list->owner->reference;
}
$name = $list->owner->companyModule->company->name;
}
$transaction = $list->transactions()->whereIn('status', [ApprovalStatus::APPROVED])->first();
if ($transaction) {
$invoiceDate = $transaction->created_at;
$invDate = date_format($invoiceDate, 'd-m-Y');
$invNo = $transaction->bill_no;
$amt = number_format($transaction->amount, 2);
$currentDate = new DateTime();
$interval = $currentDate->diff($invoiceDate);
$days = $interval->format('%a');
}
return [
$name,
$marking,
$orderNo,
$invNo,
$invDate,
$days,
$amt,
];
}
private function dueDateColumn($colNum, $dueDateNumber, $amt)
{
if ($colNum == $dueDateNumber) return $amt;
return null;
}
}
@@ -0,0 +1,108 @@
<?php
namespace App\Classes\Modules\Exports\Services;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Transaction;
use App\Models\Company;
use App\Models\Wallet;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Maatwebsite\Excel\Concerns\Exportable;
use Maatwebsite\Excel\Concerns\FromQuery;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
class ExportsCustomersWalletTransactionHistory implements FromQuery, WithHeadings, WithHeadingRow, WithMapping, ShouldAutoSize
{
use Exportable;
private $request;
private $runningBalance = 0;
public function __construct(Request $request)
{
$this->request = $request;
}
public function headings(): array
{
return [
'Date',
'Description',
'Incoming',
'Outgoing',
'Balance',
];
}
/**
* @return \Illuminate\Support\Collection|mixed
*/
public function query()
{
$wallet = Wallet::find($this->request->route('wallet_id'));
$transactions = $wallet->transactions()->whereIn('transactions.status', [2, 3])->orderBy('id');
return $transactions;
}
/**
* @param Transaction $transaction
*
* @return array
*/
public function map($transaction): array
{
$decimals = $this->request->route('is_precise') == 'true' ? 5 : 2;
$description = '';
switch ((int) $transaction->type) {
case TransactionType::TOP_UP:
$description = (float) $transaction->amount . ' Credit Top up';
break;
case TransactionType::GROUP_PAYMENT:
$description = (float) $transaction->amount . ' Credit Top up';
break;
case TransactionType::CREDIT_NOTE:
$description = 'Credit Voucher for ' . $transaction->payment_reference;
break;
case TransactionType::PAYMENT:
$booking = Transaction::where('payment_reference', $transaction->bill_no)->first()->owner;
if (!$booking) {
$description = 'Payment for unknown booking, please contact tech support.';
break;
}
$marking = $booking->marking;
$description = 'Payment For booking refs' . $marking;
break;
case TransactionType::DEBIT_NOTE:
$description = 'Debit Voucher for ' . $transaction->payment_reference;
break;
}
$incoming = $outgoing = '';
if (in_array($transaction->type, [TransactionType::TOP_UP, TransactionType::CREDIT_NOTE, TransactionType::GROUP_PAYMENT])) {
$incoming = number_format($transaction->amount, $decimals, '.', ',');
$this->runningBalance += $transaction->amount;
}
if (in_array($transaction->type, [TransactionType::PAYMENT, TransactionType::DEBIT_NOTE])) {
$outgoing = number_format($transaction->amount, $decimals, '.', ',');
$this->runningBalance -= $transaction->amount;
}
return [
Carbon::parse($transaction->created_at)->format('d-m-Y h:i:s A'),
$description,
$incoming,
$outgoing,
number_format($this->runningBalance, $decimals, '.', ',')
];
}
}
@@ -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,
@@ -74,7 +74,8 @@ class ExportsPaymentTransactions implements FromQuery, WithHeadings, WithHeading
$approvalStatus = ApprovalStatus::APPROVED;
}
$query->where('type', TransactionType::SHIPPING_INVOICE)->whereIn('status', [$approvalStatus]);
// $query->where('type', TransactionType::SHIPPING_INVOICE)->whereIn('status', [$approvalStatus]);
$query->whereIn('type', [TransactionType::SHIPPING_INVOICE, TransactionType::STORAGE_INVOICE])->whereIn('status', [$approvalStatus]);
if($start_date && $end_date) {
$query->whereBetween('updated_at', [
@@ -102,7 +103,12 @@ class ExportsPaymentTransactions implements FromQuery, WithHeadings, WithHeading
$container = $transaction->owner->containers()->first();
$order = $transaction->owner->owner;
$company = $order->companyModule->company;
$shippingTransactionDetails = $transaction->transactionDetails()->where('reference', 'SHIPPING_FEE')->first();
if($transaction->type === TransactionType::STORAGE_INVOICE){
$shippingTransactionDetails = $transaction->transactionDetails()->where('reference', 'STORAGE_FEE')->first();
}
else{
$shippingTransactionDetails = $transaction->transactionDetails()->where('reference', 'SHIPPING_FEE')->first();
}
$marking = $order->companyModule->inviters()->withPivot('invitee_reference')->first()->pivot->invitee_reference;
$contact = $order->companyModule->company->contacts->first();
$userName = $order->companyModule->employees()->first();
@@ -118,6 +124,8 @@ class ExportsPaymentTransactions implements FromQuery, WithHeadings, WithHeading
$furtherDescription .= $item->name.' '.$item->quantity.' CBM'."\n";
elseif($item->reference === 'MIN_CBM_CHARGES')
$furtherDescription .= $item->name.' '.$item->quantity.' CBM'."\n";
elseif($item->reference === 'STORAGE_FEE')
$furtherDescription .= str_replace('<br>', ' | ', $item->name).' '."\n";
else
$furtherDescription .= $item->name.' '.$item->quantity.' X '.$item->price."\n";
}
@@ -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));
}
@@ -75,7 +75,8 @@ class UpdateNextQuestionQALogic extends AbstractControllerLogic
/**
* @param Request $request
* @return JsonResponse
* @throws ErrorException
* @throws MalformedRequestException
* @throws ResourceNotFoundException
*/
public function logic(Request $request) : JsonResponse
{
@@ -25,6 +25,14 @@ class DeleteAnswerQAProcessor
$this->listsHelpMenuUserAnswerSelected = $listsHelpMenuUserAnswerSelected;
}
/**
* @param int $userId
* @param int $questionId
* @param Request $request
* @return void
* @throws ResourceNotFoundException
*/
public function execute($userId, $questionId, $request){
if ($request->has('isPrevious')) {
//Get current and previous question's answer
@@ -23,7 +23,7 @@ class FetchFirstQuestionQAProcessor
public function execute(Request $request){
try {
$query = $this->fetchesHelpMenuQuestion->execute(['questionnaire_set_id' => 1]);
$query = $this->fetchesHelpMenuQuestion->execute(['questionnaire_set_id' => $request->route('set_id')]);
return $query;
} catch (\Exception $exception){
throw new ErrorException($exception->getMessage(), $exception->getCode());
@@ -38,6 +38,7 @@ class FetchNextQuestionQAProcessor
$nextQuestionNumber = 0;
$nextNestedQuestion = 0;
$nextMainQuestion= 0;
$questionnaireSetId = 0;
$currentQuestion = $request->question;
$questionType = QAType::DEFAULT;
$returnQuestion = null;
@@ -48,7 +49,9 @@ class FetchNextQuestionQAProcessor
$questionType = $currentQuestion['question_type'];
$nextNestedQuestion = $currentQuestion['next_nested_question'];
$nextMainQuestion = $currentQuestion['next_main_question'];
$questionnaireSetId = $currentQuestion['questionnaire_set_id'];
}
if ($request->has('answerObj')) {
$nextQuestionNumber = $request->answerObj['next_question_number'];
}
@@ -58,7 +61,7 @@ class FetchNextQuestionQAProcessor
$previousAnswer = $this->listsHelpMenuUserAnswerSelected->execute(['user_id' => $userId, 'order_by' => (object)['column' => 'id','DESC' => true]])[0];
//Get previous question
$previousQuestion = $this->fetchesHelpMenuQuestion->execute(['questionnaire_set_id' => 1, 'id' => $previousAnswer['question_id']]);
$previousQuestion = $this->fetchesHelpMenuQuestion->execute(['questionnaire_set_id' => $questionnaireSetId, 'id' => $previousAnswer['question_id']]);
$returnQuestion = $previousQuestion;
}
else{
@@ -79,11 +82,11 @@ class FetchNextQuestionQAProcessor
$returnQuestion = null;
}
else if($question_number != 0){
$nextQuestion = $this->fetchesHelpMenuQuestion->execute(['questionnaire_set_id' => 1, 'question_number' => $question_number]);
$nextQuestion = $this->fetchesHelpMenuQuestion->execute(['questionnaire_set_id' => $questionnaireSetId, 'question_number' => $question_number]);
$returnQuestion = $nextQuestion;
}
else if (array_key_exists('id', $request->input('question'))) {
$nextQuestion = $this->fetchesHelpMenuQuestion->execute(['questionnaire_set_id' => 1, 'id_next' => $questionId, 'next_main_question' => null]);
$nextQuestion = $this->fetchesHelpMenuQuestion->execute(['questionnaire_set_id' => $questionnaireSetId, 'id_next' => $questionId, 'next_main_question' => null]);
$returnQuestion = $nextQuestion;
}
}
@@ -53,8 +53,12 @@ class FetchOrderV2Logic extends AbstractControllerLogic
$query = $this->fetchesOrder->execute(['reference' => $request->route('id'), 'with_packing_lists' => true]);
if($request->input('storages')){
$query->storages = $request->input('storages'); //from middleware
}
return $this->resourceResponse(new OrderV2Resource($query));
}
}
}
@@ -9,6 +9,8 @@ use App\Classes\Modules\Addresses\Services\FetchesAddress;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Models\PackingList;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Support\Facades\Log;
class UpdateDoFromVTPortalProcessor
{
/** @var FetchesDataFromVTPortal */
@@ -36,6 +38,8 @@ class UpdateDoFromVTPortalProcessor
*/
public function execute(PackingList $packing_list) {
Log::info('Trying to Call UpdateDoFromVTPortalProcessor');
if(!app()->environment(['production'])){
return [];
}
@@ -37,6 +37,9 @@ class UpdateDoFromYDPortalProcessor
* @throws InternalServerErrorException
*/
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;
}
@@ -70,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');
}
}
@@ -121,7 +121,7 @@ class FetchContainersFromYdPortalProcessor
$containerReference = explode('预计到港时间', $tracking[1])[0];
$loadingDate = Carbon::parse($trackingRow->trackingtime);
$etd = Carbon::parse($tracking[2])->subDays(5);
$eta = Carbon::parse($tracking[2])->addDays(2);
$eta = Carbon::parse($tracking[2]);
}
}
@@ -147,7 +147,6 @@ class FetchContainersUpdatesFromYdPortalProcessor
if($delayDate){
$delayDate = $delayDate->addDays(2);
$transport = $container->transports()->first();
if(!$transport->schedules()->whereDate('eta', '>=', $delayDate)->first()) {
@@ -162,7 +162,7 @@ class FetchLoadedContainersFromVTPortalProcessor
$container = $this->createContainerProcessor->execute($containerObject, $originWarehouse);
}
$eta = Carbon::parse($containerInfo[4])->addDays(2);
$eta = Carbon::parse($containerInfo[4]);
$etd = Carbon::parse($eta)->subDays(7);
$delayDate = $containerInfo[7];
@@ -183,7 +183,7 @@ class FetchLoadedContainersFromVTPortalProcessor
}
if($delayDate){
$delayDate = Carbon::parse($delayDate)->addDays(2);
$delayDate = Carbon::parse($delayDate);
$transport = $container->transports()->first();
if(!$transport->schedules()->where('eta', '=', $delayDate)->first()) {
@@ -199,7 +199,7 @@ class FetchOrderListsFromYdPortalProcessor
$containerReference = explode('预计到港时间', $tracking[1])[0];
$loadingDate = Carbon::parse($trackingRow->trackingtime);
$etd = Carbon::parse($tracking[2])->subDays(5);
$eta = Carbon::parse($tracking[2])->addDays(2);
$eta = Carbon::parse($tracking[2]);
}
$rescheduleETD = strpos($trackingRow->remark, '开') || strpos($trackingRow->remark, '到港');
@@ -415,7 +415,7 @@ class FetchOrderListsFromYdPortalProcessor
}
if($delayDate){
$delayDate = $delayDate->addDays(2);
$delayDate = $delayDate;
$transport = $container->transports()->first();
if(!$transport->schedules()->whereDate('eta', '>=', $delayDate)->first()) {
@@ -10,22 +10,23 @@ use App\Classes\ValueObjects\Constants\RoleTypes;
class CanListPackingLists extends AbstractRule
{
/**
* @return bool
*/
protected function authorized($object): bool
{
if(Auth()->user()){
$roleToCheck = Auth()->user()->type;
if (in_array($roleToCheck, RoleTypes::ADMIN_ROLES)) {
return true;
}
else {
return false;
}
}
return false;
// if(Auth()->user()){
// $roleToCheck = Auth()->user()->type;
// if (in_array($roleToCheck, RoleTypes::ADMIN_ROLES)) {
// return true;
// }
// else {
// return false;
// }
// }
// return false;
return true;
}
/**
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
class ConvertsPerfexCRMLeadToCustomer
@@ -27,8 +28,13 @@ class ConvertsPerfexCRMLeadToCustomer
Log::error('ConvertsPerfexCRMLeadToCustomer: '.$response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), $email, $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
class CreatesPerfexCRMCustomer
@@ -30,8 +31,13 @@ class CreatesPerfexCRMCustomer
Log::error('CreatesPerfexCRMCustomer: '.$response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), $companyName, $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
}
@@ -5,6 +5,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CustomerContactObject;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
class CreatesPerfexCRMCustomerContact
@@ -37,8 +38,13 @@ class CreatesPerfexCRMCustomerContact
Log::error('CreatesPerfexCRMCustomerContact: '.$response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), "", $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
class CreatesPerfexCRMCustomerProject
@@ -36,8 +37,13 @@ class CreatesPerfexCRMCustomerProject
Log::error('CreatesPerfexCRMCustomerProject: '.$response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), "", $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\InvoicePerfexCRMObject;
@@ -56,8 +57,13 @@ class CreatesPerfexCRMInvoice
Log::error('CreatesPerfexCRMInvoice: '.$response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), "", $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\InvoicePaymentPerfexCRMObject;
@@ -36,8 +37,13 @@ class CreatesPerfexCRMInvoicePayment
Log::error('CreatesPerfexCRMInvoicePayment: '.$response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), "", $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CreateLeadPerfexCRMObject;
@@ -43,8 +44,13 @@ class CreatesPerfexCRMLead
Log::error('CreatesPerfexCRMLead: '.$response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server ' . $exception->getMessage());
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), "", $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
class CreatesPerfexCRMMilestone
@@ -39,8 +40,13 @@ class CreatesPerfexCRMMilestone
Log::error('CreatesPerfexCRMMilestone: '.$response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), "", $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
class CreatesPerfexCRMSupportTicket
@@ -36,9 +37,15 @@ class CreatesPerfexCRMSupportTicket
Log::error($response);
return null;
}
}catch(\Exception $exception){
$error = 'Support Ticket creation failed: ' . $exception->getMessage();
Log::error($error.'\nPayload to create ticket: '.json_encode($data));
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), "", $exception->getTraceAsString());
}
catch(\Exception $exception){
$error = 'Support Ticket creation failed';
Log::error($error. ": ". $exception->getMessage());
Log::error('Payload: '.json_encode($data));
throw new MalformedRequestException($error);
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
use App\Classes\ValueObjects\Constants\PerfexCRMCustomFields;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CreateTaskPerfexCRMObject;
@@ -60,8 +61,13 @@ class CreatesPerfexCRMTask
Log::error('CreatesPerfexCRMTask: '.$response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), "", $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
class FetchesPerfexCRMCustomer
@@ -27,8 +28,15 @@ class FetchesPerfexCRMCustomer
Log::error('FetchesPerfexCRMCustomer: '.$response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), $email, $exception->getTraceAsString());
}
catch(\Exception $exception){
$error = 'Unable to get correct response from Perfex CRM server: ' . $exception->getMessage();
Log::error($error);
throw new MalformedRequestException($error);
}
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
class FetchesPerfexCRMInvoice
@@ -29,7 +30,12 @@ class FetchesPerfexCRMInvoice
Log::error('FetchesPerfexCRMInvoice: '.$response);
return null;
}
}catch(\Exception $exception){
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), "", $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
class FetchesPerfexCRMLead
@@ -27,7 +28,12 @@ class FetchesPerfexCRMLead
Log::error('FetchesPerfexCRMLead: '.$response);
return null;
}
}catch(\Exception $exception){
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), $email, $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
class FetchesPerfexCRMMilestone
@@ -33,8 +34,13 @@ class FetchesPerfexCRMMilestone
Log::error('FetchesPerfexCRMMilestone: '.$response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), "", $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
class FetchesPerfexCRMProject
@@ -33,8 +34,13 @@ class FetchesPerfexCRMProject
Log::error('FetchesPerfexCRMProject: '.$response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), "", $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
use App\Classes\General\Helper;
@@ -47,8 +48,13 @@ class FetchesPerfexCRMTask
Helper::debugLogger($response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), "", $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
use App\Classes\ValueObjects\Constants\PerfexCRMCustomFields;
use App\Classes\General\Helper;
@@ -41,8 +42,13 @@ class UpdatesPerfexCRMCustomer
// Helper::debugLogger($response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), "", $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
class UpdatesPerfexCRMInvoice
@@ -63,7 +64,12 @@ class UpdatesPerfexCRMInvoice
Log::error('UpdatesPerfexCRMInvoice: '.$response);
return null;
}
}catch(\Exception $exception){
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), "", $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
use App\Classes\ValueObjects\Constants\PerfexCRMCustomFields;
@@ -44,7 +45,12 @@ class UpdatesPerfexCRMLead
Log::error('UpdatesPerfexCRMLead: '.$response);
return null;
}
}catch(\Exception $exception){
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), "", $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
class UpdatesPerfexCRMProject
@@ -36,7 +37,12 @@ class UpdatesPerfexCRMProject
Log::error('UpdatesPerfexCRMProject: '.$response);
return null;
}
}catch(\Exception $exception){
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), "", $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
class UpdatesPerfexCRMTask
@@ -41,8 +42,13 @@ class UpdatesPerfexCRMTask
Log::error('UpdatesPerfexCRMTask: '.$response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
catch(\Illuminate\Http\Client\ConnectionException $exception){
$error = 'Failed to connect to CRM';
throw new ConnectionErrorException($error, $exception->getMessage(), "", $exception->getTraceAsString());
}
catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
}
@@ -4,18 +4,15 @@ namespace App\Classes\Modules\Transactions\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Billplzs\Processors\CallbackBillplzProcessor;
use App\Classes\Modules\Documents\Services\ApprovesDocument;
use App\Classes\Modules\Documents\Services\FetchesDocument;
use App\Classes\Modules\Documents\Services\RejectsDocument;
use App\Classes\Modules\Orders\Processors\UpdateDoFromVTPortalProcessor;
use App\Classes\Modules\Orders\Processors\UpdateDoFromYDPortalProcessor;
use App\Classes\Modules\Transactions\Processors\CreatePaymentTransactionProcessor;
use App\Classes\Modules\Transactions\Services\FetchesTransaction;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -29,15 +26,15 @@ class ApprovePaymentTransactionLogic extends AbstractControllerLogic
* @param RejectsDocument $rejectsDocument
* @param UpdateDoFromVTPortalProcessor $updateDoFromVTPortalProcessor
* @param UpdateDoFromYDPortalProcessor $updateDoFromYDPortalProcessor
* @param CreatePaymentTransactionProcessor $createPaymentTransactionProcessor
*/
public function __construct(FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, ApprovesDocument $approvesDocument, RejectsDocument $rejectsDocument, UpdateDoFromVTPortalProcessor $updateDoFromVTPortalProcessor, UpdateDoFromYDPortalProcessor $updateDoFromYDPortalProcessor)
public function __construct(FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, ApprovesDocument $approvesDocument, RejectsDocument $rejectsDocument, CallbackBillplzProcessor $callbackBillplzProcessor)
{
$this->fetchesTransaction = $fetchesTransaction;
$this->updatesTransactionStatus = $updatesTransactionStatus;
$this->approvesDocument = $approvesDocument;
$this->rejectsDocument = $rejectsDocument;
$this->updateDoFromVTPortalProcessor = $updateDoFromVTPortalProcessor;
$this->updateDoFromYDPortalProcessor = $updateDoFromYDPortalProcessor;
$this->callbackBillplzProcessor = $callbackBillplzProcessor;
}
/**
@@ -62,11 +59,8 @@ class ApprovePaymentTransactionLogic extends AbstractControllerLogic
/** @var RejectsDocument */
private $rejectsDocument;
/** @var UpdateDoFromVTPortalProcessor */
private $updateDoFromVTPortalProcessor;
/** @var UpdateDoFromYDPortalProcessor */
private $updateDoFromYDPortalProcessor ;
/** @var CallbackBillplzProcessor */
private $callbackBillplzProcessor;
/**
* @param Request $request
@@ -82,29 +76,14 @@ class ApprovePaymentTransactionLogic extends AbstractControllerLogic
$transaction = $this->fetchesTransaction->execute(['id' => $request->route('transaction_id')]);
$status === 'approve' ? $this->approvesDocument->execute($transaction->documents()->first()) : $this->rejectsDocument->execute($transaction->documents()->first());
$status === 'approve' ? $this->approvesDocument->execute($transaction->documents()->where('status', ApprovalStatus::PENDING_VERIFICATION)->first()) : $this->rejectsDocument->execute($transaction->documents()->where('status', ApprovalStatus::PENDING_VERIFICATION)->first());
$this->updatesTransactionStatus->execute($transaction, $status === 'approve' ? ApprovalStatus::APPROVED : ApprovalStatus::REJECTED);
if($transaction->status === ApprovalStatus::APPROVED){
$invoice = $transaction->owner;
$packingList = $invoice->owner;
if(($invoice->amount - $transaction->amount) < 0.01) {
$this->updatesTransactionStatus->execute($invoice, ApprovalStatus::COMPLETED);
$packingList->status = ApprovalStatus::APPROVED;
$packingList->save();
if(app()->environment('production')){
$this->updateDoFromVTPortalProcessor->execute($packingList);
$this->updateDoFromYDPortalProcessor->execute($packingList);
}
}
if ($status === 'approve') {
$this->callbackBillplzProcessor->execute($transaction, ApprovalStatus::APPROVED);
}
return $this->response([]);
}
@@ -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
@@ -84,6 +92,25 @@ class CreateGroupsLogic extends AbstractControllerLogic
// $invoices = $this->fetchesTransaction->execute(['id_in' => $invoice_ids]);
$invoices = Transaction::whereIn('id', $invoice_ids)->get();
foreach ($invoices as $invoice) {
$order = null;
if ($invoice->owner instanceof Transaction) {
if ($invoice->owner) {
if ($invoice->owner->owner) {
$order = $invoice->owner->owner->owner;
}
}
} else if (!($invoice->owner instanceof Transaction) && !($invoice->owner instanceof Wallet)) {
if ($invoice->owner) {
$order = $invoice->owner->owner;
}
}
if (!$order) {
throw new MalformedRequestException("There is an error while paying for invoice {$invoice->bill_no}");
}
}
if ($payment_method == PaymentMethodType::WALLET) {
$companyModuleId = $invoices->first()->receiver;
@@ -127,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;
@@ -153,7 +185,7 @@ class CreateGroupsLogic extends AbstractControllerLogic
$companyModuleId = $invoice->receiver;
$companyModule = $this->fetchesCompanyModule->execute(['id' => $companyModuleId]);
$topUpTransaction = $this->createWalletTopUpTransactionProcessor->execute($companyModule, $amount, $request->input('bank_code'), true, $payment_method);
$topUpTransaction = $this->createWalletTopUpTransactionProcessor->execute($companyModule, $amount, $request->input('bank_code'), $payment_method, $billNumber, true);
}
$group->issuer = $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));
}
}
@@ -50,6 +50,11 @@ class DeleteGroupLogic extends AbstractControllerLogic
{
$group = $this->fetchesGroup->execute(['id' => $request->route('id')]);
foreach ($group->groupTransactions as $groupTransaction) {
// $groupTransaction->transaction->delete();
$groupTransaction->delete();
}
$this->deletesGroup->execute($group);
return $this->response([]);
@@ -0,0 +1,57 @@
<?php
namespace App\Classes\Modules\Transactions\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Transactions\Services\FetchesTransaction;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class DeletePaymentTransactionLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Delete Payment Transaction',
'message' => 'You have successfully deleted the payment transaction'
];
}
/** @var FetchesTransaction */
private $fetchesTransaction;
/** @var UpdatesTransactionStatus */
private $updatesTransactionStatus;
/**
* SuspendTransactionLogic constructor.
* @param FetchesTransaction $fetchesTransaction
* @param UpdatesTransactionStatus $updatesTransactionStatus
*/
public function __construct(FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus)
{
$this->fetchesTransaction = $fetchesTransaction;
$this->updatesTransactionStatus = $updatesTransactionStatus;
}
public function logic(Request $request) : JsonResponse
{
$transaction = $this->fetchesTransaction->execute(['id' => $request->route('id')]);
$transaction->delete();
$invoice = $transaction->owner;
$this->updatesTransactionStatus->execute($invoice, ApprovalStatus::APPROVED);
return $this->response([]);
}
}
@@ -5,10 +5,11 @@ namespace App\Classes\Modules\Transactions\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Transactions\Services\ListsTransactions;
use App\Http\Resources\BookingResource;
use App\Http\Resources\TransactionResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
class ListTransactionsLogic extends AbstractControllerLogic
{
@@ -38,13 +39,18 @@ class ListTransactionsLogic extends AbstractControllerLogic
public function logic(Request $request) : JsonResponse
{
$query = $this->listsTransactions->execute($this->listsTransactions->deserializeFilters($request->input('filters')));
if($request->input('storages')){
foreach ($query->items() as &$item) {
$transactionId = $item['id'];
$filteredStorages = array_filter($request->input('storages'), function ($storage) use ($transactionId) {
return isset($storage['parentInvoiceId']) && $storage['parentInvoiceId'] == $transactionId;
});
$item['storages'] = $filteredStorages;
}
}
return $this->collectionResponse(TransactionResource::collection($query));
}
}
@@ -0,0 +1,79 @@
<?php
namespace App\Classes\Modules\Transactions\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Transactions\Services\ListsTransactions;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Http\Resources\WalletTransactionResource ;
use App\Models\Transaction;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class ListWalletTransactionsLogic extends AbstractControllerLogic
{
/**
* ListTransactionsLogic constructor.
* @param ListsTransactions $listsTransactions
*/
public function __construct(ListsTransactions $listsTransactions)
{
$this->listsTransactions = $listsTransactions;
}
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Retrieved Wallet Transactions',
'message' => 'You have successfully retrieved a list of transactions'
];
}
/** @var ListsTransactions */
private $listsTransactions;
public function logic(Request $request) : JsonResponse
{
$query = $this->listsTransactions->execute($this->listsTransactions->deserializeFilters($request->input('filters')));
if (str_contains($request->input('filters'), "owner_id") && $query->count() > 0) {
$wallet_total_incoming = Transaction::where('owner_type', $query->first()->owner_type)
->where('owner_id', $query->first()->owner_id)
->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])
->whereIn('type', [TransactionType::TOP_UP, TransactionType::CREDIT_NOTE, TransactionType::GROUP_PAYMENT])
->sum('amount');
$wallet_total_outgoing = Transaction::where('owner_type', $query->first()->owner_type)
->where('owner_id', $query->first()->owner_id)
->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])
->whereIn('type', [TransactionType::PAYMENT, TransactionType::DEBIT_NOTE])
->sum('amount');
$currentWalletBalance = $wallet_total_incoming - $wallet_total_outgoing;
$incoming = Transaction::where('owner_type', $query->first()->owner_type)
->where('owner_id', $query->first()->owner_id)
->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])
->whereIn('type', [TransactionType::TOP_UP, TransactionType::CREDIT_NOTE, TransactionType::GROUP_PAYMENT])
->where('id', '>', $query->first()->id)
->sum('amount');
$outgoing = Transaction::where('owner_type', $query->first()->owner_type)
->where('owner_id', $query->first()->owner_id)
->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])
->whereIn('type', [TransactionType::PAYMENT, TransactionType::DEBIT_NOTE])
->where('id', '>', $query->first()->id)
->sum('amount');
$runningBalanceInReverse = $currentWalletBalance - $incoming + $outgoing;
$request['running_balance'] = $runningBalanceInReverse;
}
return $this->collectionResponse(WalletTransactionResource::collection($query));
}
}
@@ -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([]);
}
}
@@ -17,6 +17,8 @@ use App\Classes\Modules\Documents\Services\CreatesDocument;
use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use App\Classes\Jobs\CreatePerfexCRMInvoice;
use App\Classes\Modules\Transactions\Processors\CheckStorageInvoiceTransactionProcessor;
use App\Models\Order;
class ApproveShippingInvoiceTransactionProcessor
{
@@ -30,17 +32,21 @@ class ApproveShippingInvoiceTransactionProcessor
/** @var CreatesFiles */
private $createsFiles;
/** @var CheckStorageInvoiceTransactionProcessor */
private $storageInvoiceTransactionProcessor;
/**
* @param UpdatesTransactionStatus $updatesTransactionStatus
* @param CreatesDocument $createsDocument
* @param CreatesFiles $createsFiles
*/
public function __construct(UpdatesTransactionStatus $updatesTransactionStatus, CreatesDocument $createsDocument, CreatesFiles $createsFiles)
public function __construct(UpdatesTransactionStatus $updatesTransactionStatus, CreatesDocument $createsDocument, CreatesFiles $createsFiles, CheckStorageInvoiceTransactionProcessor $storageInvoiceTransactionProcessor)
{
$this->updatesTransactionStatus = $updatesTransactionStatus;
$this->createsDocument = $createsDocument;
$this->createsFiles = $createsFiles;
$this->storageInvoiceTransactionProcessor = $storageInvoiceTransactionProcessor;
}
@@ -50,7 +56,6 @@ class ApproveShippingInvoiceTransactionProcessor
*/
public function execute(PackingList $packingList)
{
/** @var Transaction $invoice_transaction */
$invoice_transaction = $packingList->transactions()->where('transactions.type', TransactionType::SHIPPING_INVOICE)->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::PENDING_SUBMISSION])->first();
@@ -75,6 +80,11 @@ class ApproveShippingInvoiceTransactionProcessor
$user->notify(new InvoiceIssuedEmail($user, $packingList));
}
$order = $packingList->owner()->first();
if($order instanceof Order){
$this->storageInvoiceTransactionProcessor->executeOrder($order);
}
return;
}
@@ -0,0 +1,360 @@
<?php
namespace App\Classes\Modules\Transactions\Processors;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Modules\Orders\Services\FetchesOrder;
use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber;
use App\Classes\Modules\Transactions\Services\CreatesTransaction;
use App\Classes\Modules\Transactions\Services\CreatesTransactionDetail;
use App\Classes\Modules\Transactions\Services\UpdatesTransaction;
use App\Classes\Modules\Transactions\Services\FetchesTransaction;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionDetail;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use App\Classes\Modules\Transactions\Services\DeletesGroup;
use App\Classes\Modules\Billplzs\Services\DeletesBillplzBill;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionDetailObject;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\PackageType;
use App\Classes\ValueObjects\Constants\PackingListType;
use App\Classes\ValueObjects\Constants\TransactionDetailType;
use App\Http\Resources\TransactionResource;
use App\Models\Order;
use App\Models\PackingList;
use App\Models\Transaction;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
class CheckStorageInvoiceTransactionProcessor
{
/** @var FetchesOrder */
private $fetchesOrder;
/** @var GeneratesTransactionBillNumber */
private $generatesTransactionBillNumber;
/** @var FetchesTransaction */
private $fetchesTransaction;
/** @var CreatesTransaction */
private $createsTransaction;
/** @var CreatesTransactionDetail */
private $createsTransactionDetail;
/** @var UpdatesTransaction */
private $updatesTransaction;
/** @var UpdatesTransactionDetail */
private $updatesTransactionDetail;
/** @var UpdatesTransactionStatus */
private $updatesTransactionStatus;
/** @var DeletesGroup */
private $deletesGroup;
/** @var DeletesBillplzBill */
private $deletesBillplzBill;
/**
* @param FetchesOrder $fetchesOrder
* @param GeneratesTransactionBillNumber $generatesTransactionBillNumber
* @param FetchesTransaction $fetchesTransaction
* @param CreatesTransaction $createsTransaction
* @param CreatesTransactionDetail $createsTransactionDetail
* @param UpdatesTransaction $updatesTransaction
* @param UpdatesTransactionDetail $updatesTransactionDetail
* @param UpdatesTransactionStatus $updatesTransactionStatus
* @param DeletesGroup $deletesGroup
* @param DeletesBillplzBill $deletesBillplzBill
*/
public function __construct(FetchesOrder $fetchesOrder, GeneratesTransactionBillNumber $generatesTransactionBillNumber, FetchesTransaction $fetchesTransaction, CreatesTransaction $createsTransaction, CreatesTransactionDetail $createsTransactionDetail, UpdatesTransaction $updatesTransaction, UpdatesTransactionDetail $updatesTransactionDetail, UpdatesTransactionStatus $updatesTransactionStatus, DeletesGroup $deletesGroup, DeletesBillplzBill $deletesBillplzBill)
{
$this->fetchesOrder = $fetchesOrder;
$this->generatesTransactionBillNumber = $generatesTransactionBillNumber;
$this->fetchesTransaction = $fetchesTransaction;
$this->createsTransaction = $createsTransaction;
$this->createsTransactionDetail = $createsTransactionDetail;
$this->updatesTransaction = $updatesTransaction;
$this->updatesTransactionDetail = $updatesTransactionDetail;
$this->updatesTransactionStatus = $updatesTransactionStatus;
$this->deletesGroup = $deletesGroup;
$this->deletesBillplzBill = $deletesBillplzBill;
}
/**
* @throws MalformedRequestException
*/
public function execute(int $orderReference)
{
$order = $this->fetchesOrder->execute(['reference' => $orderReference, 'with_packing_lists' => true]);
return $this->executeOrder($order);
}
public function executeOrder(Order $order, bool $isBackDoorCheck = false){
$results = [];
$marking = $order->companyModule->inviters()->withPivot('invitee_reference')->first()->pivot->invitee_reference;
$is_credit_term = $order->companyModule->inviters()->withPivot('is_credit_term')->first()->pivot->is_credit_term;
if(!$is_credit_term){
Log::channel('storage_invoices')->info('orderId: '.$order->id.', orderReference: '.$order->reference.', marking: '.$marking.', is_credit_term: '.$is_credit_term);
$packingLists = $order->destinationWarehousePackages;
foreach ($packingLists as $packingList){
$arrivalDateAtChinaWarehouse = $this->getArrivalDateAtChinaWarehoue($packingList);
Log::channel('storage_invoices')->info('arrivalDateAtChinaWarehouse: '.json_encode($arrivalDateAtChinaWarehouse));
Log::channel('storage_invoices')->info('destinationWarehousePackage: '.json_encode($packingList));
$eta = $this->getEtaFromPackingList($packingList);
if($arrivalDateAtChinaWarehouse && $eta){
$transactions = $packingList->transactions()->where('transactions.type', TransactionType::SHIPPING_INVOICE)->whereIn('transactions.status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->get();
// $transactions = $destinationWarehousePackage->transactions()->where('transactions.type', TransactionType::SHIPPING_INVOICE)->where('transactions.status', ApprovalStatus::APPROVED)->get();
/** @var Transaction $invoice_transaction */
foreach ($transactions as $invoice_transaction){
$result = $this->processSingleTransactionOfTypeShippingInvoice($invoice_transaction, $packingList, $order->company_module_id, $eta, $isBackDoorCheck);
if($result){
$results[] = $result;
}
}
}
}
}
return $results;
}
private function getArrivalDateAtChinaWarehoue($packingList){
if($packingList->type === PackingListType::SHIPPING_PACKING_LIST){
$receive_packing_list = PackingList::where('reference', $packingList->reference)->where('type', PackingListType::WAREHOUSE_RECEIVE_LIST)->first();
Log::channel('storage_invoices')->info('receive_packing_list: '.json_encode($receive_packing_list->transports));
$transport = $receive_packing_list->transports->first();
if ($transport) {
$arrivalDateAtChinaWarehouse = Carbon::parse($transport->drop_date);
$dateToCompare = Carbon::parse(env('STORAGE_FEE_LAUNCH_DATE', '2023-12-11 00:00:00'));
// dd($dateToCompare);
if ($arrivalDateAtChinaWarehouse->isAfter($dateToCompare)) {
Log::channel('storage_invoices')->info('transport: '.json_encode($transport));
Log::channel('storage_invoices')->info('dateToCompare: '.$dateToCompare.', arrivalDateAtChinaWarehouse: '.$arrivalDateAtChinaWarehouse);
return $arrivalDateAtChinaWarehouse;
}
}
}
return null;
}
private function getEtaFromPackingList($packingList){
if ($packingList) {
$package = $packingList->packages->first();
if ($package) {
$container = $package->container()->first();
if ($container) {
$transport = $container->transports->first();
if ($transport) {
$schedule = $transport->schedules->last();
if ($schedule) {
return $schedule->eta;
}
}
}
}
}
return null;
}
private function processSingleTransactionOfTypeShippingInvoice($transaction, $destinationWarehousePackage, $company_module_id, $eta, $isBackDoorCheck){
$pricePerCBM = 3;
$resultNumberOfDaysFree = 10;
$dt1 = $eta->copy()->addDay()->startOfDay();
$resultStartDate = $dt1->format('Y-m-d');
$currentDatetime = Carbon::now();
$dt2 = $currentDatetime->copy()->addDay()->startOfDay();
$resultCurrentDate = $dt2->format('Y-m-d H:i:s');
$interval = Carbon::parse($dt2)->diff($dt1);
$resultNumberOfDaysExceeded = $interval->days - $resultNumberOfDaysFree;
$storageInvoice = $destinationWarehousePackage->transactions()->where('transactions.type', TransactionType::STORAGE_INVOICE)->first();
$storageInvoiceId = 0;
$transactionDetailsItems = $transaction->transactionDetails()->get();
$cbm = 0.00;
foreach ($transactionDetailsItems as $tdItem){
$quantity = $tdItem->quantity;
if($tdItem->price < 0.00){
$quantity = $quantity * -1;
}
$cbm = $cbm + $quantity;
}
$price_cbm = $pricePerCBM * $cbm * $resultNumberOfDaysExceeded;
Log::channel('storage_invoices')->info('storageInvoice: '.json_encode($storageInvoice).', $transaction->status: '.$transaction->status);
if(!$storageInvoice && $resultNumberOfDaysExceeded > 0 && $transaction->status != ApprovalStatus::COMPLETED){
Log::channel('storage_invoices')->info('Created $transaction->id: '.$transaction->id);
$billNumber = $this->generatesTransactionBillNumber->execute('STOR-');
$storageInvoice = $this->createStorageInvoiceTransaction($destinationWarehousePackage, $billNumber, $company_module_id, $price_cbm);
$storageInvoiceId = $storageInvoice->id;
$this->createStorageInvoiceTransactionDetails($storageInvoice, $destinationWarehousePackage, $cbm, $pricePerCBM, $resultNumberOfDaysExceeded);
}
else if($storageInvoice){
//Additional handling for calculation of numberOfDaysExceeded in the event of the storage already paid
$paymentStorageTransaction = $storageInvoice->transactions()->where('transactions.type', TransactionType::PAYMENT)->where('transactions.status', ApprovalStatus::APPROVED)->first();
if($paymentStorageTransaction){
$dateStorageInvoicePaid = $paymentStorageTransaction->created_at->copy()->addDay()->startOfDay();
Log::channel('storage_invoices')->info('dateStorageInvoicePaid: '.$dateStorageInvoicePaid.', resultCurrentDate: '.$resultCurrentDate);
$intervalRecalculate = Carbon::parse($dateStorageInvoicePaid)->diff($dt1);
$resultNumberOfDaysExceeded = $intervalRecalculate->days - $resultNumberOfDaysFree;
$price_cbm = $pricePerCBM * $cbm * $resultNumberOfDaysExceeded;
}
$amount = $storageInvoice->amount;
$epsilon = 0.0001; // Tolerance for the comparison
Log::channel('storage_invoices')->info('Update $transaction->id: '.$transaction->id);
Log::channel('storage_invoices')->info('$storageInvoice->status: '.$storageInvoice->status);
Log::channel('storage_invoices')->info('price_cbm: '.$price_cbm."-".gettype($price_cbm));
if(abs($price_cbm - $amount) > $epsilon && $storageInvoice->status !== ApprovalStatus::COMPLETED){
$paymentTransactions = $storageInvoice->transactions()->where('transactions.type', TransactionType::PAYMENT)->where('transactions.status', ApprovalStatus::PENDING_SUBMISSION)->get();
if(!$isBackDoorCheck){
if(count($paymentTransactions) > 0){
$this->updatePaymentTransactionViaNonGroupPayment($paymentTransactions);
}
else{
$this->updatePaymentTransactionViaGroupPayment($storageInvoice);
}
}
$storageInvoice = $this->updateStorageInvoiceTransaction($storageInvoice, $price_cbm);
$invoiceTransactionDetails = $storageInvoice->transactionDetails()->first();
$this->updateStorageInvoiceTransactionDetails($invoiceTransactionDetails, $destinationWarehousePackage, $cbm, $pricePerCBM, $resultNumberOfDaysExceeded);
}
$storageInvoiceId = $storageInvoice->id;
}
if($storageInvoiceId !== 0){
$result = [
'parentInvoiceId' => $transaction->id,
'storageInvoiceId' => $storageInvoiceId,
'numberOfDaysExceeded' => $resultNumberOfDaysExceeded,
'numberOfDaysFree' => $resultNumberOfDaysFree,
'startDate' => $resultStartDate,
'currentDate' => $resultCurrentDate,
'cbm' => $cbm,
'pricePerCBM' => $pricePerCBM,
'storageInvoice' => new TransactionResource($storageInvoice)
];
return $result;
}
}
private function updatePaymentTransactionViaGroupPayment($storageInvoice){
Log::channel('storage_invoices')->info('updatePaymentTransactionViaGroupPayment');
$groups = $storageInvoice->groups()->get();
foreach ($groups as $grp){
$groupReference = $grp->reference;
$walletTransaction = $this->fetchesTransaction->execute(['payment_reference' => $groupReference]);
if($walletTransaction->status === ApprovalStatus::PENDING_SUBMISSION || $walletTransaction->status === ApprovalStatus::PENDING_VERIFICATION){
$grp->status = ApprovalStatus::EXPIRED;
$grp->save();
$this->deletesGroup->execute($grp);
$this->updatesTransactionStatus->execute($walletTransaction, ApprovalStatus::EXPIRED);
if($walletTransaction->payment_reference){
$deletedBillplzBill = $this->deletesBillplzBill->execute($walletTransaction->payment_reference);
Log::channel('storage_invoices')->info('deletedBillplzBill TransactionType::WALLET: '.json_encode($deletedBillplzBill));
}
}
}
}
private function updatePaymentTransactionViaNonGroupPayment($paymentTransactions){
Log::channel('storage_invoices')->info('updatePaymentTransactionViaNonGroupPayment');
foreach ($paymentTransactions as $paymentTransaction){
$this->updatesTransactionStatus->execute($paymentTransaction, ApprovalStatus::EXPIRED);
if($paymentTransaction->payment_reference){
$deletedBillplzBill = $this->deletesBillplzBill->execute($paymentTransaction->payment_reference);
Log::channel('storage_invoices')->info('deletedBillplzBill TransactionType::WALLET: '.json_encode($deletedBillplzBill));
}
}
}
private function updateStorageInvoiceTransaction(Transaction $transaction, float $totalAmount){
$object = new TransactionObject(
$transaction->bill_no,
TransactionType::STORAGE_INVOICE,
1,
$transaction->receiver,
1,
PaymentMethodType::CASH,
$totalAmount,
$totalAmount,
1,
1,
0,
0,
0,
null,
ApprovalStatus::APPROVED
);
/** @var Transaction $invoice_transaction */
$invoice_transaction = $this->updatesTransaction->execute($transaction, $object);
return $invoice_transaction;
}
private function updateStorageInvoiceTransactionDetails($invoice_transaction_details, PackingList $packing_list, $cbm, $pricePerCBM, $numberOfDays){
$object_detail = new TransactionDetailObject(
'STORAGE_FEE',
TransactionDetailType::STORAGE_FEE.' for '.$numberOfDays. ' days * RM'.$pricePerCBM.'<br>'.round($packing_list->packages->where('type', '!=', PackageType::OVER_WEIGHT)->sum('quantity'), 3).' CTNS - '.round($cbm, 3).' CBM',
$cbm,
$pricePerCBM * $numberOfDays
);
$this->updatesTransactionDetail->execute($invoice_transaction_details, $object_detail);
}
private function createStorageInvoiceTransaction(PackingList $packing_list, string $billNumber, int $companyModuleId, float $totalAmount){
$object = new TransactionObject(
$billNumber,
TransactionType::STORAGE_INVOICE,
1,
$companyModuleId,
1,
PaymentMethodType::CASH,
$totalAmount,
$totalAmount,
1,
1,
0,
0,
0,
null,
ApprovalStatus::APPROVED
);
/** @var Transaction $invoice_transaction */
$invoice_transaction = $this->createsTransaction->execute($packing_list, $object);
return $invoice_transaction;
}
private function createStorageInvoiceTransactionDetails($invoice_transaction, PackingList $packing_list, $cbm, $pricePerCBM, $numberOfDays){
$object_detail = new TransactionDetailObject(
'STORAGE_FEE',
TransactionDetailType::STORAGE_FEE.' for '.$numberOfDays. ' days * RM'.$pricePerCBM.'<br>'.round($packing_list->packages->where('type', '!=', PackageType::OVER_WEIGHT)->sum('quantity'), 3).' CTNS - '.round($cbm, 3).' CBM',
$cbm,
$pricePerCBM * $numberOfDays
);
$this->createsTransactionDetail->execute($invoice_transaction, $object_detail);
}
}
@@ -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,79 @@
<?php
namespace App\Classes\Modules\Transactions\Processors;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Notifications\InvoiceIssuedEmail;
use App\Models\Document;
use App\Models\PackingList;
use App\Models\Transaction;
use Mccarlosen\LaravelMpdf\Facades\LaravelMpdf;
use App\Classes\ValueObjects\Constants\DocumentType;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\Modules\Documents\Services\CreatesFiles;
use App\Classes\Modules\Documents\Services\CreatesDocument;
use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
class CreateStorageInvoiceDocTransactionProcessor
{
/** @var UpdatesTransactionStatus */
private $updatesTransactionStatus;
/** @var CreatesDocument */
private $createsDocument;
/** @var CreatesFiles */
private $createsFiles;
/**
* @param UpdatesTransactionStatus $updatesTransactionStatus
* @param CreatesDocument $createsDocument
* @param CreatesFiles $createsFiles
*/
public function __construct(UpdatesTransactionStatus $updatesTransactionStatus, CreatesDocument $createsDocument, CreatesFiles $createsFiles)
{
$this->updatesTransactionStatus = $updatesTransactionStatus;
$this->createsDocument = $createsDocument;
$this->createsFiles = $createsFiles;
}
/**
* @throws MalformedRequestException
*/
public function execute(PackingList $packingList)
{
/** @var Transaction $invoice_transaction */
$invoice_transaction = $packingList->transactions()->where('transactions.type', TransactionType::STORAGE_INVOICE)->whereIn('status', [ApprovalStatus::COMPLETED])->first();
// $this->updatesTransactionStatus->execute($invoice_transaction, ApprovalStatus::APPROVED);
$transaction_invoice_pdf = LaravelMpdf::loadView('pages.pdfs.shipping_invoice', ['invoice_transaction' => $invoice_transaction]);
$document_object = new DocumentObject(
DocumentType::STORAGE_INVOICE,
[chunk_split('data:application/pdf;base64,'.base64_encode($transaction_invoice_pdf->output()))],
'',
ApprovalStatus::COMPLETED,
'storage_invoice'
);
$invouce_transaction_document = $invoice_transaction->documents()->where('document_type', DocumentType::STORAGE_INVOICE)->first();
if(!$invouce_transaction_document){
/** @var Document $document */
$document = $this->createsDocument->execute($invoice_transaction, $document_object);
$this->createsFiles->execute($document, $document_object);
$user = $packingList->owner->companyModule->employees()->first();
if(app()->environment(['production'])) {
$user->notify(new InvoiceIssuedEmail($user, $packingList));
}
}
}
}
@@ -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;
}
}
@@ -61,7 +61,7 @@ class CreateWalletTopUpTransactionProcessor
/**
* @throws MalformedRequestException
*/
public function execute(CompanyModule $companyModule, $amount, $bank_code, ?bool $groupTransaction = false)
public function execute(CompanyModule $companyModule, $amount, $bank_code, ?int $payment_method = PaymentMethodType::PAYMENT_GATEWAY, ?string $payment_reference = null, ?bool $groupTransaction = false)
{
/** @var Wallet $wallet */
$wallet = $companyModule->wallets()->first();
@@ -82,7 +82,9 @@ class CreateWalletTopUpTransactionProcessor
$billPlzBill = $this->createsBillplzBill->execute($companyModule->name, $user->email, 'This payment is credit topup for company ref. ' . $companyModule->reference, $amount, $billNumber, $bank_code, true);
// IF $groupTransaction, transaction type is GROUP_PAYMENT
$transaction_object = new TransactionObject($billNumber, $groupTransaction? TransactionType::GROUP_PAYMENT: TransactionType::TOP_UP, 1, $companyModule->id, 1, PaymentMethodType::PAYMENT_GATEWAY, $amount, $amount, 1, 1, 1, 0, 0, null, ApprovalStatus::PENDING_SUBMISSION, [], $billPlzBill->id);
// $transaction_object = new TransactionObject($billNumber, $groupTransaction? TransactionType::GROUP_PAYMENT: TransactionType::TOP_UP, 1, $companyModule->id, 1, PaymentMethodType::PAYMENT_GATEWAY, $amount, $amount, 1, 1, 1, 0, 0, null, ApprovalStatus::PENDING_SUBMISSION, [], $billPlzBill->id);
// no more group payment
$transaction_object = new TransactionObject($billNumber, TransactionType::TOP_UP, 1, $companyModule->id, 1, $payment_method, $amount, $amount, 1, 1, 1, 0, 0, null, ApprovalStatus::PENDING_SUBMISSION, [], $payment_method === PaymentMethodType::PAYMENT_GATEWAY ? $billPlzBill->id : $payment_reference);
$transaction = $this->createsTransactionableTransaction->execute($wallet, $transaction_object);
@@ -5,6 +5,8 @@ namespace App\Classes\Modules\Wallets\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Classes\General\Eloquent\AbstractUpdateRelationshipRecord;
use App\Classes\Modules\Wallets\DataTransferObjects\WalletObject;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Wallet;
use App\Models\Company;
@@ -16,10 +18,24 @@ class UpdatesWalletBalance extends AbstractUpdateRecord
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(Wallet $model, $amount) {
public function execute(Wallet $model, $amount)
{
$topups = 0;
$credit = 0;
$payments = 0;
$debit = 0;
$model->amount = $model->amount + $amount;
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;
}
$auditBalance = ($topups + $credit) - ($payments + $debit);
$model->amount = $auditBalance;
return $this->handler($model);
}
}
@@ -24,5 +24,6 @@ final class DocumentType {
public const SHIPPING_INVOICE = 'SHIPPING_INVOICE';
public const STORAGE_INVOICE = 'STORAGE_INVOICE';
}
@@ -11,4 +11,6 @@ final class TransactionDetailType {
public const MIN_CBM_CHARGES = 'Minimum Charge for 0.3 CBM Per Container';
public const CUSTOM_CHARGES = 'Custom charges';
public const STORAGE_FEE = 'Malaysia Warehouse Storage Fee';
}
@@ -5,9 +5,9 @@ namespace App\Classes\ValueObjects\Constants;
final class TransactionType {
// public const PAYMENT_ATTEMPT = 0;
public const SHIPPING_INVOICE = 1;
public const PAYMENT = 2;
// public const BILL = 3;
@@ -35,10 +35,11 @@ final class TransactionType {
// public const SHIPPING_COST = 14;
public const GROUP_PAYMENT = 15;
public const TRANSACTION_TYPE_ID = [
self::SHIPPING_INVOICE => "Shipping Invoice",
self::PAYMENT => "Payment",
];
public const STORAGE_INVOICE = 16;
}
@@ -0,0 +1,85 @@
<?php
namespace App\Console\Commands;
use App\Classes\Modules\Transactions\Services\ListsGroups;
use App\Classes\Modules\Transactions\Processors\CheckStorageInvoiceTransactionProcessor;
use App\Models\Order;
use Carbon\Carbon;
use Illuminate\Console\Command;
class CheckStorageInvoicesGroupTransactions extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'check-storage-invoices-group-transactions';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Check all storage invoices due to make sure that they are up to date daily, prevent \'back door\' cases';
/** @var ListsGroups */
private $listsGroups;
/** @var CheckStorageInvoiceTransactionProcessor */
private $storageInvoiceTransactionProcessor;
/**
* Create a new command instance.
*
* @return void
*/
public function __construct(ListsGroups $listsGroups, CheckStorageInvoiceTransactionProcessor $storageInvoiceTransactionProcessor)
{
parent::__construct();
$this->listsGroups = $listsGroups;
$this->storageInvoiceTransactionProcessor = $storageInvoiceTransactionProcessor;
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
ini_set('memory_limit', '-1');
$this->info(Carbon::now() . ': Start Check all pending group payment with storage invoice is valid.');
$start = new Carbon();
$newfilters['order_by_updated_at_desc'] = true;
$newfilters['status_in'] = [0, 1];
$groups = $this->listsGroups->execute($newfilters);
foreach ($groups as $group){
$this->info('CheckForStorageInvoiceByTransactions group: '.json_encode($group));
foreach ($group->groupTransactions as $groupTransaction) {
$invoice = $groupTransaction->transaction;
$packingList = $invoice->owner()->first();
if($packingList){
$order = $packingList->owner()->first();
if($order instanceof Order){
$storages = $this->storageInvoiceTransactionProcessor->executeOrder($order);
}
}
}
}
$end = new Carbon();
$elapsedTime = $start->diff($end)->format('%H:%I:%S');
$this->info(Carbon::now() . ': Done Check all pending group payment with storage invoice is valid. ElapsedTime: ' . $elapsedTime . '.');
}
}
@@ -0,0 +1,82 @@
<?php
namespace App\Console\Commands;
use App\Classes\Modules\Orders\Services\ListsOrders;
use App\Classes\Modules\Transactions\Processors\CheckStorageInvoiceTransactionProcessor;
use App\Classes\ValueObjects\Constants\OrderType;
use App\Models\Order;
use Carbon\Carbon;
use Illuminate\Console\Command;
class CheckStorageInvoicesOrders extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'check-storage-invoices-orders';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Check all storage invoices due to make sure that they are up to date daily, prevent \'back door\' cases';
/** @var ListsOrders */
private $listsOrders;
/** @var CheckStorageInvoiceTransactionProcessor */
private $storageInvoiceTransactionProcessor;
/**
* Create a new command instance.
*
* @return void
*/
public function __construct(ListsOrders $listsOrders, CheckStorageInvoiceTransactionProcessor $storageInvoiceTransactionProcessor)
{
parent::__construct();
$this->listsOrders = $listsOrders;
$this->storageInvoiceTransactionProcessor = $storageInvoiceTransactionProcessor;
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
ini_set('memory_limit', '-1');
$this->info(Carbon::now() . ': Start Check all orders for storage invoice.');
$start = new Carbon();
$orders = $this->listsOrders->execute(['with_parcels' => true, 'type_in' => [OrderType::SHARED_CONTAINER, OrderType::DEDICATED_CONTAINER]]);
$count = 0;
foreach ($orders as $order){
try{
$storages = $this->storageInvoiceTransactionProcessor->executeOrder($order);
$count = $count + 1;
$this->info('Order '.$count);
}
catch(\Exception $ex){
$this->info('Exception '.$ex->getMessage());
break;
}
}
$end = new Carbon();
$elapsedTime = $start->diff($end)->format('%H:%I:%S');
$this->info(Carbon::now() . ': Done Check all orders for storage invoice. ElapsedTime: ' . $elapsedTime . '.');
}
}
@@ -4,6 +4,7 @@ namespace App\Console\Commands;
use App\Classes\Exceptions\ResourceNotFoundException;
use App\Classes\Modules\Billplzs\DataTransferObjects\BillplzXSignatureObject;
use App\Classes\Modules\Billplzs\Processors\CallbackBillplzProcessor;
use App\Classes\Modules\Billplzs\Services\GetBillplzBill;
use App\Classes\Modules\Orders\Processors\UpdateDoFromVTPortalProcessor;
use App\Classes\Modules\Orders\Processors\UpdateDoFromYDPortalProcessor;
@@ -53,12 +54,15 @@ class FixBillplzFailedCallbackPayment extends Command
/** @var UpdateDoFromYDPortalProcessor */
private $updateDoFromYDPortalProcessor ;
/** @var CallbackBillplzProcessor */
private $callbackBillplzProcessor;
/**
* Create a new command instance.
*
* @return void
*/
public function __construct(GetBillplzBill $getBillplzBill, FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, UpdateDoFromVTPortalProcessor $updateDoFromVTPortalProcessor, UpdateDoFromYDPortalProcessor $updateDoFromYDPortalProcessor)
public function __construct(GetBillplzBill $getBillplzBill, FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, UpdateDoFromVTPortalProcessor $updateDoFromVTPortalProcessor, UpdateDoFromYDPortalProcessor $updateDoFromYDPortalProcessor, CallbackBillplzProcessor $callbackBillplzProcessor)
{
parent::__construct();
$this->getBillplzBill = $getBillplzBill;
@@ -66,6 +70,7 @@ class FixBillplzFailedCallbackPayment extends Command
$this->updatesTransactionStatus = $updatesTransactionStatus;
$this->updateDoFromVTPortalProcessor = $updateDoFromVTPortalProcessor;
$this->updateDoFromYDPortalProcessor = $updateDoFromYDPortalProcessor;
$this->callbackBillplzProcessor = $callbackBillplzProcessor;
}
/**
@@ -82,7 +87,7 @@ class FixBillplzFailedCallbackPayment extends Command
$approvalStatusArray = ApprovalStatus::APPROVAL_STATUS_ID;
$transactions = Transaction::whereIn('type', [TransactionType::PAYMENT, TransactionType::TOP_UP])->where('payment_method', PaymentMethodType::PAYMENT_GATEWAY)->whereNotIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->get();
$transactions = Transaction::whereIn('type', [TransactionType::PAYMENT, TransactionType::TOP_UP, TransactionType::GROUP_PAYMENT])->where('payment_method', PaymentMethodType::PAYMENT_GATEWAY)->whereNotIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->get();
$totalTransactions = count($transactions);
if ($totalTransactions) {
@@ -96,84 +101,15 @@ class FixBillplzFailedCallbackPayment extends Command
if($response->successful()){
$data = $response->json();
if($data['paid']){
$totalAmount += $transaction->amount;
$invoiceStatus = null;
if($data['paid']) {
$status = ApprovalStatus::PENDING_VERIFICATION;
switch($transaction->owner->status) {
case 3:
$invoiceStatus = 'Payment Completed';
break;
case 5:
$invoiceStatus = 'Dispute in progress';
break;
case 6:
$invoiceStatus = 'Cancelled Invoice';
break;
default:
$invoiceStatus = 'Pending Payment';
if($data['state'] === 'paid') {
$status = ApprovalStatus::APPROVED;
}
$order = $transaction->owner->owner->owner;
if (in_array($invoiceStatus , ['Pending Payment', 'Payment Completed'])) {
// code here
// $billPlz = $this->getBillplzBill->execute($billplzXSignatureObject->getBillPlzId());
// if(!$billPlz) throw new ResourceNotFoundException('Billplz bill not found.');
// $transaction = $this->fetchesTransaction->execute(['payment_reference' => $billplzXSignatureObject->getBillPlzId()]);
$invoice = $transaction->owner;
$packingList = $invoice->owner;
$order = $packingList->owner;
$status = ApprovalStatus::PENDING_VERIFICATION;
if($data['state'] === 'paid') {
$status = ApprovalStatus::APPROVED;
}
// if($data->state === 'due') {
// $status = $billplzXSignatureObject->getStatus() === 'failed' ? ApprovalStatus::REJECTED : ApprovalStatus::PENDING_VERIFICATION;
// }
// $token = Auth::fromUser(User::find(1));
// $request->headers->set('Authorization', 'Bearer '.$token);
$this->updatesTransactionStatus->execute($transaction, $status);
$totalPaidAmount = $invoice->transactions->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->sum('amount');
if(($invoice->amount - $totalPaidAmount) < 0.01) {
$this->updatesTransactionStatus->execute($invoice, ApprovalStatus::COMPLETED);
$packingList->status = ApprovalStatus::APPROVED;
$packingList->save();
if(app()->environment('production')){
$this->updateDoFromVTPortalProcessor->execute($packingList);
$this->updateDoFromYDPortalProcessor->execute($packingList);
}
$this->info('Updated invoice ' . $counter . ' of ' . $totalTransactions . '. Order: '. $order->reference . ' - Date: '.$transaction->owner->created_at->format('d-m-Y').' - Amount: '. $transaction->amount . '. Status: ' . $approvalStatusArray[$transaction->status] . '. Invoice Status: ' . $invoiceStatus);
} else {
$this->info('Failed to update invoice due to unsufficeint payment ' . $counter . ' of ' . $totalTransactions . '. Order: '. $order->reference . ' - Date: '.$transaction->owner->created_at->format('d-m-Y').' - Amount: '. $transaction->amount . '. Status: ' . $approvalStatusArray[$transaction->status] . '. Invoice Status: ' . $invoiceStatus);
}
} else {
if(!$order instanceof Order) {
$this->info("Error transaction id:" . $transaction->id . 'Type: ' . get_class($order));
} else {
$this->info($counter . ' of ' . $totalTransactions . '. Order: '. $order->reference . ' - Date: '.$transaction->owner->created_at->format('d-m-Y').' - Amount: '. $transaction->amount . '. Status: ' . $approvalStatusArray[$transaction->status] . '. Invoice Status: ' . $invoiceStatus);
}
}
} else {
// $totalAmount += $transaction->amount;
// $this->appendToOutput($counter . ' of ' . $totalTransactions . '. Order: '. $transaction->owner->owner->owner->reference . ' - Date: '.$transaction->owner->created_at->format('d-m-Y').' - Amount: '. $transaction->amount);
$this->info(Carbon::now() . ' : Fixing ' . $transaction->payment_reference);
$this->callbackBillplzProcessor->execute($transaction, $status);
}
}else{
$this->info("billplz error</br>");
@@ -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,84 @@
<?php
namespace App\Console\Commands;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Transaction;
use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Http;
class ShowFailediBllplzCallback extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'show-failed-billplz-callback';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Show all failled callback from billplz';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
ini_set('memory_limit', '-1');
$start = new Carbon();
$transactions = Transaction::whereIn('type', [TransactionType::PAYMENT, TransactionType::TOP_UP, TransactionType::GROUP_PAYMENT])->where('payment_method', PaymentMethodType::PAYMENT_GATEWAY)->whereNotIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->get();
$totalTransactions = count($transactions);
if ($totalTransactions) {
$this->info(Carbon::now() . ' : ' . $this->description);
}
$counter = 1;
$totalAmount = 0;
foreach ($transactions as $transaction){
$response = Http::withBasicAuth(config('billplz.api_key').':', '')->get(config('billplz.base_url').'/api/v3/bills/'.$transaction->payment_reference);
if($response->successful()){
$data = $response->json();
if($data['paid']){
dump($transaction->payment_reference);
dump($transaction->id);
}
}else{
$this->info("billplz error</br>");
}
$counter++;
}
$end = new Carbon();
$elapsedTime = $start->diff($end)->format('%H:%I:%S');
if ($totalTransactions) {
$this->info(Carbon::now() . ' : Done Billplz Failled Callback. ElapsedTime: ' . $elapsedTime . '. Total: ' . $totalAmount);
}
}
}
+5
View File
@@ -62,6 +62,11 @@ class Kernel extends ConsoleKernel
->hourly()
->withoutOverlapping()
->appendOutputTo (storage_path().'/logs/fix_failed_callback_from_billplz.log');
$schedule->command('check-storage-invoices-group-transactions')
->dailyAt('0:01')
->withoutOverlapping()
->appendOutputTo(storage_path().'/logs/check_storage_invoices.log');
}
/**
@@ -9,6 +9,7 @@ use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Maatwebsite\Excel\Excel;
use App\Classes\Modules\Exports\Services\ExportsAgingList;
class ExportArrivedParcelController
{
@@ -46,4 +47,11 @@ class ExportArrivedParcelController
ob_end_clean();
return $response;
}
public function aging(Request $request) {
$data = new ExportsAgingList();
$response = $data->download('aging_report.xls', Excel::XLS, ['Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']);
ob_end_clean();
return $response;
}
}
@@ -0,0 +1,36 @@
<?php
namespace App\Http\Controllers\Exports;
use App\Classes\Modules\Exports\Services\ExportsCustomersWalletTransactionHistory;
use App\Models\User;
use App\Models\Wallet;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Maatwebsite\Excel\Excel;
class ExportCustomersWalletTransactionToExcelController
{
/**
* ExportCustomersWalletTransactionToExcelController constructor.
* @param Request $request
*/
public function __construct(Request $request)
{
$token = Auth::fromUser(User::find(1));
$request->headers->set('Authorization', 'Bearer ' . $token);
}
public function export(Request $request)
{
$exportsTransactions = new ExportsCustomersWalletTransactionHistory($request);
$wallet = Wallet::find($request->route('wallet_id'));
$company_marking = $wallet->owner->connections->first()->invitee_reference;
$filename = $company_marking . '-wallet-' . ($request->route('is_precise') == 'true' ? 'precise-' : '') . 'transaction-history.xls';
$response = $exportsTransactions->download($filename, Excel::XLS, ['Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']);
ob_end_clean();
return $response;
}
}
@@ -0,0 +1,21 @@
<?php
namespace App\Http\Controllers\Transactions;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use App\Classes\Modules\Transactions\ControllersLogic\DeletePaymentTransactionLogic;
class DeletePaymentTransactionController
{
/**
* @param Request $request
* @param DeletePaymentTransactionLogic $logic
* @return JsonResponse
*/
public function delete(Request $request, DeletePaymentTransactionLogic $logic) : JsonResponse {
return $logic->execute($request);
}
}
@@ -0,0 +1,21 @@
<?php
namespace App\Http\Controllers\Transactions;
use App\Classes\Modules\Transactions\ControllersLogic\ListWalletTransactionsLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class ListWalletTransactionsController
{
/**
* @param Request $request
* @param ListWalletTransactionsLogic $logic
* @return JsonResponse
*/
public function list(Request $request, ListWalletTransactionsLogic $logic) : JsonResponse {
return $logic->execute($request);
}
}
@@ -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);
}
}
+5
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' => [
@@ -70,5 +72,8 @@ class Kernel extends HttpKernel
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'valid.token' => ValidateToken::class,
'token.check' => \App\Http\Middleware\TokenCheckerMiddleware::class,
'storage.invoice.check.byorder' => \App\Http\Middleware\CheckForStorageInvoiceByOrderId::class,
'storage.invoice.check.bytransactions' => \App\Http\Middleware\CheckForStorageInvoiceByTransactions::class,
'storage.invoice.check.bygroup' => \App\Http\Middleware\CheckForStorageInvoiceByGroup::class,
];
}
@@ -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,64 @@
<?php
namespace App\Http\Middleware;
use Closure;
use App\Classes\Modules\Transactions\Processors\CheckStorageInvoiceTransactionProcessor;
use App\Classes\Modules\Transactions\Services\ListsGroups;
use App\Models\Order;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
class CheckForStorageInvoiceByGroup
{
/** @var CheckStorageInvoiceTransactionProcessor */
private $storageInvoiceTransactionProcessor;
/** @var ListsGroups */
private $listsGroups;
public function __construct(CheckStorageInvoiceTransactionProcessor $storageInvoiceTransactionProcessor, ListsGroups $listsGroups)
{
$this->storageInvoiceTransactionProcessor = $storageInvoiceTransactionProcessor;
$this->listsGroups = $listsGroups;
}
/**
* Handle an incoming request.
*
* @param Request $request
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
public function handle(Request $request, Closure $next)
{
// :options="{'per_page': 10, order_by: {column: 'id', DESC: true}, 'status_in': [0, 1], 'receiver': company_module_id, order_by: {column: 'updated_at', DESC: true}}"
$filters = json_decode($request->input('filters'), true);
if(json_encode($filters['order_by']) == '{"column":"updated_at","DESC":true}'){
$filters['order_by_updated_at_desc'] = true;
}
unset($filters['order_by']);
$groups = $this->listsGroups->execute($filters);
if(isset($filters['check_for_storage_invoice'])){
foreach ($groups as $group){
foreach ($group->groupTransactions as $groupTransaction) {
$invoice = $groupTransaction->transaction;
$packingList = $invoice->owner()->first();
if($packingList){
$order = $packingList->owner()->first();
if($order instanceof Order){
$storages = $this->storageInvoiceTransactionProcessor->executeOrder($order);
}
}
}
}
}
return $next($request);
}
}
@@ -0,0 +1,36 @@
<?php
namespace App\Http\Middleware;
use Closure;
use App\Classes\Modules\Transactions\Processors\CheckStorageInvoiceTransactionProcessor;
use Illuminate\Http\Request;
class CheckForStorageInvoiceByOrderId
{
/** @var CheckStorageInvoiceTransactionProcessor */
private $storageInvoiceTransactionProcessor;
public function __construct(CheckStorageInvoiceTransactionProcessor $storageInvoiceTransactionProcessor)
{
$this->storageInvoiceTransactionProcessor = $storageInvoiceTransactionProcessor;
}
/**
* Handle an incoming request.
*
* @param Request $request
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
public function handle(Request $request, Closure $next)
{
$orderId = $request->route('id');
$storages = $this->storageInvoiceTransactionProcessor->execute($orderId);
$request->merge(['storages' => $storages]);
return $next($request);
}
}
@@ -0,0 +1,96 @@
<?php
namespace App\Http\Middleware;
use Closure;
use App\Classes\Modules\Transactions\Processors\CheckStorageInvoiceTransactionProcessor;
use App\Classes\Modules\Transactions\Services\ListsTransactions;
use App\Classes\Modules\Transactions\Services\ListsGroups;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\CompanyConnection;
use App\Models\Order;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
class CheckForStorageInvoiceByTransactions
{
/** @var CheckStorageInvoiceTransactionProcessor */
private $storageInvoiceTransactionProcessor;
/** @var ListsTransactions */
private $listsTransactions;
/** @var ListsGroups */
private $listsGroups;
public function __construct(CheckStorageInvoiceTransactionProcessor $storageInvoiceTransactionProcessor, ListsTransactions $listsTransactions, ListsGroups $listsGroups)
{
$this->storageInvoiceTransactionProcessor = $storageInvoiceTransactionProcessor;
$this->listsTransactions = $listsTransactions;
$this->listsGroups = $listsGroups;
}
/**
* Handle an incoming request.
*
* @param Request $request
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
public function handle(Request $request, Closure $next)
{
$results = [];
$transactions = null;
$marking = $request->route('marking');
if($marking){ //for web route /customer/{marking}/payment-and-billing
$connection = CompanyConnection::where('invitee_reference', $marking)->first();
$company_module_id = $connection->invitee->id;
$filters = [
'per_page' => 999,
'status_in' => [2],
'receiver' => $company_module_id,
'type_in' => [TransactionType::SHIPPING_INVOICE]
];
$transactions = $this->listsTransactions->execute($filters);
}
else{ //for api route /transactions/list
$filters = json_decode($request->input('filters'), true);
$filters['type_in'] = [TransactionType::SHIPPING_INVOICE];
if(json_encode($filters['order_by']) == '{"column":"id","DESC":true}'){
$filters['order_by_id_desc'] = true;
}
unset($filters['order_by']);
$transactions = $this->listsTransactions->execute($filters);
}
if(isset($filters['check_for_storage_invoice'])){
foreach($transactions as $transaction){
$packingList = $transaction->owner()->first();
if($packingList){
$order = $packingList->owner()->first();
if($order instanceof Order){
$storages = $this->storageInvoiceTransactionProcessor->executeOrder($order);
if($storages){
$results = array_merge($results, $storages);
}
}
}
}
}
$filteredResults = array_values(array_filter($results, function($item, $key) {
static $seen = array();
$hash = md5($item['parentInvoiceId'] . $item['storageInvoiceId']);
return !isset($seen[$hash]) && ($seen[$hash] = true);
}, ARRAY_FILTER_USE_BOTH));
$request->merge(['storages' => $filteredResults]);
return $next($request);
}
}
@@ -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;
}
}
@@ -0,0 +1,39 @@
<?php
namespace App\Http\Resources;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use Carbon\Carbon;
use Illuminate\Http\Resources\Json\JsonResource;
class GroupForOrderV2Resource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'original_amount' => (float) $this->original_amount,
'original_currency' => new CurrencyResource($this->original_currency),
'issuer_name' => $this->issuerCompany->name,
'issuer_id' => $this->issuerCompany->id,
'amount' => (float) $this->amount,
'service_charge' => (float) $this->amount,
'currency' => new CurrencyResource($this->currency),
'created_at' => Carbon::parse($this->created_at)->format('d-m-Y h:i:s A'),
'currency_rate' => (float) $this->currency_rate,
'status' => $this->status,
'status_name' => ApprovalStatus::APPROVAL_STATUS_ID[$this->status],
'payment_method' => (int)$this->payment_method,
'payment_method_name' => ucwords(PaymentMethodType::PAYMENT_METHODS_ID[$this->payment_method]),
'payment_reference' => $this->reference,
'transactions_ids' => GroupTransactionsForOrderV2Resource::collection($this->groupTransactions)
];
}
}
+8
View File
@@ -4,6 +4,7 @@ namespace App\Http\Resources;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Models\Transaction;
use Carbon\Carbon;
use Illuminate\Http\Resources\Json\JsonResource;
@@ -19,6 +20,7 @@ class GroupResource extends JsonResource
{
// dd($this->groupTransactions);
$payment_transaction = Transaction::where('payment_reference', $this->reference)->first();
return [
'id' => $this->id,
@@ -37,6 +39,12 @@ class GroupResource extends JsonResource
'payment_method_name' => ucwords(PaymentMethodType::PAYMENT_METHODS_ID[$this->payment_method]),
'invoices' => GroupTransactionResource::collection($this->groupTransactions),
'reference' => $this->reference,
'payment_transaction' => $payment_transaction ? [
'id' => $payment_transaction->id,
'status' => $payment_transaction->status,
'status_name' => ApprovalStatus::APPROVAL_STATUS_ID[$payment_transaction->status],
'documents' => $this->status === ApprovalStatus::APPROVED ? DocumentResource::collection($payment_transaction->documents->where('status', ApprovalStatus::APPROVED)) : DocumentResource::collection($payment_transaction->documents->where('status', ApprovalStatus::PENDING_VERIFICATION)),
] : []
];
}
}
@@ -0,0 +1,23 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class GroupTransactionsForOrderV2Resource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
// 'id' => $this->id,
'group_id' => $this->group_id,
'transaction_id' => $this->transaction_id,
];
}
}
@@ -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,
+2 -1
View File
@@ -31,8 +31,9 @@ class OrderV2Resource extends JsonResource
'address' => new AddressResource($this->addresses()->where('status', '=', ApprovalStatus::APPROVED)->first()),
'address_change_request' => new AddressResource($this->addressesPendingVerification()->first()),
'invoices' => $this->whenLoaded('packingLists', function() {
return TransactionResource::collection($this->transactions()->whereNotIn('transactions.status', [0, 1])->where('transactions.type', TransactionType::SHIPPING_INVOICE)->get());
return TransactionResource::collection($this->transactions()->whereNotIn('transactions.status', [0, 1])->whereIn('transactions.type', [TransactionType::SHIPPING_INVOICE, TransactionType::STORAGE_INVOICE])->get());
}),
'storages' => $this->storages ? $this->storages : null, //from middleware
'remarks' => RemarkResource::collection($this->remarks),
'created_at' => $this->created_at->format('d-m-Y')
];
+44 -4
View File
@@ -3,13 +3,14 @@
namespace App\Http\Resources;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\DocumentType;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Order;
use App\Models\Group;
use App\Models\Transaction;
use App\Models\Wallet;
use Carbon\Carbon;
use Illuminate\Http\Resources\Json\JsonResource;
class TransactionResource extends JsonResource
{
/**
@@ -20,11 +21,44 @@ class TransactionResource extends JsonResource
*/
public function toArray($request)
{
$order = null;
$groupTransactions = null;
$group_payment_attempts = null;
$group_payment_expired = null;
if ($this->owner instanceof Transaction) {
if ($this->owner) {
if ($this->owner->owner) {
$order = new OrderResource($this->owner->owner->owner);
}
}
} else if (!($this->owner instanceof Transaction) && !($this->owner instanceof Wallet)) {
if ($this->owner) {
$order = new OrderResource($this->owner->owner);
}
if($this->groups){
$group_payment_attempts = GroupForOrderV2Resource::collection($this->groups->whereNotIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]));
$group_payment_expired = GroupForOrderV2Resource::collection($this->groupsWithTrashed->whereIn('status', [ApprovalStatus::EXPIRED]));
}
} else {
$group = Group::where('reference', $this->payment_reference)->first();
if ($group) {
$groupTransactions = GroupTransactionResource::collection($group->groupTransactions);
}
}
return [
'id' => $this->id,
'owner_type' => $this->owner_type,
'order' => ($this->owner instanceof Transaction) ? new OrderResource($this->owner->owner->owner) : new OrderResource($this->owner->owner),
'documents' => DocumentResource::collection($this->documents),
'order' => $order,
'group_transactions' => $groupTransactions,
'group_reference' => $groupTransactions ? ($group ? $group->reference : null ) : null,
'groups_payment_attempts' => $group_payment_attempts,
'groups_payment_expired' => $group_payment_expired,
'documents' => $groupTransactions ? DocumentResource::collection($this->documents->where('status', ApprovalStatus::PENDING_VERIFICATION)) : DocumentResource::collection($this->documents),
'type' => (int) $this->type,
'bill_no' => $this->bill_no,
'amount' => (double) $this->amount,
@@ -46,6 +80,11 @@ class TransactionResource extends JsonResource
->payments()->where('status', ApprovalStatus::PENDING_SUBMISSION)
->get()
),
'payments_expired' => TransactionResource::collection(
$this->transactions()
->payments()->where('status', ApprovalStatus::EXPIRED)
->get()
),
'payment_history' => TransactionResource::collection(
$this->transactions()
->payments()
@@ -53,6 +92,7 @@ class TransactionResource extends JsonResource
->get()
),
'remarks' => RemarkResource::collection($this->remarks),
'storages' => $this->storages ? $this->storages : null, //from middleware
'expires_on' => Carbon::parse($this->expires_on)->format('d-m-Y h:s:i'),
'updated_at' => Carbon::parse($this->updated_at)->format('d-m-Y'),
'created_at' => Carbon::parse($this->created_at)->format('d-m-Y')
+1 -1
View File
@@ -23,7 +23,7 @@ class WalletResource extends JsonResource
'amount' => (double) $this->amount,
'company_id' => (int) $this->owner->id,
'transactions' => $this->whenLoaded('transactions', WalletTransactionResource::collection($this->transactions()->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->orderBy('id', 'DESC')->get()), []),
'top_up_records' => $this->whenLoaded('transactions', WalletTransactionResource::collection($this->transactions()->whereIn('type', [TransactionType::TOP_UP])->orderBy('id', 'DESC')->get()), []),
'top_up_records' => $this->whenLoaded('transactions', WalletTransactionResource::collection($this->transactions()->whereIn('type', [TransactionType::TOP_UP, TransactionType::GROUP_PAYMENT])->orderBy('id', 'DESC')->get()), []),
'company_module_marking' => $this->owner->connections->first()->invitee_reference,
];
}
@@ -20,28 +20,41 @@ class WalletTransactionResource extends JsonResource
public function toArray($request)
{
$description = '';
$current_running_balance = $request['running_balance'];
switch((int) $this->type){
case TransactionType::TOP_UP:
$description = (double) $this->amount.' Credit Top up';
$request['running_balance'] = bcsub($request['running_balance'], $this->amount, 5);
break;
case TransactionType::CREDIT_NOTE:
$description = 'Credit Voucher for '.$this->payment_reference;
$request['running_balance'] = bcsub($request['running_balance'], $this->amount, 5);
break;
case TransactionType::PAYMENT:
$order = Transaction::where('payment_reference', $this->bill_no)->first()->owner->owner->owner;
$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;
}
$request['running_balance'] = bcadd($request['running_balance'], $this->amount, 5);
$marking = $order->reference;
$description = 'Payment For order refs.'.'<a href="'.route('order.details', $marking).'">'.$marking.'</a>';
break;
case 11:
$request['running_balance'] = bcadd($request['running_balance'], $this->amount, 5);
$description = 'Debit Voucher for '.$this->payment_reference;
break;
case 15:
$request['running_balance'] = bcsub($request['running_balance'], $this->amount, 5);
$description = (double) $this->amount.' Credit Top up';
break;
@@ -56,6 +69,7 @@ class WalletTransactionResource extends JsonResource
'payment_method' => (float) $this->payment_method,
// 'issuer_name' => $this->issuerCompany->name,
'amount' => (double) $this->amount,
'running_balance' => (double) $current_running_balance,
'service_charge' => (double) $this->service_charge,
'tax' => (double) $this->tax,
'status' => (int) $this->status,
+2
View File
@@ -4,10 +4,12 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\SoftDeletes;
class GroupTransaction extends Model
{
protected $table = 'group_transactions';
use SoftDeletes;
/**
* @return BelongsTo
+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');
}
}
+9 -1
View File
@@ -89,6 +89,14 @@ class Transaction extends AbstractModel implements Documentable, Transactionable
return $this->BelongsToMany(Group::class, GroupTransaction::class, 'transaction_id');
}
/**
* @return BelongsToMany
*/
public function groupsWithTrashed(): BelongsToMany
{
return $this->BelongsToMany(Group::class, GroupTransaction::class, 'transaction_id')->withTrashed();;
}
public function convert_original_amount()
{
if($this->booking()->first()->fix_currency_id !== 1) {
@@ -105,7 +113,7 @@ class Transaction extends AbstractModel implements Documentable, Transactionable
*/
public function scopePayments(Builder $query)
{
return $query->where('type', TransactionType::PAYMENT);
return $query->whereIn('type', [TransactionType::PAYMENT, TransactionType::TOP_UP]);
}
/**

Some files were not shown because too many files have changed in this diff Show More