Compare commits

...

253 Commits

Author SHA1 Message Date
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
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 5934fbcb6c Add in missing update project function 2023-03-11 19:43:30 +08: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
Dillon 45c94321b1 Fix a problem in invoice item where the amount cannot be 0 2023-03-11 16:32:49 +08:00
Dillon 4fbe771dce Fix a problem with task name in CRM must be unique 2023-03-10 21:12:43 +08: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
Dillon 1c072d7b96 CRM create all remaining tasks according to documentation 2023-03-10 02:41:41 +08:00
edmondlang eeb7bb77bb delete duplicated invoice 2023-03-09 12:46:00 +08:00
edmondlang 2de60c8262 test delete duplicated invoice 2023-03-09 12:44:36 +08:00
edmondlang c8a2ce71e1 test delete duplicated invoice 2023-03-09 12:39:28 +08:00
edmondlang 7e04580be0 update show duplicated invoice 2023-03-09 12:34:37 +08:00
edmondlang 3d15a8e312 delete duplicate invoice logic 2023-03-09 10:21:40 +08:00
edmondlang 9936e42574 update show duplicated invoice 2023-03-09 10:15:20 +08:00
edmondlang 16ffec01d4 fix missing invoices 2023-03-09 09:28:45 +08:00
edmondlang 7959f8c83c fix missing invoices 2023-03-08 22:02:03 +08:00
edmondlang 16b5660f12 fix duplicated packing list 2023-03-08 15:33:17 +08:00
edmondlang 023954db70 fix duplicated packing list 2023-03-08 14:32:10 +08:00
edmondlang 535b8a59b9 fix invoice drop date 2023-03-08 11:48:38 +08:00
omair saleh dc4d7004a3 Merge branch 'dillon/crm-create-invoice' into 'master'
Dillon/crm create invoice

See merge request CIEFWorldwideSdnBhd/shipping-portal!148
2023-03-07 15:16:46 +00:00
Dillon 128c8083c3 CRM tie invoice to project 2023-03-06 15:12:55 +08:00
Dillon d52131d9df CRM create invoice 2023-03-05 20:28:48 +08:00
edmondlang 579dd02ebf update allow user to edit billing address 2023-03-02 22:20:08 +08:00
edmondlang 1e6ac000ac fix invoice command 2023-03-02 17:06:29 +08:00
edmondlang 0802198c97 update allow user to edit billing address 2023-03-02 16:25:51 +08:00
edmondlang 2421f6dcf0 allow user to edit billing address 2023-03-02 16:15:51 +08:00
omair saleh 127a13c59c Merge branch 'dillon/crm-create-task' into 'master'
Add new tasks post payment into CRM + Add task append to lead

See merge request CIEFWorldwideSdnBhd/shipping-portal!146
2023-03-02 00:25:56 +00:00
Dillon ba2bd59b04 Add new tasks post payment into CRM + Add task append to lead 2023-03-01 12:29:47 +08:00
edmondlang 981ec9bbeb approve invoice function for testing 2023-02-28 14:22:32 +08:00
edmondlang b293542321 disable user to generate invoice on web link 2023-02-28 14:12:24 +08:00
Omair Saleh 18593cb959 fix duplicated invoices 2023-02-28 12:58:53 +08:00
Omair Saleh e2d1426d19 fix duplicated invoices 2023-02-28 12:58:18 +08:00
Omair Saleh d31deeb112 fix duplicated invoices 2023-02-28 12:50:52 +08:00
Omair Saleh d61a0c2104 fix duplicated invoices 2023-02-28 12:03:17 +08:00
edmondlang cbda7aa6ba delete duplicated invoice 2023-02-27 19:29:24 +08:00
edmondlang b5027c81f8 delete duplicated invoice 2023-02-27 19:26:26 +08:00
edmondlang e83e53a1d7 delete duplicated invoice 2023-02-27 19:21:25 +08:00
edmondlang 4058456797 delete duplicated invoice 2023-02-27 19:18:43 +08:00
edmondlang d03e34a1f4 delete duplicated invoice 2023-02-27 19:15:36 +08:00
edmondlang 5d79d5808a delete duplicated invoice for order marking 165005587 only 2023-02-27 16:17:47 +08:00
edmondlang e4464c3eb4 Merge branch 'master' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal 2023-02-27 15:57:08 +08:00
edmondlang e227abac59 check duplicated invoice 2023-02-27 15:56:29 +08:00
omair saleh 997a9da276 Merge branch 'dillon/crm-integration' into 'master'
Dockerising shipping-portal usign the same setting from exchange-2.0.

