Compare commits

...

433 Commits

Author SHA1 Message Date
Dillon Ngo 68c5208316 Update: Vue 2 to Vue 3 with Typescript, node 14 to node 22, Jenkinsfile, Dockerfile, vapor.yml 2026-05-27 20:35:19 +08:00
Dillon Ngo 5ca007ab28 Fix YD API integration issue reported by Zhy Mei 2026-05-26 22:50:54 +08:00
Dillon Ngo f190997634 Show reference info on order page > Received Parcels section requested by Kanisha 2026-05-13 11:09:34 +08:00
Dillon Ngo 5dd8a70677 Fix a 504 Endpoint request timed out error at customer payment-and-billing page with storage invoice 2026-05-01 12:07:33 +08:00
Dillon Ngo 9dbb6a8b49 Fix a 504 Endpoint request timed out error at customer payment-and-billing page with storage invoice 2026-05-01 11:49:31 +08:00
Dillon Ngo 812da07f63 Fix a 504 Endpoint request timed out error at customer payment-and-billing page with storage invoice 2026-05-01 10:34:25 +08:00
Dillon Ngo 130aa78dfe Fix a 504 Endpoint request timed out error at customer payment-and-billing page with storage invoice 2026-05-01 10:13:38 +08:00
Dillon Ngo f820ba578f Fx to resolve a 504 Endpoint request timed out error on loading packages details on order page 2026-04-24 17:48:41 +08:00
Dillon Ngo 961f8acf65 Fx to resolve a 504 Endpoint request timed out error on loading packages details on order page 2026-04-24 15:53:58 +08:00
Dillon Ngo 9a2a5d797c Fx to resolve a 504 Endpoint request timed out error on loading packages details on order page 2026-04-24 15:38:22 +08:00
Dillon Ngo 743662af9e Temporary undo a previous fix to resolve a 504 Endpoint request timed out error 2026-04-24 10:26:57 +08:00
Dillon Ngo 1ba98379bf Temporary fix some yd integration api not showing reported by Zhy Mei 2026-04-14 23:07:50 +08:00
Dillon Ngo 0f18556667 Temporary fix some yd integration api not showing reported by Zhy Mei 2026-04-14 22:49:49 +08:00
Dillon Ngo 27b4dee1e3 Fix Jenkins Deployment issue 2026-04-10 13:08:44 +08:00
Dillon Ngo 3e982f5351 Fix missing E-Invoice no. in invoices's pdf summary 2026-04-10 13:00:08 +08:00
Dillon Ngo b17fe23652 Fix missing E-Invoice no. in invoices's pdf summary 2026-04-10 12:30:04 +08:00
Dillon Ngo 191bd161f3 Fix missing E-Invoice no. in invoices's pdf summary 2026-04-10 12:17:27 +08:00
Dillon Ngo 6b8a61877e Fix missing E-Invoice no. in invoices's pdf summary 2026-04-10 11:37:36 +08:00
Dillon Ngo 9730fa79e4 Fix missing E-Invoice no. in invoices's pdf summary 2026-04-10 11:22:48 +08:00
Dillon Ngo 009c064002 Fix missing E-Invoice no. in invoices's pdf summary 2026-04-10 11:11:40 +08:00
Dillon Ngo 6be228e7fd Fix missing E-Invoice no. in invoices's pdf summary 2026-04-10 10:11:19 +08:00
Dillon Ngo fd52aa6b01 Fix missing E-Invoice no. in invoices's pdf summary 2026-04-10 09:50:22 +08:00
Dillon Ngo de4c09fb07 Update tests 2026-04-06 11:26:16 +08:00
Dillon Ngo adb81ebfe9 Minor UI update 2026-03-26 11:04:45 +08:00
Dillon Ngo 8d11ff6b7f Update: laravel 8 to 12, php 7.3 to php 8.3, Jenkinsfile, Unit/Feature testing, vapor 2026-03-25 07:51:49 +08:00
Dillon Ngo 76cc4296a3 Minor UI update 2026-03-19 01:56:23 +08:00
Dillon Ngo 90f485f84b Update to use cheaper claude model 2026-03-18 09:27:34 +08:00
Dillon Ngo 1cc3581800 Enhancement to allow admin to delete package safely with immediate pull again from YD api 2026-03-17 16:30:33 +08:00
Dillon Ngo 7dfa7b0220 Update Jenkinsfile 2026-03-16 22:52:12 +08:00
Dillon Ngo 27204bca13 Emergency fix invoice transaction details inaccurate 2026-03-16 22:28:59 +08:00
Edmond Lang b735462321 rename qr warehouse prefix 2026-03-10 15:31:07 +08:00
Dillon Ngo 8b2ef2acd4 FIx an issue reported by Eileen, a customer payment and billing page not loading 2026-03-07 00:46:09 +08:00
Dillon Ngo f5f278fb77 Merge branch 'dillon/138-fix-generate-summary-invoice-issue' into vapor/production 2026-02-23 03:22:58 +08:00
Dillon Ngo 8afa6a496e Minor update on UX 2026-02-23 03:22:47 +08:00
Dillon Ngo 03a7ed5785 Added missing environment variable into .env.example 2026-02-18 23:06:18 +08:00
Dillon Ngo efe5ccecea Fix a problem reported by Joanne about group payment invoices not appearing properly 2026-02-12 16:05:33 +08:00
Dillon Ngo 7faeec6ef7 Fix a problem reported by Joanne about group payment invoices not appearing properly 2026-02-12 15:44:05 +08:00
Dillon Ngo 20e7e19bc6 Merge branch 'dillon/138-fix-generate-summary-invoice-issue' into vapor/production 2026-02-06 15:56:56 +08:00
Dillon Ngo 151447c573 Emergency DB issue Restore 2026-02-06 15:53:59 +08:00
Dillon Ngo a21614ba32 Emergency DB issue Restore 2026-02-06 15:32:21 +08:00
Dillon Ngo d99cb103ce Fix an issue reported by Eileen not able to generate summary invoice for multiple pending payment shipping invoices 2026-02-06 14:32:44 +08:00
Dillon Ngo 4c92ac5a83 Fix an issue reported by Eileen not able to generate summary invoice for multiple pending payment shipping invoices 2026-02-06 14:30:07 +08:00
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
Edmond Lang d6cfd85aa2 add /export/all-customers-info-for-lark-system 2025-06-12 22:18:53 +08:00
Dillon Ngo 844527417a Quick fix problem reported by GaryHoo - IZYIM order order quantity is different 2025-05-27 20:04:42 +08:00
Dillon Ngo f725933f7e Quick fix problem reported by Yien - IZYIM unable to claim unclaimed packing list, after key in the correct order number and click confirm, there is no response 2025-05-27 19:37:44 +08:00
Dillon Ngo d5a5f9e730 UI/UX + syntax fix 2025-05-13 11:33:58 +08:00
Dillon Ngo 62f892dfd1 UI/UX + syntax fix 2025-05-13 04:34:58 +08:00
Dillon Ngo 82f5d4c2bc UI/UX + syntax fix 2025-05-13 04:09:36 +08:00
Dillon Ngo a1eebe7f65 UI/UX + syntax fix 2025-05-13 02:45:40 +08:00
Edmondlang 18bd36217b add function to add contact person 2025-05-06 11:16:06 +08:00
Dillon Ngo 772fd583b5 Quick patch for missing parcel from YD integration reported by Yan - case number 2 on 20250502 2025-05-02 21:21:50 +08:00
Dillon Ngo 57812656fd Quick patch for missing parcel from YD integration reported by Yan - case number 2 on 20250502 2025-05-02 21:02:51 +08:00
Dillon Ngo 3933728a19 Quick patch for missing parcel from YD integration reported by Yan - case number 2 on 20250502 2025-05-02 20:47:01 +08:00
Dillon Ngo 8ce8ed813a Quick patch for missing parcel from YD integration reported by Yan - using command 2025-05-01 18:56:12 +08:00
Dillon Ngo 50b2f00bdc Merge branch 'dillon/83-yd-order-tracking-query-ui' into vapor/production 2025-04-28 22:24:11 +08:00
Dillon Ngo 54c23c9f38 New UI to show YD Order Tracking infomation - Disable unit testing for production deployment 2025-04-28 22:23:53 +08:00
Dillon Ngo 15570de9fb Merge branch 'dillon/83-yd-order-tracking-query-ui' into vapor/production 2025-04-28 22:20:55 +08:00
Edmondlang b21cdba5ae upon payment completion, need to redirect to order.show instead of order.details 2025-04-28 16:05:54 +08:00
Edmondlang fe8395b250 Yien's request: remove the MXXXXXXXX below the order number? we shouldn't show it to customer 2025-04-25 10:28:18 +08:00
Dillon Ngo 61f01ed39b New UI to show YD Order Tracking infomation - Testing 2025-04-24 12:35:32 +08:00
Dillon Ngo 6e2b2e5f65 New UI to show YD Order Tracking infomation - Harry feedback update 2025-04-23 12:48:41 +08:00
Dillon Ngo b4b509b0d1 New UI to show YD Order Tracking infomation - Harry feedback update 2025-04-23 12:39:43 +08:00
Dillon Ngo 6bafc49a22 New UI to show YD Order Tracking infomation - Testing 2025-04-19 19:46:00 +08:00
Edmondlang 4e4bf96a07 revert exportGroupTransaction. Wrong updates 2025-04-18 10:18:30 +08:00
Edmondlang 2e9c3000a6 remove the time from the "Date" column
Request from Azril:

I’ve attached 3 files below:
AutoMapping Excel – downloaded from the Exchange Portal
Paid Invoice Excel – from the IzyIM Portal
Aging Report Excel – also from the IzyIM Portal
What we need from you is to remove the time from the "Date" column in each file. We only need the date value moving forward.
2025-04-17 18:31:38 +08:00
Dillon Ngo 3e4d52d2ff New UI to show YD Order Tracking infomation - fixes for feedback on 20250408 2025-04-16 22:17:20 +08:00
Dillon Ngo f25f5ebb41 New UI to show YD Order Tracking infomation - fixes for feedback on 20250408 2025-04-16 22:13:50 +08:00
Edmondlang 404758c851 fix bug : Error: ob_end_clean(): failed to delete buffer.
use AWSS3Helper if filesystemDriver = s3
2025-04-16 18:18:08 +08:00
Edmondlang f6d00383cb Safely clean output buffer only if it's started and not already cleaned 2025-04-16 14:40:07 +08:00
Edmondlang 33dfdde9a0 Error: ob_end_clean(): failed to delete buffer. No buffer to delete.
Fix: Safely clean output buffer if it exists
2025-04-16 10:56:21 +08:00
Edmondlang 9b1a5b633c code update for: add function to change mobile no 2025-04-15 20:13:50 +08:00
Edmondlang b0cd0cca4d remove the time from the "Date" column
Request from Azril:

