Compare commits

..

129 Commits

Author SHA1 Message Date
edmondlang 1110838e35 Merge branch 'master' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into permits-reminder 2024-02-06 10:55:32 +08:00
edmondlang 9d87987488 code update - permits reminder - send email only at production 2024-02-06 10:55:19 +08:00
Omair Saleh 4c0984c9b8 fix container reschedule component 2024-02-05 15:08:51 +08:00
Omair Saleh 5517f16684 fix container reschedule component 2024-02-05 13:24:25 +08:00
Omair Saleh 4b967981dd fix container reschedule component 2024-02-05 12:56:30 +08:00
Omair Saleh e63b959714 fix container reschedule component 2024-02-05 12:52:07 +08:00
Omair Saleh a1751f274d Merge remote-tracking branch 'origin/master' 2024-02-05 12:48:54 +08:00
Omair Saleh ef6538feca fix container reschedule component 2024-02-05 12:47:51 +08:00
edmondlang de61d9a9fd add anitha email for premits reminder 2024-01-30 12:41:51 +08:00
edmondlang 2c1b857255 update permits reminder view 2024-01-30 12:37:34 +08:00
edmondlang 5b4a3507a3 add cron job to send permits reminder at daily 9.30 am 2024-01-30 00:48:23 +08:00
edmondlang 3d6543e467 add sample file 2024-01-30 00:42:21 +08:00
edmondlang 006a327a5f Merge branch 'master' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into permits-reminder 2024-01-30 00:34:51 +08:00
edmondlang 295e6454b1 add cron job command to send permits reminder 2024-01-30 00:34:39 +08:00
edmondlang f389efa6af add permits edit 2024-01-30 00:07:31 +08:00
Dillon Ngo 4ea3132334 Merge branch 'dillon/51.3-vue-polling-experimental' into 'master'
Vue Polling - Solve a problem where query of packing list with contaienrs and...

See merge request CIEFWorldwideSdnBhd/shipping-portal!197
2024-01-25 19:19:45 +00:00
Dillon Ngo 8fc3ac1b55 Vue Polling - Solve a problem where query of packing list with contaienrs and packages data is taking too long to complete 2024-01-26 03:18:58 +08:00
Dillon Ngo ed252e630b Merge branch 'dillon/51.3-vue-polling-experimental' into 'master'
Vue Polling - Solve a problem where query of packing list with contaienrs and...

See merge request CIEFWorldwideSdnBhd/shipping-portal!196
2024-01-25 18:21:17 +00:00
Dillon Ngo b6c9c8843d Vue Polling - Solve a problem where query of packing list with contaienrs and packages data is taking too long to complete 2024-01-26 02:19:31 +08:00
Dillon Ngo d80e996d02 Merge branch 'dillon/46.4-warehouse-storage-charges' into 'master'
Implement a solution to selectively waived a selected storage invoice

See merge request CIEFWorldwideSdnBhd/shipping-portal!195
2024-01-25 13:47:10 +00:00
Dillon Ngo 064ee3e41a Implement a solution to selectively waived a selected storage invoice 2024-01-24 06:50:18 +08:00
Dillon Ngo 3bda84dac5 Merge branch 'dillon/51.3-vue-polling-experimental' into 'master'
Vue Polling - Solve a problem where query of packing list with contaienrs and...

See merge request CIEFWorldwideSdnBhd/shipping-portal!194
2024-01-21 14:49:24 +00:00
Dillon Ngo e2b378e197 Vue Polling - Solve a problem where query of packing list with contaienrs and packages data is taking too long to complete 2024-01-21 22:48:48 +08:00
Dillon Ngo 0f2e1297e1 Merge branch 'dillon/51.3-vue-polling-experimental' into 'master'
Vue Polling - Solve a problem where query of packing list with contaienrs and...

See merge request CIEFWorldwideSdnBhd/shipping-portal!193
2024-01-21 14:35:45 +00:00
Dillon Ngo d034a285fc Vue Polling - Solve a problem where query of packing list with contaienrs and packages data is taking too long to complete 2024-01-21 22:31:16 +08:00
Dillon Ngo ee94943d00 Merge branch 'dillon/51.3-vue-polling-experimental' into 'master'
Experimental solution (Vue Polling) to solve an AWS API Gateway problem limitation for Laravel Vapor in the event of a emergency rollback to Google

See merge request CIEFWorldwideSdnBhd/shipping-portal!192
2024-01-21 02:54:47 +00:00
Dillon Ngo a9e89a45bd Experimental solution (Vue Polling) to solve an AWS API Gateway problem limitation for Laravel Vapor in the event of a emergency rollback to Google 2024-01-21 10:53:23 +08:00
Dillon Ngo f6b10b5763 Merge branch 'dillon/51.3-vue-polling-experimental' into 'master'
Experimental solution (Vue Polling) to solve an AWS API Gateway problem limitation for Laravel Vapor in the event of a emergency rollback to Google

See merge request CIEFWorldwideSdnBhd/shipping-portal!191
2024-01-21 02:32:55 +00:00
Dillon Ngo 9b9057ea81 Experimental solution (Vue Polling) to solve an AWS API Gateway problem limitation for Laravel Vapor in the event of a emergency rollback to Google 2024-01-21 10:31:39 +08:00
Dillon Ngo 33d2d02cb0 Merge branch 'dillon/51-vue-polling-experimental-2' into 'master'
Undo Experimental solution (Vue Polling)

See merge request CIEFWorldwideSdnBhd/shipping-portal!190
2024-01-20 19:16:33 +00:00
Dillon Ngo e5be6eaceb Undo Experimental solution (Vue Polling) 2024-01-21 03:15:46 +08:00
edmondlang a545e6bad6 add bill_no in transaction details page 2024-01-17 17:19:37 +08:00
edmondlang b64b25ff05 code update 2024-01-17 17:06:31 +08:00
edmondlang d1426c7f05 all api and ui to create permits reminder 2024-01-17 00:43:17 +08:00
edmondlang 3375934651 Merge branch 'master' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into permits-reminder
# Conflicts:
#	routes/api.php
2024-01-16 21:16:11 +08:00
edmondlang c79f58d246 permits reminder first commit 2024-01-16 21:15:29 +08:00
Dillon Ngo ee17ac0b0c Merge branch 'dillon/51-vue-polling-experimental-2' into 'master'
Experimental solution (Vue Polling) to solve an AWS API Gateway problem limitation for Laravel Vapor in the event of a emergency rollback to Google

See merge request CIEFWorldwideSdnBhd/shipping-portal!189
2024-01-15 16:43:45 +00:00
Dillon Ngo 26742a7335 Merge branch 'dillon/46.3.1-warehouse-storage-charges-fixes' into 'master'
Fix a problem with manual payment options not available when paying for invoices with warehouse storage charges

See merge request CIEFWorldwideSdnBhd/shipping-portal!188
2024-01-15 16:28:47 +00:00
Dillon Ngo 0e822ff1dd UI/UX amendment for order page when paying with storage invoice 2024-01-15 08:38:13 +08:00
Dillon Ngo 085b8b349f UI/UX amendment for order page when paying with storage invoice 2024-01-15 06:41:41 +08:00
edmondlang c1164397e8 fix errors diplaying in console in settings - warehouse 2024-01-14 22:56:45 +08:00
Dillon Ngo 3c16253795 Fix manual payment not showing in single order page when storage invoice is present 2024-01-14 09:33:31 +08:00
edmondlang 18a201611e add bind key for postcode array 2024-01-11 17:50:43 +08:00
edmondlang 7e754a9c7b add search postcode 2024-01-11 17:37:01 +08:00
edmondlang beb200fd6a Merge branch 'steve/account-mapping' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal 2024-01-11 10:59:40 +08:00
Steve Ng f0cb7828c3 invoice date for shipping portal when export invoice to autocount 2024-01-10 19:10:21 +08:00
Dillon Ngo 1956a4095d Proof of concept - Vue Polling - Performance Improvement and tweaking for better user experience 2024-01-08 17:49:42 +08:00
Dillon Ngo 71559701f4 Merge branch 'dillon/46.3-warehouse-storage-charges-fixes' into 'master'
Fix attempt on storage invoice pdf not able to be downloaded by user