See merge request CIEFWorldwideSdnBhd/shipping-portal!145
2023-02-27 05:14:32 +00:00
edmondlang a810fcad59 show duplicated invoice 2023-02-27 13:07:54 +08:00
edmondlang 9f4b04b9fb update show duplicated invoice 2023-02-27 12:57:46 +08:00
edmondlang 085692485a show duplicated invoice 2023-02-27 12:42:35 +08:00
edmondlang 6b5ae9b0b7 export invoice for PAID INVOICE and PENDING PAYMENT 2023-02-24 18:06:39 +08:00
edmondlang eb92a76a0b update invoice search function 2023-02-23 14:53:21 +08:00
Dillon 2b20160334 User feedback fix and enhancement on crm integration 2023-02-22 18:09:34 +08:00
Dillon 8a29f10ef3 Include company name and phone number into lead during regirstration 2023-02-22 10:36:35 +08:00
edmondlang a1bc3aa652 update PAYMENT AND BILLING invoice per_page to 5 2023-02-21 23:53:49 +08:00
edmondlang e5af2bf171 Merge branch 'auto-generate-invoice' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal 2023-02-21 23:42:58 +08:00
edmondlang 2443575744 correct typo 2023-02-21 23:42:37 +08:00
edmondlang 864bbc70b6 update invoice search function 2023-02-21 23:40:02 +08:00
edmondlang c439bb5d61 invoice search function 2023-02-21 23:31:20 +08:00
edmondlang 82b99a40cf update admin payments billing section component 2023-02-21 19:57:08 +08:00
edmondlang 272ce5fa39 auto generate invoice 2023-02-21 16:50:14 +08:00
edmondlang c16a49d55c update regenerate invoice by web route 2023-02-21 16:07:32 +08:00
edmondlang c85b603b81 Nana from the Digital marketing department has requested to remove the wechat_id in registration 2023-02-21 15:00:52 +08:00
Omair Saleh 6c6b104dff fix bug when container schedule has issue 2023-02-21 14:19:28 +08:00
Omair Saleh 430b26def0 Merge remote-tracking branch 'origin/master' 2023-02-21 14:15:07 +08:00
Omair Saleh 2d9482feb6 fix bug when container schedule has issue 2023-02-21 14:14:38 +08:00
edmondlang 615e3e7683 update export-customer-order 2023-02-21 09:58:47 +08:00
edmondlang 32936af538 update export-customer-order 2023-02-20 22:14:09 +08:00
edmondlang 7f4fdf0191 update export-customer-order 2023-02-20 20:31:52 +08:00
edmondlang 1c4d9520f9 update export-customer-order 2023-02-20 20:23:02 +08:00
edmondlang 6c7685dac2 update export-customer-order 2023-02-20 20:17:48 +08:00
edmondlang 4653e8403b export-customer-order 2023-02-20 19:50:53 +08:00
edmondlang a648a11567 Nana from the Digital marketing department has requested to remove the text 2023-02-20 18:22:21 +08:00
Dillon cb8d808562 done debugging, undo changes 2023-02-18 21:07:50 +08:00
Dillon 130aca262a debug 2023-02-18 20:29:49 +08:00
Dillon 06ab1be86e debug 2023-02-18 20:08:53 +08:00
Omair Saleh a78ed8271f auto generate invoices 2023-02-17 13:56:42 +08:00
Omair Saleh 16ce06ba7e auto generate invoices 2023-02-17 13:49:02 +08:00
Omair Saleh 5335b8affb auto generate invoices 2023-02-17 13:48:26 +08:00
Omair Saleh 6d1153298c auto generate invoices 2023-02-17 13:47:34 +08:00
Omair Saleh 8f65767996 auto generate invoices 2023-02-17 13:47:02 +08:00
Omair Saleh 4bba550b9e auto generate invoices 2023-02-17 13:46:16 +08:00
Omair Saleh b33b780563 auto generate invoices 2023-02-17 13:45:00 +08:00
Omair Saleh 342285247a auto generate invoices 2023-02-17 13:41:04 +08:00
Omair Saleh 0c82aa17fc auto generate invoices 2023-02-17 13:40:13 +08:00
Omair Saleh ed36b85a3d auto generate invoices 2023-02-17 13:20:55 +08:00
Omair Saleh 4f8e9fbd5f auto generate invoices 2023-02-17 13:10:02 +08:00
Omair Saleh ee575c21ea auto generate invoices 2023-02-17 13:06:52 +08:00
Omair Saleh f4f8c34cb9 auto generate invoices 2023-02-17 13:04:05 +08:00
Omair Saleh 7cb27a6114 auto generate invoices 2023-02-17 13:02:18 +08:00
Omair Saleh 2f4b568c9a auto generate invoices 2023-02-17 12:53:35 +08:00
Omair Saleh a23e0b35a2 auto generate invoices 2023-02-17 12:53:10 +08:00
Omair Saleh 598ca3807e auto generate invoices 2023-02-17 12:52:39 +08:00
Omair Saleh 0654f0335b auto generate invoices 2023-02-17 12:51:15 +08:00
Omair Saleh e4610e1a53 auto generate invoices 2023-02-17 12:50:37 +08:00
Omair Saleh 38ae8f72eb auto generate invoices 2023-02-17 12:49:55 +08:00
Omair Saleh cbdd4e8137 auto generate invoices 2023-02-17 12:49:27 +08:00
Omair Saleh c4d2b4e476 auto generate invoices 2023-02-17 12:48:48 +08:00
Omair Saleh 7eab58b45e auto generate invoices 2023-02-17 12:47:58 +08:00
Omair Saleh a9b21e9566 auto generate invoices 2023-02-17 12:47:19 +08:00
Omair Saleh 9aec5a71f1 auto generate invoices 2023-02-17 12:46:37 +08:00
Omair Saleh 771b10ffc9 auto generate invoices 2023-02-17 12:35:12 +08:00
Omair Saleh a9d4806a4a auto generate invoices 2023-02-17 12:34:06 +08:00
Omair Saleh 0d0048eb6c debug yd api 2023-02-17 11:11:51 +08:00
Omair Saleh d5f3e9ba71 debug yd api 2023-02-17 11:04:32 +08:00
Omair Saleh 5144e940f2 debug yd api 2023-02-17 10:58:35 +08:00
Omair Saleh 8dac196cb9 debug yd api 2023-02-17 10:58:02 +08:00
Omair Saleh e1bc996efb debug yd api 2023-02-17 10:56:53 +08:00
Omair Saleh ed7019f75e debug yd api 2023-02-17 10:56:25 +08:00
Omair Saleh 0f0a32488a debug yd api 2023-02-17 10:55:46 +08:00
Omair Saleh b3cc805e78 debug yd api 2023-02-17 10:55:00 +08:00
Omair Saleh fd8a09d443 debug yd api 2023-02-17 10:54:22 +08:00
Omair Saleh 8d5603c756 debug yd api 2023-02-17 10:53:58 +08:00
Omair Saleh c3de10f676 debug yd api 2023-02-17 10:53:06 +08:00
Omair Saleh 80a47f05f7 debug yd api 2023-02-17 10:52:18 +08:00
Omair Saleh 53cc2ee493 debug yd api 2023-02-17 10:49:30 +08:00
Omair Saleh fadef468bb debug yd api 2023-02-17 10:46:37 +08:00
Omair Saleh 3f0028aaf1 debug yd api 2023-02-17 10:43:47 +08:00
Omair Saleh 7ea7db9f49 debug yd api 2023-02-17 10:41:41 +08:00
Omair Saleh 7a95741af9 debug yd api 2023-02-17 10:39:36 +08:00
Omair Saleh 75c7772d98 debug yd api 2023-02-17 10:38:03 +08:00
Omair Saleh 851489bd12 debug yd api 2023-02-17 10:36:38 +08:00
Omair Saleh 666b5a7791 debug yd api 2023-02-17 10:35:07 +08:00
Omair Saleh a1461f899b debug yd api 2023-02-17 10:34:32 +08:00
Omair Saleh 2fda9e0c46 debug yd api 2023-02-17 10:33:58 +08:00
Omair Saleh ec2b46b192 debug yd api 2023-02-17 10:33:38 +08:00
Omair Saleh 833c4c5905 debug yd api 2023-02-17 10:33:05 +08:00
Omair Saleh 1aea633375 debug yd api 2023-02-17 10:32:41 +08:00
Omair Saleh cc90c16d9a debug yd api 2023-02-17 10:32:09 +08:00
Omair Saleh 10af83056a debug yd api 2023-02-17 10:31:39 +08:00
Omair Saleh cd930dbaf0 debug yd api 2023-02-17 10:30:46 +08:00
Omair Saleh 2bf3e38ced debug yd api 2023-02-17 10:07:17 +08:00
Omair Saleh 5f4010bb50 debug yd api 2023-02-17 10:03:54 +08:00
Dillon 53d076c7e5 CRM integration MVP Phase 1 - minor cleanup 2023-02-17 09:24:13 +08:00
Dillon 1b84ccf60e CRM integration MVP Phase 1 2023-02-17 09:06:18 +08:00
Omair Saleh 5955c1a633 debug yd api 2023-02-17 08:26:13 +08:00
Omair Saleh 7ece4f6470 debug yd api 2023-02-17 06:49:26 +08:00
Omair Saleh e0e82634d3 debug yd api 2023-02-17 06:47:16 +08:00
Omair Saleh 988e798cf1 debug yd api 2023-02-17 06:46:36 +08:00
Omair Saleh 4ce8440724 debug yd api 2023-02-17 06:45:35 +08:00
Omair Saleh e2f5097882 debug yd api 2023-02-17 06:44:56 +08:00
Omair Saleh 9f96caad7c debug yd api 2023-02-17 06:44:33 +08:00
Omair Saleh 3046530f71 debug yd api 2023-02-17 06:43:25 +08:00
Omair Saleh 84a6cb85dd debug yd api 2023-02-17 06:42:33 +08:00
Omair Saleh c86ea9cee4 debug yd api 2023-02-17 06:38:21 +08:00
Omair Saleh ac15f76c4f debug yd api 2023-02-17 06:36:26 +08:00
Omair Saleh 1fc176296e debug yd api 2023-02-17 06:35:29 +08:00
Omair Saleh 3f911f145a debug yd api 2023-02-17 05:45:19 +08:00
Omair Saleh d5c28df748 debug yd api 2023-02-17 05:19:04 +08:00
Omair Saleh 9bfe943898 debug yd api 2023-02-17 05:02:39 +08:00
Omair Saleh dbcbabec93 Merge remote-tracking branch 'origin/master' 2023-02-17 03:39:22 +08:00
Omair Saleh e24cdd82d4 debug yd api 2023-02-17 03:35:43 +08:00
edmondlang 01854a3292 update change company name 2023-02-16 23:09:47 +08:00
Omair Saleh 679bae6fe8 debug yd api 2023-02-16 16:41:17 +08:00
Omair Saleh f567995202 debug yd api 2023-02-16 16:40:17 +08:00
Omair Saleh 35b3cb4515 debug yd api 2023-02-16 16:39:17 +08:00
Omair Saleh 196cf3d58a debug yd api 2023-02-16 16:32:20 +08:00
Omair Saleh b12a862903 debug yd api 2023-02-16 16:27:53 +08:00
Omair Saleh f586314cd8 debug yd api 2023-02-16 16:24:42 +08:00
Omair Saleh 16f41482ad debug yd api 2023-02-16 16:19:47 +08:00
Omair Saleh 95866b0789 debug yd api 2023-02-14 14:50:45 +08:00
Omair Saleh fb2ba2a3c7 debug yd api 2023-02-14 14:50:03 +08:00
Omair Saleh 3041144968 debug yd api 2023-02-14 14:47:59 +08:00
Omair Saleh 2efdb33b71 debug yd api 2023-02-14 14:47:21 +08:00
Omair Saleh 5716050694 debug yd api 2023-02-14 14:46:51 +08:00
Omair Saleh e22c7c7e8b debug yd api 2023-02-14 14:46:31 +08:00
Omair Saleh d9972a8a95 debug yd api 2023-02-14 14:45:49 +08:00
Omair Saleh 6dbafde89c debug yd api 2023-02-14 14:45:06 +08:00
Omair Saleh 680ddd5066 debug yd api 2023-02-14 14:44:19 +08:00
Omair Saleh f6b5eb3098 debug yd api 2023-02-14 14:43:15 +08:00
Omair Saleh 82f8cae4a8 debug yd api 2023-02-14 14:41:22 +08:00
Omair Saleh 4c868de356 debug yd api 2023-02-14 14:40:30 +08:00
Omair Saleh c44278fe26 debug yd api 2023-02-14 14:38:59 +08:00
Omair Saleh 43c8530e6d debug yd api 2023-02-14 14:37:32 +08:00
edmondlang 198e0674bd Merge branch 'update-laravelmpdf' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal 2023-02-10 23:10:34 +08:00
edmondlang 7d09205817 update laravel mpdf 2023-02-10 20:55:32 +08:00
edmondlang 5f5dbeb3d1 update ExportsWarehousePackingList to only johor state 2023-02-08 18:59:09 +08:00
edmondlang 67a877ca15 update laravel mpdf 2023-02-07 23:54:33 +08:00
edmondlang 88e7bf44b5 update code on the prefix 'NX' 2023-02-07 23:40:24 +08:00
edmondlang 86461c19a1 add export function - export/packing-list-warehouse/guangzhou2-to-johor
add warehouse prefix 'NX/'
2023-02-07 23:32:18 +08:00
edmondlang 18d1841a30 Merge branch 'change-company-ui' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal 2023-02-06 23:10:00 +08:00
edmondlang 990508501d revert testing code 2023-02-06 23:07:41 +08:00
edmondlang dfec2073b0 update change company and debtor code 2023-02-06 23:02:02 +08:00
edmondlang 2300d237d3 Merge branch 'change-company-ui' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal 2023-02-06 22:43:24 +08:00
edmondlang a62e5d95fb add debtor in company resource folder 2023-02-06 22:33:57 +08:00
edmondlang 2d8535b7f5 change company name and debtor code 2023-02-06 22:24:00 +08:00
edmondlang 3f21802090 update customer payment billing section component 2023-02-03 16:10:57 +08:00
edmondlang e8191df0e9 update company invoice endpoint and customer payment-and-billing page design 2023-01-28 02:19:51 +08:00
edmondlang 02064ad68e reverse commit on app.php - Meneses\LaravelMpdf\LaravelMpdfServiceProvider::class 2023-01-28 01:15:46 +08:00
Wafie 13319aacff wip-invoice-tab 2023-01-26 21:36:52 +08:00
edmondlang 996ef4205f update multi invoice combined summary 2023-01-20 17:50:19 +08:00
sharifcse57 d91e0e56c3 Create option: Update customer name by pop up modal 2023-01-12 22:37:59 +06:00
Cleison Freitas df283e54a2 Company rename endpoint. 2023-01-10 23:03:35 -03:00
Dillon 515c71daa7 Merge branch 'dillon/setup-docker-2' into dillon/crm-integration 2022-12-06 08:34:29 +08:00
Dillon a041a70d93 Merge branch 'dillon/setup-docker' into dillon/setup-docker-2 2022-11-16 11:07:30 +08:00
Dillon d4c9899120 Dockerising shipping-portal usign the same setting from exchange-2.0.
Update gitignore to include docker-compose.yml (same as exchange-2.0)
2022-11-02 05:56:06 +08:00
147 changed files with 7343 additions and 1254 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"
-1
View File
@@ -21,7 +21,6 @@ gox.iml
rebuild_docker.sh
docker/*
db/*
docker-compose.yml
package-lock.json
public/*
/public/*
@@ -15,7 +15,7 @@ class DoesNotHaveTransactionType implements Filter
public static function apply(Builder $builder, $value)
{
return $builder->whereDoesntHave('transactions', function (Builder $query) use($value) {
$query->where('type', $value);
$query->where('type', $value)->whereIn('status', [0,1,2,3]);
})->whereHas('containers', function ($query){
return $query->whereDate('loading_date', '>=', Carbon::parse('20-09-2022'));
});
@@ -0,0 +1,21 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use App\Models\Order;
use Illuminate\Database\Eloquent\Builder;
class OrderMarkingIn implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->whereHas('owner', function($query) use ($value) {
$query->where('reference', 'LIKE', '%' . $value . '%');
});
}
}
@@ -0,0 +1,41 @@
<?php
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;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CreateLeadPerfexCRMObject;
class CreatePerfexCRMCustomer implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/** @var CreateLeadPerfexCRMObject */
private $createLeadPerfexCRMObject;
/**
* CreatePerfexCRMCustomer constructor.
* @param CreateLeadPerfexCRMObject $createLeadPerfexCRMObject
*/
public function __construct(CreateLeadPerfexCRMObject $createLeadPerfexCRMObject)
{
$this->createLeadPerfexCRMObject = $createLeadPerfexCRMObject;
}
public function handle()
{
$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);
}
}
}
@@ -0,0 +1,33 @@
<?php
namespace App\Classes\Jobs;
use App\Classes\Modules\PerfexCRM\Processors\CreatePerfexCRMInvoiceProcessor;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use App\Models\Transaction;
class CreatePerfexCRMInvoice implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/** @var Transaction $transaction*/
private $transaction;
/**
* CreatePerfexCRMInvoice constructor.
* @param Transaction $transaction
*/
public function __construct(Transaction $transaction)
{
$this->transaction = $transaction;
}
public function handle()
{
(App()->make(CreatePerfexCRMInvoiceProcessor::class))->execute($this->transaction);
}
}
@@ -0,0 +1,42 @@
<?php
namespace App\Classes\Jobs;
use App\Classes\Modules\PerfexCRM\Processors\CreatePerfexCRMTaskProcessor;
use App\Classes\Modules\PerfexCRM\Services\FetchesPerfexCRMLead;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CreateTaskPerfexCRMObject;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class CreatePerfexCRMSingleTask implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/** @var FetchesPerfexCRMLead */
private $fetchesPerfexCRMLead;
/** @var CreateTaskPerfexCRMObject */
private $createTaskPerfexCRMObject;
/**
* CreatePerfexCRMSingleTask constructor.
* @param CreateTaskPerfexCRMObject $createTaskPerfexCRMObject
*/
public function __construct(CreateTaskPerfexCRMObject $createTaskPerfexCRMObject)
{
$this->createTaskPerfexCRMObject = $createTaskPerfexCRMObject;
}
public function handle()
{
$lead = (App()->make(FetchesPerfexCRMLead::class))->execute($this->createTaskPerfexCRMObject->getEmail());
if(!is_null($lead))
{
$this->createTaskPerfexCRMObject->setLeadId($lead->id);
(App()->make(CreatePerfexCRMTaskProcessor::class))->execute($this->createTaskPerfexCRMObject);
}
}
}
@@ -2,8 +2,12 @@
namespace App\Classes\Jobs;
use App\Classes\Modules\PackingLists\Processors\FetchContainersFromYdPortalProcessor;
use App\Classes\Modules\PackingLists\Processors\FetchContainersUpdatesFromYdPortalProcessor;
use App\Classes\Modules\PackingLists\Processors\FetchDeliveryUpdatesFromYdPortalProcessor;
use App\Classes\Modules\PackingLists\Processors\FetchOrderListsFromYdPortalProcessor;
use App\Classes\Modules\PackingLists\Processors\FetchPackingListsFromYdPortalProcessor;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
@@ -25,8 +29,12 @@ class FetchOrdersFromYDPortalJob implements ShouldQueue
*/
public function handle()
{
(App()->make(FetchPackingListsFromYdPortalProcessor::class))->execute();
(App()->make(FetchContainersFromYdPortalProcessor::class))->execute();
(App()->make(FetchContainersUpdatesFromYdPortalProcessor::class))->execute();
(App()->make(FetchDeliveryUpdatesFromYdPortalProcessor::class))->execute();
(App()->make(FetchOrderListsFromYdPortalProcessor::class))->execute();
// (App()->make(FetchOrderListsFromYdPortalProcessor::class))->execute();
}
}
+33
View File
@@ -0,0 +1,33 @@
<?php
namespace App\Classes\Jobs;
use App\Classes\Modules\PerfexCRM\Processors\UpdatePerfexCRMProcessor;
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\UpdatePerfexCRMObject;
class UpdatePerfexCRM implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/** @var UpdatePerfexCRMObject */
private $updatePerfexCRMObject;
/**
* UpdatePerfexCRM constructor.
* @param UpdatePerfexCRMObject $updatePerfexCRMObject
*/
public function __construct(UpdatePerfexCRMObject $updatePerfexCRMObject)
{
$this->updatePerfexCRMObject = $updatePerfexCRMObject;
}
public function handle()
{
(App()->make(UpdatePerfexCRMProcessor::class))->execute($this->updatePerfexCRMObject);
}
}
+108
View File
@@ -0,0 +1,108 @@
<?php
namespace App\Classes\Jobs;
use App\Classes\Modules\PerfexCRM\Processors\CreatePerfexCRMInvoiceProcessor;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMInvoicePayment;
use App\Classes\Modules\PerfexCRM\Services\FetchesPerfexCRMCustomer;
use App\Classes\Modules\PerfexCRM\Services\FetchesPerfexCRMInvoice;
use App\Classes\Modules\PerfexCRM\Services\FetchesPerfexCRMProject;
use App\Classes\Modules\PerfexCRM\Services\UpdatesPerfexCRMInvoice;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\UpdatePerfexCRMInvoiceObject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\InvoicePaymentPerfexCRMObject;
use App\Classes\ValueObjects\Constants\PerfexCRMInvoiceStatus;
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 Carbon\Carbon;
use Illuminate\Support\Facades\Log;
class UpdatePerfexCRMInvoice implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/** @var UpdatePerfexCRMInvoiceObject */
private $updatePerfexCRMInvoiceObject;
/**
* CreatePerfexCRMSingleTask constructor.
* @param UpdatePerfexCRMInvoiceObject $createTaskPerfexCRMObject
*/
public function __construct(UpdatePerfexCRMInvoiceObject $updatePerfexCRMInvoiceObject)
{
$this->updatePerfexCRMInvoiceObject = $updatePerfexCRMInvoiceObject;
}
public function handle()
{
//get the client id
$customer = (App()->make(FetchesPerfexCRMCustomer::class))->execute($this->updatePerfexCRMInvoiceObject->getEmail());
$transaction = $this->updatePerfexCRMInvoiceObject->getTransaction();
//get the invoice id
$invoiceId = 0;
$invoiceStatus = 0;
$invoice = (App()->make(FetchesPerfexCRMInvoice::class))->execute($customer->userid,"INV-", $transaction->owner->bill_no);
if(is_null($invoice)){
$result = (App()->make(CreatePerfexCRMInvoiceProcessor::class))->execute($transaction->owner, $this->updatePerfexCRMInvoiceObject->getIsPaid());
$invoiceId = $result->payload['id'];
}
else{
$invoiceId = $invoice->id;
$invoiceStatus = $invoice->status;
//This only run when invoice already exist and the invoice does not have a PAID status
if($invoiceStatus != PerfexCRMInvoiceStatus::PAID){
//get project
$projectId = "";
$projectName = "";
if($transaction->owner instanceof Transaction){
$orderReference = $transaction->owner->owner->owner()->first()->reference;
$packingListReference = $transaction->owner->owner->reference;
$projectName = 'IZYIM | X1 Shipping | '.$orderReference.' | '.$packingListReference;
$result = (App()->make(FetchesPerfexCRMProject::class))->execute($projectName, $customer->userid);
if(isset($result->payload)){
$project = $result->payload[0];
$projectId = $project['id'];
}
}
if($projectId == ""){
Log::error(json_encode('UpdatePerfexCRMInvoice debug: '.$projectName));
Log::error(json_encode($transaction->owner));
}
//update invoice
(App()->make(UpdatesPerfexCRMInvoice::class))->execute($invoice, $projectId);
}
}
//create invoice payment
if($invoiceId != 0 && $invoiceStatus != PerfexCRMInvoiceStatus::PAID){
$date = Carbon::parse($transaction->created_at)->format('Y-m-d');
$invoicePaymentPerfexCRMObject = new InvoicePaymentPerfexCRMObject(
$invoiceId,
"$transaction->amount",
$date,
1,
"",
""
);
(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,88 @@
<?php
namespace App\Classes\Jobs;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\UpdatePerfexCRMObject;
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 */
private $nextJob;
/**
* UpdatePerfexCRMPrelude constructor.
* @param $packingList
* @param $transaction
* @param UpdatePerfexCRMObject $updatePerfexCRMObject
* @param $nextJob
*/
public function __construct($packingList, $transaction, UpdatePerfexCRMObject $updatePerfexCRMObject, $nextJob)
{
$this->packingList = $packingList;
$this->transaction = $transaction;
$this->updatePerfexCRMObject = $updatePerfexCRMObject;
$this->nextJob = $nextJob;
}
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);
$this->nextJob::dispatch($this->updatePerfexCRMObject);
}
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;
}
}
@@ -8,23 +8,27 @@ use App\Classes\General\Services\GeneratesInitials;
use App\Classes\Modules\Accounts\Processors\AuthenticationProcessor;
use App\Classes\Modules\Accounts\Processors\CreateUserProcessor;
use App\Classes\Modules\Accounts\Processors\GenerateEmailVerificationAttemptProcessor;
use App\Classes\Modules\Companies\DataTransferObjects\CompanyConnectionObject;
use App\Classes\Modules\Companies\Processors\AssignEmployeeProcessor;
use App\Classes\Modules\Companies\Processors\CreateCompanyProcessor;
use App\Classes\Modules\Companies\Processors\CreateCompanyModuleProcessor;
use App\Classes\Modules\Companies\DataTransferObjects\EmploymentObject;
use App\Classes\Modules\Companies\Services\ApprovesCompanyConnection;
use App\Classes\Modules\Companies\Services\CreatesCompanyConnection;
use App\Classes\Modules\Companies\Services\FetchesCompanyModule;
use App\Classes\Modules\Contacts\DataTransferObjects\ContactObject;
use App\Classes\Modules\Contacts\Processors\CreateContactProcessor;
use App\Classes\Modules\PerfexCRM\Processors\CreatePerfexCRMLeadProcessor;
use App\Classes\Modules\Documents\Processors\UploadIdentityDocumentProcessor;
use App\Classes\Modules\Companies\DataTransferObjects\CompanyConnectionObject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CreateLeadPerfexCRMObject;
use App\Classes\Modules\Companies\DataTransferObjects\EmploymentObject;
use App\Classes\Modules\Contacts\DataTransferObjects\ContactObject;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\BusinessType;
use App\Classes\ValueObjects\Constants\CompanyType;
use App\Classes\ValueObjects\Constants\RoleTypes;
use App\Classes\Jobs\CreatePerfexCRMCustomer;
use App\Models\Company;
use App\Models\CompanyModule;
use App\Models\User;
@@ -80,6 +84,9 @@ class CreateCustomerLogic extends AbstractControllerLogic
/** @var FetchesCompanyModule */
private $fetchesCompanyModule;
/** @var CreatePerfexCRMLeadProcessor */
private $createPerfexCRMLeadProcessor;
/**
* CreateCustomerLogic constructor.
* @param CreateUserProcessor $createUserProcessor
@@ -93,8 +100,9 @@ class CreateCustomerLogic extends AbstractControllerLogic
* @param AuthenticationProcessor $authenticationProcessor
* @param GenerateEmailVerificationAttemptProcessor $generateEmailVerificationAttemptProcessor
* @param FetchesCompanyModule $fetchesCompanyModule
* @param CreatePerfexCRMLeadProcessor $createPerfexCRMLeadProcessor
*/
public function __construct(CreateUserProcessor $createUserProcessor, CreateCompanyProcessor $createCompanyProcessor, CreateCompanyModuleProcessor $createCompanyModuleProcessor, CreateContactProcessor $createContactProcessor, CreatesCompanyConnection $createsCompanyConnection, ApprovesCompanyConnection $approvesCompanyConnection, AssignEmployeeProcessor $assignEmployeeProcessor, UploadIdentityDocumentProcessor $uploadIdentityDocumentProcessor, AuthenticationProcessor $authenticationProcessor, GenerateEmailVerificationAttemptProcessor $generateEmailVerificationAttemptProcessor, FetchesCompanyModule $fetchesCompanyModule)
public function __construct(CreateUserProcessor $createUserProcessor, CreateCompanyProcessor $createCompanyProcessor, CreateCompanyModuleProcessor $createCompanyModuleProcessor, CreateContactProcessor $createContactProcessor, CreatesCompanyConnection $createsCompanyConnection, ApprovesCompanyConnection $approvesCompanyConnection, AssignEmployeeProcessor $assignEmployeeProcessor, UploadIdentityDocumentProcessor $uploadIdentityDocumentProcessor, AuthenticationProcessor $authenticationProcessor, GenerateEmailVerificationAttemptProcessor $generateEmailVerificationAttemptProcessor, FetchesCompanyModule $fetchesCompanyModule, CreatePerfexCRMLeadProcessor $createPerfexCRMLeadProcessor)
{
$this->createUserProcessor = $createUserProcessor;
$this->createCompanyProcessor = $createCompanyProcessor;
@@ -107,6 +115,7 @@ class CreateCustomerLogic extends AbstractControllerLogic
$this->authenticationProcessor = $authenticationProcessor;
$this->generateEmailVerificationAttemptProcessor = $generateEmailVerificationAttemptProcessor;
$this->fetchesCompanyModule = $fetchesCompanyModule;
$this->createPerfexCRMLeadProcessor = $createPerfexCRMLeadProcessor;
}
/**
@@ -146,6 +155,18 @@ class CreateCustomerLogic extends AbstractControllerLogic
$this->uploadIdentityDocumentProcessor->execute($request, $company);
if(config('perfexcrm.is_enabled') == 'true'){
// $this->createPerfexCRMLeadProcessor->execute($request);
$createLeadPerfexCRMObject = new CreateLeadPerfexCRMObject(
$request->input('name'),
$request->input('email'),
$request->input('phone'),
$request->input('type') === CompanyType::COMPANY_BUSINESS ? $request->input('company_name') : $request->input('name'),
$connection->invitee_reference
);
CreatePerfexCRMCustomer::dispatch($createLeadPerfexCRMObject);
}
// $this->generateEmailVerificationAttemptProcessor->execute($user);
return $this->response($this->authenticationProcessor->execute($request));
@@ -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);
}
}
@@ -0,0 +1,86 @@
<?php
namespace App\Classes\Modules\Addresses\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Addresses\Services\CreatesAddress;
use App\Classes\Modules\Addresses\Standards\Rules\CanCreateAddress;
use App\Classes\Modules\Addresses\DataTransferObjects\AddressObject;
use App\Classes\Modules\Addresses\Services\FetchesAddress;
use App\Classes\Modules\Companies\Services\FetchesCompanyModule;
use App\Classes\ValueObjects\Constants\AddressType;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Http\Resources\AddressResource;
use App\Models\Address;
use App\Models\CompanyModule;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class CreateBillingAddressLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Created Billing Address',
'message' => 'You have successfully created a new Billing Address'
];
}
/** @var CanCreateAddress */
private $canCreateAddress;
/** @var FetchesCompanyModule */
private $fetchesCompanyModule;
/** @var CreatesAddress */
private $createsAddress;
/** @var FetchesAddress */
private $fetchesAddress;
/**
* CreateAddressLogic constructor.
* @param CanCreateAddress $canCreateAddress
* @param FetchesCompanyModule $fetchesCompanyModule
* @param CreatesAddress $createsAddress
* @param FetchesAddress $fetchesAddress
*/
public function __construct(CanCreateAddress $canCreateAddress, FetchesCompanyModule $fetchesCompanyModule, CreatesAddress $createsAddress, FetchesAddress $fetchesAddress)
{
$this->canCreateAddress = $canCreateAddress;
$this->fetchesCompanyModule = $fetchesCompanyModule;
$this->createsAddress = $createsAddress;
$this->fetchesAddress = $fetchesAddress;
}
/**
* @param Request $request
* @return JsonResponse
* @throws \App\Classes\Exceptions\AccessForbiddenException
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
public function logic(Request $request) : JsonResponse
{
$companyModule = $this->fetchesCompanyModule->execute(['id' => $request->input('company_module_id')]);
$address = $this->fetchesAddress->execute(['id' => $request->input('billing_address_id')]);
if ($address->type !== AddressType::BILLING || $address->id !== $companyModule->addresses->where('type', AddressType::BILLING)->first()->id) {
// delete all current billing address
Address::where('owner_type', CompanyModule::class)->where('owner_id', $request->input('company_module_id'))->where('type', AddressType::BILLING)->delete();
// create addrress
$billingAddress = new AddressObject($address->street_one, $address->street_two, $address->country_id, $address->state_id, $address->district_id, $address->postcode, AddressType::BILLING, ApprovalStatus::APPROVED, $address->reference);
$this->canCreateAddress->passes($billingAddress);
$this->createsAddress->execute($companyModule, $billingAddress);
}
return $this->resourceResponse(new AddressResource($address));
}
}
@@ -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;
@@ -1,66 +0,0 @@
<?php
namespace App\Classes\Modules\Companies\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Transactions\Services\ListsTransactions;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Http\Resources\TransactionResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class ListCompanyModuleInvoicesLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification(): array
{
return [
'title' => 'Retrieved Company Module Invoices',
'message' => 'You have successfully retrieved a list of Invoices'
];
}
/** @var ListsTransactions */
private $listsTransactions;
/**
* ListCompanyModuleInvoicesLogic constructor.
* @param ListsTransactions $listsTransactions
*/
public function __construct(ListsTransactions $listsTransactions)
{
$this->listsTransactions = $listsTransactions;
}
/**
* @param Request $request
* @return JsonResponse
* @throws \App\Classes\Exceptions\AccessForbiddenException
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
public function logic(Request $request): JsonResponse
{
$filterArray = [
"per_page" => 10,
"order_by" => (object)[
"column" => 'id',
"DESC" => true,
],
"status_in" => [2],
"receiver" => intval($request->route('company_module_id')),
"type" => TransactionType::SHIPPING_INVOICE
];
// $this->canListTransactions->passes();
$query = $this->listsTransactions->execute($filterArray);
return $this->collectionResponse(TransactionResource::collection($query));
}
}
@@ -0,0 +1,88 @@
<?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\UpdatesCompanyModuleName;
use App\Classes\Modules\Companies\Services\FetchesCompany;
use App\Classes\Modules\Companies\Standards\Rules\CanUpdateCompany;
use App\Classes\Modules\Companies\DataTransferObjects\CompanyObject;
use App\Classes\Modules\Companies\Services\UpdatesCompanyDebtor;
use App\Http\Resources\CompanyResource;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class UpdateCompanyNameAndDebtorLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Updated Company Name and Debtor',
'message' => 'You have successfully updated the Company'
];
}
/** @var CanUpdateCompany */
private $canUpdateCompany;
/** @var UpdatesCompany */
private $updatesCompany;
/** @var FetchesCompany */
private $fetchesCompany;
/** @var UpdatesCompanyDebtor */
private $updatesCompanyDebtor;
/** @var UpdatesCompanyModuleName */
private $updatesCompanyModuleName;
/**
* UpdateCompanyControllersLogic constructor.
* @param CanUpdateCompany $canUpdateCompany
* @param UpdatesCompany $updatesCompany
* @param FetchesCompany $fetchesCompany
* @param UpdatesCompanyDebtor $updatesCompanyDebtor
* @param UpdatesCompanyModuleName $updatesCompanyModuleName
*/
public function __construct(CanUpdateCompany $canUpdateCompany, UpdatesCompany $updatesCompany, FetchesCompany $fetchesCompany, UpdatesCompanyDebtor $updatesCompanyDebtor, UpdatesCompanyModuleName $updatesCompanyModuleName)
{
$this->canUpdateCompany = $canUpdateCompany;
$this->updatesCompany = $updatesCompany;
$this->fetchesCompany = $fetchesCompany;
$this->updatesCompanyDebtor = $updatesCompanyDebtor;
$this->updatesCompanyModuleName = $updatesCompanyModuleName;
}
/**
* @param Request $request
* @return JsonResponse
* @throws ErrorException
*/
public function logic(Request $request) : JsonResponse
{
$object = new CompanyObject($request->input('name'), $request->input('reference'), $request->input('type'));
$this->canUpdateCompany->passes($object);
$query = $this->fetchesCompany->execute(['id' => $request->route('id')]);
$this->updatesCompanyModuleName->execute($query->companyModules()->first(), $object->getName());
$query = $this->updatesCompany->execute($query, $object);
if ($request->input('debtor') || $query->first()->debtor !== null) {
$this->updatesCompanyDebtor->execute($query, $request->input('debtor'));
}
return $this->resourceResponse(new CompanyResource($query));
}
}
@@ -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,24 @@
<?php
namespace App\Classes\Modules\Companies\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Classes\Modules\Companies\DataTransferObjects\CompanyObject;
use App\Models\Company;
class UpdatesCompanyDebtor extends AbstractUpdateRecord
{
/**
* @param Company $model
* @param CompanyObject $object
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(Company $model, ?string $debtor)
{
$model->debtor = $debtor;
return $this->handler($model);
}
}
@@ -0,0 +1,108 @@
<?php
namespace App\Classes\Modules\Exports\Services;
use App\Models\CompanyConnection;
use App\Models\Container;
use App\Models\Order;
use App\Models\Package;
use Maatwebsite\Excel\Concerns\Exportable;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithMapping;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
use Carbon\Carbon;
class ExportsOrderSummaryByMarking implements FromCollection, WithHeadings, WithHeadingRow, WithMapping, ShouldAutoSize
{
use Exportable;
protected $customerMarking;
protected $dateFrom;
protected $dateTo;
public function headings(): array
{
return [
'Date',
'Container',
'Order Marking',
'Packing List Reference',
'Description',
'Quantity',
'L (cm)',
'H (cm)',
'W (cm)',
'CBM'
];
}
public function setParameters($customerMarking, $dateFrom, $dateTo)
{
$this->customerMarking = $customerMarking;
$this->dateFrom = $dateFrom;
$this->dateTo = $dateTo;
}
/**
* @return \Illuminate\Support\Collection|mixed
*/
public function collection()
{
$connection = CompanyConnection::where('invitee_reference', $this->customerMarking)->first();
$company_id = $connection->invitee->company->id;
$company_module_id = $connection->invitee->id;
$packagesArray = collect();
$orders = Order::where('company_module_id', $company_module_id);
if (isset($this->dateFrom) && isset($this->dateTo)) {
$from = Carbon::createFromFormat('d-m-Y', $this->dateFrom);
$to = Carbon::createFromFormat('d-m-Y', $this->dateTo);
$orders = $orders->whereBetween('created_at', [$from, $to]);
}
$orders = $orders->get();
foreach ($orders as $order){
$packingLists = $order->packingLists;
foreach ($packingLists as $packingList){
if($packingList->packingLists->first()){
$packingList = $packingList->packingLists->first();
}
$packages = $packingList->packages;
foreach ($packages as $package){
$packagesArray->push($package);
}
}
}
return $packagesArray;
}
/**
* @param Package $package
*
* @return array
*/
public function map($package): array
{
$packinglist = ($package->packingList()->first()->owner->owner_type == Order::class) ? $package->packingList()->first(): $package->packingList->owner;
$order = $packinglist->owner;
return [
Carbon::parse($package->created_at)->format('d-m-Y'),
'',
$order->reference,
$package->packingList->reference,
$package->description,
$package->quantity,
$package->length,
$package->height,
$package->width,
((($package->length / 100) * ($package->height / 100) * ($package->width / 100)) * $package->quantity)
];
}
}
@@ -60,7 +60,15 @@ class ExportsPaymentTransactions implements FromQuery, WithHeadings, WithHeading
$query = Transaction::query();
$query->where('type', TransactionType::SHIPPING_INVOICE)->whereIn('status', [ApprovalStatus::COMPLETED]);
// paidInvoiceSection
$approvalStatus = ApprovalStatus::COMPLETED;
if ($this->request->route('section') == 'pendingPaymentSection') {
// pendingPaymentSection
$approvalStatus = ApprovalStatus::APPROVED;
}
$query->where('type', TransactionType::SHIPPING_INVOICE)->whereIn('status', [$approvalStatus]);
if($start_date && $end_date) {
$query->whereBetween('updated_at', [
@@ -0,0 +1,58 @@
<?php
namespace App\Classes\Modules\Exports\Services;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\PackingListType;
use App\Models\Order;
use App\Models\State;
use Maatwebsite\Excel\Concerns\Exportable;
use Maatwebsite\Excel\Concerns\FromQuery;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithMapping;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
use Carbon\Carbon;
class ExportsWarehousePackingList implements FromQuery, WithHeadings, WithHeadingRow, WithMapping, ShouldAutoSize
{
use Exportable;
public function headings(): array
{
return [
'Customer Marking',
'Order Number'
];
}
/**
* @return \Illuminate\Support\Collection|mixed
*/
public function query()
{
$johor_state_id = State::where('name', 'johor')->first()->id;
return Order::whereHas('addresses', function($address) use ($johor_state_id){
$address->where('status', ApprovalStatus::APPROVED)->where('state_id', $johor_state_id);
})->whereHas('packingLists', function($packingLists) {
$packingLists->where('type', PackingListType::SHIPPING_PACKING_LIST)->whereDoesntHave('transports');
});
}
/**
* @param Order $order
*
* @return array
*/
public function map($order): array
{
$marking = $order->companyModule->inviters()->withPivot('invitee_reference')->first()->pivot->invitee_reference;
return [
$marking,
$order->reference,
];
}
}
@@ -7,6 +7,7 @@ use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Addresses\Services\FetchesAddress;
use App\Classes\Modules\Companies\Services\FetchesCompany;
use App\Classes\Modules\Companies\Services\FetchesCompanyModule;
use App\Classes\Modules\PerfexCRM\Processors\NewLeadTaskToPerfexCRMProcessor;
use App\Classes\Modules\Orders\Processors\CreateOrderProcessor;
use App\Classes\Modules\Orders\Services\GeneratesOrderNumber;
use App\Classes\ValueObjects\Constants\WarehouseReferences;
@@ -39,6 +40,8 @@ class CreateOrderLogic extends AbstractControllerLogic
/** @var GeneratesOrderNumber */
private $generatesOrderNumber;
/** @var NewLeadTaskToPerfexCRMProcessor */
private $newLeadTaskToPerfexCRMProcessor;
/**
* CreateOrderLogic constructor.
* @param FetchesCompany $fetchesCompany
@@ -46,22 +49,24 @@ class CreateOrderLogic extends AbstractControllerLogic
* @param CreateOrderProcessor $createOrderProcessor
* @param FetchesCompanyModule $fetchesCompanyModule
* @param GeneratesOrderNumber $generatesOrderNumber
* @param NewLeadTaskToPerfexCRMProcessor $newLeadTaskToPerfexCRMProcessor
*/
public function __construct(FetchesCompany $fetchesCompany, FetchesAddress $fetchesAddress, CreateOrderProcessor $createOrderProcessor, FetchesCompanyModule $fetchesCompanyModule, GeneratesOrderNumber $generatesOrderNumber)
public function __construct(FetchesCompany $fetchesCompany, FetchesAddress $fetchesAddress, CreateOrderProcessor $createOrderProcessor, FetchesCompanyModule $fetchesCompanyModule, GeneratesOrderNumber $generatesOrderNumber, NewLeadTaskToPerfexCRMProcessor $newLeadTaskToPerfexCRMProcessor)
{
$this->fetchesCompany = $fetchesCompany;
$this->fetchesAddress = $fetchesAddress;
$this->createOrderProcessor = $createOrderProcessor;
$this->fetchesCompanyModule = $fetchesCompanyModule;
$this->generatesOrderNumber = $generatesOrderNumber;
$this->newLeadTaskToPerfexCRMProcessor = $newLeadTaskToPerfexCRMProcessor;
}
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')]);
@@ -76,6 +81,10 @@ class CreateOrderLogic extends AbstractControllerLogic
$order = $this->createOrderProcessor->execute($company, $originWarehouse, $address, $this->generatesOrderNumber->execute());
if(config('perfexcrm.is_enabled') == 'true'){
$this->newLeadTaskToPerfexCRMProcessor->execute($company);
}
return $this->resourceResponse(new OrderResource($order));
}
}
@@ -14,12 +14,11 @@ class FetchesDataFromYDPortal
* @return \Psr\Http\Message\ResponseInterface
*/
public function clientRequest(string $url, string $method, $body){
$client = new \GuzzleHttp\Client();
$client = new \GuzzleHttp\Client();
$body['apicode'] = env('YD_API_CODE');
$request = $client->requestAsync($method, $url, ['query' => $body]);
$request = $client->requestAsync($method, $url, ['query' => $body, 'timeout' => 15]);
return $request->wait();
}
@@ -32,6 +31,7 @@ class FetchesDataFromYDPortal
$content = $request->getBody()->getContents();
$content = str_replace("\r",'', $content);
$content = str_replace("\n",'', $content);
$content = str_replace("\t",'', $content);
return json_decode($content);
}
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PackingLists\Processors;
use App\Classes\General\Interfaces\Packable;
use App\Classes\Modules\PerfexCRM\Processors\PackingListToPerfexCRMProcessor;
use App\Classes\Modules\PackingLists\DataTransferObjects\PackingListObject;
use App\Classes\Modules\PackingLists\Services\CreatesPackingList;
use App\Classes\Modules\PackingLists\Standards\Rules\CanCreatePackingList;
@@ -25,16 +26,20 @@ class CreatePackingListProcessor
/** @var CreatesPackingList */
private $createsPackingList;
/** @var PackingListToPerfexCRMProcessor */
private $packingListToPerfexCRMProcessor;
/**
* CreatePackingListProcessor constructor.
* @param CanCreatePackingList $canCreatePackingList
* @param CreatesPackingList $createsPackingList
* @param PackingListToPerfexCRMProcessor $packingListToPerfexCRMProcessor
*/
public function __construct(CanCreatePackingList $canCreatePackingList, CreatesPackingList $createsPackingList)
public function __construct(CanCreatePackingList $canCreatePackingList, CreatesPackingList $createsPackingList, PackingListToPerfexCRMProcessor $packingListToPerfexCRMProcessor)
{
$this->canCreatePackingList = $canCreatePackingList;
$this->createsPackingList = $createsPackingList;
$this->packingListToPerfexCRMProcessor = $packingListToPerfexCRMProcessor;
}
/**
@@ -51,15 +56,19 @@ class CreatePackingListProcessor
/** @var PackingList $packingList */
$packingList = $this->createsPackingList->execute($object, $packable);
$appointee_id = $packingList->owner_id == 1 ? 2037 : $packingList->owner->orderRoles()->where('role_id', '=', OrderRoleTypes::ORIGIN_FREIGHT_FORWARDER)->first()->appointee->id;
$appointee_id = $packingList->owner_id == 1 ? 2307 : $packingList->owner->orderRoles()->where('role_id', '=', OrderRoleTypes::ORIGIN_FREIGHT_FORWARDER)->first()->appointee->id;
$type = $object->getType() === PackingListType::SHIPPING_PACKING_LIST ? PackingListType::SHIPPING_PACKING_LIST_REPLICA : PackingListType::WAREHOUSE_RECEIVE_LIST_REPLICA;
/** create packing list replica */
$object = new PackingListObject($object->getReference().'_01', $appointee_id, $type, ApprovalStatus::PENDING_SUBMISSION);
$this->createsPackingList->execute($object, $packingList);
if(config('perfexcrm.is_enabled') == 'true'){
$this->packingListToPerfexCRMProcessor->execute($packingList);
}
return $packingList;
}
}
}
@@ -0,0 +1,160 @@
<?php
namespace App\Classes\Modules\PackingLists\Processors;
use App\Classes\Exceptions\AccessForbiddenException;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\RequestValidationException;
use App\Classes\Exceptions\ResourceNotFoundException;
use App\Classes\Modules\Companies\Services\FetchesCompanyModule;
use App\Classes\Modules\Orders\Services\FetchesDataFromYDPortal;
use App\Classes\Modules\Orders\Services\FetchesOrder;
use App\Classes\Modules\PackingLists\DataTransferObjects\ContainerObject;
use App\Classes\Modules\PackingLists\DataTransferObjects\PackageObject;
use App\Classes\Modules\PackingLists\DataTransferObjects\PackingListObject;
use App\Classes\Modules\PackingLists\Services\Containers\FetchesContainer;
use App\Classes\Modules\PackingLists\Services\FetchesPackingList;
use App\Classes\Modules\Schedules\DataTransferObjects\ScheduleObject;
use App\Classes\Modules\Schedules\Services\CreatesSchedule;
use App\Classes\Modules\Steps\DataTransferObjects\StepsObject;
use App\Classes\Modules\Steps\Services\CreatesStep;
use App\Classes\Modules\Transports\DataTransferObjects\TransportObject;
use App\Classes\Modules\Transports\Services\CreatesTransport;
use App\Classes\Modules\Unity\Processors\ActivateContractProcessor;
use App\Classes\Modules\Unity\Processors\AssignContractEntityProcessor;
use App\Classes\Modules\Unity\Processors\CreateContractEntityProcessor;
use App\Classes\Modules\Unity\Services\CreatesContract;
use App\Classes\Modules\Unity\Services\UpdatesContractObligation;
use App\Classes\Notifications\ShipmentDepartureEmail;
use App\Classes\Notifications\ShipmentRescheduleEmail;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\ContainerTypes;
use App\Classes\ValueObjects\Constants\OrderRoleTypes;
use App\Classes\ValueObjects\Constants\PackageType;
use App\Classes\ValueObjects\Constants\PackingListType;
use App\Classes\ValueObjects\Constants\TransportType;
use App\Classes\ValueObjects\Constants\WarehouseReferences;
use App\Models\Container;
use App\Models\Order;
use App\Models\PackingList;
use App\Models\Transport;
use Carbon\Carbon;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
class FetchContainersFromYdPortalProcessor
{
/** @var FetchesDataFromYDPortal */
private $fetchesDataFRomYDPortal;
/** @var CreatesTransport */
private $createsTransport;
/** @var CreatesSchedule */
private $createsSchedule;
/** @var FetchesContainer */
private $fetchesContainer;
/** @var CreateContainerProcessor */
private $createContainerProcessor;
/**
* @param FetchesDataFromYDPortal $fetchesDataFRomYDPortal
* @param CreatesTransport $createsTransport
* @param CreatesSchedule $createsSchedule
* @param FetchesContainer $fetchesContainer
* @param CreateContainerProcessor $createContainerProcessor
*/
public function __construct(FetchesDataFromYDPortal $fetchesDataFRomYDPortal, CreatesTransport $createsTransport, CreatesSchedule $createsSchedule, FetchesContainer $fetchesContainer, CreateContainerProcessor $createContainerProcessor)
{
$this->fetchesDataFRomYDPortal = $fetchesDataFRomYDPortal;
$this->createsTransport = $createsTransport;
$this->createsSchedule = $createsSchedule;
$this->fetchesContainer = $fetchesContainer;
$this->createContainerProcessor = $createContainerProcessor;
}
/**
* @return void
* @throws MalformedRequestException
* @throws AccessForbiddenException
* @throws RequestValidationException
*/
public function execute()
{
$packingLists = PackingList::where('type', PackingListType::SHIPPING_PACKING_LIST)->doesntHave('containers')->get();
foreach ($packingLists as $packingList) {
$time_start = microtime(true);
$containerReference = null;
$loadingDate = null;
$etd = null;
$eta = null;
$trackingRequest = $this->fetchesDataFRomYDPortal->clientRequest('http://www.yd-wl.com/api/ApiTracking.ashx', 'GET', [
'trakingno' => $packingList->reference
]);
$rows = $this->fetchesDataFRomYDPortal->getResponseBody($trackingRequest);
if(!$rows->data){
continue;
}
foreach (array_reverse($rows->data) as $trackingRow) {
if (strpos($trackingRow->tracking, '货物装柜完成。') !== false) {
$tracking = explode(':', $trackingRow->tracking);
$containerReference = explode('预计到港时间', $tracking[1])[0];
$loadingDate = Carbon::parse($trackingRow->trackingtime);
$etd = Carbon::parse($tracking[2])->subDays(5);
$eta = Carbon::parse($tracking[2])->addDays(2);
}
}
if($containerReference) {
try {
$container = $this->fetchesContainer->execute(['reference' => $containerReference]);
$container->packingLists()->detach($packingList);
$container->packingLists()->attach($packingList);
} catch (ResourceNotFoundException $exception){
if(!($packingList->owner instanceof Order)) continue;
$originWarehouse = $packingList->owner->orderRoles()->where('role_id', '=', OrderRoleTypes::ORIGIN_WAREHOUSE)->first()->appointee;
$containerObject = new ContainerObject($containerReference, '', '', ContainerTypes::FORTY_FEET_DRY_CONTAINER, $loadingDate, ApprovalStatus::PENDING_VERIFICATION);
/** @var Container $container */
$container = $this->createContainerProcessor->execute($containerObject, $originWarehouse);
$container->packingLists()->detach($packingList);
$container->packingLists()->attach($packingList);
$transport = $container->transports()->first();
if(!$transport){
$transportObject = new TransportObject(TransportType::SEA, null, null, $etd, null, ApprovalStatus::APPROVED);
/** @var Transport $transport */
$transport = $this->createsTransport->execute($transportObject, $container);
$this->createsSchedule->execute($transport, new ScheduleObject($etd, $eta, ApprovalStatus::APPROVED));
}
}
}
$time_end = microtime(true);
$execution_time = ($time_end - $time_start)/60;
echo 'successful => <b>Total Execution Time:</b> '.$execution_time.' Mins<br>';
}
}
}
@@ -0,0 +1,162 @@
<?php
namespace App\Classes\Modules\PackingLists\Processors;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Modules\Orders\Services\FetchesDataFromYDPortal;
use App\Classes\Modules\Schedules\DataTransferObjects\ScheduleObject;
use App\Classes\Modules\Schedules\Services\CreatesSchedule;
use App\Classes\Modules\Unity\Services\UpdatesContractObligation;
use App\Classes\Notifications\ShipmentRescheduleEmail;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\OrderRoleTypes;
use App\Models\Container;
use App\Models\Order;
use App\Models\PackingList;
use Carbon\Carbon;
class FetchContainersUpdatesFromYdPortalProcessor
{
/** @var FetchesDataFromYDPortal */
private $fetchesDataFRomYDPortal;
/** @var UpdatesContractObligation */
private $updatesContractObligations;
/** @var CreatesSchedule */
private $createsSchedule;
/**
* @param FetchesDataFromYDPortal $fetchesDataFRomYDPortal
* @param UpdatesContractObligation $updatesContractObligations
* @param CreatesSchedule $createsSchedule
*/
public function __construct(FetchesDataFromYDPortal $fetchesDataFRomYDPortal, UpdatesContractObligation $updatesContractObligations, CreatesSchedule $createsSchedule)
{
$this->fetchesDataFRomYDPortal = $fetchesDataFRomYDPortal;
$this->updatesContractObligations = $updatesContractObligations;
$this->createsSchedule = $createsSchedule;
}
/**
* @return void
* @throws MalformedRequestException
*/
public function execute()
{
$containers = Container::where('status', ApprovalStatus::PENDING_VERIFICATION)->get();
foreach ($containers as $container) {
$time_start = microtime(true);
$packingList = $container->packingLists()->random();
$trackingRequest = $this->fetchesDataFRomYDPortal->clientRequest('http://www.yd-wl.com/api/ApiTracking.ashx', 'GET', [
'trakingno' => $packingList->reference
]);
$rows = $this->fetchesDataFRomYDPortal->getResponseBody($trackingRequest);
if(!$rows->data){
continue;
}
$unstuffingDate = null;
$delayDate = null;
foreach (array_reverse($rows->data) as $trackingRow) {
$rescheduleETD = strpos($trackingRow->remark, '开') || strpos($trackingRow->remark, '到港');
$rescheduleETA = strpos($trackingRow->remark, '到港');
if (($rescheduleETD !== false || $rescheduleETA !== false) && strpos($trackingRow->tracking, '货物装柜完成。') === false) {
preg_match_all('/([0-9]+.{3})/', $trackingRow->remark, $matches);
$dates = collect();
foreach($matches[0] as $date){
try {
$dates->push(Carbon::parse(str_replace('.', '/', $date).Carbon::now()->format('Y')));
} catch (\Exception $exception) {
continue;
}
}
$rescheduleDate = $dates->sortDesc()->first();
if(!$delayDate || $rescheduleDate > $delayDate){
/** @var Carbon $delayDate */
$delayDate = $rescheduleDate;
if($rescheduleETA === false && $delayDate) {
$delayDate = $delayDate->addDays('5');
}
}
}
if ($trackingRow->tracking === '到港') {
$delayDate = Carbon::parse($trackingRow->trackingtime);
}
if ($trackingRow->tracking === '已开船') {
$delayDate = Carbon::parse($trackingRow->trackingtime)->addDays('5');
}
if ($trackingRow->tracking === '货物已进目的港仓库') {
$unstuffingDate = Carbon::parse($trackingRow->trackingtime);
}
}
if($delayDate){
$delayDate = $delayDate->addDays(2);
$transport = $container->transports()->first();
if(!$transport->schedules()->whereDate('eta', '>=', $delayDate)->first()) {
$etd = $transport->schedules()->where('status', '=', ApprovalStatus::APPROVED)->first()->etd;
$transport->schedules()->update(['status' => ApprovalStatus::EXPIRED]);
$this->createsSchedule->execute($transport, new ScheduleObject($etd, $delayDate, ApprovalStatus::APPROVED));
foreach ($container->packingLists as $packingList){
if(!($packingList->owner instanceof Order)) continue;
$user = $packingList->owner->companyModule->employees()->first();
if(app()->environment(['production'])) {
$user->notify(new ShipmentRescheduleEmail($user, $packingList));
}
}
}
}
if($unstuffingDate){
$container->update(['status' => ApprovalStatus::COMPLETED]);
$container->transports()->first()->update(['drop_date' => $unstuffingDate, 'status' => ApprovalStatus::COMPLETED]);
/** @var PackingList $packingList */
foreach($container->packingLists as $packingList){
if($packingList->status === ApprovalStatus::PENDING_VERIFICATION){
$packingList->status = ApprovalStatus::APPROVED;
$packingList->save();
}
if(!($packingList->owner instanceof Order)) continue;
$signature = $packingList->owner->orderRoles()->where('role_id', '=', OrderRoleTypes::SUPERVISOR)->first()->appointee->entity_sigiture;
foreach($packingList->steps()->where('reference', '!=', 'DELIVERY')->get() as $step){
$this->updatesContractObligations->execute($signature, $step->obligation_hash_id);
$step->update(['status' => ApprovalStatus::COMPLETED]);
}
}
}
$time_end = microtime(true);
$execution_time = ($time_end - $time_start)/60;
echo 'successful => <b>Total Execution Time:</b> '.$execution_time.' Mins<br>';
}
}
}
@@ -0,0 +1,115 @@
<?php
namespace App\Classes\Modules\PackingLists\Processors;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Modules\Schedules\DataTransferObjects\ScheduleObject;
use App\Classes\Modules\Schedules\Services\CreatesSchedule;
use App\Classes\Modules\Transports\DataTransferObjects\TransportObject;
use App\Classes\Modules\Transports\Services\CreatesTransport;
use App\Classes\Modules\Unity\Services\UpdatesContractObligation;
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 App\Classes\ValueObjects\Constants\WarehouseReferences;
use App\Models\CompanyModule;
use App\Models\Order;
use App\Models\PackingList;
use App\Models\Transport;
use Carbon\Carbon;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
class FetchDeliveryUpdatesFromYdPortalProcessor
{
/** @var UpdatesContractObligation */
private $updatesContractObligations;
/** @var CreatesTransport */
private $createsTransport;
/** @var CreatesSchedule */
private $createsSchedule;
/**
* @param UpdatesContractObligation $updatesContractObligations
* @param CreatesTransport $createsTransport
* @param CreatesSchedule $createsSchedule
*/
public function __construct(UpdatesContractObligation $updatesContractObligations, CreatesTransport $createsTransport, CreatesSchedule $createsSchedule)
{
$this->updatesContractObligations = $updatesContractObligations;
$this->createsTransport = $createsTransport;
$this->createsSchedule = $createsSchedule;
}
/**
* @return void
* @throws MalformedRequestException
* @throws GuzzleException
*/
public function execute()
{
$packingLists = PackingList::where('type', PackingListType::SHIPPING_PACKING_LIST)->whereRaw('LENGTH(reference) > 12')->whereHas('containers', function ($container){
return $container->where('status', 3);
})->doesntHave('transports')->get()->reverse();
foreach ($packingLists->chunk(50) as $chunk) {
foreach ($chunk as $packingList){
if(!$packingList->reference) continue;
$time_start = microtime(true);
$deliveryDate = null;
try {
$client = new \GuzzleHttp\Client(['cookies' => true, 'headers' => ['Cookie' => 'utc_offset=480']]);
$request = $client->request('get', 'https://main.universe.com.my/Tracking/User/Paging?sEcho=1&sTrackingNo='.$packingList->reference.'&sOrgId=sti', ['timeout' => 3]);
$deliveryTracking = json_decode($request->getBody()->getContents());
foreach (array_reverse($deliveryTracking->aaData) as $trackingRow) {
$trackingDate = Carbon::createFromFormat('d/m/y H:i', $trackingRow->LocalDateTime);
if (Str::contains($trackingRow->PublicDescription, ['delivered'])) {
$deliveryDate = $trackingDate;
}
}
} catch (\Exception $exception){
dump($exception);
Log::debug('failed to fetch delivery tracking');
}
if($deliveryDate){
$packingList->status = ApprovalStatus::COMPLETED;
$packingList->save();
$deliveryDate = Carbon::parse($deliveryDate);
$transportObject = new TransportObject(TransportType::LAND, null, null, $deliveryDate, $deliveryDate, ApprovalStatus::APPROVED);
/** @var Transport $transport */
$transport = $this->createsTransport->execute($transportObject, $packingList);
$this->createsSchedule->execute($transport, new ScheduleObject($deliveryDate, $deliveryDate, ApprovalStatus::APPROVED));
if(!($packingList->owner instanceof Order)) continue;
$deliveryStep = $packingList->steps()->where('reference', '=', 'LAST_MILE_DELIVERY')->first();
$signature = $packingList->owner->orderRoles()->where('role_id', '=', OrderRoleTypes::SUPERVISOR)->first()->appointee->entity_sigiture;
$this->updatesContractObligations->execute($signature, $deliveryStep->obligation_hash_id);
$deliveryStep->update(['status' => ApprovalStatus::COMPLETED]);
}
$time_end = microtime(true);
$execution_time = ($time_end - $time_start)/60;
echo 'successful => <b>Total Execution Time:</b> '.$execution_time.' Mins<br>';
}
}
}
}
@@ -264,7 +264,7 @@ class FetchLoadedContainersFromVTPortalProcessor
//
// $this->unityAssignContractEntity->execute($supervisorContractEntity->hash_id, $contractObligations);
} else {
$appointee_id = 2037;
$appointee_id = 2307;
}
$packingListObject = new PackingListObject($packingListReference, $appointee_id, PackingListType::SHIPPING_PACKING_LIST, ApprovalStatus::SUSPENDED, null);
@@ -139,336 +139,360 @@ class FetchOrderListsFromYdPortalProcessor
*/
public function execute(?Carbon $start = null, ?Carbon $end = null)
{
try {
$start = $start ? $start : Carbon::today()->subDays(30);
ini_set('max_execution_time', '900');
// $missingOrders = ['M202302161513122', 'YW202302161027442', 'YW202302151637022', 'M202302151605025', 'M202302151527103', 'M202302151527356', 'M202302151556019', 'YW202302151520241', 'YW202302151445068', 'M202302151359169', 'YW202302151349223', 'YW202302151336520', 'M202302151334316', 'YW202302151148129', 'M202302151145379', 'M202302151142411', 'M202302151037036', 'M202302151036398', 'M202302150919406', 'M202302141535009', 'YW202302141532318', 'M202302141319463', 'M202302141319045', 'YW202302141405471', 'M202302141334494', 'YW202302141321569', 'YW202302141323005', 'M202302141309053', 'M202302140905116', 'M202302141039558', 'M202302141022333', 'YW202302140943182', 'YW202302140923485', 'YW202302131728233', 'YW202302131702040', 'M202302131649417', 'M202302131638056', 'YW202302131601110', 'YW202302131530436', 'YW202302131411338', 'YW202302131355161', 'YW202302131312526', 'M202302130859076', 'M202302111708070', 'M202302111455134', 'M202302111457501', 'M202302111444041', 'M202302111506514', 'M202302111440286', 'M202302111354585', 'M202302111055551', 'M202302110900216', 'YW202302101743112', 'M202302091559443', 'M202302101716374', 'M202302101700402', 'M202302101633570', 'M202302101612095', 'M202302101611408', 'M202302101542340', 'M202302101408370', 'M202302101323341', 'M202302101129532', 'M202302101025109', 'M202302101006595', 'M202302091706357', 'YW202302091255022', 'YW202302091448196', 'YW202302091446431', 'M202302091138154', 'M202302091129396', 'YW202302091028175', 'M202302091006545', 'YW202302090942033', 'YW202302081743094', 'M202302081530599', 'M202302081531210', 'M202302081508571', 'YW202302081530492', 'M202302081500361', 'M202302081253105', 'M202302081303370', 'M202302071636303', 'M202302071741187', 'YW202302071735407', 'M202302071706323', 'M202302071537501', 'M202302071538092', 'YW202302071516453', 'M202302071311314', 'M202302071148154', 'YW202302071136018', 'M202302071036027', 'M202302071008010', 'M202302061742178', 'M202302061615198', 'M202302061502093', 'M202302061458532', 'M202302061552141', 'M202302061548431', 'M202302061555033', 'YW202302061404567', 'M202302061322463', 'M202302061042556', 'M202302061021277', 'M202302060917276', 'M202302041551570', 'M202302041552382', 'YW202302041515257', 'M202302041405502', 'M202302041030185', 'YW202302041215576', 'YW202302041058469', 'YW202302041024459', 'YW202302040939568', 'M202302031701053', 'M202302031700316', 'M202302031430562', 'M202302031431535', 'M202302031147213', 'YW202302031406529', 'YW202302031322256', 'M202302021718554', 'M202302021417415', 'YW202302021404542', 'M202302021055324', 'YW202302021037462', 'M202302011613381', 'M202302011347586', 'M202302011348245', 'M202301151635132', 'M202301141803516', 'YW202301141653536', 'M202301131504477', 'M202301131538220', 'M202301121327453', 'YW202301111153183', 'M202301091649543', 'M202212311641071', 'YW202212211532191', 'YW202212191605226'];
$startLimit = Carbon::parse('01-12-2021');
$from = $end ? Carbon::today()->diff($end)->days : 0;
$to = $start ? Carbon::today()->diff($start)->days : 10;
if($start->isBefore($startLimit)){
$start = $startLimit;
}
for ($x = $from; $x <= $to; $x++) {
try {
$startDate = Carbon::today()->subDays($x);
$end = $end ? $end : Carbon::today()->addDay();
$startLimit = Carbon::parse('01-12-2021');
$orderRequest = $this->fetchesDataFRomYDPortal->clientRequest('http://www.yd-wl.com/api/GetOrderList.ashx', 'GET', [
'begintime' => $start->timestamp,
'endtime' => $end->timestamp,
]);
if($startDate->isBefore($startLimit)){
$startDate = $startLimit;
}
$rows = $this->fetchesDataFRomYDPortal->getResponseBody($orderRequest);
$endDate = Carbon::today()->subDays($x - 1);
foreach($rows->data as $row){
$containerReference = null;
$loadingDate = null;
$unstuffingDate = null;
$deliveryDate = null;
$etd = null;
$eta = null;
$delayDate = null;
$trackingRequest = $this->fetchesDataFRomYDPortal->clientRequest('http://www.yd-wl.com/api/ApiTracking.ashx', 'GET', [
'trakingno' => $row->expressno
$orderRequest = $this->fetchesDataFRomYDPortal->clientRequest('http://www.yd-wl.com/api/GetOrderList.ashx', 'GET', [
'begintime' => $startDate->timestamp,
'endtime' => $endDate->timestamp,
]);
$rows = $this->fetchesDataFRomYDPortal->getResponseBody($trackingRequest);
$rows = $this->fetchesDataFRomYDPortal->getResponseBody($orderRequest);
if(!$rows){
continue;
}
if(!$rows->data) continue;
foreach (array_reverse($rows->data) as $trackingRow) {
if ($trackingRow->tracking === '货物已送达仓库准备入库中') {
$receiveDate = Carbon::parse($trackingRow->trackingtime);
}
foreach($rows->data as $row){
$time_start = microtime(true);
if (strpos($trackingRow->tracking, '货物装柜完成。') !== false) {
$tracking = explode(':', $trackingRow->tracking);
$containerReference = explode('预计到港时间', $tracking[1])[0];
$loadingDate = Carbon::parse($trackingRow->trackingtime);
$etd = Carbon::parse($tracking[2])->subDays(5);
$eta = Carbon::parse($tracking[2])->addDays(2);
}
$containerReference = null;
$loadingDate = null;
$unstuffingDate = null;
$deliveryDate = null;
$etd = null;
$eta = null;
$delayDate = null;
$status = $row->status;
$rescheduleETD = strpos($trackingRow->remark, '开') || strpos($trackingRow->remark, '到港');
$rescheduleETA = strpos($trackingRow->remark, '到港');
if (($rescheduleETD !== false || $rescheduleETA !== false) && strpos($trackingRow->tracking, '货物装柜完成。') === false) {
preg_match_all('/([0-9]+.{3})/', $trackingRow->remark, $matches);
$dates = collect();
foreach($matches[0] as $date){
try {
$dates->push(Carbon::parse(str_replace('.', '/', $date).Carbon::now()->format('Y')));
} catch (\Exception $exception) {
continue;
}
}
$rescheduleDate = $dates->sortDesc()->first();
if(!$delayDate || $rescheduleDate > $delayDate){
/** @var Carbon $delayDate */
$delayDate = $rescheduleDate;
if($rescheduleETA === false && $delayDate) {
$delayDate = $delayDate->addDays('5');
}
}
}
if ($trackingRow->tracking === '到港') {
$delayDate = Carbon::parse($trackingRow->trackingtime);
}
if ($trackingRow->tracking === '已开船') {
$delayDate = Carbon::parse($trackingRow->trackingtime)->addDays('5');
}
if ($trackingRow->tracking === '货物已进目的港仓库') {
$unstuffingDate = Carbon::parse($trackingRow->trackingtime);
}
if (Str::contains($trackingRow->tracking, ['派送中', '已签收', '签收完成', ' 第三方提货', '货物已派送完成', '派送', 'delivery', 'delivered'])) {
$deliveryDate = Carbon::parse($trackingRow->trackingtime);
}
}
$client = new \GuzzleHttp\Client(['cookies' => true, 'headers' => ['Cookie' => 'utc_offset=480']]);
try {
$request = $client->request('get', 'https://main.universe.com.my/Tracking/User/Paging?sEcho=1&sTrackingNo='.$row->expressno.'&sOrgId=sti');
$deliveryTracking = json_decode($request->getBody()->getContents());
foreach (array_reverse($deliveryTracking->aaData) as $trackingRow) {
$trackingDate = Carbon::createFromFormat('d/m/y H:i', $trackingRow->LocalDateTime);
if (Str::contains($trackingRow->PublicDescription, ['accepted/picked'])){
$unstuffingDate = $trackingDate;
}
if (Str::contains($trackingRow->PublicDescription, ['delivered'])) {
$deliveryDate = $trackingDate;
}
}
} catch (\Exception $exception){
Log::debug('failed to fetch delivery tracking');
}
$customerno = preg_split('(-|\(|\)|\/)', $row->customerno);
$orderNumber = $customerno[array_key_last($customerno)];
$allow_contract = true;
try {
$order = $this->fetchesOrder->execute(['reference' => $orderNumber]);
} catch (ResourceNotFoundException $exception) {
try {
$order = $this->fetchesOrder->execute(['reference' => substr($orderNumber, -9)]);
} catch (ResourceNotFoundException $exception) {
$order = $this->fetchesCompanyModule->execute(['id' => 1]);
$allow_contract = false;
}
}
$packingListReference = $row->expressno;
try{
$packingList = $this->fetchesPackingList->execute(['reference' => $row->expressno, 'type' => PackingListType::SHIPPING_PACKING_LIST]);
$packingList->packages()->delete();
$replica = $packingList->packingLists()->where('type', PackingListType::SHIPPING_PACKING_LIST_REPLICA)->first();
if($replica) $replica->packages()->delete();
$warehouseReceiveList = $this->fetchesPackingList->execute(['reference' => $row->expressno, 'type' => PackingListType::WAREHOUSE_RECEIVE_LIST]);
$warehouseReceiveList->packages()->delete();
$replica = $warehouseReceiveList->packingLists()->where('type', PackingListType::WAREHOUSE_RECEIVE_LIST_REPLICA)->first();
if($replica) $replica->packages()->delete();
} catch (ResourceNotFoundException $exception) {
if (!$allow_contract) {
$appointee_id = 2037;
} else {
$appointee_id = $order->orderRoles()->where('role_id', '=', OrderRoleTypes::ORIGIN_FREIGHT_FORWARDER)->first()->appointee->id;
}
$warehouseReceiveObject = new PackingListObject($packingListReference, $appointee_id, PackingListType::WAREHOUSE_RECEIVE_LIST, $allow_contract ? ApprovalStatus::APPROVED : ApprovalStatus::REJECTED);
/** @var PackingList $warehouseReceiveList */
$warehouseReceiveList = $this->createPackingListProcessor->execute($warehouseReceiveObject, $order);
$transportObject = new TransportObject(TransportType::LAND, null, $row->kuaidilist, Carbon::parse($receiveDate), Carbon::parse($receiveDate), $allow_contract ? ApprovalStatus::APPROVED : ApprovalStatus::REJECTED);
$transport = $this->createsTransport->execute($transportObject, $warehouseReceiveList);
if ($allow_contract) {
$contract = $this->unityCreateContract->execute();
$contractReference = $contract->hash_id;
$contractObligations = $contract->contract_obligation_list;
$this->unityActivateContract->execute($contractReference);
$supervisorHashId = $order->orderRoles()->where('role_id', '=', OrderRoleTypes::SUPERVISOR)->first()->appointee->unity_hash_id;
$supervisorContractEntity = $this->unityCreateContractEntity->execute($contractReference, $supervisorHashId);
$order->orderRoles()->where('role_id', '=', OrderRoleTypes::SUPERVISOR)->first()->update(['entity_hash_id' => $supervisorContractEntity->hash_id, 'entity_signature' => $supervisorContractEntity->entity_signature_hash_id]);
$importerContractEntity = $this->unityCreateContractEntity->execute($contractReference, $order->orderRoles()->where('role_id', '=', OrderRoleTypes::IMPORTER)->first()->appointee->unity_hash_id);
$order->orderRoles()->where('role_id', '=', OrderRoleTypes::IMPORTER)->first()->update(['entity_hash_id' => $importerContractEntity->hash_id, 'entity_signature' => $importerContractEntity->entity_signature_hash_id]);
$this->unityAssignContractEntity->execute($supervisorContractEntity->hash_id, $contractObligations);
}
$packingListObject = new PackingListObject($packingListReference, $appointee_id, PackingListType::SHIPPING_PACKING_LIST, ApprovalStatus::SUSPENDED, !$allow_contract ? null : $contractReference);
/** @var PackingList $packingList */
$packingList = $this->createPackingListProcessor->execute($packingListObject, $order);
if ($allow_contract) {
foreach ($contractObligations as $obligation) {
$stepObject = new StepsObject($order->orderRoles()->where('role_id', '=', OrderRoleTypes::SUPERVISOR)->first()->appointee->id, $obligation->reference, $obligation->sequence, $obligation->hash_id);
$this->createsStep->execute($packingList, $stepObject);
}
}
}
foreach($row->deliverysize as $package) {
$packageObject = new PackageObject(PackageType::CARTON, $row->goodname, (float) $package->width, (float) $package->height, (float) $package->length, 0, (float) $package->num, ApprovalStatus::APPROVED);
$this->createPackageProcessor->execute($packageObject, $warehouseReceiveList);
$this->createPackageProcessor->execute($packageObject, $packingList);
}
if(!count($row->deliverysize)){
$measurement = round(((float) $row->volume / (float) $row->goodcount) ** (1/3) * 100, 2);
$packageObject = new PackageObject(PackageType::CARTON, $row->goodname, (float) $measurement, (float) $measurement, (float) $measurement, 0, (float) $row->goodcount, ApprovalStatus::APPROVED);
$this->createPackageProcessor->execute($packageObject, $warehouseReceiveList);
$this->createPackageProcessor->execute($packageObject, $packingList);
}
$weightCbm = (float) $row->weight / 500;
$overWeightCbm = $weightCbm - $packingList->packages()->sum(DB::raw('(width/100) * (height/100) * (length/100) * quantity'));
if($overWeightCbm > 0){
$measurement = round($overWeightCbm ** (1/3) * 100, 2);
$packageObject = new PackageObject(PackageType::OVER_WEIGHT, 'Overweight CBM', (float) $measurement, (float) $measurement, (float) $measurement, 0, 1, ApprovalStatus::APPROVED);
$this->createPackageProcessor->execute($packageObject, $packingList);
}
if($order instanceof Order){
$marking = $order->companyModule->inviters()->withPivot('invitee_reference')->first()->pivot->invitee_reference;
if(!in_array($marking, ['1290CSW', '8997ITB', '3992WHE', '962LOW', '1152AAT'])){
$this->fetchesDataFRomYDPortal->clientRequest('http://www.yd-wl.com/api/confirmsendorder.ashx', 'GET', [
'expressno' => $row->expressno
if($status >= 3){
$trackingRequest = $this->fetchesDataFRomYDPortal->clientRequest('http://www.yd-wl.com/api/ApiTracking.ashx', 'GET', [
'trakingno' => $row->expressno
]);
$rows = $this->fetchesDataFRomYDPortal->getResponseBody($trackingRequest);
if(!$rows){
continue;
}
foreach (array_reverse($rows->data) as $trackingRow) {
if ($trackingRow->tracking === '货物已送达仓库准备入库中') {
$receiveDate = Carbon::parse($trackingRow->trackingtime);
}
if (strpos($trackingRow->tracking, '货物装柜完成。') !== false) {
$tracking = explode(':', $trackingRow->tracking);
$containerReference = explode('预计到港时间', $tracking[1])[0];
$loadingDate = Carbon::parse($trackingRow->trackingtime);
$etd = Carbon::parse($tracking[2])->subDays(5);
$eta = Carbon::parse($tracking[2])->addDays(2);
}
$rescheduleETD = strpos($trackingRow->remark, '开') || strpos($trackingRow->remark, '到港');
$rescheduleETA = strpos($trackingRow->remark, '到港');
if (($rescheduleETD !== false || $rescheduleETA !== false) && strpos($trackingRow->tracking, '货物装柜完成。') === false) {
preg_match_all('/([0-9]+.{3})/', $trackingRow->remark, $matches);
$dates = collect();
foreach($matches[0] as $date){
try {
$dates->push(Carbon::parse(str_replace('.', '/', $date).Carbon::now()->format('Y')));
} catch (\Exception $exception) {
continue;
}
}
$rescheduleDate = $dates->sortDesc()->first();
if(!$delayDate || $rescheduleDate > $delayDate){
/** @var Carbon $delayDate */
$delayDate = $rescheduleDate;
if($rescheduleETA === false && $delayDate) {
$delayDate = $delayDate->addDays('5');
}
}
}
if ($trackingRow->tracking === '到港') {
$delayDate = Carbon::parse($trackingRow->trackingtime);
}
if ($trackingRow->tracking === '已开船') {
$delayDate = Carbon::parse($trackingRow->trackingtime)->addDays('5');
}
if ($trackingRow->tracking === '货物已进目的港仓库') {
$unstuffingDate = Carbon::parse($trackingRow->trackingtime);
}
if (Str::contains($trackingRow->tracking, ['派送中', '已签收', '签收完成', ' 第三方提货', '货物已派送完成', '派送', 'delivery', 'delivered'])) {
$deliveryDate = Carbon::parse($trackingRow->trackingtime);
}
}
}
}
if($status >= 5){
$client = new \GuzzleHttp\Client(['cookies' => true, 'headers' => ['Cookie' => 'utc_offset=480']]);
try {
$request = $client->request('get', 'https://main.universe.com.my/Tracking/User/Paging?sEcho=1&sTrackingNo='.$row->expressno.'&sOrgId=sti');
$deliveryTracking = json_decode($request->getBody()->getContents());
foreach (array_reverse($deliveryTracking->aaData) as $trackingRow) {
$trackingDate = Carbon::createFromFormat('d/m/y H:i', $trackingRow->LocalDateTime);
if (Str::contains($trackingRow->PublicDescription, ['accepted/picked'])){
$unstuffingDate = $trackingDate;
}
if (Str::contains($trackingRow->PublicDescription, ['delivered'])) {
$deliveryDate = $trackingDate;
}
}
} catch (\Exception $exception){
Log::debug('failed to fetch delivery tracking');
}
}
$customerno = preg_split('(-|\(|\)|\/)', $row->customerno);
$orderNumber = $customerno[array_key_last($customerno)];
$allow_contract = true;
if($containerReference) {
try {
$container = $this->fetchesContainer->execute(['reference' => $containerReference]);
$container->packingLists()->detach($packingList);
$container->packingLists()->attach($packingList);
} catch (ResourceNotFoundException $exception){
$order = $this->fetchesOrder->execute(['reference' => $orderNumber]);
} catch (ResourceNotFoundException $exception) {
try {
$order = $this->fetchesOrder->execute(['reference' => substr($orderNumber, -9)]);
} catch (ResourceNotFoundException $exception) {
$order = $this->fetchesCompanyModule->execute(['id' => 1]);
$allow_contract = false;
}
}
$packingListReference = $row->expressno;
try{
$packingList = $this->fetchesPackingList->execute(['reference' => $row->expressno, 'type' => PackingListType::SHIPPING_PACKING_LIST]);
$packingList->packages()->delete();
$replica = $packingList->packingLists()->where('type', PackingListType::SHIPPING_PACKING_LIST_REPLICA)->first();
if($replica) $replica->packages()->delete();
$warehouseReceiveList = $this->fetchesPackingList->execute(['reference' => $row->expressno, 'type' => PackingListType::WAREHOUSE_RECEIVE_LIST]);
$warehouseReceiveList->packages()->delete();
$replica = $warehouseReceiveList->packingLists()->where('type', PackingListType::WAREHOUSE_RECEIVE_LIST_REPLICA)->first();
if($replica) $replica->packages()->delete();
} catch (ResourceNotFoundException $exception) {
if (!$allow_contract) {
$appointee_id = 2037;
}
else {
$appointee_id = $order->orderRoles()->where('role_id', '=', OrderRoleTypes::ORIGIN_WAREHOUSE)->first()->appointee->id;
$appointee_id = 2307;
} else {
$appointee_id = $order->orderRoles()->where('role_id', '=', OrderRoleTypes::ORIGIN_FREIGHT_FORWARDER)->first()->appointee->id;
}
$originWarehouse = $this->fetchesCompanyModule->execute(['id' => $appointee_id]);
$warehouseReceiveObject = new PackingListObject($packingListReference, $appointee_id, PackingListType::WAREHOUSE_RECEIVE_LIST, $allow_contract ? ApprovalStatus::APPROVED : ApprovalStatus::REJECTED);
$containerObject = new ContainerObject($containerReference, '', '', ContainerTypes::FORTY_FEET_DRY_CONTAINER, $loadingDate, ApprovalStatus::PENDING_VERIFICATION);
/** @var Container $container */
$container = $this->createContainerProcessor->execute($containerObject, $originWarehouse);
/** @var PackingList $warehouseReceiveList */
$warehouseReceiveList = $this->createPackingListProcessor->execute($warehouseReceiveObject, $order);
$container->packingLists()->detach($packingList);
$container->packingLists()->attach($packingList);
$transportObject = new TransportObject(TransportType::LAND, null, $row->kuaidilist, Carbon::parse($receiveDate), Carbon::parse($receiveDate), $allow_contract ? ApprovalStatus::APPROVED : ApprovalStatus::REJECTED);
$transport = $this->createsTransport->execute($transportObject, $warehouseReceiveList);
$transport = $container->transports()->first();
if ($allow_contract) {
if(!$transport){
$transportObject = new TransportObject(TransportType::SEA, null, null, $etd, null, ApprovalStatus::APPROVED);
/** @var Transport $transport */
$transport = $this->createsTransport->execute($transportObject, $container);
$this->createsSchedule->execute($transport, new ScheduleObject($etd, $eta, ApprovalStatus::APPROVED));
}
}
$contract = $this->unityCreateContract->execute();
if($delayDate){
$delayDate = $delayDate->addDays(2);
$transport = $container->transports()->first();
$contractReference = $contract->hash_id;
$contractObligations = $contract->contract_obligation_list;
if(!$transport->schedules()->whereDate('eta', '>=', $delayDate)->first()) {
$etd = $transport->schedules()->where('status', '=', ApprovalStatus::APPROVED)->first()->etd;
$transport->schedules()->update(['status' => ApprovalStatus::EXPIRED]);
$this->createsSchedule->execute($transport, new ScheduleObject($etd, $delayDate, ApprovalStatus::APPROVED));
foreach ($container->packingLists as $packingList){
if(!($packingList->owner instanceof Order)) continue;
$user = $packingList->owner->companyModule->employees()->first();
if(app()->environment(['production'])) {
$user->notify(new ShipmentRescheduleEmail($user, $packingList));
}
}
$this->unityActivateContract->execute($contractReference);
$supervisorHashId = $order->orderRoles()->where('role_id', '=', OrderRoleTypes::SUPERVISOR)->first()->appointee->unity_hash_id;
$supervisorContractEntity = $this->unityCreateContractEntity->execute($contractReference, $supervisorHashId);
$order->orderRoles()->where('role_id', '=', OrderRoleTypes::SUPERVISOR)->first()->update(['entity_hash_id' => $supervisorContractEntity->hash_id, 'entity_signature' => $supervisorContractEntity->entity_signature_hash_id]);
$importerContractEntity = $this->unityCreateContractEntity->execute($contractReference, $order->orderRoles()->where('role_id', '=', OrderRoleTypes::IMPORTER)->first()->appointee->unity_hash_id);
$order->orderRoles()->where('role_id', '=', OrderRoleTypes::IMPORTER)->first()->update(['entity_hash_id' => $importerContractEntity->hash_id, 'entity_signature' => $importerContractEntity->entity_signature_hash_id]);
$this->unityAssignContractEntity->execute($supervisorContractEntity->hash_id, $contractObligations);
}
}
if($unstuffingDate && $container->status !== ApprovalStatus::COMPLETED){
$container->update(['status' => ApprovalStatus::COMPLETED]);
$container->transports()->first()->update(['drop_date' => $unstuffingDate, 'status' => ApprovalStatus::COMPLETED]);
$packingListObject = new PackingListObject($packingListReference, $appointee_id, PackingListType::SHIPPING_PACKING_LIST, ApprovalStatus::SUSPENDED, !$allow_contract ? null : $contractReference);
/** @var PackingList $packingList */
foreach($container->packingLists as $packingList){
$packingList = $this->createPackingListProcessor->execute($packingListObject, $order);
if($packingList->status === ApprovalStatus::PENDING_VERIFICATION){
$packingList->status = ApprovalStatus::APPROVED;
$packingList->save();
if ($allow_contract) {
foreach ($contractObligations as $obligation) {
$stepObject = new StepsObject($order->orderRoles()->where('role_id', '=', OrderRoleTypes::SUPERVISOR)->first()->appointee->id, $obligation->reference, $obligation->sequence, $obligation->hash_id);
$this->createsStep->execute($packingList, $stepObject);
}
}
}
foreach($row->deliverysize as $package) {
$packageObject = new PackageObject(PackageType::CARTON, $row->goodname, (float) $package->width, (float) $package->height, (float) $package->length, 0, (float) $package->num, ApprovalStatus::APPROVED);
$this->createPackageProcessor->execute($packageObject, $warehouseReceiveList);
$this->createPackageProcessor->execute($packageObject, $packingList);
}
if(!count($row->deliverysize)){
$measurement = round(((float) $row->volume / (float) $row->goodcount) ** (1/3) * 100, 2);
$packageObject = new PackageObject(PackageType::CARTON, $row->goodname, (float) $measurement, (float) $measurement, (float) $measurement, 0, (float) $row->goodcount, ApprovalStatus::APPROVED);
$this->createPackageProcessor->execute($packageObject, $warehouseReceiveList);
$this->createPackageProcessor->execute($packageObject, $packingList);
}
$weightCbm = (float) $row->weight / 500;
$overWeightCbm = $weightCbm - $packingList->packages()->sum(DB::raw('(width/100) * (height/100) * (length/100) * quantity'));
if($overWeightCbm > 0){
$measurement = round($overWeightCbm ** (1/3) * 100, 2);
$packageObject = new PackageObject(PackageType::OVER_WEIGHT, 'Overweight CBM', (float) $measurement, (float) $measurement, (float) $measurement, 0, 1, ApprovalStatus::APPROVED);
$this->createPackageProcessor->execute($packageObject, $packingList);
}
if($order instanceof Order){
$marking = $order->companyModule->inviters()->withPivot('invitee_reference')->first()->pivot->invitee_reference;
if(!in_array($marking, ['1290CSW', '8997ITB', '3992WHE', '962LOW', '1152AAT'])){
$this->fetchesDataFRomYDPortal->clientRequest('http://www.yd-wl.com/api/confirmsendorder.ashx', 'GET', [
'expressno' => $row->expressno
]);
}
}
if($containerReference) {
try {
$container = $this->fetchesContainer->execute(['reference' => $containerReference]);
$container->packingLists()->detach($packingList);
$container->packingLists()->attach($packingList);
} catch (ResourceNotFoundException $exception){
if (!$allow_contract) {
$appointee_id = 2307;
}
else {
$appointee_id = $order->orderRoles()->where('role_id', '=', OrderRoleTypes::ORIGIN_WAREHOUSE)->first()->appointee->id;
}
if ($allow_contract) {
$signature = $packingList->owner->orderRoles()->where('role_id', '=', OrderRoleTypes::SUPERVISOR)->first()->appointee->entity_sigiture;
foreach($packingList->steps()->where('reference', '!=', 'DELIVERY')->get() as $step){
$this->updatesContractObligations->execute($signature, $step->obligation_hash_id);
$step->update(['status' => ApprovalStatus::COMPLETED]);
$originWarehouse = $this->fetchesCompanyModule->execute(['id' => $appointee_id]);
$containerObject = new ContainerObject($containerReference, '', '', ContainerTypes::FORTY_FEET_DRY_CONTAINER, $loadingDate, ApprovalStatus::PENDING_VERIFICATION);
/** @var Container $container */
$container = $this->createContainerProcessor->execute($containerObject, $originWarehouse);
$container->packingLists()->detach($packingList);
$container->packingLists()->attach($packingList);
$transport = $container->transports()->first();
if(!$transport){
$transportObject = new TransportObject(TransportType::SEA, null, null, $etd, null, ApprovalStatus::APPROVED);
/** @var Transport $transport */
$transport = $this->createsTransport->execute($transportObject, $container);
$this->createsSchedule->execute($transport, new ScheduleObject($etd, $eta, ApprovalStatus::APPROVED));
}
}
if($delayDate){
$delayDate = $delayDate->addDays(2);
$transport = $container->transports()->first();
if(!$transport->schedules()->whereDate('eta', '>=', $delayDate)->first()) {
$etd = $transport->schedules()->where('status', '=', ApprovalStatus::APPROVED)->first()->etd;
$transport->schedules()->update(['status' => ApprovalStatus::EXPIRED]);
$this->createsSchedule->execute($transport, new ScheduleObject($etd, $delayDate, ApprovalStatus::APPROVED));
foreach ($container->packingLists as $packingList){
if(!($packingList->owner instanceof Order)) continue;
$user = $packingList->owner->companyModule->employees()->first();
if(app()->environment(['production'])) {
$user->notify(new ShipmentRescheduleEmail($user, $packingList));
}
}
}
}
if($unstuffingDate && $container->status !== ApprovalStatus::COMPLETED){
$container->update(['status' => ApprovalStatus::COMPLETED]);
$container->transports()->first()->update(['drop_date' => $unstuffingDate, 'status' => ApprovalStatus::COMPLETED]);
/** @var PackingList $packingList */
foreach($container->packingLists as $packingList){
if($packingList->status === ApprovalStatus::PENDING_VERIFICATION){
$packingList->status = ApprovalStatus::APPROVED;
$packingList->save();
}
if ($allow_contract) {
$signature = $packingList->owner->orderRoles()->where('role_id', '=', OrderRoleTypes::SUPERVISOR)->first()->appointee->entity_sigiture;
foreach($packingList->steps()->where('reference', '!=', 'DELIVERY')->get() as $step){
$this->updatesContractObligations->execute($signature, $step->obligation_hash_id);
$step->update(['status' => ApprovalStatus::COMPLETED]);
}
}
}
}
}
}
if($deliveryDate && !$packingList->transports()->exists()){
$packingList->status = ApprovalStatus::COMPLETED;
$packingList->save();
if($deliveryDate && !$packingList->transports()->exists()){
$packingList->status = ApprovalStatus::COMPLETED;
$packingList->save();
$deliveryDate = Carbon::parse($deliveryDate);
$transportObject = new TransportObject(TransportType::LAND, null, null, $deliveryDate, $deliveryDate, ApprovalStatus::APPROVED);
/** @var Transport $transport */
$transport = $this->createsTransport->execute($transportObject, $packingList);
$this->createsSchedule->execute($transport, new ScheduleObject($deliveryDate, $deliveryDate, ApprovalStatus::APPROVED));
$deliveryDate = Carbon::parse($deliveryDate);
$transportObject = new TransportObject(TransportType::LAND, null, null, $deliveryDate, $deliveryDate, ApprovalStatus::APPROVED);
/** @var Transport $transport */
$transport = $this->createsTransport->execute($transportObject, $packingList);
$this->createsSchedule->execute($transport, new ScheduleObject($deliveryDate, $deliveryDate, ApprovalStatus::APPROVED));
if ($allow_contract) {
$deliveryStep = $packingList->steps()->where('reference', '=', 'LAST_MILE_DELIVERY')->first();
$signature = $packingList->owner->orderRoles()->where('role_id', '=', OrderRoleTypes::SUPERVISOR)->first()->appointee->entity_sigiture;
$this->updatesContractObligations->execute($signature, $deliveryStep->obligation_hash_id);
$deliveryStep->update(['status' => ApprovalStatus::COMPLETED]);
if ($allow_contract) {
$deliveryStep = $packingList->steps()->where('reference', '=', 'LAST_MILE_DELIVERY')->first();
$signature = $packingList->owner->orderRoles()->where('role_id', '=', OrderRoleTypes::SUPERVISOR)->first()->appointee->entity_sigiture;
$this->updatesContractObligations->execute($signature, $deliveryStep->obligation_hash_id);
$deliveryStep->update(['status' => ApprovalStatus::COMPLETED]);
}
}
$time_end = microtime(true);
$execution_time = ($time_end - $time_start)/60;
echo '<b>Total Execution Time:</b> '.$execution_time.' Mins';
echo 'successful';
}
echo 'successful';
} catch (\Exception $exception) {
Log::debug($exception);
}
} catch (\Exception $exception) {
Log::debug($exception);
}
}
}
@@ -66,7 +66,6 @@ class FetchPackingListFromVTPortalProcessor
}
} catch (GuzzleException $exception) {
dd($exception);
Log::error($exception);
continue;
}
@@ -0,0 +1,267 @@
<?php
namespace App\Classes\Modules\PackingLists\Processors;
use App\Classes\Exceptions\ResourceNotFoundException;
use App\Classes\Modules\Companies\Services\FetchesCompanyModule;
use App\Classes\Modules\Orders\Services\FetchesDataFromYDPortal;
use App\Classes\Modules\Orders\Services\FetchesOrder;
use App\Classes\Modules\PackingLists\DataTransferObjects\PackageObject;
use App\Classes\Modules\PackingLists\DataTransferObjects\PackingListObject;
use App\Classes\Modules\PackingLists\Services\FetchesPackingList;
use App\Classes\Modules\Steps\DataTransferObjects\StepsObject;
use App\Classes\Modules\Steps\Services\CreatesStep;
use App\Classes\Modules\Transports\DataTransferObjects\TransportObject;
use App\Classes\Modules\Transports\Services\CreatesTransport;
use App\Classes\Modules\Unity\Processors\ActivateContractProcessor;
use App\Classes\Modules\Unity\Processors\AssignContractEntityProcessor;
use App\Classes\Modules\Unity\Processors\CreateContractEntityProcessor;
use App\Classes\Modules\Unity\Services\CreatesContract;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\OrderRoleTypes;
use App\Classes\ValueObjects\Constants\PackageType;
use App\Classes\ValueObjects\Constants\PackingListType;
use App\Classes\ValueObjects\Constants\TransportType;
use App\Models\Order;
use App\Models\PackingList;
use Carbon\Carbon;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class FetchPackingListsFromYdPortalProcessor
{
/** @var FetchesDataFromYDPortal */
private $fetchesDataFRomYDPortal;
/** @var FetchesOrder */
private $fetchesOrder;
/** @var CreatePackingListProcessor */
private $createPackingListProcessor;
/** @var CreatePackageProcessor */
private $createPackageProcessor;
/** @var CreatesTransport */
private $createsTransport;
/** @var FetchesPackingList */
private $fetchesPackingList;
/** @var FetchesCompanyModule */
private $fetchesCompanyModule;
/** @var CreatesContract */
private $unityCreateContract;
/** @var AssignContractEntityProcessor */
private $unityAssignContractEntity;
/** @var CreateContractEntityProcessor */
private $unityCreateContractEntity;
/** @var CreatesStep */
private $createsStep;
/** @var ActivateContractProcessor */
private $unityActivateContract;
/**
* @param FetchesDataFromYDPortal $fetchesDataFRomYDPortal
* @param FetchesOrder $fetchesOrder
* @param CreatePackingListProcessor $createPackingListProcessor
* @param CreatePackageProcessor $createPackageProcessor
* @param CreatesTransport $createsTransport
* @param FetchesPackingList $fetchesPackingList
* @param FetchesCompanyModule $fetchesCompanyModule
* @param CreatesContract $unityCreateContract
* @param AssignContractEntityProcessor $unityAssignContractEntity
* @param CreateContractEntityProcessor $unityCreateContractEntity
* @param CreatesStep $createsStep
* @param ActivateContractProcessor $unityActivateContract
*/
public function __construct(FetchesDataFromYDPortal $fetchesDataFRomYDPortal, FetchesOrder $fetchesOrder, CreatePackingListProcessor $createPackingListProcessor, CreatePackageProcessor $createPackageProcessor, CreatesTransport $createsTransport, FetchesPackingList $fetchesPackingList, FetchesCompanyModule $fetchesCompanyModule, CreatesContract $unityCreateContract, AssignContractEntityProcessor $unityAssignContractEntity, CreateContractEntityProcessor $unityCreateContractEntity, CreatesStep $createsStep, ActivateContractProcessor $unityActivateContract)
{
$this->fetchesDataFRomYDPortal = $fetchesDataFRomYDPortal;
$this->fetchesOrder = $fetchesOrder;
$this->createPackingListProcessor = $createPackingListProcessor;
$this->createPackageProcessor = $createPackageProcessor;
$this->createsTransport = $createsTransport;
$this->fetchesPackingList = $fetchesPackingList;
$this->fetchesCompanyModule = $fetchesCompanyModule;
$this->unityCreateContract = $unityCreateContract;
$this->unityAssignContractEntity = $unityAssignContractEntity;
$this->unityCreateContractEntity = $unityCreateContractEntity;
$this->createsStep = $createsStep;
$this->unityActivateContract = $unityActivateContract;
}
/**
* @param Carbon|null $start
* @param Carbon|null $end
* @return void
* @throws GuzzleException
*/
public function execute(?Carbon $start = null, ?Carbon $end = null)
{
$from = $end ? Carbon::today()->diff($end)->days : 0;
$to = $start ? Carbon::today()->diff($start)->days : 10;
for ($x = $from; $x <= $to; $x++) {
try {
$startDate = Carbon::today()->subDays($x);
$startLimit = Carbon::parse('01-12-2021');
if($startDate->isBefore($startLimit)){
$startDate = $startLimit;
}
$endDate = Carbon::today()->subDays($x - 1);
$orderRequest = $this->fetchesDataFRomYDPortal->clientRequest('http://www.yd-wl.com/api/GetOrderList.ashx', 'GET', [
'begintime' => $startDate->timestamp,
'endtime' => $endDate->timestamp,
]);
$rows = $this->fetchesDataFRomYDPortal->getResponseBody($orderRequest);
if(!$rows->data) continue;
foreach($rows->data as $row){
$time_start = microtime(true);
$receiveDate = Carbon::parse(substr(preg_replace("/[^0-9]/", "", $row->expressno), 0, 8));
$customerno = preg_split('(-|\(|\)|\/)', $row->customerno);
$orderNumber = $customerno[array_key_last($customerno)];
$allow_contract = true;
try {
$order = $this->fetchesOrder->execute(['reference' => $orderNumber]);
} catch (ResourceNotFoundException $exception) {
try {
$order = $this->fetchesOrder->execute(['reference' => substr($orderNumber, -9)]);
} catch (ResourceNotFoundException $exception) {
$order = $this->fetchesCompanyModule->execute(['id' => 1]);
$allow_contract = false;
}
}
$packingListReference = $row->expressno;
try{
$packingList = $this->fetchesPackingList->execute(['reference' => $row->expressno, 'type' => PackingListType::SHIPPING_PACKING_LIST]);
$packingList->packages()->delete();
$replica = $packingList->packingLists()->where('type', PackingListType::SHIPPING_PACKING_LIST_REPLICA)->first();
if($replica) $replica->packages()->delete();
$warehouseReceiveList = $this->fetchesPackingList->execute(['reference' => $row->expressno, 'type' => PackingListType::WAREHOUSE_RECEIVE_LIST]);
$warehouseReceiveList->packages()->delete();
$replica = $warehouseReceiveList->packingLists()->where('type', PackingListType::WAREHOUSE_RECEIVE_LIST_REPLICA)->first();
if($replica) $replica->packages()->delete();
} catch (ResourceNotFoundException $exception) {
if (!$allow_contract) {
$appointee_id = 2307;
} else {
$appointee_id = $order->orderRoles()->where('role_id', '=', OrderRoleTypes::ORIGIN_FREIGHT_FORWARDER)->first()->appointee->id;
}
$warehouseReceiveObject = new PackingListObject($packingListReference, $appointee_id, PackingListType::WAREHOUSE_RECEIVE_LIST, $allow_contract ? ApprovalStatus::APPROVED : ApprovalStatus::REJECTED);
/** @var PackingList $warehouseReceiveList */
$warehouseReceiveList = $this->createPackingListProcessor->execute($warehouseReceiveObject, $order);
$transportObject = new TransportObject(TransportType::LAND, null, $row->kuaidilist, Carbon::parse($receiveDate), Carbon::parse($receiveDate), $allow_contract ? ApprovalStatus::APPROVED : ApprovalStatus::REJECTED);
$transport = $this->createsTransport->execute($transportObject, $warehouseReceiveList);
if ($allow_contract) {
$contract = $this->unityCreateContract->execute();
$contractReference = $contract->hash_id;
$contractObligations = $contract->contract_obligation_list;
$this->unityActivateContract->execute($contractReference);
$supervisorHashId = $order->orderRoles()->where('role_id', '=', OrderRoleTypes::SUPERVISOR)->first()->appointee->unity_hash_id;
$supervisorContractEntity = $this->unityCreateContractEntity->execute($contractReference, $supervisorHashId);
$order->orderRoles()->where('role_id', '=', OrderRoleTypes::SUPERVISOR)->first()->update(['entity_hash_id' => $supervisorContractEntity->hash_id, 'entity_signature' => $supervisorContractEntity->entity_signature_hash_id]);
$importerContractEntity = $this->unityCreateContractEntity->execute($contractReference, $order->orderRoles()->where('role_id', '=', OrderRoleTypes::IMPORTER)->first()->appointee->unity_hash_id);
$order->orderRoles()->where('role_id', '=', OrderRoleTypes::IMPORTER)->first()->update(['entity_hash_id' => $importerContractEntity->hash_id, 'entity_signature' => $importerContractEntity->entity_signature_hash_id]);
$this->unityAssignContractEntity->execute($supervisorContractEntity->hash_id, $contractObligations);
}
$packingListObject = new PackingListObject($packingListReference, $appointee_id, PackingListType::SHIPPING_PACKING_LIST, ApprovalStatus::SUSPENDED, !$allow_contract ? null : $contractReference);
/** @var PackingList $packingList */
$packingList = $this->createPackingListProcessor->execute($packingListObject, $order);
if ($allow_contract) {
foreach ($contractObligations as $obligation) {
$stepObject = new StepsObject($order->orderRoles()->where('role_id', '=', OrderRoleTypes::SUPERVISOR)->first()->appointee->id, $obligation->reference, $obligation->sequence, $obligation->hash_id);
$this->createsStep->execute($packingList, $stepObject);
}
}
}
foreach($row->deliverysize as $package) {
$packageObject = new PackageObject(PackageType::CARTON, $row->goodname, (float) $package->width, (float) $package->height, (float) $package->length, 0, (float) $package->num, ApprovalStatus::APPROVED);
$this->createPackageProcessor->execute($packageObject, $warehouseReceiveList);
$this->createPackageProcessor->execute($packageObject, $packingList);
}
if(!count($row->deliverysize)){
$measurement = round(((float) $row->volume / (float) $row->goodcount) ** (1/3) * 100, 2);
$packageObject = new PackageObject(PackageType::CARTON, $row->goodname, (float) $measurement, (float) $measurement, (float) $measurement, 0, (float) $row->goodcount, ApprovalStatus::APPROVED);
$this->createPackageProcessor->execute($packageObject, $warehouseReceiveList);
$this->createPackageProcessor->execute($packageObject, $packingList);
}
$weightCbm = (float) $row->weight / 500;
$overWeightCbm = $weightCbm - $packingList->packages()->sum(DB::raw('(width/100) * (height/100) * (length/100) * quantity'));
if($overWeightCbm > 0){
$measurement = round($overWeightCbm ** (1/3) * 100, 2);
$packageObject = new PackageObject(PackageType::OVER_WEIGHT, 'Overweight CBM', (float) $measurement, (float) $measurement, (float) $measurement, 0, 1, ApprovalStatus::APPROVED);
$this->createPackageProcessor->execute($packageObject, $packingList);
}
if($order instanceof Order){
$marking = $order->companyModule->inviters()->withPivot('invitee_reference')->first()->pivot->invitee_reference;
if(!in_array($marking, ['1290CSW', '8997ITB', '3992WHE', '962LOW', '1152AAT'])){
$this->fetchesDataFRomYDPortal->clientRequest('http://www.yd-wl.com/api/confirmsendorder.ashx', 'GET', [
'expressno' => $row->expressno
]);
}
}
$time_end = microtime(true);
$execution_time = ($time_end - $time_start)/60;
echo 'successful => <b>Total Execution Time:</b> '.$execution_time.' Mins<br>';
}
} catch (\Exception $exception) {
Log::debug($exception);
}
}
}
}
@@ -152,7 +152,7 @@ class FetchWarehouseReceiveListFromVTPortalProcessor
} catch (ResourceNotFoundException $exception) {
$allow_contract = false;
$order = $this->fetchesCompanyModule->execute(['id' => 1]);
$appointee_id = 2037;
$appointee_id = 2307;
}
$packingListReference = $parcel[0];
@@ -0,0 +1,74 @@
<?php
namespace App\Classes\Modules\PerfexCRM\DataTransferObjects;
use Illuminate\Http\Request;
use App\Classes\General\Interfaces\DataTransferObject;
class CreateLeadPerfexCRMObject implements DataTransferObject
{
/** @var string */
private $name;
/** @var string */
private $email;
/** @var string */
private $phone;
/** @var string */
private $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;
}
/**
* @return string
*/
public function getName(): string
{
return $this->name;
}
/**
* @return string
*/
public function getEmail(): string
{
return $this->email;
}
/**
* @return string
*/
public function getPhone(): string
{
return $this->phone;
}
/**
* @return string
*/
public function getCompanyName(): string
{
return $this->companyName;
}
/**
* @return string
*/
public function getCompanyReference(): string
{
return $this->companyReference;
}
}
@@ -0,0 +1,161 @@
<?php
namespace App\Classes\Modules\PerfexCRM\DataTransferObjects;
use App\Classes\General\Interfaces\DataTransferObject;
class CreateTaskPerfexCRMObject implements DataTransferObject
{
/** @var string */
private $email;
/** @var string */
private $name;
/** @var string */
private $description;
/** @var string */
private $leadId;
/** @var string */
private $milestoneId;
/** @var string */
private $projectId;
/** @var string */
private $reference;
/** @var string */
private $onTaskCompletion;
/** @var string */
private $status;
/** @var string */
private $department;
/** @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;
$this->description = $description;
$this->leadId = $leadId;
$this->projectId = $projectId;
$this->milestoneId = $milestoneId;
$this->reference = $reference;
$this->onTaskCompletion = $onTaskCompletion;
$this->status = $status;
$this->department = $department;
$this->priority = $priority;
$this->duedate = $duedate;
}
/**
* @return string
*/
public function getEmail(): string
{
return $this->email;
}
/**
* @return string
*/
public function getName(): string
{
return $this->name;
}
/**
* @return string
*/
public function getDescription(): string
{
return $this->description;
}
/**
* @return string
*/
public function getLeadId(): string
{
return $this->leadId;
}
public function setLeadId(string $leadId)
{
$this->leadId = $leadId;
}
/**
* @return string
*/
public function getProjectId(): string
{
return $this->projectId;
}
/**
* @return string
*/
public function getMilestoneId(): string
{
return $this->milestoneId;
}
/**
* @return string
*/
public function getReference(): string
{
return $this->reference;
}
/**
* @return string
*/
public function getOnTaskCompletion(): string
{
return $this->onTaskCompletion;
}
/**
* @return string
*/
public function getStatus(): string
{
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;
}
}
@@ -0,0 +1,99 @@
<?php
namespace App\Classes\Modules\PerfexCRM\DataTransferObjects;
use Illuminate\Http\Request;
use App\Classes\General\Interfaces\DataTransferObject;
class CustomerContactObject implements DataTransferObject
{
/** @var int */
private $customerId;
/** @var string */
private $firstname;
/** @var string */
private $lastname;
/** @var string */
private $email;
/** @var string */
private $password;
/** @var string */
private $isPrimary;
/** @var string */
private $sendSetPasswordEmail;
public function __construct(string $customerId, string $firstname, string $lastname, string $email, string $password, string $isPrimary, string $sendSetPasswordEmail)
{
$this->customerId = $customerId;
$this->firstname = $firstname;
$this->lastname = $lastname;
$this->email = $email;
$this->password = $password;
$this->isPrimary = $isPrimary;
$this->sendSetPasswordEmail = $sendSetPasswordEmail;
}
/**
* @return int
*/
public function getCustomerId(): int
{
return $this->customerId;
}
/**
* @return string
*/
public function getFirstName(): string
{
return $this->firstname;
}
/**
* @return string
*/
public function getLastName(): string
{
return $this->lastname;
}
/**
* @return string
*/
public function getEmail(): string
{
return $this->email;
}
/**
* @return string
*/
public function getPassword(): string
{
return $this->password;
}
/**
* @return string
*/
public function getIsPrimary(): string
{
return $this->isPrimary;
}
/**
* @return string
*/
public function getSendSetPasswordEmail(): string
{
return $this->sendSetPasswordEmail;
}
}
@@ -0,0 +1,124 @@
<?php
namespace App\Classes\Modules\PerfexCRM\DataTransferObjects;
use Illuminate\Http\Request;
use App\Classes\General\Interfaces\DataTransferObject;
class InitialPerfexCRMObject implements DataTransferObject
{
/** @var string */
private $companyName;
/** @var string */
private $companyReference;
/** @var string */
private $contactName;
/** @var string */
private $contactEmail;
/** @var string */
private $bookingMarking;
/** @var string */
private $projectName;
/** @var int */
private $projectStatus;
/** @var array */
private $milestoneNames;
/** @var array */
private $taskNames;
public function __construct(string $companyName, string $companyReference, string $contactName, string $contactEmail, string $bookingMarking, string $projectName, int $projectStatus, array $milestoneNames, array $taskNames)
{
$this->companyName = $companyName;
$this->companyReference = $companyReference;
$this->contactName = $contactName;
$this->contactEmail = $contactEmail;
$this->bookingMarking = $bookingMarking;
$this->projectName = $projectName;
$this->projectStatus = $projectStatus;
$this->milestoneNames = $milestoneNames;
$this->taskNames = $taskNames;
}
/**
* @return string
*/
public function getCompanyName(): string
{
return $this->companyName;
}
/**
* @return string
*/
public function getCompanyReference(): string
{
return $this->companyReference;
}
/**
* @return string
*/
public function getContactName(): string
{
return $this->contactName;
}
/**
* @return string
*/
public function getContactEmail(): string
{
return $this->contactEmail;
}
/**
* @return string
*/
public function getBookingMarking(): string
{
return $this->bookingMarking;
}
/**
* @return string
*/
public function getProjectName(): string
{
return $this->projectName;
}
/**
* @return string
*/
public function getProjectStatus(): int
{
return $this->projectStatus;
}
/**
* @return array
*/
public function getMilestoneNames(): array
{
return $this->milestoneNames;
}
/**
* @return array
*/
public function getTaskNames(): array
{
return $this->taskNames;
}
}
@@ -0,0 +1,86 @@
<?php
namespace App\Classes\Modules\PerfexCRM\DataTransferObjects;
use Illuminate\Http\Request;
use App\Classes\General\Interfaces\DataTransferObject;
class InvoicePaymentPerfexCRMObject implements DataTransferObject
{
/** @var int */
private $invoiceId;
/** @var float */
private $amount;
/** @var string */
private $date;
/** @var int */
private $paymentMode;
/** @var string */
private $transactionId;
/** @var string */
private $note;
public function __construct(int $invoiceId, float $amount, string $date, int $paymentMode, string $transactionId, string $note)
{
$this->invoiceId = $invoiceId;
$this->amount = $amount;
$this->date = $date;
$this->paymentMode = $paymentMode;
$this->transactionId = $transactionId;
$this->note = $note;
}
/**
* @return int
*/
public function getInvoiceId(): int
{
return $this->invoiceId;
}
/**
* @return float
*/
public function getAmount(): float
{
return $this->amount;
}
/**
* @return string
*/
public function getDate(): string
{
return $this->date;
}
/**
* @return int
*/
public function getPaymentMode(): int
{
return $this->paymentMode;
}
/**
* @return string
*/
public function getTransactionId(): string
{
return $this->transactionId;
}
/**
* @return string
*/
public function getNote(): string
{
return $this->note;
}
}
@@ -0,0 +1,145 @@
<?php
namespace App\Classes\Modules\PerfexCRM\DataTransferObjects;
use Illuminate\Http\Request;
use App\Classes\General\Interfaces\DataTransferObject;
class InvoicePerfexCRMObject implements DataTransferObject
{
/** @var string */
private $clientId;
/** @var string */
private $number;
/** @var string */
private $date;
/** @var string */
private $dueDate;
/** @var string */
private $currency;
/** @var float */
private $subTotal;
/** @var float */
private $total;
/** @var string */
private $billingStreet;
/** @var string */
private $projectId;
/** @var array */
private $allowedPaymentModes;
/** @var array */
private $invoiceItems;
public function __construct(string $clientId, string $number, string $date, string $dueDate, string $currency, float $subTotal, float $total, string $billingStreet, string $projectId, array $allowedPaymentModes, array $invoiceItems)
{
$this->clientId = $clientId;
$this->number = $number;
$this->date = $date;
$this->dueDate = $dueDate;
$this->currency = $currency;
$this->subTotal = $subTotal;
$this->total = $total;
$this->billingStreet = $billingStreet;
$this->projectId = $projectId;
$this->allowedPaymentModes = $allowedPaymentModes;
$this->invoiceItems = $invoiceItems;
}
/**
* @return string
*/
public function getClientId(): string
{
return $this->clientId;
}
/**
* @return string
*/
public function getNumber(): string
{
return $this->number;
}
/**
* @return string
*/
public function getDate(): string
{
return $this->date;
}
/**
* @return string
*/
public function getDueDate(): string
{
return $this->dueDate;
}
/**
* @return string
*/
public function getCurrency(): string
{
return $this->currency;
}
/**
* @return float
*/
public function getSubTotal(): float
{
return $this->subTotal;
}
/**
* @return float
*/
public function getTotal(): float
{
return $this->total;
}
/**
* @return string
*/
public function getBillingStreet(): string
{
return $this->billingStreet;
}
/**
* @return string
*/
public function getProjectId(): string
{
return $this->projectId;
}
/**
* @return array
*/
public function getAllowedPaymentModes(): array
{
return $this->allowedPaymentModes;
}
/**
* @return array
*/
public function getInvoiceItems(): array
{
return $this->invoiceItems;
}
}
@@ -0,0 +1,86 @@
<?php
namespace App\Classes\Modules\PerfexCRM\DataTransferObjects;
use Illuminate\Http\Request;
use App\Classes\General\Interfaces\DataTransferObject;
class InvoiceSingleItemPerfexCRMObject implements DataTransferObject
{
/** @var string */
public $description;
/** @var string */
public $longDescription;
/** @var float */
public $qty;
/** @var float */
public $rate;
/** @var int */
public $order;
/** @var string */
public $unit;
public function __construct(string $description, string $longDescription, float $qty, float $rate, int $order, string $unit)
{
$this->description = $description;
$this->longDescription = $longDescription;
$this->qty = $qty;
$this->rate = $rate;
$this->order = $order;
$this->unit = $unit;
}
/**
* @return string
*/
public function getDescription(): string
{
return $this->description;
}
/**
* @return string
*/
public function getLongDescription(): string
{
return $this->longDescription;
}
/**
* @return float
*/
public function getQty(): float
{
return $this->qty;
}
/**
* @return float
*/
public function getRate(): float
{
return $this->rate;
}
/**
* @return int
*/
public function getOrder(): int
{
return $this->order;
}
/**
* @return string
*/
public function getUnit(): string
{
return $this->unit;
}
}
@@ -0,0 +1,50 @@
<?php
namespace App\Classes\Modules\PerfexCRM\DataTransferObjects;
use Illuminate\Http\Request;
use App\Classes\General\Interfaces\DataTransferObject;
use App\Models\Transaction;
class UpdatePerfexCRMInvoiceObject implements DataTransferObject
{
/** @var string */
private $email;
/** @var Transaction */
private $transaction;
/** @var bool */
private $isPaid;
public function __construct(string $email, Transaction $transaction, bool $isPaid)
{
$this->email = $email;
$this->transaction = $transaction;
$this->isPaid = $isPaid;
}
/**
* @return string
*/
public function getEmail(): string
{
return $this->email;
}
/**
* @return Transaction
*/
public function getTransaction(): Transaction
{
return $this->transaction;
}
/**
* @return bool
*/
public function getIsPaid(): bool
{
return $this->isPaid;
}
}
@@ -0,0 +1,128 @@
<?php
namespace App\Classes\Modules\PerfexCRM\DataTransferObjects;
use Illuminate\Http\Request;
use App\Classes\General\Interfaces\DataTransferObject;
class UpdatePerfexCRMObject implements DataTransferObject
{
/** @var string */
private $companyName;
/** @var string */
private $companyReference;
/** @var string */
private $contactName;
/** @var string */
private $contactEmail;
/** @var string */
private $bookingMarking;
/** @var string */
private $projectName;
/** @var int */
private $projectStatus;
/** @var array */
private $milestoneNames;
/** @var array */
private $tasks;
public function __construct(string $companyName, string $companyReference, string $contactName, string $contactEmail, string $bookingMarking, string $projectName, int $projectStatus, array $milestoneNames, array $tasks)
{
$this->companyName = $companyName;
$this->companyReference = $companyReference;
$this->contactName = $contactName;
$this->contactEmail = $contactEmail;
$this->bookingMarking = $bookingMarking;
$this->projectName = $projectName;
$this->projectStatus = $projectStatus;
$this->milestoneNames = $milestoneNames;
$this->tasks = $tasks;
}
/**
* @return string
*/
public function getCompanyName(): string
{
return $this->companyName;
}
/**
* @return string
*/
public function getCompanyReference(): string
{
return $this->companyReference;
}
/**
* @return string
*/
public function getContactName(): string
{
return $this->contactName;
}
/**
* @return string
*/
public function getContactEmail(): string
{
return $this->contactEmail;
}
/**
* @return string
*/
public function getBookingMarking(): string
{
return $this->bookingMarking;
}
/**
* @return string
*/
public function getProjectName(): string
{
return $this->projectName;
}
/**
* @return int
*/
public function getProjectStatus(): int
{
return $this->projectStatus;
}
/**
* @return array
*/
public function getMilestoneNames(): array
{
return $this->milestoneNames;
}
/**
* @return array
*/
public function getTasks(): array
{
return $this->tasks;
}
public function setTasks($tasks)
{
$this->tasks = $tasks;
}
}
@@ -0,0 +1,178 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Processors;
use App\Models\Transaction;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMInvoice;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMInvoicePayment;
use App\Classes\Modules\PerfexCRM\Services\ConvertsPerfexCRMLeadToCustomer;
use App\Classes\Modules\PerfexCRM\Services\FetchesPerfexCRMProject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\InvoicePerfexCRMObject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\InvoicePaymentPerfexCRMObject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\InvoiceSingleItemPerfexCRMObject;
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
{
/** @var CreatesPerfexCRMInvoice */
private $createsPerfexCRMInvoice;
/** @var CreatesPerfexCRMInvoicePayment */
private $createsPerfexCRMInvoicePayment;
/** @var ConvertsPerfexCRMLeadToCustomer */
private $convertsPerfexCRMLeadToCustomer;
/** @var FetchesPerfexCRMProject */
private $fetchesPerfexCRMProject;
/** @var CreatesPerfexCRMCustomerProject */
private $createsPerfexCRMCustomerProject;
/**
* CreatePerfexCRMInvoiceProcessor constructor.
* @param CreatesPerfexCRMInvoice $createsPerfexCRMInvoice
*/
public function __construct(CreatesPerfexCRMInvoice $createsPerfexCRMInvoice,
CreatesPerfexCRMInvoicePayment $createsPerfexCRMInvoicePayment,
ConvertsPerfexCRMLeadToCustomer $convertsPerfexCRMLeadToCustomer,
FetchesPerfexCRMProject $fetchesPerfexCRMProject,
CreatesPerfexCRMCustomerProject $createsPerfexCRMCustomerProject)
{
$this->createsPerfexCRMInvoice = $createsPerfexCRMInvoice;
$this->createsPerfexCRMInvoicePayment = $createsPerfexCRMInvoicePayment;
$this->convertsPerfexCRMLeadToCustomer = $convertsPerfexCRMLeadToCustomer;
$this->fetchesPerfexCRMProject = $fetchesPerfexCRMProject;
$this->createsPerfexCRMCustomerProject = $createsPerfexCRMCustomerProject;
}
/**
* @param Transaction $transaction
* @param bool $isPaid, default: false
* @return null|object
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(Transaction $transaction, bool $isPaid = false) {
$clientId = "";
$number = $transaction->bill_no;
$prefix = "INV-";
//This will remove the prefix if prefix already exist in the string
if (substr($number, 0, strlen($prefix)) == $prefix) {
$number = substr($number, strlen($prefix));
}
$date = Carbon::parse($transaction->created_at)->format('Y-m-d');
$dueDate = Carbon::parse($transaction->created_at)->addDays(6)->startOfDay()->format('Y-m-d');
$currency = 1;
$subTotal = 0.00;
$total = 0.00;
$companyModule = $transaction->owner->owner->companyModule;
$billingStreet = "";
$addresses = $companyModule
->addresses()
->where('status', '=', \App\Classes\ValueObjects\Constants\ApprovalStatus::APPROVED)
->where('type', '=', \App\Classes\ValueObjects\Constants\AddressType::BILLING)->first();
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 = [];
$employee = $companyModule->employees()->first();
$email = $employee->email;
$result = $this->convertsPerfexCRMLeadToCustomer->execute($email);
if(isset($result->payload)){
$clientId = $result->payload['client_id'];
}
//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;
$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);
if(isset($result->payload)){ //Here means project creation successful
$projectId = $result->payload['project_id'];
}
}
}
if($projectId == ""){
Log::error(json_encode('CreatePerfexCRMInvoiceProcessor debug: '.$projectName));
Log::error(json_encode($transaction->owner));
}
}
//newitems
foreach ($transaction->transactionDetails as $key => $transaction_detail){
$order = $key + 1;
$description = $transaction_detail->name;
$quantity = $transaction_detail->quantity;
$unitPrice = $transaction_detail->price;
$subTotal = $subTotal + $transaction_detail->amount;
//string $description, string $longDescription, int $qty, int $rate, int $order, string $unit
$invoiceSingleItem = new InvoiceSingleItemPerfexCRMObject(
$description,
"",
$quantity,
$unitPrice,
$order,
""
);
array_push($invoiceItems, $invoiceSingleItem);
}
$total = $transaction->amount;
//This setting is similar to Setup > Leads > Sources, Setup > Leads > Statuses
//Can be found at Finance > Payment Modes
array_push($allowedPaymentModes, 1, 2);
$invoicePerfexCRMObject = new InvoicePerfexCRMObject(
$clientId,
$number,
$date,
$dueDate,
$currency,
$subTotal,
$total,
$billingStreet,
$projectId,
$allowedPaymentModes,
$invoiceItems
);
$result = $this->createsPerfexCRMInvoice->execute($invoicePerfexCRMObject);
return $result;
}
}
@@ -0,0 +1,36 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Processors;
// use App\Classes\Modules\PerfexCRM\DataTransferObjects\ContactObject;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMLead;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CreateLeadPerfexCRMObject;
class CreatePerfexCRMLeadProcessor
{
/** @var CreatesPerfexCRMLead */
private $createsPerfexCRMLead;
/**
* CreatePerfexCRMLeadProcessor constructor.
* @param CreatesPerfexCRMLead $createsPerfexCRMLead
*/
public function __construct(CreatesPerfexCRMLead $createsPerfexCRMLead)
{
$this->createsPerfexCRMLead = $createsPerfexCRMLead;
}
/**
* @param CreateLeadPerfexCRMObject $createLeadPerfexCRMObject
* @return null|object
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(CreateLeadPerfexCRMObject $createLeadPerfexCRMObject) {
return $this->createsPerfexCRMLead->execute($createLeadPerfexCRMObject);
}
}
@@ -0,0 +1,44 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Processors;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMTask;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CreateTaskPerfexCRMObject;
class CreatePerfexCRMTaskProcessor
{
/** @var CreatesPerfexCRMTask */
private $createsPerfexCRMTask;
/**
* @param CreatesPerfexCRMTask $createsPerfexCRMTask
*/
public function __construct(CreatesPerfexCRMTask $createsPerfexCRMTask)
{
$this->createsPerfexCRMTask = $createsPerfexCRMTask;
}
/**
* @param CreateTaskPerfexCRMObject $createTaskPerfexCRMObject
* @return true
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(CreateTaskPerfexCRMObject $createTaskPerfexCRMObject) {
$this->createsPerfexCRMTask->execute(
$createTaskPerfexCRMObject->getName(),
$createTaskPerfexCRMObject->getDescription(),
$createTaskPerfexCRMObject->getLeadId(),
$createTaskPerfexCRMObject->getMilestoneId(),
$createTaskPerfexCRMObject->getProjectId(),
$createTaskPerfexCRMObject->getReference(),
$createTaskPerfexCRMObject->getOnTaskCompletion(),
$createTaskPerfexCRMObject->getDepartment(),
$createTaskPerfexCRMObject->getStatus(),
$createTaskPerfexCRMObject->getPriority(),
$createTaskPerfexCRMObject->getDuedate()
);
return true;
}
}
@@ -0,0 +1,43 @@
<?php
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;
class NewLeadTaskToPerfexCRMProcessor
{
/**
* @param Company $company
* @return true
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(Company $company)
{
$companyModule = $company->companyModules()->first();
$employee = $companyModule->employees()->first();
$contactEmail = $employee->email;
$createTaskPerfexCRMObject = new CreateTaskPerfexCRMObject(
$contactEmail,
PerfexCRMTasks::TASK_IDENTIFICATION_1['name'],
PerfexCRMTasks::TASK_IDENTIFICATION_1['description'],
"",
"",
"",
"",
"",
PerfexCRMTasks::TASK_IDENTIFICATION_1['status'],
PerfexCRMTasks::TASK_IDENTIFICATION_1['department'],
PerfexCRMTaskPriority::DEFAULT,
"0"
);
CreatePerfexCRMSingleTask::dispatch($createTaskPerfexCRMObject);
return true;
}
}
@@ -0,0 +1,60 @@
<?php
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
{
/**
* @param PackingList $packingList
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(PackingList $packingList)
{
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,
]
);
UpdatePerfexCRMPrelude::dispatch($packingList, null, $updatePerfexCRMObject, UpdatePerfexCRM::class);
}
} catch (\Exception $exception){
Log::error(json_encode('PackingListToPerfexCRMProcessor debug:'));
Log::error(json_encode($packingList));
Log::error($exception);
}
return true;
}
}
@@ -0,0 +1,107 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Processors;
use App\Classes\Modules\PerfexCRM\Processors\UpdatePerfexCRMProcessor;
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;
/**
* TransactionToPerfexCRMProcessor constructor.
* @param UpdatePerfexCRMProcessor $updatePerfexCRMProcessor
* @param FetchesCompany $fetchesCompany
*/
public function __construct(UpdatePerfexCRMProcessor $updatePerfexCRMProcessor, FetchesCompany $fetchesCompany)
{
$this->updatePerfexCRMProcessor = $updatePerfexCRMProcessor;
$this->fetchesCompany = $fetchesCompany;
}
/**
* @param Transaction $model
* @param int $status
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(Transaction $model, int $status)
{
try
{
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;
$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,
]
);
UpdatePerfexCRMPrelude::dispatch(null, $model, $updatePerfexCRMObject, UpdatePerfexCRM::class);
$updatePerfexCRMInvoiceOject = new UpdatePerfexCRMInvoiceObject(
$contactEmail,
$model,
true
);
UpdatePerfexCRMInvoice::dispatch($updatePerfexCRMInvoiceOject)->delay(6);
}
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;
}
}
@@ -0,0 +1,227 @@
<?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\UpdatesPerfexCRMTask;
use App\Classes\Modules\PerfexCRM\Services\UpdatesPerfexCRMCustomer;
use App\Classes\Modules\PerfexCRM\Services\UpdatesPerfexCRMProject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CustomerContactObject;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\UpdatePerfexCRMObject;
use App\Classes\ValueObjects\Constants\PerfexCRMTaskStatus;
use App\Classes\ValueObjects\Constants\PerfexCRMProjectStatus;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\Http\Request;
class UpdatePerfexCRMProcessor
{
/** @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 UpdatesPerfexCRMTask */
private $updatesPerfexCRMTask;
/** @var UpdatesPerfexCRMCustomer */
private $updatesPerfexCRMCustomer;
/** @var UpdatesPerfexCRMProject */
private $updatesPerfexCRMProject;
/**
* @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 UpdatesPerfexCRMTask $updatesPerfexCRMTask
* @param UpdatesPerfexCRMCustomer $updatesPerfexCRMCustomer
* @param UpdatesPerfexCRMProject $updatesPerfexCRMProject
*/
public function __construct(ConvertsPerfexCRMLeadToCustomer $convertsPerfexCRMLeadToCustomer,
CreatesPerfexCRMCustomerProject $createsPerfexCRMCustomerProject,
CreatesPerfexCRMMilestone $createsPerfexCRMMilestone,
CreatesPerfexCRMTask $createsPerfexCRMTask,
FetchesPerfexCRMProject $fetchesPerfexCRMProject,
FetchesPerfexCRMMilestone $fetchesPerfexCRMMilestone,
FetchesPerfexCRMTask $fetchesPerfexCRMTask,
CreatesPerfexCRMCustomer $createsPerfexCRMCustomer,
CreatesPerfexCRMCustomerContact $createsPerfexCRMCustomerContact,
UpdatesPerfexCRMTask $updatesPerfexCRMTask,
UpdatesPerfexCRMCustomer $updatesPerfexCRMCustomer,
UpdatesPerfexCRMProject $updatesPerfexCRMProject)
{
$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->updatesPerfexCRMTask = $updatesPerfexCRMTask;
$this->updatesPerfexCRMCustomer = $updatesPerfexCRMCustomer;
$this->updatesPerfexCRMProject = $updatesPerfexCRMProject;
}
/**
* @param UpdatePerfexCRMObject $updatePerfexCRMObject
* @return null|object
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(UpdatePerfexCRMObject $updatePerfexCRMObject) {
// 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 = $updatePerfexCRMObject->getCompanyName();
$result = $this->convertsPerfexCRMLeadToCustomer->execute($updatePerfexCRMObject->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,
$updatePerfexCRMObject->getContactName(),
$updatePerfexCRMObject->getContactName(),
$updatePerfexCRMObject->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'] === $updatePerfexCRMObject->getCompanyReference()) {
$value_exists = true;
break;
}
}
}
if(!$value_exists);
{
$result = $this->updatesPerfexCRMCustomer->execute($crmClientId, $crmCompany, $updatePerfexCRMObject->getCompanyReference());
}
// Get existing or create project, project has to exist first before milestone can appear under it
$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 && $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->getTasks();
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->fetchesPerfexCRMMilestone->execute($tasks[$count]['milestone'], $projectId);
if(isset($result->payload)){
$array = json_decode(json_encode($result->payload[0]), true);
$milestoneId = $array['id'];
}
else{
$result = $this->createsPerfexCRMMilestone->execute($tasks[$count]['milestone'], $projectId, $count);
if(isset($result->payload)){
$milestoneId = $result->payload['milestone_id'];
}
}
}
$taskStatus = PerfexCRMTaskStatus::NOT_STARTED;
if($tasks[$count]['status'] != ''){
$taskStatus = $tasks[$count]['status'];
}
// Get existing or create task
$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;
}
}
@@ -0,0 +1,34 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
class ConvertsPerfexCRMLeadToCustomer
{
/**
* @param string $email
* @return null|object
* @throws MalformedRequestException
*/
public function execute(string $email) {
try{
$response = Http::withHeaders([
'authtoken' => config('perfexcrm.api_key'),])
->get(config('perfexcrm.base_url').'/api/leads/convertocustomer/'.$email);
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());
}
}
}
@@ -0,0 +1,37 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
class CreatesPerfexCRMCustomer
{
/**
* @param string $companyName
* @return null|object
* @throws MalformedRequestException
*/
public function execute(string $companyName) {
try{
$data = [
'company' => $companyName
];
$response = Http::asForm()->withHeaders([
'authtoken' => config('perfexcrm.api_key')])
->post(config('perfexcrm.base_url').'/api/customers',$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());
}
}
}
@@ -0,0 +1,44 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Services;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CustomerContactObject;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
class CreatesPerfexCRMCustomerContact
{
/**
* @param CustomerContactObject $customerContactObject
* @return null|object
* @throws MalformedRequestException
*/
public function execute(CustomerContactObject $customerContactObject) {
try{
$data = [
'customer_id' => $customerContactObject->getCustomerId(),
'firstname' => $customerContactObject->getFirstName(),
'lastname' => $customerContactObject->getLastName(),
'email' => $customerContactObject->getEmail(), //$email
'password' => $customerContactObject->getPassword(),
'is_primary' => $customerContactObject->getIsPrimary(),
//'send_set_password_email' => $customerContactObject->getSendSetPasswordEmail(),
];
$response = Http::asForm()->withHeaders([
'authtoken' => config('perfexcrm.api_key')])
->post(config('perfexcrm.base_url').'/api/contacts',$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());
}
}
}
@@ -0,0 +1,43 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
class CreatesPerfexCRMCustomerProject
{
/**
* @param string $projectName
* @param string $clientId
* @return null|object
* @throws MalformedRequestException
*/
public function execute(string $projectName, int $status, string $clientId) {
try{
$data = [
'name' => $projectName,
'rel_type' => 'customer',
'billing_type' => 1,
'clientid' => $clientId,
'start_date' => date('Y-m-d'),
'status' => $status
];
$response = Http::asForm()->withHeaders([
'authtoken' => config('perfexcrm.api_key')])
->post(config('perfexcrm.base_url').'/api/projects',$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());
}
}
}
@@ -0,0 +1,63 @@
<?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\Modules\PerfexCRM\DataTransferObjects\InvoicePerfexCRMObject;
class CreatesPerfexCRMInvoice
{
/**
* @param InvoicePerfexCRMObject $invoicePerfexCRMObject
* @return null|object
* @throws MalformedRequestException
*/
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($subtotal, 2, '.', ''),
'total' => number_format($total, 2, '.', ''),
'billing_street' => $invoicePerfexCRMObject->getBillingStreet(),
'project_id' => $invoicePerfexCRMObject->getProjectId(),
'allowed_payment_modes[0]' => 1,
'allowed_payment_modes[1]' => 2,
];
for($count=0; $count < count($invoicePerfexCRMObject->getInvoiceItems()); $count++) {
$oneItem = [
"newitems[".$count."][description]" => $invoicePerfexCRMObject->getInvoiceItems()[$count]->description,
"newitems[".$count."][long_description]" => $invoicePerfexCRMObject->getInvoiceItems()[$count]->longDescription,
"newitems[".$count."][qty]" => $invoicePerfexCRMObject->getInvoiceItems()[$count]->qty,
"newitems[".$count."][rate]" => $invoicePerfexCRMObject->getInvoiceItems()[$count]->rate,
"newitems[".$count."][order]" => $invoicePerfexCRMObject->getInvoiceItems()[$count]->order,
"newitems[".$count."][unit]" => $invoicePerfexCRMObject->getInvoiceItems()[$count]->unit,
];
$data = array_merge($data, $oneItem);
}
$response = Http::asForm()->withHeaders([
'authtoken' => config('perfexcrm.api_key')])
->post(config('perfexcrm.base_url').'/api/invoices',$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());
}
}
}
@@ -0,0 +1,43 @@
<?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\Modules\PerfexCRM\DataTransferObjects\InvoicePaymentPerfexCRMObject;
class CreatesPerfexCRMInvoicePayment
{
/**
* @param InvoicePaymentPerfexCRMObject $invoicePaymentPerfexCRMObject
* @return null|object
* @throws MalformedRequestException
*/
public function execute(InvoicePaymentPerfexCRMObject $invoicePaymentPerfexCRMObject) {
try{
$data = [
'invoiceid' => $invoicePaymentPerfexCRMObject->getInvoiceId(),
'amount' => number_format($invoicePaymentPerfexCRMObject->getAmount(), 2, '.', ''),
'date' => $invoicePaymentPerfexCRMObject->getDate(),
'paymentmode' => $invoicePaymentPerfexCRMObject->getPaymentMode(),
'transactionid' => $invoicePaymentPerfexCRMObject->getTransactionId(),
'note' => $invoicePaymentPerfexCRMObject->getNote(),
];
$response = Http::asForm()->withHeaders([
'authtoken' => config('perfexcrm.api_key')])
->post(config('perfexcrm.base_url').'/api/invoices/recordpayment',$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());
}
}
}
@@ -0,0 +1,50 @@
<?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\Modules\PerfexCRM\DataTransferObjects\CreateLeadPerfexCRMObject;
class CreatesPerfexCRMLead
{
/**
* @param CreateLeadPerfexCRMObject $createLeadPerfexCRMObject
* @return null|object
* @throws MalformedRequestException
*/
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
'custom_fields' => $custom_fields
];
$response = Http::asForm()->withHeaders([
'authtoken' => config('perfexcrm.api_key')])
->post(config('perfexcrm.base_url').'/api/leads/byemail',$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());
}
}
}
@@ -0,0 +1,46 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
class CreatesPerfexCRMMilestone
{
/**
* @param string $$milestoneName
* @param string $projectId
* @param string $milestoneOrder
* @return null|object
* @throws MalformedRequestException
*/
public function execute(string $milestoneName, string $projectId, string $milestoneOrder = "") {
try{
$data = [
'name' => $milestoneName,
'project_id' => $projectId,
'due_date' => date('Y-m-d'),
'start_date' => date('Y-m-d')
];
if($milestoneOrder != ""){
$data['milestone_order'] = $milestoneOrder;
}
$response = Http::asForm()->withHeaders([
'authtoken' => config('perfexcrm.api_key')])
->post(config('perfexcrm.base_url').'/api/milestones',$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());
}
}
}
@@ -0,0 +1,87 @@
<?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 CreatesPerfexCRMTask
{
/**
* @param string $taskName
* @param string $taskDescription
* @param string $leadId
* @param string $milestoneId
* @param string $projectId
* @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 $department, string $status, string $priority, string $duedate) {
try{
$custom_fields = [];
if($department != ""){
$custom_fields = [
"tasks" => [
PerfexCRMCustomFields::TASKS_DEPARTMENT => $department
]
];
}
$data = [
'name' => $taskName,
'description' => $taskDescription,
'milestone' => $milestoneId,
'startdate' => date('Y-m-d'),
'rel_type' => 'project',
'rel_id' => $projectId,
'status' => $status,
'is_system_created' => 1,
'reference' => $reference,
'on_task_completion' => $on_task_completion,
'custom_fields' => $custom_fields,
'priority' => $priority,
'duedate' => date('Y-m-d', strtotime('+' . $duedate . ' days')),
];
if($leadId != '') {
$data = [
'name' => $taskName,
'description' => $taskDescription,
'milestone' => $milestoneId,
'startdate' => date('Y-m-d'),
'rel_type' => 'lead',
'rel_id' => $leadId,
'status' => $status,
'is_system_created' => 1,
'reference' => $reference,
'on_task_completion' => $on_task_completion,
'custom_fields' => $custom_fields,
'priority' => $priority,
'duedate' => date('Y-m-d', strtotime('+' . $duedate . ' days')),
];
}
$response = Http::asForm()->withHeaders([
'authtoken' => config('perfexcrm.api_key')])
->post(config('perfexcrm.base_url').'/api/tasks',$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());
}
}
}
@@ -0,0 +1,34 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
class FetchesPerfexCRMCustomer
{
/**
* @param string $email
* @return null|object
* @throws MalformedRequestException
*/
public function execute(string $email) {
try{
$response = Http::withHeaders([
'authtoken' => config('perfexcrm.api_key'),])
->get(config('perfexcrm.base_url').'/api/customers/byemail/'.$email);
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());
}
}
}
@@ -0,0 +1,36 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
class FetchesPerfexCRMInvoice
{
/**
* @param string $clientId
* @param string $invoicePrefix
* @param string $invoiceNumber
* @return null|object
* @throws MalformedRequestException
*/
public function execute(string $clientId, string $invoicePrefix, string $invoiceNumber) {
try{
$response = Http::withHeaders([
'authtoken' => config('perfexcrm.api_key'),])
->get(config('perfexcrm.base_url').'/api/invoices/customsearch/'.$clientId.'/'.$invoicePrefix.'/'.$invoiceNumber);
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());
}
}
}
@@ -0,0 +1,34 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
class FetchesPerfexCRMLead
{
/**
* @param string $email
* @return null|object
* @throws MalformedRequestException
*/
public function execute(string $email) {
try{
$response = Http::withHeaders([
'authtoken' => config('perfexcrm.api_key'),])
->get(config('perfexcrm.base_url').'/api/leads/byemail/'.$email);
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());
}
}
}
@@ -0,0 +1,40 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
class FetchesPerfexCRMMilestone
{
/**
* @param string $milestoneName
* @param string $projectId
* @return null|object
* @throws MalformedRequestException
*/
public function execute(string $milestoneName, string $projectId) {
try{
$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();
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());
}
}
}
@@ -0,0 +1,40 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
class FetchesPerfexCRMProject
{
/**
* @param string $projectName
* @param string $clientId
* @return null|object
* @throws MalformedRequestException
*/
public function execute(string $projectName, string $clientId) {
try{
$data = [
'name' => $projectName,
'clientid' => $clientId,
];
$response = Http::asForm()->withHeaders([
'authtoken' => config('perfexcrm.api_key')])
->post(config('perfexcrm.base_url').'/api/projects/bynameandclientid', $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());
}
}
}
@@ -0,0 +1,48 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
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, string $relType, string $relId) {
try{
$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);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
}
}
@@ -0,0 +1,47 @@
<?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 UpdatesPerfexCRMCustomer
{
/**
* @param string $customerId
* @param string $companyReference
* @return null|object
* @throws MalformedRequestException
*/
public function execute(string $customerId, string $companyName, string $companyReference) {
try{
$custom_fields = [
"customers" => [
PerfexCRMCustomFields::CUSTOMERS_SHIPPING_PORTAL_REFERENCE => $companyReference
]
];
$data = [
'company' => $companyName,
'custom_fields' => $custom_fields
];
$response = Http::asJson()->withHeaders([
'authtoken' => config('perfexcrm.api_key')])
->put(config('perfexcrm.base_url').'/api/customers/'.$customerId, $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());
}
}
}
@@ -0,0 +1,70 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
class UpdatesPerfexCRMInvoice
{
/**
* @param $invoice
* @param string $projectId
* @return null|object
* @throws MalformedRequestException
*/
public function execute($invoice, string $projectId) {
try{
// <p>The Invoice number field is required.<\/p>
// <p>The Invoice date field is required.<\/p>
// <p>The Currency field is required.<\/p>
// <p>The Items field is required.<\/p>
// <p>The Allow Payment Mode field is required.<\/p>
// <p>The Billing Street field is required.<\/p>
// <p>The Sub Total field is required.<\/p>
// <p>The Total field is required.<\/p>
$newInvoiceItems = [];
foreach ($invoice->items as $item) {
$item['itemid'] = $item['id'];
unset($item['id']);
$item['order'] = $item['item_order'];
unset($item['item_order']);
array_push($newInvoiceItems,$item);
}
$allowedPaymentModes = [];
array_push($allowedPaymentModes, 1, 2);
$data = [
'number' => $invoice->number,
'date' => $invoice->date,
'duedate' => $invoice->duedate,
'currency' => $invoice->currency,
'subtotal' => $invoice->subtotal,
'total' => $invoice->total,
'billing_street' => $invoice->billing_street,
'shipping_street' => $invoice->billing_street,
'project_id' => $projectId,
'items' => $newInvoiceItems,
'allowed_payment_modes' => $allowedPaymentModes,
];
$response = Http::asJson()->withHeaders([
'authtoken' => config('perfexcrm.api_key')])
->put(config('perfexcrm.base_url').'/api/invoices/'.$invoice->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());
}
}
}
@@ -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());
}
}
}
@@ -0,0 +1,43 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
class UpdatesPerfexCRMProject
{
/**
* @param $project
* @param int $status
* @return null|object
* @throws MalformedRequestException
*/
public function execute($project, int $status) {
try{
$data = [
'name' => $project['name'],
'clientid' => $project['clientid'],
// 'rel_type' => 'customer',
'billing_type' => 1,
'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);
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());
}
}
}
@@ -0,0 +1,48 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
class UpdatesPerfexCRMTask
{
/**
* @param string $taskName
* @param string $milestoneId
* @param string $projectId
* @param string $status, default: 1
* @return null|object
* @throws MalformedRequestException
*/
public function execute(string $taskId, string $taskName, string $milestoneId, string $projectId, string $status = "1") {
try{
$data = [
'name' => $taskName,
'milestone' => $milestoneId,
'startdate' => date('Y-m-d'),
'duedate' => date('Y-m-d'),
'rel_type' => 'project',
'rel_id' => $projectId,
'status' => $status,
'repeat_every' => '',
];
$response = Http::asJson()->withHeaders([
'authtoken' => config('perfexcrm.api_key')])
->put(config('perfexcrm.base_url').'/api/tasks/'.$taskId, $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());
}
}
}
@@ -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;
}
}
@@ -3,12 +3,13 @@
namespace App\Classes\Modules\Transactions\ControllersLogic;
use App\Classes\Modules\Transactions\Processors\ApproveShippingInvoiceTransactionProcessor;
use App\Classes\Notifications\InvoiceIssuedEmail;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Meneses\LaravelMpdf\Facades\LaravelMpdf;
use Mccarlosen\LaravelMpdf\Facades\LaravelMpdf;
use App\Classes\ValueObjects\Constants\DocumentType;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
@@ -36,29 +37,17 @@ class ApproveShippingInvoiceTransactionLogic extends AbstractControllerLogic
/** @var FetchesPackingList */
private $fetchesPackingList;
/** @var UpdatesTransactionStatus */
private $updatesTransactionStatus;
/** @var CreatesDocument */
private $createsDocument;
/** @var CreatesFiles */
private $createsFiles;
/** @var ApproveShippingInvoiceTransactionProcessor */
private $approveShippingInvoiceTransactionProcessor;
/**
* ApprovePaymentVerificationLogic constructor.
* @param FetchesPackingList $fetchesPackingList
* @param UpdatesTransactionStatus $updatesTransactionStatus
* @param CreatesDocument $createsDocument
* @param CreatesFiles $createsFiles
* @param CreateInvoiceTransactionProcessor $createInvoiceTransactionProcessor
* @param ApproveShippingInvoiceTransactionProcessor $approveShippingInvoiceTransactionProcessor
*/
public function __construct(FetchesPackingList $fetchesPackingList, UpdatesTransactionStatus $updatesTransactionStatus, CreatesDocument $createsDocument, CreatesFiles $createsFiles)
public function __construct(FetchesPackingList $fetchesPackingList, ApproveShippingInvoiceTransactionProcessor $approveShippingInvoiceTransactionProcessor)
{
$this->fetchesPackingList = $fetchesPackingList;
$this->updatesTransactionStatus = $updatesTransactionStatus;
$this->createsDocument = $createsDocument;
$this->createsFiles = $createsFiles;
$this->approveShippingInvoiceTransactionProcessor = $approveShippingInvoiceTransactionProcessor;
}
/**
@@ -69,29 +58,8 @@ class ApproveShippingInvoiceTransactionLogic extends AbstractControllerLogic
public function logic(Request $request) : JsonResponse
{
$packing_list = $this->fetchesPackingList->execute(['id' => $request->route('id')]);
$this->approveShippingInvoiceTransactionProcessor->execute($packing_list);
$invoice_transaction = $packing_list->transactions()->where('transactions.type', TransactionType::SHIPPING_INVOICE)->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::PENDING_SUBMISSION])->first();
$this->updatesTransactionStatus->execute($invoice_transaction, ApprovalStatus::APPROVED);
$transaction_invoice_pdf = LaravelMpdf::loadView('pages.pdfs.shipping_invoice', ['invoice_transaction' => $invoice_transaction]);
$document_object = new DocumentObject(
DocumentType::SHIPPING_INVOICE,
[chunk_split('data:application/pdf;base64,'.base64_encode($transaction_invoice_pdf->output()))],
'',
ApprovalStatus::COMPLETED,
'shipping_invoice'
);
/** @var Document $document */
$document = $this->createsDocument->execute($invoice_transaction, $document_object);
$this->createsFiles->execute($document, $document_object);
$user = $packing_list->owner->companyModule->employees()->first();
if(app()->environment(['production'])) {
$user->notify(new InvoiceIssuedEmail($user, $packing_list));
}
return $this->response([]);
}
@@ -23,7 +23,7 @@ use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Meneses\LaravelMpdf\Facades\LaravelMpdf;
use Mccarlosen\LaravelMpdf\Facades\LaravelMpdf;
class CreatePaymentTransactionLogic extends AbstractControllerLogic
{
@@ -5,41 +5,15 @@ namespace App\Classes\Modules\Transactions\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\PackingLists\Services\FetchesPackingList;
use App\Classes\Modules\SegmentConstants\Services\FetchesSegmentConstant;
use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber;
use App\Classes\Modules\Transactions\Services\CreatesTransaction;
use App\Classes\Modules\Transactions\Services\CreatesTransactionDetail;
use App\Classes\Modules\Documents\Services\CreatesDocument;
use App\Classes\Modules\Documents\Services\CreatesFiles;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionDetailObject;
use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject;
use App\Classes\ValueObjects\Constants\OrderRoleTypes;
use App\Classes\ValueObjects\Constants\PackingListType;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\DocumentType;
use App\Classes\ValueObjects\Constants\PackageType;
use App\Classes\ValueObjects\Constants\SegmentConstants;
use App\Classes\ValueObjects\Constants\TransactionDetailType;
use App\Models\CompanyModule;
use App\Models\Document;
use App\Models\PackingList;
use App\Models\Transaction;
use Carbon\Carbon;
use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionProcessor;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Meneses\LaravelMpdf\Facades\LaravelMpdf;
class CreateShippingInvoiceTransactionLogic extends AbstractControllerLogic
{
/**
* @return array
*/
@@ -53,214 +27,26 @@ class CreateShippingInvoiceTransactionLogic extends AbstractControllerLogic
/** @var FetchesPackingList */
private $fetchesPackingList;
/** @var FetchesSegmentConstant */
private $fetchesSegmentConstant;
/** @var CreateInvoiceTransactionProcessor */
private $createInvoiceTransactionProcessor;
/** @var GeneratesTransactionBillNumber */
private $generatesTransactionBillNumber;
/** @var CreatesTransaction */
private $createsTransaction;
/** @var CreatesTransactionDetail */
private $createsTransactionDetail;
/** @var CreatesDocument */
private $createsDocument;
/** @var CreatesFiles */
private $createsFile;
public function __construct(
FetchesPackingList $fetchesPackingList,
FetchesSegmentConstant $fetchesSegmentConstant,
GeneratesTransactionBillNumber $generatesTransactionBillNumber,
CreatesTransaction $createsTransaction,
CreatesTransactionDetail $createsTransactionDetail,
CreatesDocument $createsDocument,
CreatesFiles $createsFile
)
/**
* @param FetchesPackingList $fetchesPackingList
* @param CreateInvoiceTransactionProcessor $createInvoiceTransactionProcessor
*/
public function __construct(FetchesPackingList $fetchesPackingList, CreateInvoiceTransactionProcessor $createInvoiceTransactionProcessor)
{
$this->fetchesPackingList = $fetchesPackingList;
$this->fetchesSegmentConstant = $fetchesSegmentConstant;
$this->generatesTransactionBillNumber = $generatesTransactionBillNumber;
$this->createsTransaction = $createsTransaction;
$this->createsTransactionDetail = $createsTransactionDetail;
$this->createsDocument = $createsDocument;
$this->createsFile = $createsFile;
$this->createInvoiceTransactionProcessor = $createInvoiceTransactionProcessor;
}
public function logic(Request $request) : JsonResponse
{
$packing_list = $this->fetchesPackingList->execute(['id' => $request->input('packing_list_id')]);
$packing_list = PackingList::where('reference', $packing_list->reference)->where('type', PackingListType::SHIPPING_PACKING_LIST)->first();
$billable_packing_list = $packing_list->packingLists()->first();
$billable_packing_list = $billable_packing_list ? $billable_packing_list : $packing_list;
$cbm = round($billable_packing_list->packages->where('type', '!=', PackageType::OVER_WEIGHT)->sum(function($package) {
return ($package->width / 100) * ($package->height / 100) *($package->length / 100) * ($package->quantity);
}), 3);
$over_weight_cbm = round($billable_packing_list->packages->where('type', PackageType::OVER_WEIGHT)->sum(function($package) {
return ($package->width / 100) * ($package->height / 100) *($package->length / 100) * ($package->quantity);
}), 3);
$order = $packing_list->owner;
$companyModule = $order->companyModule;
$connection = $companyModule->connections()->first();
$address = $order->addresses()->first();
$base_price_constant = $this->fetchesSegmentConstant->execute(['segment_id' => 1, 'reference' => SegmentConstants::BASE_PRICE]);
$warehouse_rate_constant = $this->fetchesSegmentConstant->execute(['segment_id' => 1, 'reference' => SegmentConstants::WAREHOUSE_RATE]);
$state_rate_constant = $this->fetchesSegmentConstant->execute(['segment_id' => 1, 'reference' => SegmentConstants::STATE_RATE]);
$center_postcode_constant = $this->fetchesSegmentConstant->execute(['segment_id' => 1, 'reference' => SegmentConstants::CENTER_POSTCODE]);
$outstation_postcode_constant = $this->fetchesSegmentConstant->execute(['segment_id' => 1, 'reference' => SegmentConstants::OUTSTATION_POSTCODE]);
$noMinimumCharge = $connection->segments()->where('segments.id', 2)->first();
$minimum_cbm = 0.3;
$state_select = '';
$segment_price = $connection->segments()->whereHas('constants', function($query){
return $query->where('reference', SegmentConstants::CUSTOM_PRICE);
})->get()->map(function($segment){
return (float) $segment->constants()->first()->value[0];
})->sort()->first();
$segment_price = $segment_price ? $segment_price : 0;
$packing_list_drop_date = PackingList::where('reference', $packing_list->reference)->where('type', 1)->first()->transports->first()->drop_date->format('Y-m-d');
$base_price = $this->getConstantByKey($base_price_constant, $packing_list_drop_date);
$warehouseId = $order->orderRoles()->where('role_id', OrderRoleTypes::ORIGIN_WAREHOUSE)->first()->company_module_id;
$selected_warehouse_rate = $this->getConstantByKey($warehouse_rate_constant, $warehouseId);
$warehouse_rate = is_object($selected_warehouse_rate) ? $selected_warehouse_rate->amount : 0;
$stateId = $address->state_id;
$state_rate_constant = $this->getConstantByKey($state_rate_constant, $stateId);
// get $state_rate
$postcode = $address->postcode;
$this->checkPostcodeExistInConstant($center_postcode_constant, $postcode) === true ? $state_select = 'center' : '' ;
$this->checkPostcodeExistInConstant($outstation_postcode_constant, $postcode) === true ? $state_select = 'outstation' : '' ;
$state_rate_constant = (array)$state_rate_constant;
$state_rate = $state_select == '' ? 0 : $state_rate_constant[$state_select];
$container = $packing_list->containers()->first();
$containerPackingLists = collect();
$hasMinimumCharge = null;
foreach ($container->packingLists as $packingList){
if($packingList->owner instanceof CompanyModule) continue;
if($packingList->owner->companyModule->id !== $companyModule->id) continue;
$containerPackingLists->push($packingList);
if(!$hasMinimumCharge) {
$hasMinimumCharge = $packingList->transactions()->whereHas('transactionDetails', function ($query){
$query->where('reference', 'MIN_CBM_CHARGES');
})->first();
}
}
$totalContainerCbm = $containerPackingLists->sum(function($packingList){
$billable_packing_list = $packingList->packingLists()->first();
$billable_packing_list = $billable_packing_list ? $billable_packing_list : $packingList;
return $billable_packing_list->packages->sum(function($package) {
return ($package->width / 100) * ($package->height / 100) *($package->length / 100) * ($package->quantity);
});
});
$minimum_charge = $minimum_cbm - $totalContainerCbm;
$minimum_charge = ($minimum_charge < 0) ? 0 : $minimum_charge;
$minimum_charge = $noMinimumCharge ? 0 : $minimum_charge;
$minimum_charge = $noMinimumCharge ? 0 : round($minimum_charge, 3);
if($hasMinimumCharge) {
$minimum_charge = 0;
}
$price_cbm = $base_price + $segment_price + $warehouse_rate + $state_rate;
$total_cbm = $price_cbm * ($cbm + $minimum_charge + $over_weight_cbm);
$billNumber = $this->generatesTransactionBillNumber->execute('SHIP-');
$object = new TransactionObject(
$billNumber,
TransactionType::SHIPPING_INVOICE,
1,
$order->company_module_id,
1,
PaymentMethodType::CASH,
$total_cbm,
$total_cbm,
1,
1,
0,
0,
0,
null,
ApprovalStatus::PENDING_SUBMISSION
);
/** @var Transaction $invoice_transaction */
$invoice_transaction = $this->createsTransaction->execute($packing_list, $object);
$object_detail = new TransactionDetailObject(
'SHIPPING_FEE',
TransactionDetailType::SHIPPING_FEE.'<br>'.round($packing_list->packages->where('type', '!=', PackageType::OVER_WEIGHT)->sum('quantity'), 3).' CTNS - '.round($cbm, 3).' CBM',
$cbm,
$price_cbm
);
$this->createsTransactionDetail->execute($invoice_transaction, $object_detail);
if ($over_weight_cbm > 0) {
$object_detail = new TransactionDetailObject(
'OVER_WEIGHT_CHARGES',
TransactionDetailType::OVER_WEIGHT_CHARGES,
$over_weight_cbm,
$price_cbm
);
$this->createsTransactionDetail->execute($invoice_transaction, $object_detail);
}
if ($minimum_charge > 0) {
$object_detail = new TransactionDetailObject(
'MIN_CBM_CHARGES',
TransactionDetailType::MIN_CBM_CHARGES,
$minimum_charge,
$price_cbm
);
$this->createsTransactionDetail->execute($invoice_transaction, $object_detail);
}
$this->createInvoiceTransactionProcessor->execute($packing_list);
return $this->response([]);
}
function getConstantByKey($segmentConstantObject, $key) {
if ($segmentConstantObject) {
$base_rate = (array) $segmentConstantObject->value;
$base_rate = array_key_exists($key, $base_rate) === true ? $base_rate[$key] : 0;
return $base_rate;
}
}
function checkPostcodeExistInConstant($segmentConstantObject, $postcode) {
$segmentConstantObject = $segmentConstantObject->value;
if (!empty($segmentConstantObject)) {
return in_array($postcode, $segmentConstantObject);
} else {
return false;
}
}
}
@@ -27,7 +27,7 @@ use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Meneses\LaravelLaravelMpdf\Facades\LaravelLaravelMpdf;
use Meneses\LaravelMpdf\Facades\LaravelMpdf;
use Mccarlosen\LaravelMpdf\Facades\LaravelMpdf;
class CreateSupplierTransactionLogic extends AbstractControllerLogic
{
@@ -7,7 +7,7 @@ use App\Models\Transaction;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Storage;
use Meneses\LaravelMpdf\Facades\LaravelMpdf;
use Mccarlosen\LaravelMpdf\Facades\LaravelMpdf;
use App\Classes\ValueObjects\Constants\DocumentType;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
@@ -0,0 +1,81 @@
<?php
namespace App\Classes\Modules\Transactions\Processors;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Notifications\InvoiceIssuedEmail;
use App\Models\Document;
use App\Models\PackingList;
use App\Models\Transaction;
use Mccarlosen\LaravelMpdf\Facades\LaravelMpdf;
use App\Classes\ValueObjects\Constants\DocumentType;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\Modules\Documents\Services\CreatesFiles;
use App\Classes\Modules\Documents\Services\CreatesDocument;
use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use App\Classes\Jobs\CreatePerfexCRMInvoice;
class ApproveShippingInvoiceTransactionProcessor
{
/** @var UpdatesTransactionStatus */
private $updatesTransactionStatus;
/** @var CreatesDocument */
private $createsDocument;
/** @var CreatesFiles */
private $createsFiles;
/**
* @param UpdatesTransactionStatus $updatesTransactionStatus
* @param CreatesDocument $createsDocument
* @param CreatesFiles $createsFiles
*/
public function __construct(UpdatesTransactionStatus $updatesTransactionStatus, CreatesDocument $createsDocument, CreatesFiles $createsFiles)
{
$this->updatesTransactionStatus = $updatesTransactionStatus;
$this->createsDocument = $createsDocument;
$this->createsFiles = $createsFiles;
}
/**
* @param PackingList $packingList
* @throws MalformedRequestException
*/
public function execute(PackingList $packingList)
{
/** @var Transaction $invoice_transaction */
$invoice_transaction = $packingList->transactions()->where('transactions.type', TransactionType::SHIPPING_INVOICE)->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::PENDING_SUBMISSION])->first();
$this->updatesTransactionStatus->execute($invoice_transaction, ApprovalStatus::APPROVED);
$transaction_invoice_pdf = LaravelMpdf::loadView('pages.pdfs.shipping_invoice', ['invoice_transaction' => $invoice_transaction]);
$document_object = new DocumentObject(
DocumentType::SHIPPING_INVOICE,
[chunk_split('data:application/pdf;base64,'.base64_encode($transaction_invoice_pdf->output()))],
'',
ApprovalStatus::COMPLETED,
'shipping_invoice'
);
/** @var Document $document */
$document = $this->createsDocument->execute($invoice_transaction, $document_object);
$this->createsFiles->execute($document, $document_object);
$user = $packingList->owner->companyModule->employees()->first();
if(app()->environment(['production'])) {
$user->notify(new InvoiceIssuedEmail($user, $packingList));
}
return;
}
}
@@ -1,229 +1,247 @@
<?php
namespace App\Classes\Modules\Transactions\Processors;
use App\Classes\Modules\Bookings\Services\CalculatesBookingTransferredAmount;
use App\Classes\Modules\ServiceTypes\Services\FetchesServiceConfigurations;
use App\Classes\Modules\Transactions\Services\ListsTransactions;
use App\Classes\Modules\Transactions\Services\CreatesTransaction;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\PackingLists\Services\FetchesPackingList;
use App\Classes\Modules\SegmentConstants\Services\FetchesSegmentConstant;
use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber;
use App\Classes\Modules\Bookings\Services\CalculatesBookingPaidAmount;
use App\Classes\Modules\Bookings\Services\CalculatesBookingCurrencyAverageRate;
use App\Classes\Modules\Companies\Services\FetchesCompany;
use App\Classes\Modules\Transactions\Services\CreatesTransaction;
use App\Classes\Modules\Transactions\Services\CreatesTransactionDetail;
use App\Classes\Modules\Documents\Services\CreatesDocument;
use App\Classes\Modules\Documents\Services\CreatesFiles;
use App\Classes\Modules\Bookings\Services\UpdatesBookingStatus;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionObject;
use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\SegmentConstants;
use App\Classes\Modules\Transactions\DataTransferObjects\TransactionDetailObject;
use App\Classes\ValueObjects\Constants\OrderRoleTypes;
use App\Classes\ValueObjects\Constants\PackingListType;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\ValueObjects\Constants\DocumentType;
use App\Models\Booking;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\PackageType;
use App\Classes\ValueObjects\Constants\SegmentConstants;
use App\Classes\ValueObjects\Constants\TransactionDetailType;
use App\Models\CompanyModule;
use App\Models\Document;
use App\Models\SegmentConstant;
use Meneses\LaravelMpdf\Facades\LaravelMpdf;
use App\Models\PackingList;
use App\Models\Transaction;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Mccarlosen\LaravelMpdf\Facades\LaravelMpdf;
class CreateInvoiceTransactionProcessor
{
/** @var ListsTransactions */
private $listsTransactions;
/** @var CreatesTransaction */
private $createsTransaction;
/** @var FetchesPackingList */
private $fetchesPackingList;
/** @var FetchesSegmentConstant */
private $fetchesSegmentConstant;
/** @var GeneratesTransactionBillNumber */
private $generatesTransactionBillNumber;
/** @var CalculatesBookingPaidAmount */
private $calculatesBookingPaidAmount;
/** @var CreatesTransaction */
private $createsTransaction;
/** @var CalculatesBookingTransferredAmount */
private $calculatesBookingTransferredAmount;
/** @var FetchesServiceConfigurations */
private $fetchesServiceConfigurations;
/** @var CalculatesBookingCurrencyAverageRate */
private $calculatesBookingCurrencyAverageRate;
/** @var FetchesCompany */
private $fetchesCompany;
/** @var CreatesDocument */
private $createsDocument;
/** @var CreatesFiles */
private $createsFile;
/** @var UpdatesBookingStatus */
private $updatesBookingStatus;
/** @var CreatesTransactionDetail */
private $createsTransactionDetail;
/**
* CreateInvoiceTransactionProcessor constructor.
* @param ListsTransactions $listsTransactions
* @param CreatesTransaction $createsTransaction
* @param FetchesPackingList $fetchesPackingList
* @param FetchesSegmentConstant $fetchesSegmentConstant
* @param GeneratesTransactionBillNumber $generatesTransactionBillNumber
* @param CalculatesBookingPaidAmount $calculatesBookingPaidAmount
* @param CalculatesBookingTransferredAmount $calculatesBookingTransferredAmount
* @param FetchesServiceConfigurations $fetchesServiceConfigurations
* @param CalculatesBookingCurrencyAverageRate $calculatesBookingCurrencyAverageRate
* @param FetchesCompany $fetchesCompany
* @param CreatesDocument $createsDocument
* @param CreatesFiles $createsFile
* @param UpdatesBookingStatus $updatesBookingStatus
* @param CreatesTransaction $createsTransaction
* @param CreatesTransactionDetail $createsTransactionDetail
*/
public function __construct(ListsTransactions $listsTransactions, CreatesTransaction $createsTransaction, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CalculatesBookingPaidAmount $calculatesBookingPaidAmount, CalculatesBookingTransferredAmount $calculatesBookingTransferredAmount, FetchesServiceConfigurations $fetchesServiceConfigurations, CalculatesBookingCurrencyAverageRate $calculatesBookingCurrencyAverageRate, FetchesCompany $fetchesCompany, CreatesDocument $createsDocument, CreatesFiles $createsFile, UpdatesBookingStatus $updatesBookingStatus)
public function __construct(FetchesPackingList $fetchesPackingList, FetchesSegmentConstant $fetchesSegmentConstant, GeneratesTransactionBillNumber $generatesTransactionBillNumber, CreatesTransaction $createsTransaction, CreatesTransactionDetail $createsTransactionDetail)
{
$this->listsTransactions = $listsTransactions;
$this->createsTransaction = $createsTransaction;
$this->fetchesPackingList = $fetchesPackingList;
$this->fetchesSegmentConstant = $fetchesSegmentConstant;
$this->generatesTransactionBillNumber = $generatesTransactionBillNumber;
$this->calculatesBookingPaidAmount = $calculatesBookingPaidAmount;
$this->calculatesBookingTransferredAmount = $calculatesBookingTransferredAmount;
$this->fetchesServiceConfigurations = $fetchesServiceConfigurations;
$this->calculatesBookingCurrencyAverageRate = $calculatesBookingCurrencyAverageRate;
$this->fetchesCompany = $fetchesCompany;
$this->createsDocument = $createsDocument;
$this->createsFile = $createsFile;
$this->updatesBookingStatus = $updatesBookingStatus;
$this->createsTransaction = $createsTransaction;
$this->createsTransactionDetail = $createsTransactionDetail;
}
/**
* @param Booking $booking
* @return void
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws MalformedRequestException
*/
public function execute(Booking $booking)
public function execute(PackingList $packingList)
{
$payment_amount = $this->calculatesBookingTransferredAmount->execute($booking, $booking->fix_currency_id);
$booking_amount = $booking->fix_amount;
$packing_list = PackingList::where('reference', $packingList->reference)->where('type', PackingListType::SHIPPING_PACKING_LIST)->first();
$billable_packing_list = $packing_list->packingLists()->first();
$billable_packing_list = $billable_packing_list ? $billable_packing_list : $packing_list;
$cbm = round($billable_packing_list->packages->where('type', '!=', PackageType::OVER_WEIGHT)->sum(function($package) {
return ($package->width / 100) * ($package->height / 100) *($package->length / 100) * ($package->quantity);
}), 3);
$over_weight_cbm = round($billable_packing_list->packages->where('type', PackageType::OVER_WEIGHT)->sum(function($package) {
return ($package->width / 100) * ($package->height / 100) *($package->length / 100) * ($package->quantity);
}), 3);
$order = $packing_list->owner;
$companyModule = $order->companyModule;
$connection = $companyModule->connections()->first();
$address = $order->addresses()->first();
$base_price_constant = $this->fetchesSegmentConstant->execute(['segment_id' => 1, 'reference' => SegmentConstants::BASE_PRICE]);
$warehouse_rate_constant = $this->fetchesSegmentConstant->execute(['segment_id' => 1, 'reference' => SegmentConstants::WAREHOUSE_RATE]);
$state_rate_constant = $this->fetchesSegmentConstant->execute(['segment_id' => 1, 'reference' => SegmentConstants::STATE_RATE]);
$center_postcode_constant = $this->fetchesSegmentConstant->execute(['segment_id' => 1, 'reference' => SegmentConstants::CENTER_POSTCODE]);
$outstation_postcode_constant = $this->fetchesSegmentConstant->execute(['segment_id' => 1, 'reference' => SegmentConstants::OUTSTATION_POSTCODE]);
$noMinimumCharge = $connection->segments()->where('segments.id', 2)->first();
$minimum_cbm = 0.3;
$state_select = '';
$segment_price = $connection->segments()->whereHas('constants', function($query){
return $query->where('reference', SegmentConstants::CUSTOM_PRICE);
})->get()->map(function($segment){
return (float) $segment->constants()->first()->value[0];
})->sort()->first();
$segment_price = $segment_price ? $segment_price : 0;
$arrivalTransport = PackingList::where('reference', $packing_list->reference)->where('type', 1)->first()->transports->first();
if(!$arrivalTransport) {
throw new MalformedRequestException('Arrival date is unknow can\'t generate invoice');
}
$packing_list_drop_date = $arrivalTransport->drop_date->format('Y-m-d');
$base_price = $this->getConstantByKey($base_price_constant, $packing_list_drop_date);
$warehouseId = $order->orderRoles()->where('role_id', OrderRoleTypes::ORIGIN_WAREHOUSE)->first()->company_module_id;
$selected_warehouse_rate = $this->getConstantByKey($warehouse_rate_constant, $warehouseId);
$warehouse_rate = is_object($selected_warehouse_rate) ? $selected_warehouse_rate->amount : 0;
$stateId = $address->state_id;
$state_rate_constant = $this->getConstantByKey($state_rate_constant, $stateId);
// get $state_rate
$postcode = $address->postcode;
$this->checkPostcodeExistInConstant($center_postcode_constant, $postcode) === true ? $state_select = 'center' : '' ;
$this->checkPostcodeExistInConstant($outstation_postcode_constant, $postcode) === true ? $state_select = 'outstation' : '' ;
$state_rate_constant = (array)$state_rate_constant;
$state_rate = $state_select == '' ? 0 : $state_rate_constant[$state_select];
$container = $packing_list->containers()->first();
$containerPackingLists = collect();
$hasMinimumCharge = null;
foreach ($container->packingLists as $packingList){
if($packingList->owner instanceof CompanyModule) continue;
if($packingList->owner->companyModule->id !== $companyModule->id) continue;
$containerPackingLists->push($packingList);
if(!$hasMinimumCharge) {
$hasMinimumCharge = $packingList->transactions()->whereHas('transactionDetails', function ($query){
$query->where('reference', 'MIN_CBM_CHARGES');
})->first();
}
if ((float) $booking_amount !== (float) $payment_amount) {
return;
}
$po_order_transaction = $booking->transactions()
->where('type', TransactionType::PURCHASE_ORDER)
->complete()
->first();
$totalContainerCbm = $containerPackingLists->sum(function($packingList){
$billable_packing_list = $packingList->packingLists()->first();
$billable_packing_list = $billable_packing_list ? $billable_packing_list : $packingList;
return $billable_packing_list->packages->sum(function($package) {
return ($package->width / 100) * ($package->height / 100) *($package->length / 100) * ($package->quantity);
});
});
$constants = SegmentConstant::where('reference', SegmentConstants::SERVICE_TYPE)->where('detail->id', $booking->service->id)->first();
$minimum_charge = $minimum_cbm - $totalContainerCbm;
$minimum_charge = ($minimum_charge < 0) ? 0 : $minimum_charge;
$minimum_charge = $noMinimumCharge ? 0 : $minimum_charge;
if($constants->detail->is_billable && !$po_order_transaction) {
return;
$minimum_charge = $noMinimumCharge ? 0 : round($minimum_charge, 3);
if($hasMinimumCharge) {
$minimum_charge = 0;
}
$transaction = $booking->transactions()
->where('type', TransactionType::PAYMENT)
->first();
$price_cbm = $base_price + $segment_price + $warehouse_rate + $state_rate;
$billNumber = $this->generatesTransactionBillNumber->execute('INV-');
$total_cbm = $price_cbm * ($cbm + $minimum_charge + $over_weight_cbm);
$booking_currency_average_rate = $this->calculatesBookingCurrencyAverageRate->execute($booking, TransactionType::PAYMENT);
$billNumber = $this->generatesTransactionBillNumber->execute('SHIP-');
$total_service_charge = $booking->transactions()
->where('type', TransactionType::PAYMENT)
->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])
->sum('service_charge');
$total_tax = $booking->transactions()
->where('type', TransactionType::PAYMENT)
->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])
->sum('tax');
$transaction_object = new TransactionObject(
$object = new TransactionObject(
$billNumber,
TransactionType::INVOICE,
$transaction->issuer,
$transaction->receiver,
$transaction->recipient_bank_account_id,
$transaction->payment_method,
$payment_amount,
$booking_amount,
$transaction->currency_id,
$transaction->original_currency_id,
$booking_currency_average_rate,
$total_tax,
$total_service_charge,
TransactionType::SHIPPING_INVOICE,
1,
$order->company_module_id,
1,
PaymentMethodType::CASH,
$total_cbm,
$total_cbm,
1,
1,
0,
0,
0,
null,
ApprovalStatus::APPROVED
);
$invoice_transaction = $this->createsTransaction->execute($po_order_transaction->booking, $transaction_object);
$supplier = $this->fetchesCompany->execute(['id' => $transaction->receiver]);
$purchase_order_pdf = LaravelMpdf::loadView('pages.pdfs.purchase_order', ['invoice_transaction' => $invoice_transaction, 'po_order_transaction' => $po_order_transaction, 'supplier' => $supplier]);
$document_object = new DocumentObject(
DocumentType::PURCHASE_ORDER,
[chunk_split('data:application/pdf;base64,'.base64_encode($purchase_order_pdf->output()))],
'',
ApprovalStatus::COMPLETED,
'purchase_orders'
);
$document = $this->createsDocument->execute($po_order_transaction->booking, $document_object);
$this->createsFile->execute($document, $document_object);
$deliver_order_pdf = LaravelMpdf::loadView('pages.pdfs.deliver_order', ['invoice_transaction' => $invoice_transaction, 'po_order_transaction' => $po_order_transaction, 'supplier' => $supplier]);
$document_object = new DocumentObject(
DocumentType::DELIVER_ORDER,
[chunk_split('data:application/pdf;base64,'.base64_encode($deliver_order_pdf->output()))],
'',
ApprovalStatus::COMPLETED,
'delivery_orders'
ApprovalStatus::PENDING_SUBMISSION
);
/** @var Document $document */
$document = $this->createsDocument->execute($po_order_transaction->booking, $document_object);
$this->createsFile->execute($document, $document_object);
/** @var Transaction $invoice_transaction */
$invoice_transaction = $this->createsTransaction->execute($packing_list, $object);
$invoice_pdf = LaravelMpdf::loadView('pages.pdfs.invoice', ['invoice_transaction' => $invoice_transaction, 'po_order_transaction' => $po_order_transaction, 'supplier' => $supplier]);
$document_object = new DocumentObject(
DocumentType::INVOICE,
[chunk_split('data:application/pdf;base64,'.base64_encode($invoice_pdf->output()))],
'',
ApprovalStatus::COMPLETED,
'invoices'
$object_detail = new TransactionDetailObject(
'SHIPPING_FEE',
TransactionDetailType::SHIPPING_FEE.'<br>'.round($packing_list->packages->where('type', '!=', PackageType::OVER_WEIGHT)->sum('quantity'), 3).' CTNS - '.round($cbm, 3).' CBM',
$cbm,
$price_cbm
);
$document = $this->createsDocument->execute($po_order_transaction->booking, $document_object);
$this->createsFile->execute($document, $document_object);
$billNumber = $this->generatesTransactionBillNumber->execute('SPDO-');
$this->createsTransactionDetail->execute($invoice_transaction, $object_detail);
$booking_currency_average_rate = $this->calculatesBookingCurrencyAverageRate->execute($booking, TransactionType::BILL);
if ($over_weight_cbm > 0) {
$object_detail = new TransactionDetailObject(
'OVER_WEIGHT_CHARGES',
TransactionDetailType::OVER_WEIGHT_CHARGES,
$over_weight_cbm,
$price_cbm
);
$transaction_object = new TransactionObject(
$billNumber,
TransactionType::SUPPLIER_DELIVER,
$transaction->issuer,
$transaction->receiver,
$transaction->recipient_bank_account_id,
$transaction->payment_method,
$payment_amount,
$booking_amount,
$transaction->currency_id,
$transaction->original_currency_id,
$booking_currency_average_rate,
$total_tax,
$total_service_charge,
null,
ApprovalStatus::APPROVED
);
$supplier_deliver_order_transaction = $this->createsTransaction->execute($po_order_transaction->booking, $transaction_object);
$this->createsTransactionDetail->execute($invoice_transaction, $object_detail);
}
$supplier_order_pdf = LaravelMpdf::loadView('pages.pdfs.supplier_deliver_order', ['supplier_deliver_order_transaction' => $supplier_deliver_order_transaction, 'po_order_transaction' => $po_order_transaction, 'supplier' => $supplier]);
$document_object = new DocumentObject(
DocumentType::SUPPLIER_DELIVER_ORDER,
[chunk_split('data:application/pdf;base64,'.base64_encode($supplier_order_pdf->output()))],
'',
ApprovalStatus::COMPLETED,
'supplier_delivery_orders'
);
$document = $this->createsDocument->execute($po_order_transaction->booking, $document_object);
$this->createsFile->execute($document, $document_object);
if ($minimum_charge > 0) {
$object_detail = new TransactionDetailObject(
'MIN_CBM_CHARGES',
TransactionDetailType::MIN_CBM_CHARGES,
$minimum_charge,
$price_cbm
);
$this->updatesBookingStatus->execute($booking, ApprovalStatus::COMPLETED);
$this->createsTransactionDetail->execute($invoice_transaction, $object_detail);
}
return;
}
function getConstantByKey($segmentConstantObject, $key) {
if ($segmentConstantObject) {
$base_rate = (array) $segmentConstantObject->value;
$base_rate = array_key_exists($key, $base_rate) === true ? $base_rate[$key] : 0;
return $base_rate;
}
}
function checkPostcodeExistInConstant($segmentConstantObject, $postcode) {
$segmentConstantObject = $segmentConstantObject->value;
if (!empty($segmentConstantObject)) {
return in_array($postcode, $segmentConstantObject);
} else {
return false;
}
}
}
@@ -4,9 +4,21 @@ namespace App\Classes\Modules\Transactions\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Models\Transaction;
use App\Classes\Modules\PerfexCRM\Processors\TransactionToPerfexCRMProcessor;
class UpdatesTransactionStatus extends AbstractUpdateRecord
{
/** @var TransactionToPerfexCRMProcessor */
private $transactionToPerfexCRMProcessor;
/**
* UpdatesTransactionStatus constructor.
* @param TransactionToPerfexCRMProcessor $transactionToPerfexCRMProcessor
*/
public function __construct(TransactionToPerfexCRMProcessor $transactionToPerfexCRMProcessor)
{
$this->transactionToPerfexCRMProcessor = $transactionToPerfexCRMProcessor;
}
/**
* @param Transaction $model
@@ -16,7 +28,13 @@ class UpdatesTransactionStatus extends AbstractUpdateRecord
*/
public function execute(Transaction $model, int $status)
{
$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;
}
}
}
@@ -18,4 +18,14 @@ final class ApprovalStatus {
public const EXPIRED = 6;
public const APPROVAL_STATUS_ID = [
self::PENDING_SUBMISSION => "Pending Submission",
self::PENDING_VERIFICATION => "Pending Verification",
self::APPROVED => "Approved",
self::COMPLETED => "Completed",
self::REJECTED => "Rejected",
self::SUSPENDED => "Suspended",
self::EXPIRED => "Expired",
];
}
@@ -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,14 @@
<?php
namespace App\Classes\ValueObjects\Constants;
final class PerfexCRMInvoiceStatus {
public const UNPAID = 1;
public const PAID = 2;
public const PARTIALLY_PAID = 3;
public const OVERDUE = 4;
}
@@ -0,0 +1,12 @@
<?php
namespace App\Classes\ValueObjects\Constants;
class PerfexCRMMilestones
{
public const MILESTONE_1 = 'MILESTONE 1 - Customer Paid';
public const MILESTONE_2 = 'MILESTONE 2 - Order Placed';
public const MILESTONE_3 = 'MILESTONE 3 - Purchase Order Approved';
public const MILESTONE_4 = 'MILESTONE 4';
public const MILESTONE_5 = 'MILESTONE 5';
}
@@ -0,0 +1,16 @@
<?php
namespace App\Classes\ValueObjects\Constants;
final class PerfexCRMProjectStatus {
public const NOT_STARTED = 1;
public const IN_PROGRESS = 2;
public const ON_HOLD = 3;
public const FINISHED = 4;
public const CANCELLED = 5;
}
@@ -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;
}
@@ -0,0 +1,17 @@
<?php
namespace App\Classes\ValueObjects\Constants;
final class PerfexCRMTaskStatus {
public const NOT_STARTED = 1;
public const AWAITING_FEEDBACK = 2;
public const TESTING = 3;
public const IN_PROGRESS = 4;
public const COMPLETED = 5;
}
@@ -0,0 +1,147 @@
<?php
namespace App\Classes\ValueObjects\Constants;
class PerfexCRMTasks
{
//IMPORTANT NOTE: TASK NAME MUST BE UNIQUE ACCORDING TO REL_TYPE
//e.g. rel_type: lead, project
public const TASK_1 = [
'name' => 'Customer Paid',
'description' => '',
'milestone' => 'MILESTONE 1 - Customer Paid',
'reference' => '',
'on_task_completion' => '',
'department' => '',
'status' => PerfexCRMTaskStatus::COMPLETED,
'priority' => PerfexCRMTaskPriority::DEFAULT,
'duedate' => 0
];
public const TASK_POST_PAYMENT_1 = [
'name' => 'Map Bank Transaction Record',
'description' => ' Purpose: To map a transaction to bank transaction in the bank statement<br>
Initial Status: In Progress<br>
Deadline: Same day<br>
Responsible department: Accounts<br>
Next step: Change the status of the Approve payment status to "In Progress" upon successful completion of the operation.<br>
Additional details: ** Any specific requirements or notes for the operation.**<br>
Dependencies: None<br>
Outcomes: Bank transaction is mapped successfully, allowing the next steps in the process to be initiated.<br>',
'milestone' => '',
'reference' => 'TASK_POST_PAYMENT_1',
'on_task_completion' => 'TASK_POST_PAYMENT_2',
'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>
Amount To be Approve: RM {amount}<br>',
'milestone' => '',
'reference' => 'TASK_POST_PAYMENT_2',
'on_task_completion' => 'TASK_POST_PAYMENT_3',
'department' => 'Accounts',
'status' => '',
'priority' => PerfexCRMTaskPriority::HIGH,
'duedate' => 0
];
public const TASK_POST_PAYMENT_3 = [
'name' => 'Issue Shipping Autocount Invoince',
'description' => ' Purpose: To issue an invoice for the customer\'s payment in accounting software.<br>
Initial Status: Not Started<br>
Deadline: Next day<br>
Responsible department: Accounts<br>
Next step: Change the status of the Knockoff Invoice operation to "In Progress" upon successful completion.<br>
Additional details: ** Any specific requirements or notes for the operation.**<br>
Dependencies: Approve Payment operation must be completed before this operation can begin.<br>
Outcomes: An invoice will be issued in accounting software for the customer\'s payment.<br>',
'milestone' => '',
'reference' => 'TASK_POST_PAYMENT_3',
'on_task_completion' => 'TASK_POST_PAYMENT_4',
'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',
'description' => ' Purpose: The purpose of this operation is to issue the official receipt and knockoff with invoice for the customer\'s payment.<br>
Initial Status: Not Started<br>
Deadline: Next day.<br>
Responsible Department: Accounts<br>
Next Step: None<br>
Additional Details: ** Any specific requirements or notes for the operation.**<br>
Dependencies: Issue Shipping Autocount Invoice operation must be completed before this operation can begin.<br>
Outcomes: The customers payment is applied to the accounting software invoice and invoice is marked as paid.<br>',
'milestone' => '',
'reference' => 'TASK_POST_PAYMENT_4',
'on_task_completion' => '',
'department' => 'Accounts',
'status' => '',
'priority' => PerfexCRMTaskPriority::MEDIUM,
'duedate' => 1
];
public const TASK_LOADED_CONTAINER_1 = [
'name' => 'Generate Shipping Invoices',
'description' => ' Purpose: -<br>
Link to order page: {link_order}<br>',
'milestone' => '',
'reference' => 'TASK_LOADED_CONTAINER_1',
'on_task_completion' => 'TASK_LOADED_CONTAINER_2',
'department' => 'Operations',
'status' => PerfexCRMTaskStatus::IN_PROGRESS,
'priority' => PerfexCRMTaskPriority::HIGH,
'duedate' => 1
];
public const TASK_LOADED_CONTAINER_2 = [
'name' => 'Approve Shipping Invoices',
'description' => ' Purpose: -<br>
Link to refer Pay On Behalf or Any extra charge: : {link_perfex}<br>',
'milestone' => '',
'reference' => 'TASK_LOADED_CONTAINER_2',
'on_task_completion' => '',
'department' => 'Customer Services',
'status' => '',
'priority' => PerfexCRMTaskPriority::HIGH,
'duedate' => 1
];
public const TASK_IDENTIFICATION_1 = [
'name' => 'Approve Identification Verification (Shipping)',
'description' => ' Purpose: To ensure the customer submit information matches the information in their identification document.<br>
Initial Status: In Progress<br>
Deadline: Same Day<br>
Responsible department: Operation<br>
Next step: None<br>
Additional details: ** Any specific requirements or notes for the operation.**<br>
Dependencies: None<br>
Outcomes: Customer account identification is verified<br>',
'milestone' => '',
'reference' => 'TASK_IDENTIFICATION_1',
'on_task_completion' => '',
'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",
];
}
@@ -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 at paid at out 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,82 @@
<?php
namespace App\Console\Commands;
use App\Classes\Modules\PackingLists\Services\ListsPackingLists;
use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionProcessor;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Models\Order;
use Carbon\Carbon;
use Exception;
use Illuminate\Console\Command;
class AutoGenerateInvoice extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'invoice:generate';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Auto generate invoice';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$packingLists = (App()->make(ListsPackingLists::class))->execute(['does_not_have_transaction_type' => 1, 'type' => 2]);
if (count($packingLists)) {
$this->info(Carbon::now() . ' : Auto generate invoice cron started.');
$start = new Carbon();
foreach ($packingLists as $packingList) {
$order = $packingList->owner;
if (!($order instanceof Order)) {
$this->info('Failed to generate invoice for reference' . $order->reference . '. It is not an instance of Order.');
continue;
}
$companyModule = $order->companyModule;
$billingAddress = $companyModule->addresses()->where('type', \App\Classes\ValueObjects\Constants\AddressType::BILLING)->first();
$deliveryAddress = $order->addresses()->where('status', ApprovalStatus::APPROVED)->first();
$postCodes = \App\Models\SegmentConstant::whereIn('reference', ['CENTER_POSTCODE', 'OUTSTATION_POSTCODE'])->get()->pluck('value')->flatten();
if (!!$billingAddress && in_array($deliveryAddress->postcode, $postCodes->toArray())) {
try {
(App()->make(CreateInvoiceTransactionProcessor::class))->execute($packingList);
$this->info('Invoice generated for reference ' . $order->reference . '.');
} catch (Exception $exception) {
$this->info('Failed to generate invoice for reference ' . $order->reference . '. Exception: ' . $exception->getMessage());
}
}
$this->info('Failed to generate invoice for reference ' . $order->reference . '. Billing Address is not defined / Postcode area is not defined.');
}
$end = new Carbon();
$elapsedTime = $start->diff($end)->format('%H:%I:%S');
$this->info(Carbon::now() . ' : Done generating invoice. ElapsedTime: ' . $elapsedTime . '.');
}
}
}
@@ -0,0 +1,182 @@
<?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 = '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 ($invoiceStatus == 'Pending Payment') {
// 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 {
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);
}
}
+83
View File
@@ -0,0 +1,83 @@
<?php
namespace App\Console\Commands;
use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject;
use App\Classes\Modules\Documents\Services\CreatesDocument;
use App\Classes\Modules\Documents\Services\CreatesFiles;
use App\Classes\Modules\PackingLists\Services\ListsPackingLists;
use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionProcessor;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\DocumentType;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\CompanyConnection;
use App\Models\Order;
use Carbon\Carbon;
use Exception;
use Illuminate\Console\Command;
use Mccarlosen\LaravelMpdf\Facades\LaravelMpdf;
class FixInvoice extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'invoice:fix {--marking=}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Fix Invoice By Company Module Marking';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$connection = CompanyConnection::where('invitee_reference', $this->option('marking'))->first();
$company_module_id = $connection->invitee->id;
$orders = Order::where('company_module_id', $company_module_id)->get();
foreach ($orders as $order){
$invoices = $order->transactions()->where('transactions.type', TransactionType::SHIPPING_INVOICE)->get();
foreach ($invoices as $invoice){
dump($invoice->id);
$invoice->documents()->delete();
$transaction_invoice_pdf = LaravelMpdf::loadView('pages.pdfs.shipping_invoice', ['invoice_transaction' => $invoice]);
$document_object = new DocumentObject(
DocumentType::SHIPPING_INVOICE,
[chunk_split('data:application/pdf;base64,'.base64_encode($transaction_invoice_pdf->output()))],
'',
ApprovalStatus::COMPLETED,
'shipping_invoice'
);
/** @var Document $document */
$document = (App()->make(CreatesDocument::class))->execute($invoice, $document_object);
(App()->make(CreatesFiles::class))->execute($document, $document_object);
}
}
}
}
@@ -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);
}
}
+59
View File
@@ -0,0 +1,59 @@
<?php
namespace App\Console\Commands;
use App\Classes\Modules\Transactions\Processors\ApproveShippingInvoiceTransactionProcessor;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Transaction;
use Exception;
use Illuminate\Console\Command;
class approveInvoice extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'approve:invoice';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Command description';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$invoices = Transaction::where('type', TransactionType::SHIPPING_INVOICE)->where('status', ApprovalStatus::PENDING_SUBMISSION)->get();
foreach ($invoices as $invoice) {
$packingList = $invoice->owner;
$order = $packingList->owner;
try {
(App()->make(ApproveShippingInvoiceTransactionProcessor::class))->execute($packingList);
$this->info('Invoice Approved for reference ' . $order->reference . '.');
} catch (Exception $exception) {
$this->info('Failed to Approve invoice for reference ' . $order->reference . '. Exception: ' . $exception->getMessage());
}
}
}
}

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