Compare commits

..

223 Commits

Author SHA1 Message Date
Edmond Lang 1c291134a1 admin move order 2026-01-25 23:39:44 +08:00
Edmond Lang 66576b6eea no message 2026-01-25 23:13:09 +08:00
Dillon Ngo 7be3614f96 New anthropic claude service to replace openai chatgpt 2026-01-25 15:31:00 +08:00
Dillon Ngo 9a1b33a413 Fix a problem reported by Eileen for an order with cbm calculation issue, removal of inline hardcode, use segment settings instead 2026-01-21 19:16:17 +08:00
Dillon Ngo 70ad358e5d Merge branch 'dillon/90-e-invoice-shipping-portal-e' into vapor/production 2026-01-19 10:56:48 +08:00
Dillon Ngo c8249b9276 E-Invoice - Allow admin to download all reports 2026-01-19 10:56:14 +08:00
Dillon Ngo 0484eabb0e Quick fix for group payment issue got stuck reported by enqi 2026-01-06 10:20:04 +08:00
Dillon Ngo 7a5cf5f2ce Quick fix for group payment issue got stuck reported by enqi 2026-01-06 10:08:37 +08:00
Dillon Ngo 49a31a743c Allow all admin role type to view tracking no 2025-12-17 12:52:47 +08:00
Dillon Ngo f3d6521e2c CSS / UI Update 2025-12-09 11:01:49 +08:00
Dillon Ngo f7a9358202 Merge branch 'dillon/123-update-district-listing-ui-to-show-state-info' into vapor/production 2025-12-07 17:36:23 +08:00
Dillon Ngo db499bfecf Fix district listing to display state info for clarity when 2 state share the same district name 2025-12-07 16:53:28 +08:00
Dillon Ngo 0538653bca Fix district listing to display state info for clarity when 2 state share the same district name 2025-12-07 16:52:20 +08:00
Dillon Ngo 9147a4cfec Fix district listing to display state info for clarity when 2 state share the same district name 2025-12-07 16:13:08 +08:00
Dillon Ngo a20f4ed9be Fix district listing to display state info for clarity when 2 state share the same district name 2025-12-07 15:50:19 +08:00
Dillon Ngo d542a20f76 Fix district listing to display state info for clarity when 2 state share the same district name 2025-12-07 15:36:39 +08:00
Dillon Ngo 6d20c8d49e Fix district listing to display state info for clarity when 2 state share the same district name 2025-12-07 14:22:11 +08:00
Dillon Ngo f02220fda8 Merge branch 'dillon/90-e-invoice-shipping-portal-e' into vapor/production 2025-12-05 08:08:51 +08:00
Dillon Ngo 2bf511a1cb E-Invoice - Fix Process E-Invoices button missed some orders left unprocessed 2025-12-05 08:08:33 +08:00
Dillon Ngo 4242777e7d Fix double wallet top up for group payment transaction problem 2025-12-02 16:03:32 +08:00
Dillon Ngo 65bd979b31 Fix double wallet top up for group payment transaction problem 2025-12-02 12:23:12 +08:00
Dillon Ngo e0213108d2 Fix a broken link at wallet details page 2025-11-28 12:07:50 +08:00
Dillon Ngo 71f50b646b Fix a unsucccessful group payment reported by Eileen 2025-11-19 09:19:37 +08:00
Dillon Ngo 2a662b42e0 Fix a unsucccessful group payment reported by Eileen 2025-11-17 21:06:03 +08:00
Dillon Ngo 024e0d666a Fix a unsucccessful group payment reported by Eileen 2025-11-17 20:47:47 +08:00
Dillon Ngo 37119344f3 Fix a problem on invoice generated has incorrect freight service charge (reported by Brian) 2025-11-17 19:48:56 +08:00
Dillon Ngo 37cb4fca18 Fix an issue reported by Eileen on order tracking page drive info not support to appear 2025-11-13 21:37:24 +08:00
Dillon Ngo 37e8bf4d9a Attempt to fix container integration from YD API with duplication 2025-11-08 04:52:19 +08:00
Dillon Ngo 0df85daf2e E-Invoice - Update 'Process E-Invoice' date range filtering target 2025-11-06 23:08:24 +08:00
Dillon Ngo 650cfba74a E-Invoice - Update 'Process E-Invoice' date range filtering target 2025-11-06 22:40:16 +08:00
Dillon Ngo 7f94148ed9 E-Invoice - Update Sales Invoice Report to have paid and unpaid invoices in the report 2025-10-24 13:37:07 +08:00
Dillon Ngo 539da4f551 E-Invoice - Update Sales Invoice Report to have paid and unpaid invoices in the report 2025-10-24 13:35:47 +08:00
Dillon Ngo 7c8f5fe791 E-Invoice - Update Sales Invoice Report to have paid and unpaid invoices in the report 2025-10-24 13:06:57 +08:00
Dillon Ngo 60c083a9cf E-Invoice - Update Sales Invoice Report to have paid and unpaid invoices in the report 2025-10-24 12:58:01 +08:00
Dillon Ngo 5b32fe9d6f E-Invoice - Update Sales Invoice Report to have paid and unpaid invoices in the report 2025-10-24 12:52:01 +08:00
Dillon Ngo d315880067 E-Invoice - Fix some problem reported y Mira on exporting report 2025-10-24 12:34:56 +08:00
Dillon Ngo 9cd2051cac E-Invoice - Update Sales Invoice Report to have paid and unpaid invoices in the report 2025-10-23 19:31:27 +08:00
Dillon Ngo 8c3e8fdeaf E-Invoice - Update Sales Invoice Report to have paid and unpaid invoices in the report 2025-10-23 19:18:48 +08:00
Dillon Ngo c31e7aaf37 E-Invoice - Update Sales Invoice Report to have paid and unpaid invoices in the report 2025-10-23 19:06:41 +08:00
Dillon Ngo 5b6f419d9e E-Invoice - Update Sales Invoice Report to have paid and unpaid invoices in the report 2025-10-23 18:52:27 +08:00
Dillon Ngo c7f00a7ce2 E-Invoice - Update Sales Invoice Report to have paid and unpaid invoices in the report 2025-10-23 18:17:56 +08:00
Dillon Ngo 35932e5351 E-Invoice - Update Sales Invoice Report to have paid and unpaid invoices in the report 2025-10-23 18:04:13 +08:00
Dillon Ngo 012b88ee37 E-Invoice - Update Sales Invoice Report to have paid and unpaid invoices in the report 2025-10-23 17:48:55 +08:00
Dillon Ngo 88869dcadb E-Invoice - Update Sales Invoice Report to have paid and unpaid invoices in the report 2025-10-23 17:30:15 +08:00
Dillon Ngo df1d80756a E-Invoice - Update Sales Invoice Report to have paid and unpaid invoices in the report 2025-10-23 17:10:57 +08:00
Dillon Ngo 066f5f52d5 E-Invoice - Update Sales Invoice Report to have paid and unpaid invoices in the report 2025-10-23 16:54:44 +08:00
Dillon Ngo 4d76ffd545 E-Invoice - Update Sales Invoice Report to have paid and unpaid invoices in the report 2025-10-23 16:15:17 +08:00
Dillon Ngo 58f62de2e8 E-Invoice - Update Sales Invoice Report to have paid and unpaid invoices in the report 2025-10-23 16:03:12 +08:00
Dillon Ngo 773b30d224 E-Invoice - Update Sales Invoice Report to have paid and unpaid invoices in the report 2025-10-23 15:12:57 +08:00
Dillon Ngo 74811f177c E-Invoice - Update Sales Invoice Report to have paid and unpaid invoices in the report 2025-10-23 15:09:50 +08:00
Dillon Ngo 82de9ae6f9 E-Invoice - Update Sales Invoice Report 2025-10-21 15:57:15 +08:00
Dillon Ngo 6cb27096f7 E-Invoice - New Report Export (Sales Invoice Report, unpaid) 2025-10-18 15:08:48 +08:00
Dillon Ngo 10660b8350 Merge branch 'dillon/90-e-invoice-shipping-portal-e-1' into vapor/production 2025-10-14 12:41:26 +08:00
Dillon Ngo 5c42d383d0 Merge branch 'dillon/90-e-invoice-shipping-portal-f' into dillon/90-e-invoice-shipping-portal-e-1 (Lost Tracked Task) 2025-10-14 12:40:40 +08:00
Dillon Ngo d3966e8b28 Merge branch 'dillon/90-e-invoice-shipping-portal-e' into vapor/production 2025-10-05 13:47:12 +08:00
Dillon Ngo 6a4570442a E-Invoice - Amendment for storage invoice to generate E-Invoice 2025-10-05 12:12:45 +08:00
Edmond Lang 300f7b6642 fix bug: unexpected token "use" (View: /Users/edmondlang/Herd/shipping-portal/resources/views/pages/pdfs/shipping_invoices_sst_combined_v2.blade.php) 2025-10-03 16:41:36 +08:00
Dillon Ngo c28ee64878 Fix a problem reported by Brian where minimum charge not suppose to be applied 2025-10-01 18:26:52 +08:00
Dillon Ngo ce6b47763c E-Invoice - Amendment for storage invoice to generate E-Invoice (partial completion) 2025-09-29 14:21:03 +08:00
Dillon Ngo 881dd71ef0 E-Invoice - Amendment for storage invoice to generate E-Invoice (partial completion) 2025-09-26 09:27:26 +08:00
Dillon Ngo beec9aef24 E-Invoice - Amendment for storage invoice to generate E-Invoice (partial completion) 2025-09-26 09:04:39 +08:00
Dillon Ngo fcd6f2d6a8 E-Invoice - Amendment for storage invoice to generate E-Invoice (partial completion) 2025-09-25 17:46:33 +08:00
Dillon Ngo ae15575b0a E-Invoice - Update einvoice template qr code appearance (code sync from Exchange) 2025-09-24 17:24:01 +08:00
Dillon Ngo 4a66578380 E-Invoice - New Report Export (11D - IZYIM - RECEIVE PAYMENT (FULL PAYMENT) [AR DEPOSIT ENTRY] - Update 2025-09-24 13:10:49 +08:00
Dillon Ngo ffbf6b0f9c E-Invoice - New Report Export (11D - IZYIM - RECEIVE PAYMENT (FULL PAYMENT) [AR DEPOSIT ENTRY] - Update 2025-09-24 08:09:49 +08:00
Dillon Ngo 1e4d2c8031 E-Invoice - New Report Export (11D - IZYIM - RECEIVE PAYMENT (FULL PAYMENT) [AR DEPOSIT ENTRY] - Update 2025-09-23 17:20:29 +08:00
Dillon Ngo 2122d18be5 E-Invoice - Update to Sales Invoice Report template ref column 2025-09-23 17:06:43 +08:00
Dillon Ngo 0e9ef67121 Merge branch 'dillon/90-e-invoice-shipping-portal-f' into vapor/production 2025-09-23 13:31:40 +08:00
Dillon Ngo c2511e2467 E-Invoice - New Report Import (11R - IZYIM - RECEIVE PAYMENT (FULL PAYMENT) [AR RECEIVE PAYMENT]) 2025-09-22 11:35:48 +08:00
Dillon Ngo e663165654 E-Invoice - New Report Import (11R - IZYIM - RECEIVE PAYMENT (FULL PAYMENT) [AR RECEIVE PAYMENT]) 2025-09-22 11:21:39 +08:00
Dillon Ngo e80e52d04e E-Invoice - New Report Export (11R - IZYIM - RECEIVE PAYMENT (FULL PAYMENT) [AR RECEIVE PAYMENT]) 2025-09-22 09:17:01 +08:00
Dillon Ngo eed5559cbf E-Invoice - New Report Export (11D - IZYIM - RECEIVE PAYMENT (FULL PAYMENT) [AR DEPOSIT ENTRY] 2025-09-19 14:44:31 +08:00
Dillon Ngo 7fdb579ab8 E-Invoice - New Report Export (11D - IZYIM - RECEIVE PAYMENT (FULL PAYMENT) [AR DEPOSIT ENTRY] 2025-09-19 12:11:17 +08:00
Dillon Ngo 6c5c5a9d34 Merge branch 'dillon/90-e-invoice-shipping-portal-f' into dillon/90-e-invoice-shipping-portal-e-1 2025-09-18 12:46:40 +08:00
Dillon Ngo 1d45a7aadf Remove redundant code 2025-09-16 14:04:03 +08:00
Dillon Ngo 81474625eb Remove redundant code 2025-09-16 13:52:59 +08:00
Dillon Ngo 769becfc16 E-Invoice - Code sync from Exchange 2025-09-16 12:59:33 +08:00
Dillon Ngo 6ee296ef06 New updated business logic for storage invoice calculation 2025-09-09 12:25:54 +08:00
Dillon Ngo e0e6e53e63 New updated business logic for storage invoice calculation 2025-09-07 21:20:15 +08:00
Dillon Ngo 9a90e8cf80 New updated business logic for storage invoice calculation 2025-09-06 15:13:12 +08:00
Dillon Ngo 4db8b24b22 Merge branch 'dillon/90-e-invoice-shipping-portal-e' into vapor/production 2025-09-02 05:19:39 +08:00
Dillon Ngo d5e008d4f3 E-Invoice - Reinstate some commented code 2025-09-02 05:09:39 +08:00
Dillon Ngo 7a6655c3d9 E-Invoice - Project 27, IZYIM - Sales Invoice - Batch process for E-Invoices 2025-09-02 04:56:44 +08:00
Dillon Ngo 7fbee7b047 E-Invoice - Project 27, IZYIM - Sales Invoice - Batch process for E-Invoices 2025-09-02 04:30:18 +08:00
Edmond Lang 2edd44a218 Update ExportsArrivedParcel -> so that the "/warehouse-list" Arrived Parcel is showing the same thing as the export 2025-09-01 22:10:49 +08:00
Edmond Lang a8d86eebd6 fix php error for HasParcelWithTransportBetweenDate 2025-09-01 22:00:13 +08:00
Edmond Lang 6f2b374cbd Add Filters for "/warehouse-list" -> Arrived Parcel 2025-09-01 20:46:45 +08:00
Dillon Ngo 3fb7befd62 E-Invoice - Project 27, IZYIM - Sales Invoice - Import 2025-08-31 17:39:07 +08:00
Dillon Ngo 8607caa84f E-Invoice - Project 27, IZYIM - Sales Invoice - Import 2025-08-31 17:04:57 +08:00
Dillon Ngo 47d564ec09 E-Invoice - Project 27, IZYIM - Sales Invoice - Export 2025-08-30 18:11:27 +08:00
Dillon Ngo 8031db446e Merge branch 'vapor/production' into dillon/90-e-invoice-shipping-portal-e 2025-08-28 10:16:03 +08:00
Dillon Ngo 62177bd3d0 Fix Identification verification listing for admin at dashboard not showing properly 2025-08-19 01:15:50 +08:00
Dillon Ngo 76512b107b Merge branch 'vapor/production' into dillon/90-e-invoice-shipping-portal-e 2025-08-19 01:07:33 +08:00
Dillon Ngo b8f284c2c0 Cleanup + Code Refactor 2025-08-16 10:39:45 +08:00
Dillon Ngo 5db1579c36 Cleanup + Code Refactor 2025-08-16 10:30:58 +08:00
Dillon Ngo 7615c3ef3e Merge branch 'vapor/production' into dillon/100-cleanup 2025-08-16 10:23:04 +08:00
Dillon Ngo d8f1262ec2 Cleanup + Code Refactor 2025-08-15 09:14:43 +08:00
Dillon Ngo 5b8893068c Fix a problem reported by Eileen of a group payment double charge problempayment through wallet 2025-08-14 04:12:54 +08:00
Dillon Ngo 1810809113 Fix a problem reported by Eileen of a group payment double charge problempayment through wallet 2025-08-14 03:39:52 +08:00
Dillon Ngo 9d4daeeb46 Debug an old 504 problem at payment-and-billing page > pending payment tab with no data 2025-08-11 11:44:14 +08:00
Dillon Ngo 84e23ec80f Merge branch 'dillon/90-e-invoice-shipping-portal-e' into vapor/production 2025-08-11 11:40:37 +08:00
Dillon Ngo 5b2e3a1828 Debug an old 504 problem at payment-and-billing page > pending payment tab with no data 2025-08-11 11:39:45 +08:00
Dillon Ngo c52b577c19 Cleanup + Code Refactor 2025-08-11 04:59:58 +08:00
Dillon Ngo 8f6443d536 Merge branch 'dillon/90-e-invoice-shipping-portal-e-2' into vapor/production 2025-08-09 23:23:18 +08:00
Dillon Ngo 5414be594d Debug an old 504 problem at payment-and-billing page > pending payment tab with no data 2025-08-09 21:16:05 +08:00
Dillon Ngo 0625c37cdc Debug an old 504 problem at payment-and-billing page > pending payment tab with no data 2025-08-09 20:30:42 +08:00
Dillon Ngo bdc45282a4 Debug an old 504 problem at payment-and-billing page > pending payment tab with no data 2025-08-09 20:12:37 +08:00
Dillon Ngo a716a7a38b Debug an old 504 problem at payment-and-billing page > pending payment tab with no data 2025-08-09 19:55:05 +08:00
Dillon Ngo b3d904f3c8 Debug an old 504 problem at payment-and-billing page > pending payment tab with no data 2025-08-09 19:16:29 +08:00
Dillon Ngo d8f3f50bb0 Debug an old 504 problem at payment-and-billing page > pending payment tab with no data 2025-08-09 18:44:31 +08:00
Dillon Ngo 6d26f690c0 Debug an old 504 problem at payment-and-billing page > pending payment tab with no data 2025-08-09 18:10:53 +08:00
Dillon Ngo f061b5eb86 Debug an old 504 problem at payment-and-billing page > pending payment tab with no data 2025-08-09 17:35:05 +08:00
Dillon Ngo e83e8aa5c8 Merge branch 'dillon/90-e-invoice-shipping-portal-b-debug-1' into dillon/90-e-invoice-shipping-portal-e-2 2025-08-09 17:24:43 +08:00
Dillon Ngo b6e4bbd94c Merge branch 'dillon/90-e-invoice-shipping-portal-e' into vapor/production 2025-08-08 22:21:03 +08:00
Dillon Ngo ca8e69b17a E-Invoice - State list to only show Malaysia states 2025-08-08 22:08:13 +08:00
Edmond Lang d99566a431 sin yee's request: add email for debtor's export 2025-08-06 21:43:45 +08:00
Dillon Ngo 6ce38e5751 Merge branch 'dillon/90-e-invoice-shipping-portal-e' into vapor/production 2025-08-05 19:48:05 +08:00
Dillon Ngo 8564667c62 Fix a problem reported by Eileen where storage invoice has negative charges 2025-08-05 19:47:42 +08:00
Edmond Lang 7da665ca5b Fix: negative storage fee issue 2025-08-05 17:27:04 +08:00
Edmond Lang 2cee63789b Fix: negative storage fee issue 2025-08-05 17:14:50 +08:00
Dillon Ngo 8fbd377965 E-Invoice - Emergency fix error reported by Eileen pending approval list at payment & billing page not showing anything 2025-08-04 17:25:04 +08:00
Dillon Ngo 11ac78881c Merge branch 'dillon/90-e-invoice-shipping-portal-f' into vapor/production 2025-07-31 23:57:30 +08:00
Dillon Ngo cc49336a4d Merge branch 'dillon/90-e-invoice-shipping-portal-b-2' into vapor/production 2025-07-30 22:11:37 +08:00
Dillon Ngo 1380d99109 E-Invoice - Project 27: Import Tax Entity, Customers Data Report 2025-07-30 21:44:55 +08:00
Edmond Lang 42e6e82df8 if billing address is null, when update e invoice details, add billing address 2025-07-24 21:49:24 +08:00
Dillon Ngo 7cac5b937f E-Invoice - IZYIM DOC DELIVERY - Part 2 (updated business logic) 2025-07-24 17:55:30 +08:00
Dillon Ngo 812f16a191 E-Invoice - IZYIM DOC DELIVERY - Part 2 (updated business logic) 2025-07-24 17:47:44 +08:00
Dillon Ngo 1073b6484c Merge branch 'dillon/90-e-invoice-shipping-portal-e' into dillon/90-e-invoice-shipping-portal-b-2 2025-07-24 16:46:15 +08:00
Dillon Ngo 549bf98725 E-Invoice - New request from Anitha billing address should follow einvoice address if exist at Pending Invoice tab at payment and billing page 2025-07-24 06:18:14 +08:00
Dillon Ngo e3afc2b008 Fix Paid Group Invoices 504 error 2025-07-09 01:19:02 +08:00
Dillon Ngo d0decc6c7b Merge branch 'vapor/production' into dillon/90-e-invoice-shipping-portal-e 2025-07-09 00:11:32 +08:00
Dillon Ngo 312b467564 Paid Group Invoices 504 error debug 2025-07-08 23:32:16 +08:00
Dillon Ngo 7adf03cf06 E-Invoice - IZYIM DOC DELIVERY - Part 2 - debug 2025-07-08 13:21:19 +08:00
Dillon Ngo 018c3eb755 Merge branch 'dillon/90-e-invoice-shipping-portal-e' into vapor/production 2025-07-08 02:42:43 +08:00
Dillon Ngo b8707fbb0d Merge branch 'dillon/90-e-invoice-shipping-portal-e' into vapor/production 2025-07-08 02:42:25 +08:00
Dillon Ngo 134e0d86ea E-Invoice - Disable auto generate E-Invoice 2025-07-08 02:42:05 +08:00
Dillon Ngo 3d70a42758 E-Invoice - IZYIM DOC DELIVERY - Part 2 (updated business logic) 2025-07-08 02:39:20 +08:00
Dillon Ngo 9ef56454a0 Merge branch 'dillon/90-e-invoice-shipping-portal-e' into vapor/production 2025-07-07 23:30:03 +08:00
Dillon Ngo ea1c447fa1 Fix a UI problem reported by Joanne for clarity 2025-07-07 23:29:49 +08:00
Dillon Ngo 79679fe2e0 Merge branch 'dillon/90-e-invoice-shipping-portal-e' into vapor/production 2025-07-07 23:15:28 +08:00
Dillon Ngo 5c1a4536f6 Fix a problem reported by Yien where admin cannot approve an invoice 2025-07-07 23:15:13 +08:00
Dillon Ngo 345c8d24ca E-Invoice - IZYIM DOC DELIVERY - Part 2 2025-07-07 05:36:50 +08:00
Dillon Ngo d986787c4c Merge branch 'dillon/90-e-invoice-shipping-portal-e-1' into dillon/90-e-invoice-shipping-portal-b-2 2025-07-06 19:31:16 +08:00
Dillon Ngo 3281625e92 Looked into a 504 error order show page 2025-07-06 03:15:52 +08:00
Dillon Ngo 71e9a479d9 Looked into a 504 error order show page 2025-07-06 01:58:16 +08:00
Dillon Ngo 5fef38a04b Looked into a 504 error order show page 2025-07-05 16:01:42 +08:00
Dillon Ngo bf22b86a02 Looked into a 504 error order show page 2025-07-05 14:52:50 +08:00
Dillon Ngo 3b0738219f E-Invoice - Fix a problem with normal invoice shown to user opted in for einvoice 2025-07-05 01:58:24 +08:00
Dillon Ngo 18434903ac Merge branch 'dillon/90-e-invoice-shipping-portal-e' into vapor/production 2025-07-04 00:13:34 +08:00
Dillon Ngo c2d51fc502 E-Invoice - Hide 'Change Billing Address' button when user already opt in for e-invoice 2025-07-04 00:11:24 +08:00
Dillon Ngo be0d10416b Merge branch 'dillon/90-e-invoice-shipping-portal-b' into vapor/production 2025-07-03 13:53:09 +08:00
Dillon Ngo 9cc80e6965 Merge branch 'dillon/90-e-invoice-shipping-portal-e' into dillon/90-e-invoice-shipping-portal-b-2 2025-07-03 06:24:10 +08:00
Dillon Ngo 9991524a2e Merge branch 'dillon/90-e-invoice-shipping-portal-e' into vapor/production 2025-07-03 06:17:03 +08:00
Dillon Ngo 7808d0d5ae Merge branch 'dillon/90-e-invoice-shipping-portal-e' into vapor/production 2025-07-03 06:16:12 +08:00
Dillon Ngo 3d7d571370 E-Invoice -
Allow SSM Registration / Identification Card number to be upda
ted without a document upload mainly for old customer
2025-07-02 19:02:14 +08:00
Dillon Ngo 955b454630 E-Invoice -
Allow SSM Registration / Identification Card number to be upda
ted without a document upload mainly for old customer
2025-07-02 18:54:24 +08:00
Dillon Ngo f45ea797d6 E-Invoice -
Allow SSM Registration / Identification Card number to be upda
ted without a document upload mainly for old customer
2025-07-02 18:40:46 +08:00
Dillon Ngo efd734bbdb Merge branch 'dillon/90-e-invoice-shipping-portal-e' into vapor/production 2025-07-02 00:48:32 +08:00
Dillon Ngo 0c849ee302 E-Invoice - New request to allow user to change of mi
nd when filling up einvoice info form to opt out when they already opt in for e-invoice
2025-07-02 00:13:02 +08:00
Edmond Lang 9c9d4fe594 update menu icon 2025-07-01 12:37:09 +08:00
Dillon Ngo 167216c26f Merge branch 'dillon/90-e-invoice-shipping-portal-e' into vapor/production 2025-06-30 23:48:46 +08:00
Dillon Ngo d97796d885 E-Invoice - Disable maintenance page for normal user 2025-06-30 23:33:05 +08:00
Dillon Ngo 2bd66f6786 Merge branch 'dillon/90-e-invoice-shipping-portal-e' into vapor/production 2025-06-30 15:46:33 +08:00
Dillon Ngo c64f6f5da5 E-Invoice - Sin Yee requestion for ability for admin to edit SSM Registration and Identification Card 2025-06-30 15:46:09 +08:00
Dillon Ngo da7843c5df E-Invoice - Sin Yee requestion for ability for admin to edit SSM Registration and Identification Card 2025-06-30 00:45:41 +08:00
Dillon Ngo 2463e419c8 Merge branch 'dillon/90-e-invoice-shipping-portal-e' into vapor/production 2025-06-29 17:53:18 +08:00
Dillon Ngo 2cbee23234 E-Invoice - Debug Pending Payment at /payment-and-billing no data (undo) 2025-06-29 17:52:07 +08:00
Dillon Ngo dca9682c59 E-Invoice - Debug Pending Payment at /payment-and-billing no data (undo) 2025-06-29 17:38:52 +08:00
Dillon Ngo b417ba074e E-Invoice - Sin Yee request for einvoice postcode need to able to input starting with 0, e.g. 02600 2025-06-29 16:22:15 +08:00
Edmond Lang 5767ab1853 add new menu "E-Invoice Guideline" - open in new tab 2025-06-28 23:41:03 +08:00
Dillon Ngo a7aad5373b E-Invoice - Debug Pending Payment at /payment-and-billing no data 2025-06-28 19:51:52 +08:00
Dillon Ngo cad314d6a7 E-Invoice - Debug Pending Payment at /payment-and-billing no data 2025-06-28 19:25:57 +08:00
Dillon Ngo 137dfe0669 E-Invoice - Debug Pending Payment at /payment-and-billing no data 2025-06-28 17:14:33 +08:00
Dillon Ngo 52b839c741 E-Invoice - Debug Pending Payment at /payment-and-billing no data 2025-06-28 16:32:22 +08:00
Dillon Ngo d8ee9f1e67 Merge branch 'dillon/90-e-invoice-shipping-portal-e' into vapor/production 2025-06-28 16:13:14 +08:00
Dillon Ngo 620b9651a3 Merge branch 'dillon/90-e-invoice-shipping-portal-a' into dillon/90-e-invoice-shipping-portal-e 2025-06-28 16:11:54 +08:00
Dillon Ngo c37ed89a73 E-Invoice - Minor amendment requested by Harry on TIN length validation 2025-06-28 15:57:09 +08:00
Dillon Ngo f56548efa7 E-Invoice - Minor amendment requested by Harry on TIN length validation 2025-06-28 15:30:16 +08:00
Dillon Ngo 679bb9978a E-Invoice - Debug Pending Payment at /payment-and-billing no data 2025-06-28 13:49:32 +08:00
Dillon Ngo 2c6b8ac7ea Merge branch 'dillon/90-e-invoice-shipping-portal-a' into dillon/90-e-invoice-shipping-portal-b-debug-1 2025-06-28 13:46:44 +08:00
Dillon Ngo 9b7a5a6f1e Merge branch 'dillon/90-e-invoice-shipping-portal-a' into dillon/90-e-invoice-shipping-portal-b 2025-06-28 13:46:19 +08:00
Dillon Ngo fbf5fb290e Merge branch 'dillon/90-e-invoice-shipping-portal-a' into vapor/production 2025-06-28 13:45:49 +08:00
Dillon Ngo 63902e9266 E-Invoice - Allow admin to update E-Invoice info on behalf of customer 2025-06-28 13:45:24 +08:00
Dillon Ngo 1a318ead7e E-Invoice - Debug Pending Payment at /payment-and-billing no data 2025-06-28 13:35:42 +08:00
Dillon Ngo bd8b212f6f E-Invoice - Debug Pending Payment at /payment-and-billing no data 2025-06-28 12:49:18 +08:00
Dillon Ngo 59fbdfa789 E-Invoice - Debug Pending Payment at /payment-and-billing no data 2025-06-28 12:27:52 +08:00
Dillon Ngo 2bd96075cc E-Invoice - Debug Pending Payment at /payment-and-billing no data 2025-06-28 12:14:20 +08:00
Dillon Ngo c046a533d8 E-Invoice - Debug Pending Payment at /payment-and-billing no data 2025-06-28 11:35:02 +08:00
Dillon Ngo 8e6c70c67b E-Invoice - Debug Pending Payment at /payment-and-billing no data 2025-06-28 11:14:44 +08:00
Dillon Ngo 878e69fdb0 E-Invoice - Debug Pending Payment at /payment-and-billing no data 2025-06-28 11:00:34 +08:00
Dillon Ngo e047632de0 E-Invoice - Debug Pending Payment at /payment-and-billing no data 2025-06-28 10:45:55 +08:00
Dillon Ngo 8d75da288a E-Invoice - Debug Pending Payment at /payment-and-billing no data 2025-06-28 10:32:48 +08:00
Dillon Ngo ab5a94cbc0 E-Invoice - Debug Pending Payment at /payment-and-billing no data 2025-06-28 10:16:48 +08:00
Edmond Lang 17d8c82cff update /export/all-customers-info-for-lark-system, fix duplications on customer connections - use the first one 2025-06-27 16:53:28 +08:00
Edmond Lang 8f80c7ac8c Merge branch 'vapor/production' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into vapor/production 2025-06-27 16:24:49 +08:00
Edmond Lang 9c09b1e01d update /export/all-customers-info-for-lark-system, fix duplications on customer connections - use the first one 2025-06-27 16:21:28 +08:00
Dillon Ngo 6911eba119 E-Invoice - Updated maintenance message 2025-06-27 12:52:05 +08:00
Dillon Ngo c564a8ed70 E-Invoice - Updated maintenance message 2025-06-27 12:46:18 +08:00
Dillon Ngo 273f81f9a8 E-Invoice - Updated maintenance message 2025-06-27 12:25:09 +08:00
Dillon Ngo ba1b287cbb E-Invoice - Minor UI update 2025-06-27 01:11:32 +08:00
Dillon Ngo 40d133aaab E-Invoice - Minor text display update 2025-06-27 00:43:41 +08:00
Dillon Ngo d52a52241c Merge branch 'dillon/90-e-invoice-shipping-portal-a' into dillon/90-e-invoice-shipping-portal-b 2025-06-27 00:40:19 +08:00
Dillon Ngo df9468d568 Merge branch 'dillon/90-e-invoice-shipping-portal-a' into vapor/production 2025-06-27 00:36:39 +08:00
Dillon Ngo 6d12f2d239 E-Invoice - Allow admin to view order without triggering rule checking 2025-06-27 00:34:14 +08:00
Dillon Ngo fe18d8bf5a Merge branch 'dillon/90-e-invoice-shipping-portal-a' into vapor/production 2025-06-27 00:26:57 +08:00
Dillon Ngo 3913d3c738 E-Invoice - Remove outdated code 2025-06-27 00:26:14 +08:00
Dillon Ngo be9df4afe3 Merge branch 'dillon/90-e-invoice-shipping-portal-a' into vapor/production 2025-06-27 00:07:06 +08:00
Dillon Ngo 82512bf4f6 E-Invoice - Sync some code fixes from Exchange to Shipping Portal 2025-06-26 23:13:17 +08:00
Dillon Ngo a9d4f3c839 E-Invo
ice - Maintenance notice for
normal user except admin
2025-06-26 20:04:11 +08:00
Dillon Ngo 218f0f8bca E-Invoice - IZYIM DOC DELIVERY 2025-06-26 18:29:15 +08:00
Edmond Lang 79db1dedc9 update /export/all-customers-info-for-lark-system, add is credit term customer 2025-06-26 17:45:13 +08:00
Edmond Lang 2aabd07ec4 update /export/all-customers-info-for-lark-system, add Debtor Code 2025-06-26 16:29:09 +08:00
Dillon Ngo 1d2eac806e E-Invoice - Initial commit main feature integration 2025-06-20 14:34:13 +08:00
Dillon Ngo 8d0fba2d21 E-Invoice - Initial commit main feature integration 2025-06-20 10:40:46 +08:00
Dillon Ngo b4c239f8a9 E-Invoice - Initial commit main feature integration 2025-06-20 10:00:26 +08:00
Dillon Ngo b3e8e5ea54 E-Invoice - Initial commit main feature integration 2025-06-20 09:41:17 +08:00
Edmond Lang ed4ec29d63 update /export/all-customers-info-for-lark-system 2025-06-13 00:44:03 +08:00
Edmond Lang ba5fd5f92d update /export/all-customers-info-for-lark-system 2025-06-13 00:36:23 +08:00
Edmond Lang e6028701db fix /export/all-customers-info-for-lark-system - handle json response 2025-06-12 23:53:47 +08:00
Edmond Lang fb2ca65168 add frontend for download /export/all-customers-info-for-lark-system 2025-06-12 23:31:09 +08:00
Edmond Lang 8ab9a0ba2d fix /export/all-customers-info-for-lark-system for php 7.4 issue 2025-06-12 23:03:38 +08:00
Edmond Lang 78ac0dbd8f test fix - {"message": "Endpoint request timed out"} 2025-06-12 22:48:58 +08:00
Edmond Lang e9c3af51c4 fix /export/all-customers-info-for-lark-system for php 7.4 issue 2025-06-12 22:35:10 +08:00
423 changed files with 16764 additions and 9138 deletions
+6 -9
View File
@@ -10,9 +10,9 @@ LOG_LEVEL=debug
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=shpping_portal
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=root
DB_PASSWORD=
BROADCAST_DRIVER=log
CACHE_DRIVER=file
@@ -56,20 +56,17 @@ MIX_EXCHANGE_URL="${EXCHANGE_URL}"
YD_API_CODE=''
JWT_SECRET=Btj63iMEleEaww6Bb2IBECkxWn7YHPhhPFluAkg9DfcQik0qDRy6QW75ABGmPT2h
PERFEXCRM_BASE_URL=""
PERFEXCRM_API_KEY=""
PERFEXCRM_IS_ENABLED="false"
WEPOST_BASE_URL=https://wepost-uat.90warehouse.com/api/router
WEPOST_CLIENT_ID=1234
WEPOST_CLIENT_SECRET=cief-secret-temp
WEPOST_IS_ENABLED=false
VAPOR_ENV=local
LARAVEL_VAPOR_ENABLED=false
COMMANDS_V2_ENABLED=false
STORAGE_FEE_LAUNCH_DATE="2023-12-11 00:00:00"
SST_START_DATE="2024-04-01 00:00:00"
E_INVOICE_START_DATE="2025-07-01 00:00:00"
MAINTENANCE_MESSAGE_TITLE="We'll be back online on 00:00 1/7/2025"
MAINTENANCE_MESSAGE="Sorry for the inconvenience but we're performing some maintenance at the moment."
-59
View File
@@ -1,59 +0,0 @@
APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:rIar2fvNeRzQdvKOgLUg03detGDMx6ym2SYFRjawrAc=
APP_DEBUG=true
APP_URL=http://localhost
LOG_CHANNEL=stack
LOG_LEVEL=debug
# DB_CONNECTION=mysql
# DB_HOST=127.0.0.1
# DB_PORT=3306
# DB_DATABASE=shpping_portal
# DB_USERNAME=root
# DB_PASSWORD=P@ssw0rd
BROADCAST_DRIVER=log
CACHE_DRIVER=file
FILESYSTEM_DRIVER=local
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
MEMCACHED_HOST=127.0.0.1
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=null
MAIL_FROM_NAME="${APP_NAME}"
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
UNITY_APP_URL="https://unity.izyim.com"
EXCHANGE_URL=https://dev.exchange.cief-malaysia.com/
MIX_EXCHANGE_URL="${EXCHANGE_URL}"
YD_API_CODE=''
JWT_SECRET=Btj63iMEleEaww6Bb2IBECkxWn7YHPhhPFluAkg9DfcQik0qDRy6QW75ABGmPT2h
-2
View File
@@ -2,8 +2,6 @@
/public/hot
/public/storage
/storage/*.key
/tests/_output
/tests/_support
/vendor
**/.idea/
.env
-129
View File
@@ -1,129 +0,0 @@
image: php:7.4
stages:
- service_build
- node
- building_assets
- database
- unit_test
- acceptance_test
- code_quality
# Variables
variables:
MYSQL_ROOT_PASSWORD: root
MYSQL_USER: mysql_password
MYSQL_PASSWORD: mysql_password
MYSQL_DATABASE: shpping_portal
DB_HOST: mysql
before_script:
- apt-get update -yqq
- apt-get install -yqq
- apt-get install -y libonig-dev
- apt-get install -y libxml2-dev
- apt-get install -y libzip-dev
- apt-get install -y libgd-dev
- apt-get install -y libgd-dev
# Install PDO MySQL extension
- docker-php-ext-install pdo_mysql
#install php dependencies
- docker-php-ext-install mbstring xml zip gd
# Install composer package manager
- curl --location --output /usr/local/bin/composer https://getcomposer.org/download/latest-stable/composer.phar
- chmod +x /usr/local/bin/composer
# Install MySQL client
- apt-get install -y default-mysql-client
#install node js
- apt-get update && apt-get install -y nodejs npm
#install gulp Js
- npm install -g gulp-cli
#jobs
#buld the backend
composer_php:
stage: service_build
script:
- composer install
- cp .env.example .env
- php artisan key:generate
rules:
- when: never
# rules:
# - if: '$CI_COMMIT_BRANCH =~ /.*/'
#build the UI
#node installation
npm:
stage: node
script:
- npm install # Install npm dependencies
rules:
- when: never
# rules:
# - if: '$CI_COMMIT_BRANCH =~ /.*/'
#building assets
building_assets:
stage: building_assets
# dependencies:
# - npm
script:
- npm install # Install npm dependencies
- gulp build # Build assets
rules:
- when: never
# rules:
# - if: '$CI_COMMIT_BRANCH =~ /.*/'
#mysql
database:
stage: database
services:
- name: mysql:8.0
command: [ "--default-authentication-plugin=mysql_native_password" ]
#dependencies:
# - composer_php
script:
- composer install
- cp .env.example .env
- php artisan key:generate
- php artisan migrate:fresh
- php artisan db:seed
rules:
- when: never
# rules:
# - if: '$CI_COMMIT_BRANCH =~ /.*/'
#mysql
#unit_test:
# stage: unit_test
# services:
# - name: mysql:8.0
# command: [ "--default-authentication-plugin=mysql_native_password" ]
#dependencies:
# - database
# script:
# - npm install # Install npm dependencies
# - gulp build # Build assets
# - composer install
# - cp .env.example .env
# - php artisan key:generate
# - php artisan migrate:fresh
# - php artisan db:seed
# - php artisan test
# rules:
# - if: '$CI_COMMIT_BRANCH =~ /.*/'
+43 -20
View File
@@ -1,39 +1,62 @@
## Shipping portal documentation
<p align="center"><a href="https://laravel.com" target="_blank"><img src="https://raw.githubusercontent.com/laravel/art/master/logo-lockup/5%20SVG/2%20CMYK/1%20Full%20Color/laravel-logolockup-cmyk-red.svg" width="400"></a></p>
simple documentation on how to install, run, test, commit and deploy application
<p align="center">
<a href="https://travis-ci.org/laravel/framework"><img src="https://travis-ci.org/laravel/framework.svg" alt="Build Status"></a>
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/dt/laravel/framework" alt="Total Downloads"></a>
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/v/laravel/framework" alt="Latest Stable Version"></a>
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/l/laravel/framework" alt="License"></a>
</p>
## creating and running unit tests
## About Laravel
Required Tools
Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experience to be truly fulfilling. Laravel takes the pain out of development by easing common tasks used in many web projects, such as:
- Chromium Driver / selenium
- add running and setting selenium on all OS if possible
- [Simple, fast routing engine](https://laravel.com/docs/routing).
- [Powerful dependency injection container](https://laravel.com/docs/container).
- Multiple back-ends for [session](https://laravel.com/docs/session) and [cache](https://laravel.com/docs/cache) storage.
- Expressive, intuitive [database ORM](https://laravel.com/docs/eloquent).
- Database agnostic [schema migrations](https://laravel.com/docs/migrations).
- [Robust background job processing](https://laravel.com/docs/queues).
- [Real-time event broadcasting](https://laravel.com/docs/broadcasting).
Required Packages :
Laravel is accessible, powerful, and provides tools required for large, robust applications.
- laravel/legacy-factories
## Learning Laravel
- codeception/codeception
Laravel has the most extensive and thorough [documentation](https://laravel.com/docs) and video tutorial library of all modern web application frameworks, making it a breeze to get started with the framework.
Or Simply Run
If you don't feel like reading, [Laracasts](https://laracasts.com) can help. Laracasts contains over 1500 video tutorials on a range of topics including Laravel, modern PHP, unit testing, and JavaScript. Boost your skills by digging into our comprehensive video library.
``Composer install``
## Laravel Sponsors
To create a unit test
We would like to extend our thanks to the following sponsors for funding Laravel development. If you are interested in becoming a sponsor, please visit the Laravel [Patreon page](https://patreon.com/taylorotwell).
``php artisan make test: Test Example --unit``
### Premium Partners
Running the tests :
- **[Vehikl](https://vehikl.com/)**
- **[Tighten Co.](https://tighten.co)**
- **[Kirschbaum Development Group](https://kirschbaumdevelopment.com)**
- **[64 Robots](https://64robots.com)**
- **[Cubet Techno Labs](https://cubettech.com)**
- **[Cyber-Duck](https://cyber-duck.co.uk)**
- **[Many](https://www.many.co.uk)**
- **[Webdock, Fast VPS Hosting](https://www.webdock.io/en)**
- **[DevSquad](https://devsquad.com)**
- **[Curotec](https://www.curotec.com/services/technologies/laravel/)**
- **[OP.GG](https://op.gg)**
Running a single Test
## Contributing
`` php artisan test --filter Example``
Thank you for considering contributing to the Laravel framework! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions).
Running Unit tests -
## Code of Conduct
`` php artisan test ``
In order to ensure that the Laravel community is welcoming to all, please review and abide by the [Code of Conduct](https://laravel.com/docs/contributions#code-of-conduct).
Running Codeception tests -
## Security Vulnerabilities
``vendor/bin/codecept run``
If you discover a security vulnerability within Laravel, please send an e-mail to Taylor Otwell via [taylor@laravel.com](mailto:taylor@laravel.com). All security vulnerabilities will be promptly addressed.
## License
The Laravel framework is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).
@@ -0,0 +1,14 @@
<?php
namespace App\Classes\Exceptions;
use App\Classes\ValueObjects\Constants\HttpStatus;
final class CriteriaNotFulfilledException extends ServiceApiException {
public function __construct(?string $message = null) {
parent::__construct(
$message ?? 'One or more required criteria were not fulfilled.',
HttpStatus::VALIDATION_FAILED
);
}
}
@@ -65,28 +65,22 @@ abstract class AbstractControllerLogic
return $response;
} catch (ErrorException|GeneralExceptions|TypeError $exception){
if ($request->has('isApiPub')) {
Log::error($exception);
return (new ApiResponseObject($this->getNotificationTitle().' failed', "Server Error",
!in_array($exception->getCode(), [0, 42000]) ? $exception->getCode() : HttpStatus::SERVER_ERROR))->handler();
} else {
if ($exception instanceof JobResourceNotFoundException) {
LogHelper::channel('vue_polling')->info(sprintf(
"Uncaught exception '%s' with message '%s' in %s:%d",
get_class($exception),
$exception->getMessage(),
$exception->getTrace()[0]['file'],
$exception->getTrace()[0]['line']
));
}
else{
Log::error($exception);
}
return (new ApiResponseObject($this->getNotificationTitle().' failed', $exception->getMessage(),
!in_array($exception->getCode(), [0, 42000]) ? $exception->getCode() : HttpStatus::SERVER_ERROR))->handler();
if ($exception instanceof JobResourceNotFoundException) {
LogHelper::channel('vue_polling')->info(sprintf(
"Uncaught exception '%s' with message '%s' in %s:%d",
get_class($exception),
$exception->getMessage(),
$exception->getTrace()[0]['file'],
$exception->getTrace()[0]['line']
));
}
else{
Log::error($exception);
}
return (new ApiResponseObject($this->getNotificationTitle().' failed', $exception->getMessage(),
!in_array($exception->getCode(), [0, 42000]) ? $exception->getCode() : HttpStatus::SERVER_ERROR))->handler();
}
}
@@ -0,0 +1,38 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Log;
class HasParcelWithTransportBetweenDate implements Filter
{
public static function apply(Builder $builder, $value)
{
if (is_string($value)) {
$value = json_decode($value, true) ?? [];
}
$startDate = Carbon::make(data_get($value, 'start_date'));
$endDate = Carbon::make(data_get($value, 'end_date'));
$start = $startDate ? $startDate->startOfDay() : null;
$end = $endDate ? $endDate->endOfDay() : null;
if (!$start && !$end) return $builder;
if ($start && $end && $start->gt($end)) [$start, $end] = [$end, $start];
return $builder->whereHas('transports', function (Builder $q) use ($start, $end) {
if ($start && $end && $start->isSameDay($end)) {
return $q->whereDate('drop_date', $start->toDateString());
}
if ($start && $end) {
return $q->whereBetween('drop_date', [$start, $end]);
}
return $start
? $q->where('drop_date', '>=', $start)
: $q->where('drop_date', '<=', $end);
});
}
}
@@ -28,6 +28,40 @@ class PackingListLimitOneByTypeOrderedByInvoiceDate implements Filter
SELECT id FROM transactions WHERE owner_id = packing_lists.id AND type = 16 LIMIT 1
))');
})->orderBy('transactions.updated_at', 'DESC');
}
//Original with problem
// return $builder->select('packing_lists.*')->join('transactions', function($join){
// $join->on('transactions.owner_id', '=', 'packing_lists.id');
// $join->where('transactions.owner_type', '=', PackingList::class);
// $join->where('transactions.status', '=', ApprovalStatus::APPROVED);
// $join->whereNull('transactions.deleted_at');
// $join->whereRaw('(transactions.type <> 16 OR transactions.id = (
// SELECT id FROM transactions WHERE owner_id = packing_lists.id AND type = 16 LIMIT 1
// ))');
// })->orderBy('transactions.updated_at', 'DESC');
//Attempt 1
// return $builder->with(['transactions' => function ($query) {
// $query->where('status', ApprovalStatus::APPROVED)
// ->whereNull('deleted_at')
// ->whereRaw('(
// transactions.type <> 16 OR transactions.id = (
// SELECT id FROM transactions AS t2
// WHERE t2.owner_id = transactions.owner_id
// AND t2.owner_type = ?
// AND t2.type = 16
// LIMIT 1
// )
// )', [PackingList::class])
// ->orderBy('updated_at', 'DESC');
// }]);
//Attempt 2
// return $builder->with(['transactions' => function ($query) {
// $query->where('status', ApprovalStatus::APPROVED)
// ->where('type', '<>', 16 )
// ->whereNull('deleted_at')
// ->orderBy('updated_at', 'DESC');
// }]);
}
}
@@ -23,6 +23,7 @@ class PackingListOrderedByInvoiceDate implements Filter
$join->on('transactions.owner_id', '=', 'packing_lists.id');
$join->where('transactions.owner_type', '=', PackingList::class);
$join->where('transactions.status', '=', ApprovalStatus::APPROVED);
$join->whereNull('transactions.deleted_at');
})->orderBy('transactions.updated_at', 'DESC');
}
@@ -0,0 +1,20 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class TypeNotIn implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->whereNotIn('type', $value);
}
}
+67
View File
@@ -57,4 +57,71 @@ class Helper
static function deserializeFilters(?string $json): array {
return $json !== null ? collect(json_decode($json))->toArray() : [];
}
public static function getLHDNStateCodeByName($name)
{
$path = resource_path('data/lhdn/StateCodes.json');
if (!file_exists($path)) {
return null;
}
$json = file_get_contents($path);
$data = json_decode($json, true);
if (!is_array($data)) {
return null;
}
$name = strtolower(trim($name));
// Step 1: Try exact match
foreach ($data as $item) {
if (
isset($item['State']) &&
strtolower(trim($item['State'])) === $name
) {
return $item['Code'] ?? null;
}
}
// Step 2: Try partial match
foreach ($data as $item) {
if (
isset($item['State']) &&
str_contains(strtolower($item['State']), $name)
) {
return $item['Code'] ?? null;
}
}
return null;
}
public static function getLHDNMsicDescriptionByCode($code)
{
$path = resource_path('data/lhdn/MSICSubCategoryCodes.json');
if (!file_exists($path)) {
return null;
}
$json = file_get_contents($path);
$data = json_decode($json, true);
if (!is_array($data)) {
return null;
}
foreach ($data as $item) {
if (
isset($item['Code']) &&
$item['Code'] === $code
) {
return $item['Description'] ?? null;
}
}
return null;
}
}
@@ -8,5 +8,5 @@ use Illuminate\Database\Eloquent\Relations\MorphMany;
interface KeyValueInterface
{
public function attributes(): morphMany;
public function attributesKVP(): morphMany;
}
-42
View File
@@ -1,42 +0,0 @@
<?php
namespace App\Classes\General;
class WePostHelper
{
/**
* @param string $clientId
* @param string $clientSecrent
* @param string $type
* @return string
*/
static function generateSignature(string $clientId, string $clientSecrent, string $type){
// public parameters
$timestamp = 1234; //time();
$params = [
'client_id' => $clientId,
'type' => $type,
'timestamp' => $timestamp
];
// $businessParams = [
// 'test1' => '1',
// ];
ksort($params);
$str = '';
foreach ($params as $key => $value) {
if(is_array($value)) {
$str .= $key.json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
continue;
}
$str .= $key. $value;
}
$str = $clientSecrent.$str.$clientSecrent;
$signature = strtoupper(md5($str));
return $signature;
}
}
@@ -0,0 +1,44 @@
<?php
namespace App\Classes\Jobs\Commands\V2;
use Carbon\Carbon;
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\Orders\Services\ListsOrders;
use App\Classes\Modules\Transactions\Processors\CheckStorageInvoiceTransactionProcessor;
use App\Classes\ValueObjects\Constants\OrderType;
use Illuminate\Support\Facades\Log;
class CheckStorageInvoicesSingleOrderV2CommandJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $order;
public function __construct($order)
{
$this->order = $order;
}
public function handle()
{
Log::info(Carbon::now() . ': Start job - Check single order for storage invoice.');
$start = new Carbon();
try{
Log::info("Processing Order - ID: {$this->order->id}, Reference: {$this->order->reference}");
(App()->make(CheckStorageInvoiceTransactionProcessor::class))->executeOrder($this->order);
}
catch(\Exception $ex){
Log::info('Exception '.$ex->getMessage());
}
$end = new Carbon();
$elapsedTime = $start->diff($end)->format('%H:%I:%S');
Log::info(Carbon::now() . ': End job - Check single order for storage invoice. ElapsedTime: ' . $elapsedTime . '.');
}
}
@@ -8,16 +8,12 @@ use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
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\Jobs\DataTransferObjects\FixInvoiceV2CommandObject;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\Modules\Transactions\Processors\CreateShippingInvoiceTransactionDocProcessor;
use App\Classes\ValueObjects\Constants\DocumentType;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\CompanyConnection;
use App\Models\Order;
use Mccarlosen\LaravelMpdf\Facades\LaravelMpdf;
use Illuminate\Support\Facades\Log;
class FixInvoiceV2CommandJob implements ShouldQueue
@@ -52,29 +48,10 @@ class FixInvoiceV2CommandJob implements ShouldQueue
dump($invoice->id);
$invoice->documents()->delete();
// $invoice->documents()->delete();
$invoice->documents()->where('document_type', DocumentType::SHIPPING_EINVOICE)->delete();
$view = 'pages.pdfs.shipping_invoice';
$dateToCompare = Carbon::parse(env('SST_START_DATE', '2024-04-01 00:00:00'));
$shippingInvoiceTransactionCreatedDate = Carbon::parse($invoice->created_at);
if ($shippingInvoiceTransactionCreatedDate->isAfter($dateToCompare) && $invoice->tax > 0) {
$view = 'pages.pdfs.shipping_invoice_sst';
}
$transaction_invoice_pdf = LaravelMpdf::loadView($view, ['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);
(App()->make(CreateShippingInvoiceTransactionDocProcessor::class))->execute($invoice);
}
}
@@ -0,0 +1,49 @@
<?php
namespace App\Classes\Jobs\Commands\V2;
use Carbon\Carbon;
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\Transactions\Processors\CreatePaymentTransactionProcessor;
use App\Classes\Modules\Transactions\Processors\ReleaseGoodsToCustomerProcessor;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Models\Group;
use App\Models\Transaction;
use Illuminate\Support\Facades\Log;
class OneTimeFixWalletGroupTransactionV2CommandJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function handle()
{
Log::info(Carbon::now() . ': Start job - This is a one time fix of unsuccessful group payment through wallet.');
$start = new Carbon();
$invoice_ids = [31493]; //31493
$invoices = Transaction::whereIn('id', $invoice_ids)->get();
foreach ($invoices as $invoice) {
if($invoice->status == ApprovalStatus::APPROVED){
$paymentTransaction = (App()->make(CreatePaymentTransactionProcessor::class))->execute($invoice, PaymentMethodType::WALLET, '', false);
if($paymentTransaction && $paymentTransaction->status == ApprovalStatus::APPROVED){
$pL = $invoice->owner;
(App()->make(ReleaseGoodsToCustomerProcessor::class))->execute($pL, $invoice);
}
}
}
$group = Group::where('id', 1569)->first(); //1569
$group->status = ApprovalStatus::APPROVED;
$group->save();
$end = new Carbon();
$elapsedTime = $start->diff($end)->format('%H:%I:%S');
Log::info(Carbon::now() . ': End job - This is a one time fix of unsuccessful group payment through wallet. ElapsedTime: ' . $elapsedTime . '.');
}
}
@@ -20,13 +20,12 @@ class OneTimeTransactionFixBillplzFailedCbV2CommandJob implements ShouldQueue
public function handle()
{
Log::info(Carbon::now() . ': Start job - One time fix failled callback from billplz cron ended.');
Log::info(Carbon::now() . ': Start job - One time fix failled callback from billplz.');
$start = new Carbon();
//Transaction fix with this one time fix command: 15205, 16803, 17310, 22008, 6770
//This transaction, 16803 has approve payment but not its owner, shipping invoice
$transactions = Transaction::whereIn('id', [22008, 6770])->get();
Log::info(Carbon::now() . ' : One time fix failled callback from billplz started.');
foreach ($transactions as $transaction){
if($transaction){
@@ -40,6 +39,6 @@ class OneTimeTransactionFixBillplzFailedCbV2CommandJob implements ShouldQueue
$end = new Carbon();
$elapsedTime = $start->diff($end)->format('%H:%I:%S');
Log::info(Carbon::now() . ': End job - One time fix failled callback from billplz cron ended. ElapsedTime: ' . $elapsedTime . '.');
Log::info(Carbon::now() . ': End job - One time fix failled callback from billplz. ElapsedTime: ' . $elapsedTime . '.');
}
}
@@ -0,0 +1,90 @@
<?php
namespace App\Classes\Jobs\Commands\V2;
use App\Classes\Modules\Accounts\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\Accounts\Services\CreatesKeyValuePair;
use App\Classes\Modules\Accounts\Services\UpdatesKeyValuePair;
use App\Classes\ValueObjects\Constants\KVPKey;
use Carbon\Carbon;
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\KeyValuePair;
use Illuminate\Support\Facades\Log;
class ProcessPaymentReportV2CommandJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/** @var array */
private $details;
/**
* ProcessPaymentReportV2CommandJob constructor.
* @param array $details
*/
public function __construct(array $details)
{
$this->details = $details;
}
public function handle()
{
Log::info(Carbon::now() . ': Start job - Processing single record from 11R - RECEIVE PAYMENT (FULL PAYMENT) [AR RECEIVE PAYMENT] Import.');
$start = new Carbon();
$docNo = $this->details['docno'] ?? null;
$docDate = $this->details['docdate'] ?? null;
$debtorCode = $this->details['debtorcode'] ?? null;
$description = $this->details['description'] ?? null;
$paymentMethod = $this->details['paymentmethod'] ?? null;
$paymentAmt = $this->details['paymentamt'] ?? null;
$knockOffDocNo = $this->details['knockoffdocno'] ?? null;
Log::info("Processing Payment Report:", [
'DocNo' => $docNo,
'DocDate' => $docDate,
'DebtorCode' => $debtorCode,
'Description' => $description,
'PaymentMethod' => $paymentMethod,
'PaymentAmt' => $paymentAmt,
'KnockOffDocNo' => $knockOffDocNo,
]);
if($knockOffDocNo){
$kvp = KeyValuePair::where('key', KVPKey::AUTOCOUNT_DOCNO_INVOICE)->where('value', $knockOffDocNo)->first();
if($kvp){
$transaction = $kvp->owner;
if($transaction){
if($docNo != "" && $docNo != "<<New>>"){
$this->updateOrCreateKeyValuePair($transaction, KVPKey::AUTOCOUNT_DOCNO_OFFICIAL_RECEIPT, $docNo);
}
// if($eInvoiceValidationLink){
// $this->updateOrCreateKeyValuePair($booking, KVPKey::AUTOCOUNT_EINVOICE_VALIDATION_LINK, $eInvoiceValidationLink);
// }
}
}
}
$end = new Carbon();
$elapsedTime = $start->diff($end)->format('%H:%I:%S');
Log::info(Carbon::now() . ': End job - Processing single record from 11R - RECEIVE PAYMENT (FULL PAYMENT) [AR RECEIVE PAYMENT] Import. ElapsedTime: ' . $elapsedTime . '.');
}
private function updateOrCreateKeyValuePair($booking, $key, $value)
{
$keyValuePairObject = new KeyValuePairObject($key, $value);
$metadata = $booking->attributesKVP()->where('key', $key)->first();
if ($metadata) {
(App()->make(UpdatesKeyValuePair::class))->execute($metadata, $keyValuePairObject);
} else {
(App()->make(CreatesKeyValuePair::class))->execute($booking, $keyValuePairObject);
}
}
}
@@ -0,0 +1,131 @@
<?php
namespace App\Classes\Jobs\Commands\V2;
use App\Classes\Modules\Accounts\DataTransferObjects\KeyValuePairObject;
use App\Classes\Modules\Accounts\Services\CreatesKeyValuePair;
use App\Classes\Modules\Accounts\Services\UpdatesKeyValuePair;
use App\Classes\ValueObjects\Constants\KVPKey;
use App\Classes\ValueObjects\Constants\TransactionType;
use Carbon\Carbon;
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\Order;
use App\Models\Transaction;
use Illuminate\Support\Facades\Log;
class ProcessSalesInvoiceReportV2CommandJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/** @var array */
private $details;
/**
* ProcessSalesInvoiceReportV2CommandJob constructor.
* @param array $details
*/
public function __construct(array $details)
{
$this->details = $details;
}
public function handle()
{
Log::info(Carbon::now() . ': Start job - Processing single record for E-Invoice from Sales Invoice Report Import.');
$start = new Carbon();
$docNo = $this->details['docno'] ?? null;
$docDate = $this->details['docdate'] ?? null;
$debtorCode = $this->details['debtorcode'] ?? null;
$ref = $this->details['ref'] ?? null;
$shipInfo = $this->details['shipinfo'] ?? null;
$accNo = $this->details['accno'] ?? null;
$detailDescription = $this->details['detaildescription'] ?? null;
$furtherDescription = $this->details['furtherdescription'] ?? null;
$classification = $this->details['classification'] ?? null;
$projNo = $this->details['projno'] ?? null;
$deptNo = $this->details['deptno'] ?? null;
$qty = $this->details['qty'] ?? null;
$unitPrice = $this->details['unitprice'] ?? null;
$taxCode = $this->details['taxcode'] ?? null;
$taxableAmt = $this->details['taxableamt'] ?? null;
$taxRate = $this->details['taxrate'] ?? null;
$submitEinvoice = $this->details['submiteinvoice'] ?? null;
$consolidatedEinvoice = $this->details['consolidatedeinvoice'] ?? null;
$eInvoiceValidationLink = $this->details['einvoicevalidationlink'] ?? null;
// Log for debugging
Log::info("Processing Sales Invoice Report:", [
'DocNo' => $docNo,
'DocDate' => $docDate,
'DebtorCode' => $debtorCode,
'Ref' => $ref,
'ShipInfo' => $shipInfo,
'AccNo' => $accNo,
'DetailDescription' => $detailDescription,
'FurtherDescription' => $furtherDescription,
'Classification' => $classification,
'ProjNo' => $projNo,
'DeptNo' => $deptNo,
'Qty' => $qty,
'UnitPrice' => $unitPrice,
'TaxCode' => $taxCode,
'TaxableAmt' => $taxableAmt,
'TaxRate' => $taxRate,
'SubmitEinvoice' => $submitEinvoice,
'ConsolidatedEinvoice' => $consolidatedEinvoice,
'EInvoiceValidationLink' => $eInvoiceValidationLink,
]);
// $order = Order::where('reference', $ref)->first();
// $transactions = $order->transactions()->whereIn('transactions.type', [TransactionType::SHIPPING_INVOICE, TransactionType::STORAGE_INVOICE])->get();
// $matchedTransaction = null;
// foreach ($transactions as $transaction) {
// $transactionDetails = $transaction->transactionDetails;
// foreach ($transactionDetails as $detail) {
// $detailName = str_replace('<br>', ' ', $detail->name);
// if (
// $detailName === $furtherDescription &&
// $detail->quantity == $qty &&
// $detail->price == $unitPrice
// ) {
// $matchedTransaction = $transaction;
// break 2;
// }
// }
// }
$matchedTransaction = Transaction::where('bill_no', $ref)->first();
if($matchedTransaction){
if($docNo != "" && $docNo != "<<New>>"){
$this->updateOrCreateKeyValuePair($matchedTransaction, KVPKey::AUTOCOUNT_DOCNO_INVOICE, $docNo);
}
if($eInvoiceValidationLink){
$this->updateOrCreateKeyValuePair($matchedTransaction, KVPKey::AUTOCOUNT_EINVOICE_VALIDATION_LINK, $eInvoiceValidationLink);
}
}
$end = new Carbon();
$elapsedTime = $start->diff($end)->format('%H:%I:%S');
Log::info(Carbon::now() . ': End job - Processing single record for E-Invoice from Sales Invoice Report Import. ElapsedTime: ' . $elapsedTime . '.');
}
private function updateOrCreateKeyValuePair($booking, $key, $value)
{
$keyValuePairObject = new KeyValuePairObject($key, $value);
$metadata = $booking->attributesKVP()->where('key', $key)->first();
if ($metadata) {
(App()->make(UpdatesKeyValuePair::class))->execute($metadata, $keyValuePairObject);
} else {
(App()->make(CreatesKeyValuePair::class))->execute($booking, $keyValuePairObject);
}
}
}
@@ -0,0 +1,72 @@
<?php
namespace App\Classes\Jobs\Commands\V2;
use App\Classes\Modules\Transactions\Processors\CreateShippingEInvoiceDocProcessor;
use App\Classes\Modules\Transactions\Processors\CreateStorageEInvoiceDocProcessor;
use App\Classes\ValueObjects\Constants\DocumentType;
use App\Classes\ValueObjects\Constants\KVPKey;
use App\Classes\ValueObjects\Constants\TransactionType;
use Carbon\Carbon;
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;
use Illuminate\Support\Facades\Log;
class ProcessTransactionForEInvoiceV2CommandJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/** @var Transaction */
private $transaction;
/**
* ProcessTransactionForEInvoiceV2CommandJob constructor.
* @param Transaction $transaction
*/
public function __construct(Transaction $transaction)
{
$this->transaction = $transaction;
}
public function handle()
{
Log::info(Carbon::now() . ': Start job - Processing single transaction for E-Invoice.');
$start = new Carbon();
$isGenerated = false;
$companyModule = $this->transaction->owner->owner->companyModule;
if($companyModule->company->e_invoice === 1){
$document = $this->transaction->documents()->where('document_type', DocumentType::SHIPPING_EINVOICE)->first();
$kvp = $this->transaction->attributesKVP()->where('key', KVPKey::AUTOCOUNT_DOCNO_INVOICE)->first();
if(!$document && $kvp && $this->transaction->type == TransactionType::SHIPPING_INVOICE){
(App()->make(CreateShippingEInvoiceDocProcessor::class))->execute($this->transaction);
$isGenerated = true;
}
else {
$document2 = $this->transaction->documents()->where('document_type', DocumentType::STORAGE_EINVOICE)->first();
$kvp2 = $this->transaction->attributesKVP()->where('key', KVPKey::AUTOCOUNT_DOCNO_INVOICE)->first();
if(!$document2 && $kvp2 && $this->transaction->type == TransactionType::STORAGE_INVOICE){
(App()->make(CreateStorageEInvoiceDocProcessor::class))->execute($this->transaction);
$isGenerated = true;
}
}
}
if(!$isGenerated){
Log::info("NO E-Invoice generated for transaction with id: " . $this->transaction->id . ', order: ' . $this->transaction->owner->owner->reference );
}
else{
Log::info("E-Invoice generated for transaction with id: " . $this->transaction->id . ', order: ' . $this->transaction->owner->owner->reference );
}
$end = new Carbon();
$elapsedTime = $start->diff($end)->format('%H:%I:%S');
Log::info(Carbon::now() . ': End job - Processing single transaction for E-Invoice. ElapsedTime: ' . $elapsedTime . '.');
}
}
@@ -0,0 +1,47 @@
<?php
namespace App\Classes\Jobs\Commands\V2;
use Carbon\Carbon;
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\Orders\Services\ListsOrders;
use App\Classes\Modules\Transactions\Processors\CheckStorageInvoiceTransactionProcessor;
use App\Classes\Modules\Transactions\Processors\ReleaseGoodsToCustomerProcessor;
use App\Classes\ValueObjects\Constants\OrderType;
use Illuminate\Support\Facades\Log;
class ReleaseGoodsToCustomerV2CommandJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $invoice;
public function __construct($invoice)
{
$this->invoice = $invoice;
}
public function handle()
{
Log::info(Carbon::now() . ': Start job - Release goods to customer.');
$start = new Carbon();
try{
$obj = json_encode($this->invoice);
Log::info("Processing Order - ID: {$this->invoice->id}, invoice: {$obj}");
$pL = $this->invoice->owner;
(App()->make(ReleaseGoodsToCustomerProcessor::class))->execute($pL, $this->invoice);
}
catch(\Exception $ex){
Log::info('Exception '.$ex->getMessage());
}
$end = new Carbon();
$elapsedTime = $start->diff($end)->format('%H:%I:%S');
Log::info(Carbon::now() . ': End job - Release goods to customer. ElapsedTime: ' . $elapsedTime . '.');
}
}
+1 -3
View File
@@ -11,16 +11,14 @@ 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\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;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use App\Classes\General\Helper;
use App\Classes\General\LogHelper;
@@ -3,7 +3,7 @@
namespace App\Classes\Modules\Accounts\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\General\LogHelper;
use App\Classes\General\Services\GeneratesInitials;
use App\Classes\Modules\Accounts\Processors\AuthenticationProcessor;
use App\Classes\Modules\Accounts\Processors\CreateUserProcessor;
@@ -28,8 +28,7 @@ use App\Classes\ValueObjects\Constants\CompanyType;
use App\Classes\ValueObjects\Constants\RoleTypes;
use App\Classes\Jobs\CreatePerfexCRMCustomer;
use App\Classes\Modules\Accounts\Processors\RegisterOnExchangeProcessor;
use App\Classes\Modules\Companies\Services\ConnectCompanyModuleToExchangeCompany;
use App\Models\Company;
use App\Models\CompanyModule;
use App\Models\User;
@@ -90,12 +89,6 @@ class CreateCustomerLogic extends AbstractControllerLogic
/** @var CreatePerfexCRMLeadProcessor */
private $createPerfexCRMLeadProcessor;
/** @var RegisterOnExchangeProcessor */
private $registerOnExchangeProcessor;
/** @var ConnectCompanyModuleToExchangeCompany */
private $connectCompanyModuleToExchangeCompany;
/**
* CreateCustomerLogic constructor.
* @param CreateUserProcessor $createUserProcessor
@@ -110,10 +103,8 @@ class CreateCustomerLogic extends AbstractControllerLogic
* @param GenerateEmailVerificationAttemptProcessor $generateEmailVerificationAttemptProcessor
* @param FetchesCompanyModule $fetchesCompanyModule
* @param CreatePerfexCRMLeadProcessor $createPerfexCRMLeadProcessor
* @param RegisterOnExchangeProcessor $registerOnExchangeProcessor
* @param ConnectCompanyModuleToExchangeCompany $connectCompanyModuleToExchangeCompany
*/
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, RegisterOnExchangeProcessor $registerOnExchangeProcessor, ConnectCompanyModuleToExchangeCompany $connectCompanyModuleToExchangeCompany)
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;
@@ -127,8 +118,6 @@ class CreateCustomerLogic extends AbstractControllerLogic
$this->generateEmailVerificationAttemptProcessor = $generateEmailVerificationAttemptProcessor;
$this->fetchesCompanyModule = $fetchesCompanyModule;
$this->createPerfexCRMLeadProcessor = $createPerfexCRMLeadProcessor;
$this->registerOnExchangeProcessor = $registerOnExchangeProcessor;
$this->connectCompanyModuleToExchangeCompany = $connectCompanyModuleToExchangeCompany;
}
/**
@@ -166,7 +155,7 @@ class CreateCustomerLogic extends AbstractControllerLogic
$this->assignEmployeeProcessor->execute($Object);
// $this->uploadIdentityDocumentProcessor->execute($request, $company);
$this->uploadIdentityDocumentProcessor->execute($request, $company);
if(config('perfexcrm.is_enabled') == 'true'){
// $this->createPerfexCRMLeadProcessor->execute($request);
@@ -190,24 +179,11 @@ class CreateCustomerLogic extends AbstractControllerLogic
'portal' => 'izyim'
];
$response = Http::post($url, $payload);
LogHelper::channel('wac_webhook')->info('Register Account: ' . json_encode($response));
Log::channel('wac_webhook')->info('Register Account: ' . json_encode($response));
}
// $this->generateEmailVerificationAttemptProcessor->execute($user);
$exchangeCompanyId = null;
if ($request->input('exchange_company_id')) {
$exchangeCompanyId = $request->input('exchange_company_id');
} else {
// register account on exchange portal if this registration not coming from exchange
$exchangeCompanyId = $this->registerOnExchangeProcessor->execute($request, $companyModule->id);
}
if ($exchangeCompanyId) {
// create exchange company connection
$this->connectCompanyModuleToExchangeCompany->execute($companyModule, $exchangeCompanyId);
}
return $this->response($this->authenticationProcessor->execute($request));
}
}
@@ -1,83 +0,0 @@
<?php
namespace App\Classes\Modules\Accounts\ControllersLogic;
use App\Classes\Exceptions\AccessUnauthorisedException;
use App\Classes\Modules\Accounts\Processors\AuthenticationProcessor;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Accounts\Services\GeneratesAuthenticationToken;
use App\Classes\Modules\Accounts\Services\GeneratesAuthenticationTokenWithExchangeBookingId;
use App\Models\ExchangeCompanyConnection;
use App\Models\Order;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
class LoginThroughExchangeLogic extends AbstractControllerLogic
{
protected function notification():array {
return [
'title' => 'Authentication',
'message' => 'You have successfully logged in to your account'
];
}
/** @var AuthenticationProcessor */
private $authenticationProcessor;
/** @var GeneratesAuthenticationToken */
private $generatesAuthenticationToken;
/** @var GeneratesAuthenticationTokenWithExchangeBookingId */
private $generatesAuthenticationTokenWithExchangeBookingId;
/**
* LoginThroughExchangeLogic constructor.
* @param AuthenticationProcessor $authenticationProcessor
* @param GeneratesAuthenticationToken $generatesAuthenticationToken
* @param GeneratesAuthenticationTokenWithExchangeBookingId $generatesAuthenticationTokenWithExchangeBookingId
*/
public function __construct(GeneratesAuthenticationToken $generatesAuthenticationToken, GeneratesAuthenticationTokenWithExchangeBookingId $generatesAuthenticationTokenWithExchangeBookingId)
{
$this->generatesAuthenticationToken = $generatesAuthenticationToken;
$this->generatesAuthenticationTokenWithExchangeBookingId = $generatesAuthenticationTokenWithExchangeBookingId;
}
/**
* @param Request $request
* @return JsonResponse
* @throws \App\Classes\Exceptions\AccessForbiddenException
* @throws \App\Classes\Exceptions\AccessUnauthorisedException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
protected function logic(Request $request): JsonResponse {
$token = explode('.', $request->input("exchangeToken"))[1];
$decodedToken = base64_decode($token);
$exchangeUser = json_decode($decodedToken, true)['user'];
$exchangeCompanyId = $exchangeUser['company_id'];
$connection = ExchangeCompanyConnection::where("exchange_company_id", $exchangeCompanyId)->first();
if (!$connection) {
throw new AccessUnauthorisedException('These credentials do not match our records.');
}
$companyModule = $connection->companyModule;
$user = $companyModule->employees->last();
$exchangeBookingId = null;
if (isset($exchangeUser['booking_id']) && $exchangeUser['booking_id']) {
$exchangeBookingId = $exchangeUser['booking_id'];
$token = $this->generatesAuthenticationTokenWithExchangeBookingId->execute($user, $exchangeBookingId);
return $this->response(['access_token' => $token, 'redirect_url' => route('dashboard') . "?createOrder=true"]);
} else {
$token = $this->generatesAuthenticationToken->execute($user);
$order = Order::where('id', $request->input("orderId"))->first();
return $this->response(['access_token' => $token, 'redirect_url' => route('order.show' , $order->reference)]);
}
}
}
@@ -1,45 +0,0 @@
<?php
namespace App\Classes\Modules\Accounts\Processors;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Log;
class RegisterOnExchangeProcessor
{
/**
* @param Request $request
* @return string
* @throws \App\Classes\Exceptions\AccessForbiddenException
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
public function execute(Request $request, $companyModuleId) {
if (App::environment(['production'])) {
dd("Delete this line before push to production");
$url = 'https://exchange.cief-malaysia.com/api/v1/account/registration/registration';
} else if (App::environment(['local'])) {
$url = 'http://127.0.0.1:8000/api/v1/account/registration/registration';
} else {
$url = 'https://dev.exchange.cief-malaysia.com/api/v1/account/registration/registration';
}
try {
$client = new \GuzzleHttp\Client(['verify' => false]);
$formParams = $request->toArray();
$formParams['shipping_company_module_id'] = $companyModuleId;
$response = $client->request('POST', $url, ['form_params' => $formParams]);
$body = $response->getBody();
$contents = json_decode($body, true);
$payload = $contents['payload'];
$token = explode('.', $payload['access_token'])[1];
$decodedToken = base64_decode($token);
$exchangeUser = json_decode($decodedToken, true)['user'];
return $exchangeUser['company_id'];
} catch(\GuzzleHttp\Exception\RequestException $exception){
Log::error($exception->getResponse()->getBody()->getContents());
}
}
}
@@ -22,7 +22,7 @@ class CreatesKeyValuePair extends AbstractUpdateRelationshipRecord
$model->key = $object->getKey();
$model->value = $object->getValue();
return $this->handler($kv->attributes(), $model);
return $this->handler($kv->attributesKVP(), $model);
}
}
@@ -0,0 +1,19 @@
<?php
namespace App\Classes\Modules\Accounts\Services;
use App\Classes\General\Eloquent\AbstractDeleteRecord;
use App\Models\KeyValuePair;
class DeletesKeyValuePair extends AbstractDeleteRecord
{
/**
* @param KeyValuePair $model
* @return mixed
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(KeyValuePair $model) {
return $this->handler($model);
}
}
@@ -1,81 +0,0 @@
<?php
namespace App\Classes\Modules\Accounts\Services;
use App\Classes\Exceptions\InternalServerErrorException;
use App\Classes\ValueObjects\Constants\OrderRoleTypes;
use App\Classes\ValueObjects\Constants\RoleTypes;
use App\Models\Company;
use App\Models\Role;
use App\Models\User;
use Carbon\Carbon;
use Tymon\JWTAuth\JWT;
class GeneratesAuthenticationTokenWithExchangeBookingId {
/** @var JWT */
private $builder;
/**
* GeneratesAuthenticationTokenWithExchangeBookingId constructor.
* @param JWT $builder
*/
public function __construct(JWT $builder) {
$this->builder = $builder;
}
/**
* @param User $user
* @param bool $rememberUser
* @return string
*/
public function execute(User $user, $bookingId): string {
$this->builder->manager()->setBlacklistEnabled(false);
// generate token for the customer
$this->builder->factory()->setTTL(Carbon::now()->addDay()->timestamp);
// set the claim based on the object
$this->setTokenClaims($user, $bookingId);
return $this->builder->fromUser($user);
}
/**
* @param User $user
*/
private function setTokenClaims(User $user, $bookingId): void {
$claims = [
'id' => $user->id,
'name' => $user->name,
'email' => $user->email,
'type' => $user->type,
'status' => $user->status
];
if($user->type === RoleTypes::USER) {
/** @var Company $companyModule */
$companyModule = $user->companyModule()->first();
$claims = array_merge($claims, [
'company_id' => $companyModule->company_id,
'company_module_id' => $companyModule->id,
'company_module_type' => $companyModule->type,
'company_name' => $companyModule->name,
'company_marking' => $companyModule->type !== 8 ? $companyModule->inviters()->withPivot('invitee_reference')->first()->pivot->invitee_reference : 'HWT',
'exchange_booking_id' => $bookingId
]);
}
$this->builder->factory()->customClaims(['user' => $claims]);
$this->builder->factory()->buildClaimsCollection();
}
}
@@ -0,0 +1,22 @@
<?php
namespace App\Classes\Modules\Accounts\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Classes\Modules\Accounts\DataTransferObjects\KeyValuePairObject;
use App\Models\KeyValuePair;
class UpdatesKeyValuePair extends AbstractUpdateRecord
{
/**
* @param KeyValuePair $model
* @param KeyValuePairObject $object
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(KeyValuePair $model, KeyValuePairObject $object) {
$model->key = $object->getKey();
$model->value = $object->getValue();
return $this->handler($model);
}
}
@@ -3,9 +3,6 @@
namespace App\Classes\Modules\Addresses\ControllersLogic;
use App\Classes\Exceptions\AccessForbiddenException;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\RequestValidationException;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\General\Interfaces\Contactable;
use App\Classes\Modules\Addresses\Services\CreatesAddress;
@@ -21,7 +18,6 @@ use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\RemarkTypes;
use App\Http\Resources\AddressResource;
use App\Models\Address;
use App\Transformers\AddressTransformer;
use Carbon\Carbon;
use ErrorException;
use Illuminate\Http\JsonResponse;
@@ -33,8 +29,7 @@ class CreateAddressLogic extends AbstractControllerLogic
/**
* @return array
*/
protected function notification(): array
{
protected function notification():array {
return [
'title' => 'Created Address',
'message' => 'You have successfully created a new Address'
@@ -81,11 +76,11 @@ class CreateAddressLogic extends AbstractControllerLogic
/**
* @param Request $request
* @return JsonResponse
* @throws AccessForbiddenException
* @throws MalformedRequestException
* @throws RequestValidationException
* @throws \App\Classes\Exceptions\AccessForbiddenException
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
public function logic(Request $request): JsonResponse
public function logic(Request $request) : JsonResponse
{
$district = $this->fetchesDistrict->execute(['id' => $request->input('district_id')]);
@@ -97,21 +92,16 @@ class CreateAddressLogic extends AbstractControllerLogic
/** @var Address $address */
$address = $this->createsAddress->execute($this->fetchesCompanyModule->execute(['id' => $request->input('company_module_id')]), $object);
if ($request->input('phone')) {
if($request->input('phone')){
$contactObject = new ContactObject($request->input('person_in_charge'), $request->input('phone'), '', '');
$this->createContactProcessor->execute($contactObject, $address);
}
if ($request->input('remark')) {
if($request->input('remark')){
$remarkObject = new RemarkObject($request->input('remark'), Auth()->user()->id);
$this->createRemarkProcessor->execute($address, $remarkObject);
}
/* return fractal()
->item($address, new AddressTransformer())
->parseIncludes('remark')
->respond(200, [], JSON_PRETTY_PRINT);*/
if ($request->input('pickup_time_to') <= $request->input('pickup_time_from')) {
$pickupTimeFrom = Carbon::parse($request->input('pickup_time_from'));
$request->merge([
@@ -2,10 +2,7 @@
namespace App\Classes\Modules\Addresses\ControllersLogic;
use App\Classes\Exceptions\AccessForbiddenException;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\RequestValidationException;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Addresses\Services\CreatesAddress;
use App\Classes\Modules\Addresses\Standards\Rules\CanCreateAddress;
@@ -14,10 +11,10 @@ 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\Classes\ValueObjects\Constants\RoleTypes;
use App\Http\Resources\AddressResource;
use App\Models\Address;
use App\Models\CompanyModule;
use App\Transformers\AddressTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -27,8 +24,7 @@ class CreateBillingAddressLogic extends AbstractControllerLogic
/**
* @return array
*/
protected function notification(): array
{
protected function notification():array {
return [
'title' => 'Created Billing Address',
'message' => 'You have successfully created a new Billing Address'
@@ -65,35 +61,35 @@ class CreateBillingAddressLogic extends AbstractControllerLogic
/**
* @param Request $request
* @return JsonResponse
* @throws AccessForbiddenException
* @throws MalformedRequestException
* @throws RequestValidationException
* @throws \App\Classes\Exceptions\AccessForbiddenException
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
public function logic(Request $request): JsonResponse
public function logic(Request $request) : JsonResponse
{
$companyModule = $this->fetchesCompanyModule->execute(['id' => $request->input('company_module_id')]);
$billingAddressInputed = $this->fetchesAddress->execute(['id' => $request->input('billing_address_id')]);
//cief todo: 90 - move this into canCreateAddress
$roleToCheck = Auth()->user()->type;
if (!in_array($roleToCheck, RoleTypes::ADMIN_ROLES)) {
if($companyModule->company->e_invoice === 1){
throw new AccessForbiddenException('Update of billing address not allowed.');
}
}
if ($billingAddressInputed->type !== AddressType::BILLING || $billingAddressInputed->id !== $companyModule->addresses->where('type', AddressType::BILLING)->first()->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 new billing addrress
$billingAddress = new AddressObject($billingAddressInputed->street_one, $billingAddressInputed->street_two, $billingAddressInputed->country_id, $billingAddressInputed->state_id, $billingAddressInputed->district_id, $billingAddressInputed->postcode, AddressType::BILLING, ApprovalStatus::APPROVED, $billingAddressInputed->reference);
// 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);
}
//load address with only owner address
/* return fractal()
->item($billingAddressInputed, new AddressTransformer())
->parseIncludes('Owner_address')
->respond(200, [], JSON_PRETTY_PRINT);*/
return $this->resourceResponse(new AddressResource($billingAddressInputed));
return $this->resourceResponse(new AddressResource($address));
}
}
}
@@ -3,8 +3,6 @@
namespace App\Classes\Modules\Addresses\ControllersLogic;
use App\Classes\Exceptions\AccessForbiddenException;
use App\Classes\Exceptions\RequestValidationException;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Addresses\Services\FetchesAddress;
use App\Classes\Modules\Addresses\Standards\Rules\CanFetchAddress;
@@ -19,8 +17,7 @@ class FetchAddressLogic extends AbstractControllerLogic
/**
* @return array
*/
protected function notification(): array
{
protected function notification():array {
return [
'title' => 'Retrieved Address',
'message' => 'You have successfully retrieved a Address'
@@ -48,22 +45,15 @@ class FetchAddressLogic extends AbstractControllerLogic
/**
* @param Request $request
* @return JsonResponse
* @throws AccessForbiddenException
* @throws RequestValidationException
* @throws \App\Classes\Exceptions\AccessForbiddenException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
public function logic(Request $request): JsonResponse
public function logic(Request $request) : JsonResponse
{
$this->canFetchAddress->passes();
$query = $this->fetchesAddress->execute(['id' => $request->route('id')]);
//load address with no relationships
/* return fractal()
->item($address, new AddressTransformer())
->respond(200, [], JSON_PRETTY_PRINT);*/
return $this->resourceResponse(new AddressResource($query));
}
@@ -3,14 +3,11 @@
namespace App\Classes\Modules\Addresses\ControllersLogic;
use App\Classes\Exceptions\AccessForbiddenException;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\RequestValidationException;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Addresses\Services\ListsAddresses;
use App\Classes\Modules\Addresses\Standards\Rules\CanListAddresses;
use App\Classes\ValueObjects\Constants\AddressType;
use App\Http\Resources\AddressResource;
use App\Transformers\AddressTransformer;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -21,8 +18,7 @@ class ListAddressesLogic extends AbstractControllerLogic
/**
* @return array
*/
protected function notification(): array
{
protected function notification():array {
return [
'title' => 'Retrieved Addresses',
'message' => 'You have successfully retrieved a list of Addresses'
@@ -50,27 +46,18 @@ class ListAddressesLogic extends AbstractControllerLogic
/**
* @param Request $request
* @return JsonResponse
* @throws AccessForbiddenException
* @throws MalformedRequestException
* @throws RequestValidationException
* @throws \App\Classes\Exceptions\AccessForbiddenException
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
public function logic(Request $request): JsonResponse
public function logic(Request $request) : JsonResponse
{
$this->canListAddresses->passes();
$query = $this->listsAddresses->execute($this->listsAddresses->deserializeFilters($request->input('filters')));
//a collection of addresses with all incluides
/* return fractal()
->collection($query, new AddressTransformer)
->parseIncludes('Owner_address')
->parseIncludes('remark')
->parseIncludes('contact')
->respond(200, [], JSON_PRETTY_PRINT);*/
//$query = $this->listsAddresses->execute($this->listsAddresses->deserializeFilters($request->input('filters')));
$query = $this->listsAddresses->execute(array_merge($this->listsAddresses->deserializeFilters($request->input('filters')), ['type_not_in' => [AddressType::E_INVOICE]]));
return $this->collectionResponse(AddressResource::collection($query));
}
}
}
@@ -7,6 +7,7 @@ use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Addresses\Services\ListsAddresses;
use App\Classes\Modules\Addresses\Services\ListsDistricts;
use App\Classes\Modules\Addresses\Standards\Rules\CanListAddresses;
use App\Http\Resources\AddressResource;
use App\Http\Resources\DistrictResource;
use ErrorException;
use Illuminate\Http\JsonResponse;
@@ -7,6 +7,7 @@ use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Addresses\Services\ListsAddresses;
use App\Classes\Modules\Addresses\Services\ListsStates;
use App\Classes\Modules\Addresses\Standards\Rules\CanListAddresses;
use App\Http\Resources\AddressResource;
use App\Http\Resources\StateResource;
use ErrorException;
use Illuminate\Http\JsonResponse;
@@ -9,7 +9,6 @@ use App\Classes\Modules\Addresses\Services\FetchesAddress;
use App\Classes\Modules\Addresses\Services\ResetsAddressesDefault;
use App\Classes\Modules\Addresses\Services\SetsAddressToDefault;
use App\Models\Address;
use App\Transformers\AddressTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -34,7 +33,7 @@ class SetAddressToDefaultLogic extends AbstractControllerLogic
/** @var ResetsAddressesDefault */
private $resetsAddressesDefault;
/** @var SetsAddressToDefault */
/** @var SetsAddressToDefault*/
private $setsAddressToDefault;
@@ -65,15 +64,7 @@ class SetAddressToDefaultLogic extends AbstractControllerLogic
$this->resetsAddressesDefault->execute($address->owner, $address->type);
$setAddress = $this->setsAddressToDefault->execute($address);
//no relationships needed
/* return fractal()
->item($setAddress, new AddressTransformer())
->respond(200, [], JSON_PRETTY_PRINT);*/
return $this->resourceResponse(new AddressResource($address));
return $this->resourceResponse(new AddressResource($this->setsAddressToDefault->execute($address)));
}
}
@@ -18,7 +18,6 @@ use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\RemarkTypes;
use App\Http\Resources\AddressResource;
use App\Models\Address;
use App\Transformers\AddressTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Carbon\Carbon;
@@ -29,8 +28,7 @@ class UpdateAddressLogic extends AbstractControllerLogic
/**
* @return array
*/
protected function notification(): array
{
protected function notification():array {
return [
'title' => 'Updated Address',
'message' => 'You have successfully updated the Address'
@@ -81,7 +79,7 @@ class UpdateAddressLogic extends AbstractControllerLogic
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
public function logic(Request $request): JsonResponse
public function logic(Request $request) : JsonResponse
{
$district = $this->fetchesDistrict->execute(['id' => $request->input('district_id')]);
@@ -94,25 +92,18 @@ class UpdateAddressLogic extends AbstractControllerLogic
/** @var Address $address */
$address = $this->updatesAddress->execute($address, $object);
$address->contacts()->delete();
$address->remarks()->delete();
$address->contacts()->delete(); $address->remarks()->delete();
if ($request->input('phone')) {
if($request->input('phone')){
$contactObject = new ContactObject($request->input('person_in_charge'), $request->input('phone'), '', '');
$this->createContactProcessor->execute($contactObject, $address);
}
if ($request->input('remark')) {
if($request->input('remark')){
$remarkObject = new RemarkObject($request->input('remark'), Auth()->user()->id);
$this->createRemarkProcessor->execute($address, $remarkObject);
}
//only remark relationship needed
/* return fractal()
->item($address, new AddressTransformer())
->parseIncludes('remark')
->respond(200, [], JSON_PRETTY_PRINT);*/
if ($request->input('pickup_time_to') <= $request->input('pickup_time_from')) {
$pickupTimeFrom = Carbon::parse($request->input('pickup_time_from'));
$request->merge([
@@ -122,7 +113,6 @@ class UpdateAddressLogic extends AbstractControllerLogic
$addressExtraFields = [
'property_type' => $request->input('property_type'),
'additional_request' => $request->input('additional_request'),
'receive_goods_working_hours' => $request->input('receive_goods_working_hours'),
'receive_goods_after_hours' => $request->input('receive_goods_after_hours'),
'receive_goods_on_saturday' => $request->input('receive_goods_on_saturday'),
@@ -130,7 +120,6 @@ class UpdateAddressLogic extends AbstractControllerLogic
$address->addressExtraFields()->delete();
$addressExtraFieldsObject = new RemarkObject(json_encode($addressExtraFields), Auth()->user()->id, RemarkTypes::ADDRESS_EXTRA_COLUMNS);
$this->createRemarkProcessor->execute($address, $addressExtraFieldsObject);
$remark = $this->createRemarkProcessor->execute($address, $addressExtraFieldsObject);
return $this->resourceResponse(new AddressResource($address));
@@ -23,7 +23,7 @@ class AddressObject implements DataTransferObject
/** @var int */
private $districtId;
/** @var int */
/** @var string */
private $postCode;
/** @var int */
@@ -42,12 +42,12 @@ class AddressObject implements DataTransferObject
* @param int $countryId
* @param int $stateId
* @param int $districtId
* @param int $postCode
* @param string $postCode
* @param int $type
* @param int $status
* @param null|string $reference
*/
public function __construct(string $streetOne, ?string $streetTwo, int $countryId, int $stateId, int $districtId, int $postCode, int $type, int $status, ?string $reference = null)
public function __construct(string $streetOne, ?string $streetTwo, int $countryId, int $stateId, int $districtId, string $postCode, int $type, int $status, ?string $reference = null)
{
$this->streetOne = $streetOne;
$this->streetTwo = $streetTwo;
@@ -101,9 +101,9 @@ class AddressObject implements DataTransferObject
}
/**
* @return int
* @return string
*/
public function getPostCode(): int
public function getPostCode(): string
{
return $this->postCode;
}
@@ -133,4 +133,4 @@ class AddressObject implements DataTransferObject
}
}
}
@@ -0,0 +1,40 @@
<?php
namespace App\Classes\Modules\Addresses\Services;
use App\Classes\General\Eloquent\AbstractUpdateRelationshipRecord;
use App\Classes\General\Interfaces\Addressable;
use App\Classes\Modules\Addresses\DataTransferObjects\AddressObject;
use App\Models\Address;
use App\Models\CompanyModule;
class UpsertsAddress extends AbstractUpdateRelationshipRecord
{
/**
* Create or update the company's address.
*
* @param Addressable $addressable
* @param AddressObject $object
* @param int $id
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(Addressable $addressable, AddressObject $object, int $id)
{
//Create new or update?
$model = $addressable->addresses()->where('id', $id)->first() ?? new Address();
$model->reference = $object->getReference();
$model->street_one = $object->getStreetOne();
$model->street_two = $object->getStreetTwo();
$model->country_id = $object->getCountryId();
$model->state_id = $object->getStateId();
$model->district_id = $object->getDistrictId();
$model->postcode = $object->getPostCode();
$model->status = $object->getStatus();
$model->type = $object->getType();
return $this->handler($addressable->addresses(), $model);
}
}
@@ -20,7 +20,7 @@ class AssignsAnnouncementToSegment extends AbstractUpdateRecord
{
try {
$announcement->segments()->attach($segment, ['created_at' => now(), 'updated_at' => now()]);
$announcement->segments()->attach($segment);
return $announcement;
@@ -0,0 +1,66 @@
<?php
namespace App\Classes\Modules\Anthropic\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
class CreatesClaudeResponse
{
/**
* @param string $userPrompt
* @param string $model
* @return null|object
* @throws MalformedRequestException
*/
public function execute(string $userPrompt, string $model = "") {
try {
$content = [];
$content[] = [
'type' => 'text',
'text' => $userPrompt,
];
$response = Http::withHeaders([
'x-api-key' => config('anthropic.api_key'),
'anthropic-version' => config('anthropic.api_version', '2023-06-01'),
'Content-Type' => 'application/json',
])->post(config('anthropic.base_url') . '/v1/messages', [
'model' => config('anthropic.default_model', 'claude-sonnet-4-5-20250929'),
'max_tokens' => 8192,
'messages' => [
[
'role' => 'user',
'content' => $content,
],
],
]);
if ($response->successful()) {
return $response->json();
} else {
Log::info('CreatesClaudeResponse error: ' . $response->body());
return null;
}
}
catch (\Illuminate\Http\Client\ConnectionException $exception) {
Log::info('ConnectionException' . json_encode($exception));
throw new ConnectionErrorException(
'Failed to connect to Claude API',
$exception->getMessage(),
$userPrompt,
$exception->getTraceAsString()
);
}
catch (\Exception $exception) {
Log::info('Exception' . json_encode($exception));
throw new MalformedRequestException(
'Unable to get correct response from Claude API: ' . $exception->getMessage()
);
}
}
}
@@ -0,0 +1,67 @@
<?php
namespace App\Classes\Modules\Anthropic\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
class CreatesClaudeResponseWithFiles
{
public function execute(string $userPrompt, array $fileIds)
{
try {
$content = [];
// User prompt
$content[] = [
'type' => 'text',
'text' => $userPrompt,
];
// Attach files
foreach ($fileIds as $fileId) {
$content[] = [
'type' => 'document',
'source' => [
'type' => 'file',
'file_id' => $fileId,
],
];
}
$response = Http::withHeaders([
'x-api-key' => config('anthropic.api_key'),
'anthropic-version' => config('anthropic.api_version', '2023-06-01'),
'anthropic-beta' => 'files-api-2025-04-14',
'Content-Type' => 'application/json',
])->post(config('anthropic.base_url') . '/v1/messages', [
'model' => config('anthropic.default_model', 'claude-sonnet-4-5-20250929'),
'max_tokens' => 16384,
'messages' => [
[
'role' => 'user',
'content' => $content,
],
],
]);
return $response->json();
}
catch (\Illuminate\Http\Client\ConnectionException $exception) {
$error = 'Failed to connect to Claude API';
throw new ConnectionErrorException(
$error,
$exception->getMessage(),
$userPrompt,
$exception->getTraceAsString()
);
}
catch (\Exception $exception) {
throw new MalformedRequestException(
'Unable to get correct response from Claude API: ' . $exception->getMessage()
);
}
}
}
@@ -0,0 +1,57 @@
<?php
namespace App\Classes\Modules\Anthropic\Services;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
class UploadsClaudeFiles
{
public function execute(array $paths): array
{
try {
$ids = [];
foreach ($paths as $path) {
$response = Http::withHeaders([
'x-api-key' => config('anthropic.api_key'),
'anthropic-version' => '2023-06-01',
'anthropic-beta' => 'files-api-2025-04-14',
])->attach(
'file',
fopen($path, 'r'),
basename($path)
)->post(config('anthropic.base_url') . '/v1/files');
$data = $response->json();
if ($response->successful() && isset($data['id'])) {
$ids[] = $data['id'];
} else {
Log::error('Claude file upload failed', [
'path' => $path,
'response' => $data,
]);
}
}
return $ids;
}
catch (\Illuminate\Http\Client\ConnectionException $exception) {
$error = 'Failed to connect to Claude API';
throw new ConnectionErrorException(
$error,
$exception->getMessage(),
$exception->getTraceAsString()
);
}
catch (\Exception $exception) {
throw new MalformedRequestException(
'Unable to get correct response from Claude API: ' . $exception->getMessage()
);
}
}
}
@@ -9,18 +9,14 @@ use App\Classes\Modules\Orders\Services\UpdatesOrdersStatus;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Http\Resources\DocumentResource;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Companies\Processors\ApproveIdentificationDocumentOnExchangeProcessor;
use App\Classes\Modules\Documents\Services\FetchesDocument;
use App\Classes\Modules\Documents\Services\ApprovesDocument;
use App\Classes\Modules\Documents\Services\PendingVerificationDocument;
use App\Classes\Modules\Notifications\DataTransferObjects\NotificationObject;
use App\Classes\Modules\Notifications\Processors\CreateNotificationProcessor;
use App\Classes\ValueObjects\Constants\DocumentType;
use App\Models\Document;
use App\Models\ExchangeCompanyConnection;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
class ApproveIdentificationDocumentLogic extends AbstractControllerLogic
{
@@ -60,9 +56,6 @@ class ApproveIdentificationDocumentLogic extends AbstractControllerLogic
/** @var CreateNotificationProcessor */
private $createNotificationProcessor;
/** @var ApproveIdentificationDocumentOnExchangeProcessor */
private $approveIdentificationDocumentOnExchangeProcessor;
/**
* ApproveIdentificationDocumentLogic constructor.
* @param CanApproveDocument $canApproveDocument
@@ -73,9 +66,8 @@ class ApproveIdentificationDocumentLogic extends AbstractControllerLogic
* @param UpdatesCompanyStatus $updatesCompanyStatus
* @param UpdatesOrdersStatus $updatesOrdersStatus
* @param CreateNotificationProcessor $createNotificationProcessor
* @param ApproveIdentificationDocumentOnExchangeProcessor $approveIdentificationDocumentOnExchangeProcessor
*/
public function __construct(CanApproveDocument $canApproveDocument, ApprovesDocument $approvesDocument, RejectsDocument $rejectsDocument, FetchesDocument $fetchesDocument, UpdatesCompanyStatus $updatesCompanyStatus, UpdatesOrdersStatus $updatesOrdersStatus, CreateNotificationProcessor $createNotificationProcessor, ApproveIdentificationDocumentOnExchangeProcessor $approveIdentificationDocumentOnExchangeProcessor, PendingVerificationDocument $pendingVerificationDocument)
public function __construct(CanApproveDocument $canApproveDocument, ApprovesDocument $approvesDocument, RejectsDocument $rejectsDocument, FetchesDocument $fetchesDocument, UpdatesCompanyStatus $updatesCompanyStatus, UpdatesOrdersStatus $updatesOrdersStatus, CreateNotificationProcessor $createNotificationProcessor, PendingVerificationDocument $pendingVerificationDocument)
{
$this->canApproveDocument = $canApproveDocument;
$this->approvesDocument = $approvesDocument;
@@ -85,7 +77,6 @@ class ApproveIdentificationDocumentLogic extends AbstractControllerLogic
$this->updatesOrdersStatus = $updatesOrdersStatus;
$this->createNotificationProcessor = $createNotificationProcessor;
$this->pendingVerificationDocument = $pendingVerificationDocument;
$this->approveIdentificationDocumentOnExchangeProcessor = $approveIdentificationDocumentOnExchangeProcessor;
}
/**
@@ -97,13 +88,6 @@ class ApproveIdentificationDocumentLogic extends AbstractControllerLogic
*/
public function logic(Request $request): JsonResponse
{
$documentId = $request->route('document_id');
if ($request->route('exchange_company_id')) {
$companyModule = ExchangeCompanyConnection::where('exchange_company_id', $request->route('exchange_company_id'))->first()->companyModule;
$company = $companyModule->company;
$documentId = $company->documents()->whereIn('document_type', DocumentType::IDENTIFICATION_DOCUMENTS)->where('status', ApprovalStatus::PENDING_VERIFICATION)->first()->id;
}
$status = $request->route('status');
@@ -133,12 +117,6 @@ class ApproveIdentificationDocumentLogic extends AbstractControllerLogic
// $this->createNotificationProcessor->execute($object);
// if this request is not calling from exchange portal, then approve the document on exchange portal for this user
$companyModule = $document->owner->companyModules()->first();
if (!$request->route('exchange_company_id') && $companyModule->exchangeCompanyConnection()->first()) {
$this->approveIdentificationDocumentOnExchangeProcessor->execute($request, $companyModule->id, $status);
}
return $this->resourceResponse(new DocumentResource($document));
}
}
}
@@ -4,7 +4,6 @@ namespace App\Classes\Modules\Companies\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Companies\Processors\CreateIdentificationDocumentOnExchangeProcessor;
use App\Classes\Modules\Companies\Services\FetchesCompany;
use App\Classes\Modules\Companies\Services\UpdatesCompanyStatus;
use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject;
@@ -15,7 +14,6 @@ use App\Classes\ValueObjects\Constants\CompanyType;
use App\Classes\ValueObjects\Constants\DocumentType;
use App\Models\Company;
use App\Models\Document;
use App\Models\ExchangeCompanyConnection;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -44,9 +42,6 @@ class CreateIdentificationDocumentLogic extends AbstractControllerLogic
/** @var UpdatesCompanyStatus */
private $updatesCompanyStatus;
/** @var CreateIdentificationDocumentOnExchangeProcessor */
private $createIdentificationDocumentOnExchangeProcessor;
/**
* CreateIdentificationDocumentLogic constructor.
@@ -54,15 +49,13 @@ class CreateIdentificationDocumentLogic extends AbstractControllerLogic
* @param CreatesDocument $createsDocument
* @param CreatesFiles $createsFile
* @param UpdatesCompanyStatus $updatesCompanyStatus
* @param CreateIdentificationDocumentOnExchangeProcessor $createIdentificationDocumentOnExchangeProcessor
*/
public function __construct(FetchesCompany $fetchesCompany, CreatesDocument $createsDocument, CreatesFiles $createsFile, UpdatesCompanyStatus $updatesCompanyStatus, CreateIdentificationDocumentOnExchangeProcessor $createIdentificationDocumentOnExchangeProcessor)
public function __construct(FetchesCompany $fetchesCompany, CreatesDocument $createsDocument, CreatesFiles $createsFile, UpdatesCompanyStatus $updatesCompanyStatus)
{
$this->fetchesCompany = $fetchesCompany;
$this->createsDocument = $createsDocument;
$this->createsFile = $createsFile;
$this->updatesCompanyStatus = $updatesCompanyStatus;
$this->createIdentificationDocumentOnExchangeProcessor = $createIdentificationDocumentOnExchangeProcessor;
}
/**
@@ -73,15 +66,8 @@ class CreateIdentificationDocumentLogic extends AbstractControllerLogic
public function logic(Request $request) : JsonResponse
{
if ($request->route('exchange_company_id')) {
$companyModule = ExchangeCompanyConnection::where('exchange_company_id', $request->route('exchange_company_id'))->first()->companyModule;
$companyId = $companyModule->company_id;
} else {
$companyId = $request->route('id');
}
/** @var Company $company */
$company = $this->fetchesCompany->execute(['id' => $companyId]);
$company = $this->fetchesCompany->execute(['id' => $request->route('id')]);
$object = new DocumentObject($company->type === CompanyType::COMPANY_BUSINESS ?
DocumentType::SSM_REGISTRATION : DocumentType::IDENTITY_CARD, $request->input('files'),
$request->input('identification_no'), ApprovalStatus::PENDING_VERIFICATION, 'identifications');
@@ -92,12 +78,6 @@ class CreateIdentificationDocumentLogic extends AbstractControllerLogic
$this->updatesCompanyStatus->execute($company, ApprovalStatus::PENDING_VERIFICATION);
// create identification on exchange if this request not coming from exchange
$companyModule = $company->companyModules()->first();
if (!$request->route('exchange_company_id') && $companyModule->exchangeCompanyConnection()->first()) {
$this->createIdentificationDocumentOnExchangeProcessor->execute($request, $companyModule->id);
}
return $this->response([]);
}
@@ -0,0 +1,69 @@
<?php
namespace App\Classes\Modules\Companies\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Companies\Services\FetchesCompany;
use App\Classes\Modules\Companies\Standards\Rules\CanFetchCompany;
use App\Classes\ValueObjects\Constants\AddressType;
use App\Http\Resources\EInvoiceInfoResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class FetchCompanyEInvoiceInfoLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Retrieved Company E-Invoice Info',
'message' => 'You have successfully retrieved a Company E-Invoice Info'
];
}
/** @var CanFetchCompany */
private $canFetchCompany;
/** @var FetchesCompany */
private $fetchesCompany;
/**
* FetchCompanyEInvoiceInfoLogic constructor.
* @param CanFetchCompany $canFetchCompany
* @param FetchesCompany $fetchesCompany
*/
public function __construct(CanFetchCompany $canFetchCompany, FetchesCompany $fetchesCompany)
{
$this->canFetchCompany = $canFetchCompany;
$this->fetchesCompany = $fetchesCompany;
}
/**
* @param Request $request
* @return JsonResponse
* @throws \App\Classes\Exceptions\AccessForbiddenException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
public function logic(Request $request) : JsonResponse
{
$this->canFetchCompany->passes();
$company = $this->fetchesCompany->execute(['id' => $request->route('id')]);
$eInvoiceInfo = $company->companyModules()->first()->addresses()->where('type', '=', AddressType::E_INVOICE)->latest()->first();
if($eInvoiceInfo){
$eInvoiceInfo->tin = $company->tin;
$eInvoiceInfo->msic_code = $company->msic_code;
$eInvoiceInfo->e_invoice = $company->e_invoice;
}
else{
return $this->response([]);
}
return $this->resourceResponse(new EInvoiceInfoResource($eInvoiceInfo));
}
}
@@ -1,45 +0,0 @@
<?php
namespace App\Classes\Modules\Companies\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Companies\Processors\LinkExchangeCompanyProcessor;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class LinkExchangeCompanyLogic extends AbstractControllerLogic
{
protected function notification():array {
return [
'title' => 'Connect Exchange with Izyim Account',
'message' => 'You have successfully connect your exchange account to Izyim Account'
];
}
/** @var LinkExchangeCompanyProcessor */
private $linkExchangeCompanyProcessor;
/**
* LinkExchangeCompanyLogic constructor.
* @param LinkExchangeCompanyProcessor $linkExchangeCompanyProcessor
*/
public function __construct(LinkExchangeCompanyProcessor $linkExchangeCompanyProcessor)
{
$this->linkExchangeCompanyProcessor = $linkExchangeCompanyProcessor;
}
/**
* @param Request $request
* @return JsonResponse
* @throws \App\Classes\Exceptions\AccessForbiddenException
* @throws \App\Classes\Exceptions\AccessUnauthorisedException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
protected function logic(Request $request): JsonResponse {
return $this->response($this->linkExchangeCompanyProcessor->execute($request));
}
}
@@ -3,14 +3,10 @@
namespace App\Classes\Modules\Companies\ControllersLogic;
use App\Classes\Exceptions\AccessForbiddenException;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\RequestValidationException;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Companies\Services\ListsCompanyModules;
use App\Classes\Modules\Companies\Standards\Rules\CanListCompanies;
use App\Http\Resources\CompanyModuleResource;
use App\Transformers\CompanyTransformer;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -21,8 +17,7 @@ class ListCompanyModulesLogic extends AbstractControllerLogic
/**
* @return array
*/
protected function notification(): array
{
protected function notification():array {
return [
'title' => 'Retrieved Company Moduels',
'message' => 'You have successfully retrieved a list of Companies'
@@ -50,26 +45,15 @@ class ListCompanyModulesLogic extends AbstractControllerLogic
/**
* @param Request $request
* @return JsonResponse
* @throws AccessForbiddenException
* @throws MalformedRequestException
* @throws RequestValidationException
* @throws \App\Classes\Exceptions\AccessForbiddenException
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
public function logic(Request $request): JsonResponse
public function logic(Request $request) : JsonResponse
{
$this->canListCompanies->passes();
$query = $this->listsCompanyModules->execute($this->listsCompanyModules->deserializeFilters($request->input('filters')));
/*include all relationships*/
/* return fractal()
->collection($query, new CompanyTransformer)
->parseIncludes('company')
->parseIncludes('contact')
->parseIncludes('remarks')
->parseIncludes('address')
->parseIncludes('billingAddress')
->respond(200, [], JSON_PRETTY_PRINT);*/
return $this->collectionResponse(CompanyModuleResource::collection($query));
}
@@ -0,0 +1,190 @@
<?php
namespace App\Classes\Modules\Companies\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Companies\Services\FetchesCompany;
use App\Classes\Modules\Companies\Services\UpdatesCompany;
use App\Classes\Modules\Companies\Services\UpdatesCompanyDebtor;
use App\Classes\Modules\Addresses\Services\UpsertsAddress;
use App\Classes\Modules\Addresses\Services\FetchesDistrict;
use App\Classes\Modules\Companies\Services\UpdatesCompanyModuleName;
use App\Classes\Modules\Documents\Services\FetchesDocument;
use App\Classes\Modules\Documents\Services\UpdatesDocumentReference;
use App\Classes\Modules\Documents\Services\CreatesDocument;
use App\Classes\Modules\Documents\Services\CreatesFiles;
use App\Classes\Modules\Companies\Services\UpdatesCompanyEInvoiceInfo;
use App\Classes\Modules\Companies\Standards\Rules\CanUpdateCompany;
use App\Classes\Modules\Addresses\Standards\Rules\CanCreateAddress;
use App\Classes\Modules\Addresses\DataTransferObjects\AddressObject;
use App\Classes\Modules\Companies\DataTransferObjects\CompanyObject;
use App\Classes\Modules\Companies\DataTransferObjects\UpdateCompanyDetailsDTO;
use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject;
use App\Classes\ValueObjects\Constants\CompanyType;
use App\Classes\ValueObjects\Constants\DocumentType;
use App\Classes\ValueObjects\Constants\AddressType;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Http\Resources\CompanyResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class UpdateCompanyDetailsLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Update Company Details',
'message' => 'You have successfully updated the Company Details'
];
}
/** @var CanUpdateCompany */
private $canUpdateCompany;
/** @var UpdatesCompany */
private $updatesCompany;
/** @var FetchesCompany */
private $fetchesCompany;
/** @var UpdatesCompanyDebtor */
private $updatesCompanyDebtor;
/** @var CanCreateAddress */
private $canCreateAddress;
/** @var FetchesDistrict */
private $fetchesDistrict;
/** @var UpsertsAddress */
private $upsertsAddress;
/** @var UpdatesCompanyEInvoiceInfo */
private $updatesCompanyEInvoiceInfo;
/** @var UpdatesCompanyModuleName */
private $updatesCompanyModuleName;
/** @var FetchesDocument */
private $fetchesDocument;
/** @var UpdatesDocumentReference */
private $updatesDocumentReference;
/** @var CreatesDocument */
private $createsDocument;
/** @var CreatesFiles */
private $createsFile;
/**
* UpdateCompanyDetailsLogic constructor.
* @param CanUpdateCompany $canUpdateCompany
* @param UpdatesCompany $updatesCompany
* @param FetchesCompany $fetchesCompany
* @param UpdatesCompanyDebtor $updatesCompanyDebtor
* @param CanCreateAddress $canCreateAddress
* @param FetchesDistrict $fetchesDistrict
* @param UpsertsAddress $upsertsAddress
* @param UpdatesCompanyEInvoiceInfo $updatesCompanyEInvoiceInfo;
* @param FetchesDocument $fetchesDocument
* @param UpdatesDocumentReference $updatesDocumentReference
* @param CreatesDocument $createsDocument
* @param CreatesFiles $createsFile
*/
public function __construct(
CanUpdateCompany $canUpdateCompany,
UpdatesCompany $updatesCompany,
FetchesCompany $fetchesCompany,
UpdatesCompanyDebtor $updatesCompanyDebtor,
CanCreateAddress $canCreateAddress,
FetchesDistrict $fetchesDistrict,
UpsertsAddress $upsertsAddress,
UpdatesCompanyEInvoiceInfo $updatesCompanyEInvoiceInfo,
UpdatesCompanyModuleName $updatesCompanyModuleName,
FetchesDocument $fetchesDocument,
UpdatesDocumentReference $updatesDocumentReference,
CreatesDocument $createsDocument,
CreatesFiles $createsFile
)
{
$this->canUpdateCompany = $canUpdateCompany;
$this->updatesCompany = $updatesCompany;
$this->fetchesCompany = $fetchesCompany;
$this->updatesCompanyDebtor = $updatesCompanyDebtor;
$this->canCreateAddress = $canCreateAddress;
$this->fetchesDistrict = $fetchesDistrict;
$this->upsertsAddress = $upsertsAddress;
$this->updatesCompanyEInvoiceInfo = $updatesCompanyEInvoiceInfo;
$this->updatesCompanyModuleName = $updatesCompanyModuleName;
$this->fetchesDocument = $fetchesDocument;
$this->updatesDocumentReference = $updatesDocumentReference;
$this->createsDocument = $createsDocument;
$this->createsFile = $createsFile;
}
/**
* @param Request $request
* @return JsonResponse
* @throws ErrorException
*/
public function logic(Request $request) : JsonResponse
{
$dto = new UpdateCompanyDetailsDTO($request->all());
$object = new CompanyObject($dto->name, $dto->reference, $dto->type);
$this->canUpdateCompany->passes($object);
$company = $this->fetchesCompany->execute(['id' => $request->route('id')]);
$this->updatesCompanyModuleName->execute($company->companyModules()->first(), $object->getName());
//Update Name and Debtor, Type
$company = $this->updatesCompany->execute($company, $object);
if ($request->input('debtor') || $company->first()->debtor !== null) {
$this->updatesCompanyDebtor->execute($company, $request->input('debtor'));
}
//Update EInvoice Related Info
if($company->e_invoice){
$district = $this->fetchesDistrict->execute(['id' => $dto->districtId]);
$addObj = new AddressObject($dto->streetOne, $dto->streetTwo, $district->country_id, $dto->stateId, $district->id, $dto->postCode, AddressType::E_INVOICE, ApprovalStatus::APPROVED, 'E-Invoice');
$this->canCreateAddress->passes($addObj);
$this->upsertsAddress->execute($company->companyModules()->first(), $addObj, $dto->addressId);
$this->updatesCompanyEInvoiceInfo->execute($company, $dto->tin, $dto->msicCode);
}
//Update Identification Card / SSM Registration
if($dto->identificationId){
$document = $this->fetchesDocument->execute(['id' => $dto->identificationId]);
$this->updatesDocumentReference->execute($document, $dto->identificationReference);
}
else{
if($dto->identificationReference){
$pathToFile = base_path('resources/assets/images/ssm_ic_placeholder.png');
$mimeType = mime_content_type($pathToFile);
$fileContents = file_get_contents($pathToFile);
$base64 = base64_encode($fileContents);
$base64File = "data:$mimeType;base64,$base64";
$files = [$base64File];
/** @var Document $document */
$company = $this->fetchesCompany->execute(['id' => $dto->id]);
$object = new DocumentObject($company->type === CompanyType::COMPANY_BUSINESS ?
DocumentType::SSM_REGISTRATION : DocumentType::IDENTITY_CARD, $files,
$dto->identificationReference, ApprovalStatus::PENDING_VERIFICATION, 'identifications');
$document = $this->createsDocument->execute($company, $object);
$this->createsFile->execute($document, $object);
}
}
return $this->resourceResponse(new CompanyResource($company));
}
}
@@ -0,0 +1,116 @@
<?php
namespace App\Classes\Modules\Companies\ControllersLogic;
use App\Classes\Exceptions\CriteriaNotFulfilledException;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Addresses\Services\CreatesAddress;
use App\Classes\Modules\Addresses\Services\FetchesDistrict;
use App\Classes\Modules\Addresses\Standards\Rules\CanCreateAddress;
use App\Classes\Modules\Addresses\DataTransferObjects\AddressObject;
use App\Classes\Modules\Companies\Services\FetchesCompanyModule;
use App\Classes\Modules\Companies\Services\UpdatesCompanyEInvoiceInfo;
use App\Classes\Modules\Companies\DataTransferObjects\EInvoiceInfoDTO;
use App\Classes\Modules\Rules\Services\RuleEvaluator;
use App\Classes\Modules\Rules\Standards\Rules\CanPassEInvoicePromptedRule;
use App\Classes\ValueObjects\Constants\AddressType;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class UpdateCompanyEInvoiceInfoLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'EInvoice Info Update',
'message' => 'You have successfully updated company E-Invoice information'
];
}
/** @var CanCreateAddress */
private $canCreateAddress;
/** @var FetchesDistrict */
private $fetchesDistrict;
/** @var FetchesCompanyModule */
private $fetchesCompanyModule;
/** @var CreatesAddress */
private $createsAddress;
/** @var RuleEvaluator */
private $ruleEvaluator;
/** @var UpdatesCompanyEInvoiceInfo */
private $updatesCompanyEInvoiceInfo;
/** @var CanPassEInvoicePromptedRule */
private $canPassEInvoicePromptedRule;
/**
* UpdateCompanyEInvoiceInfoLogic constructor.
* @param CanCreateAddress $canCreateAddress
* @param FetchesDistrict $fetchesDistrict
* @param FetchesCompanyModule $fetchesCompanyModule
* @param CreatesAddress $createsAddress
* @param RuleEvaluator $ruleEvaluator;
* @param UpdatesCompanyEInvoiceInfo $updatesCompanyEInvoiceInfo;
* @param CanPassEInvoicePromptedRule $canPassEInvoicePromptedRule
*/
public function __construct(CanCreateAddress $canCreateAddress, FetchesDistrict $fetchesDistrict, FetchesCompanyModule $fetchesCompanyModule, CreatesAddress $createsAddress, RuleEvaluator $ruleEvaluator, UpdatesCompanyEInvoiceInfo $updatesCompanyEInvoiceInfo, CanPassEInvoicePromptedRule $canPassEInvoicePromptedRule)
{
$this->canCreateAddress = $canCreateAddress;
$this->fetchesDistrict = $fetchesDistrict;
$this->fetchesCompanyModule = $fetchesCompanyModule;
$this->createsAddress = $createsAddress;
$this->ruleEvaluator = $ruleEvaluator;
$this->updatesCompanyEInvoiceInfo = $updatesCompanyEInvoiceInfo;
$this->canPassEInvoicePromptedRule = $canPassEInvoicePromptedRule;
}
/**
* @param Request $request
* @return JsonResponse
* @throws \App\Classes\Exceptions\AccessForbiddenException
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws \App\Classes\Exceptions\RequestValidationException
* @throws \App\Classes\Exceptions\CriteriaNotFulfilledException
*/
public function logic(Request $request) : JsonResponse
{
$dto = new EInvoiceInfoDTO($request->all());
$result = $this->ruleEvaluator->evaluate([
$this->canPassEInvoicePromptedRule,
], $dto);
if ($result->failed()) {
throw new CriteriaNotFulfilledException("- " . implode("<br>- ", $result->messages()));
}
$district = $this->fetchesDistrict->execute(['id' => $dto->districtId]);
$object = new AddressObject($dto->streetOne, $dto->streetTwo, $district->country_id, $dto->stateId, $district->id, $dto->postCode, AddressType::E_INVOICE, ApprovalStatus::APPROVED, 'E-Invoice');
//Update Address
$this->canCreateAddress->passes($object);
$companyModule = $this->fetchesCompanyModule->execute(['id' => $dto->companyModuleId]);
$this->createsAddress->execute($companyModule, $object);
// create billing address if not exists
$billingAddress = $companyModule->addresses->where('type', AddressType::BILLING)->where('status', ApprovalStatus::APPROVED)->first();
if (!$billingAddress) {
$billingAddress = new AddressObject($dto->streetOne, $dto->streetTwo, $district->country_id, $dto->stateId, $district->id, $dto->postCode, AddressType::BILLING, ApprovalStatus::APPROVED, 'Billing Address');
$this->createsAddress->execute($companyModule, $billingAddress);
}
//Update tin, msic code
$this->updatesCompanyEInvoiceInfo->execute($companyModule->company, $dto->tin, $dto->msicCode);
return $this->response([]);
}
}
@@ -0,0 +1,62 @@
<?php
namespace App\Classes\Modules\Companies\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Companies\Services\UpdatesCompanyEInvoiceRequest;
use App\Classes\Modules\Companies\Services\FetchesCompanyModule;
use App\Classes\Modules\Companies\DataTransferObjects\EInvoiceRequestDTO;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class UpdateCompanyEInvoiceRequestChangeLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Updated EInvoice Request',
'message' => 'You have successfully updated company E-Invoice request'
];
}
/** @var FetchesCompanyModule */
private $fetchesCompanyModule;
/** @var UpdatesCompanyEInvoiceRequest */
private $updatesCompanyEInvoiceRequest;
/**
* UpdateCompanyEInvoiceRequestChangeLogic constructor.
* @param FetchesCompanyModule $fetchesCompanyModule
* @param UpdatesCompanyEInvoiceRequest $updatesCompanyEInvoiceRequest
*/
public function __construct(FetchesCompanyModule $fetchesCompanyModule, UpdatesCompanyEInvoiceRequest $updatesCompanyEInvoiceRequest)
{
$this->fetchesCompanyModule = $fetchesCompanyModule;
$this->updatesCompanyEInvoiceRequest = $updatesCompanyEInvoiceRequest;
}
/**
* @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
{
$dto = new EInvoiceRequestDTO($request->all());
$companyModule = $this->fetchesCompanyModule->execute(['id' => $dto->companyModuleId]);
if($companyModule->company->e_invoice === 1){
$this->updatesCompanyEInvoiceRequest->execute($companyModule->company, $dto->eInvoiceRequest);
}
return $this->response([]);
}
}
@@ -0,0 +1,59 @@
<?php
namespace App\Classes\Modules\Companies\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Companies\Services\UpdatesCompanyEInvoiceRequest;
use App\Classes\Modules\Companies\Services\FetchesCompanyModule;
use App\Classes\Modules\Companies\DataTransferObjects\EInvoiceRequestDTO;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class UpdateCompanyEInvoiceRequestLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Updated EInvoice Request',
'message' => 'You have successfully updated company E-Invoice request'
];
}
/** @var FetchesCompanyModule */
private $fetchesCompanyModule;
/** @var UpdatesCompanyEInvoiceRequest */
private $updatesCompanyEInvoiceRequest;
/**
* UpdateCompanyEInvoiceRequestLogic constructor.
* @param FetchesCompanyModule $fetchesCompanyModule
* @param UpdatesCompanyEInvoiceRequest $updatesCompanyEInvoiceRequest
*/
public function __construct(FetchesCompanyModule $fetchesCompanyModule, UpdatesCompanyEInvoiceRequest $updatesCompanyEInvoiceRequest)
{
$this->fetchesCompanyModule = $fetchesCompanyModule;
$this->updatesCompanyEInvoiceRequest = $updatesCompanyEInvoiceRequest;
}
/**
* @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
{
$dto = new EInvoiceRequestDTO($request->all());
$companyModule = $this->fetchesCompanyModule->execute(['id' => $dto->companyModuleId]);
$this->updatesCompanyEInvoiceRequest->execute($companyModule->company, $dto->eInvoiceRequest);
return $this->response([]);
}
}
@@ -0,0 +1,43 @@
<?php
namespace App\Classes\Modules\Companies\DataTransferObjects;
use App\Classes\General\Interfaces\DataTransferObject;
class EInvoiceInfoDTO implements DataTransferObject
{
public string $tin;
public string $msicCode;
public int $districtId;
public int $stateId;
public int $companyModuleId;
public string $streetOne;
public string $streetTwo;
public string $postCode;
public function __construct(array $data)
{
$this->tin = (string) ($data['tin'] ?? '');
$this->msicCode = (string) ($data['msic_code'] ?? '');
$this->districtId = (int) ($data['district_id'] ?? 0);
$this->stateId = (int) ($data['state_id'] ?? 0);
$this->companyModuleId = (int) ($data['company_module_id'] ?? 0);
$this->streetOne = (string) ($data['street_one'] ?? '');
$this->streetTwo = (string) ($data['street_two'] ?? '');
$this->postCode = (string) ($data['post_code'] ?? '');
}
public function toArray(): array
{
return [
'tin' => $this->tin,
'msic_code' => $this->msicCode,
'district_id' => $this->districtId,
'state_id' => $this->stateId,
'company_module_id' => $this->companyModuleId,
'street_one' => $this->streetOne,
'street_two' => $this->streetTwo,
'post_code' => $this->postCode,
];
}
}
@@ -0,0 +1,25 @@
<?php
namespace App\Classes\Modules\Companies\DataTransferObjects;
use App\Classes\General\Interfaces\DataTransferObject;
class EInvoiceRequestDTO implements DataTransferObject
{
public bool $eInvoiceRequest;
public int $companyModuleId;
public function __construct(array $data)
{
$this->eInvoiceRequest = $data['e_invoice_request'];
$this->companyModuleId = $data['company_module_id'];
}
public function toArray(): array
{
return [
'e_invoice_request' => $this->eInvoiceRequest,
'company_module_id' => $this->companyModuleId,
];
}
}
@@ -0,0 +1,72 @@
<?php
namespace App\Classes\Modules\Companies\DataTransferObjects;
use App\Classes\General\Interfaces\DataTransferObject;
class UpdateCompanyDetailsDTO implements DataTransferObject
{
public int $id;
public string $name;
public string $debtor;
public string $reference;
public int $type;
public string $tin;
public string $msicCode;
public int $addressId;
public int $districtId;
public int $stateId;
public int $companyId;
public string $streetOne;
public string $streetTwo;
public string $postCode;
public string $identificationReference;
public int $identificationId;
public function __construct(array $data)
{
$this->id = (int) ($data['id'] ?? 0);
$this->name = (string) ($data['name'] ?? '');
$this->debtor = (string) ($data['debtor'] ?? '');
$this->reference = (string) ($data['reference'] ?? '');
$this->type = (int) ($data['type'] ?? 0);
$this->tin = (string) ($data['tin'] ?? 0);
$this->msicCode = (string) ($data['msic_code'] ?? '');
$this->addressId = (int) ($data['address_id'] ?? 0);
$this->districtId = (int) ($data['district_id'] ?? 0);
$this->stateId = (int) ($data['state_id'] ?? 0);
$this->companyId = (int) ($data['company_id'] ?? 0);
$this->streetOne = (string) ($data['street_one'] ?? '');
$this->streetTwo = (string) ($data['street_two'] ?? '');
$this->postCode = (string) ($data['post_code'] ?? '');
$this->identificationReference = (string) ($data['identification_reference'] ?? '');
$this->identificationId = (int) ($data['identification_id'] ?? 0);
}
public function toArray(): array
{
return [
'id' => $this->id,
'name' => $this->name,
'debtor' => $this->debtor,
'reference' => $this->reference,
'type' => $this->type,
'tin' => $this->tin,
'msic_code' => $this->msicCode,
'address_id' => $this->addressId,
'district_id' => $this->districtId,
'state_id' => $this->stateId,
'company_id' => $this->companyId,
'street_one' => $this->streetOne,
'street_two' => $this->streetTwo,
'post_code' => $this->postCode,
'identification_reference' => $this->identificationReference,
'identification_id' => $this->identificationId,
];
}
}
@@ -1,48 +0,0 @@
<?php
namespace App\Classes\Modules\Companies\Processors;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Log;
class ApproveIdentificationDocumentOnExchangeProcessor
{
/**
* @param Request $request
* @return string
* @throws \App\Classes\Exceptions\AccessForbiddenException
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
public function execute(Request $request, $companyModuleId, $status) {
if (App::environment(['production'])) {
dd("Delete this line before push to production");
$url = "https://exchange.cief-malaysia.com/api/v1/shipping/company/{$companyModuleId}/identification/approval/{$status}";
} else if (App::environment(['local'])) {
$url = "http://127.0.0.1:8000/api/v1/shipping/company/{$companyModuleId}/identification/approval/{$status}";
} else {
$url = "https://dev.exchange.cief-malaysia.com/api/v1/shipping/company/{$companyModuleId}/identification/approval/{$status}";
}
try {
$client = new \GuzzleHttp\Client(['verify' => false]);
$token = $request->bearerToken();
$headers = [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
];
$formParams = $request->toArray();
$response = $client->request('PUT', $url, [
'headers' => $headers,
'form_params' => $formParams
]);
$body = $response->getBody();
$contents = json_decode($body, true);
return $contents;
} catch(\GuzzleHttp\Exception\RequestException $exception){
Log::error($exception->getResponse()->getBody()->getContents());
}
}
}
@@ -1,48 +0,0 @@
<?php
namespace App\Classes\Modules\Companies\Processors;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Log;
class CreateIdentificationDocumentOnExchangeProcessor
{
/**
* @param Request $request
* @return string
* @throws \App\Classes\Exceptions\AccessForbiddenException
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
public function execute(Request $request, $companyModuleId) {
if (App::environment(['production'])) {
dd("Delete this line before push to production");
$url = "https://exchange.cief-malaysia.com/api/v1/shipping/company/{$companyModuleId}/identification/create";
} else if (App::environment(['local'])) {
$url = "http://127.0.0.1:8000/api/v1/shipping/company/{$companyModuleId}/identification/create";
} else {
$url = "https://dev.exchange.cief-malaysia.com/api/v1/shipping/company/{$companyModuleId}/identification/create";
}
try {
$client = new \GuzzleHttp\Client(['verify' => false]);
$token = $request->bearerToken();
$headers = [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
];
$formParams = $request->toArray();
$response = $client->request('POST', $url, [
'headers' => $headers,
'form_params' => $formParams
]);
$body = $response->getBody();
$contents = json_decode($body, true);
return $contents;
} catch(\GuzzleHttp\Exception\RequestException $exception){
Log::error($exception->getResponse()->getBody()->getContents());
}
}
}
@@ -1,80 +0,0 @@
<?php
namespace App\Classes\Modules\Companies\Processors;
use App\Classes\Modules\Accounts\DataTransferObjects\AuthenticationCredentialsObject;
use App\Classes\Modules\Accounts\Services\AuthenticatesUser;
use App\Classes\Modules\Accounts\Services\AuthenticationRedirect;
use App\Classes\Modules\Accounts\Services\FetchesUser;
use App\Classes\Modules\Accounts\Services\GeneratesAuthenticationToken;
use App\Classes\Modules\Accounts\Standards\Rules\CanAuthenticateUser;
use App\Classes\Modules\Companies\Services\ConnectCompanyModuleToExchangeCompany;
use Illuminate\Http\Request;
class LinkExchangeCompanyProcessor
{
/** @var CanAuthenticateUser */
private $canAuthenticateUser;
/** @var AuthenticatesUser */
private $authenticatesUser;
/** @var GeneratesAuthenticationToken */
private $generatesAuthenticationToken;
/** @var FetchesUser */
private $fetchesUser;
/** @var AuthenticationRedirect */
private $authenticationRedirect;
/** @var ConnectCompanyModuleToExchangeCompany */
private $connectCompanyModuleToExchangeCompany;
/**
* AuthenticationProcessor constructor.
* @param CanAuthenticateUser $canAuthenticateUser
* @param AuthenticatesUser $authenticatesUser
* @param GeneratesAuthenticationToken $generatesAuthenticationToken
* @param FetchesUser $fetchesUser
* @param AuthenticationRedirect $authenticationRedirect
* @param ConnectCompanyModuleToExchangeCompany $connectCompanyModuleToExchangeCompany
*/
public function __construct(CanAuthenticateUser $canAuthenticateUser, AuthenticatesUser $authenticatesUser, GeneratesAuthenticationToken $generatesAuthenticationToken, FetchesUser $fetchesUser, AuthenticationRedirect $authenticationRedirect, ConnectCompanyModuleToExchangeCompany $connectCompanyModuleToExchangeCompany)
{
$this->canAuthenticateUser = $canAuthenticateUser;
$this->authenticatesUser = $authenticatesUser;
$this->generatesAuthenticationToken = $generatesAuthenticationToken;
$this->fetchesUser = $fetchesUser;
$this->authenticationRedirect = $authenticationRedirect;
$this->connectCompanyModuleToExchangeCompany = $connectCompanyModuleToExchangeCompany;
}
/**
* @param Request $request
* @return array
* @throws \App\Classes\Exceptions\AccessForbiddenException
* @throws \App\Classes\Exceptions\AccessUnauthorisedException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
public function execute(Request $request): array {
$object = new AuthenticationCredentialsObject($request->input('email'), $request->input('password'));
$this->canAuthenticateUser->passes($object);
$this->authenticatesUser->execute($object);
$user = $this->fetchesUser->execute(['email' => $object->getEmail()]);
$companyModule = $user->companyModule()->first();
$this->connectCompanyModuleToExchangeCompany->execute($companyModule, $request->route('exchange_company_id'));
return ['shipping_company_module_id' => $companyModule->id];
}
}
@@ -20,7 +20,7 @@ class AssignsCompanyConnectionToConnectionSegment extends AbstractUpdateRecord
{
try {
$companyConnection->segments()->attach($segment, ['created_at' => now(), 'updated_at' => now()]);
$companyConnection->segments()->attach($segment);
return $companyConnection;
@@ -22,7 +22,7 @@ class AssignsCompanyToSegment extends AbstractUpdateRecord
try {
$companyModule = $company->companyModules()->where('type', BusinessType::IMPORTER)->first();
$connection = $companyModule->connections()->where('inviter_reference', 'CIEF');
$connection->segments()->attach($segment, ['created_at' => now(), 'updated_at' => now()]);
$connection->segments()->attach($segment);
return $company;
@@ -18,7 +18,7 @@ class AssignsEmployee extends AbstractUpdateRecord
{
try {
$object->getCompanyModule()->employees()->attach($object->getUser(), ['status' => $object->getStatus(), 'role_id' => $object->getRoleId(), 'created_at' => now(), 'updated_at' => now()]);
$object->getCompanyModule()->employees()->attach($object->getUser(), ['status' => $object->getStatus(),'role_id' => $object->getRoleId()]);
return $object->getCompanyModule();
@@ -1,25 +0,0 @@
<?php
namespace App\Classes\Modules\Companies\Services;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Models\CompanyModule;
use App\Models\ExchangeCompanyConnection;
class ConnectCompanyModuleToExchangeCompany extends AbstractUpdateRecord
{
/**
* @param Company $company
* @return \Illuminate\Database\Eloquent\Model
* @throws MalformedRequestException
*/
public function execute(CompanyModule $companyModule, $exchangeCompanyId)
{
$model = new ExchangeCompanyConnection();
$model->company_module_id = $companyModule->id;
$model->exchange_company_id = $exchangeCompanyId;
return $this->handler($model);
}
}
@@ -0,0 +1,25 @@
<?php
namespace App\Classes\Modules\Companies\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Models\Company;
class UpdatesCompanyEInvoiceInfo extends AbstractUpdateRecord
{
/**
* @param Company $model
* @param string $tin
* @param string $msicCode
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(Company $model, string $tin, string $msicCode)
{
$model->tin = $tin;
$model->msic_code = $msicCode;
return $this->handler($model);
}
}
@@ -0,0 +1,35 @@
<?php
namespace App\Classes\Modules\Companies\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Models\Company;
class UpdatesCompanyEInvoiceRequest extends AbstractUpdateRecord
{
/**
* @param Company $model
* @param bool $eInvoice
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(Company $model, bool $eInvoice)
{
if($eInvoice){
if (is_null($model->e_invoice_requested_at)) {
if($eInvoice){
$model->e_invoice_requested_at = now();
}
}
$model->e_invoice = 1;
}
else{
$model->e_invoice_requested_at = null;
$model->e_invoice = 0;
}
return $this->handler($model);
}
}
@@ -8,7 +8,6 @@ use App\Classes\Modules\Contacts\Services\UpdatesContact;
use App\Classes\Modules\Contacts\DataTransferObjects\ContactObject;
use App\Classes\Modules\Contacts\Services\FetchesContact;
use App\Http\Resources\ContactResource;
use App\Transformers\ContactTransformer;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -64,13 +63,6 @@ class UpdateContactLogic extends AbstractControllerLogic
$query = $this->updatesContact->execute($query, $object);
/*uniformity*/
/* return fractal()
->item($query, new ContactTransformer())
->parseIncludes('remark')
->respond(200, [], JSON_PRETTY_PRINT);*/
return $this->resourceResponse(new ContactResource($query));
}
@@ -7,7 +7,6 @@ use App\Classes\Modules\Orders\Services\CancelsOrder;
use App\Classes\Modules\Orders\Services\FetchesOrder;
use App\Http\Resources\DeliveryOrderResource;
use App\Models\Order;
use App\Transformers\DeliveryOrderTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -53,14 +52,6 @@ class CancelDeliveryOrderLogic extends AbstractControllerLogic
/** @var Order $order */
$order = $this->fetchesOrder->execute(['id' => $request->route('id')]);
$order = $this->cancelsOrder->execute($order);
//no relationship needed
/* return fractal()
->item($order, new DeliveryOrderTransformer())
->respond(200, [], JSON_PRETTY_PRINT);*/
return $this->resourceResponse(new DeliveryOrderResource($this->cancelsOrder->execute($order)));
}
@@ -172,12 +172,6 @@ class CreateDeliveryOrderLogic extends AbstractControllerLogic
$packageObject = new PackageObject($request->input('packing_list.type'), $request->input('packing_list.description'), (float) 1, (float) 1, (float) 1, $request->input('packing_list.weight'), (float) $request->input('packing_list.quantity'), ApprovalStatus::APPROVED);
$this->createsPackage->execute($packageObject, $packingList);
//add relationship to order
/* return fractal()
->item($order, new DeliveryOrderTransformer())
->parseIncludes(['sender_address', 'delivery_address', 'sender_address.contacts', 'delivery_address.contacts', 'sender_address.remarks', 'delivery_address.remarks', 'packing_list', 'packing_list.packages'])
->respond(200, [], JSON_PRETTY_PRINT);*/
return $this->resourceResponse(new DeliveryOrderResource($order));
}
@@ -48,12 +48,6 @@ class ListOrdersLogic extends AbstractControllerLogic
$query = $this->listsOrders->execute(array_merge($this->listsOrders->deserializeFilters($request->input('filters')), ['with_parcels' => true, 'type_in' => [OrderType::LAST_MILE_DELIVERY]]));
//no relationship needed
/* return fractal()
->collection($query, new DeliveryOrderTransformer)
->respond(200, [], JSON_PRETTY_PRINT);*/
return $this->collectionResponse(DeliveryOrderResource::collection($query));
}
@@ -7,13 +7,9 @@ use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Documents\Services\ListsDocuments;
use App\Classes\Modules\Documents\Standards\Rules\CanListDocuments;
use App\Http\Resources\DocumentResource;
use App\Models\Document;
use App\Transformers\DocumentTransformer;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use League\Fractal;
class ListDocumentLogic extends AbstractControllerLogic
{
@@ -62,11 +58,6 @@ class ListDocumentLogic extends AbstractControllerLogic
return $this->collectionResponse(DocumentResource::collection($query));
/* return fractal()
->collection($query, new DocumentTransformer)
->respond(200, [], JSON_PRETTY_PRINT);*/
}
}
@@ -5,7 +5,6 @@ namespace App\Classes\Modules\Documents\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Models\Document;
use App\Models\User;
use Carbon\Carbon;
class ApprovesDocument extends AbstractUpdateRecord
@@ -18,19 +17,8 @@ class ApprovesDocument extends AbstractUpdateRecord
*/
public function execute(Document $model)
{
$user = Auth()->user();
// if auth user is null, then this services is calling from exchange
if (!$user) {
$token = explode('.', request()->bearerToken())[1];
$decodedToken = base64_decode($token);
$exchangeUser = json_decode($decodedToken, true)['user'];
$user = User::where('email', $exchangeUser['email'])->first();
if (!$user) {
$user = User::find(1);
}
}
$model->status = ApprovalStatus::APPROVED;
$model->approver = $user->id;
$model->approver = Auth()->user()->id;
$model->approval_date = Carbon::now();
return $this->handler($model);
@@ -5,10 +5,7 @@ namespace App\Classes\Modules\Documents\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Models\Document;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
class RejectsDocument extends AbstractUpdateRecord
{
@@ -20,19 +17,8 @@ class RejectsDocument extends AbstractUpdateRecord
*/
public function execute(Document $model)
{
$user = Auth()->user();
// if auth user is null, then this services is calling from exchange
if (!$user) {
$token = explode('.', request()->bearerToken())[1];
$decodedToken = base64_decode($token);
$exchangeUser = json_decode($decodedToken, true)['user'];
$user = User::where('email', $exchangeUser['email'])->first();
if (!$user) {
$user = User::find(1);
}
}
$model->status = ApprovalStatus::REJECTED;
$model->approver = $user->id;
$model->approver = Auth()->user()->id;
$model->approval_date = Carbon::now();
return $this->handler($model);
@@ -2,19 +2,27 @@
namespace App\Classes\Modules\Exports\Services;
use App\Models\CompanyConnection;
use Maatwebsite\Excel\Concerns\FromQuery;
use Maatwebsite\Excel\Concerns\Exportable;
use Maatwebsite\Excel\Concerns\WithMapping;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use App\Classes\General\Eloquent\ApplyFiltersToQuery;
use App\Models\Company;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
class ExportsAllCustomersInfoForLarkSystem implements WithHeadings, WithHeadingRow, WithMapping, ShouldAutoSize, FromQuery
class ExportsAllCustomersInfoForLarkSystem implements FromQuery, WithMapping, WithHeadings, ShouldAutoSize
{
use Exportable;
public function __construct() {}
protected $deduplicateMarking;
protected $request;
public function __construct(Request $request, $deduplicateMarking = true)
{
$this->deduplicateMarking = $deduplicateMarking;
$this->request = $request;
}
public function headings(): array
{
@@ -25,33 +33,54 @@ class ExportsAllCustomersInfoForLarkSystem implements WithHeadings, WithHeadingR
'Email',
'Registration Date',
'Last Order Date',
'Debtor Code',
'Credit Term Customer',
'Custom Segments',
];
}
public function query()
{
return (new ApplyFiltersToQuery())->execute(Company::query(), [
'has_business_module_type' => 1,
$baseQuery = CompanyConnection::has('invitee.company');
if ($this->deduplicateMarking) {
$baseQuery->whereIn('id', function ($sub) {
$sub->selectRaw('min(id)')
->from('company_connections')
->groupBy('invitee_reference');
});
}
return $baseQuery->with([
'invitee.company.contacts',
'invitee.company.companyModules.employees',
'segments'
]);
}
public function map($company): array
public function map($connection): array
{
$company_module = $company->companyModules()->first();
$marking = $company_module->getMarking();
$employees = $company_module->employees()->first();
$company = optional(optional($connection)->invitee)->company;
$companyModule = optional($company)->companyModules->first();
$employee = optional($companyModule)->employees->first();
$contact = optional($company)->contacts->first();
$data = [
$marking = $connection->invitee_reference;
$creditTermCustomer = $connection->is_credit_term ? 'YES' : 'NO';
$employeeEmail = optional($employee)->email ?? '';
$contactPhone = optional($contact)->phone ?? '';
$segments = optional($connection->segments)->pluck('name')->implode(', ') ?: '';
return [
$marking,
$company->name,
$company->contacts()->first()->phone ?? '',
$employees?->email ?? '',
$company->created_at,
$company->updated_at,
$company_module->connections()->first()->segments()->pluck('name')->implode(', ')
optional($company)->name ?? '',
$contactPhone,
$employeeEmail,
optional($company)->created_at ? $company->created_at->toDateString() : '',
optional($company)->updated_at ? $company->updated_at->toDateString() : '',
optional($company)->debtor ?? '',
$creditTermCustomer,
$segments,
];
return $data;
}
}
@@ -51,7 +51,7 @@ class ExportsArrivedParcel implements WithHeadings, WithHeadingRow, WithMapping,
'transports'
])
->where('type', '=', 1)
->where('status', '=', 2)
// ->where('status', '=', 2)
->where('owner_type', Order::class)
->whereBetween('created_at', [Carbon::now()->subMonths(12), Carbon::now()]); //Limit, 'expensive' query
@@ -0,0 +1,105 @@
<?php
namespace App\Classes\Modules\Exports\Services;
use App\Classes\General\Helper;
use App\Classes\ValueObjects\Constants\AddressType;
use App\Classes\ValueObjects\Constants\DocumentType;
use App\Models\Company;
use Carbon\Carbon;
use Maatwebsite\Excel\Concerns\Exportable;
use Maatwebsite\Excel\Concerns\FromQuery;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
use Illuminate\Support\Facades\Log;
class ExportsCompanies implements FromQuery, WithHeadings, WithHeadingRow, WithMapping, ShouldAutoSize
{
use Exportable;
protected $startDate;
protected $endDate;
public function __construct($startDate = null, $endDate = null) {
$this->startDate = $startDate ? Carbon::parse($startDate)->startOfDay() : Carbon::now()->subMonths(1);
$this->endDate = $endDate ? Carbon::parse($endDate)->endOfDay() : Carbon::now();
}
public function headings(): array
{
return [
'TIN',
'IdentityNo',
'Name',
'IdentityType',
'TaxClassification',
'MSICCode',
'BusinessActivityDesc',
'DebtorCode',
'TradeName',
'Address',
'PostCode',
'Phone',
'EmailAddress',
'City',
'CountryCode',
'StateCode'
];
}
/**
* @return \Illuminate\Support\Collection|mixed
*/
public function query()
{
return Company::whereBetween('e_invoice_requested_at', [$this->startDate, $this->endDate]);
}
/**
* @param Company $company
*
* @return array
*/
public function map($company): array
{
$companyModule = $company->companyModules()->first();
$employee = $companyModule->employees()->first();
$identityNo = $company->documents->where('document_type', DocumentType::IDENTITY_CARD)->first();
$identityType = DocumentType::IDENTITY_CARD;
if(!$identityNo){
$identityNo = $company->documents->where('document_type', DocumentType::SSM_REGISTRATION)->first();
$identityType = DocumentType::SSM_REGISTRATION;
}
$identityReference = "";
if($identityNo){
$identityReference = preg_replace('/\s*\(.*?\)/', '', $identityNo->reference);
}
$address = $companyModule->addresses()->where('type', AddressType::E_INVOICE)->latest()->first();
if(!$address){
$address = $companyModule->addresses()->where('type', AddressType::BILLING)->first();
}
return [
$company->tin, // 'TIN',
$identityReference, // 'IdentityNo',
$company->name, // 'Name',
$identityType === DocumentType::IDENTITY_CARD ? 'MyKAD' : '', // 'IdentityType',
$company->type !== null ? (string) $company->type : '0', // 'TaxClassification',
$company->msic_code, // 'MSICCode',
$company->msic_code ? Helper::getLHDNMsicDescriptionByCode($company->msic_code) : '', // 'BusinessActivityDesc',
$company->debtor, // 'DebtorCode',
$company->name, // 'TradeName',
$address ? $address->street_one . ',' . $address->street_two : '',// 'Address',
$address ? $address->postcode : '', // 'PostCode',
$company->contacts()->first() ? $company->contacts()->first()->phone : '', // 'Phone',
$employee ? $employee->email : '', // 'EmailAddress',
$address ? $address->district()->first()->name : '', // 'City',
'MYS', // 'CountryCode',
$address ? Helper::getLHDNStateCodeByName($address->state()->first()->name) : '', // 'StateCode'
];
}
}
@@ -68,6 +68,8 @@ class ExportsNullDebtors implements FromQuery, WithHeadings, WithHeadingRow, Wit
public function map($company): array
{
$marking = $company->companyModules()->where('type', BusinessType::IMPORTER)->first()->inviters()->withPivot('invitee_reference')->first()->pivot->invitee_reference;
$companyModule = $company->companyModules()->first();
$employee = $companyModule->employees()->first();
return [
'<<New>>',
@@ -87,7 +89,7 @@ class ExportsNullDebtors implements FromQuery, WithHeadings, WithHeadingRow, Wit
'',
'',
'',
'',//EmailAddress
$employee->email,//EmailAddress
'',
'',
'',
@@ -0,0 +1,103 @@
<?php
namespace App\Classes\Modules\Exports\Services;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Models\Transaction;
use App\Models\Wallet;
use Maatwebsite\Excel\Concerns\Exportable;
use Maatwebsite\Excel\Concerns\FromQuery;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
class ExportsReceivePaymentDepositEntryReport implements FromQuery, WithHeadings, WithHeadingRow, WithMapping, ShouldAutoSize
{
use Exportable;
protected $startDate;
protected $endDate;
public function __construct($startDate = null, $endDate = null) {
$this->startDate = $startDate ? Carbon::parse($startDate)->startOfDay() : Carbon::now()->subMonths(1);
$this->endDate = $endDate ? Carbon::parse($endDate)->endOfDay() : Carbon::now();
}
public function headings(): array
{
return [
'DocNo',
'DocDate',
'DebtorCode',
'Description',
'DeptNo',
'DepositPaymentMethod',
'PaymentMethod',
'PaymentAmt',
];
}
/**
* @return \Illuminate\Support\Collection|mixed
*/
public function query()
{
$type = TransactionType::PAYMENT;
$query = Transaction::query();
// $query->where('owner_type', '!=', Wallet::class);
$query->where('type', $type);
$query->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]);
$query->whereBetween('created_at', [$this->startDate, $this->endDate]);
return $query;
}
/**
* @param Transaction $transaction
* @return array
*/
public function map($transaction): array
{
$formattedDocumentDate = Carbon::parse($transaction->created_at)->format('m/d/Y');
$order = null;
$owner = $transaction->owner;
if(!$owner) return[];
if($owner instanceof Wallet){
$company = $owner->owner->company;
}
else{
$order = $owner->owner->owner;
$company = $order->companyModule->company;
}
$paymentMethod = '';
if($transaction->payment_method == PaymentMethodType::WALLET){
$paymentMethod = 'WALLET DEPOSIT-IZYIM';
if($owner instanceof Transaction){
return[];
}
}
else{
$paymentMethod = 'MBB';
}
return [
'<<New>>', //DocNo
$formattedDocumentDate, //DocDate
$company ? $company->debtor : '', //DebtorCode
$order ? $order->reference : '', //Description
'C', //DeptNo
'SALES DEPOSIT - IZYI', //DepositPaymentMethod
$paymentMethod, //PaymentMethod
number_format($transaction->amount, 2), //PaymentAmt
];
}
}
@@ -0,0 +1,111 @@
<?php
namespace App\Classes\Modules\Exports\Services;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\KVPKey;
use App\Classes\ValueObjects\Constants\PaymentMethodType;
use App\Models\Transaction;
use App\Models\Wallet;
use Maatwebsite\Excel\Concerns\Exportable;
use Maatwebsite\Excel\Concerns\FromQuery;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
class ExportsReceivePaymentForOrderReport implements FromQuery, WithHeadings, WithHeadingRow, WithMapping, ShouldAutoSize
{
use Exportable;
protected $startDate;
protected $endDate;
public function __construct($startDate = null, $endDate = null) {
$this->startDate = $startDate ? Carbon::parse($startDate)->startOfDay() : Carbon::now()->subMonths(1);
$this->endDate = $endDate ? Carbon::parse($endDate)->endOfDay() : Carbon::now();
}
public function headings(): array
{
return [
'DocNo',
'Docdate',
'DebtorCode',
'Description',
'DeptNo',
'PaymentMethod',
'PaymentAmt',
'KnockOffDocType',
'KnockOffDocNo',
'KnockOffAmt',
];
}
/**
* @return \Illuminate\Support\Collection|mixed
*/
public function query()
{
$type = TransactionType::PAYMENT;
$query = Transaction::query();
// $query->where('owner_type', '!=', Wallet::class);
$query->where('type', $type);
$query->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]);
$query->whereBetween('created_at', [$this->startDate, $this->endDate]);
return $query;
}
/**
* @param Transaction $transaction
* @return array
*/
public function map($transaction): array
{
$autoCountSalesInvoiceId = null;
$formattedDocumentDate = Carbon::parse($transaction->created_at)->format('m/d/Y');
$order = null;
$invoice = null;
$owner = $transaction->owner;
if($owner instanceof Wallet){
$company = $owner->company;
}
else{
$invoice = $transaction->owner;
$order = $invoice->owner->owner;
$company = $order->companyModule->company;
}
if($invoice){
$metadata = $invoice->attributesKVP()->where('key', KVPKey::AUTOCOUNT_DOCNO_INVOICE)->first();
if($metadata){
$autoCountSalesInvoiceId = $metadata->value;
}
}
if($transaction->payment_method == PaymentMethodType::WALLET){
if($owner instanceof Wallet){
return[];
}
}
return [
'<<New>>', //DocNo
$formattedDocumentDate, //DocDate
$company ? $company->debtor : '', //DebtorCode
'Payment for ' . $autoCountSalesInvoiceId ?? '', //Description
'C', //DeptNo
'SALES DEPOSIT - IZYI', //PaymentMethod
number_format($transaction->amount, 2), //PaymentAmt
'RI', //KnockOffDocType
$autoCountSalesInvoiceId ?? '', //KnockOffDocNo
number_format($transaction->amount, 2), //KnockOffAmt
];
}
}
@@ -0,0 +1,210 @@
<?php
namespace App\Classes\Modules\Exports\Services;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\KVPKey;
use App\Models\Transaction;
use Maatwebsite\Excel\Concerns\Exportable;
use Maatwebsite\Excel\Concerns\FromQuery;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
class ExportsSalesInvoicesReport implements FromQuery, WithHeadings, WithHeadingRow, WithMapping, ShouldAutoSize
{
use Exportable;
protected $startDate;
protected $endDate;
protected $isUnpaid;
public function __construct($startDate = null, $endDate = null, $isUnpaid = false) {
$this->startDate = $startDate ? Carbon::parse($startDate)->startOfDay() : Carbon::now()->subMonths(1);
$this->endDate = $endDate ? Carbon::parse($endDate)->endOfDay() : Carbon::now();
$this->isUnpaid = $isUnpaid;
}
public function headings(): array
{
return [
'DocNo',
'DocDate',
'DebtorCode',
'Ref',
'ShipInfo',
'AccNo',
'DetailDescription',
'FurtherDescription',
'Classification',
'ProjNo',
'DeptNo',
'Qty',
'UnitPrice',
'TaxCode',
'TaxableAmt',
'TaxRate',
'SubmitEinvoice',
'ConsolidatedEInvoice',
// 'PaymentDate',
];
}
/**
* @return \Illuminate\Support\Collection|mixed
*/
public function query()
{
$start_date = $this->startDate;
$end_date = $this->endDate;
$query = Transaction::with([
'transactionDetails',
'transactions',
'attributesKVP',
'owner.containers',
'owner.owner.companyModule.company.contacts',
'owner.owner.companyModule.inviters',
'owner.owner.companyModule.employees'
]);
// if($this->isUnpaid){
// $approvalStatus = ApprovalStatus::COMPLETED;
// $query->whereIn('type', [TransactionType::SHIPPING_INVOICE, TransactionType::STORAGE_INVOICE])
// ->whereNotIn('status', [$approvalStatus])
// ->whereBetween('created_at', [$start_date, $end_date]);
// }
// else{
// $approvalStatus = ApprovalStatus::COMPLETED;
// $query->whereIn('type', [TransactionType::SHIPPING_INVOICE, TransactionType::STORAGE_INVOICE])
// ->where('status', $approvalStatus)
// ->whereBetween('created_at', [$start_date, $end_date]);
// $query->whereHas('transactions', function($transaction) {
// $transaction->where('type', TransactionType::PAYMENT)
// ->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]);
// });
// }
if($this->isUnpaid){
$approvalStatus = ApprovalStatus::COMPLETED;
$query->whereIn('type', [TransactionType::SHIPPING_INVOICE, TransactionType::STORAGE_INVOICE])
->whereNotIn('status', [$approvalStatus])
->whereBetween('created_at', [$start_date, $end_date]);
}
else{
//This will query everything both paid and unpaid unlike previously paid only
$query->whereIn('type', [TransactionType::SHIPPING_INVOICE, TransactionType::STORAGE_INVOICE])
->whereBetween('created_at', [$start_date, $end_date]);
}
return $query;
}
public function map($transaction): array
{
$container = $transaction->owner ? $transaction->owner->containers->first() : null;
$packingList = $transaction->owner;
if(!$packingList) return[];
$order = $packingList->owner;
$company = $order->companyModule->company;
// if(!$this->isUnpaid){
// $lastPaymentTransaction = $transaction->transactions
// ->whereIn('type', [TransactionType::PAYMENT, TransactionType::TOP_UP])
// ->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED])
// ->sortByDesc('created_at')
// ->first();
// $documentDate = Carbon::parse($lastPaymentTransaction->created_at);
// if($company->e_invoice === 1){
// $documentDate = $documentDate->copy()->endOfMonth();
// }
// $formattedDocumentDate = Carbon::parse($documentDate)->format('m/d/Y');
// }
$documentDate = Carbon::parse($transaction->created_at);
if($company->e_invoice === 1){
$documentDate = $documentDate->copy()->endOfMonth();
}
$formattedDocumentDate = Carbon::parse($documentDate)->format('m/d/Y');
// if($transaction->type === TransactionType::STORAGE_INVOICE){
// $shippingTransactionDetails = $transaction->transactionDetails->where('reference', 'STORAGE_FEE')->first();
// }
// else{
// $shippingTransactionDetails = $transaction->transactionDetails->where('reference', 'SHIPPING_FEE')->first();
// }
$marking = $order->companyModule->inviters()->withPivot('invitee_reference')->first()->pivot->invitee_reference;
// $contact = $order->companyModule->company->contacts->first();
// $userName = $order->companyModule->employees->first();
// $link = route('customer.payment-and-billing', $marking);
$furtherDescription = '';
foreach ($transaction->transactionDetails as $item){
if($item->reference === 'SHIPPING_FEE')
$furtherDescription .= str_replace('X1 Freight Service Charge<br>', '', $item->name)."\n";
elseif($item->reference === 'OVER_WEIGHT_CHARGES')
$furtherDescription .= $item->name.' '.$item->quantity.' CBM'."\n";
elseif($item->reference === 'MIN_CBM_CHARGES')
$furtherDescription .= $item->name.' '.$item->quantity.' CBM'."\n";
elseif($item->reference === 'STORAGE_FEE')
$furtherDescription .= str_replace('<br>', ' | ', $item->name).' '."\n";
else
$furtherDescription .= $item->name.' '.$item->quantity.' X '.$item->price."\n";
}
$transactionDetails = $transaction->transactionDetails;
$firstItem = true;
$docNo = '<<New>>';
$firstItem = true;
if($transaction){
$transactionKVP = $transaction->attributesKVP->where('key', KVPKey::AUTOCOUNT_DOCNO_INVOICE)->first();
if($transactionKVP){
$docNo = $transactionKVP->value;
}
}
$rows = [];
foreach ($transactionDetails as $detail) {
$rows[] = [
$firstItem ? $docNo : '', //DocNo
$formattedDocumentDate ?? '', //DocDate
$company->debtor, //DebtorCode
$transaction->bill_no, //Ref
$order->reference, //ShipInfo
'500-0000', //AccNo
'SERVICE OR ITEM :', //DetailDescription
str_replace('<br>', ' ', $detail->name), //FurtherDescription
'022', //Classification
$container->reference, //ProjNo
'C ', //DeptNo
$detail->quantity, //Qty
$detail->price, //UnitPrice
floatval($detail->tax_percentage) > 0 ? 'SV-6' : '', //TaxCode
floatval($detail->tax_percentage) > 0 ? number_format($detail->amount, 2) : '0.00', //TaxableAmt
$detail->tax_percentage, //TaxRate
$firstItem ? 'T' : '', //SubmitEinvoice
$company->e_invoice === 1 ? 'F' : 'T', //ConsolidatedEInvoice
// $transaction->transactions()->where('type', TransactionType::PAYMENT)->first()->updated_at->format('m/d/Y'), //PaymentDate
];
if($firstItem) {
$firstItem = false;
}
}
return $rows;
}
}
@@ -5,6 +5,7 @@ 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;
@@ -31,8 +32,10 @@ class ExportsWarehousePackingList implements FromQuery, WithHeadings, WithHeadin
*/
public function query()
{
return Order::whereHas('addresses', function($address) {
$address->where('status', ApprovalStatus::APPROVED);
$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');
});
@@ -0,0 +1,55 @@
<?php
namespace App\Classes\Modules\Imports\ControllersLogic;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject;
use App\Classes\Modules\Imports\Services\AutoCountDataImport;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Maatwebsite\Excel\Facades\Excel;
class ImportExcelLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Import Excel',
'message' => 'You have successfully imported data from excel file'
];
}
/**
* @param Request $request
* @return JsonResponse
* @throws MalformedRequestException
*/
public function logic(Request $request) : JsonResponse
{
$result = [];
$reportType = $request->input('report_type');
$object = new DocumentObject('', $request->input('files'), '', ApprovalStatus::APPROVED, 'imports');
$files = $object->getFiles();
if (count($files) > 1) {
throw new MalformedRequestException('Import function can only process one file at a time.');
}
foreach ($files as $file) {
$filePath = json_decode($file)->file_info->original->file;
$import = new AutoCountDataImport($reportType);
Excel::import($import, $filePath);
}
return $this->response($result);
}
}
@@ -0,0 +1,85 @@
<?php
namespace App\Classes\Modules\Imports\Services;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\ToCollection;
use Maatwebsite\Excel\Concerns\WithChunkReading;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Jobs\Commands\V2\ProcessSalesInvoiceReportV2CommandJob;
use App\Classes\Jobs\Commands\V2\ProcessPaymentReportV2CommandJob;
use Illuminate\Support\Facades\Log;
class AutoCountDataImport implements ToCollection, WithHeadingRow, WithChunkReading
{
protected $reportType;
public function __construct($reportType)
{
$this->reportType = $reportType;
}
public function headingRow(): int
{
return 1;
}
/**
* @param Collection $collection
*/
public function collection(Collection $collection)
{
static $headerProcessed = false;
foreach ($collection as $row) {
if (!$headerProcessed) {
$header = $row->keys()->map(fn($h) => strtolower(trim($h)))->toArray();
$this->validateHeader($header, $this->reportType);
$headerProcessed = true;
}
if ($this->reportType === 'Sales Invoice Report') {
ProcessSalesInvoiceReportV2CommandJob::dispatch($row->toArray());
}
elseif ($this->reportType === '11R - RECEIVE PAYMENT (FULL PAYMENT) [AR RECEIVE PAYMENT]') {
ProcessPaymentReportV2CommandJob::dispatch($row->toArray());
}
else{
throw new MalformedRequestException('Cannot process report type: ' . $this->reportType);
}
}
}
public function chunkSize(): int
{
return 1000;
}
private function validateHeader(array $header, String $reportType)
{
$optionalColumn = 'einvoicevalidationlink';
$salesInvoiceHeader =
['docno', 'docdate', 'debtorcode', 'ref',
'shipinfo', 'accno', 'detaildescription', 'furtherdescription', 'classification', 'projno', 'deptno',
'qty', 'unitprice', 'taxcode', 'taxableamt', 'taxrate', 'submiteinvoice', 'consolidatedeinvoice'];
$paymentReportHeader = [
'docno',
'docdate',
'debtorcode',
'description',
'paymentmethod',
'paymentamt',
'knockoffdocno'
];
if ($reportType === 'Sales Invoice Report' &&
$header !== $salesInvoiceHeader &&
$header !== [...$salesInvoiceHeader, $optionalColumn]) {
throw new MalformedRequestException('Uploaded Excel file format is incorrect. Column headers do not match expected format.');
}
elseif ($reportType === '11R - RECEIVE PAYMENT (FULL PAYMENT) [AR RECEIVE PAYMENT]' && $header !== $paymentReportHeader) {
throw new MalformedRequestException('Uploaded Excel file format is incorrect. Column headers do not match expected format.');
}
}
}
@@ -6,7 +6,6 @@ use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Orders\Processors\ApproveChangeOrderAddressProcessor;
use App\Http\Resources\AddressResource;
use App\Http\Resources\OrderResource;
use App\Transformers\AddressTransformer;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
@@ -40,12 +39,6 @@ class ApproveChangeOrderAddressLogic extends AbstractControllerLogic
{
$address = $this->approveChangeOrderAddressProcessor->execute($request);
//load address with no relationships
/* return fractal()
->item($address, new AddressTransformer())
->respond(200, [], JSON_PRETTY_PRINT);*/
return $this->resourceResponse(new AddressResource($address));
}
}
@@ -0,0 +1,85 @@
<?php
namespace App\Classes\Modules\Orders\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Jobs\Commands\V2\ProcessTransactionForEInvoiceV2CommandJob;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Transaction;
use Carbon\Carbon;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Facades\Log;
class CreateBatchProcessingAutoCountImportLogic extends AbstractControllerLogic
{
protected int $processedCount = 0;
/**
* @return array
*/
protected function notification(): array
{
return [
'title' => 'Generate E-Invoices',
'message' => sprintf(
'You have successfully submitted %d transaction%s for E-Invoices processing.',
$this->processedCount,
$this->processedCount === 1 ? '' : 's'
),
];
}
/**
* @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
{
$validated = $request->validate([
'startDate' => 'nullable|date_format:d-m-Y',
'endDate' => 'nullable|date_format:d-m-Y|after_or_equal:startDate',
]);
$startDate = null;
$endDate = null;
$startDate = isset($validated['startDate']) && $validated['startDate']
? Carbon::createFromFormat('d-m-Y', $validated['startDate'])->startOfDay()
: Carbon::now()->startOfMonth()->startOfDay();
$endDate = isset($validated['endDate']) && $validated['endDate']
? Carbon::createFromFormat('d-m-Y', $validated['endDate'])->endOfDay()
: Carbon::now()->endOfMonth()->endOfDay();
$query = Transaction::query();
$query->whereIn('type', [TransactionType::SHIPPING_INVOICE, TransactionType::STORAGE_INVOICE])
->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]);
// $transactions = $query->whereHas('transactions', function($transaction) use ($startDate, $endDate) {
// $transaction->where('type', TransactionType::PAYMENT)
// ->whereBetween('updated_at', [$startDate, $endDate])
// ->whereIn('status', [ApprovalStatus::APPROVED, ApprovalStatus::COMPLETED]);
// })->get();
$transactions = $query->whereBetween('created_at', [$startDate, $endDate])->get();
$count = 0;
foreach ($transactions as $transaction) {
ProcessTransactionForEInvoiceV2CommandJob::dispatch($transaction);
// $count = $count + 1;
// if($count > 15){
// break;
// }
}
$this->processedCount = count($transactions);
return $this->resourceResponse(JsonResource::collection(collect([])));
}
}
@@ -4,25 +4,14 @@ namespace App\Classes\Modules\Orders\ControllersLogic;
use App\Classes\Exceptions\RequestValidationException;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Addresses\DataTransferObjects\AddressObject;
use App\Classes\Modules\Addresses\Services\CreatesAddress;
use App\Classes\Modules\Accounts\DataTransferObjects\KeyValuePairObject;
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\Orders\Processors\ConnectOrderToExchangeBookingOnExchangeProcessor;
use App\Classes\Modules\PerfexCRM\Processors\NewLeadTaskToPerfexCRMProcessor;
use App\Classes\Modules\Orders\Processors\CreateOrderProcessor;
use App\Classes\Modules\Orders\Services\ConnectOrderToExchangeBooking;
use App\Classes\Modules\Orders\Services\GeneratesOrderNumber;
use App\Classes\ValueObjects\Constants\AddressType;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\Modules\Addresses\Standards\Rules\CanCreateAddress;
use App\Models\Address;
use App\Classes\Modules\Accounts\Services\CreatesKeyValuePair;
use App\Classes\ValueObjects\Constants\WarehouseReferences;
use App\Http\Resources\OrderResource;
use App\Models\Order;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
@@ -52,25 +41,8 @@ class CreateOrderLogic extends AbstractControllerLogic
/** @var GeneratesOrderNumber */
private $generatesOrderNumber;
/** @var CreatesAddress */
private $createsAddress;
/** @var CanCreateAddress */
private $canCreateAddress;
/** @var NewLeadTaskToPerfexCRMProcessor */
private $newLeadTaskToPerfexCRMProcessor;
/** @var ConnectOrderToExchangeBooking */
private $connectOrderToExchangeBooking;
/** @var ConnectOrderToExchangeBookingOnExchangeProcessor */
private $connectOrderToExchangeBookingOnExchangeProcessor;
/** @var CreatesKeyValuePair */
private $createsKeyValuePair;
/**
* CreateOrderLogic constructor.
* @param FetchesCompany $fetchesCompany
@@ -79,10 +51,8 @@ class CreateOrderLogic extends AbstractControllerLogic
* @param FetchesCompanyModule $fetchesCompanyModule
* @param GeneratesOrderNumber $generatesOrderNumber
* @param NewLeadTaskToPerfexCRMProcessor $newLeadTaskToPerfexCRMProcessor
* @param ConnectOrderToExchangeBooking $connectOrderToExchangeBooking
* @param ConnectOrderToExchangeBookingOnExchangeProcessor $connectOrderToExchangeBookingOnExchangeProcessor
*/
public function __construct(FetchesCompany $fetchesCompany, FetchesAddress $fetchesAddress, CreateOrderProcessor $createOrderProcessor, FetchesCompanyModule $fetchesCompanyModule, GeneratesOrderNumber $generatesOrderNumber, NewLeadTaskToPerfexCRMProcessor $newLeadTaskToPerfexCRMProcessor, ConnectOrderToExchangeBooking $connectOrderToExchangeBooking, ConnectOrderToExchangeBookingOnExchangeProcessor $connectOrderToExchangeBookingOnExchangeProcessor, CreatesKeyValuePair $createsKeyValuePair)
public function __construct(FetchesCompany $fetchesCompany, FetchesAddress $fetchesAddress, CreateOrderProcessor $createOrderProcessor, FetchesCompanyModule $fetchesCompanyModule, GeneratesOrderNumber $generatesOrderNumber, NewLeadTaskToPerfexCRMProcessor $newLeadTaskToPerfexCRMProcessor)
{
$this->fetchesCompany = $fetchesCompany;
$this->fetchesAddress = $fetchesAddress;
@@ -90,18 +60,12 @@ class CreateOrderLogic extends AbstractControllerLogic
$this->fetchesCompanyModule = $fetchesCompanyModule;
$this->generatesOrderNumber = $generatesOrderNumber;
$this->newLeadTaskToPerfexCRMProcessor = $newLeadTaskToPerfexCRMProcessor;
$this->connectOrderToExchangeBooking = $connectOrderToExchangeBooking;
$this->connectOrderToExchangeBookingOnExchangeProcessor = $connectOrderToExchangeBookingOnExchangeProcessor;
$this->createsKeyValuePair = $createsKeyValuePair;
}
public function logic(Request $request): JsonResponse
{
$isTermsAgreed = $request->input('is_terms_agree');
if(!$isTermsAgreed){
throw new RequestValidationException('You must read and agree to our terms and conditions to proceed');
}
$company = $this->fetchesCompany->execute(['id' => $request->input('company_id')]);
@@ -127,32 +91,12 @@ class CreateOrderLogic extends AbstractControllerLogic
throw new RequestValidationException('Our Yiwu warehouse is unable to ship goods to Sabah & Sarawak at the moment. you can select our Guangzhou warehouse as an alternative.');
}
/** @var Order $order */
$order = $this->createOrderProcessor->execute($company, $originWarehouse, $address, $this->generatesOrderNumber->execute());
$keyValuePairObject = new KeyValuePairObject(
"TERMS_AND_CONDITIONS",
$isTermsAgreed
);
$this->createsKeyValuePair->execute($order, $keyValuePairObject);
if(config('perfexcrm.is_enabled') == 'true'){
$this->newLeadTaskToPerfexCRMProcessor->execute($company);
}
$token = explode('.', $request->bearerToken())[1];
$decodedToken = base64_decode($token);
$exchangeUser = json_decode($decodedToken, true)['user'];
$exchangeBookingId = null;
if (isset($exchangeUser['exchange_booking_id']) && $exchangeUser['exchange_booking_id']) {
$exchangeBookingId = $exchangeUser['exchange_booking_id'];
}
if ($exchangeBookingId) {
$this->connectOrderToExchangeBooking->execute($order, $exchangeBookingId);
$this->connectOrderToExchangeBookingOnExchangeProcessor->execute($request, $order->id, $exchangeBookingId);
}
return $this->resourceResponse(new OrderResource($order));
}
}
@@ -6,13 +6,13 @@ namespace App\Classes\Modules\Orders\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Orders\Services\FetchesOrder;
use App\Classes\Modules\Orders\Standards\Rules\CanFetchOrder;
use App\Http\Resources\OrderPackagesBaseResource;
use App\Http\Resources\OrderPackagesDeprecatedResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
/**
* @deprecated This class is deprecated and should not be used.
* Use `FetchOrderPackagesV2Logic` instead or write a new one based on FetchOrderPackagesV2Logic
* Use `FetchOrderPackagesReceivedV2Logic` instead or write a new one based on FetchOrderPackagesReceivedV2Logic
*/
class FetchOrderPackagesLogic extends AbstractControllerLogic
{
@@ -74,7 +74,7 @@ class FetchOrderPackagesLogic extends AbstractControllerLogic
$query->include_packages_received = $filters['include_packages_received'];
}
return $this->resourceResponse(new OrderPackagesBaseResource($query));
return $this->resourceResponse(new OrderPackagesDeprecatedResource($query));
}
@@ -0,0 +1,59 @@
<?php
namespace App\Classes\Modules\Orders\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Orders\Services\FetchesOrder;
use App\Classes\Modules\Orders\Standards\Rules\CanFetchOrder;
use App\Http\Resources\OrderPackagesReceivedResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class FetchOrderPackagesReceivedV2Logic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Retrieved Order Packages Received',
'message' => 'You have successfully retrieved an order packages'
];
}
/** @var CanFetchOrder */
private $canFetchOrder;
/** @var FetchesOrder */
private $fetchesOrder;
/**
* FetchOrderPackagesReceivedV2Logic constructor.
* @param CanFetchOrder $canFetchOrder
* @param FetchesOrder $fetchesOrder
*/
public function __construct(CanFetchOrder $canFetchOrder, FetchesOrder $fetchesOrder)
{
$this->canFetchOrder = $canFetchOrder;
$this->fetchesOrder = $fetchesOrder;
}
/**
* @param Request $request
* @return JsonResponse
* @throws \App\Classes\Exceptions\AccessForbiddenException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
public function logic(Request $request) : JsonResponse
{
$this->canFetchOrder->passes();
$query = $this->fetchesOrder->execute(['reference' => $request->route('id'), 'with_packing_lists' => true]);
//Can refer FetchOrderPackagesLogic for different type of OrderPackages Resources
return $this->resourceResponse(new OrderPackagesReceivedResource($query));
}
}
@@ -6,10 +6,11 @@ namespace App\Classes\Modules\Orders\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Orders\Services\FetchesOrder;
use App\Classes\Modules\Orders\Standards\Rules\CanFetchOrder;
use App\Http\Resources\OrderPackagesReceivedResource;
use App\Http\Resources\OrderPackagesResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class FetchOrderPackagesV2Logic extends AbstractControllerLogic
{
@@ -49,11 +50,7 @@ class FetchOrderPackagesV2Logic extends AbstractControllerLogic
public function logic(Request $request) : JsonResponse
{
$this->canFetchOrder->passes();
$query = $this->fetchesOrder->execute(['reference' => $request->route('id'), 'with_packing_lists' => true]);
//Can refer FetchOrderPackagesLogic for different type of OrderPackages Resources
return $this->resourceResponse(new OrderPackagesReceivedResource($query));
return $this->resourceResponse(new OrderPackagesResource($query));
}
}
@@ -6,7 +6,7 @@ namespace App\Classes\Modules\Orders\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Orders\Services\FetchesOrder;
use App\Classes\Modules\Orders\Standards\Rules\CanFetchOrder;
use App\Http\Resources\OrderV2Resource;
use App\Http\Resources\FetchOrderResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -48,7 +48,6 @@ class FetchOrderV2Logic extends AbstractControllerLogic
*/
public function logic(Request $request) : JsonResponse
{
$this->canFetchOrder->passes();
$query = $this->fetchesOrder->execute(['reference' => $request->route('id'), 'with_packing_lists' => true]);
@@ -56,9 +55,6 @@ class FetchOrderV2Logic extends AbstractControllerLogic
if($request->input('storages')){
$query->storages = $request->input('storages'); //from middleware
}
return $this->resourceResponse(new OrderV2Resource($query));
return $this->resourceResponse(new FetchOrderResource($query));
}
}
@@ -8,7 +8,6 @@ use App\Classes\Modules\Orders\Services\ListsOrders;
use App\Classes\Modules\Orders\Standards\Rules\CanListOrders;
use App\Classes\ValueObjects\Constants\OrderType;
use App\Http\Resources\OrderBaseResource;
use App\Http\Resources\OrderV2Resource;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -65,9 +64,5 @@ class ListOrdersV2Logic extends AbstractControllerLogic
}
return $this->collectionResponse(OrderBaseResource::collection($query));
//return $this->collectionResponse(OrderV2Resource::collection($query));
}
}
@@ -1,48 +0,0 @@
<?php
namespace App\Classes\Modules\Orders\Processors;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Log;
class ConnectOrderToExchangeBookingOnExchangeProcessor
{
/**
* @param Request $request
* @return string
* @throws \App\Classes\Exceptions\AccessForbiddenException
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
public function execute(Request $request, $orderId, $exchangeBookingId) {
if (App::environment(['production'])) {
dd("Delete this line before push to production");
$url = "https://exchange.cief-malaysia.com/api/v1/shipping/order/{$orderId}/booking/{$exchangeBookingId}/connect";
} else if (App::environment(['local'])) {
$url = "http://127.0.0.1:8000/api/v1/shipping/order/{$orderId}/booking/{$exchangeBookingId}/connect";
} else {
$url = "https://dev.exchange.cief-malaysia.com/api/v1/shipping/order/{$orderId}/booking/{$exchangeBookingId}/connect";
}
try {
$client = new \GuzzleHttp\Client(['verify' => false]);
$token = $request->bearerToken();
$headers = [
'Authorization' => 'Bearer ' . $token,
'Accept' => 'application/json',
];
$formParams = $request->toArray();
$response = $client->request('POST', $url, [
'headers' => $headers,
'form_params' => $formParams
]);
$body = $response->getBody();
$contents = json_decode($body, true);
return $contents;
} catch(\GuzzleHttp\Exception\RequestException $exception){
Log::error($exception->getResponse()->getBody()->getContents());
}
}
}
@@ -67,7 +67,7 @@ class CreateOrderProcessor
* @param CompanyModule $originWarehouse
* @param Address $address
* @param int|null $orderNumber
* @return Order
* @return Addressable
* @throws \App\Classes\Exceptions\AccessForbiddenException
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws \App\Classes\Exceptions\RequestValidationException
@@ -1,25 +0,0 @@
<?php
namespace App\Classes\Modules\Orders\Services;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Models\ExchangeBookingOrder;
use App\Models\Order;
class ConnectOrderToExchangeBooking extends AbstractUpdateRecord
{
/**
* @param Order $order
* @return \Illuminate\Database\Eloquent\Model
* @throws MalformedRequestException
*/
public function execute(Order $order, $exchangeBookingId)
{
$model = new ExchangeBookingOrder();
$model->order_id = $order->id;
$model->exchange_booking_id = $exchangeBookingId;
return $this->handler($model);
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\PackingLists\ControllersLogic;
use App\Classes\Exceptions\ResourceNotFoundException;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Jobs\Commands\V2\YD\FetchPackingListsFromYdPortalV2CommandJob;
use App\Classes\Modules\PackingLists\Services\FetchesPackingList;
use App\Classes\Modules\Orders\Services\FetchesOrder;
@@ -23,9 +24,11 @@ use App\Classes\ValueObjects\Constants\OrderRoleTypes;
use App\Classes\Modules\Steps\DataTransferObjects\StepsObject;
use App\Http\Resources\PackingListResource;
use Carbon\Carbon;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
class AssignPackingListOrderLogic extends AbstractControllerLogic
{
@@ -162,7 +165,43 @@ class AssignPackingListOrderLogic extends AbstractControllerLogic
}
// Update Packing Lists' packages info,
// Important for markup 'No Extra Centimeter Charged' reevaluation as a result of packing list is now 'Claimed' to an order (before this was Unclaimed Packing Lists)
// See CreatePackageProcessor.php
$jobs1 = $this->fetchPackingListsFromYdPortalV2CommandJobs();
foreach ($jobs1 as $index => $job) {
dispatch($job)->delay(now()->addSeconds($index * 2));
}
return $this->resourceResponse(new PackingListResource($warehouse_packing_list));
}
private function fetchPackingListsFromYdPortalV2CommandJobs(){
$jobs = [];
$from = 0;
$to = 10;
$count = 0;
for ($x = $from; $x <= $to; $x++) {
$startDate = Carbon::today()->subDays($x);
$startLimit = Carbon::parse('01-12-2021');
if($startDate->isBefore($startLimit)){
$startDate = $startLimit;
}
$endDate = Carbon::today()->subDays($x - 1);
$jobs[] = new FetchPackingListsFromYdPortalV2CommandJob($startDate, $endDate);
Log::info('(AssignPackingListOrderLogic) Dispatched FetchPackingListsFromYdPortalV2CommandJob for start date: ' . $startDate . ', end date: ' . $endDate);
$count++;
}
Log::info('(AssignPackingListOrderLogic) Total FetchPackingListsFromYdPortalV2CommandJob dispatched: ' . $count);
return $jobs;
}
}
@@ -6,7 +6,6 @@ use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\PackingLists\Services\Containers\FetchesContainer;
use App\Classes\Modules\PackingLists\Services\FetchesPackingList;
use App\Http\Resources\ContainerResource;
use App\Transformers\ContainerTransformer;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -54,16 +53,9 @@ class AssignPackingListContainerLogic extends AbstractControllerLogic
foreach ($packing_list as $key => $row) {
$packing_list_item = $this->fetchesPackingList->execute(['id' => $row]);
$container->packingLists()->attach($packing_list_item, ['created_at' => now(), 'updated_at' => now()]);
$container->packingLists()->attach($packing_list_item);
}
//only return with packing list relationship
/* return fractal()
->item($container, new ContainerTransformer())
->parseInclude(['packingLists'])
->respond(200, [], JSON_PRETTY_PRINT);*/
return $this->resourceResponse(new ContainerResource($container));
} catch (\Exception $exception){
@@ -8,7 +8,6 @@ use App\Classes\Modules\PackingLists\Services\Containers\FetchesContainer;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Http\Resources\ContainerResource;
use App\Transformers\ContainerTransformer;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -20,8 +19,7 @@ class CompleteContainerLogic extends AbstractControllerLogic
/**
* @return array
*/
protected function notification(): array
{
protected function notification():array {
return [
'title' => 'Updated Container',
'message' => 'You have successfully updated the Container'
@@ -53,16 +51,10 @@ class CompleteContainerLogic extends AbstractControllerLogic
* @return JsonResponse
* @throws ErrorException
*/
public function logic(Request $request): JsonResponse
public function logic(Request $request) : JsonResponse
{
$container = $this->fetchesContainer->execute(['id' => $request->route('id')]);
$query = $this->updatesContainerStatus->execute($container, ApprovalStatus::COMPLETED);
//no relationships needed
/* return fractal()
->item($container, new ContainerTransformer())
->respond(200, [], JSON_PRETTY_PRINT);*/
return $this->resourceResponse(new ContainerResource($container));
}
@@ -11,7 +11,6 @@ use App\Classes\Modules\PackingLists\DataTransferObjects\ContainerObject;
use App\Classes\Modules\PackingLists\Services\FetchesPackingList;
use App\Http\Resources\ContainerResource;
use App\Transformers\ContainerTransformer;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -71,11 +70,6 @@ class CreateContainerLogic extends AbstractControllerLogic
$query = $this->createsContainer->execute($object, $this->fetchesCompanyModule->execute(['id' => $request->input('company_module_id')]));
//no relationship needed
/* return fractal()
->item($query, new ContainerTransformer())
->respond(200, [], JSON_PRETTY_PRINT);*/
return $this->resourceResponse(new ContainerResource($query));
}
@@ -8,7 +8,6 @@ use App\Classes\Modules\PackingLists\Services\Containers\FetchesContainer;
use App\Classes\Modules\Remarks\DataTransferObjects\RemarkObject;
use App\Classes\Modules\Remarks\Processors\CreateRemarkProcessor;
use App\Http\Resources\ContainerResource;
use App\Transformers\ContainerTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -19,8 +18,7 @@ class CreateContainerRemarkLogic extends AbstractControllerLogic
/**
* @return array
*/
protected function notification(): array
{
protected function notification():array {
return [
'title' => 'Created Container Remark',
'message' => 'You have successfully created a new Container Remark'
@@ -52,7 +50,7 @@ class CreateContainerRemarkLogic extends AbstractControllerLogic
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
public function logic(Request $request): JsonResponse
public function logic(Request $request) : JsonResponse
{
$container = $this->fetchesContainer->execute(['id' => $request->route('id')]);
@@ -61,12 +59,6 @@ class CreateContainerRemarkLogic extends AbstractControllerLogic
$this->createRemarkProcessor->execute($container, $object);
//load with remarks only
/* return fractal()
->item($container, new ContainerTransformer())
->parseIncludes(['remarks'])
->respond(200, [], JSON_PRETTY_PRINT);*/
return $this->resourceResponse(new ContainerResource($container));
}
@@ -17,7 +17,6 @@ use App\Classes\ValueObjects\Constants\TransportType;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Http\Resources\ContainerResource;
use App\Transformers\ContainerTransformer;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -29,8 +28,7 @@ class CreateLoadContainerLogic extends AbstractControllerLogic
/**
* @return array
*/
protected function notification(): array
{
protected function notification():array {
return [
'title' => 'Created Container',
'message' => 'You have successfully created a new Container'
@@ -43,7 +41,7 @@ class CreateLoadContainerLogic extends AbstractControllerLogic
/** @var FetchesPackingList */
private $fetchesPackingList;
/** @var FetchesCompanyModule */
/** @var FetchesCompanyModule */
private $fetchesCompanyModule;
/** @var CreatesPackingList */
@@ -56,12 +54,12 @@ class CreateLoadContainerLogic extends AbstractControllerLogic
private $createsSchedule;
public function __construct(
CanCreateContainer $canCreateContainer,
FetchesPackingList $fetchesPackingList,
FetchesCompanyModule $fetchesCompanyModule,
CreatesContainer $createsContainer,
CreatesTransport $createsTransport,
CreatesSchedule $createsSchedule
CanCreateContainer $canCreateContainer,
FetchesPackingList $fetchesPackingList,
FetchesCompanyModule $fetchesCompanyModule,
CreatesContainer $createsContainer,
CreatesTransport $createsTransport,
CreatesSchedule $createsSchedule
)
{
$this->canCreateContainer = $canCreateContainer;
@@ -79,11 +77,11 @@ class CreateLoadContainerLogic extends AbstractControllerLogic
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
public function logic(Request $request): JsonResponse
public function logic(Request $request) : JsonResponse
{
$object = new ContainerObject(
$request->input('container_reference'),
$request->input('container_number'),
$request->input('container_reference'),
$request->input('container_number'),
$request->input('seal_reference'),
$request->input('container_type'),
ApprovalStatus::APPROVED
@@ -94,27 +92,21 @@ class CreateLoadContainerLogic extends AbstractControllerLogic
$container = $this->createsContainer->execute($object, $this->fetchesCompanyModule->execute(['id' => $request->input('company_module_id')]));
$transportObject = new TransportObject(
TransportType::LAND, null,
$request->input('tracking'),
Carbon::parse($request->input('etd')),
Carbon::parse($request->input('eta')),
TransportType::LAND, null,
$request->input('tracking'),
Carbon::parse($request->input('etd')),
Carbon::parse($request->input('eta')),
ApprovalStatus::APPROVED
);
$transport = $this->createsTransport->execute($transportObject, $container);
$scheduleObject = new ScheduleObject(
Carbon::parse($request->input('etd')),
Carbon::parse($request->input('etd')),
Carbon::parse($request->input('eta')),
ApprovalStatus::APPROVED
);
);
$schedule = $this->createsSchedule->execute($transport, $scheduleObject);
//include transport
/* return fractal()
->item($container, new ContainerTransformer())
->parseIncludes(['transport'])
->respond(200, [], JSON_PRETTY_PRINT);*/
return $this->resourceResponse(new ContainerResource($container));
}
@@ -17,8 +17,7 @@ class FetchContainerLogic extends AbstractControllerLogic
/**
* @return array
*/
protected function notification(): array
{
protected function notification():array {
return [
'title' => 'Retrieved Container',
'message' => 'You have successfully retrieved a Container'
@@ -49,19 +48,12 @@ class FetchContainerLogic extends AbstractControllerLogic
* @throws \App\Classes\Exceptions\AccessForbiddenException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
public function logic(Request $request): JsonResponse
public function logic(Request $request) : JsonResponse
{
$this->canFetchContainer->passes();
$query = $this->fetchesContainer->execute(['id' => $request->route('id'), 'with_packing_lists' => true]);
//load with packing lists
/* return fractal()
->item($query, new ContainerTransformer())
->parseIncludes(['packing_lists'])
->respond(200, [], JSON_PRETTY_PRINT);*/
// return $this->resourceResponse(new ContainerResource($query));
return $this->resourceResponse(new ContainerBaseResource($query));
}

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