Compare commits

..

189 Commits

Author SHA1 Message Date
Martin Kiragu 0b30357568 selenium json file 2023-03-03 07:23:50 +03:00
Martin Kiragu 034e9da69e conception acceptance test configurations 2023-03-03 07:23:13 +03:00
Martin Kiragu 4b25764fb3 Merge branch 'development' of gitlab.com:CIEFWorldwideSdnBhd/shipping-portal into development 2023-03-03 06:29:16 +03:00
Martin Kiragu 422a0af465 move all UI related tests to codeception tets 2023-03-03 06:28:45 +03:00
edmondlang c73d65343b Merge branch 'update-create-dilivery-address' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into development 2023-03-02 23:38:33 +08:00
edmondlang 9e5784b6ec update force create order delivery address 2023-03-02 23:38:12 +08:00
edmondlang 9a863e2143 Merge branch 'update-create-dilivery-address' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into development 2023-03-02 23:18:12 +08:00
edmondlang 8024865d5d create order with force enter billing address 2023-03-02 23:17:42 +08:00
edmondlang 579dd02ebf update allow user to edit billing address 2023-03-02 22:20:08 +08:00
Martin Kiragu 66abe81e73 Merge remote-tracking branch 'origin/development' into development 2023-03-02 12:24:07 +03:00
Martin Kiragu ca178e1b31 add HasFactory facade to Users model 2023-03-02 12:23:49 +03:00
edmondlang e52a27aedb Merge branch 'master' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into development 2023-03-02 17:06:55 +08:00
edmondlang 1e6ac000ac fix invoice command 2023-03-02 17:06:29 +08:00
Martin Kiragu 6c2c28fb31 rerun UI build on the test job 2023-03-02 11:58:09 +03:00
Martin Kiragu 049da351ef Merge remote-tracking branch 'origin/development' into development 2023-03-02 11:28:03 +03:00
Martin Kiragu 0ce8709f70 reduplicate mysql service for unit test job 2023-03-02 11:27:25 +03:00
edmondlang 1e5609bb1b Merge branch 'master' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into development 2023-03-02 16:26:11 +08:00
edmondlang 0802198c97 update allow user to edit billing address 2023-03-02 16:25:51 +08:00
edmondlang 8e7970a925 Merge branch 'master' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into development 2023-03-02 16:16:23 +08:00
edmondlang 2421f6dcf0 allow user to edit billing address 2023-03-02 16:15:51 +08:00
Martin Kiragu 06b2c5166d remove dependencies test and add reruns 2023-03-02 11:01:10 +03:00
Martin Kiragu 6ba3b873a2 add building assets and dependencies test 2023-03-02 10:47:45 +03:00
Martin Kiragu 623fb1609b switch dependencies with an installation rerun 2023-03-02 10:29:40 +03:00
Martin Kiragu 24be20a60d switch dependencies with an installation rerun 2023-03-02 10:17:30 +03:00
Martin Kiragu 3535201481 remove test dependency injection 2023-03-02 10:04:09 +03:00
Martin Kiragu cdefd48d26 remove pdo echo 2023-03-02 09:50:44 +03:00
Martin Kiragu 45fbcf1447 pdo addition 2023-03-02 09:42:49 +03:00
Martin Kiragu 53805f3608 add database test 2023-03-02 09:20:02 +03:00
Martin Kiragu 99e90ad357 update remove pdo and mysql extension 2023-03-02 09:03:28 +03:00
Martin Kiragu 5edb9b5cfe add node and gulp builds 2023-03-02 08:58:23 +03:00
Martin Kiragu 86a5a3b2d9 add migration and seeder 2023-03-02 08:37:38 +03:00
Martin Kiragu a6590e3b81 test set up on the set up job 2023-03-02 08:31:14 +03:00
Martin Kiragu b1bb2b9f33 add .env.example to the env file 2023-03-02 08:25:04 +03:00
omair saleh 127a13c59c Merge branch 'dillon/crm-create-task' into 'master'
Add new tasks post payment into CRM + Add task append to lead

See merge request CIEFWorldwideSdnBhd/shipping-portal!146
2023-03-02 00:25:56 +00:00
Dillon 9318e7471f Merge branch 'dillon/crm-create-task' into development 2023-03-01 12:36:15 +08:00
Dillon ba2bd59b04 Add new tasks post payment into CRM + Add task append to lead 2023-03-01 12:29:47 +08:00
Martin Maina Kiragu e19ba1c9f3 Merge branch 'feature/TDD' into 'development'
Feature/tdd

See merge request CIEFWorldwideSdnBhd/shipping-portal!140
2023-03-01 03:54:54 +00:00
edmondlang 8cffae079b test approve invoice 2023-02-28 14:46:04 +08:00
edmondlang 594b25b71b temporary disable all other cron on development server 2023-02-28 14:29:04 +08:00
edmondlang d142a86683 Merge branch 'master' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into development 2023-02-28 14:23:11 +08:00
edmondlang 981ec9bbeb approve invoice function for testing 2023-02-28 14:22:32 +08:00
edmondlang b293542321 disable user to generate invoice on web link 2023-02-28 14:12:24 +08:00
Omair Saleh 18593cb959 fix duplicated invoices 2023-02-28 12:58:53 +08:00
Omair Saleh e2d1426d19 fix duplicated invoices 2023-02-28 12:58:18 +08:00
Omair Saleh d31deeb112 fix duplicated invoices 2023-02-28 12:50:52 +08:00
Omair Saleh d61a0c2104 fix duplicated invoices 2023-02-28 12:03:17 +08:00
edmondlang cbda7aa6ba delete duplicated invoice 2023-02-27 19:29:24 +08:00
edmondlang b5027c81f8 delete duplicated invoice 2023-02-27 19:26:26 +08:00
edmondlang e83e53a1d7 delete duplicated invoice 2023-02-27 19:21:25 +08:00
edmondlang 4058456797 delete duplicated invoice 2023-02-27 19:18:43 +08:00
edmondlang d03e34a1f4 delete duplicated invoice 2023-02-27 19:15:36 +08:00
edmondlang 5d79d5808a delete duplicated invoice for order marking 165005587 only 2023-02-27 16:17:47 +08:00
edmondlang 935f3e9bf5 Merge branch 'master' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into development 2023-02-27 15:59:49 +08:00
edmondlang e4464c3eb4 Merge branch 'master' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal 2023-02-27 15:57:08 +08:00
edmondlang e227abac59 check duplicated invoice 2023-02-27 15:56:29 +08:00
omair saleh 997a9da276 Merge branch 'dillon/crm-integration' into 'master'
Dockerising shipping-portal usign the same setting from exchange-2.0.

See merge request CIEFWorldwideSdnBhd/shipping-portal!145
2023-02-27 05:14:32 +00:00
edmondlang a810fcad59 show duplicated invoice 2023-02-27 13:07:54 +08:00
edmondlang 9f4b04b9fb update show duplicated invoice 2023-02-27 12:57:46 +08:00
edmondlang 085692485a show duplicated invoice 2023-02-27 12:42:35 +08:00
edmondlang dedd6464f4 Merge branch 'master' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into development 2023-02-24 18:08:22 +08:00
edmondlang 38aba65178 Merge branch 'master' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into development 2023-02-23 14:53:41 +08:00
Dillon 091119c244 Merge branch 'dillon/crm-integration' into development 2023-02-22 18:09:51 +08:00
Dillon 2b20160334 User feedback fix and enhancement on crm integration 2023-02-22 18:09:34 +08:00
Dillon 4d095b5459 Merge branch 'development' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into development 2023-02-22 17:10:08 +08:00
Dillon 1c50181132 Merge branch 'dillon/crm-integration' into development 2023-02-22 10:37:19 +08:00
Dillon 8a29f10ef3 Include company name and phone number into lead during regirstration 2023-02-22 10:36:35 +08:00
edmondlang 9e26c470f5 Merge branch 'master' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into development 2023-02-21 23:54:08 +08:00
edmondlang 4c0bf164a0 Merge branch 'master' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into development 2023-02-21 23:43:18 +08:00
edmondlang 8ab7f72e90 reverse invoice search function 2023-02-21 23:42:00 +08:00
edmondlang 5772e30575 Merge branch 'master' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into development 2023-02-21 23:41:19 +08:00
edmondlang 4b2daa62d7 test auto generate invoice function 2023-02-21 17:32:20 +08:00
edmondlang 2bd8700a61 Merge branch 'auto-generate-invoice' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into development 2023-02-21 16:50:42 +08:00
edmondlang ad7e77c169 Merge branch 'master' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into development 2023-02-21 15:01:09 +08:00
edmondlang e95c41bd3e Merge branch 'master' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into development 2023-02-20 19:51:11 +08:00
edmondlang 903269e714 Merge branch 'master' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into development 2023-02-20 18:22:48 +08:00
edmondlang 4120a50559 commented on the web routes and api routes to test on the crm 2023-02-18 23:09:24 +08:00
Dillon 88b31f2d3f Merge branch 'dillon/crm-integration' into development 2023-02-18 21:08:08 +08:00
Dillon cb8d808562 done debugging, undo changes 2023-02-18 21:07:50 +08:00
Dillon a2f9bf83ce Merge branch 'dillon/crm-integration' into development 2023-02-18 20:29:57 +08:00
Dillon 130aca262a debug 2023-02-18 20:29:49 +08:00
Dillon dd2ac4c966 Merge branch 'dillon/crm-integration' into development 2023-02-18 20:09:08 +08:00
Dillon 06ab1be86e debug 2023-02-18 20:08:53 +08:00
Dillon c88f6890d6 Merge branch 'dillon/crm-integration' into development 2023-02-17 09:24:38 +08:00
Dillon 53d076c7e5 CRM integration MVP Phase 1 - minor cleanup 2023-02-17 09:24:13 +08:00
Dillon 1b84ccf60e CRM integration MVP Phase 1 2023-02-17 09:06:18 +08:00
edmondlang bf4b3fa97f Merge branch 'master' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into development 2023-02-16 23:13:22 +08:00
edmondlang 6bcea5a8f1 Merge branch 'master' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into development 2023-02-16 16:53:12 +08:00
Martin Maina Kiragu 2704ec1665 Merge branch 'feature/pipeline' into 'development'
Update .gitlab-ci.yml file