See merge request CIEFWorldwideSdnBhd/shipping-portal!187
2024-01-05 21:55:59 +00:00
Dillon Ngo 9ceba30680 Fix attempt on storage invoice pdf not able to be downloaded by user 2024-01-06 05:53:59 +08:00
Dillon Ngo 3b2d06ed8f Fix attempt on storage invoice pdf not able to be downloaded by user 2024-01-06 05:52:55 +08:00
Dillon Ngo 81e04e9cb0 Fix attempt on storage invoice pdf not able to be downloaded by user 2024-01-06 05:52:26 +08:00
Dillon Ngo 286ca64413 Merge branch 'dillon/46.3-warehouse-storage-charges-fixes' into 'master'
Fix attempt on storage invoice pdf not able to be downloaded by user

See merge request CIEFWorldwideSdnBhd/shipping-portal!186
2024-01-05 21:11:33 +00:00
Dillon Ngo 51a96812fd Fix attempt on storage invoice pdf not able to be downloaded by user 2024-01-06 05:10:50 +08:00
Dillon Ngo 07459b9a1b Merge branch 'dillon/46.3-warehouse-storage-charges-fixes' into 'master'
Fix attempt on storage invoice pdf not able to be downloaded by user

See merge request CIEFWorldwideSdnBhd/shipping-portal!185
2024-01-05 21:08:00 +00:00
Dillon Ngo ee69f9123c Fix attempt on storage invoice pdf not able to be downloaded by user 2024-01-06 05:05:59 +08:00
Steve Ng 7a2ed92147 change posting date to invoice date for shipping portal when export invoice to autocount 2024-01-05 11:10:42 +08:00
Dillon Ngo 894481591d Proof of concept - Vue Polling - Performance Improvement and tweaking for better user experience 2024-01-04 13:52:11 +08:00
Dillon Ngo e5580c2abd Proof of concept - Vue Polling - Performance Improvement and tweaking for better user experience 2024-01-04 02:50:55 +08:00
Dillon Ngo 47ee304da1 Proof of concept - Vue Polling - Performance Improvement and tweaking for better user experience 2024-01-04 02:10:04 +08:00
Steve Ng 6427e2996f change posting date to invoice date for shipping portal when export invoice to autocount 2024-01-03 09:05:07 +08:00
Dillon Ngo f54aae5dc9 Proof of concept - Vue Polling - Performance Improvement and tweaking for better user experience 2024-01-03 05:39:43 +08:00
Dillon Ngo f0ef9a5602 Proof of concept - Vue Polling - Performance Improvement and tweaking for better user experience 2023-12-30 19:13:40 +08:00
Dillon Ngo 4d682c2ac6 Proof of concept - Vue Polling - Performance Improvement and tweaking for better user experience 2023-12-26 04:21:46 +08:00
Dillon Ngo 8ea00e0383 Proof of concept - Vue Polling - Performance Improvement and tweaking for better user experience 2023-12-24 21:59:41 +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 18df1c0c7b Proof of concept - Vue Polling a workaround for AWS API Gateway limitation 2023-12-20 14:47:56 +08:00
Dillon Ngo 359c103d01 Code sync from Exchange 2023-12-17 17:23:04 +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
JiaSheng 56bba0eaaf wallet pagination, export 2023-10-22 23:46:09 +08:00
166 changed files with 6831 additions and 227 deletions
@@ -0,0 +1,11 @@
<?php
namespace App\Classes\Exceptions;
use App\Classes\ValueObjects\Constants\HttpStatus;
final class JobResourceNotFoundException extends ServiceApiException {
public function __construct(?string $message = null) {
parent::__construct($message ?? 'Unable to find the requested resource', HttpStatus::RESOURCE_NOT_FOUND);
}
}
@@ -15,6 +15,8 @@ use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Http\Resources\Json\ResourceCollection;
use Illuminate\Support\Facades\DB;
use App\Classes\Exceptions\JobResourceNotFoundException;
use Illuminate\Support\Facades\Log;
abstract class AbstractControllerLogic
{
@@ -62,6 +64,19 @@ abstract class AbstractControllerLogic
return $response;
} catch (ErrorException|GeneralExceptions|TypeError $exception){
if ($exception instanceof JobResourceNotFoundException) {
Log::error(sprintf(
"Uncaught exception '%s' with message '%s' in %s:%d",
get_class($exception),
$exception->getMessage(),
$exception->getTrace()[0]['file'],
$exception->getTrace()[0]['line']
));
}
else{
Log::error($exception);
}
return (new ApiResponseObject($this->getNotificationTitle().' failed', $exception->getMessage(),
!in_array($exception->getCode(), [0, 42000]) ? $exception->getCode() : HttpStatus::SERVER_ERROR))->handler();
@@ -6,6 +6,8 @@ namespace App\Classes\General\Eloquent;
use App\Classes\Exceptions\ResourceNotFoundException;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use App\Classes\Exceptions\JobResourceNotFoundException;
abstract class AbstractFetchRecord extends AbstractGetRecord
{
@@ -26,12 +28,18 @@ abstract class AbstractFetchRecord extends AbstractGetRecord
* @return Model
* @throws ResourceNotFoundException
*/
public function getResults(Builder $query): Model {
public function getResults(Builder $query, array $param = []): Model {
if(!$query->exists()){
throw new ResourceNotFoundException('Unable to find any record based on the criteria provided');
$table = $query->getModel()->getTable();
if($table ==='job_results'){
throw new JobResourceNotFoundException('Unable to find any job based on the criteria provided');
}
else{
throw new ResourceNotFoundException('Unable to find any record based on the criteria provided');
}
}
return $query->first();
}
}
}
@@ -50,9 +50,9 @@ abstract class AbstractGetRecord
* @param array $filters
* @return mixed
*/
public function handler(array $filters){
public function handler(array $filters, array $params = []){
$this->filters = collect($filters);
return $this->getResults($this->applyFiltersToQuery());
return $this->getResults($this->applyFiltersToQuery(), $params);
}
@@ -65,6 +65,6 @@ abstract class AbstractGetRecord
* @param Builder $query
* @return mixed
*/
abstract function getResults(Builder $query);
abstract function getResults(Builder $query, array $params = []);
}
}
@@ -16,11 +16,10 @@ abstract class AbstractListRecord extends AbstractGetRecord
* @return mixed
* @throws MalformedRequestException
*/
public function execute(array $filters = []){
public function execute(array $filters = [], array $param = []){
try{
return $this->handler($filters);
return $this->handler($filters, $param);
} catch (QueryException $exception){
throw new MalformedRequestException('Unable to fetch the list of records due to unexpected error');
@@ -32,7 +31,7 @@ abstract class AbstractListRecord extends AbstractGetRecord
* @param Builder $query
* @return mixed
*/
public function getResults(Builder $query) {
public function getResults(Builder $query, array $param = []) {
$filters = $this->getDecorationFilters();
if($filters->has('order_by')){
@@ -44,8 +43,12 @@ abstract class AbstractListRecord extends AbstractGetRecord
}
//dd($query->toSql());
return $filters->has('per_page') ? $query->paginate($filters->get('per_page')) : $query->get();
if(!empty($param)){
return $filters->has('per_page') ? $query->paginate($filters->get('per_page'), ['*'], 'page', $param['page']) : $query->get(); //page data from query parameters e.g ?page=1
}
else{
return $filters->has('per_page') ? $query->paginate($filters->get('per_page')) : $query->get();
}
}
}
@@ -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 JobId implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->where('job_id', $value);
}
}
@@ -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);
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class PostcodeLike implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->where('postcode', 'LIKE', '%'.$value.'%');
}
}
@@ -0,0 +1,19 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class RequestSignature implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->where('request_signature', $value);
}
}
@@ -0,0 +1,18 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class ResultNotNull implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->whereNotNull('result');
}
}
@@ -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,20 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class WithContainersPackages implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->with(['containers', 'packages']);
}
}
@@ -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();
}
}
+9
View File
@@ -2,6 +2,7 @@
namespace App\Classes\General;
use Illuminate\Http\Resources\Json\ResourceCollection;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Log;
@@ -40,4 +41,12 @@ class Helper
}
}
}
/**
* @param ResourceCollection $collection
* @return array
*/
static function collectionResponse(ResourceCollection $collection){
return json_decode($collection->response()->getContent(), true);
}
}
+45
View File
@@ -0,0 +1,45 @@
<?php
namespace App\Classes\Jobs;
use App\Classes\Modules\PackingLists\Processors\ListPackingListsJobProcessor;
use App\Classes\Modules\Jobs\DataTransferObjects\ListGenericJobObject;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class ListPackingListsJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $timeout = 900;
/** @var ListGenericJobObject */
private $listGenericJobObject;
/**
* ListPackingListsJob constructor.
* @param ListGenericJobObject $listGenericJobObject
*/
public function __construct(ListGenericJobObject $listGenericJobObject)
{
$this->listGenericJobObject = $listGenericJobObject;
}
public function handle()
{
$rawPayload = $this->job->payload();
if(isset($rawPayload['data']['commandName'])){
$this->listGenericJobObject->setJobCommandName($rawPayload['data']['commandName']);
}
if(isset($rawPayload['data']['command'])){
$this->listGenericJobObject->setJobCommand($rawPayload['data']['command']);
}
$result = (App()->make(ListPackingListsJobProcessor::class))->execute($this->listGenericJobObject);
}
}
@@ -18,11 +18,13 @@ 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
{
@@ -50,6 +52,9 @@ class CallbackBillplzLogic
/** @var CallbackBillplzProcessor */
private $callbackBillplzProcessor;
/** @var CheckStorageInvoiceTransactionProcessor */
private $storageInvoiceTransactionProcessor;
/**
* CallbackBillplzLogic constructor.
* @param GetBillplzBill $getBillplzBill
@@ -59,8 +64,9 @@ class CallbackBillplzLogic
* @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, CallbackBillplzProcessor $callbackBillplzProcessor)
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;
@@ -70,6 +76,7 @@ class CallbackBillplzLogic
$this->updatesWalletBalance = $updatesWalletBalance;
$this->createPaymentTransactionProcessor = $createPaymentTransactionProcessor;
$this->callbackBillplzProcessor = $callbackBillplzProcessor;
$this->storageInvoiceTransactionProcessor = $storageInvoiceTransactionProcessor;
}
@@ -109,10 +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);
$this->callbackBillplzProcessor->execute($transaction, $status);
$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;
@@ -123,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
}
}
}
}
}
}
@@ -6,13 +6,14 @@ use Illuminate\Http\Request;
use App\Models\Wallet;
use App\Models\Group;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\Modules\Transactions\Processors\CreatePaymentTransactionProcessor;
use App\Classes\Modules\Transactions\Processors\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
{
@@ -31,6 +32,9 @@ class CallbackBillplzProcessor
/** @var CreatePaymentTransactionProcessor */
private $createPaymentTransactionProcessor;
/** @var ReleaseGoodsToCustomerProcessor */
private $releaseGoodsToCustomerProcessor;
/**
* CreateUserProcessor constructor.
* @param UpdatesTransactionStatus $updatesTransactionStatus
@@ -38,14 +42,16 @@ class CallbackBillplzProcessor
* @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)
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;
}
@@ -58,6 +64,9 @@ class CallbackBillplzProcessor
$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
@@ -66,33 +75,54 @@ class CallbackBillplzProcessor
$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;
$this->createPaymentTransactionProcessor->execute($invoice, PaymentMethodType::WALLET, null);
$paymentTransaction = $this->createPaymentTransactionProcessor->execute($invoice, PaymentMethodType::WALLET, null, false);
if($paymentTransaction && $paymentTransaction->status == ApprovalStatus::APPROVED){
$pL = $invoice->owner;
$this->releaseGoodsToCustomerProcessor->execute($pL, $invoice);
}
}
$group->status = $status;
$group->save();
}
}
if (!$transaction->owner instanceof Wallet) {
$totalPaidAmount = $invoice->transactions->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->sum('amount');
$this->releaseGoodsToCustomerProcessor->execute($packingList, $invoice);
}
if (($invoice->amount - $totalPaidAmount) < 0.01) {
$this->updatesTransactionStatus->execute($invoice, ApprovalStatus::COMPLETED);
return true;
}
$packingList->status = ApprovalStatus::APPROVED;
$packingList->save();
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;
if (app()->environment('production')) {
$this->updateDoFromVTPortalProcessor->execute($packingList);
$this->updateDoFromYDPortalProcessor->execute($packingList);
}
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,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));
}
@@ -0,0 +1,23 @@
<?php
namespace App\Classes\Modules\Imports\Services;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\ToCollection;
class GenericImport implements ToCollection, WithHeadingRow
{
function headingRow(): int { return 1; }
public $rows;
/**
* @param Collection $collection
*/
public function collection(Collection $collection)
{
$this->rows = $collection;
}
}
@@ -0,0 +1,52 @@
<?php
namespace App\Classes\Modules\Jobs\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Jobs\Processors\FetchesJobResultProcessor;
use App\Http\Resources\JobResultResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class FetchJobResultLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Retrieved Data',
'message' => 'You have successfully retrieved data'
];
}
/** @var FetchesJobResultProcessor */
private $fetchesJobResultProcessor;
/**
* FetchJobResultLogic constructor.
* @param FetchesJobResultProcessor $fetchesJobResultProcessor
*/
public function __construct(FetchesJobResultProcessor $fetchesJobResultProcessor)
{
$this->fetchesJobResultProcessor = $fetchesJobResultProcessor;
}
/**
* @param Request $request
* @return JsonResponse
* @throws \App\Classes\Exceptions\AccessForbiddenException
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
public function logic(Request $request) : JsonResponse
{
$query = $this->fetchesJobResultProcessor->execute($request);
return $this->resourceResponse(new JobResultResource($query));
}
}
@@ -0,0 +1,118 @@
<?php
namespace App\Classes\Modules\Jobs\DataTransferObjects;
use App\Classes\General\Interfaces\DataTransferObject;
class ListGenericJobObject implements DataTransferObject
{
/** @var string */
private $name;
/** @var array */
private $payload;
/** @var string */
private $jobId;
/** @var string */
private $requestSignature;
/** @var string */
private $resultSignature;
/** @var object */
private $userInfo;
/** @var string */
private $jobCommandName;
/** @var string */
private $jobCommand;
public function __construct(string $name, array $payload, string $requestSignature, ?string $resultSignature, string $jobId, object $userInfo = null)
{
$this->name = $name;
$this->payload = $payload;
$this->jobId = $jobId;
$this->requestSignature = $requestSignature;
$this->resultSignature = $resultSignature;
$this->userInfo = $userInfo;
}
/**
* @return string
*/
public function getName(): string
{
return $this->name;
}
/**
* @return array
*/
public function getPayload(): array
{
return $this->payload;
}
/**
* @return string
*/
public function getJobId(): string
{
return $this->jobId;
}
/**
* @return string
*/
public function getRequestSignature(): string
{
return $this->requestSignature;
}
/**
* @return string
*/
public function getResultSignature(): ?string
{
return $this->resultSignature;
}
/**
* @return object
*/
public function getUserInfo(): object
{
return $this->userInfo;
}
/**
* @return string
*/
public function getJobCommandName(): string
{
return $this->jobCommandName;
}
/**
* @return string
*/
public function getJobCommand(): string
{
return $this->jobCommand;
}
public function setJobCommandName(string $jobCommandName)
{
$this->jobCommandName = $jobCommandName;
}
public function setJobCommand(string $jobCommand)
{
$this->jobCommand = $jobCommand;
}
}
@@ -0,0 +1,60 @@
<?php
namespace App\Classes\Modules\Jobs\DataTransferObjects;
use App\Classes\General\Interfaces\DataTransferObject;
class UpdateJobResultObject implements DataTransferObject
{
/** @var string */
private $result;
/** @var string */
private $resultSignature;
/** @var string */
private $jobCommandName;
/** @var string */
private $jobCommand;
public function __construct(string $result, string $resultSignature, string $jobCommandName, string $jobCommand)
{
$this->result = $result;
$this->resultSignature = $resultSignature;
$this->jobCommandName = $jobCommandName;
$this->jobCommand = $jobCommand;
}
/**
* @return string
*/
public function getResult(): string
{
return $this->result;
}
/**
* @return array
*/
public function getResultSignature(): string
{
return $this->resultSignature;
}
/**
* @return string
*/
public function getJobCommandName(): string
{
return $this->jobCommandName;
}
/**
* @return string
*/
public function getJobCommand(): string
{
return $this->jobCommand;
}
}
@@ -0,0 +1,47 @@
<?php
namespace App\Classes\Modules\Jobs\Processors;
use App\Classes\Exceptions\JobResourceNotFoundException;
use App\Classes\Modules\Jobs\Services\FetchesJobResult;
use Illuminate\Http\Request;
class FetchesJobResultProcessor
{
/** @var FetchesJobResult */
private $fetchesJobResult;
/**
* FetchesJobResultProcessor constructor.
* @param FetchesJobResult $fetchesJobResult
*/
public function __construct(FetchesJobResult $fetchesJobResult)
{
$this->fetchesJobResult = $fetchesJobResult;
}
/**
* @param Request $request
* @return Model
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws \App\Classes\Exceptions\JobResourceNotFoundException
* @throws \App\Classes\Exceptions\ResourceNotFoundException
*/
public function execute(Request $request){
$res1 = $this->fetchesJobResult->execute(['job_id' => $request->route('job_id')]);
if($request->route('is_last')){
$res2 = $this->fetchesJobResult->execute(['request_signature' => $res1->request_signature, 'result_not_null' => true, 'order_by_id_desc' => true]);
return $res2;
}
if(!$res1->result){
throw new JobResourceNotFoundException('Unable to find any job based on the criteria provided');
}
return $res1;
}
}
@@ -0,0 +1,64 @@
<?php
namespace App\Classes\Modules\Jobs\Processors;
use App\Classes\Modules\Jobs\Services\UpdatesJobResult;
use App\Classes\Modules\Jobs\Services\FetchesJobResult;
use App\Classes\Exceptions\JobResourceNotFoundException;
use App\Classes\Modules\Jobs\DataTransferObjects\ListGenericJobObject;
use App\Classes\Modules\Jobs\DataTransferObjects\UpdateJobResultObject;
class UpdateJobResultProcessor
{
/** @var FetchesJobResult */
private $fetchesJobResult;
/** @var UpdatesJobResult */
private $updatesJobResult;
/**
* UpdateJobResultProcessor constructor.
* @param FetchesJobResult $fetchesJobResult
* @param UpdatesJobResult $updatesJobResult
*/
public function __construct(FetchesJobResult $fetchesJobResult, UpdatesJobResult $updatesJobResult)
{
$this->fetchesJobResult = $fetchesJobResult;
$this->updatesJobResult = $updatesJobResult;
}
/**
* @param ListGenericJobObject $listGenericJobObject
* @param array $resultCurrent
* @return void
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws \App\Classes\Exceptions\JobResourceNotFoundException
*/
public function execute(ListGenericJobObject $listGenericJobObject, $resultCurrent) {
$jobResultCurrent = $this->fetchesJobResult->execute(['job_id' => $listGenericJobObject->getJobId()]);
$resultCurrentJson = json_encode($resultCurrent);
$resultSignatureCurrent = md5($resultCurrentJson);
try{
$jobResultExisting = $this->fetchesJobResult->execute(['request_signature' => $jobResultCurrent->request_signature, 'result_not_null' => true, 'order_by_id_desc' => true]);
$resultSignatureExisting = $jobResultExisting->result_signature;
//if($resultSignatureExisting != $resultSignatureCurrent){
$this->updateJobResult($jobResultCurrent, $resultCurrentJson, $resultSignatureCurrent, $listGenericJobObject->getJobCommandName(), $listGenericJobObject->getJobCommand());
//}
} catch (JobResourceNotFoundException $exception){
$this->updateJobResult($jobResultCurrent, $resultCurrentJson, $resultSignatureCurrent, $listGenericJobObject->getJobCommandName(), $listGenericJobObject->getJobCommand());
}
}
private function updateJobResult($jobResultCurrent, $resultCurrentJson, $resultSignatureCurrent, $jobCommandName, $jobCommand){
$updateJobResultObject = new UpdateJobResultObject(
$resultCurrentJson,
$resultSignatureCurrent,
$jobCommandName,
$jobCommand
);
$create = $this->updatesJobResult->execute($jobResultCurrent, $updateJobResultObject);
}
}
@@ -0,0 +1,26 @@
<?php
namespace App\Classes\Modules\Jobs\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Models\JobResult;
use App\Classes\Modules\Jobs\DataTransferObjects\ListGenericJobObject;
class CreatesJobResult extends AbstractUpdateRecord
{
/**
* @param ListGenericJobObject $listGenericJobObject
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(ListGenericJobObject $listGenericJobObject)
{
$model = new JobResult();
$model->job_id = $listGenericJobObject->getJobId();
$model->request_signature = $listGenericJobObject->getRequestSignature();
$model->result_signature = $listGenericJobObject->getResultSignature();
$model->url = $listGenericJobObject->getName();
return $this->handler($model);
}
}
@@ -0,0 +1,33 @@
<?php
namespace App\Classes\Modules\Jobs\Services;
use App\Classes\General\Eloquent\AbstractFetchRecord;
use Illuminate\Database\Eloquent\Builder;
use App\Models\JobResult;
class FetchesJobResult extends AbstractFetchRecord
{
/** @var JobResult */
private $repository;
/**
* FetchesJobResult constructor.
* @param JobResult $repository
*/
public function __construct(JobResult $repository)
{
$this->repository = $repository;
}
/**
* @return Builder
*/
public function getRepository(): Builder
{
return $this->repository->newQuery();
}
}
@@ -0,0 +1,33 @@
<?php
namespace App\Classes\Modules\Jobs\Services;
use App\Classes\General\Eloquent\AbstractListRecord;
use Illuminate\Database\Eloquent\Builder;
use App\Models\JobResult;
class ListsJobResult extends AbstractListRecord
{
/** @var JobResult */
private $repository;
/**
* ListsJobResult constructor.
* @param JobResult $repository
*/
public function __construct(JobResult $repository)
{
$this->repository = $repository;
}
/**
* @return Builder
*/
function getRepository(): Builder
{
return $this->repository->newQuery();
}
}
@@ -0,0 +1,28 @@
<?php
namespace App\Classes\Modules\Jobs\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Classes\Modules\Jobs\DataTransferObjects\UpdateJobResultObject;
use App\Models\JobResult;
class UpdatesJobResult extends AbstractUpdateRecord
{
/**
* @param JobResult $model
* @param UpdateJobResultObject $updateJobResultObject
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(JobResult $model, UpdateJobResultObject $updateJobResultObject) {
$model->result = $updateJobResultObject->getResult();
$model->result_signature = $updateJobResultObject->getResultSignature();
$model->job_command_name = $updateJobResultObject->getJobCommandName();
$model->job_command = $updateJobResultObject->getJobCommand();
return $this->handler($model);
}
}
@@ -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));
}
}
}
@@ -38,6 +38,7 @@ class UpdateDoFromYDPortalProcessor
*/
public function execute(PackingList $packingList) {
Log::info('Trying to Call UpdateDoFromYDPortalProcessor');
Log::channel('storage_invoices')->info('UpdateDoFromYDPortalProcessor: '.json_encode($packingList));
if(!app()->environment(['production'])){
return;
@@ -72,6 +73,7 @@ class UpdateDoFromYDPortalProcessor
} catch (\Exception $exception){
log::debug($exception);
throw new InternalServerErrorException('failed to approve address due to an error related to YD portal');
}
}
@@ -0,0 +1,78 @@
<?php
namespace App\Classes\Modules\PackingLists\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Jobs\ListPackingListsJob;
use App\Classes\Modules\Jobs\DataTransferObjects\ListGenericJobObject;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Classes\Modules\Jobs\Services\CreatesJobResult;
class ListPackingListsJobLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Job Retrieving PackingLists',
'message' => 'You have successfully submit a job to retrieve a list of PackingLists'
];
}
/** @var CreatesJobResult */
private $createsJobResult;
/**
* ListPackingListsJobLogic constructor.
* @param CreatesJobResult $createsJobResult
*/
public function __construct(CreatesJobResult $createsJobResult)
{
$this->createsJobResult = $createsJobResult;
}
/**
* @param Request $request
* @return JsonResponse
*/
public function logic(Request $request) : JsonResponse
{
$jobId = uniqid();
$user = Auth::user();
$userInfo = (object) [
// 'email' => $user->email,
'type' => $user->type,
];
$userInfoJson = json_encode($userInfo);
$requestSignature = md5($userInfoJson . $request->fullUrl());
$listGenericJobObject = new ListGenericJobObject(
$request->fullUrl(),
$request->all(),
$requestSignature,
null,
$jobId,
$userInfo
);
ListPackingListsJob::dispatch($listGenericJobObject);
$result = [];
$result['job_id'] = $jobId;
$this->createsJobResult->execute($listGenericJobObject);
return $this->response(['data' => $result]);
}
}
@@ -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()) {
@@ -0,0 +1,50 @@
<?php
namespace App\Classes\Modules\PackingLists\Processors;
use App\Classes\Modules\PackingLists\Services\ListsPackingLists;
use App\Classes\Modules\Jobs\Processors\UpdateJobResultProcessor;
use App\Classes\General\Helper;
use App\Classes\Modules\Jobs\DataTransferObjects\ListGenericJobObject;
use App\Http\Resources\ListPackingListJobResource;
class ListPackingListsJobProcessor
{
/** @var ListsPackingLists */
private $listsPackingLists;
/** @var UpdateJobResultProcessor */
private $updateJobResultProcessor;
/**
* ListPackingListsJobProcessor constructor.
* @param ListsPackingLists $listsPackingLists
* @param UpdateJobResultProcessor $updateJobResultProcessor
*/
public function __construct(ListsPackingLists $listsPackingLists, UpdateJobResultProcessor $updateJobResultProcessor)
{
$this->listsPackingLists = $listsPackingLists;
$this->updateJobResultProcessor = $updateJobResultProcessor;
}
/**
* @param ListGenericJobObject $listGenericJobObject
* @return void
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws \App\Classes\Exceptions\JobResourceNotFoundException
*/
public function execute(ListGenericJobObject $listGenericJobObject) {
// $query = $this->listsPackingLists->execute($this->listsPackingLists->deserializeFilters($listGenericJobObject->getPayload()['filters']), ['page' => $listGenericJobObject->getPayload()['page'], 'with_containers_packages' => true]);
$query = $this->listsPackingLists->execute(array_merge($this->listsPackingLists->deserializeFilters($listGenericJobObject->getPayload()['filters']), ['page' => $listGenericJobObject->getPayload()['page'], 'with_containers_packages' => true]));
foreach ($query->items() as &$item) {
$item['userInfo'] = $listGenericJobObject->getUserInfo();
}
$resultCurrent = Helper::collectionResponse(ListPackingListJobResource::collection($query));
$this->updateJobResultProcessor->execute($listGenericJobObject, $resultCurrent);
}
}
@@ -21,6 +21,8 @@ use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Models\GroupTransaction;
use App\Http\Resources\WalletTransactionResource;
use App\Models\Wallet;
use App\Classes\Modules\Transactions\Processors\ReleaseGoodsToCustomerProcessor;
class CreateGroupsLogic extends AbstractControllerLogic
{
@@ -55,13 +57,18 @@ class CreateGroupsLogic extends AbstractControllerLogic
/** @var CreatesGroup */
private $createsGroup;
/** @var ReleaseGoodsToCustomerProcessor */
private $releaseGoodsToCustomerProcessor;
public function __construct(
FetchesTransaction $fetchesTransaction,
GeneratesTransactionBillNumber $generatesTransactionBillNumber,
FetchesTransaction $fetchesTransaction,
GeneratesTransactionBillNumber $generatesTransactionBillNumber,
FetchesCompanyModule $fetchesCompanyModule,
CreateWalletTopUpTransactionProcessor $createWalletTopUpTransactionProcessor,
CreatePaymentTransactionProcessor $createPaymentTransactionProcessor,
CreatesGroup $createsGroup
CreatesGroup $createsGroup,
ReleaseGoodsToCustomerProcessor $releaseGoodsToCustomerProcessor
)
{
$this->fetchesTransaction = $fetchesTransaction;
@@ -70,6 +77,7 @@ class CreateGroupsLogic extends AbstractControllerLogic
$this->createWalletTopUpTransactionProcessor = $createWalletTopUpTransactionProcessor;
$this->createPaymentTransactionProcessor = $createPaymentTransactionProcessor;
$this->createsGroup = $createsGroup;
$this->releaseGoodsToCustomerProcessor = $releaseGoodsToCustomerProcessor;
}
public function logic(Request $request) : JsonResponse
@@ -146,7 +154,12 @@ class CreateGroupsLogic extends AbstractControllerLogic
foreach ($invoices as $invoice) {
if ($payment_method == PaymentMethodType::WALLET) {
$this->createPaymentTransactionProcessor->execute($invoice, PaymentMethodType::WALLET, $request->input('bank_code'));
$paymentTransaction = $this->createPaymentTransactionProcessor->execute($invoice, PaymentMethodType::WALLET, $request->input('bank_code'), false);
if($paymentTransaction && $paymentTransaction->status == ApprovalStatus::APPROVED){
$pL = $invoice->owner;
$this->releaseGoodsToCustomerProcessor->execute($pL, $invoice);
}
}
$issuer = $invoice->issuer;
@@ -10,6 +10,8 @@ use App\Http\Resources\TransactionResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use App\Classes\Modules\Transactions\Processors\CreatePaymentTransactionProcessor;
use App\Classes\Modules\Transactions\Processors\ReleaseGoodsToCustomerProcessor;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
class CreatePaymentTransactionLogic extends AbstractControllerLogic
{
@@ -30,13 +32,18 @@ class CreatePaymentTransactionLogic extends AbstractControllerLogic
/** @var CreatePaymentTransactionProcessor */
private $createPaymentTransactionProcessor;
/** @var ReleaseGoodsToCustomerProcessor */
private $releaseGoodsToCustomerProcessor;
public function __construct(
FetchesTransaction $fetchesTransaction,
CreatePaymentTransactionProcessor $createPaymentTransactionProcessor
CreatePaymentTransactionProcessor $createPaymentTransactionProcessor,
ReleaseGoodsToCustomerProcessor $releaseGoodsToCustomerProcessor
)
{
$this->fetchesTransaction = $fetchesTransaction;
$this->createPaymentTransactionProcessor = $createPaymentTransactionProcessor;
$this->releaseGoodsToCustomerProcessor = $releaseGoodsToCustomerProcessor;
}
public function logic(Request $request) : JsonResponse
@@ -45,7 +52,12 @@ class CreatePaymentTransactionLogic extends AbstractControllerLogic
$invoice_transaction = $this->fetchesTransaction->execute(['id' => $request->input('transaction_id')]);
$payment_transaction = $this->createPaymentTransactionProcessor->execute($invoice_transaction, $payment_method , $request->input('bank_code'));
$payment_transaction = $this->createPaymentTransactionProcessor->execute($invoice_transaction, $payment_method , $request->input('bank_code'), false);
if($payment_transaction && $payment_transaction->status == ApprovalStatus::APPROVED){
$pL = $invoice_transaction->owner;
$this->releaseGoodsToCustomerProcessor->execute($pL, $invoice_transaction);
}
//cief todo: at exchange there is a transition step - starts
// if(PaymentMethodType::PAYMENT_METHODS[$request->input('payment_method')] == PaymentMethodType::PAYMENT_GATEWAY){
@@ -63,4 +75,7 @@ class CreatePaymentTransactionLogic extends AbstractControllerLogic
return $this->resourceResponse(new TransactionResource($payment_transaction));
}
}
@@ -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 App\Http\Resources\TransactionWithStorageResource;
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')));
return $this->collectionResponse(TransactionResource::collection($query));
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(TransactionWithStorageResource::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,372 @@
<?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\TransactionWithStorageResource;
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 giving selected storage invoice a waiver
if(isset($storageInvoice->is_waived) && $storageInvoice->is_waived){
$pricePerCBM = 0;
$price_cbm = $pricePerCBM * $cbm * $resultNumberOfDaysExceeded;
}
//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));
Log::channel('storage_invoices')->info('amount: '.$amount);
$proceedToUpdate = false;
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);
}
}
$proceedToUpdate = true;
}
if($proceedToUpdate || ($pricePerCBM == 0 && $amount != 0)){
Log::channel('storage_invoices')->info('proceedToUpdate');
$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 TransactionWithStorageResource($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 CreateStorageInvoiceDocTransactionFixProcessor
{
/** @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,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;
}
}
@@ -0,0 +1,36 @@
<?php
namespace App\Classes\Notifications;
use App\Models\User;
use Illuminate\Notifications\Messages\MailMessage;
class PermitsReminderEmail extends AbstractEmail
{
/** @var User */
private $user;
private $reminders;
/**
* SendResetPasswordEmail constructor.
* @param User $user
* @param PasswordReset $attempt
*/
public function __construct(User $user, $reminders)
{
$this->user = $user;
$this->reminders = $reminders;
}
public function toMail()
{
return (new MailMessage)
->subject('Permits Renew Remidner Email')
->view('emails.reminder.permits_reminder', ['user' => $this->user, 'reminders' => $this->reminders]);
}
}
@@ -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 . '.');
}
}
@@ -0,0 +1,95 @@
<?php
namespace App\Console\Commands;
use App\Classes\Modules\Transactions\Services\FetchesGroup;
use App\Classes\Modules\Orders\Services\FetchesOrder;
use App\Classes\Modules\Transactions\Processors\ReleaseGoodsToCustomerProcessor;
use App\Classes\Modules\Transactions\Processors\CreateStorageInvoiceDocTransactionFixProcessor;
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;
/** @var FetchesOrder */
private $fetchesOrder;
/** @var CreateStorageInvoiceDocTransactionFixProcessor */
private $createStorageInvoiceDocTransactionProcessor;
/**
* Create a new command instance.
*
* @return void
*/
public function __construct(FetchesGroup $fetchesGroup, ReleaseGoodsToCustomerProcessor $releaseGoodsToCustomerProcessor, FetchesOrder $fetchesOrder, CreateStorageInvoiceDocTransactionFixProcessor $createStorageInvoiceDocTransactionProcessor)
{
parent::__construct();
$this->fetchesGroup = $fetchesGroup;
$this->releaseGoodsToCustomerProcessor = $releaseGoodsToCustomerProcessor;
$this->fetchesOrder = $fetchesOrder;
$this->createStorageInvoiceDocTransactionProcessor = $createStorageInvoiceDocTransactionProcessor;
}
/**
* 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));
$pL = $invoice->owner;
$this->releaseGoodsToCustomerProcessor->execute($pL, $invoice);
}
}
*/
$order = $this->fetchesOrder->execute(['reference' => '729251424']);
$packingLists = $order->destinationWarehousePackages;
foreach ($packingLists as $packingList){
$this->createStorageInvoiceDocTransactionProcessor->execute($packingList, true);
dd(json_encode($packingList));
}
$end = new Carbon();
$elapsedTime = $start->diff($end)->format('%H:%I:%S');
$this->info(Carbon::now() . ': Done data patch. ElapsedTime: ' . $elapsedTime . '.');
}
}
@@ -0,0 +1,74 @@
<?php
namespace App\Console\Commands;
use App\Classes\Notifications\PermitsReminderEmail;
use App\Models\PermitsReminder;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Console\Command;
class SendPermitsReminderEmails extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'permitsReminder:send';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Send Permits Reminders Email';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$now = now();
$startRange = $now->subDays(3)->startOfDay();
$endRange = $now->copy()->addDays(6)->endOfDay();
$reminders = PermitsReminder::whereDate('reminder_date', '>=', $startRange)
->whereDate('reminder_date', '<=', $endRange)
->pluck('model');
$this->info($this->getTimeStamp() . json_encode($reminders));
$users = User::whereIn(
'email',
[
// 'edmond.wuiming2021@gmail.com',
'anithagurl96@gmail.com'
]
)->get();
foreach ($users as $user) {
$this->info($this->getTimeStamp() . 'Reminder email sent to ' . $user->email);
if (app()->environment('production')) {
$user->notify(new PermitsReminderEmail($user, $reminders));
}
}
}
public function getTimeStamp()
{
return '[' . Carbon::now()->format('Y-m-d H:i:s') . '] - ';
}
}
+10
View File
@@ -62,6 +62,16 @@ 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');
$schedule->command('permitsReminder:send')
->dailyAt('09:30')
->withoutOverlapping()
->appendOutputTo(storage_path().'/logs/permits-reminder-send.log');
}
/**
@@ -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,85 @@
<?php
namespace App\Http\Controllers\Imports;
use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject;
use App\Classes\Modules\Imports\Services\GenericImport;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Models\PermitsReminder;
use Carbon\Carbon;
use DateTime;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Maatwebsite\Excel\Facades\Excel;
use PhpOffice\PhpSpreadsheet\Shared\Date;
class ImportPermitsReminderController
{
/**
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function import(Request $request)
{
$object = new DocumentObject('', $request->input('files'), '', ApprovalStatus::APPROVED, 'imports');
$file = json_decode($object->getFiles()[0])->file_info->original->file;
$file = storage_path('app/documents/' . $file);
$import = new GenericImport();
Excel::import($import, $file);
$excelRows = $import->rows->toArray();
$successRows = [];
$returnArray = []; // Initialize the return array
foreach ($excelRows as $row) {
if (is_null($row['expiry_date']) && is_null($row['reminder_date'])) {
continue;
}
$row['expiry_date'] = $this->changeExcelDate($row['expiry_date']);
$row['reminder_date'] = $this->changeExcelDate($row['reminder_date']);
$validator = Validator::make($row, [
'model' => 'required|unique:permits_reminders,model',
'expiry_date' => 'required|date|after_or_equal:today',
'reminder_date' => 'required|date|after_or_equal:today',
]);
if ($validator->fails()) {
$row['status'] = 'failed';
$row['message'] = $validator->errors()->all();
$returnArray[] = $row;
} else {
$row['created_at'] = Carbon::now();
$row['updated_at'] = Carbon::now();
$successRows[] = $row;
}
}
if (!empty($successRows)) {
PermitsReminder::insert($successRows); // Insert only if there are successful rows
}
$successCount = count($successRows);
return response()->json([
'completedRows' => $successCount,
'failedRows' => count($returnArray),
'remark' => "Successful Imported {$successCount} data.",
'data' => $returnArray
]);
}
public function changeExcelDate($date)
{
$formatedDate = DateTime::createFromFormat('d/m/Y', $date);
if ($formatedDate instanceof DateTime) {
return $formatedDate->format('Y-m-d');
}
$unixTime = (($date - 25569) * 86400);
return (new DateTime("@$unixTime"))->format('Y-m-d');
}
}
@@ -0,0 +1,19 @@
<?php
namespace App\Http\Controllers\Jobs;
use App\Classes\Modules\Jobs\ControllersLogic\FetchJobResultLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class FetchJobResultController
{
/**
* @param Request $request
* @param FetchJobResultLogic $logic
* @return JsonResponse
*/
public function fetch(Request $request, FetchJobResultLogic $logic): JsonResponse {
return $logic->execute($request);
}
}
@@ -0,0 +1,21 @@
<?php
namespace App\Http\Controllers\PackingLists;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use App\Classes\Modules\PackingLists\ControllersLogic\ListPackingListsJobLogic;
class ListPackingListsJobController
{
/**
* @param Request $request
* @param ListPackingListsJobLogic $logic
* @return JsonResponse
*/
public function list(Request $request, ListPackingListsJobLogic $logic) : JsonResponse {
return $logic->execute($request);
}
}
@@ -0,0 +1,59 @@
<?php
namespace App\Http\Controllers\PermitsReminder;
use App\Classes\Exceptions\RequestValidationException;
use App\Models\PermitsReminder;
use Carbon\Carbon;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
class CreatePermitsReminderController
{
/**
* @param Request $request
* @return JsonResponse
*/
public function create(Request $request): JsonResponse
{
// Define validation rules
$rules = [
'model' => 'required|unique:permits_reminders,model',
'expiry_date' => 'required|date|after_or_equal:today',
'reminder_date' => 'required|date|after_or_equal:today',
];
// Perform validation
$validator = Validator::make($request->all(), $rules);
if ($validator->fails()) {
$validationErrors = $validator->errors()->all();
$validationError = implode("<br>", $validationErrors);
// Return validation error response
return response()->json([
'title' => 'Create Permits Reminder Failed',
'message' => $validationError,
"payload" => []
], 422); // 422 Unprocessable Entity status code for validation errors
}
// If validation passes, create the record
$record = PermitsReminder::create([
'expiry_date' => Carbon::parse($request->input('expiry_date'))->format('Y-m-d'),
'reminder_date' => Carbon::parse($request->input('reminder_date'))->format('Y-m-d'),
'model' => $request->input('model'),
]);
$response = [
"title" => "Create Permits Reminder Successful",
"message" => "You have successfully created a Permits Reminder",
"payload" => [
"data" => $record
]
];
return response()->json($response);
}
}
@@ -0,0 +1,28 @@
<?php
namespace App\Http\Controllers\PermitsReminder;
use App\Models\PermitsReminder;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class DeletePermitsReminderController
{
/**
* @param Request $request
* @return JsonResponse
*/
public function delete(Request $request): JsonResponse
{
$record = PermitsReminder::find($request->route('id'));
$record->delete();
$response = [
"title" => "Delete Permits Reminder Successful",
"message" => "You have successfully deleted a Permits Reminder",
"payload" => []
];
return response()->json($response);
}
}
@@ -0,0 +1,55 @@
<?php
namespace App\Http\Controllers\PermitsReminder;
use App\Models\PermitsReminder;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class ListPermitsReminderController
{
/**
* @param Request $request
* @return JsonResponse
*/
public function list(Request $request): JsonResponse
{
$perPage = 10; // Number of items per page
$page = request('page', 1); // Get the current page from the request
// Paginate the PermitsReminder model
$query = PermitsReminder::orderBy('id', 'desc');
$paginator = $query->paginate($perPage, ['*'], 'page', $page);
// Convert paginated data to an array
$data = $paginator->items();
// Create pagination links
$links = [
"first" => $paginator->url(1),
"last" => $paginator->url($paginator->lastPage()),
"prev" => $paginator->previousPageUrl(),
"next" => $paginator->nextPageUrl(),
];
$response = [
"title" => "List Permits Reminder",
"message" => "You have successfully retrieved a list of Permits Reminder",
"payload" => [
'data' => $data,
"links" => $links,
"meta" => [
"current_page" => $paginator->currentPage(),
"from" => $paginator->firstItem(),
"last_page" => $paginator->lastPage(),
"path" => $request->path(),
"per_page" => $paginator->perPage(),
"to" => $paginator->lastItem(),
"total" => $paginator->total(),
]
]
];
return response()->json($response);
}
}
@@ -0,0 +1,51 @@
<?php
namespace App\Http\Controllers\PermitsReminder;
use App\Models\PermitsReminder;
use Carbon\Carbon;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
class UpdatePermitsReminderController
{
/**
* @param Request $request
* @return JsonResponse
*/
public function update(Request $request): JsonResponse
{
$rules = [
'model' => 'required|unique:permits_reminders,model,' . $request->route('id'),
'expiry_date' => 'required|date|after_or_equal:today',
'reminder_date' => 'required|date|after_or_equal:today',
];
$validator = Validator::make($request->all(), $rules);
if ($validator->fails()) {
$validationErrors = $validator->errors()->all();
$validationError = implode("<br>", $validationErrors);
return response()->json([
'title' => 'Update Permits Reminder Failed',
'message' => $validationError,
"payload" => []
], 422);
}
$record = PermitsReminder::findOrFail($request->route('id'));
$record->model = $request->input('model');
$record->expiry_date = Carbon::parse($request->input('expiry_date'))->format('Y-m-d');
$record->reminder_date = Carbon::parse($request->input('reminder_date'))->format('Y-m-d');
$record->save();
return response()->json([
'title' => 'Permits Reminder Updated',
'message' => 'The permits reminder has been successfully updated.',
"payload" => $record
]);
}
}
@@ -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);
}
}
+3
View File
@@ -70,5 +70,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,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,47 @@
<?php
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;
class GroupForOrderV2Resource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
$payment_transaction = Transaction::where('payment_reference', $this->reference)->first();
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),
'payment_transaction' => $payment_transaction ? [
'id' => $payment_transaction->id,
'status' => $payment_transaction->status,
'status_name' => ApprovalStatus::APPROVAL_STATUS_ID[$payment_transaction->status]
] : []
];
}
}
@@ -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,
+22
View File
@@ -0,0 +1,22 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class JobResultResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'job_id' => $this->job_id,
'result' => $this->result,
];
}
}
@@ -0,0 +1,47 @@
<?php
namespace App\Http\Resources;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\PackingListType;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\ValueObjects\Constants\RoleTypes;
use App\Models\Order;
use App\Models\PackingList;
use Illuminate\Http\Resources\Json\JsonResource;
use App\Http\Resources\V2\PackingListV2Resource;
class ListPackingListJobResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
$exceptionUsers = in_array($this->userInfo ? $this->userInfo->type : Auth()->user()->type, [RoleTypes::SHADOW_ADMIN, RoleTypes::SUPER_ADMIN]);
$packages = !$this->packingLists()->exists() || $exceptionUsers ? $this->packages : $this->packingLists->first()->packages;
return [
'id' => $this->id,
'claimant_id' => $this->claimant_id,
'reference' => $this->reference,
'status' => $this->status,
'transport' => new TransportResource($this->transports()->first()),
'type' => $this->type,
'receive_packing_list' => $this->when($this->type === PackingListType::SHIPPING_PACKING_LIST, new PackingListV2Resource(PackingList::where('reference', $this->reference)->where('type', PackingListType::WAREHOUSE_RECEIVE_LIST)->first(), $this->userInfo)),
// 'packages' => PackageResource::collection($packages),
// $this->mergeWhen($this->owner instanceof Order, [
// 'order' => New OrderResource($this->owner)
// ]),
'container' => new ContainerResource($this->containers->first()),
'packages' => PackageWithoutOrderResource::collection($packages),
$this->mergeWhen($this->owner instanceof Order, [ 'order' => New OrderResource($this->owner) ]),
'shipping_transaction' => new TransactionResource($this->transactions()->where('type', TransactionType::SHIPPING_INVOICE)->whereNotIn('status', [ApprovalStatus::SUSPENDED, ApprovalStatus::EXPIRED])->first()),
'suspended_invoice' => new TransactionResource($this->transactions()->where('type', TransactionType::SHIPPING_INVOICE)->whereIn('status', [ApprovalStatus::SUSPENDED])->first()),
// 'suspended_invoices' => TransactionResource::collection($this->transactions()->where('type', TransactionType::SHIPPING_INVOICE)->whereIn('status', [ApprovalStatus::SUSPENDED])->get()),
];
}
}
@@ -37,6 +37,7 @@ class MappableTransactionResource extends JsonResource
'owner_type' => Transaction::class,
'owner_id'=> $this->id,
'owner_reference'=> $reference,
'created_at'=> $this->created_at, // invoice date
];
}
}
@@ -27,16 +27,19 @@ class MappableTransactionWithDetailsResource extends JsonResource
'order_reference' => null,
'bill_no' => null,
'marking' => null,
'created_at' => null
];
if ($this->type === TransactionType::PAYMENT) {
$order = $this->owner->owner->owner;
$data['order_reference'] = $order->reference;
$data['debtor_code'] = $order->companyModule->company->debtor;
$data['created_at'] = $this->owner->created_at; // invoice date
} elseif (in_array($this->type, [TransactionType::GROUP_PAYMENT, TransactionType::TOP_UP])) {
$connection = $this->owner->owner->inviters()->withPivot('invitee_reference')->first();
$data['marking'] = $connection ? $connection->pivot->invitee_reference : '';
$data['bill_no'] = $this->bill_no;
$data['created_at'] = $this->created_at;
} else {
$payments = $this->transactions()
->payments()->where('status', ApprovalStatus::APPROVED)
@@ -54,6 +57,7 @@ class MappableTransactionWithDetailsResource extends JsonResource
'type' => $payment->type,
'marking' => null,
'amount' => $payment->amount,
'created_at' => $this->created_at
];
})->toArray();
} else {
@@ -61,6 +65,7 @@ class MappableTransactionWithDetailsResource extends JsonResource
$data['amount'] = 'Transaction Type not allowed';
$data['transaction_type'] = $this->type;
$data['payment_transactions'] = null;
$data['created_at'] = null;
}
}
+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 TransactionWithStorageResource::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')
];
@@ -0,0 +1,38 @@
<?php
namespace App\Http\Resources;
use App\Models\Order;
use App\Models\PackingList;
use Illuminate\Http\Resources\Json\JsonResource;
class PackageWithoutOrderResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'type' => $this->type,
'description' => $this->description,
'width' => floatval($this->width),
'height' => floatval($this->height),
'length' => floatval($this->length),
'weight' => $this->weight,
'quantity' => $this->quantity,
'cbm' => (($this->width / 100) * ($this->height / 100) * ($this->length / 100)) * $this->quantity,
'reference' => $this->packingList->reference,
'status' => $this->status,
// $this->mergeWhen($originalPackingList->owner instanceof Order, [
// 'order' => New OrderResource($originalPackingList->owner)
// ]),
// 'container' => new ContainerResource($originalPackingList->containers()->first()),
// 'transport' => new TransportResource($originalPackingList->transports()->first())
];
}
}
+2 -2
View File
@@ -40,7 +40,7 @@ class TransactionResource extends JsonResource
if ($group) {
$groupTransactions = GroupTransactionResource::collection($group->groupTransactions);
}
}
return [
@@ -48,7 +48,7 @@ class TransactionResource extends JsonResource
'owner_type' => $this->owner_type,
'order' => $order,
'group_transactions' => $groupTransactions,
'group_reference' => $groupTransactions ? $group->reference : null,
'group_reference' => $groupTransactions ? ($group ? $group->reference : null ) : null,
'documents' => $groupTransactions ? DocumentResource::collection($this->documents->where('status', ApprovalStatus::PENDING_VERIFICATION)) : DocumentResource::collection($this->documents),
'type' => (int) $this->type,
'bill_no' => $this->bill_no,
@@ -0,0 +1,128 @@
<?php
namespace App\Http\Resources;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Group;
use App\Models\Transaction;
use App\Models\Wallet;
use Carbon\Carbon;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Facades\Log;
class TransactionWithStorageResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
$order = null;
$groupTransactions = null;
$group_payment_attempts = null;
$groupPaymentAttemptsFiltered = [];
$group_payment_expired = null;
$group_payment_history = null;
$groupTotalAmount = 0;
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]));
$group_payment_history = GroupForOrderV2Resource::collection($this->groups->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::REJECTED]));
}
} else {
$group = Group::where('reference', $this->payment_reference)->first();
if ($group) {
$groupTransactions = GroupTransactionResource::collection($group->groupTransactions);
}
}
$ts = $this->groups->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION])->last();
if ($ts) {
$paymentTransaction = Transaction::where('payment_reference', $ts->reference)->whereIn('status', [ApprovalStatus::PENDING_SUBMISSION])->first();
if($paymentTransaction){
$groupTotalAmount = (double) $this->amount;
foreach ($group_payment_history as $key => $value) {
if ($value->id === $ts->id && $value->reference === $ts->reference) {
unset($group_payment_history[$key]);
}
}
foreach ($group_payment_attempts as $key => $value) {
if ($value->id === $ts->id && $value->reference == $ts->reference) {
$groupPaymentAttemptsFiltered[$key] = $value;
}
}
}
}
return [
'id' => $this->id,
'owner_type' => $this->owner_type,
'order' => $order,
'group_transactions' => $groupTransactions,
'group_reference' => $groupTransactions ? ($group ? $group->reference : null ) : null,
'groups_payment_attempts' => $groupPaymentAttemptsFiltered,
'groups_payment_expired' => $group_payment_expired,
'groups_payment_history' => $group_payment_history,
'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,
'payment_method' => (int) $this->payment_method,
'payment_reference' => $this->payment_reference,
'outstanding' => (double) $this->amount - ($this->transactions()->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->sum('amount')),
'floating' => $group_payment_attempts ? $groupTotalAmount : (double) $this->transactions()->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::PENDING_SUBMISSION, ApprovalStatus::PENDING_VERIFICATION])->sum('amount'),
'service_charge' => (double) $this->service_charge,
'tax' => (double) $this->tax,
'original_amount' => (double) $this->original_amount,
'currency' => new CurrencyResource($this->currency),
'original_currency' => new CurrencyResource($this->original_currency),
'currency_rate' => (double) $this->currency_rate,
'status' => (int) $this->status,
'details' => TransactionDetailResource::collection($this->transactionDetails),
'transactions' => TransactionResource::collection($this->transactions),
'payment_attempts' => TransactionResource::collection(
$this->transactions()
->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()
->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::COMPLETED, ApprovalStatus::REJECTED])
->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')
];
}
}
@@ -0,0 +1,54 @@
<?php
namespace App\Http\Resources\V2;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\PackingListType;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\ValueObjects\Constants\RoleTypes;
use App\Models\Order;
use App\Models\PackingList;
use Illuminate\Http\Resources\Json\JsonResource;
use App\Http\Resources as V1;
class PackingListV2Resource extends JsonResource
{
private $userInfo;
public function __construct($resource, $userInfo = null)
{
parent::__construct($resource);
$this->userInfo = $userInfo;
}
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
$user = $this->userInfo ? $this->userInfo : Auth()->user();
$exceptionUsers = in_array($user->type, [RoleTypes::SHADOW_ADMIN, RoleTypes::SUPER_ADMIN]);
$packages = !$this->packingLists()->exists() || $exceptionUsers ? $this->packages : $this->packingLists->first()->packages;
return [
'id' => $this->id,
'claimant_id' => $this->claimant_id,
'reference' => $this->reference,
'status' => $this->status,
'transport' => new V1\TransportResource($this->transports()->first()),
'type' => $this->type,
'receive_packing_list' => $this->when($this->type === PackingListType::SHIPPING_PACKING_LIST, new PackingListV2Resource(PackingList::where('reference', $this->reference)->where('type', PackingListType::WAREHOUSE_RECEIVE_LIST)->first(), $user)),
'packages' => V1\PackageResource::collection($packages),
$this->mergeWhen($this->owner instanceof Order, [
'order' => New V1\OrderResource($this->owner)
]),
'shipping_transaction' => new V1\TransactionResource($this->transactions()->where('type', TransactionType::SHIPPING_INVOICE)->whereNotIn('status', [ApprovalStatus::SUSPENDED, ApprovalStatus::EXPIRED])->first()),
'suspended_invoice' => new V1\TransactionResource($this->transactions()->where('type', TransactionType::SHIPPING_INVOICE)->whereIn('status', [ApprovalStatus::SUSPENDED])->first()),
// 'suspended_invoices' => V1\TransactionResource::collection($this->transactions()->where('type', TransactionType::SHIPPING_INVOICE)->whereIn('status', [ApprovalStatus::SUSPENDED])->get()),
];
}
}
@@ -20,33 +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:
$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;
@@ -61,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,
+13
View File
@@ -0,0 +1,13 @@
<?php
namespace App\Models;
class JobResult extends AbstractModel
{
protected $table = 'job_results';
public $fillable = [
'job_id',
'result'
];
}
+33
View File
@@ -0,0 +1,33 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Carbon;
class PermitsReminder extends Model
{
use SoftDeletes;
protected $table = 'permits_reminders';
protected $dates = ['deleted_at'];
protected $fillable = ['model', 'expiry_date', 'reminder_date'];
public function getExpiryDateAttribute($value)
{
return $this->attributes['expiry_date'] === null ? NULL : Carbon::parse($this->attributes['expiry_date'])->format('d-m-Y');
}
public function getReminderDateAttribute($value)
{
return $this->attributes['reminder_date'] === null ? NULL : Carbon::parse($this->attributes['reminder_date'])->format('d-m-Y');
}
public function getCreatedAtAttribute($value)
{
return $this->attributes['created_at'] === null ? NULL : Carbon::parse($this->attributes['created_at'])->format('d-m-Y');
}
}
+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');
}
}
+8
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) {
+12
View File
@@ -54,6 +54,12 @@ return [
'days' => 14,
],
'storage_invoices' => [
'driver' => 'single',
'path' => storage_path('logs/laravel_storage_invoices.log'),
'level' => 'info',
],
'slack' => [
'driver' => 'slack',
'url' => env('LOG_SLACK_WEBHOOK_URL'),
@@ -100,6 +106,12 @@ return [
'emergency' => [
'path' => storage_path('logs/laravel.log'),
],
'paymentUnknownOrderLog' => [
'driver' => 'single',
'path' => storage_path('logs/paymentUnknownOrderLog.log'),
'level' => 'info',
],
],
];

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