Compare commits

..

142 Commits

Author SHA1 Message Date
edmondlang 2bc43cbc8f list order v2 2023-04-25 23:40:27 +08:00
Omair Saleh e0a02c7051 update foshan map png 2023-04-20 00:01:38 +08:00
Omair Saleh 34a08563f3 Merge remote-tracking branch 'origin/master' 2023-04-19 23:57:31 +08:00
Omair Saleh 9df1e158a4 disable temporary include new columns to invoice export for chasing payment 2023-04-19 23:55:31 +08:00
edmondlang 33cd313950 foshan-warehouse image 2023-04-19 23:53:16 +08:00
EDMOND MING 2af5035e99 Delete foshan-map.png 2023-04-19 15:52:26 +00:00
Omair Saleh acb7337b4a temporary include new columns to invoice export for chasing payment 2023-04-19 15:41:19 +08:00
Omair Saleh 0a9bc29202 temporary include new columns to invoice export for chasing payment 2023-04-19 15:33:16 +08:00
Omair Saleh 1568c7272a temporary include new columns to invoice export for chasing payment 2023-04-19 15:31:12 +08:00
Omair Saleh 14f0560055 Merge remote-tracking branch 'origin/master' 2023-04-19 15:27:06 +08:00
Omair Saleh fc339f1dec temporary include new columns to invoice export for chasing payment 2023-04-19 15:26:45 +08:00
edmondlang 77f7e86a5f fix bug date error in update announcement function in settings page 2023-04-19 12:52:46 +08:00
edmondlang 6970908b75 update generate PDF controller 2023-04-19 12:34:01 +08:00
edmondlang 3f31d2d578 add foshan map 2023-04-19 00:32:22 +08:00
edmondlang 8d8c468b09 foshan-warehouse 2023-04-18 23:42:49 +08:00
Dillon Ngo 557ab483f8 Merge branch 'dillon/improvement-1' into 'master'
Reduce flooding of logs from Perfex CRM

See merge request CIEFWorldwideSdnBhd/shipping-portal!162
2023-04-15 14:02:03 +00:00
Dillon 4b0b88b5d8 Reduce flooding of logs from Perfex CRM 2023-04-15 21:46:26 +08:00
edmondlang 1960cff426 create a cron job to fix all billplz failed callback for all the success payments. 2023-04-14 11:39:24 +08:00
edmondlang 0402fc67e2 update package loading animation 2023-04-13 22:57:46 +08:00
edmondlang 4089683ab7 remove all css comments 2023-04-13 22:53:12 +08:00
edmondlang 3fdd2a2b56 update package loading animation 2023-04-13 22:46:41 +08:00
edmondlang 76193eeb9f update order v2 2023-04-13 16:09:18 +08:00
edmondlang a696e1dab9 change all order to v2 link 2023-04-13 16:05:20 +08:00
edmondlang c9642bd8f5 update order v2 page 2023-04-13 16:01:12 +08:00
DESKTOP-5I7S92L\nicho a3d26bfb63 uncomment order package code 2023-04-13 12:20:49 +08:00
DESKTOP-5I7S92L\nicho 094f995dcf orde v2 include packages 2023-04-13 12:18:22 +08:00
edmondlang 1a5db25285 update show duplicated invoice logic 2023-04-12 12:15:06 +08:00
edmondlang 2bb4afe426 update show duplicated invoice logic 2023-04-12 11:58:10 +08:00
edmondlang f7a9b2332c enable customer 769SMC summary in 2 different year 2022 and 2023 2023-04-11 11:39:22 +08:00
Dillon Ngo fa0c97b1da Merge branch 'dillon/accounting-bank-mapping' into 'master'
New route, middleware, token table, filters for query to allow  third party to access api

See merge request CIEFWorldwideSdnBhd/shipping-portal!161
2023-04-06 15:19:15 +00:00
Dillon 43cd6f35be New route, middleware, token table, filters for query to allow third party to access api 2023-04-06 22:57:50 +08:00
edmondlang 697c02ac8a delete packing list by package id 2023-04-06 19:22:40 +08:00
edmondlang 3dd9dfe361 Merge branch 'master' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into delete-packing-list 2023-04-06 18:52:48 +08:00
edmondlang 7c50dfbfc3 update 769SMC summary 2023-04-06 17:30:02 +08:00
edmondlang e77e513bef support page update 2023-04-06 14:24:56 +08:00
DESKTOP-5I7S92L\nicho e173a9ddd3 support update 2023-04-06 14:00:41 +08:00
edmondlang c40d563372 add support at menu 2023-04-06 00:08:06 +08:00
edmondlang 7f0de1c1e4 support page 2023-04-05 23:49:23 +08:00
edmondlang c5477890d6 oder v2 2023-04-05 20:27:22 +08:00
edmondlang 26027f5f3f order profile v2 2023-04-05 19:13:17 +08:00
edmondlang a28f735d8f order v2 2023-04-05 19:12:07 +08:00
DESKTOP-5I7S92L\nicho 225abaacb8 order v2 2023-04-05 16:38:28 +08:00
DESKTOP-5I7S92L\nicho 70fc8285f8 order v2 2023-04-05 16:21:53 +08:00
DESKTOP-5I7S92L\nicho 1f6eaa65a5 order v2 2023-04-05 16:02:10 +08:00
DESKTOP-5I7S92L\nicho 7e2428957e delete packing list 2023-04-05 15:18:46 +08:00
edmondlang 069c3cea35 Showing Billplz payment status 2023-04-02 12:09:44 +08:00
edmondlang 07998c6850 super admin delete invoice/transaction 2023-04-02 11:25:50 +08:00
Dillon Ngo cd3e955f3e Merge branch 'dillon/debug-and-fixes-2' into 'master'
Another attempt to solve invoice without projectId, rewriting job chaining one after another

See merge request CIEFWorldwideSdnBhd/shipping-portal!160
2023-04-01 16:28:55 +00:00
edmondlang 869397056c final-duplicated-invoice-debug 2023-04-01 19:36:43 +08:00
edmondlang c58cdde254 final-duplicated-invoice-debug 2023-04-01 19:35:47 +08:00
edmondlang 982a7c1d44 final-duplicated-invoice-debug 2023-04-01 19:34:30 +08:00
edmondlang c976319521 final-duplicated-invoice-debug 2023-04-01 19:19:48 +08:00
edmondlang 145bf3263a final-duplicated-invoice-debug 2023-04-01 18:51:37 +08:00
edmondlang 57eb1e147d final-duplicated-invoice-debug 2023-04-01 18:48:34 +08:00
edmondlang e1c69f2de4 final-duplicated-invoice-debug 2023-04-01 18:35:15 +08:00
edmondlang 90b2bffd19 final-duplicated-invoice-debug 2023-04-01 18:31:02 +08:00
edmondlang 562815f9fe final-duplicated-invoice-debug 2023-04-01 18:27:04 +08:00
edmondlang 401db91437 final-duplicated-invoice-debug 2023-04-01 18:20:22 +08:00
edmondlang 0d1a623512 final-duplicated-invoice-debug 2023-04-01 17:36:59 +08:00
edmondlang 548a50c14a final-duplicated-invoice-debug 2023-04-01 17:33:51 +08:00
edmondlang 299512ec08 final-duplicated-invoice-debug 2023-04-01 17:29:28 +08:00
edmondlang 7241db7743 final-duplicated-invoice-debug 2023-04-01 17:27:13 +08:00
edmondlang ce24deea18 final-duplicated-invoice-debug 2023-04-01 17:11:07 +08:00
edmondlang c4642c2042 final-duplicated-invoice-debug 2023-04-01 17:06:37 +08:00
edmondlang 3871d8c010 clean up web routes 2023-04-01 16:01:20 +08:00
edmondlang cb65a1f29b fix bug billplz failed callback 2023-03-31 21:24:43 +08:00
edmondlang b1b13d7cbf fix bug billplz failed callback 2023-03-31 21:21:26 +08:00
Omair Saleh f6fa2fcf51 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	routes/web.php
2023-03-31 15:44:13 +08:00
Omair Saleh 6c00a57446 smc summary report 2023-03-31 15:43:04 +08:00
edmondlang 48445020fb adjust warehouse contact ui 2023-03-31 00:41:45 +08:00
edmondlang 46f1368a92 ui and api to update warehouse contact 2023-03-31 00:29:15 +08:00
edmondlang 82a16a5d9d update address 2023-03-30 17:26:19 +08:00
edmondlang 23002f61da update admin role type 2023-03-30 15:13:41 +08:00
edmondlang 2355c74b65 update customer/summary/monthly to 2023 records 2023-03-30 14:22:10 +08:00
edmondlang bd81560c3d remove console.log 2023-03-30 14:21:31 +08:00
edmondlang 575491e500 search admin in settings 2023-03-30 14:18:22 +08:00
edmondlang 1c703489b9 update admin role type 2023-03-30 12:47:02 +08:00
DESKTOP-5I7S92L\nicho 30ef3a7e41 fix call API bug for changeAdminRoleTypeForm 2023-03-30 12:35:30 +08:00
DESKTOP-5I7S92L\nicho f9b1289d28 call api 2023-03-30 12:28:45 +08:00
edmondlang 9fe49d8658 Merge branch 'master' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into update-admin-role-type 2023-03-30 12:16:04 +08:00
DESKTOP-5I7S92L\nicho e265b069d2 change button color to transparent 2023-03-30 12:12:35 +08:00
edmondlang f90818dbca updates user name and admin type api 2023-03-30 12:06:33 +08:00
DESKTOP-5I7S92L\nicho bfd490854d change admin role type 2023-03-30 11:53:54 +08:00
Dillon 94d96c96ea Another attempt to solve invoice without projectId, rewriting job chaining one after another 2023-03-30 05:58:26 +08:00
edmondlang feaab3cd8e check billplz failed callback 2023-03-30 00:37:09 +08:00
edmondlang 094801abbe check billplz failed callback 2023-03-30 00:35:59 +08:00
edmondlang 275d8880d9 check billplz failed callback 2023-03-30 00:30:12 +08:00
edmondlang 98843d0688 check billplz failed callback 2023-03-30 00:07:21 +08:00
edmondlang 317f4c2351 check billplz failed callback 2023-03-29 23:39:58 +08:00
edmondlang 83c7d70551 check billplz failed callback 2023-03-29 23:29:05 +08:00
Dillon Ngo 20099c416f Merge branch 'dillon/debug-and-fixes-2' into 'master'
New merge request From dillon/debug-and-fixes-2 into master

See merge request CIEFWorldwideSdnBhd/shipping-portal!159
2023-03-29 13:35:13 +00:00
Dillon 03b26e2af9 Typo error a to quick fix for update a CRM project 2023-03-29 13:14:49 +08:00
Dillon Ngo eb399dcbae Merge branch 'dillon/debug-and-fixes-2' into 'master'
New merge request From dillon/debug-and-fixes-2 into master

See merge request CIEFWorldwideSdnBhd/shipping-portal!158
2023-03-28 16:03:34 +00:00
Dillon d602200140 A quick fix 2023-03-29 00:01:48 +08:00
Dillon Ngo 84028b5ed7 Merge branch 'dillon/crm-create-task-3-26' into 'master'
New merge request From dillon/crm-create-task-3-26 into master

See merge request CIEFWorldwideSdnBhd/shipping-portal!157
2023-03-28 15:56:51 +00:00
Dillon 78ceb62dec Sync code fix from exchange 2023-03-28 23:35:49 +08:00
edmondlang 27190868b4 change company type 2023-03-28 16:15:07 +08:00
edmondlang b897b00703 change company type 2023-03-28 15:53:14 +08:00
DESKTOP-5I7S92L\nicho cd93deac26 change company type 2023-03-28 15:35:13 +08:00
edmondlang 0d0e147647 update dummy data seeder generate and approve invoice 2023-03-26 22:48:12 +08:00
edmondlang efba270ea5 update dummy seeder data - postcode 2023-03-26 21:50:14 +08:00
edmondlang 69da484b72 update dummy seeder data - state charges, so the invoice total wont be in 0 2023-03-26 21:37:54 +08:00
Dillon b25adef107 Fix another error from production logs 2023-03-25 14:20:38 +08:00
Dillon 329aa4b496 Minor cleanup 2023-03-25 02:17:51 +08:00
Dillon a05609081b minor code streamline 2023-03-24 15:15:05 +08:00
Dillon 9d442c8cc4 CRM Task with dynamic data 2023-03-24 03:14:57 +08:00
Dillon f5df1adff8 Fix a problem with new registration uploadin documentg 2023-03-23 04:31:35 +08:00
Dillon 119e58c1c9 Added new task, new task details such as priority and due date + some cleanup 2023-03-23 04:18:17 +08:00
Dillon b08ba3e716 Exchange - changes code sync 2023-03-22 22:19:31 +08:00
edmondlang 2169f09ffe billplz failed callback payment 2023-03-22 19:36:26 +08:00
edmondlang 1dfbc71302 billplz failed callback payment 2023-03-22 13:50:11 +08:00
edmondlang 57cdedbdd0 update billplz callback logic 2023-03-21 16:58:12 +08:00
edmondlang fea03de5bd audit billplz invoice 2023-03-21 13:08:05 +08:00
edmondlang 75babc9f38 audit billplz invoice 2023-03-21 13:03:27 +08:00
edmondlang a36f7123e8 audit billplz invoice 2023-03-21 12:56:53 +08:00
Dillon Ngo fad56e30dc Merge branch 'dillon/debug-and-fixes-1' into 'master'
Fix a problem in invoice where rounding issue cause an invoice that is fully...

See merge request CIEFWorldwideSdnBhd/shipping-portal!154
2023-03-20 14:17:04 +00:00
Dillon Ngo 6b56899004 Merge branch 'dillon/crm-invoice-update-23' into 'master'
Dillon/crm invoice update 23

See merge request CIEFWorldwideSdnBhd/shipping-portal!155
2023-03-20 14:16:13 +00:00
edmondlang 37444e6e30 update billing question display position 2023-03-20 18:05:29 +08:00
Dillon 32591273f8 Fix a problem in invoice where rounding issue cause an invoice that is fully paid to appear partially paid 2023-03-19 22:21:10 +08:00
Dillon f73b1d7fe3 Fix a problem at CRM where downloading of invoice in PDF throws errors 2023-03-19 22:20:49 +08:00
Dillon 0d4f7e0ed5 Another attempt to fix an error where invoice created at crm has no project id 2023-03-19 17:34:34 +08:00
Dillon 9786198ca2 Fix Error: BadMethodCallException: Call to undefined method 2023-03-19 16:31:30 +08:00
Dillon 76a9af2dc8 Fix a problem of a mismatch in data update for invoice 2023-03-19 04:50:12 +08:00
Dillon 3dcf3cff10 Update CRM invoice due date 2023-03-19 04:29:50 +08:00
Dillon Ngo 37da620927 Merge branch 'dillon/debug-and-fixes-1' into 'master'
Insert logs for debugging

See merge request CIEFWorldwideSdnBhd/shipping-portal!153
2023-03-18 08:28:57 +00:00
Dillon 64ec76eed6 Insert logs for debugging 2023-03-17 17:28:18 +08:00
edmondlang ef3c738fb1 debug billplz payment 2023-03-15 19:58:05 +08:00
edmondlang 92b6e6dc3a debug billplz payment 2023-03-15 19:48:48 +08:00
Dillon Ngo 0d330447eb Merge branch 'dillon/crm-tasks-department' into 'master'
CRM add department custom field to tasks

See merge request CIEFWorldwideSdnBhd/shipping-portal!152
2023-03-14 12:41:49 +00:00
Omair Saleh daeb376aa5 billplz audit 2023-03-13 16:05:41 +08:00
Omair Saleh f4d81cbde9 Merge remote-tracking branch 'origin/master' 2023-03-13 16:03:18 +08:00
Omair Saleh 0fd3584af2 billplz audit 2023-03-13 16:03:05 +08:00
edmondlang a2f70f266d billplz audit 2023-03-13 06:57:19 +08:00
Omair Saleh 432ce2d14a billplz audit 2023-03-13 01:42:14 +08:00
edmondlang 715384f4a4 audit billplz 2023-03-13 00:42:44 +08:00
edmondlang 8277b9d0fd fix bug unsuccessfull payment can went through 2023-03-13 00:32:59 +08:00
Dillon 4769541535 CRM add department custom field to tasks 2023-03-12 17:37:49 +08:00
Dillon Ngo fe8b6d0518 Merge branch 'dillon/crm-create-task-2' into 'master'
Add in missing update project function

See merge request CIEFWorldwideSdnBhd/shipping-portal!151
2023-03-11 11:45:11 +00:00
Dillon Ngo c078a879d2 Merge branch 'dillon/crm-feed-improvement-1' into 'master'
Dillon/crm feed improvement 1

See merge request CIEFWorldwideSdnBhd/shipping-portal!150
2023-03-11 08:56:40 +00:00
Dillon Ngo c58f2e55d7 Merge branch 'dillon/crm-create-task-2' into 'master'
Dillon/crm create task 2