See merge request CIEFWorldwideSdnBhd/shipping-portal!144
2023-02-13 07:28:57 +00:00
Martin Maina Kiragu 0c636d2156 remove spaces on Export warehouse service 2023-02-13 05:17:03 +00:00
Martin Kiragu 1270ba3f43 delete the code ide-helper file 2023-02-13 08:08:06 +03:00
Martin Kiragu f2c32c5024 fix more spaces 2023-02-13 08:07:11 +03:00
Martin Kiragu ccb3bde260 clean up spaces on my branch 2023-02-13 08:01:23 +03:00
Martin Kiragu a7eb14c2b7 Merge branch 'feature/TDD' of gitlab.com:CIEFWorldwideSdnBhd/shipping-portal into feature/TDD 2023-02-13 07:37:01 +03:00
Martin Kiragu abac96b1e5 revert all models changes 2023-02-13 07:36:40 +03:00
Martin Maina Kiragu ecb48c8897 Merge branch 'master' into 'feature/TDD'
# Conflicts:
#   config/app.php
2023-02-13 04:24:32 +00:00
Martin Maina Kiragu 2686229a0f Merge branch 'master' into 'feature/pipeline'
# Conflicts:
#   config/app.php
2023-02-13 04:12:19 +00:00
Martin Kiragu 558fa7ae52 remove migration and seeder 2023-02-13 06:49:08 +03:00
Martin Kiragu 88e2136c07 add cp .env 2023-02-13 06:47:58 +03:00
Martin Kiragu 70cdcded9b generate key, run migration and database seeder 2023-02-13 06:40:02 +03:00
Martin Kiragu 4022b640f9 test by rerunning the install 2023-02-13 06:31:05 +03:00
Martin Kiragu 0d780074b8 vender test to php 2023-02-13 06:23:53 +03:00
Martin Kiragu 078f675a7f add codeception and change vender test to php 2023-02-13 06:20:42 +03:00
Martin Kiragu 2b48a86f98 comment the Meneses\LaravelMpdf\LaravelMpdfServiceProvider 2023-02-13 06:11:41 +03:00
Martin Maina Kiragu 19f3aa18fc Update .gitlab-ci.yml file
add libzip
2023-02-13 03:07:34 +00:00
Martin Maina Kiragu 2b4c932fc8 Update .gitlab-ci.yml file
add libzip
2023-02-13 03:05:29 +00:00
Martin Maina Kiragu 89f0ca651a Update .gitlab-ci.yml file
add libzip
2023-02-13 03:01:07 +00:00
Martin Maina Kiragu c9fc5938c6 Update .gitlab-ci.yml file
add libzip
2023-02-13 02:55:41 +00:00
Martin Maina Kiragu 2ad8235c1b Update .gitlab-ci.yml file
add libzip
2023-02-13 02:53:22 +00:00
Martin Maina Kiragu dbf8301cb9 Update .gitlab-ci.yml file
add libzip
2023-02-13 02:49:27 +00:00
Martin Maina Kiragu 7d582c6bca Update .gitlab-ci.yml file
add libzip
2023-02-13 02:48:30 +00:00
Martin Maina Kiragu 3c4b6afcb2 Update .gitlab-ci.yml file
add zip
2023-02-13 02:46:21 +00:00
Martin Maina Kiragu e4bc56d188 Update .gitlab-ci.yml file 2023-02-13 02:44:10 +00:00
Martin Maina Kiragu 9a448d5a3d Update .gitlab-ci.yml file 2023-02-13 02:41:24 +00:00
Martin Maina Kiragu 5c1074b244 Update .gitlab-ci.yml file 2023-02-13 02:38:49 +00:00
Martin Maina Kiragu 49fcdfd89e Update .gitlab-ci.yml file 2023-02-13 02:36:51 +00:00
Martin Maina Kiragu c900759234 Update .gitlab-ci.yml file 2023-02-13 02:30:15 +00:00
Martin Maina Kiragu cd3b47ab1a Update .gitlab-ci.yml file 2023-02-13 02:26:31 +00:00
Martin Maina Kiragu c5f95cdf61 Update .gitlab-ci.yml file 2023-02-13 02:22:31 +00:00
Martin Maina Kiragu cc428a92b8 Update .gitlab-ci.yml file 2023-02-13 02:08:09 +00:00
Martin Maina Kiragu 97bac45612 Update .gitlab-ci.yml file 2023-02-13 02:03:30 +00:00
Martin Maina Kiragu 8048396a88 Update .gitlab-ci.yml file 2023-02-13 01:59:14 +00:00
Martin Maina Kiragu 400ec31235 Update .gitlab-ci.yml file 2023-02-13 01:54:53 +00:00
Martin Maina Kiragu 4d9346c62c Update .gitlab-ci.yml file 2023-02-13 01:49:47 +00:00
Martin Maina Kiragu 94fd2069e8 Update .gitlab-ci.yml file 2023-02-13 01:43:41 +00:00
Martin Maina Kiragu 1f401eb347 Update .gitlab-ci.yml file 2023-02-13 01:39:09 +00:00
Martin Maina Kiragu 80e282bda0 Update .gitlab-ci.yml file 2023-02-13 01:35:00 +00:00
Martin Maina Kiragu 65cd6aae3c Update .gitlab-ci.yml file 2023-02-13 01:33:05 +00:00
Martin Maina Kiragu eba2a30024 Update .gitlab-ci.yml file 2023-02-13 01:28:16 +00:00
Martin Maina Kiragu c103deb2a7 Update .gitlab-ci.yml file 2023-02-13 01:25:16 +00:00
Martin Maina Kiragu dcef782587 Update .gitlab-ci.yml file
--update to php 7.4
2023-02-13 01:22:54 +00:00
Martin Maina Kiragu 10e7da4673 Update .gitlab-ci.yml file 2023-02-13 01:15:20 +00:00
Martin Kiragu faff35f241 update the pipeline with master branch code 2023-02-13 04:07:33 +03:00
Martin Maina Kiragu e2c1562f19 Update .gitlab-ci.yml file 2023-02-13 00:57:12 +00:00
Martin Maina Kiragu df35ceb798 Update .gitlab-ci.yml file 2023-02-13 00:51:03 +00:00
Martin Maina Kiragu cdb81a0bf4 Update .gitlab-ci.yml file 2023-02-13 00:48:41 +00:00
Martin Maina Kiragu f1b1955190 Update .gitlab-ci.yml file 2023-02-13 00:42:05 +00:00
Martin Maina Kiragu 860632b7a3 Update .gitlab-ci.yml file 2023-02-13 00:39:49 +00:00
Martin Maina Kiragu bde7a61fb4 Update .gitlab-ci.yml file 2023-02-13 00:35:42 +00:00
edmondlang b6600c5168 Merge branch 'update-laravelmpdf' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into development 2023-02-10 20:56:42 +08:00
edmondlang 25f38ef7fe Merge branches 'development' and 'master' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into development 2023-02-07 23:40:38 +08:00
edmondlang ddeb44b920 Merge branch 'master' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into development 2023-02-07 23:32:35 +08:00
Martin Maina Kiragu 02be710203 Update .gitlab-ci.yml file try php 7.3 2023-02-06 16:14:50 +00:00
Martin Maina Kiragu 2ffbfc9f1c Update .gitlab-ci.yml file 2023-02-06 16:12:41 +00:00
Martin Maina Kiragu 7b34f8116c Update .gitlab-ci.yml file 2023-02-06 16:09:41 +00:00
Martin Maina Kiragu 8a9b6df255 Update .gitlab-ci.yml file 2023-02-06 16:04:42 +00:00
Martin Kiragu c881dd44d6 updated action file 2023-02-06 18:38:12 +03:00
Martin Kiragu 1cfaeaf8bb add triggers 2023-02-06 18:28:46 +03:00
Martin Kiragu 914f29184d simple pipeline configuration 2023-02-06 18:23:51 +03:00
edmondlang f510d57463 Merge branch 'change-company-ui' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into development 2023-02-06 23:08:03 +08:00
edmondlang 7833c17938 Merge branch 'change-company-ui' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into development 2023-02-06 23:02:43 +08:00
edmondlang 97fdffe6eb Merge branch 'master' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into development 2023-02-06 22:46:53 +08:00
edmondlang b1f2900f1c Merge branch 'change-company-ui' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into development 2023-02-06 22:25:33 +08:00
edmondlang ddf015dc71 Revert "work on combine invoices"
This reverts commit 2a9d4fd212.
2023-02-06 22:24:48 +08:00
Sheikh Ahmer 2a9d4fd212 work on combine invoices 2023-02-04 16:36:09 +05:00
Martin Kiragu 2cacc23a38 login acceptance test 2023-02-04 10:04:34 +03:00
Martin Kiragu a7fd5a038e Merge branch 'master' of gitlab.com:CIEFWorldwideSdnBhd/shipping-portal into feature/TDD 2023-02-04 07:53:45 +03:00
edmondlang 626b31084f Merge branch 'wip-invoice-tab' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into development 2023-02-03 16:11:48 +08:00
Martin Kiragu 4f3c25d5bd Merge branch 'master' of gitlab.com:CIEFWorldwideSdnBhd/shipping-portal into feature/TDD 2023-01-29 10:51:30 +03:00
Martin Kiragu 8da942e41e updated list of all user, passwords and emails unit tests 2023-01-28 12:56:41 +03:00
edmondlang b599c8a151 Merge branch 'multi-invoice-combined-ui' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into development 2023-01-20 17:15:25 +08:00
Martin Kiragu d41f796825 fix access_token issue 2023-01-20 10:39:39 +03:00
Martin Kiragu dd612e2660 fix issues 2023-01-19 12:12:54 +03:00
Martin Kiragu c503b5e677 acceptance test set up and demo 2023-01-19 12:03:09 +03:00
Martin Kiragu 0b433cfa18 ed debug 2023-01-19 09:39:16 +03:00
Martin Kiragu 75aba8c4ac remove password related tests on auth test class 2023-01-19 09:39:16 +03:00
Martin Kiragu 81c65874a3 added the Auth tdd and a modal property autogenerator helpers 2023-01-19 09:39:15 +03:00
Martin Kiragu 79d29d9c7b Authentication TDD 2023-01-19 09:39:15 +03:00
Martin Kiragu 1e558b93af set up testig env codeception laravela and phpunit 2023-01-19 09:39:15 +03:00
edmondlang 6d3d52639e Merge branch 'multi-invoice-combined-ui' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into development 2023-01-19 00:33:37 +08:00
edmondlang a1d460aa6c Merge branch 'multi-invoice-combined-ui' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into development 2023-01-19 00:20:38 +08:00
edmondlang 5a0bc7aaea Merge branch 'multi-invoice-combined-ui' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into development
# Conflicts:
#	resources/views/pages/pdfs/shipping_invoices_combined.blade.php
2023-01-18 23:59:58 +08:00
Martin Kiragu c7962b4231 ed debug 2023-01-18 18:34:18 +03:00
Martin Kiragu d14bb39ae8 remove password related tests on auth test class 2023-01-18 09:11:30 +03:00
Martin Kiragu 5cc2f51c02 added the Auth tdd and a modal property autogenerator helpers 2023-01-18 08:17:05 +03:00
Martin Kiragu a185f73e8a Authentication TDD 2023-01-16 14:40:57 +03:00
edmondlang f9a9598210 Merge branch 'dillon/search-marking-by-email' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into development 2023-01-15 14:20:38 +08:00
edmondlang 9976ccec41 Merge branch 'ChangeCompanie' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into development 2023-01-11 22:39:58 +08:00
edmondlang 8bfb2d749a Merge branch 'dillon/multiple-invoices-combined' of gitlab.com:CIEFWorldwideSdnBhd/shipping-portal into development 2023-01-11 18:25:28 +08:00
Martin Kiragu 7bf9a570a1 set up testig env codeception laravela and phpunit 2023-01-11 12:44:32 +03:00
edmondlang b38df170e8 Merge branch 'multiple-payment-ui' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into development 2023-01-09 22:58:10 +08:00
Dillon bf38ace70c Multiple invoices into one 2023-01-07 11:51:27 +08:00
edmondlang 66c008f97e Merge branch 'master' of gitlab.com:CIEFWorldwideSdnBhd/shipping-portal into development 2023-01-03 13:49:15 +08:00
edmondlang 0298eb946f Merge branch 'master' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into activity-route-log-dev 2023-01-02 17:41:29 +08:00
edmondlang 70fb35e37c api and web route logs 2023-01-02 17:41:00 +08:00
edmondlang 1a30877ca9 activity route log dev 2022-12-31 11:53:41 +08:00
WAKOYA_KUMSA\waqo1 569a22c0db route activity log 2022-12-28 13:15:15 +03:00
Dillon 515c71daa7 Merge branch 'dillon/setup-docker-2' into dillon/crm-integration 2022-12-06 08:34:29 +08:00
Dillon a041a70d93 Merge branch 'dillon/setup-docker' into dillon/setup-docker-2 2022-11-16 11:07:30 +08:00
Dillon d4c9899120 Dockerising shipping-portal usign the same setting from exchange-2.0.
Update gitignore to include docker-compose.yml (same as exchange-2.0)
2022-11-02 05:56:06 +08:00
107 changed files with 4829 additions and 603 deletions
+4 -2
View File
@@ -10,9 +10,9 @@ LOG_LEVEL=debug
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_DATABASE=shpping_portal
DB_USERNAME=root
DB_PASSWORD=
DB_PASSWORD=root
BROADCAST_DRIVER=log
CACHE_DRIVER=file
@@ -55,3 +55,5 @@ EXCHANGE_URL=https://dev.exchange.cief-malaysia.com/
MIX_EXCHANGE_URL="${EXCHANGE_URL}"
YD_API_CODE=''
JWT_SECRET=Btj63iMEleEaww6Bb2IBECkxWn7YHPhhPFluAkg9DfcQik0qDRy6QW75ABGmPT2h
+59
View File
@@ -0,0 +1,59 @@
APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:rIar2fvNeRzQdvKOgLUg03detGDMx6ym2SYFRjawrAc=
APP_DEBUG=true
APP_URL=http://localhost
LOG_CHANNEL=stack
LOG_LEVEL=debug
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=shpping_portal
DB_USERNAME=root
DB_PASSWORD=P@ssw0rd
BROADCAST_DRIVER=log
CACHE_DRIVER=file
FILESYSTEM_DRIVER=local
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
MEMCACHED_HOST=127.0.0.1
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=null
MAIL_FROM_NAME="${APP_NAME}"
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
UNITY_APP_URL="https://unity.izyim.com"
EXCHANGE_URL=https://dev.exchange.cief-malaysia.com/
MIX_EXCHANGE_URL="${EXCHANGE_URL}"
YD_API_CODE=''
JWT_SECRET=Btj63iMEleEaww6Bb2IBECkxWn7YHPhhPFluAkg9DfcQik0qDRy6QW75ABGmPT2h
+2 -1
View File
@@ -2,6 +2,8 @@
/public/hot
/public/storage
/storage/*.key
/tests/_output
/tests/_support
/vendor
**/.idea/
.env
@@ -21,7 +23,6 @@ gox.iml
rebuild_docker.sh
docker/*
db/*
docker-compose.yml
package-lock.json
public/*
/public/*
+149
View File
@@ -0,0 +1,149 @@
image: php:7.4
stages:
- service_build
- node
- building_assets
- database
- unit_test
- acceptance_test
- code_quality
# Variables
variables:
MYSQL_ROOT_PASSWORD: root
MYSQL_USER: mysql_password
MYSQL_PASSWORD: mysql_password
MYSQL_DATABASE: shpping_portal
DB_HOST: mysql
before_script:
- apt-get update -yqq
- apt-get install -yqq
- apt-get install -y libonig-dev
- apt-get install -y libxml2-dev
- apt-get install -y libzip-dev
- apt-get install -y libgd-dev
- apt-get install -y libgd-dev
# Install PDO MySQL extension
- docker-php-ext-install pdo_mysql
#install php dependencies
- docker-php-ext-install mbstring xml zip gd
# Install composer package manager
- curl --location --output /usr/local/bin/composer https://getcomposer.org/download/latest-stable/composer.phar
- chmod +x /usr/local/bin/composer
# Install MySQL client
- apt-get install -y default-mysql-client
#install node js
- apt-get update && apt-get install -y nodejs npm
#install gulp Js
- npm install -g gulp-cli
#jobs
#buld the backend
composer_php:
stage: service_build
script:
- composer install
- cp .env.example .env
- php artisan key:generate
rules:
- if: '$CI_COMMIT_BRANCH =~ /.*/'
#build the UI
#node installation
npm:
stage: node
script:
- npm install # Install npm dependencies
rules:
- if: '$CI_COMMIT_BRANCH =~ /.*/'
#building assets
building_assets:
stage: building_assets
# dependencies:
# - npm
script:
- npm install # Install npm dependencies
- gulp build # Build assets
rules:
- if: '$CI_COMMIT_BRANCH =~ /.*/'
#mysql
database:
stage: database
services:
- name: mysql:8.0
command: [ "--default-authentication-plugin=mysql_native_password" ]
#dependencies:
# - composer_php
script:
- composer install
- cp .env.example .env
- php artisan key:generate
- php artisan migrate:fresh
- php artisan db:seed
rules:
- if: '$CI_COMMIT_BRANCH =~ /.*/'
#unit test
unit_test:
stage: unit_test
services:
- name: mysql:8.0
command: [ "--default-authentication-plugin=mysql_native_password" ]
#dependencies:
# - database
script:
- npm install # Install npm dependencies
- gulp build # Build assets
- composer install
- cp .env.example .env
- php artisan key:generate
- php artisan migrate:fresh
- php artisan db:seed
- php artisan test
rules:
- if: '$CI_COMMIT_BRANCH =~ /.*/'
#acceptance tests
acceptance_test:
stage: acceptance_test
services:
- name: mysql:8.0
command: [ "--default-authentication-plugin=mysql_native_password" ]
- selenium/standalone-chrome:latest
#dependencies:
# - database
script:
- npm install # Install npm dependencies
- gulp build # Build assets
- composer install
- cp .env.example .env
- php artisan key:generate
- php artisan migrate:fresh
- php artisan db:seed
- php artisan serve &
- vendor/bin/codecept run
artifacts:
when: always
paths:
- tests/_output
rules:
- if: '$CI_COMMIT_BRANCH =~ /.*/'
+20 -43
View File
@@ -1,62 +1,39 @@
<p align="center"><a href="https://laravel.com" target="_blank"><img src="https://raw.githubusercontent.com/laravel/art/master/logo-lockup/5%20SVG/2%20CMYK/1%20Full%20Color/laravel-logolockup-cmyk-red.svg" width="400"></a></p>
## Shipping portal documentation
<p align="center">
<a href="https://travis-ci.org/laravel/framework"><img src="https://travis-ci.org/laravel/framework.svg" alt="Build Status"></a>
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/dt/laravel/framework" alt="Total Downloads"></a>
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/v/laravel/framework" alt="Latest Stable Version"></a>
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/l/laravel/framework" alt="License"></a>
</p>
simple documentation on how to install, run, test, commit and deploy application
## About Laravel
## creating and running unit tests
Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experience to be truly fulfilling. Laravel takes the pain out of development by easing common tasks used in many web projects, such as:
Required Tools
- [Simple, fast routing engine](https://laravel.com/docs/routing).
- [Powerful dependency injection container](https://laravel.com/docs/container).
- Multiple back-ends for [session](https://laravel.com/docs/session) and [cache](https://laravel.com/docs/cache) storage.
- Expressive, intuitive [database ORM](https://laravel.com/docs/eloquent).
- Database agnostic [schema migrations](https://laravel.com/docs/migrations).
- [Robust background job processing](https://laravel.com/docs/queues).
- [Real-time event broadcasting](https://laravel.com/docs/broadcasting).
- Chromium Driver / selenium
- add running and setting selenium on all OS if possible
Laravel is accessible, powerful, and provides tools required for large, robust applications.
Required Packages :
## Learning Laravel
- laravel/legacy-factories
Laravel has the most extensive and thorough [documentation](https://laravel.com/docs) and video tutorial library of all modern web application frameworks, making it a breeze to get started with the framework.
- codeception/codeception
If you don't feel like reading, [Laracasts](https://laracasts.com) can help. Laracasts contains over 1500 video tutorials on a range of topics including Laravel, modern PHP, unit testing, and JavaScript. Boost your skills by digging into our comprehensive video library.
Or Simply Run
## Laravel Sponsors
``Composer install``
We would like to extend our thanks to the following sponsors for funding Laravel development. If you are interested in becoming a sponsor, please visit the Laravel [Patreon page](https://patreon.com/taylorotwell).
To create a unit test
### Premium Partners
``php artisan make test: Test Example --unit``
- **[Vehikl](https://vehikl.com/)**
- **[Tighten Co.](https://tighten.co)**
- **[Kirschbaum Development Group](https://kirschbaumdevelopment.com)**
- **[64 Robots](https://64robots.com)**
- **[Cubet Techno Labs](https://cubettech.com)**
- **[Cyber-Duck](https://cyber-duck.co.uk)**
- **[Many](https://www.many.co.uk)**
- **[Webdock, Fast VPS Hosting](https://www.webdock.io/en)**
- **[DevSquad](https://devsquad.com)**
- **[Curotec](https://www.curotec.com/services/technologies/laravel/)**
- **[OP.GG](https://op.gg)**
Running the tests :
## Contributing
Running a single Test
Thank you for considering contributing to the Laravel framework! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions).
`` php artisan test --filter Example``
## Code of Conduct
Running Unit tests -
In order to ensure that the Laravel community is welcoming to all, please review and abide by the [Code of Conduct](https://laravel.com/docs/contributions#code-of-conduct).
`` php artisan test ``
## Security Vulnerabilities
Running Codeception tests -
If you discover a security vulnerability within Laravel, please send an e-mail to Taylor Otwell via [taylor@laravel.com](mailto:taylor@laravel.com). All security vulnerabilities will be promptly addressed.
``vendor/bin/codecept run``
## License
The Laravel framework is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).
@@ -0,0 +1,20 @@
<?php
namespace App\Classes\General\Eloquent\Filters;
use Illuminate\Database\Eloquent\Builder;
class OwnerType implements Filter
{
/**
* @param Builder $builder
* @param $value
* @return Builder|mixed
*/
public static function apply(Builder $builder, $value)
{
return $builder->where('owner_type', $value);
}
}
@@ -0,0 +1,33 @@
<?php
namespace App\Classes\Jobs;
use App\Classes\Modules\PerfexCRM\Processors\CreatePerfexCRMLeadProcessor;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CreateLeadPerfexCRMObject;
class CreatePerfexCRMCustomer implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/** @var CreateLeadPerfexCRMObject */
private $createLeadPerfexCRMObject;
/**
* CreatePerfexCRMCustomer constructor.
* @param CreateLeadPerfexCRMObject $createLeadPerfexCRMObject
*/
public function __construct(CreateLeadPerfexCRMObject $createLeadPerfexCRMObject)
{
$this->createLeadPerfexCRMObject = $createLeadPerfexCRMObject;
}
public function handle()
{
(App()->make(CreatePerfexCRMLeadProcessor::class))->execute($this->createLeadPerfexCRMObject);
}
}
@@ -0,0 +1,42 @@
<?php
namespace App\Classes\Jobs;
use App\Classes\Modules\PerfexCRM\Processors\CreatePerfexCRMTaskProcessor;
use App\Classes\Modules\PerfexCRM\Services\FetchesPerfexCRMLead;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CreateTaskPerfexCRMObject;
class CreatePerfexCRMSingleTask implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/** @var FetchesPerfexCRMLead */
private $fetchesPerfexCRMLead;
/** @var CreateTaskPerfexCRMObject */
private $createTaskPerfexCRMObject;
/**
* CreatePerfexCRMSingleTask constructor.
* @param CreateTaskPerfexCRMObject $createTaskPerfexCRMObject
*/
public function __construct(CreateTaskPerfexCRMObject $createTaskPerfexCRMObject)
{
$this->createTaskPerfexCRMObject = $createTaskPerfexCRMObject;
}
public function handle()
{
$lead = (App()->make(FetchesPerfexCRMLead::class))->execute($this->createTaskPerfexCRMObject->getEmail());
if(!is_null($lead))
{
$this->createTaskPerfexCRMObject->setLeadId($lead->id);
(App()->make(CreatePerfexCRMTaskProcessor::class))->execute($this->createTaskPerfexCRMObject);
}
}
}
+33
View File
@@ -0,0 +1,33 @@
<?php
namespace App\Classes\Jobs;
use App\Classes\Modules\PerfexCRM\Processors\InitializePerfexCRMProcessor;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\InitialPerfexCRMObject;
class InitializePerfexCRM implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/** @var InitialPerfexCRMObject */
private $initialPerfexCRMObject;
/**
* InitializePerfexCRM constructor.
* @param InitialPerfexCRMObject $initialPerfexCRMObject
*/
public function __construct(InitialPerfexCRMObject $initialPerfexCRMObject)
{
$this->initialPerfexCRMObject = $initialPerfexCRMObject;
}
public function handle()
{
(App()->make(InitializePerfexCRMProcessor::class))->execute($this->initialPerfexCRMObject);
}
}
+33
View File
@@ -0,0 +1,33 @@
<?php
namespace App\Classes\Jobs;
use App\Classes\Modules\PerfexCRM\Processors\UpdatePerfexCRMProcessor;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\UpdatePerfexCRMObject;
class UpdatePerfexCRM implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/** @var UpdatePerfexCRMObject */
private $updatePerfexCRMObject;
/**
* UpdatePerfexCRM constructor.
* @param UpdatePerfexCRMObject $updatePerfexCRMObject
*/
public function __construct(UpdatePerfexCRMObject $updatePerfexCRMObject)
{
$this->updatePerfexCRMObject = $updatePerfexCRMObject;
}
public function handle()
{
(App()->make(UpdatePerfexCRMProcessor::class))->execute($this->updatePerfexCRMObject);
}
}
@@ -8,23 +8,27 @@ use App\Classes\General\Services\GeneratesInitials;
use App\Classes\Modules\Accounts\Processors\AuthenticationProcessor;
use App\Classes\Modules\Accounts\Processors\CreateUserProcessor;
use App\Classes\Modules\Accounts\Processors\GenerateEmailVerificationAttemptProcessor;
use App\Classes\Modules\Companies\DataTransferObjects\CompanyConnectionObject;
use App\Classes\Modules\Companies\Processors\AssignEmployeeProcessor;
use App\Classes\Modules\Companies\Processors\CreateCompanyProcessor;
use App\Classes\Modules\Companies\Processors\CreateCompanyModuleProcessor;
use App\Classes\Modules\Companies\DataTransferObjects\EmploymentObject;
use App\Classes\Modules\Companies\Services\ApprovesCompanyConnection;
use App\Classes\Modules\Companies\Services\CreatesCompanyConnection;
use App\Classes\Modules\Companies\Services\FetchesCompanyModule;
use App\Classes\Modules\Contacts\DataTransferObjects\ContactObject;
use App\Classes\Modules\Contacts\Processors\CreateContactProcessor;
use App\Classes\Modules\PerfexCRM\Processors\CreatePerfexCRMLeadProcessor;
use App\Classes\Modules\Documents\Processors\UploadIdentityDocumentProcessor;
use App\Classes\Modules\Companies\DataTransferObjects\CompanyConnectionObject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CreateLeadPerfexCRMObject;
use App\Classes\Modules\Companies\DataTransferObjects\EmploymentObject;
use App\Classes\Modules\Contacts\DataTransferObjects\ContactObject;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\BusinessType;
use App\Classes\ValueObjects\Constants\CompanyType;
use App\Classes\ValueObjects\Constants\RoleTypes;
use App\Classes\Jobs\CreatePerfexCRMCustomer;
use App\Models\Company;
use App\Models\CompanyModule;
use App\Models\User;
@@ -80,6 +84,9 @@ class CreateCustomerLogic extends AbstractControllerLogic
/** @var FetchesCompanyModule */
private $fetchesCompanyModule;
/** @var CreatePerfexCRMLeadProcessor */
private $createPerfexCRMLeadProcessor;
/**
* CreateCustomerLogic constructor.
* @param CreateUserProcessor $createUserProcessor
@@ -93,8 +100,9 @@ class CreateCustomerLogic extends AbstractControllerLogic
* @param AuthenticationProcessor $authenticationProcessor
* @param GenerateEmailVerificationAttemptProcessor $generateEmailVerificationAttemptProcessor
* @param FetchesCompanyModule $fetchesCompanyModule
* @param CreatePerfexCRMLeadProcessor $createPerfexCRMLeadProcessor
*/
public function __construct(CreateUserProcessor $createUserProcessor, CreateCompanyProcessor $createCompanyProcessor, CreateCompanyModuleProcessor $createCompanyModuleProcessor, CreateContactProcessor $createContactProcessor, CreatesCompanyConnection $createsCompanyConnection, ApprovesCompanyConnection $approvesCompanyConnection, AssignEmployeeProcessor $assignEmployeeProcessor, UploadIdentityDocumentProcessor $uploadIdentityDocumentProcessor, AuthenticationProcessor $authenticationProcessor, GenerateEmailVerificationAttemptProcessor $generateEmailVerificationAttemptProcessor, FetchesCompanyModule $fetchesCompanyModule)
public function __construct(CreateUserProcessor $createUserProcessor, CreateCompanyProcessor $createCompanyProcessor, CreateCompanyModuleProcessor $createCompanyModuleProcessor, CreateContactProcessor $createContactProcessor, CreatesCompanyConnection $createsCompanyConnection, ApprovesCompanyConnection $approvesCompanyConnection, AssignEmployeeProcessor $assignEmployeeProcessor, UploadIdentityDocumentProcessor $uploadIdentityDocumentProcessor, AuthenticationProcessor $authenticationProcessor, GenerateEmailVerificationAttemptProcessor $generateEmailVerificationAttemptProcessor, FetchesCompanyModule $fetchesCompanyModule, CreatePerfexCRMLeadProcessor $createPerfexCRMLeadProcessor)
{
$this->createUserProcessor = $createUserProcessor;
$this->createCompanyProcessor = $createCompanyProcessor;
@@ -107,6 +115,7 @@ class CreateCustomerLogic extends AbstractControllerLogic
$this->authenticationProcessor = $authenticationProcessor;
$this->generateEmailVerificationAttemptProcessor = $generateEmailVerificationAttemptProcessor;
$this->fetchesCompanyModule = $fetchesCompanyModule;
$this->createPerfexCRMLeadProcessor = $createPerfexCRMLeadProcessor;
}
/**
@@ -146,6 +155,17 @@ class CreateCustomerLogic extends AbstractControllerLogic
$this->uploadIdentityDocumentProcessor->execute($request, $company);
if(config('perfexcrm.is_enabled') == 'true'){
// $this->createPerfexCRMLeadProcessor->execute($request);
$createLeadPerfexCRMObject = new CreateLeadPerfexCRMObject(
$request->input('name'),
$request->input('email'),
$request->input('phone'),
$request->input('type') === CompanyType::COMPANY_BUSINESS ? $request->input('company_name') : $request->input('name')
);
CreatePerfexCRMCustomer::dispatch($createLeadPerfexCRMObject);
}
// $this->generateEmailVerificationAttemptProcessor->execute($user);
return $this->response($this->authenticationProcessor->execute($request));
@@ -0,0 +1,86 @@
<?php
namespace App\Classes\Modules\Addresses\ControllersLogic;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Addresses\Services\CreatesAddress;
use App\Classes\Modules\Addresses\Standards\Rules\CanCreateAddress;
use App\Classes\Modules\Addresses\DataTransferObjects\AddressObject;
use App\Classes\Modules\Addresses\Services\FetchesAddress;
use App\Classes\Modules\Companies\Services\FetchesCompanyModule;
use App\Classes\ValueObjects\Constants\AddressType;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Http\Resources\AddressResource;
use App\Models\Address;
use App\Models\CompanyModule;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class CreateBillingAddressLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Created Billing Address',
'message' => 'You have successfully created a new Billing Address'
];
}
/** @var CanCreateAddress */
private $canCreateAddress;
/** @var FetchesCompanyModule */
private $fetchesCompanyModule;
/** @var CreatesAddress */
private $createsAddress;
/** @var FetchesAddress */
private $fetchesAddress;
/**
* CreateAddressLogic constructor.
* @param CanCreateAddress $canCreateAddress
* @param FetchesCompanyModule $fetchesCompanyModule
* @param CreatesAddress $createsAddress
* @param FetchesAddress $fetchesAddress
*/
public function __construct(CanCreateAddress $canCreateAddress, FetchesCompanyModule $fetchesCompanyModule, CreatesAddress $createsAddress, FetchesAddress $fetchesAddress)
{
$this->canCreateAddress = $canCreateAddress;
$this->fetchesCompanyModule = $fetchesCompanyModule;
$this->createsAddress = $createsAddress;
$this->fetchesAddress = $fetchesAddress;
}
/**
* @param Request $request
* @return JsonResponse
* @throws \App\Classes\Exceptions\AccessForbiddenException
* @throws \App\Classes\Exceptions\MalformedRequestException
* @throws \App\Classes\Exceptions\RequestValidationException
*/
public function logic(Request $request) : JsonResponse
{
$companyModule = $this->fetchesCompanyModule->execute(['id' => $request->input('company_module_id')]);
$billingAddressInputed = $this->fetchesAddress->execute(['id' => $request->input('billing_address_id')]);
if ($billingAddressInputed->type !== AddressType::BILLING || $billingAddressInputed->id !== $companyModule->addresses->where('type', AddressType::BILLING)->first()->id) {
// delete all current billing address
Address::where('owner_type', CompanyModule::class)->where('owner_id', $request->input('company_module_id'))->where('type', AddressType::BILLING)->delete();
// create new billing addrress
$billingAddress = new AddressObject($billingAddressInputed->street_one, $billingAddressInputed->street_two, $billingAddressInputed->country_id, $billingAddressInputed->state_id, $billingAddressInputed->district_id, $billingAddressInputed->postcode, AddressType::BILLING, ApprovalStatus::APPROVED, $billingAddressInputed->reference);
$this->canCreateAddress->passes($billingAddress);
$this->createsAddress->execute($companyModule, $billingAddress);
}
return $this->resourceResponse(new AddressResource($billingAddressInputed));
}
}
@@ -5,7 +5,6 @@ namespace App\Classes\Modules\Exports\Services;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\PackingListType;
use App\Models\Order;
use App\Models\State;
use Maatwebsite\Excel\Concerns\Exportable;
use Maatwebsite\Excel\Concerns\FromQuery;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
@@ -32,10 +31,8 @@ class ExportsWarehousePackingList implements FromQuery, WithHeadings, WithHeadin
*/
public function query()
{
$johor_state_id = State::where('name', 'johor')->first()->id;
return Order::whereHas('addresses', function($address) use ($johor_state_id){
$address->where('status', ApprovalStatus::APPROVED)->where('state_id', $johor_state_id);
return Order::whereHas('addresses', function($address) {
$address->where('status', ApprovalStatus::APPROVED);
})->whereHas('packingLists', function($packingLists) {
$packingLists->where('type', PackingListType::SHIPPING_PACKING_LIST)->whereDoesntHave('transports');
});
@@ -4,13 +4,19 @@ namespace App\Classes\Modules\Orders\ControllersLogic;
use App\Classes\Exceptions\RequestValidationException;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Addresses\DataTransferObjects\AddressObject;
use App\Classes\Modules\Addresses\Services\CreatesAddress;
use App\Classes\Modules\Addresses\Services\FetchesAddress;
use App\Classes\Modules\Companies\Services\FetchesCompany;
use App\Classes\Modules\Companies\Services\FetchesCompanyModule;
use App\Classes\Modules\Orders\Processors\CreateOrderProcessor;
use App\Classes\Modules\Orders\Services\GeneratesOrderNumber;
use App\Classes\ValueObjects\Constants\AddressType;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\WarehouseReferences;
use App\Http\Resources\OrderResource;
use App\Classes\Modules\Addresses\Standards\Rules\CanCreateAddress;
use App\Models\Address;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
@@ -39,6 +45,12 @@ class CreateOrderLogic extends AbstractControllerLogic
/** @var GeneratesOrderNumber */
private $generatesOrderNumber;
/** @var CreatesAddress */
private $createsAddress;
/** @var CanCreateAddress */
private $canCreateAddress;
/**
* CreateOrderLogic constructor.
* @param FetchesCompany $fetchesCompany
@@ -46,14 +58,18 @@ class CreateOrderLogic extends AbstractControllerLogic
* @param CreateOrderProcessor $createOrderProcessor
* @param FetchesCompanyModule $fetchesCompanyModule
* @param GeneratesOrderNumber $generatesOrderNumber
* @param CreatesAddress $createsAddress
* @param CanCreateAddress $canCreateAddress
*/
public function __construct(FetchesCompany $fetchesCompany, FetchesAddress $fetchesAddress, CreateOrderProcessor $createOrderProcessor, FetchesCompanyModule $fetchesCompanyModule, GeneratesOrderNumber $generatesOrderNumber)
public function __construct(FetchesCompany $fetchesCompany, FetchesAddress $fetchesAddress, CreateOrderProcessor $createOrderProcessor, FetchesCompanyModule $fetchesCompanyModule, GeneratesOrderNumber $generatesOrderNumber, CreatesAddress $createsAddress, CanCreateAddress $canCreateAddress)
{
$this->fetchesCompany = $fetchesCompany;
$this->fetchesAddress = $fetchesAddress;
$this->createOrderProcessor = $createOrderProcessor;
$this->fetchesCompanyModule = $fetchesCompanyModule;
$this->generatesOrderNumber = $generatesOrderNumber;
$this->createsAddress = $createsAddress;
$this->canCreateAddress = $canCreateAddress;
}
@@ -66,6 +82,21 @@ class CreateOrderLogic extends AbstractControllerLogic
$originWarehouse = $this->fetchesCompanyModule->execute(['id' => $request->input('warehouse_id')]);
if ($request->input('billing_address_id')) {
$companyModule = $company->companyModules->first();
$billingAddressInputed = $this->fetchesAddress->execute(['id' => $request->input('billing_address_id')]);
if ($billingAddressInputed->type !== AddressType::BILLING || $billingAddressInputed->id !== $companyModule->addresses->where('type', AddressType::BILLING)->first()->id) {
// delete all current billing address
Address::where('owner_type', CompanyModule::class)->where('owner_id', $request->input('company_module_id'))->where('type', AddressType::BILLING)->delete();
// create new billing addrress
$billingAddress = new AddressObject($billingAddressInputed->street_one, $billingAddressInputed->street_two, $billingAddressInputed->country_id, $billingAddressInputed->state_id, $billingAddressInputed->district_id, $billingAddressInputed->postcode, AddressType::BILLING, ApprovalStatus::APPROVED, $billingAddressInputed->reference);
$this->canCreateAddress->passes($billingAddress);
$this->createsAddress->execute($companyModule, $billingAddress);
}
}
if(!in_array($company->companyModules()->importers()->first()->id, WarehouseReferences::YD_EXEMPT_LIST)){
$originWarehouse = $this->fetchesCompanyModule->execute(['reference' => $originWarehouse->reference === WarehouseReferences::VT_GUANG_ZHOU ? WarehouseReferences::YD_GUANG_ZHOU : WarehouseReferences::YD_YIWU]);
}
@@ -2,7 +2,9 @@
namespace App\Classes\Modules\PackingLists\Processors;
use App\Classes\Exceptions\AccessForbiddenException;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Exceptions\RequestValidationException;
use App\Classes\Exceptions\ResourceNotFoundException;
use App\Classes\Modules\Companies\Services\FetchesCompanyModule;
use App\Classes\Modules\Orders\Services\FetchesDataFromYDPortal;
@@ -38,6 +40,7 @@ use App\Models\Order;
use App\Models\PackingList;
use App\Models\Transport;
use Carbon\Carbon;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
@@ -47,18 +50,6 @@ class FetchContainersFromYdPortalProcessor
/** @var FetchesDataFromYDPortal */
private $fetchesDataFRomYDPortal;
/** @var FetchesOrder */
private $fetchesOrder;
/** @var UpdatesContractObligation */
private $updatesContractObligations;
/** @var CreatePackingListProcessor */
private $createPackingListProcessor;
/** @var CreatePackageProcessor */
private $createPackageProcessor;
/** @var CreatesTransport */
private $createsTransport;
@@ -68,75 +59,31 @@ class FetchContainersFromYdPortalProcessor
/** @var FetchesContainer */
private $fetchesContainer;
/** @var FetchesPackingList */
private $fetchesPackingList;
/** @var FetchesCompanyModule */
private $fetchesCompanyModule;
/** @var CreateContainerProcessor */
private $createContainerProcessor;
/** @var CreatesContract */
private $unityCreateContract;
/** @var AssignContractEntityProcessor */
private $unityAssignContractEntity;
/** @var CreateContractEntityProcessor */
private $unityCreateContractEntity;
/** @var CreatesStep */
private $createsStep;
/** @var ActivateContractProcessor */
private $unityActivateContract;
/**
* FetchOrderListsFromYdPortalProcessor constructor.
* @param FetchesDataFromYDPortal $fetchesDataFRomYDPortal
* @param FetchesOrder $fetchesOrder
* @param UpdatesContractObligation $updatesContractObligations
* @param CreatePackingListProcessor $createPackingListProcessor
* @param CreatePackageProcessor $createPackageProcessor
* @param CreatesTransport $createsTransport
* @param CreatesSchedule $createsSchedule
* @param FetchesContainer $fetchesContainer
* @param FetchesPackingList $fetchesPackingList
* @param FetchesCompanyModule $fetchesCompanyModule
* @param CreateContainerProcessor $createContainerProcessor
* @param CreatesContract $unityCreateContract
* @param AssignContractEntityProcessor $unityAssignContractEntity
* @param CreateContractEntityProcessor $unityCreateContractEntity
* @param CreatesStep $createsStep
* @param ActivateContractProcessor $unityActivateContract
*/
public function __construct(FetchesDataFromYDPortal $fetchesDataFRomYDPortal, FetchesOrder $fetchesOrder, UpdatesContractObligation $updatesContractObligations, CreatePackingListProcessor $createPackingListProcessor, CreatePackageProcessor $createPackageProcessor, CreatesTransport $createsTransport, CreatesSchedule $createsSchedule, FetchesContainer $fetchesContainer, FetchesPackingList $fetchesPackingList, FetchesCompanyModule $fetchesCompanyModule, CreateContainerProcessor $createContainerProcessor, CreatesContract $unityCreateContract, AssignContractEntityProcessor $unityAssignContractEntity, CreateContractEntityProcessor $unityCreateContractEntity, CreatesStep $createsStep, ActivateContractProcessor $unityActivateContract)
public function __construct(FetchesDataFromYDPortal $fetchesDataFRomYDPortal, CreatesTransport $createsTransport, CreatesSchedule $createsSchedule, FetchesContainer $fetchesContainer, CreateContainerProcessor $createContainerProcessor)
{
$this->fetchesDataFRomYDPortal = $fetchesDataFRomYDPortal;
$this->fetchesOrder = $fetchesOrder;
$this->updatesContractObligations = $updatesContractObligations;
$this->createPackingListProcessor = $createPackingListProcessor;
$this->createPackageProcessor = $createPackageProcessor;
$this->createsTransport = $createsTransport;
$this->createsSchedule = $createsSchedule;
$this->fetchesContainer = $fetchesContainer;
$this->fetchesPackingList = $fetchesPackingList;
$this->fetchesCompanyModule = $fetchesCompanyModule;
$this->createContainerProcessor = $createContainerProcessor;
$this->unityCreateContract = $unityCreateContract;
$this->unityAssignContractEntity = $unityAssignContractEntity;
$this->unityCreateContractEntity = $unityCreateContractEntity;
$this->createsStep = $createsStep;
$this->unityActivateContract = $unityActivateContract;
}
/**
* @param Carbon|null $start
* @param Carbon|null $end
* @return void
* @throws \GuzzleHttp\Exception\GuzzleException
* @throws MalformedRequestException
* @throws AccessForbiddenException
* @throws RequestValidationException
*/
public function execute()
{
@@ -51,7 +51,7 @@ class FetchContainersUpdatesFromYdPortalProcessor
foreach ($containers as $container) {
$time_start = microtime(true);
$packingList = $container->packingLists()->first();
$packingList = $container->packingLists()->random();
$trackingRequest = $this->fetchesDataFRomYDPortal->clientRequest('http://www.yd-wl.com/api/ApiTracking.ashx', 'GET', [
'trakingno' => $packingList->reference
@@ -0,0 +1,63 @@
<?php
namespace App\Classes\Modules\PerfexCRM\DataTransferObjects;
use Illuminate\Http\Request;
use App\Classes\General\Interfaces\DataTransferObject;
class CreateLeadPerfexCRMObject implements DataTransferObject
{
/** @var string */
private $name;
/** @var string */
private $email;
/** @var string */
private $phone;
/** @var string */
private $companyName;
public function __construct(string $name, string $email, string $phone, string $companyName)
{
$this->name = $name;
$this->email = $email;
$this->phone = $phone;
$this->companyName = $companyName;
}
/**
* @return string
*/
public function getName(): string
{
return $this->name;
}
/**
* @return string
*/
public function getEmail(): string
{
return $this->email;
}
/**
* @return string
*/
public function getPhone(): string
{
return $this->phone;
}
/**
* @return string
*/
public function getCompanyName(): string
{
return $this->companyName;
}
}
@@ -0,0 +1,127 @@
<?php
namespace App\Classes\Modules\PerfexCRM\DataTransferObjects;
use App\Classes\General\Interfaces\DataTransferObject;
class CreateTaskPerfexCRMObject implements DataTransferObject
{
/** @var string */
private $email;
/** @var string */
private $name;
/** @var string */
private $description;
/** @var string */
private $leadId;
/** @var string */
private $milestoneId;
/** @var string */
private $projectId;
/** @var string */
private $reference;
/** @var string */
private $onTaskCompletion;
/** @var string */
private $status;
public function __construct(string $email, string $name, string $description, string $leadId, string $projectId, string $milestoneId, string $reference, string $onTaskCompletion, string $status)
{
$this->email = $email;
$this->name = $name;
$this->description = $description;
$this->leadId = $leadId;
$this->projectId = $projectId;
$this->milestoneId = $milestoneId;
$this->reference = $reference;
$this->onTaskCompletion = $onTaskCompletion;
$this->status = $status;
}
/**
* @return string
*/
public function getEmail(): string
{
return $this->email;
}
/**
* @return string
*/
public function getName(): string
{
return $this->name;
}
/**
* @return string
*/
public function getDescription(): string
{
return $this->description;
}
/**
* @return string
*/
public function getLeadId(): string
{
return $this->leadId;
}
public function setLeadId(string $leadId)
{
$this->leadId = $leadId;
}
/**
* @return string
*/
public function getProjectId(): string
{
return $this->projectId;
}
/**
* @return string
*/
public function getMilestoneId(): string
{
return $this->milestoneId;
}
/**
* @return string
*/
public function getReference(): string
{
return $this->reference;
}
/**
* @return string
*/
public function getOnTaskCompletion(): string
{
return $this->onTaskCompletion;
}
/**
* @return string
*/
public function getStatus(): string
{
return $this->status;
}
}
@@ -0,0 +1,99 @@
<?php
namespace App\Classes\Modules\PerfexCRM\DataTransferObjects;
use Illuminate\Http\Request;
use App\Classes\General\Interfaces\DataTransferObject;
class CustomerContactObject implements DataTransferObject
{
/** @var int */
private $customerId;
/** @var string */
private $firstname;
/** @var string */
private $lastname;
/** @var string */
private $email;
/** @var string */
private $password;
/** @var string */
private $isPrimary;
/** @var string */
private $sendSetPasswordEmail;
public function __construct(string $customerId, string $firstname, string $lastname, string $email, string $password, string $isPrimary, string $sendSetPasswordEmail)
{
$this->customerId = $customerId;
$this->firstname = $firstname;
$this->lastname = $lastname;
$this->email = $email;
$this->password = $password;
$this->isPrimary = $isPrimary;
$this->sendSetPasswordEmail = $sendSetPasswordEmail;
}
/**
* @return int
*/
public function getCustomerId(): int
{
return $this->customerId;
}
/**
* @return string
*/
public function getFirstName(): string
{
return $this->firstname;
}
/**
* @return string
*/
public function getLastName(): string
{
return $this->lastname;
}
/**
* @return string
*/
public function getEmail(): string
{
return $this->email;
}
/**
* @return string
*/
public function getPassword(): string
{
return $this->password;
}
/**
* @return string
*/
public function getIsPrimary(): string
{
return $this->isPrimary;
}
/**
* @return string
*/
public function getSendSetPasswordEmail(): string
{
return $this->sendSetPasswordEmail;
}
}
@@ -0,0 +1,112 @@
<?php
namespace App\Classes\Modules\PerfexCRM\DataTransferObjects;
use Illuminate\Http\Request;
use App\Classes\General\Interfaces\DataTransferObject;
class InitialPerfexCRMObject implements DataTransferObject
{
/** @var string */
private $companyName;
/** @var string */
private $companyReference;
/** @var string */
private $contactName;
/** @var string */
private $contactEmail;
/** @var string */
private $bookingMarking;
/** @var string */
private $projectName;
/** @var array */
private $milestoneNames;
/** @var array */
private $taskNames;
public function __construct(string $companyName, string $companyReference, string $contactName, string $contactEmail, string $bookingMarking, string $projectName, array $milestoneNames, array $taskNames)
{
$this->companyName = $companyName;
$this->companyReference = $companyReference;
$this->contactName = $contactName;
$this->contactEmail = $contactEmail;
$this->bookingMarking = $bookingMarking;
$this->projectName = $projectName;
$this->milestoneNames = $milestoneNames;
$this->taskNames = $taskNames;
}
/**
* @return string
*/
public function getCompanyName(): string
{
return $this->companyName;
}
/**
* @return string
*/
public function getCompanyReference(): string
{
return $this->companyReference;
}
/**
* @return string
*/
public function getContactName(): string
{
return $this->contactName;
}
/**
* @return string
*/
public function getContactEmail(): string
{
return $this->contactEmail;
}
/**
* @return string
*/
public function getBookingMarking(): string
{
return $this->bookingMarking;
}
/**
* @return string
*/
public function getProjectName(): string
{
return $this->projectName;
}
/**
* @return array
*/
public function getMilestoneNames(): array
{
return $this->milestoneNames;
}
/**
* @return array
*/
public function getTaskNames(): array
{
return $this->taskNames;
}
}
@@ -0,0 +1,86 @@
<?php
namespace App\Classes\Modules\PerfexCRM\DataTransferObjects;
use Illuminate\Http\Request;
use App\Classes\General\Interfaces\DataTransferObject;
class InvoicePaymentPerfexCRMObject implements DataTransferObject
{
/** @var int */
private $invoiceId;
/** @var float */
private $amount;
/** @var string */
private $date;
/** @var int */
private $paymentMode;
/** @var string */
private $transactionId;
/** @var string */
private $note;
public function __construct(int $invoiceId, float $amount, string $date, int $paymentMode, string $transactionId, string $note)
{
$this->invoiceId = $invoiceId;
$this->amount = $amount;
$this->date = $date;
$this->paymentMode = $paymentMode;
$this->transactionId = $transactionId;
$this->note = $note;
}
/**
* @return int
*/
public function getInvoiceId(): int
{
return $this->invoiceId;
}
/**
* @return float
*/
public function getAmount(): float
{
return $this->amount;
}
/**
* @return string
*/
public function getDate(): string
{
return $this->date;
}
/**
* @return int
*/
public function getPaymentMode(): int
{
return $this->paymentMode;
}
/**
* @return string
*/
public function getTransactionId(): string
{
return $this->transactionId;
}
/**
* @return string
*/
public function getNote(): string
{
return $this->note;
}
}
@@ -0,0 +1,145 @@
<?php
namespace App\Classes\Modules\PerfexCRM\DataTransferObjects;
use Illuminate\Http\Request;
use App\Classes\General\Interfaces\DataTransferObject;
class InvoicePerfexCRMObject implements DataTransferObject
{
/** @var int */
private $clientId;
/** @var string */
private $number;
/** @var string */
private $date;
/** @var string */
private $dueDate;
/** @var string */
private $currency;
/** @var float */
private $subTotal;
/** @var float */
private $total;
/** @var string */
private $billingStreet;
/** @var string */
private $projectId;
/** @var array */
private $allowedPaymentModes;
/** @var array */
private $invoiceItems;
public function __construct(string $clientId, string $number, string $date, string $dueDate, string $currency, float $subTotal, float $total, string $billingStreet, string $projectId, array $allowedPaymentModes, array $invoiceItems)
{
$this->clientId = $clientId;
$this->number = $number;
$this->date = $date;
$this->dueDate = $dueDate;
$this->currency = $currency;
$this->subTotal = $subTotal;
$this->total = $total;
$this->billingStreet = $billingStreet;
$this->projectId = $projectId;
$this->allowedPaymentModes = $allowedPaymentModes;
$this->invoiceItems = $invoiceItems;
}
/**
* @return int
*/
public function getClientId(): int
{
return $this->clientId;
}
/**
* @return string
*/
public function getNumber(): string
{
return $this->number;
}
/**
* @return string
*/
public function getDate(): string
{
return $this->date;
}
/**
* @return string
*/
public function getDueDate(): string
{
return $this->dueDate;
}
/**
* @return string
*/
public function getCurrency(): string
{
return $this->currency;
}
/**
* @return float
*/
public function getSubTotal(): float
{
return $this->subTotal;
}
/**
* @return float
*/
public function getTotal(): float
{
return $this->total;
}
/**
* @return string
*/
public function getBillingStreet(): string
{
return $this->billingStreet;
}
/**
* @return string
*/
public function getProjectId(): string
{
return $this->projectId;
}
/**
* @return array
*/
public function getAllowedPaymentModes(): array
{
return $this->allowedPaymentModes;
}
/**
* @return array
*/
public function getInvoiceItems(): array
{
return $this->invoiceItems;
}
}
@@ -0,0 +1,86 @@
<?php
namespace App\Classes\Modules\PerfexCRM\DataTransferObjects;
use Illuminate\Http\Request;
use App\Classes\General\Interfaces\DataTransferObject;
class InvoiceSingleItemPerfexCRMObject implements DataTransferObject
{
/** @var string */
public $description;
/** @var string */
public $longDescription;
/** @var int */
public $qty;
/** @var float */
public $rate;
/** @var int */
public $order;
/** @var string */
public $unit;
public function __construct(string $description, string $longDescription, int $qty, float $rate, int $order, string $unit)
{
$this->description = $description;
$this->longDescription = $longDescription;
$this->qty = $qty;
$this->rate = $rate;
$this->order = $order;
$this->unit = $unit;
}
/**
* @return string
*/
public function getDescription(): string
{
return $this->description;
}
/**
* @return string
*/
public function getLongDescription(): string
{
return $this->longDescription;
}
/**
* @return int
*/
public function getQty(): int
{
return $this->qty;
}
/**
* @return float
*/
public function getRate(): float
{
return $this->rate;
}
/**
* @return int
*/
public function getOrder(): int
{
return $this->order;
}
/**
* @return string
*/
public function getUnit(): string
{
return $this->unit;
}
}
@@ -0,0 +1,100 @@
<?php
namespace App\Classes\Modules\PerfexCRM\DataTransferObjects;
use Illuminate\Http\Request;
use App\Classes\General\Interfaces\DataTransferObject;
class UpdatePerfexCRMObject implements DataTransferObject
{
/** @var string */
private $companyName;
/** @var string */
private $companyReference;
/** @var string */
private $contactEmail;
/** @var string */
private $bookingMarking;
/** @var string */
private $projectName;
/** @var string */
private $milestoneName;
/** @var string */
private $taskName;
public function __construct(string $companyName, string $companyReference, string $contactEmail, string $bookingMarking, string $projectName, string $milestoneName, string $taskName)
{
$this->companyName = $companyName;
$this->companyReference = $companyReference;
$this->contactEmail = $contactEmail;
$this->bookingMarking = $bookingMarking;
$this->projectName = $projectName;
$this->milestoneName = $milestoneName;
$this->taskName = $taskName;
}
/**
* @return string
*/
public function getCompanyName(): string
{
return $this->companyName;
}
/**
* @return string
*/
public function getCompanyReference(): string
{
return $this->companyReference;
}
/**
* @return string
*/
public function getContactEmail(): string
{
return $this->contactEmail;
}
/**
* @return string
*/
public function getBookingMarking(): string
{
return $this->bookingMarking;
}
/**
* @return string
*/
public function getProjectName(): string
{
return $this->projectName;
}
/**
* @return string
*/
public function getMilestoneName(): string
{
return $this->milestoneName;
}
/**
* @return string
*/
public function getTaskName(): string
{
return $this->taskName;
}
}
@@ -0,0 +1,159 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Processors;
// use App\Classes\Modules\PerfexCRM\DataTransferObjects\ContactObject;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMInvoice;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMInvoicePayment;
use App\Classes\Modules\PerfexCRM\Services\ConvertsPerfexCRMLeadToCustomer;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\InvoicePerfexCRMObject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\InvoicePaymentPerfexCRMObject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\InvoiceSingleItemPerfexCRMObject;
use Carbon\Carbon;
class CreatePerfexCRMInvoiceProcessor
{
/** @var CreatesPerfexCRMInvoice */
private $createsPerfexCRMInvoice;
/** @var CreatesPerfexCRMInvoicePayment */
private $createsPerfexCRMInvoicePayment;
/** @var ConvertsPerfexCRMLeadToCustomer */
private $convertsPerfexCRMLeadToCustomer;
/**
* CreatePerfexCRMInvoiceProcessor constructor.
* @param CreatesPerfexCRMInvoice $createsPerfexCRMInvoice
*/
public function __construct(CreatesPerfexCRMInvoice $createsPerfexCRMInvoice,
CreatesPerfexCRMInvoicePayment $createsPerfexCRMInvoicePayment,
ConvertsPerfexCRMLeadToCustomer $convertsPerfexCRMLeadToCustomer)
{
$this->createsPerfexCRMInvoice = $createsPerfexCRMInvoice;
$this->createsPerfexCRMInvoicePayment = $createsPerfexCRMInvoicePayment;
$this->convertsPerfexCRMLeadToCustomer = $convertsPerfexCRMLeadToCustomer;
}
/**
* @param $transaction
* @param $purchaseOrder
* @param $supplier
* @return null|object
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute($transaction, $purchaseOrder, $supplier) {
$clientId = "";
$number = $transaction->bill_no;
$prefix = "INV-";
if (substr($number, 0, strlen($prefix)) == $prefix) {
$number = substr($number, strlen($prefix));
}
$date = Carbon::parse($transaction->booking->created_at)->format('Y-m-d');
$dueDate = Carbon::parse($transaction->booking->created_at)->format('Y-m-d');
$currency = 1; //cief TODO: To look into Malaysia and Chinese currency
$subTotal = 0.00;
$total = 0.00;
$billingStreet = "";
$addresses = $supplier->addresses()->where('billing', '=', true)->first();
$billingStreet = $billingStreet.$addresses->street_one;
$billingStreet = $billingStreet.$addresses->street_two.',';
$billingStreet = $billingStreet.$addresses->district()->first()->name.',';
$billingStreet = $billingStreet.$addresses->postcode;
$billingStreet = $billingStreet.$addresses->state()->first()->name.',';
$billingStreet = $billingStreet.$addresses->country()->first()->name;
$projectId = "";
$allowedPaymentModes = [];
$invoiceItems = [];
$email = $supplier->employees()->first()->email;
$email = 'dillon37@yahoo.com'; //cief TODO: To be updated to user actual email address
$result = $this->convertsPerfexCRMLeadToCustomer->execute($email);
if(isset($result->payload)){
$clientId = $result->payload['client_id'];
}
//newitems
foreach ($purchaseOrder->transactionDetails as $key => $transaction_detail){
$order = $key + 1;
$stockCode = $transaction_detail->product_code;
$description = $transaction_detail->product_name;
$quantity = $transaction_detail->quantity;
$unitPrice = 0.00;
if($transaction->booking()->first()->fix_currency_id !== 1)
$unitPrice = (1/$transaction->currency_rate) * $transaction_detail->price;
else
$unitPrice = $transaction_detail->price;
//$totalAmount = 0.00;
if($transaction->booking()->first()->fix_currency_id !== 1){
//$totalAmount = (float)number_format( (1/$transaction->currency_rate) * $transaction_detail->price, 2,'.','')*$transaction_detail->quantity;
$subTotal += (1/$transaction->currency_rate) * $transaction_detail->price * $transaction_detail->quantity;
}
else
{
//$totalAmount = (float)number_format($transaction_detail->price, 2,'.','')*$transaction_detail->quantity;
$subTotal += $transaction_detail->price * $transaction_detail->quantity;
}
//string $description, string $longDescription, int $qty, int $rate, int $order, string $unit
$invoiceSingleItem = new InvoiceSingleItemPerfexCRMObject(
$description,
"",
$quantity,
$unitPrice,
$order,
""
);
array_push($invoiceItems, $invoiceSingleItem);
}
if($transaction->booking()->first()->fix_currency_id !== 1){
$total = ((1/$transaction->currency_rate) * $transaction->amount) + $transaction->service_charge + $transaction->tax;
}
else{
$total = $transaction->amount + $transaction->service_charge + $transaction->tax;
}
//cief TODO: To be updated, temporarily hardcoded allow payment modes
array_push($allowedPaymentModes, 1, 2);
$invoicePerfexCRMObject = new InvoicePerfexCRMObject(
$clientId,
$number,
$date,
$dueDate,
$currency,
$subTotal,
$total,
$billingStreet,
$projectId,
$allowedPaymentModes,
$invoiceItems
);
$result = $this->createsPerfexCRMInvoice->execute($invoicePerfexCRMObject);
//If there is a checking whether an payment to an invoice need to be generated, do it here
if(true && $result->payload['id']){
$invoicePaymentPerfexCRMObject = new InvoicePaymentPerfexCRMObject(
$result->payload['id'],
$total,
$date,
1,
"",
""
);
$this->createsPerfexCRMInvoicePayment->execute($invoicePaymentPerfexCRMObject);
}
return true;
}
}
@@ -0,0 +1,36 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Processors;
// use App\Classes\Modules\PerfexCRM\DataTransferObjects\ContactObject;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMLead;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CreateLeadPerfexCRMObject;
class CreatePerfexCRMLeadProcessor
{
/** @var CreatesPerfexCRMLead */
private $createsPerfexCRMLead;
/**
* CreatePerfexCRMLeadProcessor constructor.
* @param CreatesPerfexCRMLead $createsPerfexCRMLead
*/
public function __construct(CreatesPerfexCRMLead $createsPerfexCRMLead)
{
$this->createsPerfexCRMLead = $createsPerfexCRMLead;
}
/**
* @param CreateLeadPerfexCRMObject $createLeadPerfexCRMObject
* @return null|object
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(CreateLeadPerfexCRMObject $createLeadPerfexCRMObject) {
return $this->createsPerfexCRMLead->execute($createLeadPerfexCRMObject);
}
}
@@ -0,0 +1,41 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Processors;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMTask;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CreateTaskPerfexCRMObject;
class CreatePerfexCRMTaskProcessor
{
/** @var CreatesPerfexCRMTask */
private $createsPerfexCRMTask;
/**
* @param CreatesPerfexCRMTask $createsPerfexCRMTask
*/
public function __construct(CreatesPerfexCRMTask $createsPerfexCRMTask)
{
$this->createsPerfexCRMTask = $createsPerfexCRMTask;
}
/**
* @param CreateTaskPerfexCRMObject $createTaskPerfexCRMObject
* @return true
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(CreateTaskPerfexCRMObject $createTaskPerfexCRMObject) {
$this->createsPerfexCRMTask->execute(
$createTaskPerfexCRMObject->getName(),
$createTaskPerfexCRMObject->getDescription(),
$createTaskPerfexCRMObject->getLeadId(),
$createTaskPerfexCRMObject->getMilestoneId(),
$createTaskPerfexCRMObject->getProjectId(),
$createTaskPerfexCRMObject->getReference(),
$createTaskPerfexCRMObject->getOnTaskCompletion(),
$createTaskPerfexCRMObject->getStatus(),
);
return true;
}
}
@@ -0,0 +1,192 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Processors;
use App\Classes\Modules\PerfexCRM\Services\ConvertsPerfexCRMLeadToCustomer;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMCustomerProject;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMMilestone;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMTask;
use App\Classes\Modules\PerfexCRM\Services\FetchesPerfexCRMProject;
use App\Classes\Modules\PerfexCRM\Services\FetchesPerfexCRMMilestone;
use App\Classes\Modules\PerfexCRM\Services\FetchesPerfexCRMTask;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMCustomer;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMCustomerContact;
use App\Classes\Modules\PerfexCRM\Services\UpdatesPerfexCRMCustomer;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CustomerContactObject;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\InitialPerfexCRMObject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\UpdatePerfexCRMObject;
use App\Classes\ValueObjects\Constants\PerfexCRMMilestones;
use App\Classes\ValueObjects\Constants\PerfexCRMTasks;
use App\Classes\ValueObjects\Constants\PerfexCRMStatus;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\Http\Request;
class InitializePerfexCRMProcessor
{
/** @var ConvertsPerfexCRMLeadToCustomer */
private $convertsPerfexCRMLeadToCustomer;
/** @var CreatesPerfexCRMCustomerProject */
private $createsPerfexCRMCustomerProject;
/** @var CreatesPerfexCRMMilestone */
private $createsPerfexCRMMilestone;
/** @var CreatesPerfexCRMTask */
private $createsPerfexCRMTask;
/** @var FetchesPerfexCRMProject */
private $fetchesPerfexCRMProject;
/** @var FetchesPerfexCRMMilestone */
private $fetchesPerfexCRMMilestone;
/** @var FetchesPerfexCRMTask */
private $fetchesPerfexCRMTask;
/** @var CreatesPerfexCRMCustomer */
private $createsPerfexCRMCustomer;
/** @var CreatesPerfexCRMCustomerContact */
private $createsPerfexCRMCustomerContact;
/** @var UpdatesPerfexCRM */
private $updatePerfexCRM;
/** @var UpdatesPerfexCRMCustomer */
private $updatesPerfexCRMCustomer;
/**
* @param ConvertsPerfexCRMLeadToCustomer $convertsPerfexCRMLeadToCustomer
* @param CreatesPerfexCRMCustomerProject $createsPerfexCRMCustomerProject
* @param CreatesPerfexCRMMilestone $createsPerfexCRMMilestone
* @param CreatesPerfexCRMTask $createsPerfexCRMTask
* @param FetchesPerfexCRMProject $fetchesPerfexCRMProject
* @param FetchesPerfexCRMMilestone $fetchesPerfexCRMMilestone
* @param FetchesPerfexCRMTask $fetchesPerfexCRMTask
* @param CreatesPerfexCRMCustomer $createsPerfexCRMCustomer
* @param CreatesPerfexCRMCustomerContact $createsPerfexCRMCustomerContact
* @param UpdatesPerfexCRMCustomer $updatesPerfexCRMCustomer
*/
public function __construct(ConvertsPerfexCRMLeadToCustomer $convertsPerfexCRMLeadToCustomer,
CreatesPerfexCRMCustomerProject $createsPerfexCRMCustomerProject,
CreatesPerfexCRMMilestone $createsPerfexCRMMilestone,
CreatesPerfexCRMTask $createsPerfexCRMTask,
FetchesPerfexCRMProject $fetchesPerfexCRMProject,
FetchesPerfexCRMMilestone $fetchesPerfexCRMMilestone,
FetchesPerfexCRMTask $fetchesPerfexCRMTask,
CreatesPerfexCRMCustomer $createsPerfexCRMCustomer,
CreatesPerfexCRMCustomerContact $createsPerfexCRMCustomerContact,
UpdatesPerfexCRMCustomer $updatesPerfexCRMCustomer)
{
$this->convertsPerfexCRMLeadToCustomer = $convertsPerfexCRMLeadToCustomer;
$this->createsPerfexCRMCustomerProject = $createsPerfexCRMCustomerProject;
$this->createsPerfexCRMMilestone = $createsPerfexCRMMilestone;
$this->createsPerfexCRMTask = $createsPerfexCRMTask;
$this->fetchesPerfexCRMProject = $fetchesPerfexCRMProject;
$this->fetchesPerfexCRMMilestone = $fetchesPerfexCRMMilestone;
$this->fetchesPerfexCRMTask = $fetchesPerfexCRMTask;
$this->createsPerfexCRMCustomer = $createsPerfexCRMCustomer;
$this->createsPerfexCRMCustomerContact = $createsPerfexCRMCustomerContact;
$this->updatesPerfexCRMCustomer = $updatesPerfexCRMCustomer;
}
/**
* @param InitialPerfexCRMObject $initialPerfexCRMObject
* @return null|object
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(InitialPerfexCRMObject $initialPerfexCRMObject) {
// Customer has to exist first before Project can appear under it
// Check with Perfex CRM, if this user (email) was previously a lead, should automatically now become a customer
$crmCompany = $initialPerfexCRMObject->getCompanyName();
$result = $this->convertsPerfexCRMLeadToCustomer->execute($initialPerfexCRMObject->getContactEmail());
if(isset($result->payload)){
$crmClientId = $result->payload['client_id'];
if (isset($result->payload['company'])) {
$crmCompany = $result->payload['company'];
}
}
else{
//if reach this point, this means this user is not a official customer nor is a lead in crm
//Create Customer has 2 parts: Create Company (client), Create Contact
$result = $this->createsPerfexCRMCustomer->execute($crmCompany);
if(is_null($result)){
$crmCompany = $crmCompany." 2";
$result = $this->createsPerfexCRMCustomer->execute($crmCompany);
}
$crmClientId = $result->payload['clientId'];
$customerContactObject = new CustomerContactObject(
$crmClientId,
$initialPerfexCRMObject->getContactName(),
$initialPerfexCRMObject->getContactName(),
$initialPerfexCRMObject->getContactEmail(),
"pU^T@sC#9Q",
"on",
"on"
);
$result = $this->createsPerfexCRMCustomerContact->execute($customerContactObject);
}
//Update custom fields to identify company reference from exchange or shipping portal
$value_exists = false;
if (isset($result->payload['customfields'])) {
foreach ($result->payload['customfields'] as $element) {
if ($element['value'] === $initialPerfexCRMObject->getCompanyReference()) {
$value_exists = true;
break;
}
}
}
if(!$value_exists);
{
$result = $this->updatesPerfexCRMCustomer->execute($crmClientId, $crmCompany, $initialPerfexCRMObject->getCompanyReference());
}
// Get existing or create project, project has to exist first before milestone can appear under it
$result = $this->createsPerfexCRMCustomerProject->execute($initialPerfexCRMObject->getProjectName(), $crmClientId);
if(isset($result->payload)){ //Here means project creation successful
$projectId = $result->payload['project_id'];
}
else{
$projectId = $this->fetchesPerfexCRMProject->execute($initialPerfexCRMObject->getProjectName(), $crmClientId)->id;
}
if(!is_null($result)){
$tasks = $initialPerfexCRMObject->getTaskNames();
//Create tasks with milestone
for($count=0; $count < count($tasks); $count++) {
$milestoneId = 0; //By default milestoneId is 0, having this set at individual task is optional
if($tasks[$count]['milestone'] != "") //Create milestone only if it is defined
{
// Get existing or create milestone, milestone has to exist first before task can appear under it
$result = $this->createsPerfexCRMMilestone->execute($tasks[$count]['milestone'], $projectId, $count);
if(isset($result->payload)){
$milestoneId = $result->payload['milestone_id'];
}
else{
$milestone = $this->fetchesPerfexCRMMilestone->execute($tasks[$count]['milestone'], $projectId);
$array = json_decode(json_encode($milestone), true);
$milestoneId = $array[0]['id'];
}
}
$taskStatus = PerfexCRMStatus::NOT_STARTED;
if($tasks[$count]['status'] != ''){
$taskStatus = $tasks[$count]['status'];
}
// Get existing or create task
$result = $this->createsPerfexCRMTask->execute($tasks[$count]['name'], $tasks[$count]['description'], '', $milestoneId, $projectId, $tasks[$count]['reference'], $tasks[$count]['on_task_completion'], $taskStatus);
}
}
return true;
}
}
@@ -0,0 +1,34 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Processors;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CreateTaskPerfexCRMObject;
use App\Classes\ValueObjects\Constants\PerfexCRMStatus;
use App\Classes\Jobs\CreatePerfexCRMSingleTask;
class NewLeadTaskToPerfexCRMProcessor
{
/**
* @param None
* @return true
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute()
{
$createTaskPerfexCRMObject = new CreateTaskPerfexCRMObject(
"dillontest1@gmail.com",
"test is the name of the task",
"this is the description of the task",
"",
"",
"",
"",
"",
PerfexCRMStatus::NOT_STARTED
);
CreatePerfexCRMSingleTask::dispatch($createTaskPerfexCRMObject);
return true;
}
}
@@ -0,0 +1,89 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Processors;
use App\Classes\Modules\PerfexCRM\Processors\UpdatePerfexCRMProcessor;
use App\Classes\Modules\PerfexCRM\Processors\InitializePerfexCRMProcessor;
use App\Classes\Modules\PerfexCRM\Services\Init;
use App\Classes\Modules\Companies\Services\FetchesCompany;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\UpdatePerfexCRMObject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\InitialPerfexCRMObject;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Classes\ValueObjects\Constants\PerfexCRMMilestones;
use App\Classes\ValueObjects\Constants\PerfexCRMTasks;
use App\Models\Transaction;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\Jobs\InitializePerfexCRM;
use App\Classes\Jobs\UpdatePerfexCRM;
class TransactionToPerfexCRMProcessor
{
/** @var FetchesCompany */
private $fetchesCompany;
/** @var UpdatePerfexCRMProcessor */
private $updatePerfexCRMProcessor;
/** @var InitializePerfexCRMProcessor */
private $initializePerfexCRMProcessor;
/**
* TransactionToPerfexCRMProcessor constructor.
* @param UpdatePerfexCRMProcessor $updatePerfexCRMProcessor
* @param InitializePerfexCRMProcessor $initializePerfexCRMProcessor
* @param FetchesCompany $fetchesCompany
*/
public function __construct(UpdatePerfexCRMProcessor $updatePerfexCRMProcessor, InitializePerfexCRMProcessor $initializePerfexCRMProcessor, FetchesCompany $fetchesCompany)
{
$this->updatePerfexCRMProcessor = $updatePerfexCRMProcessor;
$this->initializePerfexCRMProcessor = $initializePerfexCRMProcessor;
$this->fetchesCompany = $fetchesCompany;
}
/**
* @param Transaction $model
* @param int $status
* @return \Illuminate\Database\Eloquent\Model
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(Transaction $model, int $status)
{
if($model->owner instanceof \App\Models\Transaction && $status == ApprovalStatus::APPROVED){
//dd(json_encode($packingList->owner()->first()->companyModule()->first()->inviters()->withPivot('invitee_reference')->first()->pivot->invitee_reference));
//dd(json_encode($model->owner->owner->owner()->first()->companyModule()->first()->inviters()->withPivot('invitee_reference')->first()->pivot->invitee_reference));
$companyModule = $model->owner->owner->owner()->first()->companyModule()->first();
$companyName = $companyModule->name;
$companyReference = $companyModule->inviters()->withPivot('invitee_reference')->first()->pivot->invitee_reference;
$employee = $companyModule->employees()->first();
$contactEmail = $employee->email;
$contactName = $employee->name;
$orderReference = $model->owner->owner->owner()->first()->reference;
$packingListReference = $model->owner->owner->reference;
$projectName = 'IZYIM | X1 Shipping | '.$orderReference.' | '.$packingListReference;
$bookingMarking = $model->owner->owner->id."-".$model->owner->owner->owner->id;
$initialPerfexCRMObject = new InitialPerfexCRMObject(
$companyName,
$companyReference,
$contactName,
$contactEmail,
$bookingMarking,
$projectName,
[],
[
PerfexCRMTasks::TASK_1,
PerfexCRMTasks::TASK_POST_PAYMENT_1,
PerfexCRMTasks::TASK_POST_PAYMENT_2,
PerfexCRMTasks::TASK_POST_PAYMENT_3,
PerfexCRMTasks::TASK_POST_PAYMENT_4,
]
);
//$this->initializePerfexCRMProcessor->execute($initialPerfexCRMObject);
InitializePerfexCRM::dispatch($initialPerfexCRMObject);
}
return true;
}
}
@@ -0,0 +1,139 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Processors;
use App\Classes\Modules\PerfexCRM\Services\ConvertsPerfexCRMLeadToCustomer;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMCustomerProject;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMMilestone;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMTask;
use App\Classes\Modules\PerfexCRM\Services\FetchesPerfexCRMProject;
use App\Classes\Modules\PerfexCRM\Services\FetchesPerfexCRMMilestone;
use App\Classes\Modules\PerfexCRM\Services\FetchesPerfexCRMTask;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMCustomer;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMCustomerContact;
use App\Classes\Modules\PerfexCRM\Services\UpdatesPerfexCRMTask;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CustomerContactObject;
use App\Classes\Exceptions\MalformedRequestException;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\UpdatePerfexCRMObject;
use App\Classes\ValueObjects\Constants\PerfexCRMStatus;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\Http\Request;
class UpdatePerfexCRMProcessor
{
/** @var ConvertsPerfexCRMLeadToCustomer */
private $convertsPerfexCRMLeadToCustomer;
/** @var CreatesPerfexCRMCustomerProject */
private $createsPerfexCRMCustomerProject;
/** @var CreatesPerfexCRMMilestone */
private $createsPerfexCRMMilestone;
/** @var CreatesPerfexCRMTask */
private $createsPerfexCRMTask;
/** @var FetchesPerfexCRMProject */
private $fetchesPerfexCRMProject;
/** @var FetchesPerfexCRMMilestone */
private $fetchesPerfexCRMMilestone;
/** @var FetchesPerfexCRMTask */
private $fetchesPerfexCRMTask;
/** @var CreatesPerfexCRMCustomer */
private $createsPerfexCRMCustomer;
/** @var CreatesPerfexCRMCustomerContact */
private $createsPerfexCRMCustomerContact;
/** @var UpdatesPerfexCRMTask */
private $updatesPerfexCRMTask;
/**
* @param ConvertsPerfexCRMLeadToCustomer $convertsPerfexCRMLeadToCustomer
* @param CreatesPerfexCRMCustomerProject $createsPerfexCRMCustomerProject
* @param CreatesPerfexCRMMilestone $createsPerfexCRMMilestone
* @param CreatesPerfexCRMTask $createsPerfexCRMTask
* @param FetchesPerfexCRMProject $fetchesPerfexCRMProject
* @param FetchesPerfexCRMMilestone $fetchesPerfexCRMMilestone
* @param FetchesPerfexCRMTask $fetchesPerfexCRMTask
* @param CreatesPerfexCRMCustomer $createsPerfexCRMCustomer
* @param CreatesPerfexCRMCustomerContact $createsPerfexCRMCustomerContact
* @param UpdatesPerfexCRMTask $updatesPerfexCRMTask
*/
public function __construct(ConvertsPerfexCRMLeadToCustomer $convertsPerfexCRMLeadToCustomer,
CreatesPerfexCRMCustomerProject $createsPerfexCRMCustomerProject,
CreatesPerfexCRMMilestone $createsPerfexCRMMilestone,
CreatesPerfexCRMTask $createsPerfexCRMTask,
FetchesPerfexCRMProject $fetchesPerfexCRMProject,
FetchesPerfexCRMMilestone $fetchesPerfexCRMMilestone,
FetchesPerfexCRMTask $fetchesPerfexCRMTask,
CreatesPerfexCRMCustomer $createsPerfexCRMCustomer,
CreatesPerfexCRMCustomerContact $createsPerfexCRMCustomerContact,
UpdatesPerfexCRMTask $updatesPerfexCRMTask)
{
$this->convertsPerfexCRMLeadToCustomer = $convertsPerfexCRMLeadToCustomer;
$this->createsPerfexCRMCustomerProject = $createsPerfexCRMCustomerProject;
$this->createsPerfexCRMMilestone = $createsPerfexCRMMilestone;
$this->createsPerfexCRMTask = $createsPerfexCRMTask;
$this->fetchesPerfexCRMProject = $fetchesPerfexCRMProject;
$this->fetchesPerfexCRMMilestone = $fetchesPerfexCRMMilestone;
$this->fetchesPerfexCRMTask = $fetchesPerfexCRMTask;
$this->createsPerfexCRMCustomer = $createsPerfexCRMCustomer;
$this->createsPerfexCRMCustomerContact = $createsPerfexCRMCustomerContact;
$this->updatesPerfexCRMTask = $updatesPerfexCRMTask;
}
/**
* @param PerfexCRMObject $perfexCRMObject
* @return null|object
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(UpdatePerfexCRMObject $updatePerfexCRMObject) {
// Customer has to exist first before Project can appear under it
// Check with Perfex CRM, if this user (email) was previously a lead, should automatically now become a customer
$result = $this->convertsPerfexCRMLeadToCustomer->execute($updatePerfexCRMObject->getContactEmail());
if(isset($result->payload)){
$crmClientId = $result->payload['client_id'];
}
// Get existing or create project, project has to exist first before milestone can appear under it
$result = $this->createsPerfexCRMCustomerProject->execute($updatePerfexCRMObject->getProjectName(), $crmClientId);
if(isset($result->payload)){
$projectId = $result->payload['project_id'];
}
else{
$projectId = $this->fetchesPerfexCRMProject->execute($updatePerfexCRMObject->getProjectName(), $crmClientId)->id;
}
// Get existing or create milestone, milestone has to exist first before task can appear under it
$result = $this->createsPerfexCRMMilestone->execute($updatePerfexCRMObject->getMilestoneName(), $projectId);
if(isset($result->payload)){
$milestoneId = $result->payload['milestone_id'];
}
else{
$milestone = $this->fetchesPerfexCRMMilestone->execute($updatePerfexCRMObject->getMilestoneName(), $projectId);
$array = json_decode(json_encode($milestone), true);
$milestoneId = $array[0]['id'];
}
// Get existing or create task
$result = $this->createsPerfexCRMTask->execute($updatePerfexCRMObject->getTaskName(), $milestoneId, $projectId);
if(isset($result->payload)){
$taskId = $result->payload['task_id'];
}
else{
$taskId = $this->fetchesPerfexCRMTask->execute($updatePerfexCRMObject->getTaskName(), $milestoneId)->id;
}
$this->updatesPerfexCRMTask->execute($taskId, $updatePerfexCRMObject->getTaskName(), $milestoneId, $projectId, PerfexCRMStatus::COMPLETED);
return null;
}
}
@@ -0,0 +1,34 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
class ConvertsPerfexCRMLeadToCustomer
{
/**
* @param string $email
* @return null|object
* @throws MalformedRequestException
*/
public function execute(string $email) {
try{
$response = Http::withHeaders([
'authtoken' => config('perfexcrm.api_key'),])
->get(config('perfexcrm.base_url').'/api/leads/convertocustomer/'.$email);
if($response->successful()){
$data = $response->json();
return (object) $data;
}else{
Log::error($response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
}
}
@@ -0,0 +1,37 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
class CreatesPerfexCRMCustomer
{
/**
* @param string $companyName
* @return null|object
* @throws MalformedRequestException
*/
public function execute(string $companyName) {
try{
$data = [
'company' => $companyName
];
$response = Http::asForm()->withHeaders([
'authtoken' => config('perfexcrm.api_key')])
->post(config('perfexcrm.base_url').'/api/customers',$data);
if($response->successful()){
$data = $response->json();
return (object) $data;
}else{
Log::error($response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
}
}
@@ -0,0 +1,44 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Services;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CustomerContactObject;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
class CreatesPerfexCRMCustomerContact
{
/**
* @param CustomerContactObject $customerContactObject
* @return null|object
* @throws MalformedRequestException
*/
public function execute(CustomerContactObject $customerContactObject) {
try{
$data = [
'customer_id' => $customerContactObject->getCustomerId(),
'firstname' => $customerContactObject->getFirstName(),
'lastname' => $customerContactObject->getLastName(),
'email' => $customerContactObject->getEmail(), //$email
'password' => $customerContactObject->getPassword(),
'is_primary' => $customerContactObject->getIsPrimary(),
//'send_set_password_email' => $customerContactObject->getSendSetPasswordEmail(),
];
$response = Http::asForm()->withHeaders([
'authtoken' => config('perfexcrm.api_key')])
->post(config('perfexcrm.base_url').'/api/contacts',$data);
if($response->successful()){
$data = $response->json();
return (object) $data;
}else{
Log::error($response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
}
}
@@ -0,0 +1,43 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
class CreatesPerfexCRMCustomerProject
{
/**
* @param string $projectName
* @param string $clientId
* @return null|object
* @throws MalformedRequestException
*/
public function execute(string $projectName, string $clientId) {
try{
$data = [
'name' => $projectName,
'rel_type' => 'customer',
'billing_type' => 1,
'clientid' => $clientId,
'start_date' => date('Y-m-d'),
'status' => 1
];
$response = Http::asForm()->withHeaders([
'authtoken' => config('perfexcrm.api_key')])
->post(config('perfexcrm.base_url').'/api/projects',$data);
if($response->successful()){
$data = $response->json();
return (object) $data;
}else{
Log::error($response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
}
}
@@ -0,0 +1,60 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\InvoicePerfexCRMObject;
class CreatesPerfexCRMInvoice
{
/**
* @param InvoicePerfexCRMObject $invoicePerfexCRMObject
* @return null|object
* @throws MalformedRequestException
*/
public function execute(InvoicePerfexCRMObject $invoicePerfexCRMObject) {
try{
$data = [
'clientid' => $invoicePerfexCRMObject->getClientId(),
'number' => $invoicePerfexCRMObject->getNumber(),
'date' => $invoicePerfexCRMObject->getDate(),
'duedate' => $invoicePerfexCRMObject->getDueDate(),
'currency' => $invoicePerfexCRMObject->getCurrency(),
'subtotal' => $invoicePerfexCRMObject->getSubTotal(),
'total' => $invoicePerfexCRMObject->getTotal(),
'billing_street' => $invoicePerfexCRMObject->getBillingStreet(),
'project_id' => $invoicePerfexCRMObject->getProjectId(),
'allowed_payment_modes[0]' => 1,
'allowed_payment_modes[1]' => 2,
];
for($count=0; $count < count($invoicePerfexCRMObject->getInvoiceItems()); $count++) {
$oneItem = [
"newitems[".$count."][description]" => $invoicePerfexCRMObject->getInvoiceItems()[$count]->description,
"newitems[".$count."][long_description]" => $invoicePerfexCRMObject->getInvoiceItems()[$count]->longDescription,
"newitems[".$count."][qty]" => $invoicePerfexCRMObject->getInvoiceItems()[$count]->qty,
"newitems[".$count."][rate]" => $invoicePerfexCRMObject->getInvoiceItems()[$count]->rate,
"newitems[".$count."][order]" => $invoicePerfexCRMObject->getInvoiceItems()[$count]->order,
"newitems[".$count."][unit]" => $invoicePerfexCRMObject->getInvoiceItems()[$count]->unit,
];
$data = array_merge($data, $oneItem);
}
$response = Http::asForm()->withHeaders([
'authtoken' => config('perfexcrm.api_key')])
->post(config('perfexcrm.base_url').'/api/invoices',$data);
if($response->successful()){
$data = $response->json();
return (object) $data;
}else{
Log::error($response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
}
}
@@ -0,0 +1,43 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\InvoicePaymentPerfexCRMObject;
class CreatesPerfexCRMInvoicePayment
{
/**
* @param InvoicePaymentPerfexCRMObject $invoicePaymentPerfexCRMObject
* @return null|object
* @throws MalformedRequestException
*/
public function execute(InvoicePaymentPerfexCRMObject $invoicePaymentPerfexCRMObject) {
try{
$data = [
'invoiceid' => $invoicePaymentPerfexCRMObject->getInvoiceId(),
'amount' => $invoicePaymentPerfexCRMObject->getAmount(),
'date' => $invoicePaymentPerfexCRMObject->getDate(),
'paymentmode' => $invoicePaymentPerfexCRMObject->getPaymentMode(),
'transactionid' => $invoicePaymentPerfexCRMObject->getTransactionId(),
'note' => $invoicePaymentPerfexCRMObject->getNote(),
];
$response = Http::asForm()->withHeaders([
'authtoken' => config('perfexcrm.api_key')])
->post(config('perfexcrm.base_url').'/api/invoices/recordpayment',$data);
if($response->successful()){
$data = $response->json();
return (object) $data;
}else{
Log::error($response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
}
}
@@ -0,0 +1,43 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CreateLeadPerfexCRMObject;
class CreatesPerfexCRMLead
{
/**
* @param CreateLeadPerfexCRMObject $createLeadPerfexCRMObject
* @return null|object
* @throws MalformedRequestException
*/
public function execute(CreateLeadPerfexCRMObject $createLeadPerfexCRMObject) {
try{
$data = [
'name' => $createLeadPerfexCRMObject->getName(),
'email' => $createLeadPerfexCRMObject->getEmail(),
'phonenumber' => $createLeadPerfexCRMObject->getPhone(),
'company' => $createLeadPerfexCRMObject->getCompanyName(),
'source' => 2, //1: Exchange, 2: Shipping Portal
'status' => 2 //2: Lead, 1: Customer
];
$response = Http::asForm()->withHeaders([
'authtoken' => config('perfexcrm.api_key')])
->post(config('perfexcrm.base_url').'/api/leads/byemail',$data);
if($response->successful()){
$data = $response->json();
return (object) $data;
}else{
Log::error($response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server ' . $exception->getMessage());
}
}
}
@@ -0,0 +1,46 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
class CreatesPerfexCRMMilestone
{
/**
* @param string $$milestoneName
* @param string $projectId
* @param string $milestoneOrder
* @return null|object
* @throws MalformedRequestException
*/
public function execute(string $milestoneName, string $projectId, string $milestoneOrder = "") {
try{
$data = [
'name' => $milestoneName,
'project_id' => $projectId,
'due_date' => date('Y-m-d'),
'start_date' => date('Y-m-d')
];
if($milestoneOrder != ""){
$data['milestone_order'] = $milestoneOrder;
}
$response = Http::asForm()->withHeaders([
'authtoken' => config('perfexcrm.api_key')])
->post(config('perfexcrm.base_url').'/api/milestones',$data);
if($response->successful()){
$data = $response->json();
return (object) $data;
}else{
Log::error($response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
}
}
@@ -0,0 +1,68 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
class CreatesPerfexCRMTask
{
/**
* @param string $taskName
* @param string $taskDescription
* @param string $leadId
* @param string $milestoneId
* @param string $projectId
* @param string $reference, default: ''
* @param string $on_task_completion, default: ''
* @param string $status, default: 1
* @return null|object
* @throws MalformedRequestException
*/
public function execute(string $taskName, string $taskDescription, string $leadId, string $milestoneId, string $projectId, string $reference = '', string $on_task_completion = '', string $status = "1") {
try{
$data = [
'name' => $taskName,
'description' => $taskDescription,
'milestone' => $milestoneId,
'startdate' => date('Y-m-d'),
'rel_type' => 'project',
'rel_id' => $projectId,
'status' => $status,
'is_system_created' => 1,
'reference' => $reference,
'on_task_completion' => $on_task_completion
];
if($leadId != '') {
$data = [
'name' => $taskName,
'description' => $taskDescription,
'milestone' => $milestoneId,
'startdate' => date('Y-m-d'),
'rel_type' => 'lead',
'rel_id' => $leadId,
'status' => $status,
'is_system_created' => 1,
'reference' => $reference,
'on_task_completion' => $on_task_completion
];
}
$response = Http::asForm()->withHeaders([
'authtoken' => config('perfexcrm.api_key')])
->post(config('perfexcrm.base_url').'/api/tasks',$data);
if($response->successful()){
$data = $response->json();
return (object) $data;
}else{
Log::error($response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
}
}
@@ -0,0 +1,34 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
class FetchesPerfexCRMLead
{
/**
* @param string $email
* @return null|object
* @throws MalformedRequestException
*/
public function execute(string $email) {
try{
$response = Http::withHeaders([
'authtoken' => config('perfexcrm.api_key'),])
->get(config('perfexcrm.base_url').'/api/leads/byemail/'.$email);
if($response->successful()){
$data = $response->json();
return (object) $data;
}else{
Log::error($response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
}
@@ -0,0 +1,35 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
class FetchesPerfexCRMMilestone
{
/**
* @param string $milestoneName
* @param string $projectId
* @return null|object
* @throws MalformedRequestException
*/
public function execute(string $milestoneName, string $projectId) {
try{
$response = Http::withHeaders([
'authtoken' => config('perfexcrm.api_key'),])
->get(config('perfexcrm.base_url').'/api/milestones/bynameandprojectid/'.rawurlencode($milestoneName).'/'.$projectId);
if($response->successful()){
$data = $response->json();
return (object) $data;
}else{
Log::error($response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
}
}
@@ -0,0 +1,40 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
class FetchesPerfexCRMProject
{
/**
* @param string $projectName
* @param string $clientId
* @return null|object
* @throws MalformedRequestException
*/
public function execute(string $projectName, string $clientId) {
try{
$data = [
'name' => $projectName,
'clientid' => $clientId,
];
$response = Http::asForm()->withHeaders([
'authtoken' => config('perfexcrm.api_key')])
->post(config('perfexcrm.base_url').'/api/projects/bynameandclientid', $data);
if($response->successful()){
$data = $response->json();
return (object) $data;
}else{
Log::error($response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
}
}
@@ -0,0 +1,35 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
class FetchesPerfexCRMTask
{
/**
* @param string $taskName
* @param string $milestoneId
* @return null|object
* @throws MalformedRequestException
*/
public function execute(string $taskName, string $milestoneId) {
try{
$response = Http::withHeaders([
'authtoken' => config('perfexcrm.api_key'),])
->get(config('perfexcrm.base_url').'/api/tasks/bynameandmilestoneid/'.rawurlencode($taskName).'/'.$milestoneId);
if($response->successful()){
$data = $response->json();
return (object) $data;
}else{
Log::error($response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
}
}
@@ -0,0 +1,46 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
class UpdatesPerfexCRMCustomer
{
/**
* @param string $customerId
* @param string $companyReference
* @return null|object
* @throws MalformedRequestException
*/
public function execute(string $customerId, string $companyName, string $companyReference) {
try{
$custom_fields = [
"customers" => [
2 => $companyReference
]
];
$data = [
'company' => $companyName,
'custom_fields' => $custom_fields
];
$response = Http::asJson()->withHeaders([
'authtoken' => config('perfexcrm.api_key')])
->put(config('perfexcrm.base_url').'/api/customers/'.$customerId, $data);
if($response->successful()){
$data = $response->json();
return (object) $data;
}else{
Log::error($response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
}
}
@@ -0,0 +1,48 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
class UpdatesPerfexCRMTask
{
/**
* @param string $taskName
* @param string $milestoneId
* @param string $projectId
* @param string $status, default: 1
* @return null|object
* @throws MalformedRequestException
*/
public function execute(string $taskId, string $taskName, string $milestoneId, string $projectId, string $status = "1") {
try{
$data = [
'name' => $taskName,
'milestone' => $milestoneId,
'startdate' => date('Y-m-d'),
'duedate' => date('Y-m-d'),
'rel_type' => 'project',
'rel_id' => $projectId,
'status' => $status,
'repeat_every' => '',
];
$response = Http::asJson()->withHeaders([
'authtoken' => config('perfexcrm.api_key')])
->put(config('perfexcrm.base_url').'/api/tasks/'.$taskId, $data);
if($response->successful()){
$data = $response->json();
return (object) $data;
}else{
Log::error($response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server' . $exception->getMessage());
}
}
}
@@ -0,0 +1,104 @@
<?php
namespace App\Classes\Modules\Transactions\ControllersLogic;
use App\Classes\Notifications\InvoiceIssuedEmail;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Meneses\LaravelMpdf\Facades\LaravelMpdf;
use App\Classes\ValueObjects\Constants\DocumentType;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Classes\Modules\Documents\Services\CreatesFiles;
use App\Classes\General\Abstracts\AbstractControllerLogic;
use App\Classes\Modules\Documents\Services\CreatesDocument;
use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject;
use App\Classes\Modules\PackingLists\Services\FetchesPackingList;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use App\Classes\Modules\Transactions\ControllersLogic\Document;
class CreateCombinedInvoicesLogic extends AbstractControllerLogic
{
/**
* @return array
*/
protected function notification():array {
return [
'title' => 'Shipping Invoice Status',
'message' => 'You have successfully updated multiple shipping invoices status'
];
}
/** @var FetchesPackingList */
private $fetchesPackingList;
/** @var UpdatesTransactionStatus */
private $updatesTransactionStatus;
/** @var CreatesDocument */
private $createsDocument;
/** @var CreatesFiles */
private $createsFiles;
/**
* ApprovePaymentVerificationLogic constructor.
* @param FetchesPackingList $fetchesPackingList
* @param UpdatesTransactionStatus $updatesTransactionStatus
* @param CreatesDocument $createsDocument
* @param CreatesFiles $createsFiles
* @param CreateInvoiceTransactionProcessor $createInvoiceTransactionProcessor
*/
public function __construct(FetchesPackingList $fetchesPackingList, UpdatesTransactionStatus $updatesTransactionStatus, CreatesDocument $createsDocument, CreatesFiles $createsFiles)
{
$this->fetchesPackingList = $fetchesPackingList;
$this->updatesTransactionStatus = $updatesTransactionStatus;
$this->createsDocument = $createsDocument;
$this->createsFiles = $createsFiles;
}
/**
* @param Request $request
* @return JsonResponse
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function logic(Request $request) : JsonResponse
{
$items = $request->input('ids');
$invoice_transactions=array();
foreach($items as $item){
$packing_list = $this->fetchesPackingList->execute(['id' => $item['id']]);
$invoice_transaction = $packing_list->transactions()->where('transactions.type', TransactionType::SHIPPING_INVOICE)->whereIn('status', [ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::PENDING_SUBMISSION])->first();
array_push($invoice_transactions, $invoice_transaction);
// $this->updatesTransactionStatus->execute($invoice_transaction, ApprovalStatus::APPROVED);
}
$transaction_invoice_pdf = LaravelMpdf::loadView('pages.pdfs.shipping_invoices_combined', ['invoice_transactions' => $invoice_transactions]);
$document_object = new DocumentObject(
DocumentType::SHIPPING_INVOICE,
[chunk_split('data:application/pdf;base64,'.base64_encode($transaction_invoice_pdf->output()))],
'',
ApprovalStatus::COMPLETED,
'shipping_invoice'
);
/** @var Document $document */
$document = $this->createsDocument->execute($invoice_transaction, $document_object);
$this->createsFiles->execute($document, $document_object);
$user = $packing_list->owner->companyModule->employees()->first();
if(app()->environment(['production'])) {
$user->notify(new InvoiceIssuedEmail($user, $packing_list));
}
return $this->response([]);
}
}
@@ -4,9 +4,27 @@ namespace App\Classes\Modules\Transactions\Services;
use App\Classes\General\Eloquent\AbstractUpdateRecord;
use App\Models\Transaction;
use App\Classes\Modules\PerfexCRM\Processors\TransactionToPerfexCRMProcessor;
use App\Classes\Modules\PerfexCRM\Processors\NewLeadTaskToPerfexCRMProcessor;
class UpdatesTransactionStatus extends AbstractUpdateRecord
{
/** @var TransactionToPerfexCRMProcessor */
private $transactionToPerfexCRMProcessor;
/** @var NewLeadTaskToPerfexCRMProcessor */
private $newLeadTaskToPerfexCRMProcessor;
/**
* UpdatesTransactionStatus constructor.
* @param TransactionToPerfexCRMProcessor $transactionToPerfexCRMProcessor
* @param NewLeadTaskToPerfexCRMProcessor $newLeadTaskToPerfexCRMProcessor
*/
public function __construct(TransactionToPerfexCRMProcessor $transactionToPerfexCRMProcessor, NewLeadTaskToPerfexCRMProcessor $newLeadTaskToPerfexCRMProcessor)
{
$this->transactionToPerfexCRMProcessor = $transactionToPerfexCRMProcessor;
$this->newLeadTaskToPerfexCRMProcessor = $newLeadTaskToPerfexCRMProcessor;
}
/**
* @param Transaction $model
@@ -16,7 +34,11 @@ class UpdatesTransactionStatus extends AbstractUpdateRecord
*/
public function execute(Transaction $model, int $status)
{
if(config('perfexcrm.is_enabled') == 'true'){
$this->transactionToPerfexCRMProcessor->execute($model, $status);
// $this->newLeadTaskToPerfexCRMProcessor->execute();
}
$model->status = $status;
return $this->handler($model);
}
}
}
@@ -18,4 +18,14 @@ final class ApprovalStatus {
public const EXPIRED = 6;
public const APPROVAL_STATUS_ID = [
self::PENDING_SUBMISSION => "Pending Submission",
self::PENDING_VERIFICATION => "Pending Verification",
self::APPROVED => "Approved",
self::COMPLETED => "Completed",
self::REJECTED => "Rejected",
self::SUSPENDED => "Suspended",
self::EXPIRED => "Expired",
];
}
@@ -0,0 +1,12 @@
<?php
namespace App\Classes\ValueObjects\Constants;
class PerfexCRMMilestones
{
public const MILESTONE_1 = 'MILESTONE 1 - Customer Paid';
public const MILESTONE_2 = 'MILESTONE 2 - Order Placed';
public const MILESTONE_3 = 'MILESTONE 3 - Purchase Order Approved';
public const MILESTONE_4 = 'MILESTONE 4';
public const MILESTONE_5 = 'MILESTONE 5';
}
@@ -0,0 +1,17 @@
<?php
namespace App\Classes\ValueObjects\Constants;
final class PerfexCRMStatus {
public const NOT_STARTED = 1;
public const AWAITING_FEEDBACK = 2;
public const TESTING = 3;
public const IN_PROGRESS = 4;
public const COMPLETED = 5;
}
@@ -0,0 +1,76 @@
<?php
namespace App\Classes\ValueObjects\Constants;
class PerfexCRMTasks
{
public const TASK_1 = [
'name' => 'Customer Paid',
'description' => '',
'milestone' => 'MILESTONE 1 - Customer Paid',
'reference' => '',
'on_task_completion' => '',
'status' => PerfexCRMStatus::COMPLETED
];
public const TASK_POST_PAYMENT_1 = [
'name' => 'Map Bank Transaction Record',
'description' => ' Purpose: To map a transaction to bank transaction in the bank statement<br>
Initial Status: In Progress<br>
Deadline: Same day<br>
Responsible department: Accounts<br>
Next step: Change the status of the Approve payment status to "In Progress" upon successful completion of the operation.<br>
Additional details: ** Any specific requirements or notes for the operation.**<br>
Dependencies: None<br>
Outcomes: Bank transaction is mapped successfully, allowing the next steps in the process to be initiated.<br>',
'milestone' => '',
'reference' => 'TASK_POST_PAYMENT_1',
'on_task_completion' => 'TASK_POST_PAYMENT_2',
'status' => PerfexCRMStatus::IN_PROGRESS
];
public const TASK_POST_PAYMENT_2 = [
'name' => 'Approve Payment',
'description' => ' Purpose: To verify and approve the customer\'s payment on IZYIM<br>
Initial Status: Not Started<br>
Deadline:Same day<br>
Responsible department: Accounts<br>
Next step: Change the status of the Issue Shipping Autocount Invoice operation to "In Progress"<br>
Additional details: When the payment method is FPX or Wallet this task is performed automatically by the system.<br>
Dependencies: Map Transaction operation must be completed before this operation can begin.<br>
Outcomes: The payment will be approved in IZYIM, which will release the customers goods for delivery.<br>',
'milestone' => '',
'reference' => 'TASK_POST_PAYMENT_2',
'on_task_completion' => 'TASK_POST_PAYMENT_3',
'status' => ''
];
public const TASK_POST_PAYMENT_3 = [
'name' => 'Issue Shipping Autocount Invoince',
'description' => ' Purpose: To issue an invoice for the customer\'s payment in accounting software.<br>
Initial Status: Not Started<br>
Deadline: Next day<br>
Responsible department: Accounts<br>
Next step: Change the status of the Knockoff Invoice operation to "In Progress" upon successful completion.<br>
Additional details: ** Any specific requirements or notes for the operation.**<br>
Dependencies: Approve Payment operation must be completed before this operation can begin.<br>
Outcomes: An invoice will be issued in accounting software for the customer\'s payment.<br>',
'milestone' => '',
'reference' => 'TASK_POST_PAYMENT_3',
'on_task_completion' => 'TASK_POST_PAYMENT_4',
'status' => ''
];
public const TASK_POST_PAYMENT_4 = [
'name' => 'Knockoff Invoice',
'description' => ' Purpose: The purpose of this operation is to issue the official receipt and knockoff with invoice for the customer\'s payment.<br>
Initial Status: Not Started<br>
Deadline: Next day.<br>
Responsible Department: Accounts<br>
Next Step: None<br>
Additional Details: ** Any specific requirements or notes for the operation.**<br>
Dependencies: Issue Shipping Autocount Invoice operation must be completed before this operation can begin.<br>
Outcomes: The customers payment is applied to the accounting software invoice and invoice is marked as paid.<br>',
'milestone' => '',
'reference' => 'TASK_POST_PAYMENT_4',
'on_task_completion' => '',
'status' => ''
];
}
@@ -0,0 +1,11 @@
<?php
namespace App\Classes\ValueObjects\Constants;
final class RouteType {
public const WEB = 1;
public const API = 2;
}
+83
View File
@@ -0,0 +1,83 @@
<?php
namespace App\Console\Commands;
use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject;
use App\Classes\Modules\Documents\Services\CreatesDocument;
use App\Classes\Modules\Documents\Services\CreatesFiles;
use App\Classes\Modules\PackingLists\Services\ListsPackingLists;
use App\Classes\Modules\Transactions\Processors\CreateInvoiceTransactionProcessor;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\DocumentType;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\CompanyConnection;
use App\Models\Order;
use Carbon\Carbon;
use Exception;
use Illuminate\Console\Command;
use Mccarlosen\LaravelMpdf\Facades\LaravelMpdf;
class FixInvoice extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'invoice:fix {--marking=}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Fix Invoice By Company Module Marking';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$connection = CompanyConnection::where('invitee_reference', $this->option('marking'))->first();
$company_module_id = $connection->invitee->id;
$orders = Order::where('company_module_id', $company_module_id)->get();
foreach ($orders as $order){
$invoices = $order->transactions()->where('transactions.type', TransactionType::SHIPPING_INVOICE)->get();
foreach ($invoices as $invoice){
dump($invoice->id);
$invoice->documents()->delete();
$transaction_invoice_pdf = LaravelMpdf::loadView('pages.pdfs.shipping_invoice', ['invoice_transaction' => $invoice]);
$document_object = new DocumentObject(
DocumentType::SHIPPING_INVOICE,
[chunk_split('data:application/pdf;base64,'.base64_encode($transaction_invoice_pdf->output()))],
'',
ApprovalStatus::COMPLETED,
'shipping_invoice'
);
/** @var Document $document */
$document = (App()->make(CreatesDocument::class))->execute($invoice, $document_object);
(App()->make(CreatesFiles::class))->execute($document, $document_object);
}
}
}
}
+59
View File
@@ -0,0 +1,59 @@
<?php
namespace App\Console\Commands;
use App\Classes\Modules\Transactions\Processors\ApproveShippingInvoiceTransactionProcessor;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\TransactionType;
use App\Models\Transaction;
use Exception;
use Illuminate\Console\Command;
class approveInvoice extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'approve:invoice';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Command description';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$invoices = Transaction::where('type', TransactionType::SHIPPING_INVOICE)->where('status', ApprovalStatus::PENDING_SUBMISSION)->get();
foreach ($invoices as $invoice) {
$packingList = $invoice->owner;
$order = $packingList->owner;
try {
(App()->make(ApproveShippingInvoiceTransactionProcessor::class))->execute($packingList);
$this->info('Invoice Approved for reference ' . $order->reference . '.');
} catch (Exception $exception) {
$this->info('Failed to Approve invoice for reference ' . $order->reference . '. Exception: ' . $exception->getMessage());
}
}
}
}
+17 -12
View File
@@ -28,25 +28,30 @@ class Kernel extends ConsoleKernel
protected function schedule(Schedule $schedule)
{
$schedule->command('command:curlVTCommand')
->cron('0 8 * * *')
->withoutOverlapping()
->appendOutputTo (storage_path().'/logs/curlvt.log');
// $schedule->command('command:curlVTCommand')
// ->cron('0 8 * * *')
// ->withoutOverlapping()
// ->appendOutputTo (storage_path().'/logs/curlvt.log');
$schedule->command('command:curlYdOrderListCommand')
->cron('30 9-18/3 * * *')
->withoutOverlapping()
->appendOutputTo (storage_path().'/logs/curlyd.log');
// $schedule->command('command:curlYdOrderListCommand')
// ->cron('30 9-18/3 * * *')
// ->withoutOverlapping()
// ->appendOutputTo (storage_path().'/logs/curlyd.log');
$schedule->command('command:curlYdOrderListCommand')
->cron('0 9 * * *')
->withoutOverlapping()
->appendOutputTo (storage_path().'/logs/departure_email.log');
// $schedule->command('command:curlYdOrderListCommand')
// ->cron('0 9 * * *')
// ->withoutOverlapping()
// ->appendOutputTo (storage_path().'/logs/departure_email.log');
$schedule->command('invoice:generate')
->hourly()
->withoutOverlapping()
->appendOutputTo (storage_path().'/logs/auto_generate_invoice.log');
$schedule->command('approve:invoice')
->hourly()
->withoutOverlapping()
->appendOutputTo (storage_path().'/logs/approve_invoice.log');
}
/**
@@ -0,0 +1,20 @@
<?php
namespace App\Http\Controllers\Addresses;
use App\Classes\Modules\Addresses\ControllersLogic\CreateBillingAddressLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class CreateBillingAddressController
{
/**
* @param Request $request
* @param CreateBillingAddressLogic $logic
* @return JsonResponse
*/
public function create(Request $request, CreateBillingAddressLogic $logic): JsonResponse {
return $logic->execute($request);
}
}
@@ -0,0 +1,15 @@
<?php
namespace App\Http\Controllers\Transactions;
use App\Classes\Modules\Transactions\ControllersLogic\CreateCombinedInvoicesLogic;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class CreateCombinedInvoicesController
{
public function combine(Request $request, CreateCombinedInvoicesLogic $logic): JsonResponse {
return $logic->execute($request);
}
}
+2
View File
@@ -38,11 +38,13 @@ class Kernel extends HttpKernel
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
// \App\Http\Middleware\WebRouteLogs::class,
],
'api' => [
'throttle:300,1',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
// \App\Http\Middleware\ApiRouteLogs::class,
],
];
+64
View File
@@ -0,0 +1,64 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
use App\Models\RouteLog;
use App\Classes\ValueObjects\Constants\RouteType;
use Illuminate\Support\Facades\Auth;
class ApiRouteLogs
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
public function handle(Request $request, Closure $next)
{
$ip_address = getenv('REMOTE_ADDR') == '::1' ? '127.0.0.1' : getenv('REMOTE_ADDR');
$url = urldecode($request->fullUrl());
$request_method = $request->method();
$platform = $request->header('sec-ch-ua-platform');
$browser = Str::after($request->header('sec-ch-ua'), 'Not?A_Brand";v="8", "Chromium";v="108", "');
$geo = unserialize(file_get_contents("http://www.geoplugin.net/php.gp?ip=$ip_address"));
$longitude = $geo["geoplugin_longitude"];
$latitude = $geo["geoplugin_latitude"];
$last_page = url()->previous();
$countryName = $geo["geoplugin_countryName"];
$user_id = Auth::user() ? Auth::user()->id : 0;
// if ($user_id != 0) {
// // $ip_address
// $webRouteLogWithSameIp = RouteLog::where('ip_address', $ip_address)->where('user_id', 0)->get();
// dd($webRouteLogWithSameIp);
// foreach($webRouteLogWithSameIp as $result){
// $result
// }
// }
$route_log = [
'user_id' => $user_id,
// 'ip_address' => $request->ip(),
'ip_address' => $ip_address,
'url' => $url,
'request_method' => $request_method,
'browser' => $browser,
'platform' => $platform,
'longitude' => $longitude,
'latitude' => $latitude,
'last_page' => $last_page,
'countryname' => $countryName,
'route_type' => RouteType::API,
];
RouteLog::create($route_log);
return $next($request);
}
}
+55
View File
@@ -0,0 +1,55 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
use App\Models\RouteLog;
use App\Classes\ValueObjects\Constants\RouteType;
use Illuminate\Support\Facades\Auth;
class WebRouteLogs
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
public function handle(Request $request, Closure $next)
{
$ip_address = getenv('REMOTE_ADDR') == '::1' ? '127.0.0.1' : getenv('REMOTE_ADDR');
$url = $request->fullUrl();
$request_method = $request->method();
$platform = $request->header('sec-ch-ua-platform');
$browser = Str::after($request->header('sec-ch-ua'), 'Not?A_Brand";v="8", "Chromium";v="108", "');
$geo = unserialize(file_get_contents("http://www.geoplugin.net/php.gp?ip=$ip_address"));
$longitude = $geo["geoplugin_longitude"];
$latitude = $geo["geoplugin_latitude"];
$last_page = url()->previous();
$countryName = $geo["geoplugin_countryName"];
$route_log = [
'user_id' => Auth::user() ? Auth::user()->id : 0,
// 'ip_address' => $request->ip(),
'ip_address' => $ip_address,
'url' => $url,
'request_method' => $request_method,
'browser' => $browser,
'platform' => $platform,
'longitude' => $longitude,
'latitude' => $latitude,
'last_page' => $last_page,
'countryname' => $countryName,
'route_type' => RouteType::WEB,
];
// dd($route_log);
RouteLog::create($route_log);
return $next($request);
}
}
-120
View File
@@ -1,120 +0,0 @@
<?php
namespace App\Models;
use App\Classes\General\Interfaces\Documentable;
use App\Classes\General\Interfaces\Transactionable;
use App\Classes\General\Traits\LogData;
use App\Classes\ValueObjects\Constants\RoleTypes;
use App\Scopes\CustomerBookingsScope;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Staudenmeir\EloquentHasManyDeep\HasManyDeep;
use Staudenmeir\EloquentHasManyDeep\HasRelationships;
/**
* Class Booking
* @package App\Models
*
* @property \App\Models\Company company_id
* @property \App\Models\Bank transferable_bank_id
* @property string marking
* @property string reference
* @property float fix_amount
* @property int convertible_currency_id
* @property int conversion_currency_id
*/
class Booking extends AbstractModel implements Documentable, Transactionable
{
use HasRelationships;
use SoftDeletes;
use LogData;
protected $table = 'bookings';
protected $dates = ['deleted_at'];
/**
* @return BelongsTo
*/
public function company(): BelongsTo
{
return $this->BelongsTo(Company::class, 'company_id')->withTrashed();
}
/**
* @return BelongsTo
*/
public function service(): BelongsTo
{
return $this->BelongsTo(ServiceType::class, 'service_id');
}
/**
* @return BelongsTo
*/
public function bank(): BelongsTo
{
return $this->BelongsTo(Bank::class, 'bank_id')->withTrashed();
}
/**
* @return BelongsTo
*/
public function fixedCurrency(): BelongsTo
{
return $this->BelongsTo(Currency::class, 'fix_currency_id');
}
/**
* @return BelongsTo
*/
public function convertibleCurrency(): BelongsTo
{
return $this->BelongsTo(Currency::class, 'convertible_currency_id');
}
/**
* @return BelongsTo
*/
public function conversionCurrency(): BelongsTo
{
return $this->BelongsTo(Currency::class, 'conversion_currency_id');
}
/**
* @return MorphMany
*/
public function documents(): MorphMany
{
return $this->MorphMany(Document::class, 'owner');
}
/**
* @return MorphMany
*/
public function transactions(): MorphMany
{
return $this->MorphMany(Transaction::class, 'owner');
}
/**
* @return hasManyDeep
*/
public function bills(): hasManyDeep
{
return $this->hasManyDeep(Transaction::class, [Transaction::class.' as alias'], [['owner_type', 'owner_id'], ['owner_type', 'owner_id']], [null, null]);
}
protected static function booted()
{
if (auth()->user()) {
if (auth()->user()->type === RoleTypes::USER) {
static::addGlobalScope(new CustomerBookingsScope);
}
}
}
}
+25
View File
@@ -0,0 +1,25 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class RouteLog extends Model
{
use HasFactory;
protected $fillable = [
'user_id',
'ip_address',
'url',
'request_method',
'browser',
'platform',
'longitude',
'latitude',
'last_page',
'countryname',
'route_type'
];
}
+2 -1
View File
@@ -2,6 +2,7 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphMany;
@@ -25,7 +26,7 @@ class User extends AbstractModel implements
AuthorizableContract,
CanResetPasswordContract
{
use HasRoles, Notifiable, Authenticatable, Authorizable, CanResetPassword, MustVerifyEmail, SoftDeletes;
use HasRoles, Notifiable, Authenticatable, Authorizable, CanResetPassword, MustVerifyEmail, SoftDeletes, HasFactory;
protected $dates = ['deleted_at'];
+12
View File
@@ -0,0 +1,12 @@
paths:
tests: tests
output: tests/_output
data: tests/_data
support: tests/_support
envs: tests/_envs
actor_suffix: Tester
extensions:
enabled:
- Codeception\Extension\RunFailed
params:
- .env.testing
+13 -2
View File
@@ -2,20 +2,24 @@
"name": "laravel/laravel",
"type": "project",
"description": "The Laravel Framework.",
"keywords": ["framework", "laravel"],
"keywords": [
"framework",
"laravel"
],
"license": "MIT",
"require": {
"php": "^7.3",
"ext-fileinfo": "^7.3",
"ext-json": "*",
"barryvdh/laravel-dompdf": "^0.9.0",
"carlos-meneses/laravel-mpdf": "^2.1",
"carlos-meneses/laravel-mpdf": "*",
"doctrine/dbal": "^3.1",
"fideloper/proxy": "^4.4",
"fruitcake/laravel-cors": "^2.0",
"guzzlehttp/guzzle": "^7.0.1",
"intervention/image": "^2.5",
"laravel/framework": "^8.40",
"laravel/legacy-factories": "^1.3",
"laravel/tinker": "^2.5",
"maatwebsite/excel": "^3.1",
"rinvex/countries": "^6.1",
@@ -25,6 +29,13 @@
"tymon/jwt-auth": "^1.0"
},
"require-dev": {
"barryvdh/laravel-ide-helper": "^2.12",
"codeception/codeception": "^4.2",
"codeception/module-asserts": "^2.0",
"codeception/module-laravel": "^2.3",
"codeception/module-phpbrowser": "^2.0",
"codeception/module-rest": "^2.0",
"codeception/module-webdriver": "^2.0",
"facade/ignition": "^2.5",
"fakerphp/faker": "^1.9.1",
"laravel/sail": "^1.0.1",
+7
View File
@@ -0,0 +1,7 @@
<?php
return [
'base_url' => env('PERFEXCRM_BASE_URL', 'http://192.168.1.100:8084'), //cief todo: Update crm api domain here
'api_key' => env('PERFEXCRM_API_KEY', ''),
'is_enabled' => env('PERFEXCRM_IS_ENABLED', 'true'),
];
-14
View File
@@ -25,23 +25,9 @@ class UserFactory extends Factory
return [
'name' => $this->faker->name(),
'email' => $this->faker->unique()->safeEmail(),
'email_verified_at' => now(),
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
'remember_token' => Str::random(10),
];
}
/**
* Indicate that the model's email address should be unverified.
*
* @return \Illuminate\Database\Eloquent\Factories\Factory
*/
public function unverified()
{
return $this->state(function (array $attributes) {
return [
'email_verified_at' => null,
];
});
}
}
@@ -0,0 +1,42 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateRouteLogsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('route_logs', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->unsigned();
$table->string('ip_address');
$table->string('url', 255);
$table->string('request_method');
$table->string('browser')->nullable();
$table->string('platform')->nullable();
$table->string('longitude')->nullable();
$table->string('latitude')->nullable();
$table->string('last_page')->nullable();
$table->string('countryname')->nullable();
$table->integer('route_type');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('route_logs');
}
}
+40
View File
@@ -0,0 +1,40 @@
version: '3'
services:
web:
build:
context: .
args:
PHP_VERSION: 7.4
ports:
- "9000:9000"
db:
image: mysql:5.7
environment:
MYSQL_DATABASE: laravel
MYSQL_USER: laravel
MYSQL_PASSWORD: secret
MYSQL_ROOT_PASSWORD: secret
ports:
- "3306:3306"
tests:
build:
context: .
args:
PHP_VERSION: 7.4
command: bash -c "composer install && php artisan migrate --seed && vendor/bin/phpunit"
links:
- db
- redis
acceptance:
image: node:14
working_dir: /app
volumes:
- ./:/app
command: bash -c "npm install && gulp build"
links:
- web
- redis
redis:
image: redis:6.0
ports:
- "6379:6379"
+28
View File
@@ -0,0 +1,28 @@
FROM php:7.4-fpm
WORKDIR /var/www/html
RUN docker-php-ext-install pdo pdo_mysql
RUN apt-get update && apt-get install -y \
libfreetype6-dev \
libjpeg62-turbo-dev \
libpng-dev \
libzip-dev \
zip \
cron \
supervisor \
nano \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install -j$(nproc) gd \
&& docker-php-ext-install zip \
&& docker-php-ext-install bcmath
COPY --from=composer:1.9.3 /usr/bin/composer /usr/bin/composer
#NODEJS & NPM
RUN curl -sL https://deb.nodesource.com/setup_12.x | bash -
RUN apt-get -y install nodejs
RUN chown -R www-data:www-data /var/www
RUN chmod 755 /var/www
+54
View File
@@ -0,0 +1,54 @@
version: '3'
networks:
shipping-portal-staging:
services:
#################################################################
nginx:
image: nginx:stable-alpine
container_name: shipping-portal-ngnix
ports:
- "8081:80"
volumes:
- ../:/var/www/html
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
depends_on:
- php
- mysql
networks:
- shipping-portal-staging
#################################################################
mysql:
image: mysql:5.7.29
container_name: shipping-portal-mysql
restart: unless-stopped
tty: true
ports:
- 3307:3306
environment:
MYSQL_ROOT_USER: root
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: shipping-portal-db
MYSQL_USER: master
MYSQL_PASSWORD: cDe7gcrRBWetaAP
volumes:
- mysql-data:/var/lib/mysql
networks:
- shipping-portal-staging
#################################################################
php:
build:
context: .
dockerfile: Dockerfile
container_name: shipping-portal-php
volumes:
- ../:/var/www/html
ports:
- "9001:9000"
networks:
- shipping-portal-staging
#################################################################
volumes:
mysql-data:
+27
View File
@@ -0,0 +1,27 @@
server {
listen 80;
index index.php index.html;
server_name localhost;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
root /var/www/html/public;
server_name localhost;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_intercept_errors on;
fastcgi_keep_conn on;
fastcgi_param PHP_VALUE "auto_prepend_file= \n allow_url_include=Off \n output_buffering=Off \n output_buffering=4096";
}
}
+2 -2
View File
@@ -21,8 +21,8 @@
<server name="APP_ENV" value="testing"/>
<server name="BCRYPT_ROUNDS" value="4"/>
<server name="CACHE_DRIVER" value="array"/>
<!-- <server name="DB_CONNECTION" value="sqlite"/> -->
<!-- <server name="DB_DATABASE" value=":memory:"/> -->
<server name="DB_CONNECTION" value="sqlite"/>
<server name="DB_DATABASE" value=":memory:"/>
<server name="MAIL_MAILER" value="array"/>
<server name="QUEUE_CONNECTION" value="sync"/>
<server name="SESSION_DRIVER" value="array"/>
@@ -198,6 +198,9 @@
},
methods:{
submitForm(){
if (this.type) {
this.parameters.type = this.type;
}
this.submit(this.data ? (this.route('api.address.update', this.data.id)) : (this.route('api.address.create')), this.data ? 'put' : 'post', 'addressList', true, true);
},
},
@@ -0,0 +1,124 @@
<style>
@media screen and (min-width: 570px) {
.extend-modal-body{
width: 700px;
max-width: calc(100% - 20px);
}
}
</style>
<template>
<div class="row m-b-20 bg-white text-black padding-15 rounded extend-modal-body">
<div class="col">
<div class="row m-b-20 text-info">
<div class="col text-center">
<h3>Please select the <b>Billing Address</b></h3>
</div>
</div>
<div class="row b-rounded justify-content-center m-b-15" @click="updateBillingAddressFilters">
<div class="col col-md-10 bg-master-lightest margin-auto padding-15">
<div class="row justify-content-center">
<div class="col pointer d-flex justtify-content-center align-items-center">
<i class="fa fs-30 fa-fw" :class="{'fa-square-o': !useDeliveryAddress, 'fa-check-square': useDeliveryAddress, 'text-primary':useDeliveryAddress}" ></i>
<p class="m-b-0">Use Delivery Address</p>
</div>
</div>
</div>
</div>
<div class="row justify-content-center m-b-15" v-if="error">
<div class="col-10">
<small class="text-danger">{{error}}</small>
</div>
</div>
<div class="row justify-content-center">
<div class="col col-md-10">
<list-component :key="currentKey" style="min-height: 50px;" section="addressList" :emptyListSection=false :endpoint="route('api.address.list')" :options="billingAddressFilters">
<template slot="list" slot-scope="{data}">
<select-address-component :data="data" :value="parameters.billing_address_id" v-model="parameters.billing_address_id"></select-address-component>
</template>
</list-component>
<div class="row m-b-10 animate__animated animate__fadeInUpBig animate__delay-1 animate__fast">
<div class="col b-a p-t-15 p-b-15 pointer" :class="{ 'b-primary': !parameters.billing_address_id, 'b-grey': parameters.billing_address_id}" @click="parameters.billing_address_id = null">
<div class="row align-items-center">
<div class="col-auto p-r-0">
<i class="fa fs-20 p-t-5" :class="{'fa-circle-o': parameters.billing_address_id, 'fa-check-circle': !parameters.billing_address_id, 'text-primary': !parameters.billing_address_id}"></i>
</div>
<div class="col-auto semi-bold">New Address</div>
</div>
<div class="row" v-show="!parameters.billing_address_id">
<div class="col">
<address-form-component :type="1" :id="company_module_id" section="addressList" @input="parameters.billing_address_id = $event"></address-form-component>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col"></div>
<div class="col-auto">
<button type="button" class="btn btn-lg rounded btn-primary" v-if="parameters.billing_address_id" @click="submitForm()">Confirm</button>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
section: {
type: String,
default: 'addressList'
},
company_module_id: {
type: Number,
default: 1
},
},
data(){
return {
useDeliveryAddress: false,
isLoading: false,
error: '',
billingAddressFilters: {
per_page: 10,
HasMorphCompanyModule: this.company_module_id,
ownerType: 'App\\Models\\CompanyModule',
type: 1
},
parameters : {
company_module_id: this.company_module_id,
billing_address_id: null,
},
item:{
id:null
},
currentKey: 1,
}
},
methods: {
updateBillingAddressFilters(){
if(this.useDeliveryAddress) {
// if use delivery address
this.billingAddressFilters = {
per_page: 10,
HasMorphCompanyModule: this.company_module_id,
type: 1
}
this.parameters.billing_address_id = '';
} else {
this.billingAddressFilters = {per_page: 10, HasMorphCompanyModule: this.company_module_id,};
}
this.useDeliveryAddress = !this.useDeliveryAddress;
this.currentKey++;
},
submitForm(){
this.submit(this.route('api.address.billingAddress.create'), 'post', this.section, true, true)
},
successHandler(response){
this.closeModal();
location.reload();
},
}
}
</script>
@@ -58,6 +58,12 @@
</div>
</div>
</div>
<div class="col-auto">
<div class="btn-lg btn-primary b-a b-white pointer fs-14 position-relative bg-transparent requestModal" data-type="billingAddressComponent" style="z-index: 2;">Change Billing Address</div>
</div>
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="billingAddressComponent">
<billing-address-section-component :company_module_id="company.company_module.id" :section="section"></billing-address-section-component>
</modal-component>
</div>
</div>
</div>
@@ -72,7 +72,7 @@
</div>
</div>
</div>
<div class="row justify-content-center" v-if="step === 2">
<div class="row justify-content-center" v-if="step === 2 && !chooseBillingAddress">
<div class="col col-md-10">
<div class="row m-b-20">
<div class="col">
@@ -88,7 +88,7 @@
</div>
<div class="row justify-content-center">
<div class="col col-md-10">
<list-component style="min-height: 50px;" section="addressList" :emptyListSection=false :endpoint="route('api.address.list')" :options="{per_page: 10, HasMorphCompanyModule: company.company_module.id}">
<list-component style="min-height: 50px;" section="addressList" :emptyListSection=false :endpoint="route('api.address.list')" :options="{per_page: 10, HasMorphCompanyModule: company.company_module.id, type:2}">
<template slot="list" slot-scope="{data}">
<select-address-component :data="data" :value="parameters.address_id" v-model="parameters.address_id"></select-address-component>
</template>
@@ -119,7 +119,72 @@
<button type="button" class="btn btn-lg btn-default b-rad-none" @click="step--">back</button>
</div>
<div class="col p-l-5">
<button type="button" class="btn btn-lg btn-block btn-primary b-rad-none" @click="createOrder()" v-if="parameters.address_id">Create Order</button>
<button type="button" class="btn btn-lg btn-block btn-primary b-rad-none" @click="createOrder()" v-if="parameters.address_id && company.company_module.billingAddress">Create Order</button>
<button type="button" class="btn btn-lg btn-block btn-primary b-rad-none" @click=" chooseBillingAddress = !chooseBillingAddress" v-if="parameters.address_id && !company.company_module.billingAddress">Select Billing Address</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row justify-content-center" v-if="step === 2 && chooseBillingAddress">
<div class="col col-md-10">
<div class="row m-b-20">
<div class="col">
<div class="row m-b-20 text-info">
<div class="col text-center">
<h3>Please select the <b>Billing Address</b></h3>
</div>
</div>
<div class="row b-rounded justify-content-center m-b-15" @click="updateBillingAddressFilters">
<div class="col col-md-10 bg-master-lightest margin-auto padding-15">
<div class="row justify-content-center">
<div class="col pointer d-flex justtify-content-center align-items-center">
<i class="fa fs-30 fa-fw" :class="{'fa-square-o': !useDeliveryAddress, 'fa-check-square': useDeliveryAddress, 'text-primary':useDeliveryAddress}" ></i>
<p class="m-b-0">Use Delivery Address</p>
</div>
</div>
</div>
</div>
<div class="row justify-content-center m-b-15" v-if="error">
<div class="col-10">
<small class="text-danger">{{error}}</small>
</div>
</div>
<div class="row justify-content-center">
<div class="col col-md-10">
<list-component :key="currentKey" style="min-height: 50px;" section="addressList" :emptyListSection=false :endpoint="route('api.address.list')" :options="billingAddressFilters">
<template slot="list" slot-scope="{data}">
<select-address-component :data="data" :value="parameters.billing_address_id" v-model="parameters.billing_address_id"></select-address-component>
</template>
</list-component>
<div class="row m-b-10 animate__animated animate__fadeInUpBig animate__delay-1 animate__fast">
<div class="col b-a p-t-15 p-b-15 pointer" :class="{ 'b-primary': !parameters.billing_address_id, 'b-grey': parameters.billing_address_id}" @click="parameters.billing_address_id = null">
<div class="row align-items-center">
<div class="col-auto p-r-0">
<i class="fa fs-20 p-t-5" :class="{'fa-circle-o': parameters.billing_address_id, 'fa-check-circle': !parameters.billing_address_id, 'text-primary': !parameters.billing_address_id}"></i>
</div>
<div class="col-auto semi-bold">New Address</div>
</div>
<div class="row" v-show="!parameters.billing_address_id">
<div class="col">
<address-form-component :type="1" :id="company.company_module.id" section="addressList" @input="parameters.billing_address_id = $event"></address-form-component>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row justify-content-center animate__animated animate__fadeInUpBig animate__delay-1 animate__fast">
<div class="col col-md-8 no-padding">
<div class="row">
<div class="col-auto p-r-5">
<button type="button" class="btn btn-lg btn-default b-rad-none" @click="chooseBillingAddress = !chooseBillingAddress">back</button>
</div>
<div class="col p-l-5">
<button type="button" class="btn btn-lg btn-block btn-primary b-rad-none" @click="createOrder()" v-if="parameters.billing_address_id">Create Order</button>
</div>
</div>
</div>
@@ -172,11 +237,20 @@
return {
section: 'createOrderForm',
step: 1,
currentKey: 1,
error: '',
chooseBillingAddress: false,
useDeliveryAddress: false,
billingAddressFilters: {
per_page: 10,
HasMorphCompanyModule: this.company.company_module.id,
type: 1
},
parameters : {
warehouse_id: '',
address_id: '',
company_id: this.company.id,
billing_address_id: '',
}
}
},
@@ -205,6 +279,21 @@
alert(response.message)
this.error = response.message;
this.step--;
},
updateBillingAddressFilters(){
if(this.useDeliveryAddress) {
// if use delivery address
this.billingAddressFilters = {
per_page: 10,
HasMorphCompanyModule: this.company.company_module.id,
type: 1
}
this.parameters.billing_address_id = '';
} else {
this.billingAddressFilters = {per_page: 10, HasMorphCompanyModule: this.company.company_module.id};
}
this.useDeliveryAddress = !this.useDeliveryAddress;
this.currentKey++;
}
}
}
@@ -1,66 +0,0 @@
<template>
<div class="row bg-white padding-25">
<div class="col">
<div class="row m-b-20 text-info">
<div class="col text-center">
<h3>Please select the address where you want to receive this order</h3>
</div>
</div>
<div class="row justify-content-center m-b-15" v-if="error">
<div class="col-10">
<small class="text-danger">{{error}}</small>
</div>
</div>
<div class="row justify-content-center">
<div class="col col-md-10">
<list-component style="min-height: 50px;" class="m-b-20" section="addressList" :emptyListSection=false :endpoint="route('api.address.list')" :options="{per_page: 5, HasMorphCompanyModule: data.order.company_module.id}">
<template slot="list" slot-scope="{data}">
<select-address-component :data="data" :value="parameters.address_id" v-model="parameters.address_id"></select-address-component>
</template>
</list-component>
<div class="row m-b-10 animate__animated animate__fadeInUpBig animate__delay-1 animate__fast">
<div class="col b-a p-t-15 p-b-15 pointer" :class="{ 'b-primary': !parameters.address_id, 'b-grey': parameters.address_id}" @click="parameters.address_id = null">
<div class="row align-items-center">
<div class="col-auto p-r-0">
<i class="fa fs-20 p-t-5" :class="{'fa-circle-o': parameters.address_id, 'fa-check-circle': !parameters.address_id, 'text-primary': !parameters.address_id}"></i>
</div>
<div class="col-auto semi-bold">New Address</div>
</div>
<div class="row" v-show="!parameters.address_id">
<div class="col">
<address-form-component :id="data.order.company_module.id" section="addressList" @input="parameters.address_id = $event"></address-form-component>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row m-t-15 justify-content-center">
<div class="col-6 col-md-4 p-r-5">
<div class="btn btn-default w-100 btn-lg b-rad-none" data-dismiss="modal">Cancel</div>
</div>
<div class="col-6 col-md-4 p-l-5">
<!-- <div class="btn btn-primary w-100 btn-lg" @click="submit(route('api.segment.constant.update.postcode', 1), 'put', section, true, true)">Confirm</div> -->
<div class="btn btn-primary w-100 btn-lg">Confirm</div>
</div>
</div>
</div>
</div>
</template>
<script>
import modalFormHandler from '../../../general/mixins/modalFormHandler';
export default {
data() {
return {
error: '',
parameters : {
warehouse_id: '',
address_id: '',
}
}
},
mixins: [modalFormHandler]
}
</script>
@@ -1,179 +0,0 @@
@extends('layouts.base_portal')
@section('inner_content')
<div class="row">
<div class="col bg-white p-t-15 p-b-15">
<div class="row no-margin">
<div class="col-12">
<form method="post" >
@csrf
<div class="row">
<div class="col">
<input class="form-control" type="text" name="marking" placeholder="Marking" value="{{$marking}}">
</div>
<div class="col">
<input class="form-control" type="text" name="customer_email" placeholder="Email" value="{{$email}}">
</div>
<div class="col">
<input class="form-control" type="text" name="booking_reference" placeholder="Booking Reference" value="{{$bookingReference}}">
</div>
<div class="col-auto">
<button class="btn btn-complete" type="submit">Search</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col">
<main>
@if($company)
@php
$employees = $company->employees;
$primaryEmployee = $employees->first();
$identification = $company->documents->whereIn('document_type', \App\Classes\ValueObjects\Constants\DocumentType::IDENTIFICATION_DOCUMENTS)->first()
@endphp
<section id="customer-account" class="m-b-50">
<h3>Customer Account</h3>
<p>Marking: <span><a href="{{route('customer.profile', $company->reference)}}" target="_blank">{{$company->reference}}</a></span></p>
<p>Account Type: <span>{{$company->type === 1 ? 'Business' : 'Personal'}}</span></p>
@if($company->type === 1)<p>Company's Name: <span>{{$company->name}}</span></p>@endif
<p>Customer's Name: <span>{{$employees->pluck('name')->implode(', ')}}</span></p>
<p>Email: <span>{{$employees->pluck('email')->implode(', ')}}</span></p>
<p>Phone: <span>{{$company->contacts->pluck('phone')->implode(', ')}}</span></p>
<p>Registration Date: <span>{{$company->created_at->format('d-m-Y')}}</span></p>
</section>
<section id="customer-verification" class="m-b-50">
<h3>Customer Verification</h3>
<p>Email Verification Status: <span>{{ $primaryEmployee->status === 2 ? 'Verified' : 'Pending Verification'}}</span></p>
<p>Identification Verification Status: <span>{{$identification ? ($identification->status === 2 ? 'Verified' : 'Pending Verification') : 'Not Submitted'}}</span></p>
</section>
@if(!$booking)
<section>
<h3>Customer Bookings</h3>
@php
$bookings = $company->bookings()->whereIn('status', [2, 3])->get();
@endphp
<section>
@foreach($bookings as $booking)
@php
$payments = $booking->transactions()->where('type', \App\Classes\ValueObjects\Constants\TransactionType::PAYMENT)->get();
$purchaseOrder = $booking->transactions()->where('type', \App\Classes\ValueObjects\Constants\TransactionType::PURCHASE_ORDER)->first();
@endphp
<section class="m-b-50">
<h5 class="bold">Booking Reference: {{$booking->marking}}</h5>
<p>Amount: <span>{{$booking->fix_amount.' '.$booking->fixedCurrency->short_code}}</span></p>
<p>Status: <span>{{$booking->status === 3 ? 'Complete' : 'In Progress'}}</span></p>
<p>Purchase Order Status: <span>{{$purchaseOrder ? ($purchaseOrder->status === 3 ? 'Approved' : ($purchaseOrder->status === 1 ? 'Pending Approval' : 'Incomplete Submission')) : 'Pending Submission'}}</span></p>
@if($payments)<p class="m-t-35 bold">Payment History:</p>@endif
@php $i = 1; @endphp
@foreach($payments as $payment)
@php
$bill = $payment->transactions()->where('type', \App\Classes\ValueObjects\Constants\TransactionType::BILL)->first();
$transferProof = null;
$status = 'Pending Submission';
if($payment->status === 1) {
$status = 'Pending Approval';
}
if($payment->status === 2) {
$status = 'Pending Confirmation';
}
if(in_array($payment->status, [4, 5])) {
$status = 'Rejected/Failed Payment';
}
if($bill) {
if($bill->status === 1) {
$status = 'Pending Transfer Proof';
}
if(in_array($bill->status, [2, 3])) {
$status = 'Transfer Complete';
$transferProof = $bill->documents()->first();
}
}
@endphp
<section class="m-b-35">
<p>{{$i++}}.</p>
<p>Amount: <span>{{$payment->original_amount.' '.$payment->original_currency->short_code}}</span></p>
<p>Status: <span>{{$status}}</span></p>
<p>Payment Date: <span>{{$payment->created_at->format('d-m-Y')}}</span></p>
@if($bill)
<p>Supplier: <span>{{$bill->issuerCompany->name}}</span></p>
<p>Supplier Order Date: <span>{{$bill->created_at->format('d-m-Y')}}</span></p>
@if($transferProof)<p>Transfer Proof Upload Date: <span>{{$transferProof->created_at->format('d-m-Y')}}</span></p>@endif
@endif
</section>
@endforeach
</section>
@endforeach
</section>
</section>
@endif
@endif
@if($booking)
@php
$payments = $booking->transactions()->where('type', \App\Classes\ValueObjects\Constants\TransactionType::PAYMENT)->get();
$purchaseOrder = $booking->transactions()->where('type', \App\Classes\ValueObjects\Constants\TransactionType::PURCHASE_ORDER)->first();
@endphp
<section>
<h5 class="bold">Booking Reference: {{$booking->marking}}</h5>
<p>Amount: <span>{{$booking->fix_amount.' '.$booking->fixedCurrency->short_code}}</span></p>
<p>Status: <span>{{$booking->status === 3 ? 'Complete' : 'In Progress'}}</span></p>
<p>Purchase Order Status: <span>{{$purchaseOrder ? ($purchaseOrder->status === 3 ? 'Approved' : ($purchaseOrder->status === 1 ? 'Pending Approval' : 'Incomplete Submission')) : 'Pending Submission'}}</span></p>
@if($payments)<p class="m-t-35 bold">Payment History:</p>@endif
@php $i = 1; @endphp
@foreach($payments as $payment)
@php
$bill = $payment->transactions()->where('type', \App\Classes\ValueObjects\Constants\TransactionType::BILL)->first();
$transferProof = null;
$status = 'Pending Submission';
if($payment->status === 1) {
$status = 'Pending Approval';
}
if($payment->status === 2) {
$status = 'Pending Confirmation';
}
if(in_array($payment->status, [4, 5])) {
$status = 'Rejected/Failed Payment';
}
if($bill) {
if($bill->status === 1) {
$status = 'Pending Transfer Proof';
}
if(in_array($bill->status, [2, 3])) {
$status = 'Transfer Complete';
$transferProof = $bill->documents()->first();
}
}
@endphp
<section class="m-b-35">
<p>{{$i++}}.</p>
<p>Amount: <span>{{$payment->original_amount.' '.$payment->original_currency->short_code}}</span></p>
<p>Status: <span>{{$status}}</span></p>
<p>Payment Date: <span>{{$payment->created_at->format('d-m-Y')}}</span></p>
@if($bill)
<p>Supplier: <span>{{$bill->issuerCompany->name}}</span></p>
<p>Supplier Order Date: <span>{{$bill->created_at->format('d-m-Y')}}</span></p>
@if($transferProof)<p>Transfer Proof Upload Date: <span>{{$transferProof->created_at->format('d-m-Y')}}</span></p>@endif
@endif
</section>
@endforeach
</section>
@endif
</main>
</div>
</div>
@endsection
+2
View File
@@ -14,6 +14,8 @@ Route::group(['prefix' => 'address', 'as' => 'address.', 'namespace' => 'Address
Route::get('state/list', 'ListStatesController@list')->name('state.list');
Route::post('/create', 'CreateAddressController@create')->name('create');
Route::post('billingAddress/create', 'CreateBillingAddressController@create')->name('billingAddress.create');
Route::put('/update/{id}', 'UpdateAddressController@update')->name('update');
+7 -2
View File
@@ -13,13 +13,18 @@ Route::group(['prefix' => 'transactions', 'namespace' => 'Transactions', 'as' =>
Route::post('/upload-verification-document/{transaction_id}', 'UploadPaymentVerificationDocumentController@upload')->name('verification.create');
Route::put('/approve/{transaction_id}/{status}', 'ApprovePaymentTransactionController@approve')->where('status', 'approve|reject')->name('approval');
});
Route::group(['prefix' => 'invoice', 'as' => 'invoice.'], function () {
route::post('/shipping-invoice/create', 'CreateShippingInvoiceTransactionController@create')->name('create');
route::put('/shipping-invoice/{id}/update', 'UpdateShippingInvoiceTransactionController@update')->name('update');
route::put('/shipping-invoice/{id}/approve', 'ApproveShippingInvoiceTransactionController@approve')->name('approve');
});
Route::group(['prefix' => 'invoices', 'as' => 'invoices.'], function () {
route::put('/combine', 'CreateCombinedInvoicesController@combine')->name('combine');
});
route::post('/shipping-invoice/calculator', 'ShippingEstimationCalculatorController@calculate')->name('shipping.estimation.calculator');
// Route::group(['prefix' => '{id}/payment', 'as' => 'payment.'], function () {
@@ -34,4 +39,4 @@ Route::group(['prefix' => 'transactions', 'namespace' => 'Transactions', 'as' =>
// Route::post('booking/{id}/details/update', 'CreatePurchaseOrderTransactionController@create')->name('po.create');
});
});
+115 -62
View File
@@ -44,8 +44,6 @@ use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Route;
use Mccarlosen\LaravelMpdf\Facades\LaravelMpdf;
use App\Models\Company;
use App\Models\Booking;
/*
|--------------------------------------------------------------------------
@@ -729,6 +727,8 @@ Route::get('/invoices/fix/{company_module_id}', function($company_module_id) {
$document = (App()->make(CreatesDocument::class))->execute($invoice, $document_object);
(App()->make(CreatesFiles::class))->execute($document, $document_object);
dump($document);
}
}
@@ -744,33 +744,33 @@ Route::get('/invoices/combine/{ids}', function($ids){
return $pdf->download('combined_invoice_.pdf');
})->name('invoice.combined_summary');
Route::get('/generate/invoices', function(){
$packingLists = (App()->make(ListsPackingLists::class))->execute(['does_not_have_transaction_type' => 1, 'type' => 2]);
foreach ($packingLists as $packingList){
$order = $packingList->owner;
if(!($order instanceof Order)) {
echo '<span style="color: red;">failed to generate...</span><br>';
continue;
}
// Route::get('/generate/invoices', function(){
// $packingLists = (App()->make(ListsPackingLists::class))->execute(['does_not_have_transaction_type' => 1, 'type' => 2]);
// foreach ($packingLists as $packingList){
// $order = $packingList->owner;
// if(!($order instanceof Order)) {
// echo '<span style="color: red;">failed to generate...</span><br>';
// continue;
// }
$companyModule = $order->companyModule;
$billingAddress = $companyModule->addresses()->where('type', \App\Classes\ValueObjects\Constants\AddressType::BILLING)->first();
$deliveryAddress = $order->addresses()->where('status', ApprovalStatus::APPROVED)->first();
// $companyModule = $order->companyModule;
// $billingAddress = $companyModule->addresses()->where('type', \App\Classes\ValueObjects\Constants\AddressType::BILLING)->first();
// $deliveryAddress = $order->addresses()->where('status', ApprovalStatus::APPROVED)->first();
$postCodes = \App\Models\SegmentConstant::whereIn('reference', ['CENTER_POSTCODE', 'OUTSTATION_POSTCODE'])->get()->pluck('value')->flatten();
// $postCodes = \App\Models\SegmentConstant::whereIn('reference', ['CENTER_POSTCODE', 'OUTSTATION_POSTCODE'])->get()->pluck('value')->flatten();
if(!!$billingAddress && in_array($deliveryAddress->postcode, $postCodes->toArray())){
try {
(App()->make(CreateInvoiceTransactionProcessor::class))->execute($packingList);
echo '<span style="color: green;">Invoice Generated...</span><br>';
// if(!!$billingAddress && in_array($deliveryAddress->postcode, $postCodes->toArray())){
// try {
// (App()->make(CreateInvoiceTransactionProcessor::class))->execute($packingList);
// echo '<span style="color: green;">Invoice Generated...</span><br>';
} catch (Exception $exception){
echo '<span style="color: red;">failed to generate...</span><br>';
}
}
echo '<span style="color: red;">failed to generate...</span><br>';
}
})->name('generate.invoices');
// } catch (Exception $exception){
// echo '<span style="color: red;">failed to generate...</span><br>';
// }
// }
// echo '<span style="color: red;">failed to generate...</span><br>';
// }
// })->name('generate.invoices');
Route::get('/invoices/approve', function(Request $request){
// whereDoesntHave
@@ -780,8 +780,10 @@ Route::get('/invoices/approve', function(Request $request){
$packingList = $invoice->owner;
$order = $packingList->owner;
if(in_array($order->reference, json_decode($request->input('exclude')))){
continue;
if ($request->input('exclude')){
if(in_array($order->reference, json_decode($request->input('exclude')))){
continue;
}
}
try {
@@ -797,46 +799,97 @@ Route::get('/invoices/approve', function(Request $request){
})->name('invoices.approve');
Route::get('/support', function () {
return view('pages.customer_support', [
'marking' => null,
'email' => null,
'bookingReference' => null,
'company' => null,
'booking' => null
]);
})->name('support');
Route::get('/invoices/show-duplicated', function(Request $request){
$transactionWithMultipleInvoice = DB::table('transactions')
->where('type', TransactionType::SHIPPING_INVOICE)
->where('status', '!=' , ApprovalStatus::COMPLETED)
->where('deleted_at', null)
->select('owner_id', DB::raw('count(*) as count'))
->groupBy('owner_id')
->having('count', '>', 1)
->get();
Route::post('/support', function (Request $request) {
// delete invoice type suspended
$marking = $request->input('marking');
$email = $request->input('customer_email');
$bookingReference = $request->input('booking_reference');
echo '<table>';
echo "<tr>";
echo "<td style='border:1px solid'>owner_id</td>";
echo "<td style='border:1px solid'>count</td>";
echo "</tr>";
$company = null;
$booking = null;
if($email) {
$company = Company::whereHas('Employees', function($user) use($email) {
return $user->where('email', $email);
})->first();
$duplicatedOrderId = [];
foreach($transactionWithMultipleInvoice as $invoice) {
$duplicatedOrderId[] = $invoice->owner_id;
echo "<tr>";
echo "<td style='border:1px solid'>$invoice->owner_id</td>";
echo "<td style='border:1px solid'>$invoice->count</td>";
echo "</tr>";
}
echo '</table>';
if($marking) {
$company = Company::where('reference', $marking)->first();
$duplicatedInvoice = Transaction::whereIn('owner_id', $duplicatedOrderId)->orderByDesc('owner_id')->get();
// dd($duplicatedInvoice);
echo '<br>';
echo '<table>';
echo "<tr>";
echo "<td style='border:1px solid'>Order Reference</td>";
echo "<td style='border:1px solid'>Status</td>";
echo "<td style='border:1px solid'>Invoice Owner ID</td>";
echo "<td style='border:1px solid'>Invoice Owner ID</td>";
echo "</tr>";
foreach($duplicatedInvoice as $invoice) {
$order = $invoice->owner->owner;
echo "<tr>";
echo '<td style="border:1px solid"><a target="_blank" href="'.route('order.show', $order->reference).'">'. $order->reference.' - </a>' . $order->created_at . '</td>';
echo "<td style='border:1px solid'>".ApprovalStatus::APPROVAL_STATUS_ID[$invoice->status]."</td>";
echo "<td style='border:1px solid'>$invoice->owner_id</td>";
echo "<td style='border:1px solid'>$invoice->amount</td>";
echo "</tr>";
}
echo '</table>';
});
Route::get('/invoices/delete-duplicated', function(Request $request){
$duplicatedInvoices = DB::table('transactions')
->where('type', TransactionType::SHIPPING_INVOICE)
->where('status', '!=' , ApprovalStatus::COMPLETED)
->where('deleted_at', null)
->select('owner_id', DB::raw('count(*) as count'))
->groupBy('owner_id')
->having('count', '>', 1)
->get();
$duplicatedInvoices = Transaction::whereIn('owner_id', $duplicatedInvoices->pluck('owner_id'))->get()->groupBy('owner_id');
foreach($duplicatedInvoices as $invoice) {
$packingList = $invoice->first()->owner;
$order = $packingList->owner;
$paidInvoice = $packingList->transactions()->where('type', TransactionType::SHIPPING_INVOICE)->where('status', ApprovalStatus::COMPLETED)->get();
$unpaidInvoices = $packingList->transactions()->where('type', TransactionType::SHIPPING_INVOICE)->whereIn('status', [ApprovalStatus::PENDING_SUBMISSION, ApprovalStatus::PENDING_VERIFICATION, ApprovalStatus::APPROVED])->orderBy('id', 'desc')->get();
if (count($paidInvoice)) {
$packingList->transactions()->where('type', TransactionType::SHIPPING_INVOICE)->where('status', '!=', ApprovalStatus::COMPLETED)->delete();
continue;
}
// delete duplicated invoices
$unpaidInvoicesIds = $unpaidInvoices->pluck('id')->toArray();
array_shift($unpaidInvoicesIds);
Transaction::whereIn('id', $unpaidInvoicesIds)->delete();
// delete expired invoices
$packingList->transactions()->where('type', TransactionType::SHIPPING_INVOICE)->where('status', '!=', ApprovalStatus::EXPIRED)->delete();
// delete suspended invoices
$suspendedInvoices = $packingList->transactions()->where('type', TransactionType::SHIPPING_INVOICE)->where('status', '!=', ApprovalStatus::SUSPENDED)->orderBy('id', 'desc')->get();
$suspendedInvoicesIds = $suspendedInvoices->pluck('id')->toArray();
array_shift($suspendedInvoicesIds);
Transaction::whereIn('id', $suspendedInvoicesIds)->delete();
if($bookingReference) {
$booking = Booking::where('marking', $bookingReference)->first();
$company = $booking->company;
}
return view('pages.customer_support', [
'marking' => $marking,
'email' => $email,
'bookingReference' => $bookingReference,
'company' => $company,
'booking' => $booking,
]);
})->name('support');
});
+9
View File
@@ -0,0 +1,9 @@
{
"default": {
"capabilities": {
"browserName": "chrome"
},
"port": 9515,
"path": "/wd/hub"
}
}
+3 -2
View File
@@ -3,15 +3,16 @@
namespace Tests;
use Illuminate\Contracts\Console\Kernel;
use Illuminate\Foundation\Application;
trait CreatesApplication
{
/**
* Creates the application.
*
* @return \Illuminate\Foundation\Application
* @return Application
*/
public function createApplication()
public function createApplication(): Application
{
$app = require __DIR__.'/../bootstrap/app.php';
+44 -1
View File
@@ -2,9 +2,52 @@
namespace Tests;
use Faker\Factory as Faker;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
use Illuminate\Support\Facades\Artisan;
use JWTAuth;
abstract class TestCase extends BaseTestCase
{
use CreatesApplication;
use CreatesApplication, RefreshDatabase, DatabaseMigrations;
protected $faker;
/* public function actingAs($user, $driver = "api"): TestCase
{
$token = JWTAuth::fromUser($user);
$this->withHeader('Authorization', "Bearer {$token}");
parent::actingAs($user);
return $this;
}*/
/**
* Sets up the tests
*/
public function setUp(): void
{
parent::setUp();
$this->faker = Faker::create();
Artisan::call('migrate');
}
/**
* Rolls back migrations
*/
public function tearDown(): void
{
Artisan::call('migrate:rollback');
parent::tearDown();
}
}
+230
View File
@@ -0,0 +1,230 @@
<?php
namespace Tests\Unit;
use App\Classes\Modules\Accounts\Services\GeneratesAuthenticationToken;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\RoleTypes;
use App\Http\Middleware\ValidateToken;
use App\Models\User;
use JWTAuth;
use Tests\TestCase;
class AuthenticationTest extends TestCase
{
protected $loginRoute = 'api.account.authentication.authenticate.attempt';
/**
* Test Authenticated Users can not Access the login page
* TODO fix this test
* @return void
*/
public function testAuthenticatedUsersCanNotAccessLoginPage()
{
$user = User::factory()->create();
$this->actingAs($user)
->assertAuthenticatedAs($user)
->get(route('login'))
->assertSee('Sign In');
}
/**
* Empty email and password can not be null
* @return void
*/
public function testBothEmailAndPasswordAreRequiredToLogin()
{
$response = $this->post(route($this->loginRoute), [
'email' => '',
'password' => ''
]);
$response->assertStatus(500)
->assertSee('Authentication failed');
//todo we need to implement Laravel Requests for proper error handling
}
/**
* Test a user with Valid credentials can login
* @return void
*/
public function testUserWithValidCredentialsCanLogin()
{
$user = User::factory()->create([
'password' => bcrypt($password = 'password')
]);
$response = $this->post(route($this->loginRoute), [
'email' => $user->email,
'password' => $password
]);
$response->assertStatus(200)
->assertSee('You have successfully logged in to your account')
->assertSee('access_token');
}
/**
* Invalid Users get an error
* * @return void
*/
public function testUserWithInvalidCredentialCanNotLogin()
{
$user = User::factory()->create([
'password' => bcrypt($password = 'password')
]);
$response = $this->post((route($this->loginRoute)), [
'email' => $user->email,
'password' => 'wrongpassword'
]);
$response->assertStatus(401)
->assertSee('Authentication failed')
->assertSee('These credentials do not match our records.');
}
/**
* test User can Logout
* @return void
*/
public function testUserCanLogout()
{
$user = User::factory()->create();
$token = JWTAuth::fromUser($user);
$response = $this->withHeaders([
'Authorization' => 'Bearer ' . $token,
])->json('GET', route('api.account.authentication.logout'));
$response->assertStatus(200)
->assertSee('Logout Successful')
->assertSee('You have successfully logged out of your account')
->assertDontSee('access_token');
}
/**
* test Refresh token
* @return void
*/
public function testUserCanRefreshToken()
{
$user = User::factory()->create();
$token = JWTAuth::fromUser($user);
$response = $this->withHeaders([
'Authorization' => 'Bearer ' . $token,
])->json('GET', route('api.account.authentication.refresh'));
$response->assertStatus(200)
->assertSee('Refresh Authentication Successful')
->assertSee('You have successfully your account authentication')
->assertJsonStructure([
'title',
'message',
'payload',
]);
}
/**
* test forgot password
* @return void
*/
public function testForgotPassword()
{
$route = 'api.account.authentication.password.forget';
$user = User::factory()->create();
$response = $this->post(route($route), [
'email' => $user->email
]);
$response->assertStatus(200)
->assertSee('Reset Password Successful')
->assertSee('Reset Password Successful')
->assertSee('You have successfully sent you an email to reset your password');
}
/**
* test reset password
* @return void
*/
public function testUserGetResetPasswordLink()
{
$route = 'api.account.authentication.password.reset';
$user = User::factory()->create();
$token = JWTAuth::fromUser($user);
$response = $this->withHeaders([
'Authorization' => 'Bearer ' . $token,
])->json('POST', route($route), [
'password' => 'newPassword',
'confirmPassword' => 'newPassword'
]);
$response->assertStatus(500)
->assertSee('Password Change failed');
}
/*
* todo
* $response->assertStatus(200)
->assertSee('Reset Password Successful')
->assertSee('Reset Password Successful')
->assertSee('You have successfully sent you an email to reset your password');*/
/*}*/
/**
* test user can verify email
* @return void
*/
/*public function testCanVerifyEmail()
{
$route = 'api.account.email.verify';
$user = User::factory()->create();
$token = Password::createToken($user);
dd($token);
$response = $this->actingAs($user)
->post(route($route), [
'token' => $token
])->assertStatus(200);
}*/
/**
* test Resend verification email
* @return void
*/
public function testResendVerification()
{
$route = 'api.account.email.verification.resend';
$user = User::factory()->create();
$response = $this->post(route($route), [
'user_id' => $user->id
])
->assertStatus(200)
->assertSee('Resend Verification Email Successful')
->assertSee('Successfully resent a new verification email');
}
}
+26
View File
@@ -0,0 +1,26 @@
<?php
namespace Tests\Unit;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class BrowserSessionsTest extends TestCase
{
use RefreshDatabase;
public function test_other_browser_sessions_can_be_logged_out()
{
$user = User::factory()->create();
$this->actingAs($user);
$response = $this->get('/user/other-browser-sessions', [
'password' => 'password',
]);
$response->assertSessionHasNoErrors();
}
}
+101
View File
@@ -0,0 +1,101 @@
<?php
namespace Tests\Unit;
use App\Models\User;
use App\Providers\RouteServiceProvider;
use Illuminate\Auth\Events\Verified;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\URL;
use JWTAuth;
use Tests\TestCase;
class EmailVerificationTest extends TestCase
{
use RefreshDatabase;
public function test_check_existing_email()
{
$user = User::factory()->create();
$response = $this->post('api/v1/account/authentication/login/check_email', [
'email' => $user->email
]);
$response->assertStatus(200)
->assertSee("User found Successful")
->assertSee("Account Already Exists");
}
public function test_check_unknown_email()
{
$response = $this->post('api/v1/account/authentication/login/check_email', [
'email' => 'random_email@test.com'
]);
$response->assertStatus(404)
->assertSee("User found failed")
->assertSee("Unable to find any record based on the criteria provided");
}
//todo test post success email verification
public function test_email_verification()
{
$user = User::factory()->create();
//todo create a new email verification token, not post request method found
$response = $this->actingAs($user)->post('api/v1/account/email/verify', [
'token' => 'simple_string'
]);
//todo need to register notification services on IOC
$response->assertStatus(404);
}
public function test_resend_email()
{
$user = User::factory()->create();
//create a new email verification token, not post request method found
$response = $this->actingAs($user)->post('api/v1/account/email/verification/resend', [
'user_id' => $user->id
]);
$response->assertStatus(200)
->assertSee("Resend Verification Email Successful")
->assertSee("Successfully resent a new verification email");
}
public function test_change_email()
{
$user = User::factory()->create();
$token = JWTAuth::fromUser($user);
//create a new email verification token, not post request method found
$response = $this->withHeaders([
'Authorization' => 'Bearer ' . $token,
])->json('POST', 'api/v1/company/team/create', [
'email' => "newemail@test.abc"
]);
//todo add user payload to the response and assert json
$response->assertStatus(200)
->assertSee("Updated Email Successful")
->assertSee("Successfully updated email");
}
}
-19
View File
@@ -1,19 +0,0 @@
<?php
namespace Tests\Unit;
use PHPUnit\Framework\TestCase;
class ExampleTest extends TestCase
{
/**
* A basic test example.
*
* @return void
*/
public function testBasicTest()
{
$this->assertTrue(true);
}
}
+46
View File
@@ -0,0 +1,46 @@
<?php
namespace Tests\Unit;
use App\Classes\Modules\Accounts\Services\ExpiresPasswordReset;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Queue;
use Tests\TestCase;
class PasswordRestTest extends TestCase
{
use RefreshDatabase;
public function test_generate_reset_password()
{
$user = User::factory()->create();
$response = $this->actingAs($user)->post('api/v1/account/authentication/password/forget', [
'email' => $user->email
]);
$response->assertStatus(200)
->assertSee("Reset Password Successful")
->assertSee("You have successfully sent you an email to reset your password");
//assert a reset data was saved in the database
$this->assertDatabaseHas('password_resets', [
'user_id' => $user->id,
]);
//todo register all classes in the IOC
//assert a verification Link was generated
// Queue::assertDispatched(ProcessImage::class, function ($job) {
// return $job->image === 'image.jpg';
// });
//get the token and pass it on the verification link
}
}
+60
View File
@@ -0,0 +1,60 @@
<?php
namespace Tests\Unit;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class RegistrationTest extends TestCase
{
use RefreshDatabase;
/* public function test_create_invitation_request_test()
{
//todo to be updated on finalizing creating company module
$response = $this->post('api/v1/account/invite/registration', [
'company_id' => 1,
'name' => 'Test User',
'email' => 'test@example.com',
'phone' => '899990989',
'wechat_id' => '5666',
'company_name' => 'test company co',
'password' => 'password',
'password_confirmation' => 'password',
'contact_email' => "contact@email.com",
]);
$response->assertStatus(404);
}
public function test_new_users_can_register()
{
$response = $this->post('/api/v1/account/registration', [
'type' => 1,
'name' => 'Test User',
'email' => 'test@example.com',
'phone' => '899990989',
'wechat_id' => '5666',
'company_name' => 'test company co',
'password' => 'password',
'password_confirmation' => 'password',
'contact_email' => "contact@email.com",
]);
$this->assertDatabaseHas('users', [
'id' => 1,
'email' => 'test@example.com',
'name' => 'Test User',
]);
//todo an error experienced on line $inviter = $this->fetchesCompanyModule->execute(['reference'=>'CIEF']);
//todo 1. assert a user was logged in 2. assert a user was redirected 3. assert user has a token
}
*/
}
+180
View File
@@ -0,0 +1,180 @@
<?php
namespace Tests\Unit;
use App\Classes\Modules\Accounts\Services\GeneratesAuthenticationToken;
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\RoleTypes;
use App\Http\Middleware\ValidateToken;
use App\Models\User;
use JWTAuth;
use Tests\TestCase;
class UsersTest extends TestCase
{
protected $loginRoute = 'api.account.authentication.authenticate.attempt';
/**
* Get User by Id
*
* @return void
*/
public function test_get_user_by_id()
{
$user = User::factory()->create();
$token = JWTAuth::fromUser($user);
$response = $this->withHeaders([
'Authorization' => 'Bearer ' . $token,
])->json('POST', route('api.account.user.show', [
'user_id' => $user->id
]));
$response->assertStatus(200)
->assertSee('Fetch Users Successful')
->assertSee('You have successfully retrieved the user');
}
/**
* Get User by email
*
* @return void
*/
public function test_get_fetch_user_by_email()
{
$user = User::factory()->create();
$token = JWTAuth::fromUser($user);
$response = $this->withHeaders([
'Authorization' => 'Bearer ' . $token,
])->json('GET', route('api.account.user.company', $user->email), [
'email' => $user->email
]);
//todo fix the invitee issue
/* $response->assertStatus(200)
->assertSee('Fetch Users')
->assertSee('You have successfully retrieved the user by email'); */
$response->assertStatus(500);
}
/**
* Get a List of all users test
* @return void
*/
public function test_list_users()
{
$user = User::factory()->create([
'type' => RoleTypes::ADMIN,
'status' => ApprovalStatus::APPROVED
]);
$token = JWTAuth::fromUser($user);
$response = $this->withHeaders([
'Authorization' => 'Bearer ' . $token,
])->json('GET', 'api/v1/account/user/list?&filters=null}');
$response->assertStatus(404);
//todo add a default return list without filter or null filters
/*
$response->assertStatus(200)
->assertSee('Retrieved Companies Successful')
->assertSee('You have successfully retrieved a list of users');*/
}
/**
* Test Can Create an Admin User
*
* @return void
*/
public function test_create_an_admin_user()
{
$user = User::factory()->create();
$token = JWTAuth::fromUser($user);
$response = $this->withHeaders([
'Authorization' => 'Bearer ' . $token,
])->json('POST', route('api.account.user.admin.create'),
[
'name' => 'Test Admin',
'email' => 'admin@example.com',
'password' => 'password',
'password_confirmation' => 'password',
]);
$response->assertStatus(200)
->assertSee('Created Account')
->assertSee('You have successfully created a new Account');
}
/**
* Test Can create a user
*
* @return void
*/
public function test_can_update_user()
{
$user = User::factory()->create();
$token = JWTAuth::fromUser($user);
$response = $this->withHeaders([
'Authorization' => 'Bearer ' . $token,
])->json('PUT', route('api.account.user.update', $user->id), [
'name' => 'Test Admin',
/*'email' => 'admin@example.com',
'password' => 'password',
'password_confirmation' => 'password',*/
]);
$response->assertStatus(200)
->assertSee('Updated User Profile')
->assertSee('You have successfully updated the User Profile');
}
/**
* Test Can delete a user
*
* @return void
*/
public function test_can_delete_user_profile()
{
$user = User::factory()->create();
$token = JWTAuth::fromUser($user);
$response = $this->withHeaders([
'Authorization' => 'Bearer ' . $token,
])->json('DELETE', route('api.account.user.delete', $user->id), [
'id' => $user->id
]);
$response->assertStatus(200)
->assertSee('Delete User Successful')
->assertSee('You have successfully deleted the User');
}
}
View File
+2
View File
@@ -0,0 +1,2 @@
*
!.gitignore
+28
View File
@@ -0,0 +1,28 @@
<?php
use Codeception\Actor;
/**
* Inherited Methods
* @method void wantToTest($text)
* @method void wantTo($text)
* @method void execute($callable)
* @method void expectTo($prediction)
* @method void expect($prediction)
* @method void amGoingTo($argumentation)
* @method void am($role)
* @method void lookForwardTo($achieveValue)
* @method void comment($description)
* @method void pause()
*
* @SuppressWarnings(PHPMD)
*/
class AcceptanceTester extends Actor
{
use _generated\AcceptanceTesterActions;
/**
* Define custom actions here
*/
}
+26
View File
@@ -0,0 +1,26 @@
<?php
/**
* Inherited Methods
* @method void wantToTest($text)
* @method void wantTo($text)
* @method void execute($callable)
* @method void expectTo($prediction)
* @method void expect($prediction)
* @method void amGoingTo($argumentation)
* @method void am($role)
* @method void lookForwardTo($achieveValue)
* @method void comment($description)
* @method void pause()
*
* @SuppressWarnings(PHPMD)
*/
class FunctionalTester extends \Codeception\Actor
{
use _generated\FunctionalTesterActions;
/**
* Define custom actions here
*/
}
+10
View File
@@ -0,0 +1,10 @@
<?php
namespace Helper;
// here you can define custom actions
// all public methods declared in helper class will be available in $I
class Acceptance extends \Codeception\Module
{
}
+10
View File
@@ -0,0 +1,10 @@
<?php
namespace Helper;
// here you can define custom actions
// all public methods declared in helper class will be available in $I
class Functional extends \Codeception\Module
{
}
+10
View File
@@ -0,0 +1,10 @@
<?php
namespace Helper;
// here you can define custom actions
// all public methods declared in helper class will be available in $I
class Unit extends \Codeception\Module
{
}

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