I’ve attached 3 files below:
AutoMapping Excel – downloaded from the Exchange Portal
Paid Invoice Excel – from the IzyIM Portal
Aging Report Excel – also from the IzyIM Portal
What we need from you is to remove the time from the "Date" column in each file. We only need the date value moving forward.
2025-04-15 19:49:26 +08:00
Edmondlang c0e60e5d3b add function to change mobile no 2025-04-15 19:24:11 +08:00
Dillon Ngo d093b774c2 New UI to show YD Order Tracking infomation - Testing 2025-04-14 15:29:21 +08:00
Dillon Ngo 3fa4b498e9 New UI to show YD Order Tracking infomation - Testing 2025-04-14 15:14:44 +08:00
Dillon Ngo ccd06ff740 New UI to show YD Order Tracking infomation - Testing 2025-04-14 13:53:22 +08:00
Dillon Ngo c209f6e4ed New UI to show YD Order Tracking infomation - Testing 2025-04-14 12:58:00 +08:00
Dillon Ngo f4d8ece23f New UI to show YD Order Tracking infomation - Testing 2025-04-14 12:44:50 +08:00
Dillon Ngo 215e4c72d3 New UI to show YD Order Tracking infomation - Testing 2025-04-14 12:20:54 +08:00
Dillon Ngo 386f5740f4 New UI to show YD Order Tracking infomation - Testing 2025-04-14 10:20:09 +08:00
Dillon Ngo 78c43fd7a4 New UI to show YD Order Tracking infomation - Testing 2025-04-14 10:05:45 +08:00
edmondlang d076892176 invoice date in the order payment section is wrong. It should be created_at date 2025-04-09 17:21:52 +08:00
Dillon Ngo 06b9695528 New UI to show YD Order Tracking infomation - Testing 2025-04-03 09:58:01 +08:00
Dillon Ngo 0a54f46b91 New UI to show YD Order Tracking infomation - Testing 2025-04-03 09:49:58 +08:00
Dillon Ngo 83b3d0c725 New UI to show YD Order Tracking infomation - Testing 2025-04-03 09:42:13 +08:00
Dillon Ngo de7331547c New UI to show YD Order Tracking infomation - Testing 2025-04-03 09:38:17 +08:00
Dillon Ngo 4daaac476d New UI to show YD Order Tracking infomation - Testing 2025-04-03 09:26:05 +08:00
Dillon Ngo fbf036d4b8 New UI to show YD Order Tracking infomation 2025-04-03 08:02:18 +08:00
Dillon Ngo 055e720e9f New UI to show YD Order Tracking infomation 2025-04-03 07:18:31 +08:00
Dillon Ngo 5a0b2d5a86 New UI to show YD Order Tracking infomation 2025-03-25 07:02:01 +08:00
Dillon Ngo 8f6f9893bb New UI to show YD Order Tracking infomation 2025-03-25 06:57:50 +08:00
Dillon Ngo 3255020f11 New UI to show YD Order Tracking infomation 2025-03-25 06:54:44 +08:00
Dillon Ngo 8c16277c6c New UI to show YD Order Tracking infomation 2025-03-25 06:36:32 +08:00
Dillon Ngo 87aeb0ae59 New UI to show YD Order Tracking infomation 2025-03-25 06:28:10 +08:00
Dillon Ngo 76b14cd667 New UI to show YD Order Tracking infomation 2025-03-25 06:24:43 +08:00
Dillon Ngo 6affa86c92 Quick patch for missing YD integration - using web route 2025-03-25 03:59:43 +08:00
Dillon Ngo a8c4661b2d New UI to show YD Order Tracking infomation 2025-03-24 06:40:55 +08:00
Dillon Ngo acb42ef3ab New UI to show YD Order Tracking infomation 2025-03-24 05:48:00 +08:00
Dillon Ngo 21f1a14e6f New UI to show YD Order Tracking infomation 2025-03-24 05:20:53 +08:00
Dillon Ngo d5a9e3923e New UI to show YD Order Tracking infomation 2025-03-22 11:39:31 +08:00
Dillon Ngo 7416aa00ac Quick patch for missing YD integration - using web route 2025-03-21 09:21:01 +08:00
Dillon Ngo 437765bdbb Quick patch for missing YD integration - using web route 2025-03-19 09:01:05 +08:00
Dillon Ngo 9c7ed93a54 Quick patch for missing YD integration 2025-03-18 12:31:02 +08:00
edmondlang a3b08a7c11 fix bug error web "/container/billing/{month}/{year}" 2025-02-17 17:43:52 +08:00
edmondlang e3bc918bd8 add new segment - No Extra Centimeter Charged 2025-02-14 00:30:53 +08:00
Dillon Ngo a23a632b87 Debug approve payment problem 2025-02-01 21:31:32 +08:00
Dillon Ngo 651092aa65 Debug approve payment problem 2025-02-01 21:09:44 +08:00
Dillon Ngo fe79d5bcef Debug approve payment problem 2025-02-01 19:01:24 +08:00
Dillon Ngo 6ea7517187 Debug approve payment problem 2025-02-01 18:45:05 +08:00
Dillon Ngo 4e68eefe4d Debug approve payment problem 2025-02-01 18:21:03 +08:00
Dillon Ngo 48fc02f2d2 Debug approve payment problem 2025-02-01 18:00:12 +08:00
Dillon Ngo 942c94c821 Debug approve payment problem 2025-02-01 02:20:10 +08:00
Dillon Ngo bfb76bc512 Debug approve payment problem 2025-02-01 02:00:07 +08:00
Dillon Ngo 8e3cdef4e1 Debug approve payment problem 2025-02-01 01:04:15 +08:00
Dillon Ngo c798d96238 Debug approve payment problem 2025-02-01 00:40:52 +08:00
Dillon Ngo 64d1b91fa3 Debug approve payment problem 2025-01-31 23:51:15 +08:00
Dillon Ngo 2ff63c8d0d Debug approve payment problem 2025-01-31 23:26:52 +08:00
Dillon Ngo b57a7cb2bb Debug approve payment problem 2025-01-31 23:07:20 +08:00
Dillon Ngo bf5c5574d6 Debug approve payment problem 2025-01-31 22:34:45 +08:00
Dillon Ngo 74a1f2af4c Debug approve payment problem 2025-01-31 22:11:03 +08:00
Dillon Ngo 95d230d64f Debug approve payment problem 2025-01-31 21:58:16 +08:00
Dillon Ngo 88564c661f Debug approve payment problem 2025-01-31 21:33:14 +08:00
edmondlang 6ce7f7dc91 add Google Tag Manager (GTM) so that the chat daddy code can work 2025-01-21 13:08:14 +08:00
edmondlang b91a8635d5 disable crisp 2025-01-21 12:36:19 +08:00
edmondlang 236b3769f8 add more district in seeder 2025-01-21 12:35:16 +08:00
edmondlang 3c4a19d4be update order Resource 2024-12-17 18:03:43 +08:00
edmondlang 269fbcbd66 revert logging for UpdateDoFromYDPortalProcessor response 2024-12-16 14:33:32 +08:00
edmondlang 603a67c770 add created_at for ExportsSegmentCustomers 2024-12-16 13:16:32 +08:00
edmondlang bb0832b8b0 add logging for UpdateDoFromYDPortalProcessor response 2024-12-16 12:22:29 +08:00
Dillon Ngo 8276fef3e1 YD API - Added logs for debugging 2024-12-15 09:46:54 +08:00
edmondlang aa4fcae07e update export segment customers 2024-12-13 20:34:32 +08:00
edmondlang 05adf091a8 update export segment customers 2024-12-13 20:00:07 +08:00
edmondlang b5e5e88a6a export segment customers 2024-12-13 18:41:11 +08:00
Dillon Ngo 32bad3bf07 Data patch for order already PAID, but still showing unpaid 2024-12-11 02:19:48 +08:00
edmondlang 1508fb5f1a add new advertisement - Tax Refund Service 2024-11-29 20:46:14 +08:00
edmondlang 70a2bdec48 change all 'Tax Rebate' to 'Tax Refund' 2024-11-26 19:05:01 +08:00
Dillon Ngo f5df0c9f1f Merge branch 'dillon/34.8b-yd-api-bug-fix' into vapor/production 2024-11-26 15:58:51 +08:00
Dillon Ngo e50bab014d Laravel Vapor - Fix a problem where packages not updating correct status 2024-11-26 15:58:31 +08:00
edmondlang 1933787fc3 addd function to revert identification document approval 2024-11-21 14:46:22 +08:00
Dillon Ngo 5535f13aff Merge branch 'dillon/34.8a-enhancement' into vapor/production 2024-11-18 20:56:19 +08:00
Dillon Ngo 3a2131a04d Laravel Vapor - Enhancement to prevent customer from underpay when a payment transaction include storage invoice(s) 2024-11-17 13:51:54 +08:00
Dillon Ngo c8e8c9cb0e Merge branch 'dillon/34.8b-yd-api-bug-fix' into vapor/production 2024-11-16 15:49:18 +08:00
Dillon Ngo 0e617f5ce2 Laravel Vapor - YD API integration code rewrite to fix eta/etd 2024-11-16 15:49:00 +08:00
Dillon Ngo ccb77ce56c Merge branch 'dillon/34.8b-yd-api-bug-fix' into vapor/production 2024-11-16 14:29:21 +08:00
Dillon Ngo 8f8c3ca660 Laravel Vapor - YD API integration code rewrite to fix eta/etd 2024-11-16 14:28:43 +08:00
Dillon Ngo 922718f7c2 Laravel Vapor - Enhancement to prevent customer from underpay when a payment transaction include storage invoice(s) 2024-11-16 09:17:15 +08:00
Dillon Ngo 54e6041fe5 Laravel Vapor - Enhancement to prevent customer from underpay when a payment transaction include storage invoice(s) 2024-11-15 18:34:08 +08:00
Dillon Ngo 141f1ed9d5 Laravel Vapor - Enhancement to prevent customer from underpay when a payment transaction include storage invoice(s) 2024-11-15 09:17:16 +08:00
Dillon Ngo 61d7ad22e7 Laravel Vapor - Enhancement to prevent customer from underpay when a transaction also invoice storage invoices 2024-11-14 14:03:29 +08:00
Dillon Ngo 798bf4e70e Merge branch 'dillon/34.8b-yd-api-bug-fix' into vapor/production 2024-11-14 12:02:24 +08:00
Dillon Ngo aa833f7a9f Laravel Vapor - YD API integration code rewrite to fix eta/etd 2024-11-14 11:48:26 +08:00
Dillon Ngo 8dd3fbf97a Merge branch 'dillon/34.8b-yd-api-bug-fix' into vapor/production 2024-11-13 21:38:36 +08:00
Dillon Ngo 63e1b767fc Laravel Vapor - YD API integration code rewrite to fix eta/etd 2024-11-13 21:37:20 +08:00
Dillon Ngo 60ff1c5130 Laravel Vapor - YD API integration code rewrite to fix eta/etd 2024-11-13 21:36:56 +08:00
Dillon Ngo 22aac2df04 Laravel Vapor - YD API integration code rewrite to fix eta/etd 2024-11-13 10:54:17 +08:00
edmondlang 33d65be53b tax rebate feedback:
1. add the word "退税“ behind the order number as requested by YD
2. the word "供应商” should change to “联络人”
3, Tax Rebate Refund only applicable on GZ warehouse. YW and FS warehouse cannot do Tax Rebate. Can you block or disallow the tax rebate section for this both warehouse ?
4. It will be good if a delete button can be implemented in the Created Tax Rebate QR code, so customer can remove them if they created wrongly
2024-11-13 00:18:16 +08:00
Dillon Ngo d2f6f4e8a1 Laravel Vapor - YD API integration code rewrite to fix eta/etd 2024-11-12 17:45:01 +08:00
Dillon Ngo 299c384cb2 Laravel Vapor - YD API integration code rewrite to fix eta/etd 2024-11-12 13:48:06 +08:00
Dillon Ngo be171f550b Laravel Vapor - YD API integration code rewrite to fix eta/etd 2024-11-12 12:18:07 +08:00
Dillon Ngo 8295b80f73 Merge branch 'dillon/34.8-jenkins-vapor' into vapor/production 2024-11-12 09:24:09 +08:00
Dillon Ngo 67969c63d3 Laravel Vapor - Logs output minor amendments (code sync with Exchange) 2024-11-12 09:05:45 +08:00
Dillon Ngo 2074c8661a Laravel Vapor - Remove comments 2024-11-12 08:01:59 +08:00
Dillon Ngo 9518928b7d Laravel Vapor - Remove comments 2024-11-12 07:59:38 +08:00
Dillon Ngo 634a39b1ea Merge branch 'dillon/34.8-jenkins-vapor' into vapor/production 2024-11-11 15:08:14 +08:00
Dillon Ngo 5808fd0b2f Laravel Vapor - Fix missing info with order packages where in China Warehoue 2024-11-11 15:06:30 +08:00
Dillon Ngo d7ce1df29b Laravel Vapor - YD API integration code rewrite to fix eta/etd 2024-11-11 15:01:31 +08:00
Dillon Ngo eac3f31351 Laravel Vapor - YD API integration code rewrite to fix eta/etd 2024-11-11 14:48:05 +08:00
Dillon Ngo 95a9cba32d Laravel Vapor - YD API integration code rewrite to fix eta/etd 2024-11-11 13:22:28 +08:00
Dillon Ngo 26812f723a Laravel Vapor - YD API integration code rewrite to fix eta/etd 2024-11-11 12:48:52 +08:00
edmondlang 0734447937 fix bug - /orders search component not working 2024-11-06 18:38:48 +08:00
Dillon Ngo e3f57fffd6 Merge branch 'dillon/34.8-jenkins-vapor' into vapor/production 2024-11-05 04:21:27 +08:00
Dillon Ngo b4bc441a5b Laravel Vapor - Update custom logs retention period (sync code from Exchange) 2024-11-05 04:09:08 +08:00
Dillon Ngo d678440032 Laravel Vapor - Update custom logs retention period (sync code from Exchange) 2024-11-05 03:28:17 +08:00
edmondlang 4f95520826 Merge branch 'vapor/production' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into vapor/production 2024-11-04 16:46:22 +08:00
edmondlang 33a271a54c fix bug - /orders search component not working 2024-11-04 16:45:59 +08:00
Dillon Ngo 3e3728a089 Laravel Vapor - move certain environment variables to source code vapor YAML file 2024-11-02 07:04:29 +08:00
Dillon Ngo dc8a1b0325 Merge branch 'dillon/34.8a-enhancement' into vapor/production 2024-11-02 06:08:31 +08:00
edmondlang 4a6e5f7130 fix bug create order add address extra fields 2024-11-01 17:27:55 +08:00
Dillon Ngo 6b78ca3d46 Laravel Vapor - move certain environment variables to source code vapor YAML file 2024-11-01 11:18:47 +08:00
Dillon Ngo 38612253d0 Laravel Vapor - move certain environment variables to source code vapor YAML file 2024-11-01 11:00:41 +08:00
Dillon Ngo 2fccdf4f7e Laravel Vapor - Enhancement to prevent customer from underpay when a transaction also invoice storage invoices 2024-11-01 10:05:16 +08:00
edmondlang 56d48598df deploy tax rebate QR and address extra fields 2024-10-31 18:13:10 +08:00
edmondlang 4f77da822b Merge branch 'vapor-address-extra-fields' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into vapor/production 2024-10-31 18:05:50 +08:00
edmondlang cf6fd2dad9 Merge branch 'vapor/tax-rebate-qr' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into vapor/production 2024-10-31 18:05:35 +08:00
Dillon Ngo 6cb1ec82f3 Merge branch 'dillon/34.8-jenkins-vapor' into vapor/production 2024-10-30 12:42:36 +08:00
Dillon Ngo 733b9cdfcc Laravel Vapor - sync code from Exchange date filter for reports download at /downloads page 2024-10-30 12:24:50 +08:00
Dillon Ngo 4a2860449f Laravel Vapor - Enhancement to prevent customer from underpay when a transaction also invoice storage invoices 2024-10-30 10:02:18 +08:00
Dillon Ngo 6fbea32761 Merge branch 'dillon/34.8-jenkins-vapor' into vapor/production 2024-10-23 03:06:31 +08:00
Dillon Ngo 50624b3d75 Laravel Vapor - Debug YD API call 2024-10-23 03:06:24 +08:00
Dillon Ngo dddbeb2ebd Merge branch 'dillon/34.8-jenkins-vapor' into vapor/production 2024-10-23 01:37:26 +08:00
Dillon Ngo 22714a2763 Laravel Vapor - Debug YD API call 2024-10-23 01:37:01 +08:00
edmondlang bc2c9610ee update tax rebate qr 2024-10-22 23:50:44 +08:00
edmondlang 3dc234321c update tax rebate qr 2024-10-22 23:29:51 +08:00
edmondlang 4a65031aa3 tax rebate qr 2024-10-22 22:58:06 +08:00
Dillon Ngo 4dd30b29c0 Merge branch 'dillon/34.8-jenkins-vapor' into vapor/production 2024-10-19 03:17:35 +08:00
Dillon Ngo ac6211cf5f Laravel Vapor - FIx a problem where order page not showing any thing 2024-10-19 03:17:20 +08:00
Dillon Ngo 65a622cd7b Merge branch 'dillon/34.8-jenkins-vapor' into vapor/production 2024-10-19 02:07:24 +08:00
Dillon Ngo bba600725e Laravel Vapor - Data patch for underpay group payments 2024-10-19 01:07:58 +08:00
Dillon Ngo 4fa80a2a88 Merge branch 'dillon/34.8-jenkins-vapor' into vapor/production 2024-10-18 12:15:49 +08:00
Dillon Ngo 64f52f2c11 Laravel Vapor - FIx a problem where order page not showing any thing 2024-10-18 12:15:35 +08:00
Dillon Ngo 72c1b2fb2e Merge branch 'dillon/34.8-jenkins-vapor' into vapor/production 2024-10-16 03:52:39 +08:00
Dillon Ngo b4f5328a21 Laravel Vapor - Minor typo error amendment 2024-10-16 03:23:05 +08:00
Dillon Ngo 7aee324294 Merge branch 'dillon/34.8-jenkins-vapor' into vapor/production 2024-10-16 01:51:40 +08:00
Dillon Ngo 7930e45393 Laravel Vapor - Update new RDS endpoint 2024-10-16 01:51:18 +08:00
Dillon Ngo 052dc4e5a0 Merge branch 'dillon/34.7-jenkins-vapor' into vapor/production 2024-10-16 01:21:43 +08:00
Dillon Ngo 450d2c15f9 Laravel Vapor - Update new RDS Instance endpoint 2024-10-13 16:28:52 +08:00
Dillon Ngo 7b6ed51ce8 Laravel Vapor - New website under maintenance page 2024-10-12 23:50:22 +08:00
Dillon Ngo 30d99b8d79 Laravel Vapor - New website under maintenance page 2024-10-12 23:22:01 +08:00
Dillon Ngo e6db981d5e Laravel Vapor - New UI for admin to download reports 2024-10-12 14:58:41 +08:00
Dillon Ngo d4e008380b Laravel Vapor - New UI for admin to download reports 2024-10-12 14:44:15 +08:00
784 changed files with 42703 additions and 14863 deletions
+7
View File
@@ -66,3 +66,10 @@ 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."
OPENAI_API_KEY=""
ANTHROPIC_API_KEY=""
+12
View File
@@ -0,0 +1,12 @@
APP_NAME=Laravel
APP_ENV=testing
APP_KEY=base64:I9qXyDlm7GVu/e47+YGzLB00fA/FMA2/hMPEhqu8pUQ=
JWT_SECRET=9j7f7vUWEzxUBjLYcQimZp5wmxHEglcjU3beog26qC4pQKENZSpfWQfv065tjZrZ
DB_CONNECTION=mysql
DB_HOST=172.18.0.2
DB_PORT=3306
DB_DATABASE=ci_test_shipping_portal
DB_USERNAME=ci
DB_PASSWORD=bi9y@T8r
+3 -1
View File
@@ -6,6 +6,7 @@
**/.idea/
.env
.env.backup
.env.testing.example
.phpunit.result.cache
Homestead.json
Homestead.yaml
@@ -21,7 +22,6 @@ gox.iml
rebuild_docker.sh
docker/*
db/*
package-lock.json
public/*
/public/*
storage/framework/laravel-excel/*
@@ -29,3 +29,5 @@ storage/framework/laravel-excel/*
.env.production
.env.staging
.env.development
docz/*
.phpunit.cache/
+37
View File
@@ -0,0 +1,37 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Site Under Maintenance</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
text-align: center;
padding: 50px;
}
.content {
background: white;
padding: 20px;
border-radius: 10px;
display: inline-block;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
</style>
<script>
setInterval(function() {
window.location.href = "/";
}, 60000); // 60000 ms = 1 minute, 300000 ms = 5 minutes
</script>
</head>
<body>
<div class="content">
<h1>We'll be back soon!</h1>
<p>Sorry for the inconvenience but we're performing some maintenance at the moment. We'll be back online shortly!</p>
<p>&mdash; CIEF IZYIM</p>
<a href="/" class="btn">Go Back Home</a>
</div>
</body>
</html>
Vendored
+68 -5
View File
@@ -9,14 +9,17 @@
pipeline {
agent {
docker {
args '--group-add 992 -v /var/run/docker.sock:/var/run/docker.sock'
image '303644228504.dkr.ecr.ap-southeast-1.amazonaws.com/jenkins-pipeline-agent:latest'
args '--network ci-net --group-add 992 -v /var/run/docker.sock:/var/run/docker.sock'
image '303644228504.dkr.ecr.ap-southeast-1.amazonaws.com/jenkins-pipeline-agent-php-8.3-node-22:latest'
registryCredentialsId "ecr:ap-southeast-1:aws-ec2-instance-iam-role"
registryUrl "https://303644228504.dkr.ecr.ap-southeast-1.amazonaws.com"
}
}
environment {
HOME = '.'
// DB_CONNECTION = 'mysql'
// DB_DATABASE = 'portal_development'
// APP_ENV = 'testing'
}
stages {
stage('Download source code from Git') {
@@ -28,6 +31,7 @@ pipeline {
case "vapor/production":
case "vapor/staging":
case "vapor/development":
case "vapor/test":
git(
url: 'https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal.git',
credentialsId: 'gitlab-jenkins-localhost',
@@ -58,8 +62,45 @@ pipeline {
stage('Tests') {
steps {
//sh 'vendor/bin/phpunit tests/Unit'
script{
// sh 'vendor/bin/phpunit tests/Unit'
// withCredentials([
// usernamePassword(
// credentialsId: 'shipping-portal-dev-db-credential',
// usernameVariable: 'DB_USERNAME',
// passwordVariable: 'DB_PASSWORD'
// ),
// string(credentialsId: 'shipping-portal-dev-db-host', variable: 'DB_HOST')
// ]) {
// sh 'vendor/bin/phpunit --filter ListOrderTrackingLogicTest'
// }
sh '''
set -e
export APP_ENV=testing
# export APP_KEY=$(php -r "echo 'base64:'.base64_encode(random_bytes(32));")
# export JWT_SECRET=$(php -r "echo bin2hex(random_bytes(32));")
# Show which PHP binary is used
which php
php -v
# List PHP modules to confirm pdo_mysql
php -m | grep pdo_mysql || echo "pdo_mysql not loaded"
# Show DB environment variables
echo "DB_CONNECTION=$DB_CONNECTION"
echo "DB_HOST=$DB_HOST"
echo "DB_PORT=$DB_PORT"
echo "DB_DATABASE=$DB_DATABASE"
echo "DB_USERNAME=$DB_USERNAME"
# Do NOT echo password in logs
php artisan migrate:fresh --force
vendor/bin/phpunit -c phpunit.ci.xml --group ok_to_run
'''
script {
currentBuild.description = 'Step 4 of 6 Completed'
}
}
@@ -81,6 +122,9 @@ pipeline {
case "vapor/development":
sh "vendor/bin/vapor deploy development --message='${gitCommitMessage}'"
break
case "vapor/test":
sh "vendor/bin/vapor deploy test --message='${gitCommitMessage}'"
break
case "origin/dillon/34-jenkins-vapor":
sh "vendor/bin/vapor deploy development --message='${gitCommitMessage}'"
break
@@ -94,10 +138,29 @@ pipeline {
steps {
script {
try {
sh 'docker image prune -a -f'
sh '''
echo "Starting Docker cleanup..."
# Remove stopped containers
docker container prune -f
# Remove unused networks
docker network prune -f
# Remove unused images
docker image prune -a -f
# Remove unused build cache
docker builder prune -f
echo "Docker cleanup completed."
docker system df
'''
} catch (Exception e) {
echo "Error during cleanup: ${e.message}"
}
currentBuild.description = 'Step 6 of 6 Completed'
}
}
@@ -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
);
}
}
@@ -19,22 +19,29 @@ abstract class AbstractGetRecord
/**
* @return Collection
*/
private function getQueryFilters(){
private function getQueryFilters()
{
return $this->filters->except(self::DECORATION_FILTERS);
}
/**
* @return Collection
*/
public function getDecorationFilters(){
public function getDecorationFilters()
{
return $this->filters->only(self::DECORATION_FILTERS);
}
/**
* @param null|string $json
* @param null|string|array $json
* @return array
*/
public function deserializeFilters(?string $json): array {
public function deserializeFilters($json): array
{
if (is_array($json)) {
return $json;
}
return $json !== null ? collect(json_decode($json))->toArray() : [];
}
@@ -50,7 +57,8 @@ abstract class AbstractGetRecord
* @param array $filters
* @return mixed
*/
public function handler(array $filters, array $params = []){
public function handler(array $filters, array $params = [])
{
$this->filters = collect($filters);
return $this->getResults($this->applyFiltersToQuery(), $params);
}
@@ -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);
});
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class OrderTrackingId implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->where('order_tracking_id', $value);
}
}
@@ -23,10 +23,45 @@ class PackingListLimitOneByTypeOrderedByInvoiceDate 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');
$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');
}
//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,23 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class TrackingNo implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->where('tracking_no', $value)
->where(function ($query) {
$query->whereNotNull('tracking_english')
->orWhereNotNull('remark_english');
});
}
}
@@ -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;
}
}
@@ -0,0 +1,12 @@
<?php
namespace App\Classes\General\Interfaces;
use Illuminate\Database\Eloquent\Relations\MorphMany;
interface KeyValueInterface
{
public function attributesKVP(): morphMany;
}
+1 -1
View File
@@ -10,4 +10,4 @@ interface Steppable
public function steps(): morphMany;
}
}
+15 -3
View File
@@ -19,7 +19,11 @@ class LogHelper
{
$envVar = env('LARAVEL_VAPOR_ENABLED');
$isLocal = env('VAPOR_ENV') === 'local';
Log::info("LogHelper.info: {$message} channelName {$this->channelName}, envVar {$envVar}");
if($envVar)
{
Log::info("Info: {$message} channelName {$this->channelName}, envVar {$envVar}");
}
if ($envVar && !$isLocal) {
Log::channel($this->channelName.'_vapor')->info($message);
}
@@ -32,7 +36,11 @@ class LogHelper
{
$envVar = env('LARAVEL_VAPOR_ENABLED');
$isLocal = env('VAPOR_ENV') === 'local';
Log::info("LogHelper.warning: {$message} channelName {$this->channelName}, envVar {$envVar}");
if($envVar)
{
Log::info("Warning: {$message} channelName {$this->channelName}, envVar {$envVar}");
}
if ($envVar && !$isLocal) {
Log::channel($this->channelName . '_vapor')->warning($message);
} else {
@@ -44,7 +52,11 @@ class LogHelper
{
$envVar = env('LARAVEL_VAPOR_ENABLED');
$isLocal = env('VAPOR_ENV') === 'local';
Log::info("LogHelper.error: {$message} channelName {$this->channelName}, envVar {$envVar}");
if($envVar)
{
Log::info("Error: {$message} channelName {$this->channelName}, envVar {$envVar}");
}
if ($envVar && !$isLocal) {
Log::channel($this->channelName . '_vapor')->error($message);
} else {
@@ -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,61 @@
<?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\Billplzs\Processors\CallbackBillplzProcessor;
use App\Classes\Modules\Documents\Services\ApprovesDocument;
use App\Classes\Modules\Documents\Services\RejectsDocument;
use App\Classes\Modules\Transactions\Services\FetchesTransaction;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Models\Group;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
class FixPaymentApprovalTimedOutErrorV2CommandJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function handle()
{
Log::info(Carbon::now() . ': Start job - Fix payment approval timed out error (status 504: Endpoint request timed out).');
$start = new Carbon();
$status= 'approve';
$transactionId = 23160;
$transaction = (App()->make(FetchesTransaction::class))->execute(['id' => $transactionId]);
$document = $transaction->documents()
->where('status', ApprovalStatus::PENDING_VERIFICATION)
->first();
Log::info("FixApprovedPaymentFailedGroupV2CommandJob document: ".json_encode($document));
if($status === 'approve') {
// (App()->make(ApprovesDocument::class))->execute($document);
$document->status = ApprovalStatus::APPROVED;
// $document->approver = Auth()->user()->id;
$document->approval_date = Carbon::now();
$document->save();
}
else {
(App()->make(RejectsDocument::class))->execute($document);
}
(App()->make(UpdatesTransactionStatus::class))->execute($transaction, $status === 'approve' ? ApprovalStatus::APPROVED : ApprovalStatus::REJECTED);
if ($status === 'approve') {
(App()->make(CallbackBillplzProcessor::class))->execute($transaction, ApprovalStatus::APPROVED);
}
$end = new Carbon();
$elapsedTime = $start->diff($end)->format('%H:%I:%S');
Log::info(Carbon::now() . ': End job - Fix payment approval timed out error (status 504: Endpoint request timed out). ElapsedTime: ' . $elapsedTime . '.');
}
}
@@ -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 . '.');
}
}
@@ -8,6 +8,7 @@ use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use App\Classes\Modules\Billplzs\Processors\CallbackBillplzProcessor;
use App\Classes\Modules\Billplzs\Processors\CallbackBillplzDataPatchProcessor;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Models\Transaction;
@@ -19,26 +20,25 @@ class OneTimeTransactionFixBillplzFailedCbV2CommandJob implements ShouldQueue
public function handle()
{
Log::info(Carbon::now() . ': Start job - One time fix failled callback from billplz for transaction with id 17310 cron ended.');
Log::info(Carbon::now() . ': Start job - One time fix failled callback from billplz.');
$start = new Carbon();
// ini_set('memory_limit', '-1');
//Transaction fix with this one time fix command: 15205, 16803, 17310
//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
$transaction = Transaction::whereIn('id', [17310])->first();
Log::info(Carbon::now() . ' : One time fix failled callback from billplz for transaction with id 17310 cron started.');
$transactions = Transaction::whereIn('id', [22008, 6770])->get();
if($transaction && $transaction->id == 17310){
foreach ($transactions as $transaction){
if($transaction){
Log::info(Carbon::now() . ' : 17310.');
$status = ApprovalStatus::APPROVED;
// $this->callbackBillplzProcessor->execute($transaction, $status);
(App()->make(CallbackBillplzDataPatchProcessor::class))->execute($transaction, $status);
Log::info(Carbon::now() . ' : '.$transaction->id);
$status = ApprovalStatus::APPROVED;
(App()->make(CallbackBillplzProcessor::class))->execute($transaction, $status);
// (App()->make(CallbackBillplzDataPatchProcessor::class))->execute($transaction, $status);
}
}
$end = new Carbon();
$elapsedTime = $start->diff($end)->format('%H:%I:%S');
Log::info(Carbon::now() . ': End job - One time fix failled callback from billplz for transaction with id 17310 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 . '.');
}
}
@@ -0,0 +1,31 @@
<?php
namespace App\Classes\Jobs\Commands\V2\YD;
use App\Classes\Modules\PackingLists\Processors\V2\FetchByTrakingNoYdPortalV2Processor;
use App\Models\PackingList;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
class FetchTrakingInfoYDByPackingListV2CommandJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $packingList;
public function __construct(PackingList $packingList)
{
$this->packingList = $packingList;
}
public function handle()
{
Log::info('Processing FetchTrakingInfoYDByPackingListV2CommandJob');
$processor = app(FetchByTrakingNoYdPortalV2Processor::class);
$processor->execute($this->packingList);
}
}
@@ -0,0 +1,30 @@
<?php
namespace App\Classes\Jobs\Commands\V2\YD;
use App\Classes\Modules\PackingLists\Processors\V2\FetchByTrakingNoYdPortalV2Processor;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
class FetchTrakingInfoYDByTrackingNoV2CommandJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $trackingNo;
public function __construct(string $trackingNo)
{
$this->trackingNo = $trackingNo;
}
public function handle()
{
Log::info('Processing FetchTrakingInfoYDByTrackingNoV2CommandJob');
$processor = app(FetchByTrakingNoYdPortalV2Processor::class);
$processor->processTrackingNo($this->trackingNo);
}
}
@@ -0,0 +1,30 @@
<?php
namespace App\Classes\Jobs\Commands\V2\YD;
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\Artisan;
class ProcessYDByTrakingNoDataV2Job implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $trackingNo;
public function __construct($trackingNo)
{
$this->trackingNo = $trackingNo;
}
public function handle()
{
Artisan::call('process-yd-by-traking-no-data-command', [
'trackingNo' => $this->trackingNo
]);
}
}
@@ -0,0 +1,33 @@
<?php
namespace App\Classes\Jobs\Commands\V2\YD;
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\Artisan;
class ProcessYDPortalDataV2Job implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $start;
protected $end;
public function __construct($start, $end)
{
$this->start = $start;
$this->end = $end;
}
public function handle()
{
Artisan::call('process-yd-portal-data-command', [
'start_date' => $this->start,
'end_date' => $this->end
]);
}
}
@@ -0,0 +1,32 @@
<?php
namespace App\Classes\Jobs\Commands\V3\YD;
use App\Classes\Modules\PackingLists\Processors\V3\FetchContainersUpdatesYdPortalV3Processor;
use App\Models\Container;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
class FetchContainersUpdatesYdPortalV3CommandJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $container;
public function __construct(Container $container)
{
$this->container = $container;
}
public function handle()
{
Log::info('Processing FetchContainersUpdatesYdPortalV3CommandJob');
$processor = app(FetchContainersUpdatesYdPortalV3Processor::class);
$processor->execute($this->container);
}
}
@@ -0,0 +1,32 @@
<?php
namespace App\Classes\Jobs\Commands\V3\YD;
use App\Classes\Modules\PackingLists\Processors\V3\FetchContainersYdPortalV3Processor;
use App\Models\PackingList;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
class FetchContainersYdPortalV3CommandJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $packingList;
public function __construct(PackingList $packingList)
{
$this->packingList = $packingList;
}
public function handle()
{
Log::info('Processing FetchContainersYdPortalV3CommandJob');
$processor = app(FetchContainersYdPortalV3Processor::class);
$processor->execute($this->packingList);
}
}
@@ -0,0 +1,44 @@
<?php
namespace App\Classes\Modules\Accounts\DataTransferObjects;
use App\Classes\General\Interfaces\DataTransferObject;
class KeyValuePairObject implements DataTransferObject
{
/** @var string */
private $key;
/** @var string */
private $value;
/**
* KeyValuePairObject constructor.
* @param string $key
* @param string $value
*/
public function __construct(string $key, string $value)
{
$this->key = $key;
$this->value = $value;
}
/**
* @return string
*/
public function getKey(): string
{
return $this->key;
}
/**
* @return string
*/
public function getValue(): string
{
return $this->value;
}
}
@@ -0,0 +1,28 @@
<?php
namespace App\Classes\Modules\Accounts\Services;
use App\Classes\General\Eloquent\AbstractUpdateRelationshipRecord;
use App\Classes\General\Interfaces\KeyValueInterface;
use App\Classes\Modules\Accounts\DataTransferObjects\KeyValuePairObject;
use App\Models\KeyValuePair;
class CreatesKeyValuePair extends AbstractUpdateRelationshipRecord
{
/**
* @param KeyValueInterface $kv
* @param KeyValuePairObject $object
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(KeyValueInterface $kv, KeyValuePairObject $object) {
$model = new KeyValuePair();
$model->key = $object->getKey();
$model->value = $object->getValue();
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);
}
}
@@ -11,7 +11,8 @@ use App\Models\User;
use Carbon\Carbon;
use Tymon\JWTAuth\JWT;
class GeneratesAuthenticationToken {
class GeneratesAuthenticationToken
{
/** @var JWT */
private $builder;
@@ -21,7 +22,8 @@ class GeneratesAuthenticationToken {
* GeneratesAuthenticationToken constructor.
* @param JWT $builder
*/
public function __construct(JWT $builder) {
public function __construct(JWT $builder)
{
$this->builder = $builder;
}
@@ -31,15 +33,16 @@ class GeneratesAuthenticationToken {
* @param bool $rememberUser
* @return string
*/
public function execute(User $user, bool $rememberUser = false): string {
public function execute(User $user, bool $rememberUser = false): string
{
$this->builder->manager()->setBlacklistEnabled(false);
// generate token for the customer
$this->builder->factory()->setTTL(Carbon::now()->addDay()->timestamp);
$this->builder->factory()->setTTL(525600); // 1 year
if ($rememberUser === true) {
$this->builder->factory()->setTTL(Carbon::now()->addWeek()->timestamp);
$this->builder->factory()->setTTL(525600); // 1 year
}
// set the claim based on the object
@@ -52,7 +55,8 @@ class GeneratesAuthenticationToken {
/**
* @param User $user
*/
private function setTokenClaims(User $user): void {
private function setTokenClaims(User $user): void
{
$claims = [
'id' => $user->id,
@@ -62,7 +66,7 @@ class GeneratesAuthenticationToken {
'status' => $user->status
];
if($user->type === RoleTypes::USER) {
if ($user->type === RoleTypes::USER) {
/** @var Company $companyModule */
$companyModule = $user->companyModule()->first();
@@ -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);
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\Accounts\Standards\Validators;
use App\Classes\General\Abstracts\AbstractValidation;
use App\Classes\Modules\Accounts\DataTransferObjects\UserObject;
use Illuminate\Validation\Rule;
class UserCreateValidation extends AbstractValidation
{
@@ -29,7 +30,7 @@ class UserCreateValidation extends AbstractValidation
{
return [
'name' => 'required',
'email' => 'required|unique:users',
'email' => ['required', Rule::unique('users')],
'password' => 'required',
];
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\Accounts\Standards\Validators;
use App\Classes\General\Abstracts\AbstractValidation;
use App\Classes\Modules\Accounts\DataTransferObjects\RegistrationObject;
use Illuminate\Validation\Rule;
class UserRegistrationValidation extends AbstractValidation
{
@@ -32,7 +33,7 @@ class UserRegistrationValidation extends AbstractValidation
{
return [
'name' => 'required',
'email' => 'required|email|max:255|unique:users,email',
'email' => ['required', 'email', 'max:255', Rule::unique('users', 'email')],
'password' => 'required|min:6|confirmed',
'type' => 'required',
'status' => 'required'
@@ -15,8 +15,10 @@ use App\Classes\Modules\Contacts\Processors\CreateContactProcessor;
use App\Classes\Modules\Remarks\DataTransferObjects\RemarkObject;
use App\Classes\Modules\Remarks\Processors\CreateRemarkProcessor;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\RemarkTypes;
use App\Http\Resources\AddressResource;
use App\Models\Address;
use Carbon\Carbon;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -100,6 +102,24 @@ class CreateAddressLogic extends AbstractControllerLogic
$this->createRemarkProcessor->execute($address, $remarkObject);
}
if ($request->input('pickup_time_to') <= $request->input('pickup_time_from')) {
$pickupTimeFrom = Carbon::parse($request->input('pickup_time_from'));
$request->merge([
'pickup_time_to' => $pickupTimeFrom->addHour()->format('H:i') // Format to hh:mm
]);
}
$addressExtraFields = [
'property_type' => $request->input('property_type'),
'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'),
];
$address->addressExtraFields()->delete();
$addressExtraFieldsObject = new RemarkObject(json_encode($addressExtraFields), Auth()->user()->id, RemarkTypes::ADDRESS_EXTRA_COLUMNS);
$remark = $this->createRemarkProcessor->execute($address, $addressExtraFieldsObject);
return $this->resourceResponse(new AddressResource($address));
}
@@ -2,7 +2,7 @@
namespace App\Classes\Modules\Addresses\ControllersLogic;
use App\Classes\Exceptions\AccessForbiddenException;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Addresses\Services\CreatesAddress;
use App\Classes\Modules\Addresses\Standards\Rules\CanCreateAddress;
@@ -11,6 +11,7 @@ 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;
@@ -67,7 +68,15 @@ class CreateBillingAddressLogic extends AbstractControllerLogic
public function logic(Request $request) : JsonResponse
{
$companyModule = $this->fetchesCompanyModule->execute(['id' => $request->input('company_module_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.');
}
}
$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) {
@@ -83,4 +92,4 @@ class CreateBillingAddressLogic extends AbstractControllerLogic
return $this->resourceResponse(new AddressResource($address));
}
}
}
@@ -6,6 +6,7 @@ namespace App\Classes\Modules\Addresses\ControllersLogic;
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 ErrorException;
use Illuminate\Http\JsonResponse;
@@ -51,13 +52,12 @@ class ListAddressesLogic extends AbstractControllerLogic
*/
public function logic(Request $request) : JsonResponse
{
$this->canListAddresses->passes();
$query = $this->listsAddresses->execute($this->listsAddresses->deserializeFilters($request->input('filters')));
//$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));
}
}
}
@@ -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);
}
}
@@ -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' => !empty($model) ? $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()
);
}
}
}
@@ -88,14 +88,14 @@ class CallbackBillplzDataPatchProcessor
$invoice = $groupTransaction->transaction;
Log::info('CallbackBillplzDataPatchProcessor 3: '.json_encode($invoice));
//if($invoice->status !== ApprovalStatus::COMPLETED){
// $paymentTransaction = $this->createPaymentTransactionProcessor->execute($invoice, PaymentMethodType::WALLET, null, false);
if($invoice->status !== ApprovalStatus::COMPLETED){
$paymentTransaction = $this->createPaymentTransactionProcessor->execute($invoice, PaymentMethodType::WALLET, null, false);
// if($paymentTransaction && $paymentTransaction->status == ApprovalStatus::APPROVED){
if($paymentTransaction && $paymentTransaction->status == ApprovalStatus::APPROVED){
$pL = $invoice->owner;
$this->releaseGoodsToCustomerProcessor->execute($pL, $invoice, true);
//}
//}
}
}
}
$group->status = $status;
@@ -8,15 +8,12 @@ use App\Classes\Modules\Documents\Standards\Rules\CanApproveDocument;
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\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\Modules\Notifications\Processors\CreateNotificationProcessor;
use App\Models\Document;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -27,10 +24,11 @@ class ApproveIdentificationDocumentLogic extends AbstractControllerLogic
/**
* @return array
*/
protected function notification():array {
protected function notification(): array
{
return [
'title' => 'Approve Document',
'message' => 'You have successfully approved the Document'
'title' => 'Update Document Status',
'message' => 'You have successfully updated the Document Status'
];
}
@@ -43,6 +41,9 @@ class ApproveIdentificationDocumentLogic extends AbstractControllerLogic
/** @var RejectsDocument */
private $rejectsDocument;
/** @var PendingVerificationDocument */
private $pendingVerificationDocument;
/** @var FetchesDocument */
private $fetchesDocument;
@@ -61,11 +62,12 @@ class ApproveIdentificationDocumentLogic extends AbstractControllerLogic
* @param ApprovesDocument $approvesDocument
* @param RejectsDocument $rejectsDocument
* @param FetchesDocument $fetchesDocument
* @param PendingVerificationDocument $pendingVerificationDocument
* @param UpdatesCompanyStatus $updatesCompanyStatus
* @param UpdatesOrdersStatus $updatesOrdersStatus
* @param CreateNotificationProcessor $createNotificationProcessor
*/
public function __construct(CanApproveDocument $canApproveDocument, ApprovesDocument $approvesDocument, RejectsDocument $rejectsDocument, FetchesDocument $fetchesDocument, UpdatesCompanyStatus $updatesCompanyStatus, UpdatesOrdersStatus $updatesOrdersStatus, CreateNotificationProcessor $createNotificationProcessor)
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;
@@ -74,6 +76,7 @@ class ApproveIdentificationDocumentLogic extends AbstractControllerLogic
$this->updatesCompanyStatus = $updatesCompanyStatus;
$this->updatesOrdersStatus = $updatesOrdersStatus;
$this->createNotificationProcessor = $createNotificationProcessor;
$this->pendingVerificationDocument = $pendingVerificationDocument;
}
/**
@@ -83,37 +86,37 @@ class ApproveIdentificationDocumentLogic extends AbstractControllerLogic
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
public function logic(Request $request) : JsonResponse
public function logic(Request $request): JsonResponse
{
$status = $request->route('status');
/** @var Document $document */
$document = $this->fetchesDocument->execute(['id' => $request->route('document_id')]);
$this->canApproveDocument->passes();
$document = $status === 'approve' ? $this->approvesDocument->execute($document) : $this->rejectsDocument->execute($document);
$this->updatesCompanyStatus->execute($document->owner, $status === 'approve' ? ApprovalStatus::APPROVED : ApprovalStatus::REJECTED);
// $object = new NotificationObject(
// 'ID Verification ' . ( $status === 'approve' ? 'Approved' : 'Rejected' ),
// ( $status === 'approve' ? 'Dear user, congratulations that your ' : 'Dear user, we are sorry to inform you that your ' ) . ( $document->type === 'IDENTITY_CARD' ? 'IC' : 'SSM' ) . ( $status === 'approve' ? ' has been approved. Start your first order now!' : ' has been rejected due to ' . ( $request->input('rejectRemark') ?? '' ) . ', please resubmit it for further action.' ),
// $document->owner,
// $document->owner->companyModules()->first()->employees()->first(),
// $document,
// );
//
// $this->createNotificationProcessor->execute($object);
if($status === 'approve'){
$orders = $this->updatesOrdersStatus->execute($document->owner, ApprovalStatus::APPROVED);
if ($status === 'approve') {
$document = $this->approvesDocument->execute($document);
$this->updatesCompanyStatus->execute($document->owner, ApprovalStatus::APPROVED);
$this->updatesOrdersStatus->execute($document->owner, ApprovalStatus::APPROVED);
} elseif ($status === 'reject') {
$document = $this->rejectsDocument->execute($document);
$this->updatesCompanyStatus->execute($document->owner, ApprovalStatus::REJECTED);
} elseif ($status === 'pending') {
$document = $this->pendingVerificationDocument->execute($document);
$this->updatesCompanyStatus->execute($document->owner, ApprovalStatus::PENDING_VERIFICATION);
}
// $object = new NotificationObject(
// 'ID Verification ' . ( $status === 'approve' ? 'Approved' : 'Rejected' ),
// ( $status === 'approve' ? 'Dear user, congratulations that your ' : 'Dear user, we are sorry to inform you that your ' ) . ( $document->type === 'IDENTITY_CARD' ? 'IC' : 'SSM' ) . ( $status === 'approve' ? ' has been approved. Start your first order now!' : ' has been rejected due to ' . ( $request->input('rejectRemark') ?? '' ) . ', please resubmit it for further action.' ),
// $document->owner,
// $document->owner->companyModules()->first()->employees()->first(),
// $document,
// );
// $this->createNotificationProcessor->execute($object);
return $this->resourceResponse(new DocumentResource($document));
}
}
}
@@ -0,0 +1,74 @@
<?php
namespace App\Classes\Modules\Companies\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Contacts\DataTransferObjects\ContactObject;
use App\Classes\Modules\Companies\Services\FetchesCompany;
use App\Classes\Modules\Contacts\Services\CreatesContact;
use App\Http\Resources\ContactResource;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use App\Classes\Modules\Contacts\Processors\CreateContactProcessor;
use App\Http\Resources\CompanyResource;
class CreateCompanyContactNumberLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Created Company Contact Number',
'message' => 'You have successfully created the Company Contact Number'
];
}
/** @var FetchesCompany */
private $fetchesCompany;
/** @var CreatesContact */
private $createsContact;
/** @var CreateContactProcessor */
private $createContactProcessor;
/**
* UpdateCompanyControllersLogic constructor.
* @param FetchesCompany $fetchesCompany
* @param CreatesContact $createsContact
* @param CreateContactProcessor $createContactProcessor
*/
public function __construct(FetchesCompany $fetchesCompany, CreatesContact $createsContact, CreateContactProcessor $createContactProcessor)
{
$this->fetchesCompany = $fetchesCompany;
$this->createsContact = $createsContact;
$this->createContactProcessor = $createContactProcessor;
}
/**
* @param Request $request
* @return JsonResponse
* @throws ErrorException
*/
public function logic(Request $request) : JsonResponse
{
$company = $this->fetchesCompany->execute(['id' => $request->input('companyId')]);
$contact = new ContactObject(
$company->reference,
$request->input('contactNumber'),
$company->email,
$company->wechat_id
);
$this->createContactProcessor->execute($contact, $company);
return $this->resourceResponse(new CompanyResource($company));
}
}
@@ -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));
}
}
@@ -0,0 +1,67 @@
<?php
namespace App\Classes\Modules\Companies\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Contacts\DataTransferObjects\ContactObject;
use App\Classes\Modules\Contacts\Services\FetchesContact;
use App\Classes\Modules\Contacts\Services\UpdatesContact;
use App\Http\Resources\ContactResource;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class UpdateCompanyContactNumberLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Updated Company Contact Number',
'message' => 'You have successfully updated the Company Contact Number'
];
}
/** @var FetchesContact */
private $fetchesContact;
/** @var UpdatesContact */
private $updatesContact;
/**
* UpdateCompanyControllersLogic constructor.
* @param FetchesContact $fetchesContact
* @param UpdatesContact $updatesContact
*/
public function __construct(FetchesContact $fetchesContact, UpdatesContact $updatesContact)
{
$this->fetchesContact = $fetchesContact;
$this->updatesContact = $updatesContact;
}
/**
* @param Request $request
* @return JsonResponse
* @throws ErrorException
*/
public function logic(Request $request) : JsonResponse
{
$query = $this->fetchesContact->execute(['id' => $request->input('id')]);
$contact = new ContactObject(
$query->reference,
$request->input('contactNumber'),
$query->email,
$query->wechat_id
);
$this->updatesContact->execute($query, $contact);
return $this->resourceResponse(new ContactResource($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,
];
}
}
@@ -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);
}
}
@@ -5,8 +5,10 @@ namespace App\Classes\Modules\Documents\DataTransferObjects;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\General\Interfaces\DataTransferObject;
use App\Classes\ValueObjects\Constants\FileType;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Intervention\Image\ImageManager;
use Intervention\Image\Drivers\Gd\Driver;
class FileObject implements DataTransferObject
{
@@ -28,7 +30,13 @@ class FileObject implements DataTransferObject
*/
public function getData()
{
return in_array($this->getExtension(), ['pdf', 'excel']) ? $this->data : (new imageManager())->make($this->data);
// intervention/image v2: old
// return in_array($this->getExtension(), ['pdf', 'excel']) ? $this->data : (new imageManager())->make($this->data);
// intervention/image v3: new
return in_array($this->getExtension(), ['pdf', 'excel'])
? $this->data
: (new ImageManager(new Driver()))->read($this->data);
}
/**
@@ -66,9 +74,10 @@ class FileObject implements DataTransferObject
*/
public function getDecodedData(): string
{
// intervention/image v3: Use encode()->toDataUri() instead of encode('data-url')->encoded
return in_array($this->getExtension(), ['pdf', 'excel']) ?
base64_decode((explode('base64,', $this->getData()))[1]):
$this->getData()->encode('data-url')->encoded;
$this->getData()->encode()->toDataUri();
}
/**
@@ -66,17 +66,22 @@ class ConvertsBase64ToFile
$suffix = $size !== 'original' ? '_'.$size : '';
if($size !== 'original') {
$thumbnail = $file->getData()->widen($value, function ($constraint) {
$constraint->upsize();
// intervention/image v2: old
// $thumbnail = $file->getData()->widen($value, function ($constraint) {
// $constraint->upsize();
// })->heighten($value, function ($constraint) {
// $constraint->upsize();
// });
// $file->setData($thumbnail->encode('data-url')->encoded);
})->heighten($value, function ($constraint) {
$constraint->upsize();
// intervention/image v3: Use scaleDown() instead of widen()/heighten()
// scaleDown() maintains aspect ratio and prevents upsizing by default
$thumbnail = $file->getData()->scaleDown(width: $value, height: $value);
});
$file->setData($thumbnail->encode('data-url')->encoded);
// intervention/image v3: Use encode()->toDataUri() instead of encode('data-url')->encoded
$file->setData($thumbnail->encode()->toDataUri());
}
@@ -19,14 +19,18 @@ class CreatesFiles extends AbstractUpdateRelationshipRecord
{
$models = [];
// foreach ($object->getFiles() as $file) {
// $model = new File(['file' => $file]);
// $models[] = $this->handler($document->files(), $model);
// }
foreach ($object->getFiles() as $file) {
$model = new File(['file' => $file]);
$fileData = is_string($file) ? json_decode($file, true) : $file;
$model = new File(['file' => $fileData]);
$models[] = $this->handler($document->files(), $model);
}
return $models;
}
}
}
@@ -0,0 +1,26 @@
<?php
namespace App\Classes\Modules\Documents\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Models\Document;
use Carbon\Carbon;
class PendingVerificationDocument extends AbstractUpdateRecord
{
/**
* @param Document $model
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(Document $model)
{
$model->status = ApprovalStatus::PENDING_VERIFICATION;
$model->approver = Auth()->user()->id;
$model->approval_date = Carbon::now();
return $this->handler($model);
}
}
@@ -0,0 +1,86 @@
<?php
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 Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
class ExportsAllCustomersInfoForLarkSystem implements FromQuery, WithMapping, WithHeadings, ShouldAutoSize
{
use Exportable;
protected $deduplicateMarking;
protected $request;
public function __construct(Request $request, $deduplicateMarking = true)
{
$this->deduplicateMarking = $deduplicateMarking;
$this->request = $request;
}
public function headings(): array
{
return [
'Marking',
'Name',
'Phone Number',
'Email',
'Registration Date',
'Last Order Date',
'Debtor Code',
'Credit Term Customer',
'Custom Segments',
];
}
public function query()
{
$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($connection): array
{
$company = optional(optional($connection)->invitee)->company;
$companyModule = optional($company)->companyModules->first();
$employee = optional($companyModule)->employees->first();
$contact = optional($company)->contacts->first();
$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,
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,
];
}
}
@@ -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
'',
'',
'',
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\Exports\Services;
use App\Classes\Modules\Exports\Sheets\ContainersSheet;
use App\Classes\Modules\Exports\Sheets\PackingListsSheet;
use Carbon\Carbon;
use Maatwebsite\Excel\Concerns\Exportable;
use Maatwebsite\Excel\Concerns\WithMultipleSheets;;
@@ -11,6 +12,14 @@ class ExportsParcel implements WithMultipleSheets
{
use Exportable;
protected $startDate;
protected $endDate;
public function __construct($startDate = null, $endDate = null) {
$this->startDate = $startDate;
$this->endDate = $endDate;
}
/**
* @return array
@@ -19,10 +28,10 @@ class ExportsParcel implements WithMultipleSheets
{
$sheets = [];
$sheets[] = new ContainersSheet();
$sheets[] = new PackingListsSheet();
$sheets[] = new ContainersSheet($this->startDate, $this->endDate);
$sheets[] = new PackingListsSheet($this->startDate, $this->endDate);
return $sheets;
}
}
}
@@ -143,8 +143,10 @@ class ExportsPaymentTransactions implements FromQuery, WithHeadings, WithHeading
// Prepare each row based on the transaction detail
$rows[] = [
$firstItem ? '<<New>>' : '',
$transaction->created_at->format('m/d/Y H:m'),
$transaction->transactions()->where('type', TransactionType::PAYMENT)->first()->updated_at->format('m/d/Y H:m'),
// $transaction->created_at->format('m/d/Y H:m'),
$transaction->created_at->format('m/d/Y'),
// $transaction->transactions()->where('type', TransactionType::PAYMENT)->first()->updated_at->format('m/d/Y H:m'),
$transaction->transactions()->where('type', TransactionType::PAYMENT)->first()->updated_at->format('m/d/Y'),
$company->debtor,
$order->reference,
$order->reference,
@@ -169,7 +171,8 @@ class ExportsPaymentTransactions implements FromQuery, WithHeadings, WithHeading
return [
'<<New>>',
$transaction->transactions()->where('type', TransactionType::PAYMENT)->first()->updated_at->format('m/d/Y H:m'),
// $transaction->transactions()->where('type', TransactionType::PAYMENT)->first()->updated_at->format('m/d/Y H:m'),
$transaction->transactions()->where('type', TransactionType::PAYMENT)->first()->updated_at->format('m/d/Y'),
$company->debtor,
$order->reference,
$order->reference,
@@ -188,7 +191,8 @@ class ExportsPaymentTransactions implements FromQuery, WithHeadings, WithHeading
];
return [
'<<New>>',
$transaction->updated_at->format('m/d/Y H:m'),
// $transaction->updated_at->format('m/d/Y H:m'),
$transaction->updated_at->format('m/d/Y'),
$company->debtor,
$container->reference,
'500-0000',
@@ -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;
}
}
@@ -0,0 +1,78 @@
<?php
namespace App\Classes\Modules\Exports\Services;
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\Support\Facades\Log;
class ExportsSegmentCustomers implements WithHeadings, WithHeadingRow, WithMapping, ShouldAutoSize, FromQuery
{
use Exportable;
private $filters;
protected $customerMarking;
protected $segment;
public function __construct() {}
public function setParameters($customerMarking, $segment)
{
$this->customerMarking = $customerMarking;
$this->segment = $segment;
$this->filters = [
"company_segments_in" => [$this->segment],
];
if ($this->customerMarking != 0) {
$this->filters['marking_in'] = [$this->customerMarking];
}
}
public function headings(): array
{
return [
'Company Name',
'Company Marking',
'Is Credit Term Customers',
'Auto Release',
'Latest Order Creation Date',
];
}
public function query()
{
return (new ApplyFiltersToQuery())->execute(Company::query(), $this->filters);
}
public function map($list): array
{
$companyModule = $list->companyModules()->first();
$marking = $companyModule->getMarking();
$isCreditTermCustomer = false;
$segments = $companyModule->connections()->first()->segments()->pluck('name')->toArray();
$isCreditTermCustomer = in_array('Credit Term Customer', $segments);
$autoRelease = in_array('Auto Release', $segments);
$lastestOrder = $companyModule->orders()->orderBy('id', 'desc')->first();
return [
$list->name,
$marking,
$isCreditTermCustomer ? 'TRUE' : 'FALSE',
$autoRelease ? 'TRUE' : 'FALSE',
$lastestOrder ? $lastestOrder->created_at : '',
];
}
}
@@ -23,9 +23,16 @@ use Maatwebsite\Excel\Concerns\ShouldAutoSize;
class ContainersSheet implements WithHeadings, WithHeadingRow, WithMapping, ShouldAutoSize, FromQuery, WithTitle
{
use Exportable;
protected $startDate;
protected $endDate;
public function __construct($startDate = null, $endDate = null) {
$this->startDate = $startDate ? Carbon::parse($startDate)->startOfDay() : Carbon::now()->subMonths(3);
$this->endDate = $endDate ? Carbon::parse($endDate)->endOfDay() : Carbon::now();
}
public function headings(): array
{
return [
@@ -47,7 +54,7 @@ class ContainersSheet implements WithHeadings, WithHeadingRow, WithMapping, Shou
public function query()
{
return Container::query()
->whereBetween('created_at', [Carbon::now()->subMonths(3), Carbon::now()]); //Limit, 'expensive' query
->whereBetween('created_at', [$this->startDate, $this->endDate]); //Limit, 'expensive' query
}
/**
@@ -30,6 +30,14 @@ class PackingListsSheet implements WithHeadings, WithHeadingRow, WithMapping, Sh
use Exportable;
protected $startDate;
protected $endDate;
public function __construct($startDate = null, $endDate = null) {
$this->startDate = $startDate ? Carbon::parse($startDate)->startOfDay() : Carbon::now()->subMonths(3);
$this->endDate = $endDate ? Carbon::parse($endDate)->endOfDay() : Carbon::now();
}
public function headings(): array
{
return [
@@ -55,7 +63,7 @@ class PackingListsSheet implements WithHeadings, WithHeadingRow, WithMapping, Sh
{
$packingLists = PackingList::where('status', '=', 2)
->whereIn('type', [PackingListType::WAREHOUSE_RECEIVE_LIST, PackingListType::SHIPPING_PACKING_LIST])
->whereBetween('created_at', [Carbon::now()->subMonths(3), Carbon::now()]) //Limit, 'expensive' query
->whereBetween('created_at', [$this->startDate, $this->endDate]) //Limit, 'expensive' query
->get();
return $packingLists->filter(function ($packingList) {
@@ -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.');
}
}
}
@@ -0,0 +1,49 @@
<?php
namespace App\Classes\Modules\OpenAI\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\ConnectionErrorException;
use Illuminate\Support\Facades\Log;
class CreatesChatGPTResponse
{
/**
* @param string $userPrompt
* @return null|object
* @throws MalformedRequestException
*/
public function execute(string $userPrompt) {
try {
$data = [
'model' => 'gpt-4-turbo', //gpt-4-turbo, gpt-4o-mini
'messages' => [
[
'role' => 'user',
'content' => $userPrompt
]
]
];
$response = Http::withHeaders([
'Authorization' => 'Bearer ' . config('openai.api_key')
])->post(config('openai.base_url') . '/v1/chat/completions', $data);
if ($response->successful()) {
$data = $response->json();
return $data;
} else {
Log::info('CreatesChatGPTResponse: ' . $response);
return null;
}
}
catch (\Illuminate\Http\Client\ConnectionException $exception) {
$error = 'Failed to connect to ChatGPT API';
throw new ConnectionErrorException($error, $exception->getMessage(), $userPrompt, $exception->getTraceAsString());
}
catch (\Exception $exception) {
throw new MalformedRequestException('Unable to get correct response from ChatGPT API: ' . $exception->getMessage());
}
}
}
@@ -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([])));
}
}
@@ -0,0 +1,84 @@
<?php
namespace App\Classes\Modules\Orders\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Orders\Services\ChecksIfOrderNumberExists;
use App\Classes\Modules\Orders\Services\RestoresOrder;
use App\Classes\Modules\Orders\Services\FetchesOrder;
use App\Http\Resources\OrderResource;
use App\Models\Order;
use App\Models\SupplierTaxRebate;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
class CreateSupplierTaxRebateLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification(): array
{
return [
'title' => 'Create Supplier Tax Refund',
'message' => 'You have successfully created a Supplier Tax Refund'
];
}
/** @var RestoresOrder */
private $restoresOrder;
/** @var FetchesOrder */
private $fetchesOrder;
/** @var ChecksIfOrderNumberExists */
private $checkIfOrderNumberExists;
/**
* CancelOrderLogic constructor.
* @param RestoresOrder $restoresOrder
* @param FetchesOrder $fetchesOrder
*/
public function __construct(RestoresOrder $restoresOrder, FetchesOrder $fetchesOrder, ChecksIfOrderNumberExists $checkIfOrderNumberExists)
{
$this->restoresOrder = $restoresOrder;
$this->fetchesOrder = $fetchesOrder;
$this->checkIfOrderNumberExists = $checkIfOrderNumberExists;
}
/**
* @param Request $request
* @return JsonResponse
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function logic(Request $request): JsonResponse
{
/** @var Order $order */
$order = $this->fetchesOrder->execute(['id' => $request->route('id')]);
$taxRebate = SupplierTaxRebate::create([
'order_id' => $order->id,
'supplier_name' => $request->input('supplier_name'),
'supplier_contact_number' => $request->input('supplier_contact_number'),
'reference_number' => $this->generateUniqueReferenceNumber(),
]);
return $this->resourceResponse(new OrderResource($order));
}
public function generateUniqueReferenceNumber(?string $prefix = '', ?int $length = 9): string
{
// regenerate new reference number until a new unique reference is found
do {
$reference = $prefix . rand((int)('1' . str_repeat('0', $length - 2) . '1'), (int) str_repeat('9', $length));
} while (
SupplierTaxRebate::where('reference_number', $reference)->exists() || $this->checkIfOrderNumberExists->execute($reference)
);
return $reference;
}
}
@@ -0,0 +1,41 @@
<?php
namespace App\Classes\Modules\Orders\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Models\SupplierTaxRebate;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class DeleteSupplierTaxRebateLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification(): array
{
return [
'title' => 'Delete Supplier Tax Refund',
'message' => 'You have successfully deleted a Supplier Tax Refund'
];
}
/**
* DeleteSupplierTaxRebateLogic constructor.
*/
public function __construct() {}
/**
* @param Request $request
* @return JsonResponse
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function logic(Request $request): JsonResponse
{
SupplierTaxRebate::find($request->route('id'))->delete();
return $this->response([]);
}
}
@@ -6,10 +6,14 @@ 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 `FetchOrderPackagesReceivedV2Logic` instead or write a new one based on FetchOrderPackagesReceivedV2Logic
*/
class FetchOrderPackagesLogic extends AbstractControllerLogic
{
@@ -70,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\OrderPackagesOriginWarehouseResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class FetchOrderPackagesOriginWarehouseV2Logic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Retrieved Order Packages Origin Warehouse',
'message' => 'You have successfully retrieved an order packages'
];
}
/** @var CanFetchOrder */
private $canFetchOrder;
/** @var FetchesOrder */
private $fetchesOrder;
/**
* FetchOrderPackagesOriginWarehouseV2Logic 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 OrderPackagesOriginWarehouseResource($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));
}
}
@@ -0,0 +1,56 @@
<?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\OrderPackagesResource;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class FetchOrderPackagesV2Logic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Retrieved Order Packages',
'message' => 'You have successfully retrieved an order packages'
];
}
/** @var CanFetchOrder */
private $canFetchOrder;
/** @var FetchesOrder */
private $fetchesOrder;
/**
* FetchOrderPackagesV2Logic constructor.
* @param CanFetchOrder $canFetchOrder
* @param FetchesOrder $fetchesOrder
*/
public function __construct(CanFetchOrder $canFetchOrder, FetchesOrder $fetchesOrder)
{
$this->canFetchOrder = $canFetchOrder;
$this->fetchesOrder = $fetchesOrder;
}
/**
* @param Request $request
* @return JsonResponse
* @throws \App\Classes\Exceptions\AccessForbiddenException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
public function logic(Request $request) : JsonResponse
{
$this->canFetchOrder->passes();
$query = $this->fetchesOrder->execute(['reference' => $request->route('id'), 'with_packing_lists' => true]);
return $this->resourceResponse(new 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));
}
}
@@ -0,0 +1,84 @@
<?php
namespace App\Classes\Modules\Orders\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Orders\Services\ListsOrderTracking;
use App\Http\Resources\OrderTrackingResource;
use App\Models\Order;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\Log;
use Illuminate\Contracts\Encryption\DecryptException;
use App\Classes\Modules\Orders\Standards\Rules\CanListTrackings;
class ListOrderTrackingLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Retrieved Order Tracking',
'message' => 'You have successfully retrieved order tracking info'
];
}
/** @var ListsOrderTracking */
private $listsOrderTracking;
/** @var CanListTrackings */
private $canListTrackings;
/**
* ListOrderTrackingLogic constructor.
* @param CanListTrackings $canListTrackings
* @param ListsOrderTracking $listsOrderTracking
*/
public function __construct(CanListTrackings $canListTrackings, ListsOrderTracking $listsOrderTracking)
{
$this->canListTrackings = $canListTrackings;
$this->listsOrderTracking = $listsOrderTracking;
}
public function logic(Request $request) : JsonResponse
{
$query = null;
$filters = json_decode($request->input('filters'), true);
$trackingNo = $filters['tracking_no'];
try {
$trackingNo = Crypt::decryptString($trackingNo);
$trackingNo = str_replace('_01', '', $trackingNo);
} catch (DecryptException $e) {
Log::info('Decryption failed, string might already be decrypted or invalid.');
$this->canListTrackings->passes();
// if(!in_array(Auth()->user()->type, [RoleTypes::SHADOW_ADMIN, RoleTypes::SUPER_ADMIN])){
// abort(404);
// }
}
if (preg_match('/^\d{9}$/', $trackingNo)) {
$order = Order::where('reference', $trackingNo)->first();
if($order){
$packingList = $order->packingLists()->first();
$trackingNo = $packingList->reference;
Artisan::call('process-yd-by-traking-no-data-command', [
'trackingNo' => $trackingNo
]);
$query = $this->listsOrderTracking->execute(array_merge($this->listsOrderTracking->deserializeFilters($request->input('filters')), ['tracking_no' => $trackingNo]));
}
}
else{
Artisan::call('process-yd-by-traking-no-data-command', [
'trackingNo' => $trackingNo
]);
$query = $this->listsOrderTracking->execute(array_merge($this->listsOrderTracking->deserializeFilters($request->input('filters')), ['tracking_no' => $trackingNo]));
}
return $this->collectionResponse(OrderTrackingResource::collection($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));
}
}
@@ -15,6 +15,10 @@ use App\Classes\Modules\OrderSteps\DataTransferObjects\StepsObject;
use App\Classes\Modules\OrderSteps\Services\UpdatesOrderSteps;
use Illuminate\Http\Request;
/**
* @deprecated This class uses incorrect StepsObject instantiation (9 parameters instead of 4)
* FIXME: Correct pattern: new StepsObject($appointee_id, $obligation->reference, $obligation->sequence, $obligation->hash_id)
*/
class ConfirmOrderProcessor
{
private $canConfirmOrder;
@@ -42,6 +46,8 @@ class ConfirmOrderProcessor
//Only Processing Step is created at this point
$orderStep = $order->orderSteps[0];
// FIXME: Incorrect StepsObject instantiation - uses 9 parameters instead of correct 4-parameter pattern
// Correct pattern: new StepsObject($appointee_id, $obligation->reference, $obligation->sequence, $obligation->hash_id)
$orderStepObject = new StepsObject(
0,
$orderStep->reference,
@@ -69,10 +69,8 @@ class UpdateDoFromYDPortalProcessor
'cellphone' => $phone,
'postcode' => $address->postcode,
'streetAddress' => $address->street_one . ' ' . $address->street_two . ' '. $address->district->name.' '. $address->post_code.' '.$address->state->name.' '.$address->country->name.' '.$address->postcode.' || '.$remark
]);
]
);
} catch (\Exception $exception){
log::debug($exception);
throw new InternalServerErrorException('failed to approve address due to an error related to YD portal');
@@ -0,0 +1,31 @@
<?php
namespace App\Classes\Modules\Orders\Services;
use Illuminate\Database\Eloquent\Builder;
use App\Classes\General\Eloquent\AbstractListRecord;
use App\Models\YDOrderTracking;
class ListsOrderTracking extends AbstractListRecord
{
/** @var YDOrderTracking */
private $repository;
/**
* ListsOrderTracking constructor.
* @param YDOrderTracking $repository
*/
public function __construct(YDOrderTracking $repository)
{
$this->repository = $repository;
}
/**
* @return Builder
*/
public function getRepository(): Builder
{
return $this->repository->newQuery();
}
}
@@ -0,0 +1,50 @@
<?php
namespace App\Classes\Modules\Orders\Services;
use App\Classes\ValueObjects\Constants\WarehouseReferences;
use App\Models\Address;
use App\Models\CompanyModule;
class ResolveIzyimQrWarehousePrefix
{
public const NEW_LOCATION_PREFIX_MAP = [
'kuching' => 'KCH-',
'bintulu' => 'BNT-',
'miri' => 'MIRI-',
];
public function execute(CompanyModule $originWarehouse, Address $deliveryAddress): string
{
$warehousePrefix = '';
if ($originWarehouse->reference === WarehouseReferences::YD_YIWU) {
$warehousePrefix = 'YW/';
}
$stateName = strtolower((string) optional($deliveryAddress->state)->name);
$districtName = strtolower((string) optional($deliveryAddress->district)->name);
if (in_array($originWarehouse->reference, [WarehouseReferences::YD_GUANG_ZHOU, WarehouseReferences::YD_GUANG_ZHOU_2, WarehouseReferences::YD_FS_EAST_MALAYSIA, WarehouseReferences::YD_FS_WEST_MALAYSIA])) {
$warehousePrefix = 'YD/';
if (strtolower($deliveryAddress->state->name) === 'sabah' || strtolower($deliveryAddress->state->name) === 'labuan' || in_array(strtolower($deliveryAddress->district->name), ['limbang', 'lawas'])) {
$warehousePrefix = 'KK/';
}
if (strtolower($deliveryAddress->state->name) === 'sarawak' && !in_array(strtolower($deliveryAddress->district->name), ['limbang', 'lawas'])) {
$warehousePrefix = 'KU/';
}
if (strtolower($deliveryAddress->state->name) === 'johor') {
$warehousePrefix = 'NX/';
}
}
if (isset(self::NEW_LOCATION_PREFIX_MAP[$districtName])) {
$warehousePrefix = self::NEW_LOCATION_PREFIX_MAP[$districtName];
}
return $warehousePrefix;
}
}
@@ -0,0 +1,47 @@
<?php
namespace App\Classes\Modules\Orders\Standards\Rules;
use App\Classes\General\Abstracts\AbstractRule;
use App\Classes\ValueObjects\Constants\RoleTypes;
class CanListTrackings extends AbstractRule
{
/**
* @return bool
*/
protected function authorized($object): bool
{
if(Auth()->user()){
$roleToCheck = Auth()->user()->type;
if (in_array($roleToCheck, RoleTypes::ADMIN_ROLES)) {
return true;
}
else {
return false;
}
}
return false;
}
/**
* @param BookingObject $object
* @return bool
*/
protected function validators($object): bool
{
return true;
}
/**
* @param BookingObject $object
* @return bool
*/
protected function criteria($object): bool
{
return true;
}
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\Orders\Standards\Validators;
use App\Classes\General\Abstracts\AbstractValidation;
use App\Classes\Modules\Orders\DataTransferObjects\OrderObject;
use Illuminate\Validation\Rule;
class ConfirmOrderValidation extends AbstractValidation
{
@@ -26,7 +27,7 @@ class ConfirmOrderValidation extends AbstractValidation
{
return [
'id' => 'required|exists:orders,id'
'id' => ['required', Rule::exists('orders', 'id')]
];
}
@@ -4,6 +4,7 @@ namespace App\Classes\Modules\Orders\Standards\Validators;
use App\Classes\General\Abstracts\AbstractValidation;
use App\Classes\Modules\Orders\DataTransferObjects\OrderObject;
use Illuminate\Validation\Rule;
class OrderRoleValidation extends AbstractValidation
{
@@ -28,8 +29,8 @@ class OrderRoleValidation extends AbstractValidation
protected function rules(?string $type = 'POST'): array
{
return [
'order_id' => 'required|exists:orders,id',
'company_module_id' => 'required|exists:company_modules,id',
'order_id' => ['required', Rule::exists('orders', 'id')],
'company_module_id' => ['required', Rule::exists('company_modules', 'id')],
];
}
@@ -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
{
@@ -107,8 +110,17 @@ class AssignPackingListOrderLogic extends AbstractControllerLogic
*/
public function logic(Request $request) : JsonResponse
{
// $warehouse_packing_list = $this->fetchesPackingList->execute([
// 'id' => $request->route('id'),
// 'type' => PackingListType::WAREHOUSE_RECEIVE_LIST
// ]);
$packing_list = $this->fetchesPackingList->execute([
'id' => $request->route('id'),
]);
$warehouse_packing_list = $this->fetchesPackingList->execute([
'id' => $request->route('id'),
'reference' => $packing_list->reference,
'type' => PackingListType::WAREHOUSE_RECEIVE_LIST
]);
@@ -153,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;
}
}
@@ -4,15 +4,19 @@ namespace App\Classes\Modules\PackingLists\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Jobs\Commands\V2\YD\FetchPackingListsFromYdPortalV2CommandJob;
use App\Classes\Modules\PackingLists\Services\DeletesPackingList;
use App\Classes\Modules\PackingLists\Services\FetchesPackingList;
use App\Classes\Modules\PackingLists\Services\Packages\FetchesPackage;
use App\Classes\Modules\PackingLists\Standards\Rules\CanDeletePackingList;
use App\Classes\ValueObjects\Constants\PackingListType;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\PackingList;
use Carbon\Carbon;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
class DeletePackingListByPackageIdLogic extends AbstractControllerLogic
{
@@ -69,13 +73,48 @@ class DeletePackingListByPackageIdLogic extends AbstractControllerLogic
$packingList = PackingList::where('reference', $packingList->reference)->get();
foreach ($packingList as $singlePL) {
$invoice_transaction = $singlePL->transactions()->where('transactions.type', TransactionType::SHIPPING_INVOICE)->get();
if($invoice_transaction->count() > 0){
throw new ErrorException('Effective 2026, packages cannot be deleted if a related invoice has already been generated. Please delete the invoice first before proceeding with this action. Please contact IT support for more information.');
}
}
$childPackingList = PackingList::where('owner_type', PackingList::class)->whereIn('owner_id', $packingList->pluck('id'))->get();
$packingList->each->delete();
$childPackingList->each->delete();
$jobs1 = $this->fetchPackingListsFromYdPortalV2CommandJobs();
foreach ($jobs1 as $index => $job) {
dispatch($job)->delay(now()->addSeconds($index * 2));
}
return $this->response([]);
}
private function fetchPackingListsFromYdPortalV2CommandJobs()
{
$jobs = [];
$count = 0;
// Always take last 10 days INCLUDING today
for ($x = 0; $x < 10; $x++) {
$startDate = Carbon::today()->subDays($x)->startOfDay();
$endDate = Carbon::today()->subDays($x - 1)->startOfDay();
$jobs[] = new FetchPackingListsFromYdPortalV2CommandJob($startDate, $endDate);
Log::info('Dispatched FetchPackingListsFromYdPortalV2CommandJob for start date: ' . $startDate . ', end date: ' . $endDate);
$count++;
}
Log::info('Total FetchPackingListsFromYdPortalV2CommandJob dispatched: ' . $count);
return $jobs;
}
}
@@ -0,0 +1,56 @@
<?php
namespace App\Classes\Modules\PackingLists\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\PackingLists\Services\ListsPackingLists;
use App\Classes\Modules\PackingLists\Standards\Rules\CanListPackingLists;
use App\Http\Resources\PackingListForWarehouseResource;
use ErrorException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class ListPackingListsForWarehouseLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Retrieved PackingLists for Warehouse',
'message' => 'You have successfully retrieved a list of PackingLists for warehouse'
];
}
/** @var CanListPackingLists */
private $canListPackingLists;
/** @var ListsPackingLists */
private $listsPackingLists;
/**
* ListPackingListsForWarehouseLogic constructor.
* @param CanListPackingLists $canListPackingLists
* @param ListsPackingLists $listsPackingLists
*/
public function __construct(CanListPackingLists $canListPackingLists, ListsPackingLists $listsPackingLists)
{
$this->canListPackingLists = $canListPackingLists;
$this->listsPackingLists = $listsPackingLists;
}
/**
* @param Request $request
* @return JsonResponse
* @throws ErrorException
*/
public function logic(Request $request) : JsonResponse
{
$this->canListPackingLists->passes();
$query = $this->listsPackingLists->execute($this->listsPackingLists->deserializeFilters($request->input('filters')));
return $this->collectionResponse(PackingListForWarehouseResource::collection($query));
}
}

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