See merge request CIEFWorldwideSdnBhd/shipping-portal!149
2023-03-11 08:56:25 +00:00
edmondlang 9f8ba5163c fix list admin user 2023-03-10 19:23:01 +08:00
Dillon b06cef4045 Feedback from user on crm leads registration 2023-03-10 17:58:13 +08:00
129 changed files with 4750 additions and 616 deletions
+4
View File
@@ -55,3 +55,7 @@ EXCHANGE_URL=https://dev.exchange.cief-malaysia.com/
MIX_EXCHANGE_URL="${EXCHANGE_URL}"
YD_API_CODE=''
PERFEXCRM_BASE_URL=""
PERFEXCRM_API_KEY=""
PERFEXCRM_IS_ENABLED="false"
@@ -0,0 +1,19 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class AmountExceed implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->where('amount', '>', $value);
}
}
@@ -0,0 +1,19 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class AmountShort implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->where('amount', '<', $value);
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
class CreatedBefore implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->where('created_at', '<', Carbon::parse($value));
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class EmailLike implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->where('email', 'LIKE', '%'.$value.'%');
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class PaymentMethod implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->where('payment_method', $value);
}
}
+19 -2
View File
@@ -2,8 +2,8 @@
namespace App\Classes\General;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Log;
class Helper
{
@@ -24,4 +24,21 @@ class Helper
return array_slice(get_class_methods($className), 1);
}
}
/**
* @param $log
* @return none
*/
static function debugLoggerForPerfexCRM($log){
if($log){
$message = $log['message'];
$substring = 'No data were found';
if (isset($message)) {
if (strpos($message, $substring) !== false) {
// Log::info('Message exist');
} else {
Log::info($log['message']);
}
}
}
}
}
+9 -1
View File
@@ -3,6 +3,8 @@
namespace App\Classes\Jobs;
use App\Classes\Modules\PerfexCRM\Processors\CreatePerfexCRMLeadProcessor;
use App\Classes\Modules\PerfexCRM\Services\FetchesPerfexCRMLead;
use App\Classes\Modules\PerfexCRM\Services\UpdatesPerfexCRMLead;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
@@ -28,6 +30,12 @@ class CreatePerfexCRMCustomer implements ShouldQueue
public function handle()
{
(App()->make(CreatePerfexCRMLeadProcessor::class))->execute($this->createLeadPerfexCRMObject);
$lead = (App()->make(FetchesPerfexCRMLead::class))->execute($this->createLeadPerfexCRMObject->getEmail());
if(!is_null($lead)){
(App()->make(UpdatesPerfexCRMLead::class))->execute($lead, $this->createLeadPerfexCRMObject->getCompanyReference());
}
else{
(App()->make(CreatePerfexCRMLeadProcessor::class))->execute($this->createLeadPerfexCRMObject);
}
}
}
-33
View File
@@ -1,33 +0,0 @@
<?php
namespace App\Classes\Jobs;
use App\Classes\Modules\PerfexCRM\Processors\InitializePerfexCRMProcessor;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\InitialPerfexCRMObject;
class InitializePerfexCRM implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/** @var InitialPerfexCRMObject */
private $initialPerfexCRMObject;
/**
* InitializePerfexCRM constructor.
* @param InitialPerfexCRMObject $initialPerfexCRMObject
*/
public function __construct(InitialPerfexCRMObject $initialPerfexCRMObject)
{
$this->initialPerfexCRMObject = $initialPerfexCRMObject;
}
public function handle()
{
(App()->make(InitializePerfexCRMProcessor::class))->execute($this->initialPerfexCRMObject);
}
}
+23 -2
View File
@@ -9,6 +9,7 @@ use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\UpdatePerfexCRMObject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\UpdatePerfexCRMInvoiceObject;
class UpdatePerfexCRM implements ShouldQueue
{
@@ -17,17 +18,37 @@ class UpdatePerfexCRM implements ShouldQueue
/** @var UpdatePerfexCRMObject */
private $updatePerfexCRMObject;
/** @var UpdatePerfexCRMInvoice */
private $nextJob;
/** @var */
private $transaction;
/**
* UpdatePerfexCRM constructor.
* @param UpdatePerfexCRMObject $updatePerfexCRMObject
* @param UpdatePerfexCRMInvoice $nextJob
* @param $transaction
*/
public function __construct(UpdatePerfexCRMObject $updatePerfexCRMObject)
public function __construct(UpdatePerfexCRMObject $updatePerfexCRMObject, $transaction, $nextJob)
{
$this->updatePerfexCRMObject = $updatePerfexCRMObject;
$this->nextJob = $nextJob;
$this->transaction = $transaction;
}
public function handle()
{
(App()->make(UpdatePerfexCRMProcessor::class))->execute($this->updatePerfexCRMObject);
$result = (App()->make(UpdatePerfexCRMProcessor::class))->execute($this->updatePerfexCRMObject);
if($this->nextJob != null && $this->transaction != null){
$updatePerfexCRMInvoiceOject = new UpdatePerfexCRMInvoiceObject(
$this->updatePerfexCRMObject->getContactEmail(),
$result->projectId,
$this->transaction,
true
);
/** @var UpdatePerfexCRMInvoice $nextJob */
$this->nextJob::dispatch($updatePerfexCRMInvoiceOject);
}
}
}
+18 -14
View File
@@ -18,6 +18,8 @@ use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use App\Classes\General\Helper;
class UpdatePerfexCRMInvoice implements ShouldQueue
{
@@ -45,10 +47,16 @@ class UpdatePerfexCRMInvoice implements ShouldQueue
$invoiceId = 0;
$invoiceStatus = 0;
$invoice = (App()->make(FetchesPerfexCRMInvoice::class))->execute($customer->userid,"INV-", $transaction->owner->bill_no);
Log::error(json_encode('UpdatePerfexCRMInvoice debug $transaction->owner->bill_no: '.$transaction->owner->bill_no));
if(is_null($invoice)){
$result = (App()->make(CreatePerfexCRMInvoiceProcessor::class))->execute($transaction->owner, $this->updatePerfexCRMInvoiceObject->getIsPaid());
$invoiceId = $result->payload['id'];
if ($result) {
$invoiceId = $result->payload['id'];
} else {
// Log::error(json_encode('UpdatePerfexCRMInvoice CreatePerfexCRMInvoiceProcessor failed'));
Helper::debugLoggerForPerfexCRM('UpdatePerfexCRMInvoice CreatePerfexCRMInvoiceProcessor failed');
}
}
else{
$invoiceId = $invoice->id;
@@ -56,20 +64,9 @@ class UpdatePerfexCRMInvoice implements ShouldQueue
//This only run when invoice already exist and the invoice does not have a PAID status
if($invoiceStatus != PerfexCRMInvoiceStatus::PAID){
//get project
$projectId = "";
if($transaction->owner instanceof Transaction){
$orderReference = $transaction->owner->owner->owner()->first()->reference;
$packingListReference = $transaction->owner->owner->reference;
$projectName = 'IZYIM | X1 Shipping | '.$orderReference.' | '.$packingListReference;
$project = (App()->make(FetchesPerfexCRMProject::class))->execute($projectName, $customer->userid);
if(!is_null($project)){
$projectId = $project->id;
}
}
Log::error(json_encode('UpdatePerfexCRMInvoice debug $this->updatePerfexCRMInvoiceObject->getProjectId(): '.$this->updatePerfexCRMInvoiceObject->getProjectId()));
//update invoice
(App()->make(UpdatesPerfexCRMInvoice::class))->execute($invoice, $projectId);
(App()->make(UpdatesPerfexCRMInvoice::class))->execute($invoice, $this->updatePerfexCRMInvoiceObject->getProjectId());
}
}
@@ -89,4 +86,11 @@ class UpdatePerfexCRMInvoice implements ShouldQueue
(App()->make(CreatesPerfexCRMInvoicePayment::class))->execute($invoicePaymentPerfexCRMObject);
}
}
public function delay($delay)
{
// Add delay in seconds to the job
$this->delay = $delay;
return $this;
}
}
@@ -0,0 +1,96 @@
<?php
namespace App\Classes\Jobs;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\UpdatePerfexCRMObject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\UpdatePerfexCRMInvoiceObject;
use App\Models\PackingList;
use App\Models\Transaction;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
class UpdatePerfexCRMPrelude implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/** @var */
private $packingList;
/** @var */
private $transaction;
/** @var UpdatePerfexCRMObject */
private $updatePerfexCRMObject;
/** @var UpdatePerfexCRM */
private $nextJob1;
/** @var UpdatePerfexCRMInvoice */
private $nextJob2;
/**
* UpdatePerfexCRMPrelude constructor.
* @param $packingList
* @param $transaction
* @param UpdatePerfexCRMObject $updatePerfexCRMObject
* @param UpdatePerfexCRM $nextJob1
* @param UpdatePerfexCRMInvoice $nextJob2
*/
public function __construct($packingList, $transaction, UpdatePerfexCRMObject $updatePerfexCRMObject, $nextJob1, $nextJob2)
{
$this->packingList = $packingList;
$this->transaction = $transaction;
$this->updatePerfexCRMObject = $updatePerfexCRMObject;
$this->nextJob1 = $nextJob1;
$this->nextJob2 = $nextJob2;
}
public function handle()
{
if(is_null($this->packingList)){
$this->packingList = $this->transaction->owner->owner;
}
$amount = 0.00;
if(!is_null($this->transaction)){
$amount = $this->transaction->amount;
}
$data = [
'amount' => number_format($amount, 2, '.', ''),
'link_order' => config('app.url').'/order/show/'.$this->packingList->owner->reference,
'link_autocount_or' => 'https://docs.google.com/spreadsheets/d/1Q3rJBGQ9Bo04HZp5WR9zbLp7pIW2kfDYsabxG7JON-4/edit#gid=2013983170',
'link_perfex' => 'https://perfex.cief-malaysia.com/admin/projects/view/89',
];
$result = $this->replacePlaceholders($this->updatePerfexCRMObject->getTasks(), $data);
$this->updatePerfexCRMObject->setTasks($result);
/** @var UpdatePerfexCRM $nextJob1 */
/** @var UpdatePerfexCRMInvoice $nextJob2 */
$this->nextJob1::dispatch($this->updatePerfexCRMObject, $this->transaction, $this->nextJob2);
}
function replacePlaceholders($template, $data, $prefix = '')
{
foreach ($template as $key => $value) {
foreach ($data as $dataKey => $dataValue) {
if (is_array($dataValue)) {
$template[$key] = $this->replacePlaceholders($template[$key], $dataValue, $dataKey);
} else {
if ($prefix != '') {
$template[$key] = str_replace('{' .$prefix. "." .$dataKey . '}', $dataValue, $template[$key]);
} else {
$template[$key] = str_replace('{' . $dataKey . '}', $dataValue, $template[$key]);
}
}
}
}
return $template;
}
}
@@ -161,7 +161,8 @@ class CreateCustomerLogic extends AbstractControllerLogic
$request->input('name'),
$request->input('email'),
$request->input('phone'),
$request->input('type') === CompanyType::COMPANY_BUSINESS ? $request->input('company_name') : $request->input('name')
$request->input('type') === CompanyType::COMPANY_BUSINESS ? $request->input('company_name') : $request->input('name'),
$connection->invitee_reference
);
CreatePerfexCRMCustomer::dispatch($createLeadPerfexCRMObject);
}
@@ -4,7 +4,7 @@ namespace App\Classes\Modules\Accounts\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Accounts\Services\UpdatesUser;
use App\Classes\Modules\Accounts\Services\UpdatesUserFullName;
use App\Classes\Modules\Accounts\Services\FetchesUser;
use App\Classes\Modules\Accounts\Standards\Rules\CanUpdateUser;
use App\Classes\Modules\Accounts\DataTransferObjects\FullNameObject;
@@ -29,8 +29,8 @@ class UpdateUserLogic extends AbstractControllerLogic
/** @var CanUpdateUser */
private $canUpdateUser;
/** @var UpdatesUser */
private $updatesUser;
/** @var UpdatesUserFullName */
private $updatesUserFullName;
/** @var FetchesUser */
private $fetchesUser;
@@ -38,13 +38,13 @@ class UpdateUserLogic extends AbstractControllerLogic
/**
* UpdateAddressLogic constructor.
* @param CanUpdateUser $canUpdateUser
* @param UpdatesUser $updatesUser
* @param UpdatesUserFullName $updatesUserFullName
* @param FetchesUser $fetchesUSer
*/
public function __construct(CanUpdateUser $canUpdateUser, UpdatesUser $updatesUser, FetchesUser $fetchesUser)
public function __construct(CanUpdateUser $canUpdateUser, UpdatesUserFullName $updatesUserFullName, FetchesUser $fetchesUser)
{
$this->canUpdateUser = $canUpdateUser;
$this->updatesUser = $updatesUser;
$this->updatesUserFullName = $updatesUserFullName;
$this->fetchesUser = $fetchesUser;
}
@@ -64,7 +64,7 @@ class UpdateUserLogic extends AbstractControllerLogic
$query = $this->fetchesUser->execute(['id' => $request->route('id')]);
$query = $this->updatesUser->execute($query, $object);
$query = $this->updatesUserFullName->execute($query, $object);
return $this->resourceResponse(new UserResource($query));
@@ -0,0 +1,71 @@
<?php
namespace App\Classes\Modules\Accounts\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Accounts\Services\UpdatesUser;
use App\Classes\Modules\Accounts\Services\FetchesUser;
use App\Classes\Modules\Accounts\Standards\Rules\CanUpdateUser;
use App\Classes\Modules\Accounts\DataTransferObjects\FullNameObject;
use App\Classes\Modules\Accounts\DataTransferObjects\UserObject;
use App\Http\Resources\UserResource;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class UpdateUserRoleLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Updated Admin Role',
'message' => 'You have successfully updated the Admin Role'
];
}
/** @var CanUpdateUser */
private $canUpdateUser;
/** @var UpdatesUser */
private $updatesUser;
/** @var FetchesUser */
private $fetchesUser;
/**
* UpdateAddressLogic constructor.
* @param CanUpdateUser $canUpdateUser
* @param UpdatesUser $updatesUser
* @param FetchesUser $fetchesUSer
*/
public function __construct(CanUpdateUser $canUpdateUser, UpdatesUser $updatesUser, FetchesUser $fetchesUser)
{
$this->canUpdateUser = $canUpdateUser;
$this->updatesUser = $updatesUser;
$this->fetchesUser = $fetchesUser;
}
/**
* @param Request $request
* @return JsonResponse
* @throws ErrorException
*/
public function logic(Request $request) : JsonResponse
{
$query = $this->fetchesUser->execute(['id' => $request->route('id')]);
$object = new UserObject($query->name, $request->input('type'));
$this->canUpdateUser->passes($object);
$query = $this->updatesUser->execute($query, $object);
return $this->resourceResponse(new UserResource($query));
}
}
@@ -0,0 +1,40 @@
<?php
namespace App\Classes\Modules\Accounts\DataTransferObjects;
use App\Classes\General\Interfaces\DataTransferObject;
class UserObject implements DataTransferObject
{
/** @var string */
private $name;
/** @var int */
private $type;
/**
* FullNameObject constructor.
* @param string $name
*/
public function __construct(string $name, int $type)
{
$this->name = $name;
$this->type = $type;
}
/**
* @return string
*/
public function getName(): string
{
return $this->name;
}
/**
* @return int
*/
public function getType(): int
{
return $this->type;
}
}
@@ -3,7 +3,7 @@
namespace App\Classes\Modules\Accounts\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Classes\Modules\Accounts\DataTransferObjects\FullNameObject;
use App\Classes\Modules\Accounts\DataTransferObjects\UserObject;
use App\Models\User;
class UpdatesUser extends AbstractUpdateRecord
@@ -11,13 +11,14 @@ class UpdatesUser extends AbstractUpdateRecord
/**
* @param User $model
* @param FullNameObject $object
* @param UserObject $object
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(User $model, FullNameObject $object) {
public function execute(User $model, UserObject $object) {
$model->name = $object->getName();
$model->type = $object->getType();
return $this->handler($model);
}
@@ -0,0 +1,24 @@
<?php
namespace App\Classes\Modules\Accounts\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Classes\Modules\Accounts\DataTransferObjects\FullNameObject;
use App\Models\User;
class UpdatesUserFullName extends AbstractUpdateRecord
{
/**
* @param User $model
* @param FullNameObject $object
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(User $model, FullNameObject $object) {
$model->name = $object->getName();
return $this->handler($model);
}
}
@@ -10,7 +10,7 @@ use App\Classes\Modules\Announcements\Services\FetchesAnnouncement;
use App\Classes\Modules\Announcements\Services\UpdatesAnnouncement;
use App\Http\Resources\AnnouncementResource;
use Carbon\Carbon;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -66,8 +66,8 @@ class UpdateAnnouncementLogic extends AbstractControllerLogic
$annoucement_object = new AnnouncementObject(
$request->input('title'),
$request->input('description'),
$request->input('starting_on'),
$request->input('ending_on')
Carbon::createFromFormat('d-m-Y', $request->input('starting_on'))->format('Y-m-d H:i:s'),
Carbon::createFromFormat('d-m-Y', $request->input('ending_on'))->format('Y-m-d H:i:s')
);
$this->canUpdateAnnouncement->passes($annoucement_object);
@@ -23,6 +23,7 @@ use App\Classes\Modules\Billplzs\DataTransferObjects\BillplzXSignatureObject;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Transactions\Services\FetchesTransaction;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
@@ -101,9 +102,11 @@ class CallbackBillplzLogic
$token = Auth::fromUser(User::find(1));
$request->headers->set('Authorization', 'Bearer '.$token);
$this->updatesTransactionStatus->execute($transaction, ApprovalStatus::APPROVED);
$this->updatesTransactionStatus->execute($transaction, $status);
if(($invoice->amount - $transaction->amount) < 0.01) {
$totalPaidAmount = $invoice->transactions->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->sum('amount');
if(($invoice->amount - $totalPaidAmount) < 0.01) {
$this->updatesTransactionStatus->execute($invoice, ApprovalStatus::COMPLETED);
$packingList->status = ApprovalStatus::APPROVED;
@@ -0,0 +1,69 @@
<?php
namespace App\Classes\Modules\Companies\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Companies\Services\UpdatesCompany;
use App\Classes\Modules\Companies\Services\FetchesCompany;
use App\Classes\Modules\Companies\Standards\Rules\CanUpdateCompany;
use App\Classes\Modules\Companies\DataTransferObjects\CompanyObject;
use App\Http\Resources\CompanyResource;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class UpdateCompanyTypeLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Updated Company Type',
'message' => 'You have successfully updated the Company Tyoe'
];
}
/** @var CanUpdateCompany */
private $canUpdateCompany;
/** @var UpdatesCompany */
private $updatesCompany;
/** @var FetchesCompany */
private $fetchesCompany;
/**
* UpdateCompanyControllersLogic constructor.
* @param CanUpdateCompany $canUpdateCompany
* @param UpdatesCompany $updatesCompany
* @param FetchesCompany $fetchesCompany
*/
public function __construct(CanUpdateCompany $canUpdateCompany, UpdatesCompany $updatesCompany, FetchesCompany $fetchesCompany)
{
$this->canUpdateCompany = $canUpdateCompany;
$this->updatesCompany = $updatesCompany;
$this->fetchesCompany = $fetchesCompany;
}
/**
* @param Request $request
* @return JsonResponse
* @throws ErrorException
*/
public function logic(Request $request) : JsonResponse
{
$query = $this->fetchesCompany->execute(['id' => $request->route('id')]);
$object = new CompanyObject($query->name, $query->reference, $request->input('type'));
$this->canUpdateCompany->passes($object);
$query = $this->updatesCompany->execute($query, $object);
return $this->resourceResponse(new CompanyResource($query));
}
}
@@ -0,0 +1,69 @@
<?php
namespace App\Classes\Modules\Contacts\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Contacts\Services\UpdatesContact;
use App\Classes\Modules\Contacts\DataTransferObjects\ContactObject;
use App\Classes\Modules\Contacts\Services\FetchesContact;
use App\Http\Resources\ContactResource;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class UpdateContactLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Updated Contact',
'message' => 'You have successfully updated the Contact'
];
}
/** @var UpdatesContact */
private $updatesContact;
/** @var FetchesContact */
private $fetchesContact;
/**
* UpdateContactLogic constructor.
* @param UpdatesContact $updatesContact
* @param FetchesContact $fetchesContact
*/
public function __construct(UpdatesContact $updatesContact, FetchesContact $fetchesContact)
{
$this->updatesContact = $updatesContact;
$this->fetchesContact = $fetchesContact;
}
/**
* @param Request $request
* @return JsonResponse
* @throws ErrorException
*/
public function logic(Request $request) : JsonResponse
{
$object = new ContactObject(
$request->input('reference'),
$request->input('phone'),
$request->input('email'),
$request->input('wechat_id')
);
// $this->canUpdateContact->passes($object);
$query = $this->fetchesContact->execute(['id' => $request->route('id')]);
$query = $this->updatesContact->execute($query, $object);
return $this->resourceResponse(new ContactResource($query));
}
}
@@ -0,0 +1,32 @@
<?php
namespace App\Classes\Modules\Contacts\Services;
use App\Classes\General\Eloquent\AbstractFetchRecord;
use Illuminate\Database\Eloquent\Builder;
use App\Models\Contact;
class FetchesContact extends AbstractFetchRecord
{
/** @var Contact */
private $repository;
/**
* FetchesContact constructor.
* @param Contact $repository
*/
public function __construct(Contact $repository)
{
$this->repository = $repository;
}
/**
* @return Builder
*/
public function getRepository(): Builder
{
return $this->repository->newQuery();
}
}
@@ -0,0 +1,26 @@
<?php
namespace App\Classes\Modules\Contacts\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Classes\Modules\Contacts\DataTransferObjects\ContactObject;
use App\Models\Contact;
class UpdatesContact extends AbstractUpdateRecord
{
/**
* @param Contact $model
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(Contact $model, ContactObject $object)
{
$model->reference = $object->getReference();
$model->phone = $object->getPhone();
$model->email = $object->getEmail();
$model->wechat_id = $object->getWechatId();
return $this->handler($model);
}
}
@@ -39,7 +39,12 @@ class ExportsPaymentTransactions implements FromQuery, WithHeadings, WithHeading
'ProjNo',
'DeptNo',
'Qty',
'UnitPrice'
'UnitPrice',
// 'marking',
// 'contact person',
// 'contact number',
// 'link',
// 'amount'
];
}
@@ -97,6 +102,10 @@ class ExportsPaymentTransactions implements FromQuery, WithHeadings, WithHeading
$order = $transaction->owner->owner;
$company = $order->companyModule->company;
$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();
$link = route('customer.payment-and-billing', $marking);
$furtherDescription = '';
@@ -123,7 +132,12 @@ class ExportsPaymentTransactions implements FromQuery, WithHeadings, WithHeading
$container->reference,
'CIEF',
$shippingTransactionDetails->quantity,
$shippingTransactionDetails->price
$shippingTransactionDetails->price,
// $marking,
// $contact ? $contact->phone : '',
// $userName->name,
// $link,
// $transaction->amount
];
return [
'<<New>>',
@@ -18,7 +18,8 @@ use Illuminate\Http\JsonResponse;
class CreateOrderLogic extends AbstractControllerLogic
{
protected function notification():array {
protected function notification(): array
{
return [
'title' => 'Created Order',
'message' => 'You have successfully created a new Order'
@@ -62,19 +63,31 @@ class CreateOrderLogic extends AbstractControllerLogic
}
public function logic(Request $request) : JsonResponse {
public function logic(Request $request): JsonResponse
{
$company = $this->fetchesCompany->execute(['id' => $request->input('company_id')]);
$address = $this->fetchesAddress->execute(['id' => $request->input('address_id')]);
$originWarehouse = $this->fetchesCompanyModule->execute(['id' => $request->input('warehouse_id')]);
// todo-new: fix this
// if select warehouse foshan
if ($request->input('warehouse_id') === 'foshan') {
// 13 - sabah, 14 - sarawak
if (in_array($address->state->id, [13, 14])) {
$originWarehouse = $this->fetchesCompanyModule->execute(['reference' => WarehouseReferences::YD_FS_WEST_MALAYSIA]);
} else {
$originWarehouse = $this->fetchesCompanyModule->execute(['reference' => WarehouseReferences::YD_FS_WEST_MALAYSIA]);
}
} else {
$originWarehouse = $this->fetchesCompanyModule->execute(['id' => $request->input('warehouse_id')]);
if(!in_array($company->companyModules()->importers()->first()->id, WarehouseReferences::YD_EXEMPT_LIST)){
$originWarehouse = $this->fetchesCompanyModule->execute(['reference' => $originWarehouse->reference === WarehouseReferences::VT_GUANG_ZHOU ? WarehouseReferences::YD_GUANG_ZHOU : WarehouseReferences::YD_YIWU]);
if (!in_array($company->companyModules()->importers()->first()->id, WarehouseReferences::YD_EXEMPT_LIST)) {
$originWarehouse = $this->fetchesCompanyModule->execute(['reference' => $originWarehouse->reference === WarehouseReferences::VT_GUANG_ZHOU ? WarehouseReferences::YD_GUANG_ZHOU : WarehouseReferences::YD_YIWU]);
}
}
if($originWarehouse->reference === WarehouseReferences::YD_YIWU && in_array($address->state_id, [5, 13, 14])) {
throw new RequestValidationException('Our Yiwu warehouse is unable to ship goods to Sabah & Sarawak at the moment. you can select our Guangzhou warehouse as an alternative.');
}
@@ -0,0 +1,60 @@
<?php
namespace App\Classes\Modules\Orders\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Orders\Services\FetchesOrder;
use App\Classes\Modules\Orders\Standards\Rules\CanFetchOrder;
use App\Http\Resources\OrderV2Resource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class FetchOrderV2Logic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Retrieved Order',
'message' => 'You have successfully retrieved an order'
];
}
/** @var CanFetchOrder */
private $canFetchOrder;
/** @var FetchesOrder */
private $fetchesOrder;
/**
* FetchOrderLogic constructor.
* @param CanFetchOrder $canFetchOrder
* @param FetchesOrder $fetchesOrder
*/
public function __construct(CanFetchOrder $canFetchOrder, FetchesOrder $fetchesOrder)
{
$this->canFetchOrder = $canFetchOrder;
$this->fetchesOrder = $fetchesOrder;
}
/**
* @param Request $request
* @return JsonResponse
* @throws \App\Classes\Exceptions\AccessForbiddenException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
public function logic(Request $request) : JsonResponse
{
$this->canFetchOrder->passes();
$query = $this->fetchesOrder->execute(['reference' => $request->route('id'), 'with_packing_lists' => true]);
return $this->resourceResponse(new OrderV2Resource($query));
}
}
@@ -0,0 +1,56 @@
<?php
namespace App\Classes\Modules\Orders\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Orders\Services\ListsOrders;
use App\Classes\Modules\Orders\Standards\Rules\CanListOrders;
use App\Classes\ValueObjects\Constants\OrderType;
use App\Http\Resources\OrderV2Resource;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class ListOrdersV2Logic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Retrieved Orders',
'message' => 'You have successfully retrieved a list of Orders'
];
}
/** @var CanListOrders */
private $canListOrders;
/** @var ListsOrders */
private $listsOrders;
/**
* ListOrdersLogic constructor.
* @param CanListOrders $canListOrders
* @param ListsOrders $listsOrders
*/
public function __construct(CanListOrders $canListOrders, ListsOrders $listsOrders)
{
$this->canListOrders = $canListOrders;
$this->listsOrders = $listsOrders;
}
public function logic(Request $request) : JsonResponse
{
$this->canListOrders->passes();
$query = $this->listsOrders->execute(array_merge($this->listsOrders->deserializeFilters($request->input('filters')), ['with_parcels' => true, 'type_in' => [OrderType::SHARED_CONTAINER, OrderType::DEDICATED_CONTAINER]]));
return $this->collectionResponse(OrderV2Resource::collection($query));
}
}
@@ -0,0 +1,81 @@
<?php
namespace App\Classes\Modules\PackingLists\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\PackingLists\Services\DeletesPackingList;
use App\Classes\Modules\PackingLists\Services\FetchesPackingList;
use App\Classes\Modules\PackingLists\Services\Packages\FetchesPackage;
use App\Classes\Modules\PackingLists\Standards\Rules\CanDeletePackingList;
use App\Classes\ValueObjects\Constants\PackingListType;
use App\Models\PackingList;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class DeletePackingListByPackageIdLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Deleted PackingList',
'message' => 'You have successfully deleted a PackingList'
];
}
/** @var CanDeletePackingList */
private $canDeletePackingList;
/** @var DeletesPackingList */
private $deletesPackingList;
/** @var FetchesPackingList */
private $fetchesPackingList;
/** @var FetchesPackage */
private $fetchesPackage;
/**
* DeletePackingListByPackageIdLogic constructor.
* @param CanDeletePackingList $canDeletePackingList
* @param DeletesPackingList $deletesPackingList
* @param FetchesPackingList $fetchesPackingList
* @param FetchesPackage $fetchesPackage
*/
public function __construct(CanDeletePackingList $canDeletePackingList, DeletesPackingList $deletesPackingList, FetchesPackingList $fetchesPackingList, FetchesPackage $fetchesPackage)
{
$this->canDeletePackingList = $canDeletePackingList;
$this->deletesPackingList = $deletesPackingList;
$this->fetchesPackingList = $fetchesPackingList;
$this->fetchesPackage = $fetchesPackage;
}
/**
* @param Request $request
* @return JsonResponse
* @throws ErrorException
*/
public function logic(Request $request) : JsonResponse
{
$this->canDeletePackingList->passes();
$package = $this->fetchesPackage->execute(['id' => $request->route('id')]);
$packingList = $package->packingList;
$packingList = PackingList::where('reference', $packingList->reference)->get();
$childPackingList = PackingList::where('owner_type', PackingList::class)->whereIn('owner_id', $packingList->pluck('id'))->get();
$packingList->each->delete();
$childPackingList->each->delete();
return $this->response([]);
}
}
@@ -19,13 +19,17 @@ class CreateLeadPerfexCRMObject implements DataTransferObject
/** @var string */
private $companyName;
public function __construct(string $name, string $email, string $phone, string $companyName)
/** @var string */
private $companyReference;
public function __construct(string $name, string $email, string $phone, string $companyName, string $companyReference)
{
$this->name = $name;
$this->email = $email;
$this->phone = $phone;
$this->companyName = $companyName;
$this->companyReference = $companyReference;
}
/**
@@ -60,4 +64,11 @@ class CreateLeadPerfexCRMObject implements DataTransferObject
return $this->companyName;
}
/**
* @return string
*/
public function getCompanyReference(): string
{
return $this->companyReference;
}
}
@@ -33,8 +33,16 @@ class CreateTaskPerfexCRMObject implements DataTransferObject
/** @var string */
private $status;
/** @var string */
private $department;
public function __construct(string $email, string $name, string $description, string $leadId, string $projectId, string $milestoneId, string $reference, string $onTaskCompletion, string $status)
/** @var string */
private $priority;
/** @var string */
private $duedate;
public function __construct(string $email, string $name, string $description, string $leadId, string $projectId, string $milestoneId, string $reference, string $onTaskCompletion, string $status, string $department, string $priority, string $duedate)
{
$this->email = $email;
$this->name = $name;
@@ -45,6 +53,9 @@ class CreateTaskPerfexCRMObject implements DataTransferObject
$this->reference = $reference;
$this->onTaskCompletion = $onTaskCompletion;
$this->status = $status;
$this->department = $department;
$this->priority = $priority;
$this->duedate = $duedate;
}
/**
@@ -124,4 +135,27 @@ class CreateTaskPerfexCRMObject implements DataTransferObject
return $this->status;
}
/**
* @return string
*/
public function getDepartment(): string
{
return $this->department;
}
/**
* @return string
*/
public function getPriority(): string
{
return $this->priority;
}
/**
* @return string
*/
public function getDuedate(): string
{
return $this->duedate;
}
}
@@ -17,11 +17,15 @@ class UpdatePerfexCRMInvoiceObject implements DataTransferObject
/** @var bool */
private $isPaid;
public function __construct(string $email, Transaction $transaction, bool $isPaid)
/** @var string */
private $projectId;
public function __construct(string $email, string $projectId, Transaction $transaction, bool $isPaid)
{
$this->email = $email;
$this->transaction = $transaction;
$this->isPaid = $isPaid;
$this->projectId = $projectId;
}
/**
@@ -32,6 +36,14 @@ class UpdatePerfexCRMInvoiceObject implements DataTransferObject
return $this->email;
}
/**
* @return string
*/
public function getProjectId(): string
{
return $this->projectId;
}
/**
* @return Transaction
*/
@@ -32,10 +32,10 @@ class UpdatePerfexCRMObject implements DataTransferObject
private $milestoneNames;
/** @var array */
private $taskNames;
private $tasks;
public function __construct(string $companyName, string $companyReference, string $contactName, string $contactEmail, string $bookingMarking, string $projectName, int $projectStatus, array $milestoneNames, array $taskNames)
public function __construct(string $companyName, string $companyReference, string $contactName, string $contactEmail, string $bookingMarking, string $projectName, int $projectStatus, array $milestoneNames, array $tasks)
{
$this->companyName = $companyName;
@@ -46,7 +46,7 @@ class UpdatePerfexCRMObject implements DataTransferObject
$this->projectName = $projectName;
$this->projectStatus = $projectStatus;
$this->milestoneNames = $milestoneNames;
$this->taskNames = $taskNames;
$this->tasks = $tasks;
}
/**
@@ -116,8 +116,13 @@ class UpdatePerfexCRMObject implements DataTransferObject
/**
* @return array
*/
public function getTaskNames(): array
public function getTasks(): array
{
return $this->taskNames;
return $this->tasks;
}
public function setTasks($tasks)
{
$this->tasks = $tasks;
}
}
@@ -14,6 +14,7 @@ use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMCustomerProject;
use App\Classes\ValueObjects\Constants\PerfexCRMProjectStatus;
use App\Models\PackingList;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
class CreatePerfexCRMInvoiceProcessor
{
@@ -67,8 +68,8 @@ class CreatePerfexCRMInvoiceProcessor
}
$date = Carbon::parse($transaction->created_at)->format('Y-m-d');
$dueDate = Carbon::parse($transaction->created_at)->format('Y-m-d');
$currency = 1; //cief TODO: To look into Malaysia and Chinese currency
$dueDate = Carbon::parse($transaction->created_at)->addDays(6)->startOfDay()->format('Y-m-d');
$currency = 1;
$subTotal = 0.00;
$total = 0.00;
@@ -79,12 +80,17 @@ class CreatePerfexCRMInvoiceProcessor
->where('status', '=', \App\Classes\ValueObjects\Constants\ApprovalStatus::APPROVED)
->where('type', '=', \App\Classes\ValueObjects\Constants\AddressType::BILLING)->first();
$billingStreet = $billingStreet.$addresses->street_one;
$billingStreet = $billingStreet.$addresses->street_two.',';
$billingStreet = $billingStreet.$addresses->district()->first()->name.',';
$billingStreet = $billingStreet.$addresses->postcode;
$billingStreet = $billingStreet.$addresses->state()->first()->name.',';
$billingStreet = $billingStreet.$addresses->country()->first()->name;
if ($addresses !== null) {
$billingStreet = $billingStreet.$addresses->street_one;
$billingStreet = $billingStreet.$addresses->street_two.',';
$billingStreet = $billingStreet.$addresses->district()->first()->name.',';
$billingStreet = $billingStreet.$addresses->postcode;
$billingStreet = $billingStreet.$addresses->state()->first()->name.',';
$billingStreet = $billingStreet.$addresses->country()->first()->name;
}
else{
$billingStreet = "[Pending Billing Details by user]";
}
$allowedPaymentModes = [];
$invoiceItems = [];
@@ -99,14 +105,16 @@ class CreatePerfexCRMInvoiceProcessor
//get project
$projectId = ""; //Project only exist in CRM if the customer already made payment
$projectName = "";
if($isPaid){
if($transaction->owner instanceof PackingList){
$orderReference = $transaction->owner->owner->reference;
$packingListReference = $transaction->owner->reference;
$projectName = 'IZYIM | X1 Shipping | '.$orderReference.' | '.$packingListReference;
$project = $this->fetchesPerfexCRMProject->execute($projectName, $clientId);
if(!is_null($project)){
$projectId = $project->id;
$result = $this->fetchesPerfexCRMProject->execute($projectName, $clientId);
if(isset($result->payload)){
$project = $result->payload[0];
$projectId = $project['id'];
}
else{
$result = $this->createsPerfexCRMCustomerProject->execute($projectName, PerfexCRMProjectStatus::NOT_STARTED, $clientId);
@@ -115,6 +123,11 @@ class CreatePerfexCRMInvoiceProcessor
}
}
}
if($projectId == ""){
Log::error(json_encode('CreatePerfexCRMInvoiceProcessor debug: '.$projectName));
Log::error(json_encode($transaction->owner));
}
}
//newitems
@@ -33,7 +33,10 @@ class CreatePerfexCRMTaskProcessor
$createTaskPerfexCRMObject->getProjectId(),
$createTaskPerfexCRMObject->getReference(),
$createTaskPerfexCRMObject->getOnTaskCompletion(),
$createTaskPerfexCRMObject->getDepartment(),
$createTaskPerfexCRMObject->getStatus(),
$createTaskPerfexCRMObject->getPriority(),
$createTaskPerfexCRMObject->getDuedate()
);
return true;
}
@@ -1,195 +0,0 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Processors;
use App\Classes\Modules\PerfexCRM\Services\ConvertsPerfexCRMLeadToCustomer;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMCustomerProject;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMMilestone;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMTask;
use App\Classes\Modules\PerfexCRM\Services\FetchesPerfexCRMProject;
use App\Classes\Modules\PerfexCRM\Services\FetchesPerfexCRMMilestone;
use App\Classes\Modules\PerfexCRM\Services\FetchesPerfexCRMTask;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMCustomer;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMCustomerContact;
use App\Classes\Modules\PerfexCRM\Services\UpdatesPerfexCRMCustomer;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CustomerContactObject;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\InitialPerfexCRMObject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\UpdatePerfexCRMObject;
use App\Classes\ValueObjects\Constants\PerfexCRMMilestones;
use App\Classes\ValueObjects\Constants\PerfexCRMTasks;
use App\Classes\ValueObjects\Constants\PerfexCRMTaskStatus;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\Http\Request;
class InitializePerfexCRMProcessor
{
/** @var ConvertsPerfexCRMLeadToCustomer */
private $convertsPerfexCRMLeadToCustomer;
/** @var CreatesPerfexCRMCustomerProject */
private $createsPerfexCRMCustomerProject;
/** @var CreatesPerfexCRMMilestone */
private $createsPerfexCRMMilestone;
/** @var CreatesPerfexCRMTask */
private $createsPerfexCRMTask;
/** @var FetchesPerfexCRMProject */
private $fetchesPerfexCRMProject;
/** @var FetchesPerfexCRMMilestone */
private $fetchesPerfexCRMMilestone;
/** @var FetchesPerfexCRMTask */
private $fetchesPerfexCRMTask;
/** @var CreatesPerfexCRMCustomer */
private $createsPerfexCRMCustomer;
/** @var CreatesPerfexCRMCustomerContact */
private $createsPerfexCRMCustomerContact;
/** @var UpdatesPerfexCRM */
private $updatePerfexCRM;
/** @var UpdatesPerfexCRMCustomer */
private $updatesPerfexCRMCustomer;
/**
* @param ConvertsPerfexCRMLeadToCustomer $convertsPerfexCRMLeadToCustomer
* @param CreatesPerfexCRMCustomerProject $createsPerfexCRMCustomerProject
* @param CreatesPerfexCRMMilestone $createsPerfexCRMMilestone
* @param CreatesPerfexCRMTask $createsPerfexCRMTask
* @param FetchesPerfexCRMProject $fetchesPerfexCRMProject
* @param FetchesPerfexCRMMilestone $fetchesPerfexCRMMilestone
* @param FetchesPerfexCRMTask $fetchesPerfexCRMTask
* @param CreatesPerfexCRMCustomer $createsPerfexCRMCustomer
* @param CreatesPerfexCRMCustomerContact $createsPerfexCRMCustomerContact
* @param UpdatesPerfexCRMCustomer $updatesPerfexCRMCustomer
*/
public function __construct(ConvertsPerfexCRMLeadToCustomer $convertsPerfexCRMLeadToCustomer,
CreatesPerfexCRMCustomerProject $createsPerfexCRMCustomerProject,
CreatesPerfexCRMMilestone $createsPerfexCRMMilestone,
CreatesPerfexCRMTask $createsPerfexCRMTask,
FetchesPerfexCRMProject $fetchesPerfexCRMProject,
FetchesPerfexCRMMilestone $fetchesPerfexCRMMilestone,
FetchesPerfexCRMTask $fetchesPerfexCRMTask,
CreatesPerfexCRMCustomer $createsPerfexCRMCustomer,
CreatesPerfexCRMCustomerContact $createsPerfexCRMCustomerContact,
UpdatesPerfexCRMCustomer $updatesPerfexCRMCustomer)
{
$this->convertsPerfexCRMLeadToCustomer = $convertsPerfexCRMLeadToCustomer;
$this->createsPerfexCRMCustomerProject = $createsPerfexCRMCustomerProject;
$this->createsPerfexCRMMilestone = $createsPerfexCRMMilestone;
$this->createsPerfexCRMTask = $createsPerfexCRMTask;
$this->fetchesPerfexCRMProject = $fetchesPerfexCRMProject;
$this->fetchesPerfexCRMMilestone = $fetchesPerfexCRMMilestone;
$this->fetchesPerfexCRMTask = $fetchesPerfexCRMTask;
$this->createsPerfexCRMCustomer = $createsPerfexCRMCustomer;
$this->createsPerfexCRMCustomerContact = $createsPerfexCRMCustomerContact;
$this->updatesPerfexCRMCustomer = $updatesPerfexCRMCustomer;
}
/**
* @param InitialPerfexCRMObject $initialPerfexCRMObject
* @return null|object
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(InitialPerfexCRMObject $initialPerfexCRMObject) {
// Customer has to exist first before Project can appear under it
// Check with Perfex CRM, if this user (email) was previously a lead, should automatically now become a customer
$crmCompany = $initialPerfexCRMObject->getCompanyName();
$result = $this->convertsPerfexCRMLeadToCustomer->execute($initialPerfexCRMObject->getContactEmail());
if(isset($result->payload)){
$crmClientId = $result->payload['client_id'];
if (isset($result->payload['company'])) {
$crmCompany = $result->payload['company'];
}
}
else{
//if reach this point, this means this user is not a official customer nor is a lead in crm
//Create Customer has 2 parts: Create Company (client), Create Contact
$result = $this->createsPerfexCRMCustomer->execute($crmCompany);
if(is_null($result)){
$crmCompany = $crmCompany." 2";
$result = $this->createsPerfexCRMCustomer->execute($crmCompany);
}
$crmClientId = $result->payload['clientId'];
$customerContactObject = new CustomerContactObject(
$crmClientId,
$initialPerfexCRMObject->getContactName(),
$initialPerfexCRMObject->getContactName(),
$initialPerfexCRMObject->getContactEmail(),
"pU^T@sC#9Q",
"on",
"on"
);
$result = $this->createsPerfexCRMCustomerContact->execute($customerContactObject);
}
//Update custom fields to identify company reference from exchange or shipping portal
$value_exists = false;
if (isset($result->payload['customfields'])) {
foreach ($result->payload['customfields'] as $element) {
if ($element['value'] === $initialPerfexCRMObject->getCompanyReference()) {
$value_exists = true;
break;
}
}
}
if(!$value_exists);
{
$result = $this->updatesPerfexCRMCustomer->execute($crmClientId, $crmCompany, $initialPerfexCRMObject->getCompanyReference());
}
// Get existing or create project, project has to exist first before milestone can appear under it
$result = $this->createsPerfexCRMCustomerProject->execute($initialPerfexCRMObject->getProjectName(), $initialPerfexCRMObject->getProjectStatus(), $crmClientId);
if(isset($result->payload)){ //Here means project creation successful
$projectId = $result->payload['project_id'];
}
else{
$projectId = $this->fetchesPerfexCRMProject->execute($initialPerfexCRMObject->getProjectName(), $crmClientId)->id;
}
$tasks = $initialPerfexCRMObject->getTaskNames();
if(count($tasks) > 0){
//Create tasks with milestone
for($count=0; $count < count($tasks); $count++) {
$milestoneId = 0; //By default milestoneId is 0, having this set at individual task is optional
if($tasks[$count]['milestone'] != "") //Create milestone only if it is defined
{
// Get existing or create milestone, milestone has to exist first before task can appear under it
$result = $this->createsPerfexCRMMilestone->execute($tasks[$count]['milestone'], $projectId, $count);
if(isset($result->payload)){
$milestoneId = $result->payload['milestone_id'];
}
else{
$milestone = $this->fetchesPerfexCRMMilestone->execute($tasks[$count]['milestone'], $projectId);
$array = json_decode(json_encode($milestone), true);
$milestoneId = $array[0]['id'];
}
}
$taskStatus = PerfexCRMTaskStatus::NOT_STARTED;
if($tasks[$count]['status'] != ''){
$taskStatus = $tasks[$count]['status'];
}
// Get existing or create task
$result = $this->createsPerfexCRMTask->execute($tasks[$count]['name'], $tasks[$count]['description'], '', $milestoneId, $projectId, $tasks[$count]['reference'], $tasks[$count]['on_task_completion'], $taskStatus);
if(is_null($result)){
break; //Breaking the rest of the tasks in array assuming that they are all created as a batch previously
}
}
}
return true;
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PerfexCRM\Processors;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CreateTaskPerfexCRMObject;
use App\Classes\Jobs\CreatePerfexCRMSingleTask;
use App\Classes\ValueObjects\Constants\PerfexCRMTaskPriority;
use App\Classes\ValueObjects\Constants\PerfexCRMTasks;
use App\Models\Company;
@@ -29,7 +30,10 @@ class NewLeadTaskToPerfexCRMProcessor
"",
"",
"",
PerfexCRMTasks::TASK_IDENTIFICATION_1['status']
PerfexCRMTasks::TASK_IDENTIFICATION_1['status'],
PerfexCRMTasks::TASK_IDENTIFICATION_1['department'],
PerfexCRMTaskPriority::DEFAULT,
"0"
);
CreatePerfexCRMSingleTask::dispatch($createTaskPerfexCRMObject);
@@ -5,8 +5,10 @@ namespace App\Classes\Modules\PerfexCRM\Processors;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\UpdatePerfexCRMObject;
use App\Classes\ValueObjects\Constants\PerfexCRMTasks;
use App\Classes\Jobs\UpdatePerfexCRM;
use App\Classes\Jobs\UpdatePerfexCRMPrelude;
use App\Models\PackingList;
use App\Classes\ValueObjects\Constants\PerfexCRMProjectStatus;
use Illuminate\Support\Facades\Log;
class PackingListToPerfexCRMProcessor
{
@@ -17,35 +19,42 @@ class PackingListToPerfexCRMProcessor
*/
public function execute(PackingList $packingList)
{
$order = $packingList->owner;
$companyModule = $order->companyModule()->first();
$connection = $companyModule->inviters()->withPivot('invitee_reference')->first();
$companyName = $companyModule->name;
$companyReference = $connection ? $connection->pivot->invitee_reference:'';
$employee = $companyModule->employees()->first();
$contactEmail = $employee->email;
$contactName = $employee->name;
try {
if($packingList->owner instanceof \App\Models\Order) {
$order = $packingList->owner;
$companyModule = $order->companyModule()->first();
$connection = $companyModule->inviters()->withPivot('invitee_reference')->first();
$companyName = $companyModule->name;
$companyReference = $connection ? $connection->pivot->invitee_reference:'';
$employee = $companyModule->employees()->first();
$contactEmail = $employee->email;
$contactName = $employee->name;
$orderReference = $packingList->owner->reference;
$packingListReference = $packingList->reference;
$projectName = 'IZYIM | X1 Shipping | '.$orderReference.' | '.$packingListReference;
$updatePerfexCRMObject = new UpdatePerfexCRMObject(
$companyName,
$companyReference,
$contactName,
$contactEmail,
"",
$projectName,
PerfexCRMProjectStatus::NOT_STARTED,
[],
[
PerfexCRMTasks::TASK_LOADED_CONTAINER_1,
PerfexCRMTasks::TASK_LOADED_CONTAINER_2,
]
);
UpdatePerfexCRM::dispatch($updatePerfexCRMObject);
$orderReference = $packingList->owner->reference;
$packingListReference = $packingList->reference;
$projectName = 'IZYIM | X1 Shipping | '.$orderReference.' | '.$packingListReference;
$updatePerfexCRMObject = new UpdatePerfexCRMObject(
$companyName,
$companyReference,
$contactName,
$contactEmail,
"",
$projectName,
PerfexCRMProjectStatus::NOT_STARTED,
[],
[
PerfexCRMTasks::TASK_LOADED_CONTAINER_1,
PerfexCRMTasks::TASK_LOADED_CONTAINER_2,
]
);
UpdatePerfexCRMPrelude::dispatch($packingList, null, $updatePerfexCRMObject, UpdatePerfexCRM::class, null);
}
} catch (\Exception $exception){
Log::error(json_encode('PackingListToPerfexCRMProcessor debug:'));
Log::error(json_encode($packingList));
Log::error($exception);
}
return true;
}
}
@@ -2,46 +2,19 @@
namespace App\Classes\Modules\PerfexCRM\Processors;
use App\Classes\Modules\PerfexCRM\Processors\UpdatePerfexCRMProcessor;
use App\Classes\Modules\PerfexCRM\Processors\InitializePerfexCRMProcessor;
use App\Classes\Modules\PerfexCRM\Services\Init;
use App\Classes\Modules\Companies\Services\FetchesCompany;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\UpdatePerfexCRMObject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\UpdatePerfexCRMInvoiceObject;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Classes\ValueObjects\Constants\PerfexCRMMilestones;
use App\Classes\ValueObjects\Constants\PerfexCRMTasks;
use App\Classes\ValueObjects\Constants\PerfexCRMProjectStatus;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\Jobs\UpdatePerfexCRMInvoice;
use App\Classes\Jobs\UpdatePerfexCRM;
use App\Classes\Jobs\UpdatePerfexCRMPrelude;
use App\Classes\Jobs\CreatePerfexCRMInvoice;
use App\Models\Transaction;
use Illuminate\Support\Facades\Log;
class TransactionToPerfexCRMProcessor
{
/** @var FetchesCompany */
private $fetchesCompany;
/** @var UpdatePerfexCRMProcessor */
private $updatePerfexCRMProcessor;
/** @var InitializePerfexCRMProcessor */
private $initializePerfexCRMProcessor;
/**
* TransactionToPerfexCRMProcessor constructor.
* @param UpdatePerfexCRMProcessor $updatePerfexCRMProcessor
* @param InitializePerfexCRMProcessor $initializePerfexCRMProcessor
* @param FetchesCompany $fetchesCompany
*/
public function __construct(UpdatePerfexCRMProcessor $updatePerfexCRMProcessor, InitializePerfexCRMProcessor $initializePerfexCRMProcessor, FetchesCompany $fetchesCompany)
{
$this->updatePerfexCRMProcessor = $updatePerfexCRMProcessor;
$this->initializePerfexCRMProcessor = $initializePerfexCRMProcessor;
$this->fetchesCompany = $fetchesCompany;
}
/**
* @param Transaction $model
* @param int $status
@@ -50,50 +23,53 @@ class TransactionToPerfexCRMProcessor
*/
public function execute(Transaction $model, int $status)
{
if($model->owner instanceof \App\Models\Transaction && $status == ApprovalStatus::APPROVED)
try
{
$packingList = $model->owner->owner;
$order = $packingList->owner()->first();
$companyModule = $order->companyModule()->first();
$companyName = $companyModule->name;
$companyReference = $companyModule->inviters()->withPivot('invitee_reference')->first()->pivot->invitee_reference;
$employee = $companyModule->employees()->first();
$contactEmail = $employee->email;
$contactName = $employee->name;
if($model->owner instanceof \App\Models\Transaction && $status == ApprovalStatus::APPROVED)
{
$packingList = $model->owner->owner;
$order = $packingList->owner()->first();
$companyModule = $order->companyModule()->first();
$companyName = $companyModule->name;
$companyReference = $companyModule->inviters()->withPivot('invitee_reference')->first()->pivot->invitee_reference;
$employee = $companyModule->employees()->first();
$contactEmail = $employee->email;
$contactName = $employee->name;
$orderReference = $order->reference;
$packingListReference = $packingList->reference;
$projectName = 'IZYIM | X1 Shipping | '.$orderReference.' | '.$packingListReference;
$orderReference = $order->reference;
$packingListReference = $packingList->reference;
$projectName = 'IZYIM | X1 Shipping | '.$orderReference.' | '.$packingListReference;
$bookingMarking = $packingList->id."-".$packingList->owner->id;
$updatePerfexCRMObject = new UpdatePerfexCRMObject(
$companyName,
$companyReference,
$contactName,
$contactEmail,
$bookingMarking,
$projectName,
PerfexCRMProjectStatus::IN_PROGRESS,
[],
[
PerfexCRMTasks::TASK_1,
PerfexCRMTasks::TASK_POST_PAYMENT_1,
PerfexCRMTasks::TASK_POST_PAYMENT_2,
PerfexCRMTasks::TASK_POST_PAYMENT_3,
PerfexCRMTasks::TASK_POST_PAYMENT_4,
]
);
$bookingMarking = $packingList->id."-".$packingList->owner->id;
$updatePerfexCRMObject = new UpdatePerfexCRMObject(
$companyName,
$companyReference,
$contactName,
$contactEmail,
$bookingMarking,
$projectName,
PerfexCRMProjectStatus::IN_PROGRESS,
[],
[
PerfexCRMTasks::TASK_1,
PerfexCRMTasks::TASK_POST_PAYMENT_1,
PerfexCRMTasks::TASK_POST_PAYMENT_2,
PerfexCRMTasks::TASK_POST_PAYMENT_3,
PerfexCRMTasks::TASK_POST_PAYMENT_4,
]
);
UpdatePerfexCRM::dispatch($updatePerfexCRMObject);
$updatePerfexCRMInvoiceOject = new UpdatePerfexCRMInvoiceObject(
$contactEmail,
$model,
true
);
UpdatePerfexCRMInvoice::dispatch($updatePerfexCRMInvoiceOject);
UpdatePerfexCRMPrelude::dispatch(null, $model, $updatePerfexCRMObject, UpdatePerfexCRM::class, UpdatePerfexCRMInvoice::class);
}
else if($model->owner instanceof \App\Models\PackingList && $model->status == ApprovalStatus::PENDING_SUBMISSION && $status == ApprovalStatus::APPROVED)
{
CreatePerfexCRMInvoice::dispatch($model);
}
}
catch (\Exception $exception) {
Log::error('TransactionToPerfexCRMProcessor debug:');
Log::error($exception);
}
return true;
}
}
@@ -11,6 +11,7 @@ use App\Classes\Modules\PerfexCRM\Services\FetchesPerfexCRMMilestone;
use App\Classes\Modules\PerfexCRM\Services\FetchesPerfexCRMTask;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMCustomer;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMCustomerContact;
use App\Classes\Modules\PerfexCRM\Services\UpdatesPerfexCRMTask;
use App\Classes\Modules\PerfexCRM\Services\UpdatesPerfexCRMCustomer;
use App\Classes\Modules\PerfexCRM\Services\UpdatesPerfexCRMProject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CustomerContactObject;
@@ -51,8 +52,8 @@ class UpdatePerfexCRMProcessor
/** @var CreatesPerfexCRMCustomerContact */
private $createsPerfexCRMCustomerContact;
/** @var UpdatesPerfexCRM */
private $updatePerfexCRM;
/** @var UpdatesPerfexCRMTask */
private $updatesPerfexCRMTask;
/** @var UpdatesPerfexCRMCustomer */
private $updatesPerfexCRMCustomer;
@@ -70,6 +71,7 @@ class UpdatePerfexCRMProcessor
* @param FetchesPerfexCRMTask $fetchesPerfexCRMTask
* @param CreatesPerfexCRMCustomer $createsPerfexCRMCustomer
* @param CreatesPerfexCRMCustomerContact $createsPerfexCRMCustomerContact
* @param UpdatesPerfexCRMTask $updatesPerfexCRMTask
* @param UpdatesPerfexCRMCustomer $updatesPerfexCRMCustomer
* @param UpdatesPerfexCRMProject $updatesPerfexCRMProject
*/
@@ -82,6 +84,7 @@ class UpdatePerfexCRMProcessor
FetchesPerfexCRMTask $fetchesPerfexCRMTask,
CreatesPerfexCRMCustomer $createsPerfexCRMCustomer,
CreatesPerfexCRMCustomerContact $createsPerfexCRMCustomerContact,
UpdatesPerfexCRMTask $updatesPerfexCRMTask,
UpdatesPerfexCRMCustomer $updatesPerfexCRMCustomer,
UpdatesPerfexCRMProject $updatesPerfexCRMProject)
{
@@ -94,6 +97,7 @@ class UpdatePerfexCRMProcessor
$this->fetchesPerfexCRMTask = $fetchesPerfexCRMTask;
$this->createsPerfexCRMCustomer = $createsPerfexCRMCustomer;
$this->createsPerfexCRMCustomerContact = $createsPerfexCRMCustomerContact;
$this->updatesPerfexCRMTask = $updatesPerfexCRMTask;
$this->updatesPerfexCRMCustomer = $updatesPerfexCRMCustomer;
$this->updatesPerfexCRMProject = $updatesPerfexCRMProject;
}
@@ -104,6 +108,7 @@ class UpdatePerfexCRMProcessor
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(UpdatePerfexCRMObject $updatePerfexCRMObject) {
$projectId = "";
// Customer has to exist first before Project can appear under it
// Check with Perfex CRM, if this user (email) was previously a lead, should automatically now become a customer
@@ -154,21 +159,27 @@ class UpdatePerfexCRMProcessor
}
// Get existing or create project, project has to exist first before milestone can appear under it
$result = $this->createsPerfexCRMCustomerProject->execute($updatePerfexCRMObject->getProjectName(), $updatePerfexCRMObject->getProjectStatus(), $crmClientId);
if(isset($result->payload)){ //Here means project creation successful
$projectId = $result->payload['project_id'];
}
else{
$project = $this->fetchesPerfexCRMProject->execute($updatePerfexCRMObject->getProjectName(), $crmClientId);
$projectId = $project->id;
$result = $this->fetchesPerfexCRMProject->execute($updatePerfexCRMObject->getProjectName(), $crmClientId);
if(isset($result->payload)){
$project = $result->payload[0];
$projectId = $project['id'];
//if the project status is anything but PerfexCRMProjectStatus::NOT_STARTED, update the project
if($updatePerfexCRMObject->getProjectStatus() != PerfexCRMProjectStatus::NOT_STARTED)
if($updatePerfexCRMObject->getProjectStatus() != PerfexCRMProjectStatus::NOT_STARTED && $project['status'] == PerfexCRMProjectStatus::NOT_STARTED)
{
$this->updatesPerfexCRMProject->execute($project, $updatePerfexCRMObject->getProjectStatus());
}
}
}
else{
$result = $this->createsPerfexCRMCustomerProject->execute($updatePerfexCRMObject->getProjectName(), $updatePerfexCRMObject->getProjectStatus(), $crmClientId);
if(isset($result->payload)){ //Here means project creation successful
$projectId = $result->payload['project_id'];
}
}
$tasks = $updatePerfexCRMObject->getTaskNames();
$tasks = $updatePerfexCRMObject->getTasks();
if(count($tasks) > 0){
//Create tasks with milestone
@@ -177,14 +188,16 @@ class UpdatePerfexCRMProcessor
if($tasks[$count]['milestone'] != "") //Create milestone only if it is defined
{
// Get existing or create milestone, milestone has to exist first before task can appear under it
$result = $this->createsPerfexCRMMilestone->execute($tasks[$count]['milestone'], $projectId, $count);
$result = $this->fetchesPerfexCRMMilestone->execute($tasks[$count]['milestone'], $projectId);
if(isset($result->payload)){
$milestoneId = $result->payload['milestone_id'];
$array = json_decode(json_encode($result->payload[0]), true);
$milestoneId = $array['id'];
}
else{
$milestone = $this->fetchesPerfexCRMMilestone->execute($tasks[$count]['milestone'], $projectId);
$array = json_decode(json_encode($milestone), true);
$milestoneId = $array[0]['id'];
$result = $this->createsPerfexCRMMilestone->execute($tasks[$count]['milestone'], $projectId, $count);
if(isset($result->payload)){
$milestoneId = $result->payload['milestone_id'];
}
}
}
@@ -194,13 +207,25 @@ class UpdatePerfexCRMProcessor
}
// Get existing or create task
$result = $this->createsPerfexCRMTask->execute($tasks[$count]['name'], $tasks[$count]['description'], '', $milestoneId, $projectId, $tasks[$count]['reference'], $tasks[$count]['on_task_completion'], $taskStatus);
if(is_null($result)){
$result = $this->fetchesPerfexCRMTask->execute($tasks[$count]['name'], $milestoneId, 'project', $projectId);
if(isset($result->payload)){
break; //Breaking the rest of the tasks in array assuming that they are all created as a batch previously
//The following are code not needed at Shipping Portal, Exchange need certain task's status to be updated dynamically
// if($taskStatus != PerfexCRMTaskStatus::NOT_STARTED && $result->payload[0]['status'] == PerfexCRMTaskStatus::NOT_STARTED)
// {
// $task = $result->payload[0];
// $result = $this->updatesPerfexCRMTask->execute($task['id'], $task['name'], $task['milestone'], $task['rel_id'], $taskStatus, $task['startdate'], is_null($task['duedate']) ? '': $task['duedate']);
// }
}
else{
$result = $this->createsPerfexCRMTask->execute($tasks[$count]['name'], $tasks[$count]['description'], '', $milestoneId, $projectId, $tasks[$count]['reference'], $tasks[$count]['on_task_completion'], $tasks[$count]['department'], $taskStatus, $tasks[$count]['priority'], $tasks[$count]['duedate']);
}
}
}
return true;
$payload = [];
$payload['projectId'] = $projectId;
return (object) $payload;
}
}
@@ -16,14 +16,17 @@ class CreatesPerfexCRMInvoice
*/
public function execute(InvoicePerfexCRMObject $invoicePerfexCRMObject) {
try{
$subtotal = floor($invoicePerfexCRMObject->getSubTotal() * 100) / 100;
$total = floor($invoicePerfexCRMObject->getTotal() * 100) / 100;
$data = [
'clientid' => $invoicePerfexCRMObject->getClientId(),
'number' => $invoicePerfexCRMObject->getNumber(),
'date' => $invoicePerfexCRMObject->getDate(),
'duedate' => $invoicePerfexCRMObject->getDueDate(),
'currency' => $invoicePerfexCRMObject->getCurrency(),
'subtotal' => number_format($invoicePerfexCRMObject->getSubTotal(), 2, '.', ''),
'total' => number_format($invoicePerfexCRMObject->getTotal(), 2, '.', ''),
'subtotal' => number_format($subtotal, 2, '.', ''),
'total' => number_format($total, 2, '.', ''),
'billing_street' => $invoicePerfexCRMObject->getBillingStreet(),
'project_id' => $invoicePerfexCRMObject->getProjectId(),
'allowed_payment_modes[0]' => 1,
@@ -16,13 +16,20 @@ class CreatesPerfexCRMLead
*/
public function execute(CreateLeadPerfexCRMObject $createLeadPerfexCRMObject) {
try{
$custom_fields = [
"leads" => [
4 => $createLeadPerfexCRMObject->getCompanyReference()
]
];
$data = [
'name' => $createLeadPerfexCRMObject->getName(),
'email' => $createLeadPerfexCRMObject->getEmail(),
'phonenumber' => $createLeadPerfexCRMObject->getPhone(),
'company' => $createLeadPerfexCRMObject->getCompanyName(),
'source' => 2, //1: Exchange, 2: Shipping Portal
'status' => 2 //2: Lead, 1: Customer
'status' => 2, //2: Lead, 1: Customer
'custom_fields' => $custom_fields
];
$response = Http::asForm()->withHeaders([
@@ -5,6 +5,7 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
use App\Classes\ValueObjects\Constants\PerfexCRMCustomFields;
class CreatesPerfexCRMTask
{
@@ -14,14 +15,26 @@ class CreatesPerfexCRMTask
* @param string $leadId
* @param string $milestoneId
* @param string $projectId
* @param string $reference, default: ''
* @param string $on_task_completion, default: ''
* @param string $status, default: 1
* @param string $reference
* @param string $on_task_completion
* @param string $department
* @param string $status
* @param string $priority
* @param string $duedate
* @return null|object
* @throws MalformedRequestException
*/
public function execute(string $taskName, string $taskDescription, string $leadId, string $milestoneId, string $projectId, string $reference = '', string $on_task_completion = '', string $status = "1") {
public function execute(string $taskName, string $taskDescription, string $leadId, string $milestoneId, string $projectId, string $reference, string $on_task_completion, string $department, string $status, string $priority, string $duedate) {
try{
$custom_fields = [];
if($department != ""){
$custom_fields = [
"tasks" => [
PerfexCRMCustomFields::TASKS_DEPARTMENT => $department
]
];
}
$data = [
'name' => $taskName,
'description' => $taskDescription,
@@ -32,7 +45,10 @@ class CreatesPerfexCRMTask
'status' => $status,
'is_system_created' => 1,
'reference' => $reference,
'on_task_completion' => $on_task_completion
'on_task_completion' => $on_task_completion,
'custom_fields' => $custom_fields,
'priority' => $priority,
'duedate' => date('Y-m-d', strtotime('+' . $duedate . ' days')),
];
if($leadId != '') {
@@ -46,7 +62,10 @@ class CreatesPerfexCRMTask
'status' => $status,
'is_system_created' => 1,
'reference' => $reference,
'on_task_completion' => $on_task_completion
'on_task_completion' => $on_task_completion,
'custom_fields' => $custom_fields,
'priority' => $priority,
'duedate' => date('Y-m-d', strtotime('+' . $duedate . ' days')),
];
}
@@ -16,9 +16,14 @@ class FetchesPerfexCRMMilestone
*/
public function execute(string $milestoneName, string $projectId) {
try{
$response = Http::withHeaders([
'authtoken' => config('perfexcrm.api_key'),])
->get(config('perfexcrm.base_url').'/api/milestones/bynameandprojectid/'.rawurlencode($milestoneName).'/'.$projectId);
$data = [
'name' => $milestoneName,
'project_id' => $projectId,
];
$response = Http::asForm()->withHeaders([
'authtoken' => config('perfexcrm.api_key')])
->post(config('perfexcrm.base_url').'/api/milestones/bynameandprojectid', $data);
if($response->successful()){
$data = $response->json();
@@ -5,27 +5,41 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
use App\Classes\General\Helper;
class FetchesPerfexCRMTask
{
/**
* @param string $taskName
* @param string $milestoneId
* @param string $relType
* @param string $relId
* @return null|object
* @throws MalformedRequestException
*/
public function execute(string $taskName, string $milestoneId) {
public function execute(string $taskName, string $milestoneId, string $relType, string $relId) {
try{
$response = Http::withHeaders([
'authtoken' => config('perfexcrm.api_key'),])
->get(config('perfexcrm.base_url').'/api/tasks/bynameandmilestoneid/'.rawurlencode($taskName).'/'.$milestoneId);
$data = [
'name' => $taskName,
'rel_type' => $relType,
'rel_id' => $relId,
];
if($milestoneId != '') {
$newItem = ['milestone' => $milestoneId ];
$data = array_merge($data, $newItem);
}
$response = Http::asForm()->withHeaders([
'authtoken' => config('perfexcrm.api_key')])
->post(config('perfexcrm.base_url').'/api/tasks/customsearch', $data);
if($response->successful()){
$data = $response->json();
return (object) $data;
}else{
Log::error($response);
Helper::debugLoggerForPerfexCRM($response);
return null;
}
}catch(\Exception $exception){
@@ -5,6 +5,8 @@ namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
use App\Classes\ValueObjects\Constants\PerfexCRMCustomFields;
use App\Classes\General\Helper;
class UpdatesPerfexCRMCustomer
{
@@ -19,7 +21,7 @@ class UpdatesPerfexCRMCustomer
try{
$custom_fields = [
"customers" => [
2 => $companyReference
PerfexCRMCustomFields::CUSTOMERS_SHIPPING_PORTAL_REFERENCE => $companyReference
]
];
@@ -36,7 +38,7 @@ class UpdatesPerfexCRMCustomer
$data = $response->json();
return (object) $data;
}else{
Log::error($response);
Helper::debugLoggerForPerfexCRM($response);
return null;
}
}catch(\Exception $exception){
@@ -35,10 +35,13 @@ class UpdatesPerfexCRMInvoice
array_push($newInvoiceItems,$item);
}
$allowedPaymentModes = [];
array_push($allowedPaymentModes, 1, 2);
$data = [
'number' => $invoice->number,
'date' => $invoice->date,
'duedate' => $invoice->date,
'duedate' => $invoice->duedate,
'currency' => $invoice->currency,
'subtotal' => $invoice->subtotal,
'total' => $invoice->total,
@@ -46,7 +49,7 @@ class UpdatesPerfexCRMInvoice
'shipping_street' => $invoice->billing_street,
'project_id' => $projectId,
'items' => $newInvoiceItems,
'allowed_payment_modes' => $invoice->allowed_payment_modes,
'allowed_payment_modes' => $allowedPaymentModes,
];
$response = Http::asJson()->withHeaders([
@@ -0,0 +1,51 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
use App\Classes\ValueObjects\Constants\PerfexCRMCustomFields;
class UpdatesPerfexCRMLead
{
/**
* @param $lead
* @param string $companyReference
* @return null|object
* @throws MalformedRequestException
*/
public function execute($lead, string $companyReference) {
try{
$custom_fields = [
"leads" => [
PerfexCRMCustomFields::LEADS_SHIPPING_PORTAL_REFERENCE => $companyReference
]
];
$data = [
'name' => $lead->name,
'email' => $lead->email,
'phonenumber' => $lead->phonenumber,
'company' => $lead->company,
'custom_fields' => $custom_fields,
'source' => $lead->source,
'status' => $lead->status,
];
$response = Http::asJson()->withHeaders([
'authtoken' => config('perfexcrm.api_key')])
->put(config('perfexcrm.base_url').'/api/leads/'.$lead->id, $data);
if($response->successful()){
$data = $response->json();
return (object) $data;
}else{
Log::error($response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
}
@@ -17,17 +17,17 @@ class UpdatesPerfexCRMProject
public function execute($project, int $status) {
try{
$data = [
'name' => $project->name,
'clientid' => $project->clientid,
'name' => $project['name'],
'clientid' => $project['clientid'],
// 'rel_type' => 'customer',
'billing_type' => 1,
'start_date' => $project->start_date,
'start_date' => $project['start_date'],
'status' => $status
];
$response = Http::asJson()->withHeaders([
'authtoken' => config('perfexcrm.api_key')])
->put(config('perfexcrm.base_url').'/api/projects/'.$project->id, $data);
->put(config('perfexcrm.base_url').'/api/projects/'.$project['id'], $data);
if($response->successful()){
$data = $response->json();
@@ -5,17 +5,8 @@ namespace App\Classes\Modules\Segments\ControllersLogic;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use App\Http\Resources\ConstantResource;
use App\Classes\ValueObjects\Constants\SegmentConstants;
use App\Classes\Modules\Segments\Services\FetchesSegment;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Segments\Services\FetchesConstant;
use App\Classes\Modules\Segments\Services\UpdatesConstant;
use App\Classes\Modules\Segments\Standards\Rules\CanUpdateConstant;
use App\Classes\Modules\Segments\DataTransferObjects\ConstantObject;
use App\Classes\Modules\Segments\Services\AddItemToConstantValueArray;
use App\Classes\Modules\Segments\Services\RemoveItemFromConstantValueArray;
use App\Classes\Exceptions\ResourceNotFoundException;
use App\Classes\Modules\Segments\Services\CreatesConstant;
use App\Classes\Modules\Segments\Processors\UpdatePostcodeSegmentProcessor;
class UpdateConstantPostcodeLogic extends AbstractControllerLogic
{
@@ -30,54 +21,17 @@ class UpdateConstantPostcodeLogic extends AbstractControllerLogic
];
}
/** @var CanUpdateConstant */
private $canUpdateConstant;
/** @var UpdatesConstant */
private $updatesConstant;
/** @var FetchesSegment */
private $fetchesSegment;
/** @var FetchesConstant */
private $fetchesConstant;
/** @var AddItemToConstantValueArray */
private $addItemToConstantValueArray;
/** @var RemoveItemFromConstantValueArray */
private $removeItemFromConstantValueArray;
/** @var CreatesConstant */
private $createsConstant;
/** @var UpdatePostcodeSegmentProcessor */
private $updatePostcodeSegmentProcessor;
/**
* UpdateConstantLogic constructor.
* @param CanUpdateConstant $canUpdateConstant
* @param UpdatesConstant $updatesConstant
* @param FetchesSegment $fetchesSegment
* @param FetchesConstant $fetchesConstant
* @param AddItemToConstantValueArray $addItemToConstantValueArray
* @param CreatesConstant $createsConstant
* @param RemoveItemFromConstantValueArray $removeItemFromConstantValueArray
* @param UpdatePostcodeSegmentProcessor $updatePostcodeSegmentProcessor
*/
public function __construct(
CanUpdateConstant $canUpdateConstant,
UpdatesConstant $updatesConstant,
FetchesSegment $fetchesSegment,
FetchesConstant $fetchesConstant,
AddItemToConstantValueArray $addItemToConstantValueArray,
RemoveItemFromConstantValueArray $removeItemFromConstantValueArray,
CreatesConstant $createsConstant
)
UpdatePostcodeSegmentProcessor $updatePostcodeSegmentProcessor)
{
$this->canUpdateConstant = $canUpdateConstant;
$this->updatesConstant = $updatesConstant;
$this->fetchesSegment = $fetchesSegment;
$this->fetchesConstant = $fetchesConstant;
$this->addItemToConstantValueArray = $addItemToConstantValueArray;
$this->removeItemFromConstantValueArray = $removeItemFromConstantValueArray;
$this->createsConstant = $createsConstant;
$this->updatePostcodeSegmentProcessor = $updatePostcodeSegmentProcessor;
}
/**
* @param Request $request
@@ -88,44 +42,9 @@ class UpdateConstantPostcodeLogic extends AbstractControllerLogic
*/
public function logic(Request $request) : JsonResponse
{
$segment = $this->fetchesSegment->execute(['id' => $request->route('id')]);
try {
$constant = $this->fetchesConstant->execute(['segment_id' => $segment->id, 'reference' => $request->input('reference')]);
$constantValue = $this->addItemToConstantValueArray->execute($constant->value, $request->input('postcode'));
$object = new ConstantObject($request->input('reference'), $constantValue);
} catch (ResourceNotFoundException $exception){
$constantObject = [$request->input('postcode')];
$object = new ConstantObject(
$request->input('reference'),
$constantObject
);
$constant = $this->createsConstant->execute($segment, $object);
}
try {
// check if postcode exist in the opposite constant, and delete it
$oppositeConstant = $this->fetchesConstant->execute(['segment_id' => $segment->id, 'reference' => $request->input('reference') == SegmentConstants::CENTER_POSTCODE ? SegmentConstants::OUTSTATION_POSTCODE : SegmentConstants::CENTER_POSTCODE]);
$oppositeConstantValue = $this->removeItemFromConstantValueArray->execute($oppositeConstant->value, $request->input('postcode'));
$oppositeObject = new ConstantObject($request->input('reference') == SegmentConstants::CENTER_POSTCODE ? SegmentConstants::OUTSTATION_POSTCODE : SegmentConstants::CENTER_POSTCODE, $oppositeConstantValue);
$this->updatesConstant->execute($oppositeConstant, $oppositeObject);
} catch (ResourceNotFoundException $exception){
// if opposite constant does not exist, do nothing
}
$constant = $this->updatesConstant->execute($constant, $object);
$constant = $this->updatePostcodeSegmentProcessor->execute($request->route('id'), $request->input('reference'), $request->input('postcode'));
return $this->resourceResponse(new ConstantResource($constant));
}
}
}
@@ -0,0 +1,122 @@
<?php
namespace App\Classes\Modules\Segments\Processors;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use App\Http\Resources\ConstantResource;
use App\Classes\ValueObjects\Constants\SegmentConstants;
use App\Classes\Modules\Segments\Services\FetchesSegment;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Segments\Services\FetchesConstant;
use App\Classes\Modules\Segments\Services\UpdatesConstant;
use App\Classes\Modules\Segments\Standards\Rules\CanUpdateConstant;
use App\Classes\Modules\Segments\DataTransferObjects\ConstantObject;
use App\Classes\Modules\Segments\Services\AddItemToConstantValueArray;
use App\Classes\Modules\Segments\Services\RemoveItemFromConstantValueArray;
use App\Classes\Exceptions\ResourceNotFoundException;
use App\Classes\Modules\Segments\Services\CreatesConstant;
class UpdatePostcodeSegmentProcessor
{
/** @var CanUpdateConstant */
private $canUpdateConstant;
/** @var UpdatesConstant */
private $updatesConstant;
/** @var FetchesSegment */
private $fetchesSegment;
/** @var FetchesConstant */
private $fetchesConstant;
/** @var AddItemToConstantValueArray */
private $addItemToConstantValueArray;
/** @var RemoveItemFromConstantValueArray */
private $removeItemFromConstantValueArray;
/** @var CreatesConstant */
private $createsConstant;
/**
* UpdatePostcodeSegmentProcessor constructor.
* @param CanUpdateConstant $canUpdateConstant
* @param UpdatesConstant $updatesConstant
* @param FetchesSegment $fetchesSegment
* @param FetchesConstant $fetchesConstant
* @param AddItemToConstantValueArray $addItemToConstantValueArray
* @param CreatesConstant $createsConstant
* @param RemoveItemFromConstantValueArray $removeItemFromConstantValueArray
*/
public function __construct(
CanUpdateConstant $canUpdateConstant,
UpdatesConstant $updatesConstant,
FetchesSegment $fetchesSegment,
FetchesConstant $fetchesConstant,
AddItemToConstantValueArray $addItemToConstantValueArray,
RemoveItemFromConstantValueArray $removeItemFromConstantValueArray,
CreatesConstant $createsConstant
)
{
$this->canUpdateConstant = $canUpdateConstant;
$this->updatesConstant = $updatesConstant;
$this->fetchesSegment = $fetchesSegment;
$this->fetchesConstant = $fetchesConstant;
$this->addItemToConstantValueArray = $addItemToConstantValueArray;
$this->removeItemFromConstantValueArray = $removeItemFromConstantValueArray;
$this->createsConstant = $createsConstant;
}
/**
* @param string $name
* @param int $companyModuleId
* @throws \App\Classes\Exceptions\AccessForbiddenException
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
public function execute($segment_id, $reference, $postcode){
$segment = $this->fetchesSegment->execute(['id' => $segment_id]);
try {
$constant = $this->fetchesConstant->execute(['segment_id' => $segment->id, 'reference' => $reference]);
$constantValue = $this->addItemToConstantValueArray->execute($constant->value, $postcode);
$object = new ConstantObject($reference, $constantValue);
} catch (ResourceNotFoundException $exception){
$constantObject = [$postcode];
$object = new ConstantObject(
$reference,
$constantObject
);
$constant = $this->createsConstant->execute($segment, $object);
}
try {
// check if postcode exist in the opposite constant, and delete it
$oppositeConstant = $this->fetchesConstant->execute(['segment_id' => $segment->id, 'reference' => $reference == SegmentConstants::CENTER_POSTCODE ? SegmentConstants::OUTSTATION_POSTCODE : SegmentConstants::CENTER_POSTCODE]);
$oppositeConstantValue = $this->removeItemFromConstantValueArray->execute($oppositeConstant->value, $postcode);
$oppositeObject = new ConstantObject($reference == SegmentConstants::CENTER_POSTCODE ? SegmentConstants::OUTSTATION_POSTCODE : SegmentConstants::CENTER_POSTCODE, $oppositeConstantValue);
$this->updatesConstant->execute($oppositeConstant, $oppositeObject);
} catch (ResourceNotFoundException $exception){
// if opposite constant does not exist, do nothing
}
$constant = $this->updatesConstant->execute($constant, $object);
return $constant;
}
}
@@ -0,0 +1,52 @@
<?php
namespace App\Classes\Modules\Transactions\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Transactions\Services\FetchesTransaction;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class DeleteTransactionLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Delete Transaction',
'message' => 'You have successfully deleted the transaction'
];
}
/** @var FetchesTransaction */
private $fetchesTransaction;
/** @var UpdatesTransactionStatus */
private $updatesTransactionStatus;
/**
* SuspendTransactionLogic constructor.
* @param FetchesTransaction $fetchesTransaction
* @param UpdatesTransactionStatus $updatesTransactionStatus
*/
public function __construct(FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus)
{
$this->fetchesTransaction = $fetchesTransaction;
$this->updatesTransactionStatus = $updatesTransactionStatus;
}
public function logic(Request $request) : JsonResponse
{
$transaction = $this->fetchesTransaction->execute(['id' => $request->route('id')]);
$transaction->delete();
return $this->response([]);
}
}
@@ -75,11 +75,6 @@ class ApproveShippingInvoiceTransactionProcessor
$user->notify(new InvoiceIssuedEmail($user, $packingList));
}
// update perfex crm
if(config('perfexcrm.is_enabled') == 'true'){
CreatePerfexCRMInvoice::dispatch($invoice_transaction);
}
return;
}
@@ -5,25 +5,19 @@ namespace App\Classes\Modules\Transactions\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Models\Transaction;
use App\Classes\Modules\PerfexCRM\Processors\TransactionToPerfexCRMProcessor;
use App\Classes\Modules\PerfexCRM\Processors\NewLeadTaskToPerfexCRMProcessor;
class UpdatesTransactionStatus extends AbstractUpdateRecord
{
/** @var TransactionToPerfexCRMProcessor */
private $transactionToPerfexCRMProcessor;
/** @var NewLeadTaskToPerfexCRMProcessor */
private $newLeadTaskToPerfexCRMProcessor;
/**
* UpdatesTransactionStatus constructor.
* @param TransactionToPerfexCRMProcessor $transactionToPerfexCRMProcessor
* @param NewLeadTaskToPerfexCRMProcessor $newLeadTaskToPerfexCRMProcessor
*/
public function __construct(TransactionToPerfexCRMProcessor $transactionToPerfexCRMProcessor, NewLeadTaskToPerfexCRMProcessor $newLeadTaskToPerfexCRMProcessor)
public function __construct(TransactionToPerfexCRMProcessor $transactionToPerfexCRMProcessor)
{
$this->transactionToPerfexCRMProcessor = $transactionToPerfexCRMProcessor;
$this->newLeadTaskToPerfexCRMProcessor = $newLeadTaskToPerfexCRMProcessor;
}
/**
@@ -34,11 +28,13 @@ class UpdatesTransactionStatus extends AbstractUpdateRecord
*/
public function execute(Transaction $model, int $status)
{
if(config('perfexcrm.is_enabled') == 'true'){
$this->transactionToPerfexCRMProcessor->execute($model, $status);
// $this->newLeadTaskToPerfexCRMProcessor->execute();
}
$transaction = clone($model);
$model->status = $status;
return $this->handler($model);
$result = $this->handler($model);
if(config('perfexcrm.is_enabled') == 'true'){
$this->transactionToPerfexCRMProcessor->execute($transaction, $status);
}
return $result;
}
}
@@ -8,4 +8,9 @@ final class CompanyType {
public const COMPANY_BUSINESS = 1;
public const COMPANY_TYPE_ID = [
self::PERSONAL_BUSINESS => "Personal Business",
self::COMPANY_BUSINESS => "Company Business",
];
}
@@ -0,0 +1,18 @@
<?php
namespace App\Classes\ValueObjects\Constants;
final class PerfexCRMCustomFields {
public const CUSTOMERS_EXCHANGE_REFERENCE = 1;
public const CUSTOMERS_SHIPPING_PORTAL_REFERENCE = 2;
public const LEADS_EXCHANGE_REFERENCE = 3;
public const LEADS_SHIPPING_PORTAL_REFERENCE = 4;
public const TICKETS_CUSTOM_TAGS = 5;
public const TASKS_DEPARTMENT = 6;
}
@@ -0,0 +1,17 @@
<?php
namespace App\Classes\ValueObjects\Constants;
final class PerfexCRMTaskPriority {
public const DEFAULT = 0;
public const LOW = 1;
public const MEDIUM = 2;
public const HIGH = 3;
public const URGENT = 4;
}
@@ -13,7 +13,10 @@ class PerfexCRMTasks
'milestone' => 'MILESTONE 1 - Customer Paid',
'reference' => '',
'on_task_completion' => '',
'status' => PerfexCRMTaskStatus::COMPLETED
'department' => '',
'status' => PerfexCRMTaskStatus::COMPLETED,
'priority' => PerfexCRMTaskPriority::DEFAULT,
'duedate' => 0
];
public const TASK_POST_PAYMENT_1 = [
@@ -29,22 +32,22 @@ class PerfexCRMTasks
'milestone' => '',
'reference' => 'TASK_POST_PAYMENT_1',
'on_task_completion' => 'TASK_POST_PAYMENT_2',
'status' => PerfexCRMTaskStatus::IN_PROGRESS
'department' => 'Accounts',
'status' => PerfexCRMTaskStatus::IN_PROGRESS,
'priority' => PerfexCRMTaskPriority::HIGH,
'duedate' => 0
];
public const TASK_POST_PAYMENT_2 = [
'name' => 'Approve Payment',
'description' => ' Purpose: To verify and approve the customer\'s payment on IZYIM<br>
Initial Status: Not Started<br>
Deadline:Same day<br>
Responsible department: Accounts<br>
Next step: Change the status of the Issue Shipping Autocount Invoice operation to "In Progress"<br>
Additional details: When the payment method is FPX or Wallet this task is performed automatically by the system.<br>
Dependencies: Map Transaction operation must be completed before this operation can begin.<br>
Outcomes: The payment will be approved in IZYIM, which will release the customers goods for delivery.<br>',
Amount To be Approve: RM {amount}<br>',
'milestone' => '',
'reference' => 'TASK_POST_PAYMENT_2',
'on_task_completion' => 'TASK_POST_PAYMENT_3',
'status' => ''
'department' => 'Accounts',
'status' => '',
'priority' => PerfexCRMTaskPriority::HIGH,
'duedate' => 0
];
public const TASK_POST_PAYMENT_3 = [
'name' => 'Issue Shipping Autocount Invoince',
@@ -59,7 +62,23 @@ class PerfexCRMTasks
'milestone' => '',
'reference' => 'TASK_POST_PAYMENT_3',
'on_task_completion' => 'TASK_POST_PAYMENT_4',
'status' => ''
'department' => 'Accounts',
'status' => '',
'priority' => PerfexCRMTaskPriority::MEDIUM,
'duedate' => 1
];
public const TASK_POST_PAYMENT_3_1 = [
'name' => 'Issue Shipping Autocount OR',
'description' => ' Purpose: To issue an invoice for the customer\'s payment in accounting software.<br>
Note: Customer Actually Upload Bank Slip or Not, If not, Invoice Will Not be Exported<br>
{link_autocount_or}<br>',
'milestone' => '',
'reference' => 'TASK_POST_PAYMENT_3_1',
'on_task_completion' => 'TASK_POST_PAYMENT_4',
'department' => 'Accounts',
'status' => '',
'priority' => PerfexCRMTaskPriority::DEFAULT,
'duedate' => 0
];
public const TASK_POST_PAYMENT_4 = [
'name' => 'Knockoff Invoice',
@@ -74,34 +93,36 @@ class PerfexCRMTasks
'milestone' => '',
'reference' => 'TASK_POST_PAYMENT_4',
'on_task_completion' => '',
'status' => ''
'department' => 'Accounts',
'status' => '',
'priority' => PerfexCRMTaskPriority::MEDIUM,
'duedate' => 1
];
public const TASK_LOADED_CONTAINER_1 = [
'name' => 'Generate Shipping Invoices',
'description' => ' Purpose: -<br>
Initial Status: In Progress<br>
Deadline: Next day<br>
Responsible department: Operation<br>
Assignee: -<br>
Next step: Approve Shipping Invoice change to in progress.<br>',
Link to order page: {link_order}<br>',
'milestone' => '',
'reference' => 'TASK_LOADED_CONTAINER_1',
'on_task_completion' => 'TASK_LOADED_CONTAINER_2',
'status' => PerfexCRMTaskStatus::IN_PROGRESS
'department' => 'Operations',
'status' => PerfexCRMTaskStatus::IN_PROGRESS,
'priority' => PerfexCRMTaskPriority::HIGH,
'duedate' => 1
];
public const TASK_LOADED_CONTAINER_2 = [
'name' => 'Approve Shipping Invoices',
'description' => ' Purpose: -<br>
Initial Status: Not Starteds<br>
Deadline: Next day<br>
Responsible department: Customer Services<br>
Next step: -<br>',
Link to refer Pay On Behalf or Any extra charge: : {link_perfex}<br>',
'milestone' => '',
'reference' => 'TASK_LOADED_CONTAINER_2',
'on_task_completion' => '',
'status' => ''
'department' => 'Customer Services',
'status' => '',
'priority' => PerfexCRMTaskPriority::HIGH,
'duedate' => 1
];
@@ -118,6 +139,9 @@ class PerfexCRMTasks
'milestone' => '',
'reference' => 'TASK_IDENTIFICATION_1',
'on_task_completion' => '',
'status' => PerfexCRMTaskStatus::IN_PROGRESS
'department' => 'Operations',
'status' => PerfexCRMTaskStatus::IN_PROGRESS,
'priority' => PerfexCRMTaskPriority::DEFAULT,
'duedate' => 0
];
}
@@ -16,4 +16,10 @@ final class RoleTypes
public const USER = 3;
public const USER_TYPE_ID = [
self::SHADOW_ADMIN => "Shadow Admin",
self::SUPER_ADMIN => "Super Admin",
self::ADMIN => "Admin",
self::USER => "User",
];
}
@@ -27,4 +27,9 @@ final class TransactionType {
// public const SHIPPING_COST = 9;
public const TRANSACTION_TYPE_ID = [
self::SHIPPING_INVOICE => "Shipping Invoice",
self::PAYMENT => "Payment",
];
}
@@ -22,6 +22,10 @@ final class WarehouseReferences {
public const VT_SARAWAK = 'SRW-V01';
public const YD_FS_WEST_MALAYSIA = 'FS-V01';
public const YD_FS_EAST_MALAYSIA = 'FS-V02';
public const VT_DESTINATION_WAREHOUSE = [
1 => self::VT_KLANG,
2 => self::VT_KLANG,
@@ -0,0 +1,75 @@
<?php
namespace App\Console\Commands;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Transaction;
use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Http;
class AuditBillplzInvoice extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'billplz-invoice:audit';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Check all unpaid invoice but marked paid at our system';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
ini_set('memory_limit', '-1');
$this->info(Carbon::now() . ' : Audit Billplz Invoice cron started.');
$start = new Carbon();
$transactions = Transaction::where('type', TransactionType::SHIPPING_INVOICE)->where('status', ApprovalStatus::COMPLETED)->whereHas('transactions', function($query){
return $query->where('type', TransactionType::PAYMENT)->where('payment_method', PaymentMethodType::PAYMENT_GATEWAY)->where('status', ApprovalStatus::REJECTED);
})->get();
$totalTransactions = count($transactions);
$counter = 1;
$totalAmount = 0;
foreach ($transactions as $transaction){
$payment_transaction = $transaction->transactions->sortByDesc('created_at')->first();
if ($payment_transaction->status === ApprovalStatus::REJECTED) {
$this->info($counter . ' of ' . $totalTransactions . '. Order Marking: '. $payment_transaction->owner->owner->owner->reference . '. Transaction Id: '. $payment_transaction->id . '. Invoice Id: '. $transaction->id . ' - Date: '.$payment_transaction->created_at->format('d-m-Y').' - Amount: '. $payment_transaction->amount);
$totalAmount += $transaction->amount;
$counter++;
}
}
$end = new Carbon();
$elapsedTime = $start->diff($end)->format('%H:%I:%S');
$this->info(Carbon::now() . ' : Done Audit Billplz. ElapsedTime: ' . $elapsedTime . '. Total: ' . $totalAmount);
}
}
@@ -0,0 +1,77 @@
<?php
namespace App\Console\Commands;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Transaction;
use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Http;
class AuditBillplzPayment extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'billplz-payment:audit';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Check all failed payment in billplz, but marked at success at our system';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
ini_set('memory_limit', '-1');
$this->info(Carbon::now() . ' : Audit Billplz Payment cron started.');
$start = new Carbon();
$transactions = Transaction::where('type', TransactionType::PAYMENT)->where('payment_method', PaymentMethodType::PAYMENT_GATEWAY)->whereIn('status', [ApprovalStatus::COMPLETED, ApprovalStatus::APPROVED])->get();
$totalTransactions = count($transactions);
$counter = 1;
$totalAmount = 0;
foreach ($transactions as $transaction){
$response = Http::withBasicAuth(config('billplz.api_key').':', '')->get(config('billplz.base_url').'/api/v3/bills/'.$transaction->payment_reference);
if($response->successful()){
$data = $response->json();
if($data['paid']){
} else {
$totalAmount += $transaction->amount;
$this->info($counter . ' of ' . $totalTransactions . '. Order: '. $transaction->owner->owner->owner->reference . ' - Date: '.$transaction->owner->created_at->format('d-m-Y').' - Amount: '. $transaction->amount);
}
}else{
$this->info("billplz error</br>");
}
$counter++;
}
$end = new Carbon();
$elapsedTime = $start->diff($end)->format('%H:%I:%S');
$this->info(Carbon::now() . ' : Done Audit Billplz. ElapsedTime: ' . $elapsedTime . '. Total: ' . $totalAmount);
}
}
@@ -0,0 +1,86 @@
<?php
namespace App\Console\Commands;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Transaction;
use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Http;
class CheckDeletedInvoiceButPaid extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'check-deleted-paid-invoice';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Check all deleted invoice but has completed payment';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
ini_set('memory_limit', '-1');
$this->info(Carbon::now() . ' : Start Check all deleted invoice but has completed payment.');
$start = new Carbon();
$totalAmount = 0;
$softDeletedTransactions = Transaction::onlyTrashed()->where('type', TransactionType::SHIPPING_INVOICE)->whereHas('transactions', function (Builder $query) {
$query->where('type', TransactionType::PAYMENT)->where('payment_method', PaymentMethodType::PAYMENT_GATEWAY);
})->get();
foreach ($softDeletedTransactions as $invoice) {
$invoice_payments = $invoice->transactions()->payments()->get();
foreach($invoice_payments as $invoice_payment) {
$response = Http::withBasicAuth(config('billplz.api_key').':', '')->get(config('billplz.base_url').'/api/v3/bills/'.$invoice_payment->payment_reference);
if($response->successful()){
$data = $response->json();
$orderReference = $invoice->owner->owner->reference ?? null;
if($data['paid']){
$this->info('Invoice id: ' . $invoice->id. '. Payment id: ' . $invoice_payment->id . '. Order: ' . $orderReference);
} else {
}
}else{
$this->info("billplz error</br>");
}
}
}
$end = new Carbon();
$elapsedTime = $start->diff($end)->format('%H:%I:%S');
$this->info(Carbon::now() . ' : Done Check all deleted invoice but has completed payment. ElapsedTime: ' . $elapsedTime . '. Total: ' . $totalAmount);
}
}
@@ -0,0 +1,185 @@
<?php
namespace App\Console\Commands;
use App\Classes\Exceptions\ResourceNotFoundException;
use App\Classes\Modules\Billplzs\DataTransferObjects\BillplzXSignatureObject;
use App\Classes\Modules\Billplzs\Services\GetBillplzBill;
use App\Classes\Modules\Orders\Processors\UpdateDoFromVTPortalProcessor;
use App\Classes\Modules\Orders\Processors\UpdateDoFromYDPortalProcessor;
use App\Classes\Modules\Transactions\Services\FetchesTransaction;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Order;
use App\Models\Transaction;
use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Http;
class FixBillplzFailedCallbackPayment extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'billplz-failed-callback:fix';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Fix all failled callback from billplz';
protected $output = null;
protected $outputArray = [];
/** @var GetBillplzBill */
private $getBillplzBill;
/** @var FetchesTransaction */
private $fetchesTransaction;
/** @var UpdatesTransactionStatus */
private $updatesTransactionStatus;
/** @var UpdateDoFromVTPortalProcessor */
private $updateDoFromVTPortalProcessor;
/** @var UpdateDoFromYDPortalProcessor */
private $updateDoFromYDPortalProcessor ;
/**
* Create a new command instance.
*
* @return void
*/
public function __construct(GetBillplzBill $getBillplzBill, FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, UpdateDoFromVTPortalProcessor $updateDoFromVTPortalProcessor, UpdateDoFromYDPortalProcessor $updateDoFromYDPortalProcessor)
{
parent::__construct();
$this->getBillplzBill = $getBillplzBill;
$this->fetchesTransaction = $fetchesTransaction;
$this->updatesTransactionStatus = $updatesTransactionStatus;
$this->updateDoFromVTPortalProcessor = $updateDoFromVTPortalProcessor;
$this->updateDoFromYDPortalProcessor = $updateDoFromYDPortalProcessor;
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
ini_set('memory_limit', '-1');
$this->info(Carbon::now() . ' : Fix failled callback from billplz cron started.');
$this->outputArray = [];
$start = new Carbon();
$approvalStatusArray = ApprovalStatus::APPROVAL_STATUS_ID;
$transactions = Transaction::where('type', TransactionType::PAYMENT)->where('payment_method', PaymentMethodType::PAYMENT_GATEWAY)->whereNotIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->get();
$totalTransactions = count($transactions);
$counter = 1;
$totalAmount = 0;
foreach ($transactions as $transaction){
$response = Http::withBasicAuth(config('billplz.api_key').':', '')->get(config('billplz.base_url').'/api/v3/bills/'.$transaction->payment_reference);
if($response->successful()){
$data = $response->json();
if($data['paid']){
$totalAmount += $transaction->amount;
$invoiceStatus = null;
switch($transaction->owner->status) {
case 3:
$invoiceStatus = 'Payment Completed';
break;
case 5:
$invoiceStatus = 'Dispute in progress';
break;
case 6:
$invoiceStatus = 'Cancelled Invoice';
break;
default:
$invoiceStatus = 'Pending Payment';
}
$order = $transaction->owner->owner->owner;
if (in_array($invoiceStatus , ['Pending Payment', 'Payment Completed'])) {
// code here
// $billPlz = $this->getBillplzBill->execute($billplzXSignatureObject->getBillPlzId());
// if(!$billPlz) throw new ResourceNotFoundException('Billplz bill not found.');
// $transaction = $this->fetchesTransaction->execute(['payment_reference' => $billplzXSignatureObject->getBillPlzId()]);
$invoice = $transaction->owner;
$packingList = $invoice->owner;
$order = $packingList->owner;
$status = ApprovalStatus::PENDING_VERIFICATION;
if($data['state'] === 'paid') {
$status = ApprovalStatus::APPROVED;
}
// if($data->state === 'due') {
// $status = $billplzXSignatureObject->getStatus() === 'failed' ? ApprovalStatus::REJECTED : ApprovalStatus::PENDING_VERIFICATION;
// }
// $token = Auth::fromUser(User::find(1));
// $request->headers->set('Authorization', 'Bearer '.$token);
$this->updatesTransactionStatus->execute($transaction, $status);
$totalPaidAmount = $invoice->transactions->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->sum('amount');
if(($invoice->amount - $totalPaidAmount) < 0.01) {
$this->updatesTransactionStatus->execute($invoice, ApprovalStatus::COMPLETED);
$packingList->status = ApprovalStatus::APPROVED;
$packingList->save();
if(app()->environment('production')){
$this->updateDoFromVTPortalProcessor->execute($packingList);
$this->updateDoFromYDPortalProcessor->execute($packingList);
}
$this->info('Updated invoice ' . $counter . ' of ' . $totalTransactions . '. Order: '. $order->reference . ' - Date: '.$transaction->owner->created_at->format('d-m-Y').' - Amount: '. $transaction->amount . '. Status: ' . $approvalStatusArray[$transaction->status] . '. Invoice Status: ' . $invoiceStatus);
} else {
$this->info('Failed to update invoice due to unsufficeint payment ' . $counter . ' of ' . $totalTransactions . '. Order: '. $order->reference . ' - Date: '.$transaction->owner->created_at->format('d-m-Y').' - Amount: '. $transaction->amount . '. Status: ' . $approvalStatusArray[$transaction->status] . '. Invoice Status: ' . $invoiceStatus);
}
} else {
if(!$order instanceof Order) {
$this->info("Error transaction id:" . $transaction->id . 'Type: ' . get_class($order));
} else {
$this->info($counter . ' of ' . $totalTransactions . '. Order: '. $order->reference . ' - Date: '.$transaction->owner->created_at->format('d-m-Y').' - Amount: '. $transaction->amount . '. Status: ' . $approvalStatusArray[$transaction->status] . '. Invoice Status: ' . $invoiceStatus);
}
}
} else {
// $totalAmount += $transaction->amount;
// $this->appendToOutput($counter . ' of ' . $totalTransactions . '. Order: '. $transaction->owner->owner->owner->reference . ' - Date: '.$transaction->owner->created_at->format('d-m-Y').' - Amount: '. $transaction->amount);
}
}else{
$this->info("billplz error</br>");
}
$counter++;
}
$end = new Carbon();
$elapsedTime = $start->diff($end)->format('%H:%I:%S');
$this->info(Carbon::now() . ' : Done Billplz Failled Callback. ElapsedTime: ' . $elapsedTime . '. Total: ' . $totalAmount);
}
}
@@ -0,0 +1,69 @@
<?php
namespace App\Console\Commands;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Transaction;
use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Http;
class ShowBillplzPaymentStatus extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'billplz-payment-status {billplz_id}` ';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Show Billplz payment status';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
ini_set('memory_limit', '-1');
$this->info(Carbon::now() . ' : Show Billplz payment status started.');
$start = new Carbon();
$billplz_id = $this->argument('billplz_id');
$billplz_id = explode(",", $billplz_id);
foreach ($billplz_id as $payment) {
$response = Http::withBasicAuth(config('billplz.api_key').':', '')->get(config('billplz.base_url').'/api/v3/bills/'.$payment);
if($response->successful()){
$data = $response->json();
dump($data);
}else{
$this->info("billplz error</br>");
}
}
$end = new Carbon();
$elapsedTime = $start->diff($end)->format('%H:%I:%S');
$this->info(Carbon::now() . ' : Done Showing Billplz payment status. ElapsedTime: ' . $elapsedTime);
}
}
@@ -0,0 +1,136 @@
<?php
namespace App\Console\Commands;
use App\Classes\Exceptions\ResourceNotFoundException;
use App\Classes\Modules\Billplzs\DataTransferObjects\BillplzXSignatureObject;
use App\Classes\Modules\Billplzs\Services\GetBillplzBill;
use App\Classes\Modules\Orders\Processors\UpdateDoFromVTPortalProcessor;
use App\Classes\Modules\Orders\Processors\UpdateDoFromYDPortalProcessor;
use App\Classes\Modules\Transactions\Services\FetchesTransaction;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Order;
use App\Models\Transaction;
use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Http;
class ShowFixBillplzFailedCallbackPayment extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'billplz-failed-callback:show';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Check all failled callback from billplz';
protected $output = null;
protected $outputArray = [];
/** @var GetBillplzBill */
private $getBillplzBill;
/** @var FetchesTransaction */
private $fetchesTransaction;
/** @var UpdatesTransactionStatus */
private $updatesTransactionStatus;
/** @var UpdateDoFromVTPortalProcessor */
private $updateDoFromVTPortalProcessor;
/** @var UpdateDoFromYDPortalProcessor */
private $updateDoFromYDPortalProcessor ;
/**
* Create a new command instance.
*
* @return void
*/
public function __construct(GetBillplzBill $getBillplzBill, FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, UpdateDoFromVTPortalProcessor $updateDoFromVTPortalProcessor, UpdateDoFromYDPortalProcessor $updateDoFromYDPortalProcessor)
{
parent::__construct();
$this->getBillplzBill = $getBillplzBill;
$this->fetchesTransaction = $fetchesTransaction;
$this->updatesTransactionStatus = $updatesTransactionStatus;
$this->updateDoFromVTPortalProcessor = $updateDoFromVTPortalProcessor;
$this->updateDoFromYDPortalProcessor = $updateDoFromYDPortalProcessor;
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
ini_set('memory_limit', '-1');
$this->info(Carbon::now() . ' : Billplz Failled Callback cron started.');
$this->outputArray = [];
$start = new Carbon();
$approvalStatusArray = ApprovalStatus::APPROVAL_STATUS_ID;
$transactions = Transaction::where('type', TransactionType::PAYMENT)->where('payment_method', PaymentMethodType::PAYMENT_GATEWAY)->whereNotIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->get();
$totalTransactions = count($transactions);
$counter = 1;
$totalAmount = 0;
foreach ($transactions as $transaction){
$response = Http::withBasicAuth(config('billplz.api_key').':', '')->get(config('billplz.base_url').'/api/v3/bills/'.$transaction->payment_reference);
if($response->successful()){
$data = $response->json();
if($data['paid']){
$totalAmount += $transaction->amount;
$invoiceStatus = null;
switch($transaction->owner->status) {
case 3:
$invoiceStatus = 'Payment Completed';
break;
case 5:
$invoiceStatus = 'Dispute in progress';
break;
case 6:
$invoiceStatus = 'Cancelled Invoice';
break;
default:
$invoiceStatus = 'Pending Payment';
}
$order = $transaction->owner->owner->owner;
if(!$order instanceof Order) {
$this->info("Error transaction id:" . $transaction->id . 'Type: ' . get_class($order));
} else {
$this->info($counter . ' of ' . $totalTransactions . '. Order: '. $order->reference . ' - Date: '.$transaction->owner->created_at->format('d-m-Y').' - Amount: '. $transaction->amount . '. Status: ' . $approvalStatusArray[$transaction->status] . '. Invoice Status: ' . $invoiceStatus);
}
} else {
// $totalAmount += $transaction->amount;
// $this->appendToOutput($counter . ' of ' . $totalTransactions . '. Order: '. $transaction->owner->owner->owner->reference . ' - Date: '.$transaction->owner->created_at->format('d-m-Y').' - Amount: '. $transaction->amount);
}
}else{
$this->info("billplz error</br>");
}
$counter++;
}
$end = new Carbon();
$elapsedTime = $start->diff($end)->format('%H:%I:%S');
$this->info(Carbon::now() . ' : Done Billplz Failled Callback. ElapsedTime: ' . $elapsedTime . '. Total: ' . $totalAmount);
}
}
@@ -0,0 +1,138 @@
<?php
namespace App\Console\Commands;
use App\Classes\Exceptions\ResourceNotFoundException;
use App\Classes\Modules\Billplzs\DataTransferObjects\BillplzXSignatureObject;
use App\Classes\Modules\Billplzs\Services\GetBillplzBill;
use App\Classes\Modules\Orders\Processors\UpdateDoFromVTPortalProcessor;
use App\Classes\Modules\Orders\Processors\UpdateDoFromYDPortalProcessor;
use App\Classes\Modules\Transactions\Services\FetchesTransaction;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Order;
use App\Models\Transaction;
use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Http;
class SuccessUpdatePaymentStatusButFailedCallback extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'fix-invoice-status';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Success Updated Payment Status But Inoie stat';
protected $output = null;
protected $outputArray = [];
/** @var GetBillplzBill */
private $getBillplzBill;
/** @var FetchesTransaction */
private $fetchesTransaction;
/** @var UpdatesTransactionStatus */
private $updatesTransactionStatus;
/** @var UpdateDoFromVTPortalProcessor */
private $updateDoFromVTPortalProcessor;
/** @var UpdateDoFromYDPortalProcessor */
private $updateDoFromYDPortalProcessor ;
/**
* Create a new command instance.
*
* @return void
*/
public function __construct(GetBillplzBill $getBillplzBill, FetchesTransaction $fetchesTransaction, UpdatesTransactionStatus $updatesTransactionStatus, UpdateDoFromVTPortalProcessor $updateDoFromVTPortalProcessor, UpdateDoFromYDPortalProcessor $updateDoFromYDPortalProcessor)
{
parent::__construct();
$this->getBillplzBill = $getBillplzBill;
$this->fetchesTransaction = $fetchesTransaction;
$this->updatesTransactionStatus = $updatesTransactionStatus;
$this->updateDoFromVTPortalProcessor = $updateDoFromVTPortalProcessor;
$this->updateDoFromYDPortalProcessor = $updateDoFromYDPortalProcessor;
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
ini_set('memory_limit', '-1');
$this->info(Carbon::now() . ' : Billplz Failled Callback cron started.');
$this->outputArray = [];
$start = new Carbon();
$approvalStatusArray = ApprovalStatus::APPROVAL_STATUS_ID;
$transactions = Transaction::where('type', TransactionType::PAYMENT)
->where('payment_method', PaymentMethodType::PAYMENT_GATEWAY)
->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])
->get();
foreach ($transactions as $payment) {
$invoice = $payment->owner ?? null;
if (!$invoice) {
$this->info('Payment has no owner. Payment ID: ' . $payment->id);
continue;
}
$packingList = $invoice->owner ?? null;
if (!$packingList) {
$this->info('Invoice has no owner. Invoice ID: ' . $invoice->id);
continue;
}
$order = $packingList->owner;
if (!$invoice) {
$this->info('PackingList has no owner. PackingList ID: ' . $packingList->id);
continue;
}
if ($invoice->status == ApprovalStatus::APPROVED) {
$totalPaidAmount = $invoice->transactions->where('type', TransactionType::PAYMENT)->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])->sum('amount');
if(($invoice->amount - $totalPaidAmount) < 0.01) {
$this->updatesTransactionStatus->execute($invoice, ApprovalStatus::COMPLETED);
$packingList->status = ApprovalStatus::APPROVED;
$packingList->save();
if(app()->environment('production')){
$this->updateDoFromVTPortalProcessor->execute($packingList);
$this->updateDoFromYDPortalProcessor->execute($packingList);
}
dump('Updated invoice ' . $invoice->id . '. Order: '. $order->reference);
} else {
$this->info('Failed Update invoice ' . $invoice->id . ' because payment not enough. Invoice Amount: ' . $invoice->amount . ' . Paid Amount: ' . $totalPaidAmount . ' . Order: '. $order->reference);
}
}
}
$end = new Carbon();
$elapsedTime = $start->diff($end)->format('%H:%I:%S');
$this->info(Carbon::now() . ' : Done Billplz Failled Callback. ElapsedTime: ' . $elapsedTime );
}
}
+5
View File
@@ -47,6 +47,11 @@ class Kernel extends ConsoleKernel
->hourly()
->withoutOverlapping()
->appendOutputTo (storage_path().'/logs/auto_generate_invoice.log');
$schedule->command('billplz-failed-callback:fix')
->dailyAt('00:00')
->withoutOverlapping()
->appendOutputTo (storage_path().'/logs/dix_failed_callback_from_billplz.log');
}
/**
@@ -0,0 +1,19 @@
<?php
namespace App\Http\Controllers\Accounts;
use App\Classes\Modules\Accounts\ControllersLogic\UpdateUserRoleLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class UpdateUserRoleController
{
/**
* @param Request $request
* @param UpdateUserLogic $logic
* @return JsonResponse
*/
public function update(Request $request, UpdateUserRoleLogic $logic): JsonResponse {
return $logic->execute($request);
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Http\Controllers\Companies;
use App\Classes\Modules\Companies\ControllersLogic\UpdateCompanyTypeLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class UpdateCompanyTypeController
{
/**
* @param Request $request
* @param AddNewMemberLogic $execute
* @return JsonResponse
*/
public function create(Request $request, UpdateCompanyTypeLogic $execute) : JsonResponse
{
return $execute->execute($request);
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Http\Controllers\Contacts;
use App\Classes\Modules\Contacts\ControllersLogic\UpdateContactLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class UpdateContactController
{
/**
* @param Request $request
* @param UpdateCompanyLogic $logic
* @return JsonResponse
*/
public function update(Request $request, UpdateContactLogic $logic): JsonResponse {
return $logic->execute($request);
}
}
@@ -41,7 +41,7 @@ class DownloadOrderQrPdfController
$warehousePrefix = 'YW/';
}
if(in_array($warehouse->reference,[WarehouseReferences::YD_GUANG_ZHOU, WarehouseReferences::YD_GUANG_ZHOU_2])){
if(in_array($warehouse->reference,[WarehouseReferences::YD_GUANG_ZHOU, WarehouseReferences::YD_GUANG_ZHOU_2, WarehouseReferences::YD_FS_EAST_MALAYSIA, WarehouseReferences::YD_FS_WEST_MALAYSIA])){
$warehousePrefix = 'YD/';
if(strtolower($deliveryAddress->state->name) === 'sabah' || strtolower($deliveryAddress->state->name) === 'labuan' || in_array(strtolower($deliveryAddress->district->name), ['limbang', 'lawas'])) {
@@ -0,0 +1,20 @@
<?php
namespace App\Http\Controllers\Orders;
use App\Classes\Modules\Orders\ControllersLogic\FetchOrderV2Logic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class FetchOrderV2Controller
{
/**
* @param Request $request
* @param FetchOrderLogic $logic
* @return JsonResponse
*/
public function fetch(Request $request, FetchOrderV2Logic $logic): JsonResponse
{
return $logic->execute($request);
}
}
@@ -0,0 +1,22 @@
<?php
namespace App\Http\Controllers\Orders;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use App\Classes\Modules\Orders\ControllersLogic\ListOrdersV2Logic;
class ListOrdersV2Controller
{
/**
* @param Request $request
* @param ListOrdersV2Logic $logic
* @return JsonResponse
*/
public function list(Request $request, ListOrdersV2Logic $logic) : JsonResponse {
return $logic->execute($request);
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Http\Controllers\PackingLists;
use App\Classes\Modules\PackingLists\ControllersLogic\DeletePackingListByPackageIdLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class DeletePackingListByPackageIdController
{
/**
* @param Request $request
* @param DeletePackingListLogic $logic
* @return JsonResponse
*/
public function delete(Request $request, DeletePackingListByPackageIdLogic $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\DeleteTransactionLogic;
class DeleteTransactionController
{
/**
* @param Request $request
* @param DeleteTransactionLogic $logic
* @return JsonResponse
*/
public function delete(Request $request, DeleteTransactionLogic $logic) : JsonResponse {
return $logic->execute($request);
}
}
+7 -1
View File
@@ -44,6 +44,11 @@ class Kernel extends HttpKernel
'throttle:300,1',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'apipub' => [
// \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
/**
@@ -63,6 +68,7 @@ class Kernel extends HttpKernel
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'valid.token' => ValidateToken::class
'valid.token' => ValidateToken::class,
'token.check' => \App\Http\Middleware\TokenCheckerMiddleware::class,
];
}
@@ -0,0 +1,56 @@
<?php
namespace App\Http\Middleware;
use App\Models\PersonalAccessTokens;
use Closure;
use Illuminate\Http\Request;
class TokenCheckerMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\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)
{
//Method 1: Token pass via query parameter
// Check if the api_key query parameter is present
if (!$request->query('api-key')) {
return response()->json(['message' => 'Invalid API key.'], 401);
}
// Check if the api_key is valid
$apiKey = $request->query('api-key');
$personalAccessToken = PersonalAccessTokens::where('token', $apiKey)->first();
if (!$personalAccessToken) {
return response()->json(['error' => 'Unauthorized'], 401);
}
return $next($request);
//Method 2: Token pass via request header
/*
$authHeader = $request->header('Authorization');
if (preg_match('/Bearer\s+(.*)$/i', $authHeader, $matches)) {
$token = $matches[1];
// validate the token here
$personalAccessToken = PersonalAccessToken::where('token', $token)->first();
if (!$personalAccessToken) {
return response()->json(['error' => 'Unauthorized'], 401);
}
// if the token is valid, you can attach it to the request
$request->attributes->add(['bearerToken' => $token]);
return $next($request);
}
return response()->json(['error' => 'Unauthorized'], 401);
*/
}
}
+2 -2
View File
@@ -20,8 +20,8 @@ class AnnouncementResource extends JsonResource
'title' => $this->title,
'description' => $this->description,
'segments' => $this->segments,
'starting_on' => Carbon::parse($this->starting_on)->format('Y-m-d'),
'ending_on' => Carbon::parse($this->ending_on)->format('Y-m-d'),
'starting_on' => Carbon::parse($this->starting_on)->format('d-m-Y'),
'ending_on' => Carbon::parse($this->ending_on)->format('d-m-Y'),
'created_at' => Carbon::parse($this->created_at)->format('d-m-Y'),
];
}
@@ -49,6 +49,7 @@ class CompanyModuleResource extends JsonResource
'marking' => $marking,
'warehouseCharges' => array_key_exists($this->id, $segmentConstant) ? $segmentConstant[$this->id] : null,
'connections' => $this->connections,
'contact' => new ContactResource ($this->when($this->has('contacts'), $this->contacts->first())),
];
}
+4
View File
@@ -4,6 +4,7 @@ namespace App\Http\Resources;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\BusinessType;
use App\Classes\ValueObjects\Constants\CompanyType;
use App\Classes\ValueObjects\Constants\DocumentType;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Facades\Crypt;
@@ -19,6 +20,8 @@ class CompanyResource extends JsonResource
public function toArray($request)
{
$companyModule = $this->companyModules()->first();
$companyTypeArray = CompanyType::COMPANY_TYPE_ID;
return [
'id' => $this->id,
'hash_id' => Crypt::encryptString($this->id),
@@ -26,6 +29,7 @@ class CompanyResource extends JsonResource
'debtor' => $this->debtor,
'reference' => $this->reference,
'type' => (int) $this->type,
'type_name' => ($companyTypeArray[(int) $this->type]),
'business_type' => (int) $this->business_type,
'status' => (int) $this->status,
'segments' => SegmentResource::collection($companyModule->connections()->first()->segments),
+40
View File
@@ -0,0 +1,40 @@
<?php
namespace App\Http\Resources;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\OrderRoleTypes;
use App\Classes\ValueObjects\Constants\PackingListType;
use App\Classes\ValueObjects\Constants\TransportType;
use Carbon\Carbon;
use Illuminate\Http\Resources\Json\JsonResource;
class OrderV2Resource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'reference' => $this->reference,
'reference_contract' => (int) $this->type,
'type' => (int) $this->type,
'status' => (int) $this->status,
'company_module' => new CompanyModuleResource($this->companyModule),
'warehouse' => new CompanyModuleResource($this->orderRoles()->where('role_id', '=', OrderRoleTypes::ORIGIN_WAREHOUSE)->first()->appointee),
'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])->get());
}),
'remarks' => RemarkResource::collection($this->remarks),
'created_at' => $this->created_at->format('d-m-Y')
];
}
}
+3
View File
@@ -2,6 +2,7 @@
namespace App\Http\Resources;
use App\Classes\ValueObjects\Constants\RoleTypes;
use Illuminate\Http\Resources\Json\JsonResource;
class UserResource extends JsonResource
@@ -14,11 +15,13 @@ class UserResource extends JsonResource
*/
public function toArray($request)
{
$userTypeArray = RoleTypes::USER_TYPE_ID;
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'type' => (int) $this->type,
'type_name' => ($userTypeArray[(int) $this->type]),
'status' => (int) $this->status
];
}
+9
View File
@@ -0,0 +1,9 @@
<?php
namespace App\Models;
class PersonalAccessTokens extends AbstractModel
{
protected $table = 'personal_access_tokens';
}
+5
View File
@@ -43,6 +43,11 @@ class RouteServiceProvider extends ServiceProvider
->namespace($this->namespace)
->group(base_path('routes/api.php'));
Route::prefix('public/api')
->middleware('apipub')
->namespace($this->namespace)
->group(base_path('routes/apipub.php'));
Route::middleware('web')
->namespace($this->namespace)
->group(base_path('routes/web.php'));
@@ -0,0 +1,36 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreatePersonalAccessTokensTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('personal_access_tokens', function (Blueprint $table) {
$table->bigIncrements('id');
// $table->morphs('tokenable');
$table->string('name');
$table->string('token', 64)->unique();
$table->text('abilities')->nullable();
$table->timestamp('last_used_at')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('personal_access_tokens');
}
}
+30
View File
@@ -46,19 +46,23 @@ use App\Classes\ValueObjects\Constants\DocumentType;
use App\Classes\ValueObjects\Constants\PackageType;
use App\Classes\ValueObjects\Constants\PackingListType;
use App\Classes\ValueObjects\Constants\RoleTypes;
use App\Classes\ValueObjects\Constants\SegmentConstants;
use App\Classes\ValueObjects\Constants\TransportType;
use App\Classes\Modules\Segments\Processors\UpdatePostcodeSegmentProcessor;
use App\Models\Address;
use App\Models\Company;
use App\Models\CompanyModule;
use App\Models\Container;
use App\Models\Document;
use App\Models\PackingList;
use App\Models\SegmentConstant;
use App\Models\Transport;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Database\Seeder;
use Faker\Generator as Faker;
use Illuminate\Support\Facades\Artisan;
class DummyDataSeeder extends Seeder
{
@@ -583,6 +587,32 @@ class DummyDataSeeder extends Seeder
// 3. overweight cbm
}
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //
// Generate and Approve Dummmy Invoice //
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //
ini_set('memory_limit', '-1');
$randomCompanyModule = CompanyModule::latest('id')->take(5)->get();
$centerPostcodeConstantObject = SegmentConstant::where('reference', SegmentConstants::CENTER_POSTCODE)->get();
$centerPostcodeConstant = $centerPostcodeConstantObject->isEmpty() ? [] : (array)$centerPostcodeConstantObject->first()->value;
foreach($randomCompanyModule as $companyModule) {
foreach($companyModule->addresses as $address) {
$postcode = $address->postcode;
$postcodeArea = in_array($postcode, $centerPostcodeConstant) ? 'CENTER_POSTCODE' : null;
if (!$postcodeArea) {
$random = rand(0, 1);
$postcodeArray = ['OUTSTATION_POSTCODE', 'CENTER_POSTCODE'];
(App()->make(UpdatePostcodeSegmentProcessor::class))->execute('1', $postcodeArray[$random],$postcode);
$this->command->info($postcodeArray[$random]);
}
}
}
Artisan::call('invoice:generate');
Artisan::call('approve:invoice');
}
}
@@ -0,0 +1,127 @@
<?php
namespace Database\Seeders;
use App\Classes\Modules\Addresses\DataTransferObjects\AddressObject;
use App\Classes\Modules\Addresses\Processors\CreateAddressFromOldAddressProcessor;
use App\Classes\Modules\Addresses\Services\CreatesAddress;
use App\Classes\Modules\Companies\DataTransferObjects\CompanyConnectionObject;
use App\Classes\Modules\Companies\DataTransferObjects\CompanyObject;
use App\Classes\Modules\Companies\Processors\CreateCompanyModuleProcessor;
use App\Classes\Modules\Companies\Processors\CreateCompanyProcessor;
use App\Classes\Modules\Companies\Services\ApprovesCompanyConnection;
use App\Classes\Modules\Companies\Services\CreatesCompany;
use App\Classes\Modules\Companies\Services\CreatesCompanyConnection;
use App\Classes\Modules\Companies\Services\FetchesCompany;
use App\Classes\Modules\Companies\Services\UpdatesCompanyStatus;
use App\Classes\Modules\Contacts\DataTransferObjects\ContactObject;
use App\Classes\Modules\Contacts\Processors\CreateContactProcessor;
use App\Classes\Modules\Contacts\Services\CreatesContact;
use App\Classes\ValueObjects\Constants\AddressType;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\CompanyType;
use App\Classes\ValueObjects\Constants\BusinessType;
use App\Classes\ValueObjects\Constants\WarehouseReferences;
use App\Models\CompanyModule;
use App\Models\OldCompany;
use Illuminate\Database\Seeder;
use App\Models\Company;
class FoshanWarehouseTableSeeder extends Seeder
{
/** @var CreateCompanyProcessor */
private $createCompanyProcessor;
/** @var UpdatesCompanyStatus*/
private $updatesCompanyStatus;
/** @var CreateCompanyModuleProcessor */
private $createCompanyModuleProcessor;
/** @var CreateContactProcessor */
private $createContactProcessor;
/** @var CreatesCompanyConnection */
private $createsCompanyConnection;
/** @var ApprovesCompanyConnection */
private $approvesCompanyConnection;
/** @var CreateAddressFromOldAddressProcessor */
private $createAddressFromOldAddressProcessor;
/** @var CreatesAddress */
private $createsAddress;
/** @var FetchesCompany */
private $fetchesCompany;
/** @var CreatesContact */
private $createsContact;
/**
* ModernWarehouseTableSeeder constructor.
* @param CreateCompanyProcessor $createCompanyProcessor
* @param UpdatesCompanyStatus $updatesCompanyStatus
* @param CreateCompanyModuleProcessor $createCompanyModuleProcessor
* @param CreateContactProcessor $createContactProcessor
* @param CreatesCompanyConnection $createsCompanyConnection
* @param ApprovesCompanyConnection $approvesCompanyConnection
* @param CreateAddressFromOldAddressProcessor $createAddressFromOldAddressProcessor
* @param CreatesAddress $createsAddress
* @param FetchesCompany $fetchesCompany
* @param CreatesContact $createsContact
*/
public function __construct(CreateCompanyProcessor $createCompanyProcessor, UpdatesCompanyStatus $updatesCompanyStatus, CreateCompanyModuleProcessor $createCompanyModuleProcessor, CreateContactProcessor $createContactProcessor, CreatesCompanyConnection $createsCompanyConnection, ApprovesCompanyConnection $approvesCompanyConnection, CreateAddressFromOldAddressProcessor $createAddressFromOldAddressProcessor, CreatesAddress $createsAddress, FetchesCompany $fetchesCompany, CreatesContact $createsContact)
{
$this->createCompanyProcessor = $createCompanyProcessor;
$this->updatesCompanyStatus = $updatesCompanyStatus;
$this->createCompanyModuleProcessor = $createCompanyModuleProcessor;
$this->createContactProcessor = $createContactProcessor;
$this->createsCompanyConnection = $createsCompanyConnection;
$this->approvesCompanyConnection = $approvesCompanyConnection;
$this->createAddressFromOldAddressProcessor = $createAddressFromOldAddressProcessor;
$this->createsAddress = $createsAddress;
$this->fetchesCompany = $fetchesCompany;
$this->createsContact = $createsContact;
}
/**
* Run the database seeds.
*
* @return void
* @throws \App\Classes\Exceptions\AccessForbiddenException
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
public function run()
{
/** @var Company $company */
$company = $this->fetchesCompany->execute(['reference' => 'MODERN']);
// YD_FS_WEST_MALAYSIA - FS-V01
/** @var CompanyModule $companyModule */
$companyModule = $this->createCompanyModuleProcessor->execute($company, BusinessType::WAREHOUSE);
$companyModule->update(['name' => 'Foshan', 'reference' => WarehouseReferences::YD_FS_WEST_MALAYSIA]);
$address = new AddressObject('广东省 佛山市 南海区 狮山镇北园东路6号D幢1楼', '', 2, 35, 638, 528225, AddressType::DELIVERY, ApprovalStatus::APPROVED);
$contact = new ContactObject('郑佳鹏', '18520607573', '', '');
$this->createsAddress->execute($companyModule, $address);
$this->createsContact->execute($companyModule, $contact);
// FS_EAST_MALAYSIA - FS-V02
/** @var CompanyModule $companyModule */
$companyModule = $this->createCompanyModuleProcessor->execute($company, BusinessType::WAREHOUSE);
$companyModule->update(['name' => 'Foshan', 'reference' => WarehouseReferences::YD_FS_EAST_MALAYSIA]);
$address = new AddressObject('广东省 佛山市 南海区 狮山镇北园东路6号C幢1楼', '', 2, 35, 638, 528225, AddressType::DELIVERY, ApprovalStatus::APPROVED);
$contact = new ContactObject('游万彬', '18520607573', '', '');
$this->createsAddress->execute($companyModule, $address);
$this->createsContact->execute($companyModule, $contact);
}
}
@@ -38,7 +38,7 @@ class SegmentConstantsTableSeeder extends Seeder
Segmentconstant::create( [
'segment_id'=>1,
'reference'=>'STATE_RATE',
'value'=>'[{"state_id":1,"center":"10.00","outstation":"2.00"},{"center":"10.00","outstation":"0.00"},{"center":"10.00","outstation":"0.00"},{"center":"50.00","outstation":"0.00"},{"center":"0.00","outstation":"0.00"},{"center":"345.00","outstation":"0.00"},{"center":"10.00","outstation":"0.00"},{"center":"10.00","outstation":"0.00"},{"center":"10.00","outstation":"0.00"},{"center":"10.00","outstation":"0.00"},{"center":"10.00","outstation":"0.00"},{"center":"10.00","outstation":"0.00"},{"center":"0.00","outstation":"0.00"},{"center":"185.00","outstation":"0.00"},{"center":"185.00","outstation":"0.00"},{"center":"0.00","outstation":"0.00"},{"center":"50.00","outstation":"0.00"}]',
'value'=>'[{"state_id":1,"center":"10.00","outstation":"2.00"},{"center":"10.00","outstation":"10.00"},{"center":"10.00","outstation":"10.00"},{"center":"50.00","outstation":"50.00"},{"center":"12.00","outstation":"12.00"},{"center":"345.00","outstation":"345.00"},{"center":"10.00","outstation":"10.00"},{"center":"10.00","outstation":"10.00"},{"center":"10.00","outstation":"30.00"},{"center":"10.00","outstation":"20.00"},{"center":"10.00","outstation":"10.00"},{"center":"10.00","outstation":"10.00"},{"center":"15.00","outstation":"15.00"},{"center":"185.00","outstation":"23.00"},{"center":"185.00","outstation":"185.00"},{"center":"30.00","outstation":"30.00"},{"center":"50.00","outstation":"50.00"}]',
'deleted_at'=>NULL,
'created_at'=>NULL,
'updated_at'=>'2022-09-27 01:18:15'
@@ -71,7 +71,7 @@ class SegmentConstantsTableSeeder extends Seeder
Segmentconstant::create( [
'segment_id'=>1,
'reference'=>'OUTSTATION_POSTCODE',
'value'=>'["93250","93350","94200","94300","94600","78556","78557","94700","94750","94760","93050","93250","94000","94500","93050","93350","93350","79466","93050","94100","94500","93050","93050","93250","93350","93050","94200","94200","93010","93010","94700","94800","94807","94809","93250","94000","93050","93050","93250","86900","82300","86800","86810","81600","86800","71600","71650","72400","71600","72200","72300","71750","71770","69000","26800","26810","26820","39000","39007","39009","39010","33300","33310","33320","33100"]',
'value'=>'["93250","93350","94200","94300","94600","78556","78557","94700","94750","94760","93050","93250","94000","94500","93050","93350","93350","79466","93050","94100","94500","93050","93050","93250","93350","93050","94200","94200","93010","93010","94700","94800","94807","94809","93250","94000","93050","93050","93250","86900","82300","86800","86810","81600","86800","71600","71650","72400","71600","72200","72300","71750","71770","69000","26800","26810","26820","39000","39007","39009","39010","33300","33310","33320","33100","42425","42500","42507","42509","42800","45500","43950","47507","47600","47610","47620","47640","47650","47200","40000","40100","40470","40500","40502","40503","40505","40512","40517","40520","40529","40542","40548","40550","40551","40560","40564","40570","40572","40576","40578","40582","40590","40592","40594","40596","40598","40604","40607","40608","40610","40612","40620","40622","40626","40632","40646","40648","40660","40664","40670","40672","40673","40674","40675","40676","40680","40690","40700","40702","40704","40706","40708","40710","40712","40714","40716","40718","40720","40722","40724","40726","40728","40730","40732","40800","40802","40804","40806","40808","40810","40990"]',
'deleted_at'=>NULL,
'created_at'=>NULL,
'updated_at'=>'2022-09-21 03:35:19'
+4
View File
@@ -23,5 +23,9 @@ server {
fastcgi_intercept_errors on;
fastcgi_keep_conn on;
fastcgi_param PHP_VALUE "auto_prepend_file= \n allow_url_include=Off \n output_buffering=Off \n output_buffering=4096";
proxy_send_timeout 3600;
proxy_read_timeout 3600;
fastcgi_send_timeout 3600;
fastcgi_read_timeout 3600;
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

@@ -0,0 +1,76 @@
<template>
<div class="row m-b-10 parentContainer">
<div class="col">
<div class="row">
<div class="col-auto">
<div class="row">
<div class="col">
<h6 class="no-margin fs-12 text-black">{{item.street_one}} {{item.street_two}}, {{item.district.name}}, {{item.post_code}} {{item.state.name}}, {{item.country.name}}</h6>
</div>
</div>
</div>
<div class="col-auto">
<div class="row">
<!-- <div class="col-auto p-r-5">
<i class="fa m-r-10" data-type="defaultAddress" :class="{'fa-star': item.default, 'requestModal': !item.default, 'fa-star-o': !item.default, 'pointer': !item.default, 'text-warning': item.default}" ></i>
</div> -->
<div class="col-auto no-padding p-r-5 p-l-5 pointer">
<i class="fa fa-pencil-square-o text-complete m-r-10" @click="expanded = !expanded"></i>
</div>
<!-- <div class="col-auto p-l-5">
<i class="fa fa-trash-o text-danger requestModal" data-type="deleteAddress"></i>
</div> -->
</div>
</div>
</div>
<div class="row" v-if="expanded">
<div class="col">
<warehouse-address-form-component :company_module_id="company_module_id" :data="item" :section="section" @input="updateAddress($event)"></warehouse-address-form-component>
</div>
</div>
<!-- <modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="deleteAddress">
<delete-address-form-component :data="item" :section="section" class="text-center"></delete-address-form-component>
</modal-component>
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="defaultAddress">
<set-default-address-form-component :data="item" :section="section" class="text-center"></set-default-address-form-component>
</modal-component> -->
</div>
</div>
</template>
<script>
import componentHandler from '../../../general/mixins/componentHandler';
export default {
props: {
company_module_id: {
type: Number,
required: true
},
section: {
type: String,
required: true
}
},
data(){
return {
expanded: false
}
},
watch: {
value: function(value){
this.value = value;
if(value !== this.item.id){
this.expanded = false;
}
}
},
methods: {
updateAddress(id){
this.expanded = false;
this.$emit('input', id);
}
},
mixins: [componentHandler]
}
</script>
@@ -0,0 +1,230 @@
<template>
<div class="row p-t-25 text-left">
<div class="col">
<div class="row" v-if="![7,8].includes($store.getters.getCompanyModuleType)">
<div class="col">
<!-- <div class="row m-b-15">
<div class="col">
<validation-wrapper-component :validator="$v.parameters.reference">
<label>Address Reference/Label</label>
<input class="form-control" name="reference" v-model="parameters.reference">
</validation-wrapper-component>
</div>
</div> -->
<div class="row m-b-15">
<div class="col">
<validation-wrapper-component :validator="$v.parameters.street_one">
<label>Address Line 1</label>
<input class="form-control" name="street_one" v-model="parameters.street_one">
</validation-wrapper-component>
</div>
</div>
<div class="row m-b-15">
<div class="col">
<validation-wrapper-component :validator="$v.parameters.street_two">
<label>Address Line 2</label>
<input class="form-control" name="street_two" v-model="parameters.street_two">
</validation-wrapper-component>
</div>
</div>
<div class="row m-b-15">
<div class="col-12 col-md pr-md-1 pb-3 pb-md-0">
<validation-wrapper-component selectable :validator="$v.parameters.district_id">
<label>District</label>
<selectable-component :endpoint="route('api.address.district.list')" section="districtListSection" valueColumn="id" :labelColumn="['city']" v-model="parameters.district_id"></selectable-component>
</validation-wrapper-component>
</div>
<div class="col-12 col-md pl-md-1">
<validation-wrapper-component :validator="$v.parameters.post_code">
<label>Post Code</label>
<input class="form-control" name="post_code" v-model="parameters.post_code">
</validation-wrapper-component>
</div>
</div>
<!-- <div class="row">
<div class="col">
<div class="row">
<div class="col">
<div class="row m-b-15">
<div class="col-12 col-md pr-md-1 pb-3 pb-md-0">
<validation-wrapper-component :validator="$v.parameters.person_in_charge">
<label>Person In Charge</label>
<input class="form-control" name="person_in_charge" v-model="parameters.person_in_charge">
</validation-wrapper-component>
</div>
<div class="col-12 col-md pl-md-1">
<validation-wrapper-component :validator="$v.parameters.phone">
<label>Phone</label>
<input class="form-control" name="phone" v-model="parameters.phone">
</validation-wrapper-component>
</div>
</div>
<div class="row m-b-15">
<div class="col">
<validation-wrapper-component :validator="$v.parameters.remark">
<label>Delivery Remark</label>
<input class="form-control" name="remark" v-model="parameters.remark">
</validation-wrapper-component>
</div>
</div>
</div>
</div>
</div>
</div> -->
</div>
</div>
<div class="row" v-if="[7,8].includes($store.getters.getCompanyModuleType)">
<div class="col">
<div class="row m-b-15">
<div class="col">
<validation-wrapper-component :validator="$v.parameters.reference">
<label>Company Name</label>
<input class="form-control" name="reference" v-model="parameters.reference">
</validation-wrapper-component>
</div>
</div>
<div class="row m-b-15">
<div class="col-12 col-md pr-md-1 pb-3 pb-md-0">
<validation-wrapper-component :validator="$v.parameters.person_in_charge">
<label>Name</label>
<input class="form-control" name="person_in_charge" v-model="parameters.person_in_charge">
</validation-wrapper-component>
</div>
<div class="col-12 col-md pl-md-1">
<validation-wrapper-component :validator="$v.parameters.phone">
<label>Phone</label>
<input class="form-control" name="phone" v-model="parameters.phone">
</validation-wrapper-component>
</div>
</div>
<div class="row m-b-15">
<div class="col-12 col-md-3 pr-md-1 pb-3 pb-md-0">
<validation-wrapper-component :validator="$v.parameters.street_one">
<label>Unit No.</label>
<input class="form-control" name="street_one" v-model="parameters.street_one">
</validation-wrapper-component>
</div>
<div class="col-12 col-md pl-md-1">
<validation-wrapper-component :validator="$v.parameters.street_two">
<label>Street Address</label>
<input class="form-control" name="street_two" v-model="parameters.street_two">
</validation-wrapper-component>
</div>
</div>
<div class="row m-b-15">
<div class="col-12 col-md pr-md-1 pb-3 pb-md-0">
<validation-wrapper-component selectable :validator="$v.parameters.district_id">
<label>City/Town</label>
<selectable-component :endpoint="route('api.address.district.list')" section="districtListSection" valueColumn="id" :labelColumn="['city']" v-model="parameters.district_id"></selectable-component>
</validation-wrapper-component>
</div>
<div class="col-12 col-md pl-md-1">
<validation-wrapper-component :validator="$v.parameters.post_code">
<label>Post Code</label>
<input class="form-control" name="post_code" v-model="parameters.post_code">
</validation-wrapper-component>
</div>
</div>
<div class="row m-b-15">
<div class="col">
<validation-wrapper-component :validator="$v.parameters.remark">
<label>Remark</label>
<input class="form-control" name="remark" v-model="parameters.remark">
</validation-wrapper-component>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="row">
<div class="col"></div>
<div class="col-auto">
<button type="button" class="btn btn-sm btn-complete b-rad-none" @click="submitForm()">{{ this.data ? "Update" : "Save" }} Address</button>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { required, requiredIf, numeric } from "vuelidate/lib/validators";
import componentHandler from '../../../general/mixins/componentHandler';
export default {
props: {
company_module_id: {
type: Number,
required: true
},
type: {
type: Number,
default: 2
},
data: {
type: Object,
default: null
},
section:{
type: String,
required: true
},
},
data() {
return {
parameters : {
company_module_id: this.company_module_id,
street_one: '',
street_two: '',
district_id: '',
post_code: '',
type: this.type,
// reference: null,
// remark: null,
// phone: null,
// person_in_charge: null,
}
}
},
created(){
if(this.data){
this.parameters.reference = this.data.reference;
this.parameters.street_one = this.data.street_one;
this.parameters.street_two = this.data.street_two;
this.parameters.district_id = this.data.district.id;
this.parameters.post_code = this.data.post_code;
this.parameters.type = this.data.type;
this.parameters.phone = this.data.contact ? this.data.contact.phone : '';
this.parameters.person_in_charge = this.data.contact ? this.data.contact.reference : '';
this.parameters.remark = this.data.remark ? this.data.remark.content : '';
}
},
validations: {
parameters: {
// reference: {
// required: requiredIf(function(){
// return ![7,8].includes(this.$store.getters.getCompanyModuleType);
// })
// },
street_one: { required },
street_two: {
required: requiredIf(function(){
return [7,8].includes(this.$store.getters.getCompanyModuleType);
})
},
district_id: { required },
post_code: { required },
// remark: {},
// phone: {required, numeric},
// person_in_charge: { required },
}
},
methods:{
submitForm(){
this.submit(this.data ? (this.route('api.address.update', this.data.id)) : (this.route('api.address.create')), this.data ? 'put' : 'post', this.section, true, true);
},
},
}
</script>
@@ -16,8 +16,9 @@
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="changeCustomerName">
<change-customer-name-form-component :section="'customerProfileSection'" :data="item"></change-customer-name-form-component>
</modal-component>
<div class="font-heading fs-20 light">{{item.name}}
<div class="btn btn-xs b-rad-none pointer requestModal d-inline rounded no-border hover-primary" data-type="changeCustomerName" >
<div class="font-heading fs-20 light">
{{item.name}}
<div class="btn btn-xs b-rad-none pointer requestModal d-inline rounded no-border hover-primary bg-transparent" data-type="changeCustomerName" >
<i class="fa fa-edit pointer fa-fw fs-15 m-l-5"></i>
</div>
</div>
@@ -92,10 +93,24 @@
<h6 class="no-margin">{{item.contact.phone}}</h6>
</div>
</div>
<!-- <div class="row align-items-center">
<div class="col">
<h6 class="no-margin fs-12">WeChat ID</h6>
<h6 class="no-margin">{{item.contact.wechat_id}}</h6>
</div>
</div> -->
<div class="row align-items-center">
<div class="col">
<h6 class="no-margin fs-12">WeChat ID</h6>
<h6 class="no-margin">{{item.contact.wechat_id}}</h6>
<h6 class="no-margin fs-12">Company Type </h6>
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="changeBusinessType">
<change-business-type-form-component :section="'customerProfileSection'" :data="item"></change-business-type-form-component>
</modal-component>
<h6 class="no-margin">
{{item.type_name}}
<div class="btn btn-xs b-rad-none pointer requestModal d-inline rounded no-border hover-primary bg-transparent" data-type="changeBusinessType" v-if="$store.getters.isAdmin">
<i class="fa fa-edit pointer fa-fw fs-15 m-l-5"></i>
</div>
</h6>
</div>
</div>
</div>
@@ -0,0 +1,89 @@
<template>
<div class="row" style="width: 450px; margin: auto;" @keyup.enter="submitForm">
<div class="col bg-white padding-40 b-rad-lg">
<div class="row m-b-10">
<div class="col text-center">
<h3>Edit Contact</h3>
</div>
</div>
<div class="row m-b-15">
<div class="col">
<validation-wrapper-component :validator="$v.parameters.reference">
<label>Reference</label>
<input class="form-control" name="street_one" v-model="parameters.reference">
</validation-wrapper-component>
</div>
</div>
<div class="row m-b-15">
<div class="col">
<validation-wrapper-component :validator="$v.parameters.phone">
<label>Phone</label>
<input class="form-control" name="street_one" v-model="parameters.phone">
</validation-wrapper-component>
</div>
</div>
<div class="row m-b-15">
<div class="col">
<validation-wrapper-component :validator="$v.parameters.email">
<label>Email</label>
<input class="form-control" name="street_one" v-model="parameters.email">
</validation-wrapper-component>
</div>
</div>
<div class="row m-b-15">
<div class="col">
<validation-wrapper-component :validator="$v.parameters.wechat_id">
<label>Wechat ID</label>
<input class="form-control" name="street_one" v-model="parameters.wechat_id">
</validation-wrapper-component>
</div>
</div>
<div class="row m-t-15">
<div class="col-auto p-r-5">
<div class="btn btn-lg btn-default b-rad-none" data-dismiss="modal">Cancel</div>
</div>
<div class="col p-l-5">
<div class="btn btn-primary w-100 btn-lg" @click="submitForm">Confirm</div>
</div>
</div>
</div>
</div>
</template>
<script>
import modalFormHandler from '../../../general/mixins/modalFormHandler';
import { required } from "vuelidate/lib/validators";
export default {
props: {
company_module_id: {
type: Number,
required: true
},
},
data() {
return {
parameters: {
reference: this.data.reference,
phone: this.data.phone,
email: this.data.email,
wechat_id: this.data.wechat_id,
}
};
},
methods: {
submitForm() {
this.submit(this.route('api.contact.update', this.data.id), 'put', this.section, true, true)
},
},
validations: {
parameters: {
reference: { },
phone: { },
email: { },
wechat_id: { },
}
},
mixins: [modalFormHandler]
}
</script>
@@ -0,0 +1,144 @@
<template>
<div class="row" style="margin-top: 100px; margin-bottom: 100px;">
<div class="col">
<div class="row align-items-center justify-content-center w-100" style="height: 200px; top: 0;">
<div class="col">
<div class='tetrominos'>
<div class='tetromino box1'></div>
<div class='tetromino box2'></div>
<div class='tetromino box3'></div>
<div class='tetromino box4'></div>
</div>
</div>
</div>
<div class="row align-items-center justify-content-center">
<div class="col">
<p class="text-center fs-15 muted all-caps font-lato" style="letter-spacing: 2px">
Loading Packages Data
<span class="loading-text"></span>
</p>
</div>
</div>
</div>
</div>
</template>
<style>
.loading-text::after {
content: ".";
animation: loading 2s infinite;
}
@keyframes loading {
0% {
content: ". ";
}
25% {
content: ". . ";
}
50% {
content: ". . . ";
}
75% {
content: ". . . . ";
}
100% {
content: ". . . . . ";
}
}
.tetrominos {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-112px, -96px);
}
.tetromino {
width: 96px;
height: 112px;
position: absolute;
transition: all ease 0.3s;
background: url('data:image/svg+xml;utf-8,%3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 612 684"%3E%3Cpath fill="%23010101" d="M305.7 0L0 170.9v342.3L305.7 684 612 513.2V170.9L305.7 0z"/%3E%3Cpath fill="%23fff" d="M305.7 80.1l-233.6 131 233.6 131 234.2-131-234.2-131"/%3E%3C/svg%3E') no-repeat top center;
}
.box1 {
animation: tetromino1 1.5s ease-out infinite;
}
.box2 {
animation: tetromino2 1.5s ease-out infinite;
}
.box3 {
animation: tetromino3 1.5s ease-out infinite;
z-index: 2;
}
.box4 {
animation: tetromino4 1.5s ease-out infinite;
}
@keyframes tetromino1 {
0%,
40% {
transform: translate(0, 0);
}
50% {
transform: translate(48px, -27px);
}
60%,
100% {
transform: translate(96px, 0);
}
}
@keyframes tetromino2 {
0%,
20% {
transform: translate(96px, 0px);
}
40%,
100% {
transform: translate(144px, 27px);
}
}
@keyframes tetromino3 {
0% {
transform: translate(144px, 27px);
}
20%,
60% {
transform: translate(96px, 54px);
}
90%,
100% {
transform: translate(48px, 27px);
}
}
@keyframes tetromino4 {
0%,
60% {
transform: translate(48px, 27px);
}
90%,
100% {
transform: translate(0, 0);
}
}
</style>
@@ -0,0 +1,83 @@
<template>
<div class="row parentContainer" @keyup.enter="search">
<div class="col">
<div class="row">
<div class="col p-r-0">
<div class="row">
<!-- <div class="col">
<div class="form-group no-margin form-group-default b-rad-none">
<label class="text-primary">Customer Marking</label>
<input type="text" class="form-control" v-model="parameters.customerMarking"
@click="clearAll('customerMarking')" />
</div>
</div>
<div class="col">
<div class="form-group no-margin form-group-default b-rad-none">
<label class="text-primary">Email</label>
<input type="text" class="form-control" v-model="parameters.email"
@click="clearAll('email')" />
</div>
</div> -->
<div class="col">
<div class="form-group no-margin form-group-default b-rad-none">
<label class="text-primary">Order No</label>
<input type="text" class="form-control" v-model="parameters.orderNo"
@click="clearAll('orderNo')" />
</div>
</div>
</div>
</div>
<div class="col-auto p-l-0">
<div class="btn btn-primary b-rad-none" @click="search">
<i class="fa fa-search lh-40"></i>
</div>
<div class="btn btn-default b-rad-none lh-40" @click="reset">
Reset
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
section: {
default: 'addressList'
},
},
data() {
return {
isLoading: false,
parameters: {
customerMarking: null,
email: null,
orderNo: null,
}
}
},
methods: {
clearAll(input) {
var parameters = this.parameters;
$.each(this.parameters, function (key, value) {
if (key != input) {
parameters[key] = null;
}
});
this.parameters = parameters;
},
reset() {
this.parameters.customerMarking = null;
this.parameters.email = null;
this.parameters.orderNo = null;
},
search() {
if (this.parameters.orderNo) {
window.location.href = this.route('order.show', this.parameters.orderNo);
return;
}
}
},
}
</script>
@@ -0,0 +1,124 @@
<template>
<transition-component group enter-class="animate__animated animate__fadeInRight animate__delay-1 animate__faster p-r-30" leave-class="animate__animated animate__fadeOutLeft animate__faster p-r-30" style="min-height: 300px;width:100%">
<loading-component style="height: 200px; top: 0;" key="1" color="success" v-show="isLoading"></loading-component>
<div class="row" key="2" v-show="!isLoading">
<div class="col">
<div class="row">
<div class="col">
<div class="row align-items-center justify-content-center p-t-50 p-b-50" v-show="!$store.getters.getListData(section).length && !$store.getters.isLoading(section) && emptyListSection">
<div class="col-10">
<div class="row align-items-center justify-content-center hint-text">
<div class="col-4 hint-text"><img src="/images/not-found-illustration.png" class="w-100 hint-text"/></div>
</div>
<div class="row text-center">
<div class="col">
<div class="row m-t-20">
<div class="col">
<p class="all-caps no-margin fs-11" style="letter-spacing: 2px;">Nothing To Show Here</p>
</div>
</div>
<div class="row m-t-5 align-items-center justify-content-center hide">
<div class="col">
<small class="fs-9 muted all-caps font-lato" style="letter-spacing: 2px">There is no results found, Try adjusting your filters to find what you are looking for.</small>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="list disable-text-selection" data-check-all="checkAll">
<div class="row" v-for="group in Math.ceil($store.getters.getListData(section).length / columns)">
<div class="col-12" :class="'col-md-'+(12/columns)" v-for="item in $store.getters.getListData(section).slice((group - 1) * columns, group * columns)" v-bind:key="item.id" :data="item">
<slot name="list" :data="item"></slot>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col">
<pagination-component :section="section" class="mb-5" ref="pagination"></pagination-component>
</div>
</div>
</div>
</div>
</div>
</div>
</transition-component>
</template>
<script>
export default {
props: {
section:{
type: String,
required: true
},
endpoint: {
type: String,
default: route('api.order.v2.list'),
},
options: {
default () {
return {}
}
},
emptyListSection: {
type: Boolean,
default: true
},
columns: {
type: Number,
validator: (prop) => [1, 2, 3, 4, 6, 12].includes(prop),
default: 1
}
},
data(){
return {
filters: this.options,
api_count: 0,
isLoading: true,
}
},
created(){
this.setDecoratorDefault();
this.$store.dispatch('updateListQueue', {'name': this.section, 'page': 1, 'filters': this.filters});
},
computed: {
pendingList () {
return this.$store.getters.isInCompleteQueue(this.section);
}
},
watch: {
pendingList(inComplete){
if(inComplete){
this.fetchList();
}
}
},
methods: {
fetchList(){
let listDecorators = this.$store.getters.getListDetails(this.section);
this.submit(this.endpoint + '?page=' + listDecorators.page + '&filters=' + JSON.stringify(listDecorators.filters), 'get', this.section, false, false)
},
updateFilters(filters){
this.filters = filters;
this.setDecoratorDefault();
this.submit(this.endpoint + '?page=1&filters=' + JSON.stringify(this.filters), 'get', this.section, false, false)
},
successHandler(response){
this.$store.dispatch('completeList', {'name': this.section, 'data': response.payload.data});
this.$refs.pagination.makePagination(response.payload.meta, response.payload.links);
this.api_count += 1;
this.isLoading = false;
if (this.endpoint === route('api.order.v2.list') && this.api_count === 1) {
let listDecorators = this.$store.getters.getListDetails(this.section);
this.submit(this.route('api.order.list') + '?page=' + listDecorators.page + '&filters=' + JSON.stringify(listDecorators.filters), 'get', this.section, false, false)
}
},
}
}
</script>
@@ -62,15 +62,18 @@
<div class="row text-center">
<div class="col b-r b-grey text-info p-t-5 p-b-10">
<small class="fs-10 all-caps bold">Received</small>
<h6 class="bold no-margin text-info">{{item.parcels.received_packages.flatMap(packing_list => packing_list.packages).reduce((total, obj) => obj.quantity + total, 0)}}</h6>
<h6 class="bold no-margin text-info" v-if="item.parcels" >{{item.parcels.received_packages.flatMap(packing_list => packing_list.packages).reduce((total, obj) => obj.quantity + total, 0)}}</h6>
<h6 class="bold no-margin text-info" v-else > - </h6>
</div>
<div class="col b-r b-grey text-primary p-t-5 p-b-10">
<small class="fs-10 all-caps bold">In Transit</small>
<h6 class="bold no-margin text-primary">{{item.parcels.in_transit_packages.flatMap(packing_list => packing_list.packages).concat(item.parcels.destination_warehouse_packages.flatMap(packing_list => packing_list.packages)).reduce((total, obj) => obj.quantity + total, 0)}}</h6>
<h6 class="bold no-margin text-primary" v-if="item.parcels" >{{item.parcels.in_transit_packages.flatMap(packing_list => packing_list.packages).concat(item.parcels.destination_warehouse_packages.flatMap(packing_list => packing_list.packages)).reduce((total, obj) => obj.quantity + total, 0)}}</h6>
<h6 class="bold no-margin text-info" v-else > - </h6>
</div>
<div class="col text-success p-t-5 p-b-10">
<small class="fs-10 all-caps bold">Delivered</small>
<h6 class="bold no-margin text-success">{{item.parcels.delivered_packages.flatMap(packing_list => packing_list.packages).reduce((total, obj) => obj.quantity + total, 0)}}</h6>
<h6 class="bold no-margin text-success" v-if="item.parcels" >{{item.parcels.delivered_packages.flatMap(packing_list => packing_list.packages).reduce((total, obj) => obj.quantity + total, 0)}}</h6>
<h6 class="bold no-margin text-info" v-else > - </h6>
</div>
</div>
</div>
@@ -90,7 +93,8 @@
</div>
<div class="col-auto text-right">
<small class="fs-10 all-caps muted">Total CBM</small>
<h6 class="no-margin semi-bold">{{(Math.ceil((item.parcels.origin_warehouse_packages.flatMap(packing_list => packing_list.packages).reduce((total, obj) => obj.cbm + total, 0) + item.parcels.in_transit_packages.flatMap(packing_list => packing_list.packages).reduce((total, obj) => obj.cbm + total, 0) + item.parcels.destination_warehouse_packages.flatMap(packing_list => packing_list.packages).reduce((total, obj) => obj.cbm + total, 0) + item.parcels.delivered_packages.flatMap(packing_list => packing_list.packages).reduce((total, obj) => obj.cbm + total, 0)) * 10000) / 10000).toFixed(3)}}</h6>
<h6 class="no-margin semi-bold" v-if="item.parcels">{{(Math.ceil((item.parcels.origin_warehouse_packages.flatMap(packing_list => packing_list.packages).reduce((total, obj) => obj.cbm + total, 0) + item.parcels.in_transit_packages.flatMap(packing_list => packing_list.packages).reduce((total, obj) => obj.cbm + total, 0) + item.parcels.destination_warehouse_packages.flatMap(packing_list => packing_list.packages).reduce((total, obj) => obj.cbm + total, 0) + item.parcels.delivered_packages.flatMap(packing_list => packing_list.packages).reduce((total, obj) => obj.cbm + total, 0)) * 10000) / 10000).toFixed(3)}}</h6>
<h6 class="bold no-margin text-info" v-else > - </h6>
</div>
</div>
</div>

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