Compare commits

..

155 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
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
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 8e7970a925 Merge branch 'master' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into development 2023-03-02 16:16:23 +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
Dillon 9318e7471f Merge branch 'dillon/crm-create-task' into development 2023-03-01 12:36:15 +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 935f3e9bf5 Merge branch 'master' of https://gitlab.com/CIEFWorldwideSdnBhd/shipping-portal into development 2023-02-27 15:59:49 +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 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
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 a2f9bf83ce Merge branch 'dillon/crm-integration' into development 2023-02-18 20:29:57 +08:00
Dillon dd2ac4c966 Merge branch 'dillon/crm-integration' into development 2023-02-18 20:09:08 +08:00
Dillon c88f6890d6 Merge branch 'dillon/crm-integration' into development 2023-02-17 09:24:38 +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
67 changed files with 1814 additions and 517 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
View File
@@ -2,6 +2,8 @@
/public/hot
/public/storage
/storage/*.key
/tests/_output
/tests/_support
/vendor
**/.idea/
.env
+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);
}
}
@@ -1,33 +0,0 @@
<?php
namespace App\Classes\Jobs;
use App\Classes\Modules\PerfexCRM\Processors\CreatePerfexCRMInvoiceProcessor;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use App\Models\Transaction;
class CreatePerfexCRMInvoice implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/** @var Transaction $transaction*/
private $transaction;
/**
* CreatePerfexCRMInvoice constructor.
* @param Transaction $transaction
*/
public function __construct(Transaction $transaction)
{
$this->transaction = $transaction;
}
public function handle()
{
(App()->make(CreatePerfexCRMInvoiceProcessor::class))->execute($this->transaction);
}
}
@@ -4,12 +4,12 @@ namespace App\Classes\Jobs;
use App\Classes\Modules\PerfexCRM\Processors\CreatePerfexCRMTaskProcessor;
use App\Classes\Modules\PerfexCRM\Services\FetchesPerfexCRMLead;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CreateTaskPerfexCRMObject;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\CreateTaskPerfexCRMObject;
class CreatePerfexCRMSingleTask implements ShouldQueue
{
@@ -1,92 +0,0 @@
<?php
namespace App\Classes\Jobs;
use App\Classes\Modules\PerfexCRM\Processors\CreatePerfexCRMInvoiceProcessor;
use App\Classes\Modules\PerfexCRM\Services\CreatesPerfexCRMInvoicePayment;
use App\Classes\Modules\PerfexCRM\Services\FetchesPerfexCRMCustomer;
use App\Classes\Modules\PerfexCRM\Services\FetchesPerfexCRMInvoice;
use App\Classes\Modules\PerfexCRM\Services\FetchesPerfexCRMProject;
use App\Classes\Modules\PerfexCRM\Services\UpdatesPerfexCRMInvoice;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\UpdatePerfexCRMInvoiceObject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\InvoicePaymentPerfexCRMObject;
use App\Classes\ValueObjects\Constants\PerfexCRMInvoiceStatus;
use App\Models\Transaction;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Carbon\Carbon;
class UpdatePerfexCRMInvoice implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/** @var UpdatePerfexCRMInvoiceObject */
private $updatePerfexCRMInvoiceObject;
/**
* CreatePerfexCRMSingleTask constructor.
* @param UpdatePerfexCRMInvoiceObject $createTaskPerfexCRMObject
*/
public function __construct(UpdatePerfexCRMInvoiceObject $updatePerfexCRMInvoiceObject)
{
$this->updatePerfexCRMInvoiceObject = $updatePerfexCRMInvoiceObject;
}
public function handle()
{
//get the client id
$customer = (App()->make(FetchesPerfexCRMCustomer::class))->execute($this->updatePerfexCRMInvoiceObject->getEmail());
$transaction = $this->updatePerfexCRMInvoiceObject->getTransaction();
//get the invoice id
$invoiceId = 0;
$invoiceStatus = 0;
$invoice = (App()->make(FetchesPerfexCRMInvoice::class))->execute($customer->userid,"INV-", $transaction->owner->bill_no);
if(is_null($invoice)){
$result = (App()->make(CreatePerfexCRMInvoiceProcessor::class))->execute($transaction->owner, $this->updatePerfexCRMInvoiceObject->getIsPaid());
$invoiceId = $result->payload['id'];
}
else{
$invoiceId = $invoice->id;
$invoiceStatus = $invoice->status;
//This only run when invoice already exist and the invoice does not have a PAID status
if($invoiceStatus != PerfexCRMInvoiceStatus::PAID){
//get project
$projectId = "";
if($transaction->owner instanceof Transaction){
$orderReference = $transaction->owner->owner->owner()->first()->reference;
$packingListReference = $transaction->owner->owner->reference;
$projectName = 'IZYIM | X1 Shipping | '.$orderReference.' | '.$packingListReference;
$project = (App()->make(FetchesPerfexCRMProject::class))->execute($projectName, $customer->userid);
if(!is_null($project)){
$projectId = $project->id;
}
}
//update invoice
(App()->make(UpdatesPerfexCRMInvoice::class))->execute($invoice, $projectId);
}
}
//create invoice payment
if($invoiceId != 0 && $invoiceStatus != PerfexCRMInvoiceStatus::PAID){
$date = Carbon::parse($transaction->created_at)->format('Y-m-d');
$invoicePaymentPerfexCRMObject = new InvoicePaymentPerfexCRMObject(
$invoiceId,
"$transaction->amount",
$date,
1,
"",
""
);
(App()->make(CreatesPerfexCRMInvoicePayment::class))->execute($invoicePaymentPerfexCRMObject);
}
}
}
@@ -68,19 +68,19 @@ class CreateBillingAddressLogic extends AbstractControllerLogic
{
$companyModule = $this->fetchesCompanyModule->execute(['id' => $request->input('company_module_id')]);
$address = $this->fetchesAddress->execute(['id' => $request->input('billing_address_id')]);
$billingAddressInputed = $this->fetchesAddress->execute(['id' => $request->input('billing_address_id')]);
if ($address->type !== AddressType::BILLING || $address->id !== $companyModule->addresses->where('type', AddressType::BILLING)->first()->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 addrress
$billingAddress = new AddressObject($address->street_one, $address->street_two, $address->country_id, $address->state_id, $address->district_id, $address->postcode, AddressType::BILLING, ApprovalStatus::APPROVED, $address->reference);
// 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($address));
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]);
}
@@ -7,7 +7,7 @@ use App\Classes\General\Interfaces\DataTransferObject;
class InvoicePerfexCRMObject implements DataTransferObject
{
/** @var string */
/** @var int */
private $clientId;
/** @var string */
@@ -56,9 +56,9 @@ class InvoicePerfexCRMObject implements DataTransferObject
}
/**
* @return string
* @return int
*/
public function getClientId(): string
public function getClientId(): int
{
return $this->clientId;
}
@@ -14,7 +14,7 @@ class InvoiceSingleItemPerfexCRMObject implements DataTransferObject
/** @var string */
public $longDescription;
/** @var float */
/** @var int */
public $qty;
/** @var float */
@@ -26,7 +26,7 @@ class InvoiceSingleItemPerfexCRMObject implements DataTransferObject
/** @var string */
public $unit;
public function __construct(string $description, string $longDescription, float $qty, float $rate, int $order, string $unit)
public function __construct(string $description, string $longDescription, int $qty, float $rate, int $order, string $unit)
{
$this->description = $description;
$this->longDescription = $longDescription;
@@ -53,9 +53,9 @@ class InvoiceSingleItemPerfexCRMObject implements DataTransferObject
}
/**
* @return float
* @return int
*/
public function getQty(): float
public function getQty(): int
{
return $this->qty;
}
@@ -1,50 +0,0 @@
<?php
namespace App\Classes\Modules\PerfexCRM\DataTransferObjects;
use Illuminate\Http\Request;
use App\Classes\General\Interfaces\DataTransferObject;
use App\Models\Transaction;
class UpdatePerfexCRMInvoiceObject implements DataTransferObject
{
/** @var string */
private $email;
/** @var Transaction */
private $transaction;
/** @var bool */
private $isPaid;
public function __construct(string $email, Transaction $transaction, bool $isPaid)
{
$this->email = $email;
$this->transaction = $transaction;
$this->isPaid = $isPaid;
}
/**
* @return string
*/
public function getEmail(): string
{
return $this->email;
}
/**
* @return Transaction
*/
public function getTransaction(): Transaction
{
return $this->transaction;
}
/**
* @return bool
*/
public function getIsPaid(): bool
{
return $this->isPaid;
}
}
@@ -2,15 +2,13 @@
namespace App\Classes\Modules\PerfexCRM\Processors;
use App\Models\Transaction;
// 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\Services\FetchesPerfexCRMProject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\InvoicePerfexCRMObject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\InvoicePaymentPerfexCRMObject;
use App\Classes\Modules\PerfexCRM\DataTransferObjects\InvoiceSingleItemPerfexCRMObject;
use App\Models\PackingList;
use Carbon\Carbon;
class CreatePerfexCRMInvoiceProcessor
@@ -25,52 +23,42 @@ class CreatePerfexCRMInvoiceProcessor
/** @var ConvertsPerfexCRMLeadToCustomer */
private $convertsPerfexCRMLeadToCustomer;
/** @var FetchesPerfexCRMProject */
private $fetchesPerfexCRMProject;
/**
* CreatePerfexCRMInvoiceProcessor constructor.
* @param CreatesPerfexCRMInvoice $createsPerfexCRMInvoice
*/
public function __construct(CreatesPerfexCRMInvoice $createsPerfexCRMInvoice,
CreatesPerfexCRMInvoicePayment $createsPerfexCRMInvoicePayment,
ConvertsPerfexCRMLeadToCustomer $convertsPerfexCRMLeadToCustomer,
FetchesPerfexCRMProject $fetchesPerfexCRMProject)
ConvertsPerfexCRMLeadToCustomer $convertsPerfexCRMLeadToCustomer)
{
$this->createsPerfexCRMInvoice = $createsPerfexCRMInvoice;
$this->createsPerfexCRMInvoicePayment = $createsPerfexCRMInvoicePayment;
$this->convertsPerfexCRMLeadToCustomer = $convertsPerfexCRMLeadToCustomer;
$this->fetchesPerfexCRMProject = $fetchesPerfexCRMProject;
}
/**
* @param Transaction $transaction
* @param bool $isPaid, default: false
* @param $transaction
* @param $purchaseOrder
* @param $supplier
* @return null|object
* @throws \App\Classes\Exceptions\MalformedRequestException
*/
public function execute(Transaction $transaction, bool $isPaid = false) {
public function execute($transaction, $purchaseOrder, $supplier) {
$clientId = "";
$number = $transaction->bill_no;
$prefix = "INV-";
//This will remove the prefix if prefix already exist in the string
if (substr($number, 0, strlen($prefix)) == $prefix) {
$number = substr($number, strlen($prefix));
}
$date = Carbon::parse($transaction->created_at)->format('Y-m-d');
$dueDate = Carbon::parse($transaction->created_at)->format('Y-m-d');
$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;
$companyModule = $transaction->owner->owner->companyModule;
$billingStreet = "";
$addresses = $companyModule
->addresses()
->where('status', '=', \App\Classes\ValueObjects\Constants\ApprovalStatus::APPROVED)
->where('type', '=', \App\Classes\ValueObjects\Constants\AddressType::BILLING)->first();
$addresses = $supplier->addresses()->where('billing', '=', true)->first();
$billingStreet = $billingStreet.$addresses->street_one;
$billingStreet = $billingStreet.$addresses->street_two.',';
@@ -79,40 +67,40 @@ class CreatePerfexCRMInvoiceProcessor
$billingStreet = $billingStreet.$addresses->state()->first()->name.',';
$billingStreet = $billingStreet.$addresses->country()->first()->name;
$projectId = "";
$allowedPaymentModes = [];
$invoiceItems = [];
$employee = $companyModule->employees()->first();
$email = $employee->email;
$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'];
}
//get project
$projectId = ""; //Project only exist in CRM if the customer already made payment
if($isPaid){
if($transaction->owner instanceof PackingList){
$orderReference = $transaction->owner->owner->reference;
$packingListReference = $transaction->owner->reference;
$projectName = 'IZYIM | X1 Shipping | '.$orderReference.' | '.$packingListReference;
$project = (App()->make(FetchesPerfexCRMProject::class))->execute($projectName, $clientId);
if(!is_null($project)){
$projectId = $project->id;
}
}
}
//newitems
foreach ($transaction->transactionDetails as $key => $transaction_detail){
foreach ($purchaseOrder->transactionDetails as $key => $transaction_detail){
$order = $key + 1;
$description = $transaction_detail->name;
$stockCode = $transaction_detail->product_code;
$description = $transaction_detail->product_name;
$quantity = $transaction_detail->quantity;
$unitPrice = $transaction_detail->price;
$unitPrice = 0.00;
if($transaction->booking()->first()->fix_currency_id !== 1)
$unitPrice = (1/$transaction->currency_rate) * $transaction_detail->price;
else
$unitPrice = $transaction_detail->price;
$subTotal = $transaction_detail->amount;
//$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(
@@ -126,11 +114,16 @@ class CreatePerfexCRMInvoiceProcessor
array_push($invoiceItems, $invoiceSingleItem);
}
$total = $transaction->amount;
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;
}
//This setting is similar to Setup > Leads > Sources, Setup > Leads > Statuses
//Can be found at Finance > Payment Modes
//cief TODO: To be updated, temporarily hardcoded allow payment modes
array_push($allowedPaymentModes, 1, 2);
$invoicePerfexCRMObject = new InvoicePerfexCRMObject(
$clientId,
$number,
@@ -147,7 +140,20 @@ class CreatePerfexCRMInvoiceProcessor
$result = $this->createsPerfexCRMInvoice->execute($invoicePerfexCRMObject);
return $result;
//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;
}
}
@@ -8,15 +8,13 @@ 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\Modules\PerfexCRM\DataTransferObjects\UpdatePerfexCRMInvoiceObject;
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\UpdatePerfexCRMInvoice;
use App\Classes\Jobs\UpdatePerfexCRM;
use App\Models\Transaction;
class TransactionToPerfexCRMProcessor
{
@@ -85,15 +83,7 @@ class TransactionToPerfexCRMProcessor
//$this->initializePerfexCRMProcessor->execute($initialPerfexCRMObject);
InitializePerfexCRM::dispatch($initialPerfexCRMObject);
$updatePerfexCRMInvoiceOject = new UpdatePerfexCRMInvoiceObject(
$contactEmail,
$model,
true
);
UpdatePerfexCRMInvoice::dispatch($updatePerfexCRMInvoiceOject);
}
return true;
}
}
@@ -22,8 +22,8 @@ class CreatesPerfexCRMInvoice
'date' => $invoicePerfexCRMObject->getDate(),
'duedate' => $invoicePerfexCRMObject->getDueDate(),
'currency' => $invoicePerfexCRMObject->getCurrency(),
'subtotal' => number_format($invoicePerfexCRMObject->getSubTotal(), 2, '.', ''),
'total' => number_format($invoicePerfexCRMObject->getTotal(), 2, '.', ''),
'subtotal' => $invoicePerfexCRMObject->getSubTotal(),
'total' => $invoicePerfexCRMObject->getTotal(),
'billing_street' => $invoicePerfexCRMObject->getBillingStreet(),
'project_id' => $invoicePerfexCRMObject->getProjectId(),
'allowed_payment_modes[0]' => 1,
@@ -18,7 +18,7 @@ class CreatesPerfexCRMInvoicePayment
try{
$data = [
'invoiceid' => $invoicePaymentPerfexCRMObject->getInvoiceId(),
'amount' => number_format($invoicePaymentPerfexCRMObject->getAmount(), 2, '.', ''),
'amount' => $invoicePaymentPerfexCRMObject->getAmount(),
'date' => $invoicePaymentPerfexCRMObject->getDate(),
'paymentmode' => $invoicePaymentPerfexCRMObject->getPaymentMode(),
'transactionid' => $invoicePaymentPerfexCRMObject->getTransactionId(),
@@ -1,34 +0,0 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
class FetchesPerfexCRMCustomer
{
/**
* @param string $email
* @return null|object
* @throws MalformedRequestException
*/
public function execute(string $email) {
try{
$response = Http::withHeaders([
'authtoken' => config('perfexcrm.api_key'),])
->get(config('perfexcrm.base_url').'/api/customers/byemail/'.$email);
if($response->successful()){
$data = $response->json();
return (object) $data;
}else{
Log::error($response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
}
@@ -1,36 +0,0 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
class FetchesPerfexCRMInvoice
{
/**
* @param string $clientId
* @param string $invoicePrefix
* @param string $invoiceNumber
* @return null|object
* @throws MalformedRequestException
*/
public function execute(string $clientId, string $invoicePrefix, string $invoiceNumber) {
try{
$response = Http::withHeaders([
'authtoken' => config('perfexcrm.api_key'),])
->get(config('perfexcrm.base_url').'/api/invoices/customsearch/'.$clientId.'/'.$invoicePrefix.'/'.$invoiceNumber);
if($response->successful()){
$data = $response->json();
return (object) $data;
}else{
Log::error($response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
}
@@ -1,67 +0,0 @@
<?php
namespace App\Classes\Modules\PerfexCRM\Services;
use Illuminate\Support\Facades\Http;
use App\Classes\Exceptions\MalformedRequestException;
use Illuminate\Support\Facades\Log;
class UpdatesPerfexCRMInvoice
{
/**
* @param $invoice
* @param string $projectId
* @return null|object
* @throws MalformedRequestException
*/
public function execute($invoice, string $projectId) {
try{
// <p>The Invoice number field is required.<\/p>
// <p>The Invoice date field is required.<\/p>
// <p>The Currency field is required.<\/p>
// <p>The Items field is required.<\/p>
// <p>The Allow Payment Mode field is required.<\/p>
// <p>The Billing Street field is required.<\/p>
// <p>The Sub Total field is required.<\/p>
// <p>The Total field is required.<\/p>
$newInvoiceItems = [];
foreach ($invoice->items as $item) {
$item['itemid'] = $item['id'];
unset($item['id']);
$item['order'] = $item['item_order'];
unset($item['item_order']);
array_push($newInvoiceItems,$item);
}
$data = [
'number' => $invoice->number,
'date' => $invoice->date,
'duedate' => $invoice->date,
'currency' => $invoice->currency,
'subtotal' => $invoice->subtotal,
'total' => $invoice->total,
'billing_street' => $invoice->billing_street,
'shipping_street' => $invoice->billing_street,
'project_id' => $projectId,
'items' => $newInvoiceItems,
'allowed_payment_modes' => $invoice->allowed_payment_modes,
];
$response = Http::asJson()->withHeaders([
'authtoken' => config('perfexcrm.api_key')])
->put(config('perfexcrm.base_url').'/api/invoices/'.$invoice->id, $data);
if($response->successful()){
$data = $response->json();
return (object) $data;
}else{
Log::error($response);
return null;
}
}catch(\Exception $exception){
throw new MalformedRequestException('Unable to get correct response from Perfex CRM server: ' . $exception->getMessage());
}
}
}
@@ -0,0 +1,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([]);
}
}
@@ -16,7 +16,6 @@ use App\Classes\Modules\Documents\Services\CreatesFiles;
use App\Classes\Modules\Documents\Services\CreatesDocument;
use App\Classes\Modules\Documents\DataTransferObjects\DocumentObject;
use App\Classes\Modules\Transactions\Services\UpdatesTransactionStatus;
use App\Classes\Jobs\CreatePerfexCRMInvoice;
class ApproveShippingInvoiceTransactionProcessor
{
@@ -30,7 +29,6 @@ class ApproveShippingInvoiceTransactionProcessor
/** @var CreatesFiles */
private $createsFiles;
/**
* @param UpdatesTransactionStatus $updatesTransactionStatus
* @param CreatesDocument $createsDocument
@@ -74,12 +72,6 @@ class ApproveShippingInvoiceTransactionProcessor
if(app()->environment(['production'])) {
$user->notify(new InvoiceIssuedEmail($user, $packingList));
}
// update perfex crm
if(config('perfexcrm.is_enabled') == 'true'){
CreatePerfexCRMInvoice::dispatch($invoice_transaction);
}
return;
}
@@ -1,14 +0,0 @@
<?php
namespace App\Classes\ValueObjects\Constants;
final class PerfexCRMInvoiceStatus {
public const UNPAID = 1;
public const PAID = 2;
public const PARTIALLY_PAID = 3;
public const OVERDUE = 4;
}
@@ -0,0 +1,11 @@
<?php
namespace App\Classes\ValueObjects\Constants;
final class RouteType {
public const WEB = 1;
public const API = 2;
}
+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,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);
}
}
+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",
-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"
+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);
},
},
@@ -83,11 +83,12 @@
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: '',
billing_address_id: null,
},
item:{
id:null
@@ -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++;
}
}
}
+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');
});
});
+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
{
}
+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 UnitTester extends \Codeception\Actor
{
use _generated\UnitTesterActions;
/**
* Define custom actions here
*/
}
+2
View File
@@ -0,0 +1,2 @@
*
!.gitignore
+9
View File
@@ -0,0 +1,9 @@
actor: AcceptanceTester
modules:
enabled:
- WebDriver:
browser: chrome
url: http://127.0.0.1:8000
- Laravel:
part: ORM
environment_file: .env.testing
+55
View File
@@ -0,0 +1,55 @@
<?php
use App\Classes\ValueObjects\Constants\ApprovalStatus;
use App\Classes\ValueObjects\Constants\RoleTypes;
use App\Models\User;
use Codeception\Util\Debug;
class AuthenticationCest
{
public function _before(AcceptanceTester $I)
{
$I->wantTo('Test the Authentication Flow');
$I->amOnPage('/');
}
/**
* test if the home page is loaded
* @param AcceptanceTester $I
* @return void
*/
public function tryToTestIfWelcomePageIsLoaded(AcceptanceTester $I)
{
$I->wantTo('Check if the home page works.');
$I->amOnPage('/');
$I->see('SIGN IN');
$I->see('To keep using the service please sign in with your personal info');
$I->see('New Customer? Create Account');
}
/**
* test if admin can log in
* @param AcceptanceTester $I
* @return void
*/
public function tryToTestIfAdminCanLogin(AcceptanceTester $I)
{
// Fill out the login form
$I->fillField('email', 'omair@cief-malaysia.com');
$I->fillField('password', '123456abcabc');
$I->click(['css' => '.btn.btn-block.btn-lg.b-rad-none.no-border']);
$I->wait(5); // 2 seconds delay
$I->expectTo('be redirected to the dashboard');
$I->seeCurrentUrlEquals('/dashboard');
$I->see('Dashboard');
$I->see('NEW CUSTOMERS');
$I->see('Unclaimed Packing Lists');
$I->see('Identification Verification');
$I->see('ACTIVATED ORDERS');
}
}
+49
View File
@@ -0,0 +1,49 @@
<?php
class DashboardCest
{
public function _before(AcceptanceTester $I)
{
$I->wantTo('Test All Dashboard Data is Loaded');
$I->amOnPage('/dashboard');
}
/**
* test if the sidebar was loaded
* @param AcceptanceTester $I
* @return void
*/
public function tryToTestIfAllAdminSidebarAreLoaded(AcceptanceTester $I)
{
$I->amOnPage('/dashboard');
$I->see('DASHBOARD');
$I->see('CUSTOMERS');
$I->see('DELIVERY LIST');
$I->see('CONTAINERS');
$I->see('PAYMENT AND BILLING');
}
/**
* test if the dashboard content is Loaded
* @param AcceptanceTester $I
* @return void
*/
public function tryToTestAllDashboardComponentLoaded(AcceptanceTester $I)
{
$I->amOnPage('/dashboard');
$I->see('Dashboard');
$I->see('NEW CUSTOMERS');
$I->see('Unclaimed Packing Lists');
$I->see('Identification Verification');
$I->see('ACTIVATED ORDERS');
$I->see('PENDING SHIPMENT');
//delay a few second
$I->wait(5); // 2 seconds delay
$I->see('Unclaimed Packing Lists');
}
}
+13
View File
@@ -0,0 +1,13 @@
# Codeception Test Suite Configuration
#
# Suite for functional tests
# Emulate web requests and make application process them
# Include one of framework modules (Symfony2, Yii2, Laravel5, Phalcon4) to use it
# Remove this suite if you don't use frameworks
actor: FunctionalTester
modules:
enabled:
# add a framework module here
- \Helper\Functional
step_decorators: ~
+10
View File
@@ -0,0 +1,10 @@
# Codeception Test Suite Configuration
#
# Suite for unit or integration tests.
actor: UnitTester
modules:
enabled:
- Asserts
- \Helper\Unit
step_decorators: ~