Compare commits

...

243 Commits

Author SHA1 Message Date
Carlos Satorres 36c31af455 refs #5690 rounding translate
gitea/salix/pipeline/head This commit looks good Details
2023-07-19 12:38:13 +02:00
Carlos Satorres aaba4e74b8 Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5690-redondeo_ticketProblems 2023-07-19 12:00:59 +02:00
Alex Moreno 4150bdc6c8 Merge pull request 'refs #5824 mod ng' (!1678) from 5824-fixUpsertFixedPrice into dev
gitea/salix/pipeline/head This commit looks good Details
Reviewed-on: #1678
Reviewed-by: Alex Moreno <alexm@verdnatura.es>
2023-07-19 08:17:36 +00:00
Carlos Satorres 25ce685116 Merge branch 'dev' into 5824-fixUpsertFixedPrice
gitea/salix/pipeline/head This commit looks good Details
2023-07-19 04:36:51 +00:00
Carlos Satorres 9c746dd6c2 Merge pull request '5066-vehicleSorted' (!1467) from 5066-vehicleSorted into dev
gitea/salix/pipeline/head This commit looks good Details
Reviewed-on: #1467
Reviewed-by: Javi Gallego <jgallego@verdnatura.es>
Reviewed-by: Juan Ferrer <juan@verdnatura.es>
2023-07-18 15:21:54 +00:00
Carlos Satorres 36db2ee883 Merge branch 'dev' into 5066-vehicleSorted
gitea/salix/pipeline/head This commit looks good Details
2023-07-18 15:05:56 +00:00
Carlos Satorres bd723bb7ba refs #5824 mod ng
gitea/salix/pipeline/head There was a failure building this commit Details
2023-07-18 15:01:58 +02:00
Guillermo Bonet b285c3e37a Merge pull request 'refs #5819 Added param to call zone_getLeaves' (!1667) from 5819-zone_getLeaves into dev
gitea/salix/pipeline/head This commit looks good Details
Reviewed-on: #1667
Reviewed-by: Javi Gallego <jgallego@verdnatura.es>
Reviewed-by: Alex Moreno <alexm@verdnatura.es>
2023-07-18 06:40:50 +00:00
Guillermo Bonet 3c013110d3 refs #5819 Changed structure sql
gitea/salix/pipeline/head This commit looks good Details
2023-07-18 07:32:45 +02:00
Carlos Satorres b2b335326e Merge branch 'dev' into 5066-vehicleSorted
gitea/salix/pipeline/head There was a failure building this commit Details
2023-07-14 11:49:26 +00:00
Guillermo Bonet 765a84e2eb refs #5819 Added param to call zone_getLeaves
gitea/salix/pipeline/head There was a failure building this commit Details
2023-07-14 07:27:04 +02:00
Carlos Satorres 0d308ec8ad Merge pull request 'refs #5949 itemRecycle' (!1656) from 5949-recycledPlasticItem into dev
gitea/salix/pipeline/head This commit looks good Details
Reviewed-on: #1656
Reviewed-by: Javi Gallego <jgallego@verdnatura.es>
2023-07-13 11:59:30 +00:00
Carlos Satorres 191f478523 Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5949-recycledPlasticItem
gitea/salix/pipeline/head This commit looks good Details
2023-07-13 10:58:09 +02:00
Vicent Llopis c88a753865 Merge pull request '4770-routes_roadmap2' (!1647) from 4770-routes_roadmap2 into dev
gitea/salix/pipeline/head This commit looks good Details
Reviewed-on: #1647
Reviewed-by: Javi Gallego <jgallego@verdnatura.es>
Reviewed-by: Alex Moreno <alexm@verdnatura.es>
2023-07-13 08:35:45 +00:00
Vicent Llopis c91db1b429 a
gitea/salix/pipeline/head This commit looks good Details
2023-07-13 10:19:57 +02:00
Vicent Llopis 392dc5060a refs #4770 delete test
gitea/salix/pipeline/head There was a failure building this commit Details
2023-07-13 10:19:12 +02:00
Vicent Llopis 01dc26f64e Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 4770-routes_roadmap2
gitea/salix/pipeline/head There was a failure building this commit Details
2023-07-13 09:42:53 +02:00
Carlos Satorres 7da1824e89 Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5949-recycledPlasticItem
gitea/salix/pipeline/head There was a failure building this commit Details
2023-07-13 06:39:05 +02:00
Alex Moreno 219a4fbca9 Merge branch 'test' of https://gitea.verdnatura.es/verdnatura/salix into dev
gitea/salix/pipeline/head There was a failure building this commit Details
2023-07-12 13:09:58 +02:00
Alex Moreno 9cb29b9166 Merge branch 'master' of https://gitea.verdnatura.es/verdnatura/salix into test
gitea/salix/pipeline/head This commit looks good Details
2023-07-12 13:05:17 +02:00
Alex Moreno d7ac20dc6a hotFix(supplier): fix accessToken in before save
gitea/salix/pipeline/head There was a failure building this commit Details
2023-07-12 13:02:27 +02:00
Vicent Llopis 83698522ca Merge pull request '5887-mailAlias_refactor' (!1659) from 5887-mailAlias_refactor into master
gitea/salix/pipeline/head This commit looks good Details
Reviewed-on: #1659
Reviewed-by: Javi Gallego <jgallego@verdnatura.es>
Reviewed-by: Alex Moreno <alexm@verdnatura.es>
2023-07-12 06:34:42 +00:00
Vicent Llopis 808a9976ab refs #5887 fix: back etst
gitea/salix/pipeline/head This commit looks good Details
2023-07-11 13:53:25 +02:00
Vicent Llopis a831a1534b Merge branch 'dev' into 4770-routes_roadmap2
gitea/salix/pipeline/head There was a failure building this commit Details
2023-07-11 11:50:15 +00:00
Vicent Llopis 6655807d80 refs #4770 refactor: change acl
gitea/salix/pipeline/head Build queued... Details
2023-07-11 13:50:38 +02:00
Vicent Llopis a215797390 tranalstion
gitea/salix/pipeline/head There was a failure building this commit Details
2023-07-11 13:39:22 +02:00
Vicent Llopis d4217ff8d3 refs #5887 correct translations 2023-07-11 13:38:48 +02:00
Vicent Llopis 5a5a1ed20b refs #5887 feat: addback test
gitea/salix/pipeline/head This commit looks good Details
2023-07-11 13:22:54 +02:00
Vicent Llopis e1f12bea02 a
gitea/salix/pipeline/head There was a failure building this commit Details
2023-07-11 12:33:44 +02:00
Vicent Llopis d4a4e04f25 refs #5887 feat: cambiados permisos para añadir/quitar alias de correo 2023-07-11 12:33:34 +02:00
Vicent Llopis 810021e23a Merge pull request 'refs #5874 feat: refactorizado proceso facturación' (!1658) from hotfix_makeInvoice-refactor into master
gitea/salix/pipeline/head This commit looks good Details
Reviewed-on: #1658
Reviewed-by: Alex Moreno <alexm@verdnatura.es>
Reviewed-by: Javi Gallego <jgallego@verdnatura.es>
2023-07-11 09:49:14 +00:00
Vicent Llopis da13f0811c refs 5887 cambiado drop y create por create or replace
gitea/salix/pipeline/head This commit looks good Details
2023-07-11 09:59:11 +02:00
Vicent Llopis 56247b5012 add acl
gitea/salix/pipeline/head This commit looks good Details
2023-07-11 09:33:45 +02:00
Vicent Llopis 93e70e699a refs #5874 feat: refactorizado proceso facturación 2023-07-11 09:19:15 +02:00
Carlos Satorres 7291b793ae refs #5949 fix traduct
gitea/salix/pipeline/head This commit looks good Details
2023-07-11 08:41:43 +02:00
Alex Moreno 6978339fd3 refs #5475 fix email translations
gitea/salix/pipeline/head This commit looks good Details
2023-07-11 08:03:36 +02:00
Carlos Satorres ba109dccc5 refs #5949 trad
gitea/salix/pipeline/head This commit looks good Details
2023-07-11 07:58:18 +02:00
Alex Moreno 43bf7ce707 Merge pull request 'refs #5475 redesign 2FA email' (!1657) from 5475_redesign_2FA_email into test
gitea/salix/pipeline/head This commit looks good Details
Reviewed-on: #1657
Reviewed-by: Vicent Llopis <vicent@verdnatura.es>
2023-07-11 05:54:28 +00:00
Alex Moreno 1bcd3039cd refs #5475 redesign 2FA email
gitea/salix/pipeline/head This commit looks good Details
2023-07-11 07:41:05 +02:00
Carlos Satorres d1c8f0ff11 refs #5949 itemRecycle
gitea/salix/pipeline/head This commit looks good Details
2023-07-11 07:37:51 +02:00
Alex Moreno 60f70ac2b4 Merge pull request 'refs #4614 fear(ticket): add 'set weight' funcionality' (!1487) from 4614-ticket_weight into dev
gitea/salix/pipeline/head This commit looks good Details
Reviewed-on: #1487
Reviewed-by: Javi Gallego <jgallego@verdnatura.es>
2023-07-10 07:22:09 +00:00
Carlos Satorres ce8927a714 Merge pull request 'change ref master' (!1653) from hotfix-extraCommunityEntryRef into master
gitea/salix/pipeline/head This commit looks good Details
Reviewed-on: #1653
Reviewed-by: Alex Moreno <alexm@verdnatura.es>
2023-07-10 07:17:16 +00:00
Alex Moreno 5e6d941f36 Merge branch 'dev' into 4614-ticket_weight
gitea/salix/pipeline/head This commit looks good Details
2023-07-10 06:53:11 +00:00
Alex Moreno d941e2e18f Merge branch 'master' into hotfix-extraCommunityEntryRef
gitea/salix/pipeline/head This commit looks good Details
2023-07-10 05:26:05 +00:00
Carlos Satorres 9f2ef5c2c0 change ref master
gitea/salix/pipeline/head This commit looks good Details
2023-07-10 07:22:23 +02:00
Alex Moreno 8922d27f20 refs #4614 fix e2e
gitea/salix/pipeline/head There was a failure building this commit Details
2023-07-07 12:25:02 +02:00
Alex Moreno d9a5868ce4 refs #5930 fix(claim_updateClaim) options
gitea/salix/pipeline/head This commit looks good Details
2023-07-07 10:55:45 +02:00
Vicent Llopis 0afddb546b Merge pull request 'refs #5978 hotfix_workCenter' (!1650) from hotfix_workCenter into test
gitea/salix/pipeline/head This commit looks good Details
Reviewed-on: #1650
Reviewed-by: Alex Moreno <alexm@verdnatura.es>
2023-07-07 08:01:48 +00:00
Vicent Llopis 6fa6c21cb1 remove fixtures
gitea/salix/pipeline/head This commit looks good Details
2023-07-07 09:31:26 +02:00
Vicent Llopis 7030be3efa fix
gitea/salix/pipeline/head This commit looks good Details
2023-07-07 09:30:04 +02:00
Alex Moreno 8fe9b387ce refs #4614 test: front and correct folder
gitea/salix/pipeline/head This commit looks good Details
2023-07-06 15:16:52 +02:00
Alex Moreno be0120728d Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 4614-ticket_weight 2023-07-06 15:15:36 +02:00
Alex Moreno d9d4441d59 refs #5970 deploy: 233001 init
gitea/salix/pipeline/head This commit looks good Details
2023-07-06 13:38:59 +02:00
Alex Moreno a665b6c060 refs #5970 fix sql
gitea/salix/pipeline/head This commit looks good Details
2023-07-06 11:51:04 +02:00
Alex Moreno ea71e980cc refs #5970 add changelog
gitea/salix/pipeline/head This commit looks good Details
2023-07-06 11:45:08 +02:00
Alex Moreno 48951cc5a1 Merge pull request '5475 - Autenticación de doble factor por email' (!1429) from 5475-email_2fa into dev
gitea/salix/pipeline/head This commit looks good Details
Reviewed-on: #1429
Reviewed-by: Javi Gallego <jgallego@verdnatura.es>
Reviewed-by: Juan Ferrer <juan@verdnatura.es>
Reviewed-by: Vicent Llopis <vicent@verdnatura.es>
2023-07-06 08:59:20 +00:00
Alex Moreno 63a8f40443 Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5475-email_2fa
gitea/salix/pipeline/head This commit looks good Details
2023-07-06 10:42:53 +02:00
Carlos Satorres a7ad947168 Merge pull request '5334-editDepartment' (!1521) from 5334-editDepartment into dev
gitea/salix/pipeline/head This commit looks good Details
Reviewed-on: #1521
Reviewed-by: Javi Gallego <jgallego@verdnatura.es>
Reviewed-by: Alex Moreno <alexm@verdnatura.es>
2023-07-06 07:08:49 +00:00
Carlos Satorres 9c9b53917a refs #5334 fix error
gitea/salix/pipeline/head This commit looks good Details
2023-07-06 08:20:33 +02:00
Carlos Satorres 83467c3b6c refs #5334 quit es
gitea/salix/pipeline/head This commit looks good Details
2023-07-06 06:08:12 +02:00
Carlos Satorres 3d9f0e1497 Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5334-editDepartment 2023-07-06 05:48:45 +02:00
Alex Moreno 6530e87508 refs #4614 feat(ticket): prevent invoice without weight
gitea/salix/pipeline/head This commit looks good Details
2023-07-05 15:20:51 +02:00
Alex Moreno 040e9e4197 Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 4614-ticket_weight
gitea/salix/pipeline/head This commit looks good Details
2023-07-05 12:50:45 +02:00
Alex Moreno 59ad603de6 refs #5816 set version
gitea/salix/pipeline/head This commit looks good Details
2023-07-05 12:22:08 +02:00
Pablo Natek 089f1e48ac Merge pull request '5347-clientCreateRefactor' (!1644) from 5347-clientCreateRefactor into dev
gitea/salix/pipeline/head This commit looks good Details
Reviewed-on: #1644
Reviewed-by: Javi Gallego <jgallego@verdnatura.es>
2023-07-05 05:22:38 +00:00
Vicent Llopis 4369d275f8 refs #4770 feat: add test
gitea/salix/pipeline/head There was a failure building this commit Details
2023-07-04 15:04:32 +02:00
Vicent Llopis e58d4e5db3 refs #4770 feat: añadida sección 'Troncales'
gitea/salix/pipeline/head This commit looks good Details
2023-07-04 14:42:51 +02:00
Carlos Satorres 5000e05e05 refs #5334 merge + e2e solve
gitea/salix/pipeline/head This commit looks good Details
2023-07-04 09:57:16 +02:00
Carlos Satorres f1502139ac Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5334-editDepartment 2023-07-04 09:56:38 +02:00
Pablo Natek 2ccf8d5197 refs #5347
gitea/salix/pipeline/head This commit looks good Details
2023-07-03 14:49:21 +02:00
Pablo Natek 6b557d5d8a refs #5347 2023-07-03 14:14:25 +02:00
Pablo Natek 4d0ed75090 Merge branch '5347-clientCreateRefactor' of https://gitea.verdnatura.es/verdnatura/salix into 5347-clientCreateRefactor
gitea/salix/pipeline/head There was a failure building this commit Details
2023-07-03 14:08:53 +02:00
Pablo Natek 9fe7024d17 refs #5347 2023-07-03 14:08:50 +02:00
Carlos Satorres 983d028d06 refs #5334 popover y basic data
gitea/salix/pipeline/head This commit looks good Details
2023-07-03 13:58:40 +02:00
Alex Moreno ff6d9e427b Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5475-email_2fa
gitea/salix/pipeline/head This commit looks good Details
2023-07-03 13:54:15 +02:00
Pablo Natek 8ef6f0dd17 Merge branch 'dev' into 5347-clientCreateRefactor
gitea/salix/pipeline/head There was a failure building this commit Details
2023-07-03 11:35:50 +00:00
Alex Moreno 461e1d4d5d refs #5475 feat: userUses, fix forbiddenError and merge in dev
gitea/salix/pipeline/head This commit looks good Details
2023-07-03 13:33:48 +02:00
Carlos Satorres 5612c56aed Merge pull request '5836-clientDefaulterisWorker' (!1639) from 5836-clientDefaulterisWorker into dev
gitea/salix/pipeline/head This commit looks good Details
Reviewed-on: #1639
Reviewed-by: Javi Gallego <jgallego@verdnatura.es>
Reviewed-by: Alex Moreno <alexm@verdnatura.es>
2023-07-03 10:53:03 +00:00
Alex Moreno 2d1420e3f8 Merge branch 'dev' into 5836-clientDefaulterisWorker
gitea/salix/pipeline/head This commit looks good Details
2023-07-03 09:51:48 +00:00
Carlos Satorres 3b346d673b Merge pull request 'refs #5753 db export and fix fixtures' (!1643) from 5753_232401_db_dump into dev
gitea/salix/pipeline/head This commit looks good Details
Reviewed-on: #1643
Reviewed-by: Carlos Satorres Adam <carlossa@verdnatura.es>
Reviewed-by: Javi Gallego <jgallego@verdnatura.es>
2023-07-03 09:49:11 +00:00
Carlos Satorres 4d03ef8f09 Merge branch 'dev' into 5836-clientDefaulterisWorker
gitea/salix/pipeline/head Build queued... Details
2023-07-03 09:47:43 +00:00
Carlos Satorres c3ef642017 refs #5836 fix fk
gitea/salix/pipeline/head This commit looks good Details
2023-07-03 11:45:05 +02:00
Alex Moreno 7fe8698b6f refs #5753 fix ticketToInvoice
gitea/salix/pipeline/head This commit looks good Details
2023-07-03 10:04:03 +02:00
Carlos Satorres 5e68363312 refs #5334 onsearch postlink
gitea/salix/pipeline/head This commit looks good Details
2023-07-03 09:38:36 +02:00
Alex Moreno d1fb2859be Merge branch 'dev' into 5753_232401_db_dump
gitea/salix/pipeline/head There was a failure building this commit Details
2023-07-03 06:59:42 +00:00
Carlos Satorres dc10c20fe3 refs #5334 email validate
gitea/salix/pipeline/head This commit looks good Details
2023-07-03 07:29:58 +02:00
Carlos Satorres dc36c6fd9d refs #5334 basicData solve e2e
gitea/salix/pipeline/head This commit looks good Details
2023-06-30 13:52:46 +02:00
Carlos Satorres e6ed834bf0 refs #5836 remove case
gitea/salix/pipeline/head This commit looks good Details
2023-06-30 10:07:29 +02:00
Carlos Satorres 3d93043b98 Merge branch '5334-editDepartment' of https://gitea.verdnatura.es/verdnatura/salix into 5334-editDepartment
gitea/salix/pipeline/head This commit looks good Details
2023-06-30 09:40:15 +02:00
Carlos Satorres 83b096c206 refs #5334 fix errors 2023-06-30 09:40:12 +02:00
Carlos Satorres 6b4501146d refs #5334 fix errors 2023-06-30 09:39:48 +02:00
Alex Moreno 6fcbf69f60 refs #5753 isNotEditableCredit to zeroCreditEditor
gitea/salix/pipeline/head This commit looks good Details
2023-06-30 08:26:51 +02:00
Alex Moreno ff320895a2 Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5753_232401_db_dump 2023-06-30 08:23:00 +02:00
Alex Moreno 0441bc29b7 refs #5475 correct SQL folder
gitea/salix/pipeline/head This commit looks good Details
2023-06-29 15:24:41 +02:00
Alex Moreno b062cec747 refs #5475 fix setPassword options/cb
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-29 15:01:24 +02:00
Alex Moreno c6bee8f2f9 Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5475-email_2fa
gitea/salix/pipeline/head This commit looks good Details
2023-06-29 14:50:06 +02:00
Carlos Satorres af91630852 refs #5836 e2e fix
gitea/salix/pipeline/head This commit looks good Details
2023-06-29 13:22:51 +02:00
Pablo Natek be1c145d9a refs #5347
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-29 10:41:41 +02:00
Carlos Satorres bb4951bbc8 Merge branch 'dev' into 5334-editDepartment
gitea/salix/pipeline/head This commit looks good Details
2023-06-29 07:47:41 +00:00
Carlos Satorres 9dc52b6011 refs #5334 fix labels trad
gitea/salix/pipeline/head This commit looks good Details
2023-06-29 09:44:21 +02:00
Pablo Natek 89b63f47fc Merge branch '5347-clientCreate-→-client_create' of https://gitea.verdnatura.es/verdnatura/salix into 5347-clientCreate-→-client_create
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-29 08:14:10 +02:00
Pablo Natek c9c20711b9 refs #5347 2023-06-29 08:13:44 +02:00
Pablo Natek bbc5ed2683 Merge branch 'dev' into 5347-clientCreate-→-client_create
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-29 05:22:06 +00:00
Alex Moreno 8723cf2958 refs #5753 fix legacy bugs
gitea/salix/pipeline/head This commit looks good Details
2023-06-28 14:10:21 +02:00
Pablo Natek 54e75dc850 Merge branch '5347-clientCreate-→-client_create' of https://gitea.verdnatura.es/verdnatura/salix into 5347-clientCreate-→-client_create
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-28 14:07:38 +02:00
Pablo Natek 6e52b3b968 refs #5347 2023-06-28 14:07:37 +02:00
Carlos Satorres f02019d64d refs #5334 fix words
gitea/salix/pipeline/head This commit looks good Details
2023-06-28 11:52:53 +02:00
Alex Moreno 89c25c07b6 refs #5475 fix e2e and back test
gitea/salix/pipeline/head This commit looks good Details
2023-06-28 09:59:55 +02:00
Alex Moreno 31d637c8a7 Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5475-email_2fa
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-28 07:19:04 +02:00
Alex Moreno 162faf0d01 Merge branch '5475-email_2fa' of https://gitea.verdnatura.es/verdnatura/salix into 5475-email_2fa 2023-06-28 07:18:10 +02:00
Carlos Satorres 06437c9e80 refs #5334 remove other
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-28 07:02:59 +02:00
Alex Moreno 4b8b7a9d82 refs #5475 fix accessScope
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-27 15:30:54 +02:00
Carlos Satorres 07712f58e7 Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5334-editDepartment 2023-06-27 13:36:51 +02:00
Carlos Satorres f0b238b62a refs #5836 fix e2e
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-27 12:31:58 +02:00
Carlos Satorres 5216f12001 refs #5836 check fix
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-27 10:27:39 +02:00
Alex Moreno e43e52b561 refs #5753 db export and fix fixtures
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-26 15:21:45 +02:00
Carlos Satorres 24ea18aeb0 refs #5836 isworker back
gitea/salix/pipeline/head This commit looks good Details
2023-06-26 13:55:39 +02:00
Alex Moreno 798481b24a Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5475-email_2fa 2023-06-26 07:53:44 +02:00
Carlos Satorres eff46c1cec refs #5066 e2e fix, vnConfig
gitea/salix/pipeline/head This commit looks good Details
2023-06-26 07:43:36 +02:00
Carlos Satorres dcbe8c5f7a refs #5066 quit if
gitea/salix/pipeline/head This commit looks good Details
2023-06-26 06:28:35 +02:00
Carlos Satorres abfe012a78 Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5066-vehicleSorted 2023-06-26 06:12:22 +02:00
Pablo Natek 16af0c5d6c Merge branch 'dev' into 5347-clientCreate-→-client_create
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-22 16:02:30 +00:00
Pablo Natek 203e80afa8 refs #5347
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-22 17:56:45 +02:00
Pablo Natek f0fec2cdd6 refs #5347
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-22 17:46:21 +02:00
Pablo Natek f6cc59eafb refs #5347
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-22 16:23:36 +02:00
Carlos Satorres beb173f6ce refs #5334 quit e2e no necesario
gitea/salix/pipeline/head This commit looks good Details
2023-06-22 15:20:28 +02:00
Carlos Satorres 137e01e60c refs #5334 fix acl, filter
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-22 15:00:59 +02:00
Pablo Natek 27946c0062 Refs #5347
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-22 15:00:15 +02:00
Carlos Satorres 4931745cde Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5334-editDepartment 2023-06-22 14:42:28 +02:00
Carlos Satorres 7f9d8da7a7 refs #5836 defaulter
gitea/salix/pipeline/head This commit looks good Details
2023-06-22 11:42:21 +02:00
Alex Moreno 6ab431f8ef refs #5475 tests
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-21 14:17:25 +02:00
Carlos Satorres 168d05a830 refs #5334 fix errors
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-21 13:07:04 +02:00
Alex Moreno 2ddf8e5de6 Merge branch 'dev' into 5334-editDepartment
gitea/salix/pipeline/head This commit looks good Details
2023-06-21 06:24:19 +00:00
Alex Moreno d6c504d3bb Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5475-email_2fa
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-21 07:53:40 +02:00
Pablo Natek e741904250 refs #5347
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-20 17:01:06 +02:00
Alex Moreno a8fafacb82 refs #5475 send email force
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-20 15:06:02 +02:00
Carlos Satorres fa10070675 Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5066-vehicleSorted
gitea/salix/pipeline/head This commit looks good Details
2023-06-20 14:04:38 +02:00
Carlos Satorres f0f8b112cd Merge branch 'dev' into 5334-editDepartment
gitea/salix/pipeline/head This commit looks good Details
2023-06-20 07:22:52 +00:00
Carlos Satorres c63df30e5c refs #5334 fix back
gitea/salix/pipeline/head This commit looks good Details
2023-06-20 09:19:20 +02:00
Carlos Satorres a155f846c2 refs #5334 fix ctx
gitea/salix/pipeline/head This commit looks good Details
2023-06-20 09:15:37 +02:00
Carlos Satorres 4537344790 merge
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-20 08:20:13 +02:00
Carlos Satorres 7f20973650 refs #5334 merge
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-20 08:16:36 +02:00
Alex Moreno 092471f74e refs #5475 feat(account_changePassword): accessScope and backTest
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-19 15:06:06 +02:00
Carlos Satorres 168e7f1929 changelog
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-19 13:48:54 +02:00
Carlos Satorres 3701acd26e refs #5334 error getLeaves solve
gitea/salix/pipeline/head Build queued... Details
2023-06-19 13:48:14 +02:00
Carlos Satorres 98125f8974 Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5334-editDepartment 2023-06-19 13:22:41 +02:00
Carlos Satorres d4cc9cf82a change log remove
gitea/salix/pipeline/head This commit looks good Details
2023-06-19 13:21:26 +02:00
Alex Moreno ee1b901dea refs #5475 feat(account_changePassword): accessScope
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-16 14:31:14 +02:00
Alex Moreno dd157d59d9 Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5475-email_2fa
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-16 13:42:13 +02:00
Alex Moreno cf01c8d46e refs #5475 feat(account_changePassword)
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-16 09:35:20 +02:00
Alex Moreno b96f0f22b5 refs #5475 feat(account_changePassword)
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-15 15:16:51 +02:00
Alex Moreno 3a5e591cf0 refs #5475 feat(signin): use twoFactor and passExpired
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-14 15:15:00 +02:00
Alex Moreno aeb04efe82 Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5475-email_2fa
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-13 11:49:42 +02:00
Alex Moreno 051269d646 Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5475-email_2fa
gitea/salix/pipeline/head This commit looks good Details
2023-06-12 09:11:17 +02:00
Carlos Satorres cc27d1fa97 refs #5066 fix vehicle res.data
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-07 08:30:37 +02:00
Carlos Satorres 738b04af4c Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5066-vehicleSorted 2023-06-07 08:15:50 +02:00
Carlos Satorres d6cde764d7 refs #5334 changelog
gitea/salix/pipeline/head This commit looks good Details
2023-06-05 10:38:08 +02:00
Carlos Satorres 8afd149954 Merge branch '5334-editDepartment' of https://gitea.verdnatura.es/verdnatura/salix into 5334-editDepartment
gitea/salix/pipeline/head This commit looks good Details
2023-06-05 09:06:45 +02:00
Carlos Satorres 2545a40087 Merge branch 'dev' into 5334-editDepartment
gitea/salix/pipeline/head This commit looks good Details
2023-06-05 07:00:27 +00:00
Carlos Satorres d8f5978284 Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5334-editDepartment 2023-06-05 08:30:12 +02:00
Carlos Satorres c1cda1a3ff refs #5334 basicData e2e
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-05 08:29:56 +02:00
Carlos Satorres 9ef51f5600 remove fdescribe puppeter
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-05 07:55:53 +02:00
Carlos Satorres 5798b28c5e refs #5334 baicData e2e
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-05 07:51:15 +02:00
Carlos Satorres 1095a59954 refs #5334 rest back, e2e summary, less e2e basic
gitea/salix/pipeline/head This commit looks good Details
2023-06-02 14:44:56 +02:00
Carlos Satorres 5f72fabf8e Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5334-editDepartment 2023-06-02 08:21:14 +02:00
Carlos Satorres 04780e211d refs #5334 test front & 1/2 back
gitea/salix/pipeline/head There was a failure building this commit Details
2023-06-01 16:03:55 +02:00
Carlos Satorres bb5247c49b refs #5334 tree
gitea/salix/pipeline/head This commit looks good Details
2023-06-01 14:19:50 +02:00
Carlos Satorres f37c66304f refs #5334 change info
gitea/salix/pipeline/head This commit looks good Details
2023-06-01 12:00:15 +02:00
Carlos Satorres 4c7c7f5c96 refs #5334 mod search-panel
gitea/salix/pipeline/head This commit looks good Details
2023-06-01 11:30:28 +02:00
Carlos Satorres eb6953a2b6 refs #5334 department
gitea/salix/pipeline/head This commit looks good Details
2023-05-31 12:50:02 +02:00
Carlos Satorres d1a61b3e0d refs #5334 dinamic
gitea/salix/pipeline/head This commit looks good Details
2023-05-31 12:26:49 +02:00
Carlos Satorres 489012886b Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5334-editDepartment 2023-05-31 12:04:26 +02:00
Carlos Satorres e38bf4f1b3 refs #5334 button delete, btn popover
gitea/salix/pipeline/head This commit looks good Details
2023-05-31 12:02:22 +02:00
Carlos Satorres 0774a94d8b refs #5334 params
gitea/salix/pipeline/head This commit looks good Details
2023-05-31 11:24:11 +02:00
Carlos Satorres d18137bce0 refs #5066 not dense
gitea/salix/pipeline/head This commit looks good Details
2023-05-31 10:20:13 +02:00
Carlos Satorres cfe0ba7a77 Merge branch '5066-vehicleSorted' of https://gitea.verdnatura.es/verdnatura/salix into 5066-vehicleSorted
gitea/salix/pipeline/head This commit looks good Details
2023-05-31 10:04:36 +02:00
Carlos Satorres dfebb3b307 refs #5066 sorted without CONCAT, order=false 2023-05-31 10:04:34 +02:00
Carlos Satorres 0fd7f4183e refs #5334 fk
gitea/salix/pipeline/head This commit looks good Details
2023-05-30 15:36:39 +02:00
Carlos Satorres 1dcaba1fdc refs #5334 department workers list
gitea/salix/pipeline/head This commit looks good Details
2023-05-30 15:13:16 +02:00
Carlos Satorres 26187898e1 refs #5334 popover
gitea/salix/pipeline/head This commit looks good Details
2023-05-30 14:02:34 +02:00
Carlos Satorres 8860c77147 refs #5334 fix descriptor
gitea/salix/pipeline/head This commit looks good Details
2023-05-30 13:21:57 +02:00
Carlos Satorres 45085cccc8 refs #5334 fix search-panel
gitea/salix/pipeline/head This commit looks good Details
2023-05-30 12:54:51 +02:00
Carlos Satorres 813c4ede00 Merge branch 'dev' into 5066-vehicleSorted
gitea/salix/pipeline/head This commit looks good Details
2023-05-30 10:22:49 +00:00
Carlos Satorres eaffd61579 Merge branch '5066-vehicleSorted' of https://gitea.verdnatura.es/verdnatura/salix into 5066-vehicleSorted
gitea/salix/pipeline/head This commit looks good Details
2023-05-30 12:21:47 +02:00
Carlos Satorres 0661bf8fa9 refs #5066 remake sql without ROW_ORDER 2023-05-30 12:21:44 +02:00
Carlos Satorres e7d25a6cf3 refs #5334 filter
gitea/salix/pipeline/head This commit looks good Details
2023-05-30 12:08:45 +02:00
Carlos Satorres e26eedb51c refs #5334 descriptor wprkerFk clientFk
gitea/salix/pipeline/head This commit looks good Details
2023-05-30 11:54:14 +02:00
Carlos Satorres cf632040e7 refs #5334 workFk, clientFk
gitea/salix/pipeline/head There was a failure building this commit Details
2023-05-30 11:48:39 +02:00
Carlos Satorres 2778858705 refs #5334 search-panel
gitea/salix/pipeline/head There was a failure building this commit Details
2023-05-30 10:27:49 +02:00
Carlos Satorres 107d8d1edd refs #5334 model y vista
gitea/salix/pipeline/head There was a failure building this commit Details
2023-05-30 10:13:49 +02:00
Carlos Satorres d9a64211de refs #5334 fix descriptor, basic-data, summary
gitea/salix/pipeline/head There was a failure building this commit Details
2023-05-30 09:16:02 +02:00
Alex Moreno 8fff3989e7 Merge branch 'dev' into 5066-vehicleSorted
gitea/salix/pipeline/head This commit looks good Details
2023-05-30 06:30:48 +00:00
Carlos Satorres 9ee653dbd1 Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5334-editDepartment 2023-05-30 08:05:17 +02:00
Carlos Satorres 2d6f0bb2ce refs #5334 front fix
gitea/salix/pipeline/head There was a failure building this commit Details
2023-05-29 15:27:50 +02:00
Carlos Satorres f4e877dada refs #5334 refactor summary
gitea/salix/pipeline/head There was a failure building this commit Details
2023-05-29 14:46:39 +02:00
Carlos Satorres 3423ce612c refs #5066 e2e fixs, change name sorted
gitea/salix/pipeline/head This commit looks good Details
2023-05-29 13:49:32 +02:00
Carlos Satorres d8e7c2700a refs #5066 fix autocomplete
gitea/salix/pipeline/head This commit looks good Details
2023-05-29 12:42:27 +02:00
Carlos Satorres 91edc09057 refs #5066 move sql
gitea/salix/pipeline/head This commit looks good Details
2023-05-29 10:24:37 +02:00
Carlos Satorres 2e83d91006 Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5066-vehicleSorted 2023-05-29 10:24:19 +02:00
Carlos Satorres 2a78a912eb refs #5334 worker.department
gitea/salix/pipeline/head There was a failure building this commit Details
2023-05-26 14:35:12 +02:00
Carlos Satorres 3aa5ce6208 refs #5334 fix hasToSendMail
gitea/salix/pipeline/head There was a failure building this commit Details
2023-05-26 14:23:34 +02:00
Carlos Satorres ceaaece007 refs #5334 label-value
gitea/salix/pipeline/head There was a failure building this commit Details
2023-05-26 14:08:37 +02:00
Carlos Satorres 07e176ae4f refs #5334 fix checks basic-data
gitea/salix/pipeline/head There was a failure building this commit Details
2023-05-26 13:25:49 +02:00
Carlos Satorres f74c370446 refs #5334 checks vertical
gitea/salix/pipeline/head There was a failure building this commit Details
2023-05-26 13:15:47 +02:00
Alex Moreno 0789804352 refs #5334 fix basic-data
gitea/salix/pipeline/head There was a failure building this commit Details
2023-05-26 12:58:03 +02:00
Alex Moreno 2b06c62876 refs #5334 left-menu
gitea/salix/pipeline/head There was a failure building this commit Details
2023-05-26 12:21:15 +02:00
Carlos Satorres 027d45bc25 Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5334-editDepartment
gitea/salix/pipeline/head There was a failure building this commit Details
2023-05-26 11:47:04 +02:00
Carlos Satorres 10e085ca1b refs #5334 link department
gitea/salix/pipeline/head There was a failure building this commit Details
2023-05-26 11:43:51 +02:00
Carlos Satorres adafd7444b refs #5334 worker-department
gitea/salix/pipeline/head There was a failure building this commit Details
2023-05-17 10:04:44 +02:00
Carlos Satorres f63dd0f9a3 refs #5334 datos
gitea/salix/pipeline/head There was a failure building this commit Details
2023-05-17 09:05:28 +02:00
Carlos Satorres 5c9ee21cfc refs #5334 department.card
gitea/salix/pipeline/head There was a failure building this commit Details
2023-05-16 14:00:05 +02:00
Carlos Satorres 9f9963af56 refs #5334 descriptor
gitea/salix/pipeline/head There was a failure building this commit Details
2023-05-16 13:10:26 +02:00
Carlos Satorres d09889b08a refs #5334 fix summary route
gitea/salix/pipeline/head There was a failure building this commit Details
2023-05-16 12:12:25 +02:00
Carlos Satorres 3dcdbe0223 refs #5334 summary basic data
gitea/salix/pipeline/head There was a failure building this commit Details
2023-05-16 11:41:42 +02:00
Carlos Satorres 612d0a2dfb refs #5334 fix index
gitea/salix/pipeline/head There was a failure building this commit Details
2023-05-16 09:52:48 +02:00
Carlos Satorres fd4d04756a refs #5334 routes index fix
gitea/salix/pipeline/head There was a failure building this commit Details
2023-05-16 08:54:54 +02:00
Carlos Satorres 443821b5c2 refs #5334 ?q
gitea/salix/pipeline/head There was a failure building this commit Details
2023-05-15 13:59:54 +02:00
Carlos Satorres 071849065a refs #5334 fix main
gitea/salix/pipeline/head There was a failure building this commit Details
2023-05-15 13:55:35 +02:00
Carlos Satorres 598067f757 refs #5334 routes
gitea/salix/pipeline/head There was a failure building this commit Details
2023-05-15 13:15:33 +02:00
Carlos Satorres 87e1caa4eb refs #5334 department seccion
gitea/salix/pipeline/head There was a failure building this commit Details
2023-05-15 10:43:06 +02:00
Alex Moreno 7021e52705 correct folder
gitea/salix/pipeline/head This commit looks good Details
2023-05-09 07:11:21 +02:00
Alex Moreno 8ae67799a1 Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5475-email_2fa 2023-05-09 07:11:09 +02:00
Alex Moreno c1ea1acc8c refs #4614 fear(ticket): add 'set weight' funcionality
gitea/salix/pipeline/head This commit looks good Details
2023-04-26 13:49:08 +02:00
Carlos Satorres 237c83c6f5 refs #5066 getVehicleSorted small mod
gitea/salix/pipeline/head This commit looks good Details
2023-04-20 10:20:15 +02:00
Carlos Satorres 89a3ef5f8d Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5066-vehicleSorted
gitea/salix/pipeline/head There was a failure building this commit Details
2023-04-20 09:30:20 +02:00
Carlos Satorres 16fdfa00fd refs #5066 e2e solve
gitea/salix/pipeline/head There was a failure building this commit Details
2023-04-20 09:09:48 +02:00
Carlos Satorres b45b0ff826 refs #5066 copy project from the other
gitea/salix/pipeline/head There was a failure building this commit Details
2023-04-20 08:23:46 +02:00
Joan Sanchez c3443ecc7c Updated e2e
gitea/salix/pipeline/head This commit looks good Details
2023-04-18 14:37:20 +02:00
Joan Sanchez c2af40edb5 changes 2023-04-18 13:15:04 +02:00
Joan Sanchez d5ea45e36f Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5475-email_2fa 2023-04-18 13:14:57 +02:00
Joan Sanchez cdf092a989 Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5475-email_2fa 2023-04-18 11:52:17 +02:00
Joan Sanchez ef87dcc0f5 require authentication on every login
gitea/salix/pipeline/head There was a failure building this commit Details
2023-04-18 07:38:40 +02:00
Joan Sanchez 9aaea7e8ed Changed to new SQL version
gitea/salix/pipeline/head There was a failure building this commit Details
2023-04-13 12:01:51 +02:00
Joan Sanchez f5d26bdb99 Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5475-email_2fa 2023-04-13 12:00:22 +02:00
Joan Sanchez b5f2cf3711 Added unit test & translation fixes
gitea/salix/pipeline/head There was a failure building this commit Details
2023-04-13 11:54:56 +02:00
Joan Sanchez 4807fcb394 Removed focus
gitea/salix/pipeline/head There was a failure building this commit Details
2023-04-11 09:01:59 +02:00
Joan Sanchez b0f1bae33e Added unit test
gitea/salix/pipeline/head There was a failure building this commit Details
2023-04-11 08:56:50 +02:00
Joan Sanchez 087e91e898 Updated unit tests 2023-04-11 08:15:46 +02:00
Joan Sanchez b9e48f2102 Added translations & enable through departments
gitea/salix/pipeline/head There was a failure building this commit Details
2023-04-11 07:39:43 +02:00
Joan Sanchez 2e0325e567 Validate code
gitea/salix/pipeline/head There was a failure building this commit Details
2023-04-06 14:59:25 +02:00
Joan Sanchez 641fdf39d8 Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5475-email_2fa 2023-04-06 09:26:55 +02:00
Joan Sanchez 902709d61b Added authCode table
gitea/salix/pipeline/head There was a failure building this commit Details
2023-04-05 15:22:09 +02:00
Joan Sanchez 0d6b248f76 feat(2fa): email 2fa
gitea/salix/pipeline/head This commit looks good Details
Refs #5475
2023-04-04 14:59:33 +02:00
196 changed files with 6291 additions and 3659 deletions

View File

@ -5,6 +5,29 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [2330.01] - 2023-07-27
### Added
### Changed
### Fixed
## [2328.01] - 2023-07-13
### Added
- (Clientes -> Morosos) Añadida columna "es trabajador"
- (Trabajadores -> Departamentos) Nueva sección
- (Trabajadores -> Departamentos) Añadido listado de Trabajadores por departamento
- (Trabajadores -> Departamentos) Añadido características de departamento e información
### Changed
### Fixed
- (Trabajadores -> Departamentos) Arreglado búscador
## [2326.01] - 2023-06-29
### Added

View File

@ -0,0 +1,68 @@
const UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
Self.remoteMethod('addAlias', {
description: 'Add an alias if the user has the grant',
accessType: 'WRITE',
accepts: [
{
arg: 'ctx',
type: 'Object',
http: {source: 'context'}
},
{
arg: 'id',
type: 'number',
required: true,
description: 'The user id',
http: {source: 'path'}
},
{
arg: 'mailAlias',
type: 'number',
description: 'The new alias for user',
required: true
}
],
http: {
path: `/:id/addAlias`,
verb: 'POST'
}
});
Self.addAlias = async function(ctx, id, mailAlias, options) {
const models = Self.app.models;
const userId = ctx.req.accessToken.userId;
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const user = await Self.findById(userId, {fields: ['hasGrant']}, myOptions);
if (!user.hasGrant)
throw new UserError(`You don't have grant privilege`);
const account = await models.Account.findById(userId, {
fields: ['id'],
include: {
relation: 'aliases',
scope: {
fields: ['mailAlias']
}
}
}, myOptions);
const aliases = account.aliases().map(alias => alias.mailAlias);
const hasAlias = aliases.includes(mailAlias);
if (!hasAlias)
throw new UserError(`You cannot assign an alias that you are not assigned to`);
return models.MailAliasAccount.create({
mailAlias: mailAlias,
account: id
}, myOptions);
};
};

View File

@ -0,0 +1,55 @@
const UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
Self.remoteMethod('removeAlias', {
description: 'Remove alias if the user has the grant',
accessType: 'WRITE',
accepts: [
{
arg: 'ctx',
type: 'Object',
http: {source: 'context'}
},
{
arg: 'id',
type: 'number',
required: true,
description: 'The user id',
http: {source: 'path'}
},
{
arg: 'mailAlias',
type: 'number',
description: 'The alias to delete',
required: true
}
],
http: {
path: `/:id/removeAlias`,
verb: 'POST'
}
});
Self.removeAlias = async function(ctx, id, mailAlias, options) {
const models = Self.app.models;
const userId = ctx.req.accessToken.userId;
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const canRemoveAlias = await models.ACL.checkAccessAcl(ctx, 'VnUser', 'canRemoveAlias', 'WRITE');
if (userId != id && !canRemoveAlias) throw new UserError(`You don't have grant privilege`);
const mailAliasAccount = await models.MailAliasAccount.findOne({
where: {
mailAlias: mailAlias,
account: id
}
}, myOptions);
await mailAliasAccount.destroy(myOptions);
};
};

View File

@ -0,0 +1,102 @@
const ForbiddenError = require('vn-loopback/util/forbiddenError');
const UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
Self.remoteMethodCtx('signIn', {
description: 'Login a user with username/email and password',
accepts: [
{
arg: 'user',
type: 'String',
description: 'The user name or email',
required: true
}, {
arg: 'password',
type: 'String',
description: 'The password'
}
],
returns: {
type: 'object',
root: true
},
http: {
path: `/sign-in`,
verb: 'POST'
}
});
Self.signIn = async function(ctx, user, password, options) {
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const where = Self.userUses(user);
const vnUser = await Self.findOne({
fields: ['id', 'name', 'password', 'active', 'email', 'passExpired', 'twoFactor'],
where
}, myOptions);
const validCredentials = vnUser
&& await vnUser.hasPassword(password);
if (validCredentials) {
if (!vnUser.active)
throw new UserError('User disabled');
await Self.sendTwoFactor(ctx, vnUser, myOptions);
await Self.passExpired(vnUser, myOptions);
if (vnUser.twoFactor)
throw new ForbiddenError(null, 'REQUIRES_2FA');
}
return Self.validateLogin(user, password);
};
Self.passExpired = async(vnUser, myOptions) => {
const today = Date.vnNew();
today.setHours(0, 0, 0, 0);
if (vnUser.passExpired && vnUser.passExpired.getTime() <= today.getTime()) {
const $ = Self.app.models;
const changePasswordToken = await $.AccessToken.create({
scopes: ['changePassword'],
userId: vnUser.id
}, myOptions);
const err = new UserError('Pass expired', 'passExpired');
changePasswordToken.twoFactor = vnUser.twoFactor ? true : false;
err.details = {token: changePasswordToken};
throw err;
}
};
Self.sendTwoFactor = async(ctx, vnUser, myOptions) => {
if (vnUser.twoFactor === 'email') {
const $ = Self.app.models;
const code = String(Math.floor(Math.random() * 999999));
const maxTTL = ((60 * 1000) * 5); // 5 min
await $.AuthCode.upsertWithWhere({userFk: vnUser.id}, {
userFk: vnUser.id,
code: code,
expires: Date.vnNow() + maxTTL
}, myOptions);
const headers = ctx.req.headers;
const platform = headers['sec-ch-ua-platform']?.replace(/['"=]+/g, '');
const browser = headers['sec-ch-ua']?.replace(/['"=]+/g, '');
const params = {
args: {
recipientId: vnUser.id,
recipient: vnUser.email,
code: code,
ip: ctx.req?.connection?.remoteAddress,
device: platform && browser ? platform + ', ' + browser : headers['user-agent'],
},
req: {getLocale: ctx.req.getLocale},
};
await Self.sendTemplate(params, 'auth-code', true);
}
};
};

View File

@ -1,81 +0,0 @@
const UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
Self.remoteMethod('signIn', {
description: 'Login a user with username/email and password',
accepts: [
{
arg: 'user',
type: 'String',
description: 'The user name or email',
http: {source: 'form'},
required: true
}, {
arg: 'password',
type: 'String',
description: 'The password'
}
],
returns: {
type: 'object',
root: true
},
http: {
path: `/signIn`,
verb: 'POST'
}
});
Self.signIn = async function(user, password) {
const models = Self.app.models;
const usesEmail = user.indexOf('@') !== -1;
let token;
const userInfo = usesEmail
? {email: user}
: {username: user};
const instance = await Self.findOne({
fields: ['username', 'password'],
where: userInfo
});
const where = usesEmail
? {email: user}
: {name: user};
const vnUser = await Self.findOne({
fields: ['id', 'active', 'passExpired'],
where
});
const today = Date.vnNew();
today.setHours(0, 0, 0, 0);
const validCredentials = instance
&& await instance.hasPassword(password);
if (validCredentials) {
if (!vnUser.active)
throw new UserError('User disabled');
if (vnUser.passExpired && vnUser.passExpired.getTime() <= today.getTime()) {
const changePasswordToken = await models.AccessToken.create({
scopes: ['change-password'],
userId: vnUser.id
});
const err = new UserError('Pass expired', 'passExpired');
err.details = {token: changePasswordToken};
throw err;
}
try {
await models.Account.sync(instance.username, password);
} catch (err) {
console.warn(err);
}
}
let loginInfo = Object.assign({password}, userInfo);
token = await Self.login(loginInfo, 'user');
return {token: token.id, ttl: token.ttl};
};
};

View File

@ -0,0 +1,101 @@
const {models} = require('vn-loopback/server/server');
describe('VnUser Sign-in()', () => {
const employeeId = 1;
const unauthCtx = {
req: {
headers: {},
connection: {
remoteAddress: '127.0.0.1'
},
getLocale: () => 'en'
},
args: {}
};
const {VnUser, AccessToken} = models;
describe('when credentials are correct', () => {
it('should return the token', async() => {
let login = await VnUser.signIn(unauthCtx, 'salesAssistant', 'nightmare');
let accessToken = await AccessToken.findById(login.token);
let ctx = {req: {accessToken: accessToken}};
expect(login.token).toBeDefined();
await VnUser.logout(ctx.req.accessToken.id);
});
it('should return the token if the user doesnt exist but the client does', async() => {
let login = await VnUser.signIn(unauthCtx, 'PetterParker', 'nightmare');
let accessToken = await AccessToken.findById(login.token);
let ctx = {req: {accessToken: accessToken}};
expect(login.token).toBeDefined();
await VnUser.logout(ctx.req.accessToken.id);
});
});
describe('when credentials are incorrect', () => {
it('should throw a 401 error', async() => {
let error;
try {
await VnUser.signIn(unauthCtx, 'IDontExist', 'TotallyWrongPassword');
} catch (e) {
error = e;
}
expect(error).toBeDefined();
expect(error.statusCode).toBe(401);
expect(error.code).toBe('LOGIN_FAILED');
});
});
describe('when two-factor auth is required', () => {
it('should throw a 403 error', async() => {
const employee = await VnUser.findById(employeeId);
const tx = await VnUser.beginTransaction({});
let error;
try {
const options = {transaction: tx};
await employee.updateAttribute('twoFactor', 'email', options);
await VnUser.signIn(unauthCtx, 'employee', 'nightmare', options);
await tx.rollback();
} catch (e) {
await tx.rollback();
error = e;
}
expect(error).toBeDefined();
expect(error.statusCode).toBe(403);
expect(error.code).toBe('REQUIRES_2FA');
});
});
describe('when passExpired', () => {
it('should throw a passExpired error', async() => {
const tx = await VnUser.beginTransaction({});
const employee = await VnUser.findById(employeeId);
const yesterday = Date.vnNew();
yesterday.setDate(yesterday.getDate() - 1);
let error;
try {
const options = {transaction: tx};
await employee.updateAttribute('passExpired', yesterday, options);
await VnUser.signIn(unauthCtx, 'employee', 'nightmare', options);
await tx.rollback();
} catch (e) {
await tx.rollback();
error = e;
}
expect(error).toBeDefined();
expect(error.statusCode).toBe(400);
expect(error.message).toBe('Pass expired');
});
});
});

View File

@ -1,41 +0,0 @@
const {models} = require('vn-loopback/server/server');
describe('VnUser signIn()', () => {
describe('when credentials are correct', () => {
it('should return the token', async() => {
let login = await models.VnUser.signIn('salesAssistant', 'nightmare');
let accessToken = await models.AccessToken.findById(login.token);
let ctx = {req: {accessToken: accessToken}};
expect(login.token).toBeDefined();
await models.VnUser.logout(ctx.req.accessToken.id);
});
it('should return the token if the user doesnt exist but the client does', async() => {
let login = await models.VnUser.signIn('PetterParker', 'nightmare');
let accessToken = await models.AccessToken.findById(login.token);
let ctx = {req: {accessToken: accessToken}};
expect(login.token).toBeDefined();
await models.VnUser.logout(ctx.req.accessToken.id);
});
});
describe('when credentials are incorrect', () => {
it('should throw a 401 error', async() => {
let error;
try {
await models.VnUser.signIn('IDontExist', 'TotallyWrongPassword');
} catch (e) {
error = e;
}
expect(error).toBeDefined();
expect(error.statusCode).toBe(401);
expect(error.code).toBe('LOGIN_FAILED');
});
});
});

View File

@ -0,0 +1,52 @@
const {models} = require('vn-loopback/server/server');
describe('VnUser validate-auth()', () => {
describe('validateAuth', () => {
it('should signin if data is correct', async() => {
await models.AuthCode.create({
userFk: 9,
code: '555555',
expires: Date.vnNow() + (60 * 1000)
});
const token = await models.VnUser.validateAuth('developer', 'nightmare', '555555');
expect(token.token).toBeDefined();
});
});
describe('validateCode', () => {
it('should throw an error for a non existent code', async() => {
let error;
try {
await models.VnUser.validateCode('developer', '123456');
} catch (e) {
error = e;
}
expect(error).toBeDefined();
expect(error.statusCode).toBe(400);
expect(error.message).toEqual('Invalid or expired verification code');
});
it('should throw an error when a code doesn`t match the login username', async() => {
let error;
let authCode;
try {
authCode = await models.AuthCode.create({
userFk: 1,
code: '555555',
expires: Date.vnNow() + (60 * 1000)
});
await models.VnUser.validateCode('developer', '555555');
} catch (e) {
authCode && await authCode.destroy();
error = e;
}
expect(error).toBeDefined();
expect(error.statusCode).toBe(400);
expect(error.message).toEqual('Authentication failed');
});
});
});

View File

@ -0,0 +1,66 @@
const UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
Self.remoteMethod('validateAuth', {
description: 'Login a user with username/email and password',
accepts: [
{
arg: 'user',
type: 'String',
description: 'The user name or email',
required: true
},
{
arg: 'password',
type: 'String',
description: 'The password'
},
{
arg: 'code',
type: 'String',
description: 'The auth code'
}
],
returns: {
type: 'object',
root: true
},
http: {
path: `/validate-auth`,
verb: 'POST'
}
});
Self.validateAuth = async(username, password, code, options) => {
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const token = Self.validateLogin(username, password);
await Self.validateCode(username, code, myOptions);
return token;
};
Self.validateCode = async(username, code, myOptions) => {
const {AuthCode} = Self.app.models;
const authCode = await AuthCode.findOne({
where: {
code: code
}
}, myOptions);
const expired = authCode && Date.vnNow() > authCode.expires;
if (!authCode || expired)
throw new UserError('Invalid or expired verification code');
const user = await Self.findById(authCode.userFk, {
fields: ['name', 'twoFactor']
}, myOptions);
if (user.name !== username)
throw new UserError('Authentication failed');
await authCode.destroy(myOptions);
};
};

View File

@ -1,7 +1,4 @@
{
"AccountingType": {
"dataSource": "vn"
},
"AccessTokenConfig": {
"dataSource": "vn",
"options": {
@ -10,6 +7,12 @@
}
}
},
"AccountingType": {
"dataSource": "vn"
},
"AuthCode": {
"dataSource": "vn"
},
"Bank": {
"dataSource": "vn"
},

View File

@ -0,0 +1,31 @@
{
"name": "AuthCode",
"base": "VnModel",
"options": {
"mysql": {
"table": "salix.authCode"
}
},
"properties": {
"userFk": {
"type": "number",
"required": true,
"id": true
},
"code": {
"type": "string",
"required": true
},
"expires": {
"type": "number",
"required": true
}
},
"relations": {
"user": {
"type": "belongsTo",
"model": "Account",
"foreignKey": "userFk"
}
}
}

View File

@ -5,12 +5,15 @@ const {Email} = require('vn-print');
module.exports = function(Self) {
vnModel(Self);
require('../methods/vn-user/signIn')(Self);
require('../methods/vn-user/sign-in')(Self);
require('../methods/vn-user/acl')(Self);
require('../methods/vn-user/recover-password')(Self);
require('../methods/vn-user/validate-token')(Self);
require('../methods/vn-user/privileges')(Self);
require('../methods/vn-user/validate-auth')(Self);
require('../methods/vn-user/renew-token')(Self);
require('../methods/vn-user/addAlias')(Self);
require('../methods/vn-user/removeAlias')(Self);
Self.definition.settings.acls = Self.definition.settings.acls.filter(acl => acl.property !== 'create');
@ -111,6 +114,18 @@ module.exports = function(Self) {
return email.send();
});
Self.validateLogin = async function(user, password) {
let loginInfo = Object.assign({password}, Self.userUses(user));
token = await Self.login(loginInfo, 'user');
return {token: token.id, ttl: token.ttl};
};
Self.userUses = function(user) {
return user.indexOf('@') !== -1
? {email: user}
: {username: user};
};
const _setPassword = Self.prototype.setPassword;
Self.prototype.setPassword = async function(newPassword, options, cb) {
if (cb === undefined && typeof options === 'function') {
@ -143,8 +158,9 @@ module.exports = function(Self) {
}
};
Self.sharedClass._methods.find(method => method.name == 'changePassword')
.accessScopes = ['change-password'];
Self.sharedClass._methods.find(method => method.name == 'changePassword').ctor.settings.acls =
Self.sharedClass._methods.find(method => method.name == 'changePassword').ctor.settings.acls
.filter(acl => acl.property != 'changePassword');
// FIXME: https://redmine.verdnatura.es/issues/5761
// Self.afterRemote('prototype.patchAttributes', async(ctx, instance) => {

View File

@ -59,7 +59,10 @@
},
"passExpired": {
"type": "date"
}
},
"twoFactor": {
"type": "string"
}
},
"relations": {
"role": {
@ -111,6 +114,13 @@
"principalId": "$authenticated",
"permission": "ALLOW"
},
{
"property": "validateAuth",
"accessType": "EXECUTE",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW"
},
{
"property": "privileges",
"accessType": "*",

View File

@ -0,0 +1,3 @@
INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalId`)
VALUES
('Vehicle','sorted','WRITE','ALLOW','employee');

View File

@ -0,0 +1,11 @@
INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId)
VALUES
('VnUser', 'addAlias', 'WRITE', 'ALLOW', 'ROLE', 'employee');
INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId)
VALUES
('VnUser', 'removeAlias', 'WRITE', 'ALLOW', 'ROLE', 'employee');
INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId)
VALUES
('VnUser', 'canRemoveAlias', 'WRITE', 'ALLOW', 'ROLE', 'itManagement');

View File

@ -0,0 +1,2 @@
INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId)
VALUES('Ticket', 'invoiceTickets', 'WRITE', 'ALLOW', 'ROLE', 'employee');

View File

@ -0,0 +1,13 @@
create table `salix`.`authCode`
(
userFk int UNSIGNED not null,
code int not null,
expires bigint not null,
constraint authCode_pk
primary key (userFk),
constraint authCode_unique
unique (code),
constraint authCode_user_id_fk
foreign key (userFk) references `account`.`user` (id)
on update cascade on delete cascade
);

View File

@ -0,0 +1,89 @@
DROP PROCEDURE IF EXISTS `vn`.`clientCreate`;
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`client_create`(
vFirstname VARCHAR(50),
vSurnames VARCHAR(50),
vFi VARCHAR(9),
vAddress TEXT,
vPostcode CHAR(5),
vCity VARCHAR(25),
vProvinceFk SMALLINT(5),
vCompanyFk SMALLINT(5),
vPhone VARCHAR(11),
vEmail VARCHAR(255),
vUserFk INT
)
BEGIN
/**
* Create new client
*
* @params vFirstname firstName
* @params vSurnames surnames
* @params vFi company code from accounting transactions
* @params vAddress address
* @params vPostcode postCode
* @params vCity city
* @params vProvinceFk province
* @params vCompanyFk company in which he has become a client
* @params vPhone telephone number
* @params vEmail email address
* @params vUserFk user id
*/
DECLARE vPayMethodFk INT;
DECLARE vDueDay INT;
DECLARE vDefaultCredit DECIMAL(10, 2);
DECLARE vIsTaxDataChecked TINYINT(1);
DECLARE vHasCoreVnl BOOLEAN;
DECLARE vMandateTypeFk INT;
SELECT defaultPayMethodFk,
defaultDueDay,
defaultCredit,
defaultIsTaxDataChecked,
defaultHasCoreVnl,
defaultMandateTypeFk
INTO vPayMethodFk,
vDueDay,
vDefaultCredit,
vIsTaxDataChecked,
vHasCoreVnl,
vMandateTypeFk
FROM clientConfig;
INSERT INTO `client`
SET id = vUserFk,
name = CONCAT(vFirstname, ' ', vSurnames),
street = vAddress,
fi = TRIM(vFi),
phone = vPhone,
email = vEmail,
provinceFk = vProvinceFk,
city = vCity,
postcode = vPostcode,
socialName = CONCAT(vSurnames, ' ', vFirstname),
payMethodFk = vPayMethodFk,
dueDay = vDueDay,
credit = vDefaultCredit,
isTaxDataChecked = vIsTaxDataChecked,
hasCoreVnl = vHasCoreVnl,
isEqualizated = FALSE
ON duplicate KEY UPDATE
payMethodFk = vPayMethodFk,
dueDay = vDueDay,
credit = vDefaultCredit,
isTaxDataChecked = vIsTaxDataChecked,
hasCoreVnl = vHasCoreVnl,
isActive = TRUE;
INSERT INTO mandate (clientFk, companyFk, mandateTypeFk)
SELECT vUserFk, vCompanyFk, vMandateTypeFk
WHERE NOT EXISTS (
SELECT id
FROM mandate
WHERE clientFk = vUserFk
AND companyFk = vCompanyFk
AND mandateTypeFk = vMandateTypeFk
);
END$$
DELIMITER ;

View File

@ -0,0 +1,17 @@
ALTER TABLE `vn`.`clientConfig` ADD defaultPayMethodFk tinyint(3) unsigned NULL;
ALTER TABLE `vn`.`clientConfig` ADD defaultDueDay int unsigned NULL;
ALTER TABLE `vn`.`clientConfig` ADD defaultCredit decimal(10, 2) NULL;
ALTER TABLE `vn`.`clientConfig` ADD defaultIsTaxDataChecked tinyint(1) NULL;
ALTER TABLE `vn`.`clientConfig` ADD defaultHasCoreVnl boolean NULL;
ALTER TABLE `vn`.`clientConfig` ADD defaultMandateTypeFk smallint(5) NULL;
ALTER TABLE `vn`.`clientConfig` ADD CONSTRAINT clientNewConfigPayMethod_FK FOREIGN KEY (defaultPayMethodFk) REFERENCES vn.payMethod(id);
ALTER TABLE `vn`.`clientConfig` ADD CONSTRAINT clientNewConfigMandateType_FK FOREIGN KEY (defaultMandateTypeFk) REFERENCES vn.mandateType(id);
UPDATE `vn`.`clientConfig`
SET defaultPayMethodFk = 4,
defaultDueDay = 5,
defaultCredit = 300.0,
defaultIsTaxDataChecked = 1,
defaultHasCoreVnl = 1,
defaultMandateTypeFk = 2
WHERE id = 1;

View File

@ -0,0 +1,24 @@
alter table `vn`.`department`
add `twoFactor` ENUM ('email') null comment 'Default user two-factor auth type';
drop trigger `vn`.`department_afterUpdate`;
DELIMITER $$
$$
create definer = root@localhost trigger `vn`.`department_afterUpdate`
after update
on department
for each row
BEGIN
IF !(OLD.parentFk <=> NEW.parentFk) THEN
UPDATE vn.department_recalc SET isChanged = TRUE;
END IF;
IF !(OLD.twoFactor <=> NEW.twoFactor) THEN
UPDATE account.user u
JOIN vn.workerDepartment wd ON wd.workerFk = u.id
SET u.twoFactor = NEW.twoFactor
WHERE wd.departmentFk = NEW.id;
END IF;
END;$$
DELIMITER ;

View File

@ -0,0 +1,13 @@
UPDATE `salix`.`ACL`
SET principalId='financialBoss'
WHERE
model = 'Client'
AND property = 'editCredit';
UPDATE `salix`.`ACL`
SET property='zeroCreditEditor'
WHERE
model = 'Client'
AND property = 'isNotEditableCredit';

View File

@ -0,0 +1,10 @@
ALTER TABLE `vn`.`roadmap` COMMENT='Troncales diarios que se contratan';
ALTER TABLE `vn`.`roadmap` ADD price decimal(10,2) NULL;
ALTER TABLE `vn`.`roadmap` ADD driverName varchar(45) NULL;
ALTER TABLE `vn`.`roadmap` ADD name varchar(45) NOT NULL;
ALTER TABLE `vn`.`roadmap` CHANGE name name varchar(45) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci NOT NULL AFTER id;
ALTER TABLE `vn`.`roadmap` MODIFY COLUMN etd datetime NOT NULL;
ALTER TABLE `vn`.`expeditionTruck` COMMENT='Distintas paradas que hacen los trocales';
ALTER TABLE `vn`.`expeditionTruck` DROP FOREIGN KEY expeditionTruck_FK_2;
ALTER TABLE `vn`.`expeditionTruck` ADD CONSTRAINT expeditionTruck_FK_2 FOREIGN KEY (roadmapFk) REFERENCES vn.roadmap(id) ON DELETE CASCADE ON UPDATE CASCADE;

View File

@ -0,0 +1,6 @@
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
VALUES
('Roadmap', '*', '*', 'ALLOW', 'ROLE', 'palletizerBoss'),
('Roadmap', '*', '*', 'ALLOW', 'ROLE', 'productionBoss'),
('ExpeditionTruck', '*', '*', 'ALLOW', 'ROLE', 'palletizerBoss'),
('ExpeditionTruck', '*', '*', 'ALLOW', 'ROLE', 'productionBoss');

View File

@ -0,0 +1,5 @@
alter table `account`.`user`
add `twoFactor` ENUM ('email') null comment 'Two-factor auth type';
DELETE FROM `salix`.`ACL`
WHERE model = 'VnUser' AND property = 'changePassword';

View File

View File

@ -0,0 +1,2 @@
ALTER TABLE `vn`.`item` ADD recycledPlastic INT NULL;
ALTER TABLE `vn`.`item` ADD nonRecycledPlastic INT NULL;

View File

@ -0,0 +1,7 @@
UPDATE `vn`.`ticket` t
JOIN `vn`.`ticketObservation` o ON o.ticketFk = t.id
SET t.weight = cast(REPLACE(o.description, ',', '.') as decimal(10,2))
WHERE o.observationTypeFk = 6;
DELETE FROM `vn`.`ticketObservation` WHERE observationTypeFk = 6;
DELETE FROM `vn`.`observationType` WHERE id = 6;

File diff suppressed because one or more lines are too long

View File

@ -77,7 +77,10 @@ INSERT INTO `account`.`user`(`id`,`name`, `nickname`, `role`,`active`,`email`, `
ORDER BY id;
INSERT INTO `account`.`account`(`id`)
SELECT id FROM `account`.`user`;
SELECT `u`.`id`
FROM `account`.`user` `u`
JOIN `account`.`role` `r` ON `u`.`role` = `r`.`id`
WHERE `r`.`name` <> 'customer';
INSERT INTO `vn`.`educationLevel` (`id`, `name`)
VALUES
@ -144,17 +147,17 @@ INSERT INTO `vn`.`currency`(`id`, `code`, `name`, `ratio`)
(3, 'GBP', 'Libra', 1),
(4, 'JPY', 'Yen Japones', 1);
INSERT INTO `vn`.`country`(`id`, `country`, `isUeeMember`, `code`, `currencyFk`, `ibanLength`, `continentFk`, `hasDailyInvoice`, `CEE`, `politicalCountryFk`)
INSERT INTO `vn`.`country`(`id`, `country`, `isUeeMember`, `code`, `currencyFk`, `ibanLength`, `continentFk`, `hasDailyInvoice`, `CEE`)
VALUES
(1, 'España', 1, 'ES', 1, 24, 4, 0, 1, 1),
(2, 'Italia', 1, 'IT', 1, 27, 4, 0, 1, 2),
(3, 'Alemania', 1, 'DE', 1, 22, 4, 0, 1, 3),
(4, 'Rumania', 1, 'RO', 1, 24, 4, 0, 1, 4),
(5, 'Holanda', 1, 'NL', 1, 18, 4, 0, 1, 5),
(8, 'Portugal', 1, 'PT', 1, 27, 4, 0, 1, 8),
(13,'Ecuador', 0, 'EC', 1, 24, 2, 1, 2, 13),
(19,'Francia', 1, 'FR', 1, 27, 4, 0, 1, 19),
(30,'Canarias', 1, 'IC', 1, 24, 4, 1, 2, 30);
(1, 'España', 1, 'ES', 1, 24, 4, 0, 1),
(2, 'Italia', 1, 'IT', 1, 27, 4, 0, 1),
(3, 'Alemania', 1, 'DE', 1, 22, 4, 0, 1),
(4, 'Rumania', 1, 'RO', 1, 24, 4, 0, 1),
(5, 'Holanda', 1, 'NL', 1, 18, 4, 0, 1),
(8, 'Portugal', 1, 'PT', 1, 27, 4, 0, 1),
(13,'Ecuador', 0, 'EC', 1, 24, 2, 1, 2),
(19,'Francia', 1, 'FR', 1, 27, 4, 0, 1),
(30,'Canarias', 1, 'IC', 1, 24, 4, 1, 2);
INSERT INTO `vn`.`warehouseAlias`(`id`, `name`)
VALUES
@ -185,13 +188,13 @@ INSERT INTO `vn`.`printer` (`id`, `name`, `path`, `isLabeler`, `sectorFk`, `ipAd
UPDATE `vn`.`sector` SET mainPrinterFk = 1 WHERE id = 1;
INSERT INTO `vn`.`worker`(`id`, `code`, `firstName`, `lastName`, `userFk`,`bossFk`, `phone`, `sectorFk`, `labelerFk`)
INSERT INTO `vn`.`worker`(`id`, `code`, `firstName`, `lastName`, `userFk`,`bossFk`, `phone`)
VALUES
(1106, 'LGN', 'David Charles', 'Haller', 1106, 19, 432978106, NULL, NULL),
(1107, 'ANT', 'Hank' , 'Pym' , 1107, 19, 432978107, NULL, NULL),
(1108, 'DCX', 'Charles' , 'Xavier', 1108, 19, 432978108, 1, NULL),
(1109, 'HLK', 'Bruce' , 'Banner', 1109, 19, 432978109, 1, NULL),
(1110, 'JJJ', 'Jessica' , 'Jones' , 1110, 19, 432978110, 2, NULL);
(1106, 'LGN', 'David Charles', 'Haller', 1106, 19, 432978106),
(1107, 'ANT', 'Hank' , 'Pym' , 1107, 19, 432978107),
(1108, 'DCX', 'Charles' , 'Xavier', 1108, 19, 432978108),
(1109, 'HLK', 'Bruce' , 'Banner', 1109, 19, 432978109),
(1110, 'JJJ', 'Jessica' , 'Jones' , 1110, 19, 432978110);
INSERT INTO `vn`.`parking` (`id`, `column`, `row`, `sectorFk`, `code`, `pickingOrder`)
VALUES
@ -382,9 +385,16 @@ INSERT INTO `vn`.`clientManaCache`(`clientFk`, `mana`, `dated`)
(1103, 0, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH)),
(1104, -30, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH));
INSERT INTO `vn`.`clientConfig`(`riskTolerance`, `maxCreditRows`)
INSERT INTO `vn`.`mandateType`(`id`, `name`)
VALUES
(200, 10);
(1, 'B2B'),
(2, 'CORE'),
(3, 'LCR');
INSERT INTO `vn`.`clientConfig`(`id`, `riskTolerance`, `maxCreditRows`, `maxPriceIncreasingRatio`, `riskScope`, `defaultPayMethodFk`, `defaultDueDay`, `defaultCredit`, `defaultIsTaxDataChecked`, `defaultHasCoreVnl`, `defaultMandateTypeFk`)
VALUES
(1, 200, 10, 0.25, 2, 4, 5, 300.00, 1, 1, 2);
INSERT INTO `vn`.`address`(`id`, `nickname`, `street`, `city`, `postalCode`, `provinceFk`, `phone`, `mobile`, `isActive`, `clientFk`, `agencyModeFk`, `longitude`, `latitude`, `isEqualizated`, `isDefaultAddress`)
VALUES
@ -550,10 +560,13 @@ INSERT INTO `vn`.`supplierAddress`(`id`, `supplierFk`, `nickname`, `street`, `pr
INSERT INTO `vn`.`supplier`(`id`, `name`, `nickname`,`account`,`countryFk`,`nif`, `commission`, `created`, `isActive`, `street`, `city`, `provinceFk`, `postCode`, `payMethodFk`, `payDemFk`, `payDay`, `taxTypeSageFk`, `withholdingSageFk`, `transactionTypeSageFk`, `workerFk`, `supplierActivityFk`, `isPayMethodChecked`, `healthRegister`)
VALUES
(1, 'Plants SL', 'Plants nick', 4100000001, 1, '06089160W', 0, util.VN_CURDATE(), 1, 'supplier address 1', 'PONTEVEDRA', 1, 15214, 1, 1, 15, 4, 1, 1, 18, 'flowerPlants', 1, '400664487V'),
(2, 'Farmer King', 'The farmer', 4000020002, 1, '87945234L', 0, util.VN_CURDATE(), 1, 'supplier address 2', 'GOTHAM', 2, 43022, 1, 2, 10, 93, 2, 8, 18, 'animals', 1, '400664487V'),
(442, 'Verdnatura Levante SL', 'Verdnatura', 5115000442, 1, '06815934E', 0, util.VN_CURDATE(), 1, 'supplier address 3', 'GOTHAM', 1, 43022, 1, 2, 15, 6, 9, 3, 18, 'complements', 1, '400664487V'),
(1381, 'Ornamentales', 'Ornamentales', 7185000440, 1, '03815934E', 0, util.VN_CURDATE(), 1, 'supplier address 4', 'GOTHAM', 1, 43022, 1, 2, 15, 6, 9, 3, 18, 'complements', 1, '400664487V');
(1, 'Plants SL', 'Plants nick', 4100000001, 1, '06089160W', 0, util.VN_CURDATE(), 1, 'supplier address 1', 'PONTEVEDRA', 1, 15214, 1, 1, 15, 4, 1, 1, 18, 'flowerPlants', 1, '400664487V'),
(2, 'Farmer King', 'The farmer', 4000020002, 1, '87945234L', 0, util.VN_CURDATE(), 1, 'supplier address 2', 'GOTHAM', 2, 43022, 1, 2, 10, 93, 2, 8, 18, 'animals', 1, '400664487V'),
(69, 'Packaging', 'Packaging nick', 4100000069, 1, '94935005K', 0, util.VN_CURDATE(), 1, 'supplier address 5', 'ASGARD', 3, 46600, 1, 1, 15, 4, 1, 1, 18, 'flowerPlants', 1, '400664487V'),
(442, 'Verdnatura Levante SL', 'Verdnatura', 5115000442, 1, '06815934E', 0, util.VN_CURDATE(), 1, 'supplier address 3', 'GOTHAM', 1, 43022, 1, 2, 15, 6, 9, 3, 18, 'complements', 1, '400664487V'),
(567, 'Holland', 'Holland nick', 4000020567, 1, '14364089Z', 0, util.VN_CURDATE(), 1, 'supplier address 6', 'ASGARD', 3, 46600, 1, 2, 10, 93, 2, 8, 18, 'animals', 1, '400664487V'),
(791, 'Bros SL', 'Bros nick', 5115000791, 1, '37718083S', 0, util.VN_CURDATE(), 1, 'supplier address 7', 'ASGARD', 3, 46600, 1, 2, 15, 6, 9, 3, 18, 'complements', 1, '400664487V'),
(1381, 'Ornamentales', 'Ornamentales', 7185001381, 1, '07972486L', 0, util.VN_CURDATE(), 1, 'supplier address 4', 'GOTHAM', 1, 43022, 1, 2, 15, 6, 9, 3, 18, 'complements', 1, '400664487V');
INSERT INTO `vn`.`supplierContact`(`id`, `supplierFk`, `phone`, `mobile`, `email`, `observation`, `name`)
VALUES
@ -697,40 +710,40 @@ INSERT INTO `vn`.`route`(`id`, `time`, `workerFk`, `created`, `vehicleFk`, `agen
(6, NULL, 57, util.VN_CURDATE(), 5, 7, 'sixth route', 1.7, 60, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 3),
(7, NULL, 57, util.VN_CURDATE(), 6, 8, 'seventh route', 0, 70, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 5);
INSERT INTO `vn`.`ticket`(`id`, `priority`, `agencyModeFk`,`warehouseFk`,`routeFk`, `shipped`, `landed`, `clientFk`,`nickname`, `addressFk`, `refFk`, `isDeleted`, `zoneFk`, `zonePrice`, `zoneBonus`, `created`)
INSERT INTO `vn`.`ticket`(`id`, `priority`, `agencyModeFk`,`warehouseFk`,`routeFk`, `shipped`, `landed`, `clientFk`,`nickname`, `addressFk`, `refFk`, `isDeleted`, `zoneFk`, `zonePrice`, `zoneBonus`, `created`, `weight`)
VALUES
(1 , 3, 1, 1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 1101, 'Bat cave', 121, NULL, 0, 1, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH)),
(2 , 1, 1, 1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 1104, 'Stark tower', 124, NULL, 0, 1, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH)),
(3 , 1, 7, 1, 6, DATE_ADD(util.VN_CURDATE(), INTERVAL -2 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -2 MONTH), INTERVAL +1 DAY), 1104, 'Stark tower', 124, NULL, 0, 3, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -2 MONTH)),
(4 , 3, 2, 1, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -3 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -3 MONTH), INTERVAL +1 DAY), 1104, 'Stark tower', 124, NULL, 0, 9, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -3 MONTH)),
(5 , 3, 3, 3, 3, DATE_ADD(util.VN_CURDATE(), INTERVAL -4 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -4 MONTH), INTERVAL +1 DAY), 1104, 'Stark tower', 124, NULL, 0, 10, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -4 MONTH)),
(6 , 1, 3, 3, 3, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 1101, 'Mountain Drive Gotham', 1, NULL, 0, 10, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH)),
(7 , NULL, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1101, 'Mountain Drive Gotham', 1, NULL, 0, 3, 5, 1, util.VN_CURDATE()),
(8 , NULL, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1101, 'Bat cave', 121, NULL, 0, 3, 5, 1, util.VN_CURDATE()),
(9 , NULL, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1104, 'Stark tower', 124, NULL, 0, 3, 5, 1, util.VN_CURDATE()),
(10, 1, 1, 5, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1102, 'Ingram Street', 2, NULL, 0, 1, 5, 1, util.VN_CURDATE()),
(11, 1, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1102, 'NY roofs', 122, NULL, 0, 3, 5, 1, util.VN_CURDATE()),
(12, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE()),
(13, 1, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 3, 5, 1, util.VN_CURDATE()),
(14, 1, 2, 1, NULL, util.VN_CURDATE(), util.VN_CURDATE(), 1104, 'Malibu Point', 4, NULL, 0, 9, 5, 1, util.VN_CURDATE()),
(15, 1, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1105, 'An incredibly long alias for testing purposes', 125, NULL, 0, 3, 5, 1, util.VN_CURDATE()),
(16, 1, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1106, 'Many Places', 126, NULL, 0, 3, 5, 1, util.VN_CURDATE()),
(17, 1, 7, 2, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1106, 'Many Places', 126, NULL, 0, 3, 5, 1, util.VN_CURDATE()),
(18, 1, 4, 4, 4, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1108, 'Cerebro', 128, NULL, 0, 12, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL +12 HOUR)),
(19, 1, 5, 5, NULL, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1109, 'Somewhere in Thailand', 129, NULL, 1, NULL, 5, 1, util.VN_CURDATE()),
(20, 1, 5, 5, 3, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 1109, 'Somewhere in Thailand', 129, NULL, 0, 13, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH)),
(21, NULL, 5, 5, 5, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 1109, 'Somewhere in Holland', 102, NULL, 0, 13, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH)),
(22, NULL, 5, 5, 5, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 1109, 'Somewhere in Japan', 103, NULL, 0, 13, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH)),
(23, NULL, 8, 1, 7, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1101, 'address 21', 121, NULL, 0, 5, 5, 1, util.VN_CURDATE()),
(24 ,NULL, 8, 1, 7, util.VN_CURDATE(), util.VN_CURDATE(), 1101, 'Bruce Wayne', 1, NULL, 0, 5, 5, 1, util.VN_CURDATE()),
(25 ,NULL, 8, 1, NULL, util.VN_CURDATE(), util.VN_CURDATE(), 1101, 'Bruce Wayne', 1, NULL, 0, 1, 5, 1, util.VN_CURDATE()),
(26 ,NULL, 8, 1, NULL, util.VN_CURDATE(), util.VN_CURDATE(), 1101, 'An incredibly long alias for testing purposes', 1, NULL, 0, 1, 5, 1, util.VN_CURDATE()),
(27 ,NULL, 8, 1, NULL, util.VN_CURDATE(), util.VN_CURDATE(), 1101, 'Wolverine', 1, NULL, 0, 1, 5, 1, util.VN_CURDATE()),
(28, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE()),
(29, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE()),
(30, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE()),
(31, 1, 8, 1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL + 2 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE()),
(32, 1, 8, 1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL + 2 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE());
(1 , 3, 1, 1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 1101, 'Bat cave', 121, NULL, 0, 1, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1),
(2 , 1, 1, 1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 1104, 'Stark tower', 124, NULL, 0, 1, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 2),
(3 , 1, 7, 1, 6, DATE_ADD(util.VN_CURDATE(), INTERVAL -2 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -2 MONTH), INTERVAL +1 DAY), 1104, 'Stark tower', 124, NULL, 0, 3, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -2 MONTH), NULL),
(4 , 3, 2, 1, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -3 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -3 MONTH), INTERVAL +1 DAY), 1104, 'Stark tower', 124, NULL, 0, 9, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -3 MONTH), NULL),
(5 , 3, 3, 3, 3, DATE_ADD(util.VN_CURDATE(), INTERVAL -4 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -4 MONTH), INTERVAL +1 DAY), 1104, 'Stark tower', 124, NULL, 0, 10, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -4 MONTH), NULL),
(6 , 1, 3, 3, 3, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 1101, 'Mountain Drive Gotham', 1, NULL, 0, 10, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), NULL),
(7 , NULL, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1101, 'Mountain Drive Gotham', 1, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL),
(8 , NULL, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1101, 'Bat cave', 121, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL),
(9 , NULL, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1104, 'Stark tower', 124, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL),
(10, 1, 1, 5, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1102, 'Ingram Street', 2, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL),
(11, 1, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1102, 'NY roofs', 122, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL),
(12, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL),
(13, 1, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL),
(14, 1, 2, 1, NULL, util.VN_CURDATE(), util.VN_CURDATE(), 1104, 'Malibu Point', 4, NULL, 0, 9, 5, 1, util.VN_CURDATE(), NULL),
(15, 1, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1105, 'An incredibly long alias for testing purposes', 125, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL),
(16, 1, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1106, 'Many Places', 126, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL),
(17, 1, 7, 2, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1106, 'Many Places', 126, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL),
(18, 1, 4, 4, 4, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1108, 'Cerebro', 128, NULL, 0, 12, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL +12 HOUR), NULL),
(19, 1, 5, 5, NULL, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1109, 'Somewhere in Thailand', 129, NULL, 1, NULL, 5, 1, util.VN_CURDATE(), NULL),
(20, 1, 5, 5, 3, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 1109, 'Somewhere in Thailand', 129, NULL, 0, 13, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), NULL),
(21, NULL, 5, 5, 5, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 1109, 'Somewhere in Holland', 102, NULL, 0, 13, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), NULL),
(22, NULL, 5, 5, 5, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(util.VN_CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 1109, 'Somewhere in Japan', 103, NULL, 0, 13, 5, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), NULL),
(23, NULL, 8, 1, 7, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1101, 'address 21', 121, NULL, 0, 5, 5, 1, util.VN_CURDATE(), NULL),
(24 ,NULL, 8, 1, 7, util.VN_CURDATE(), util.VN_CURDATE(), 1101, 'Bruce Wayne', 1, NULL, 0, 5, 5, 1, util.VN_CURDATE(), NULL),
(25 ,NULL, 8, 1, NULL, util.VN_CURDATE(), util.VN_CURDATE(), 1101, 'Bruce Wayne', 1, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL),
(26 ,NULL, 8, 1, NULL, util.VN_CURDATE(), util.VN_CURDATE(), 1101, 'An incredibly long alias for testing purposes', 1, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL),
(27 ,NULL, 8, 1, NULL, util.VN_CURDATE(), util.VN_CURDATE(), 1101, 'Wolverine', 1, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL),
(28, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL),
(29, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL),
(30, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL),
(31, 1, 8, 1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL + 2 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL),
(32, 1, 8, 1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL + 2 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL);
INSERT INTO `vn`.`ticketObservation`(`id`, `ticketFk`, `observationTypeFk`, `description`)
VALUES
@ -821,12 +834,6 @@ INSERT INTO `vn`.`greuge`(`id`, `clientFk`, `description`, `amount`, `shipped`,
(11, 1101, 'some heritage charges', -15.99, DATE_ADD(util.VN_CURDATE(), INTERVAL 1 MONTH), util.VN_CURDATE(), 5, 1),
(12, 1101, 'some miscellaneous charges', 58.00, DATE_ADD(util.VN_CURDATE(), INTERVAL 1 MONTH), util.VN_CURDATE(), 6, 1);
INSERT INTO `vn`.`mandateType`(`id`, `name`)
VALUES
(1, 'B2B'),
(2, 'CORE'),
(3, 'LCR');
INSERT INTO `vn`.`mandate`(`id`, `clientFk`, `companyFk`, `code`, `created`, `mandateTypeFk`)
VALUES
(1, 1102, 442, '1-1', util.VN_CURDATE(), 2);
@ -2590,7 +2597,7 @@ UPDATE `vn`.`ticket`
UPDATE `vn`.`ticket`
SET refFk = 'A1111111'
WHERE id = 6;
WHERE id = 6;
INSERT INTO `vn`.`zoneAgencyMode`(`id`, `agencyModeFk`, `zoneFk`)
VALUES
@ -2599,9 +2606,18 @@ INSERT INTO `vn`.`zoneAgencyMode`(`id`, `agencyModeFk`, `zoneFk`)
(3, 6, 5),
(4, 7, 1);
INSERT INTO `vn`.`expeditionTruck` (`id`, `ETD`, `description`)
INSERT INTO `vn`.`roadmap` (`id`, `name`, `tractorPlate`, `trailerPlate`, `phone`, `supplierFk`, `etd`, `observations`, `userFk`, `price`, `driverName`)
VALUES
(1, CONCAT(YEAR(DATE_ADD(util.VN_CURDATE(), INTERVAL +3 YEAR))), 'Best truck in fleet');
(1, 'val-algemesi', 'RE-001', 'PO-001', '111111111', 1, util.VN_NOW(), 'this is test observation', 1, 15, 'Batman'),
(2, 'alg-valencia', 'RE-002', 'PO-002', '111111111', 1, util.VN_NOW(), 'test observation', 1, 20, 'Robin'),
(3, 'alz-algemesi', 'RE-003', 'PO-003', '222222222', 2, DATE_ADD(util.VN_NOW(), INTERVAL 2 DAY), 'observations...', 2, 25, 'Driverman');
INSERT INTO `vn`.`expeditionTruck` (`id`, `roadmapFk`, `warehouseFk`, `eta`, `description`, `userFk`)
VALUES
(1, 1, 1, DATE_ADD(util.VN_NOW(), INTERVAL 1 DAY), 'Best truck in fleet', 1),
(2, 1, 2, DATE_ADD(util.VN_NOW(), INTERVAL '1 2' DAY_HOUR), 'Second truck in fleet', 1),
(3, 1, 3, DATE_ADD(util.VN_NOW(), INTERVAL '1 4' DAY_HOUR), 'Third truck in fleet', 1),
(4, 2, 1, DATE_ADD(util.VN_NOW(), INTERVAL 3 DAY), 'Truck red', 1);
INSERT INTO `vn`.`expeditionPallet` (`id`, `truckFk`, `built`, `position`, `isPrint`)
VALUES
@ -2845,8 +2861,8 @@ INSERT INTO `vn`.`profileType` (`id`, `name`)
INSERT INTO `salix`.`url` (`appName`, `environment`, `url`)
VALUES
('lilium', 'dev', 'http://localhost:9000/#/'),
('salix', 'dev', 'http://localhost:5000/#!/');
('lilium', 'development', 'http://localhost:9000/#/'),
('salix', 'development', 'http://localhost:5000/#!/');
INSERT INTO `vn`.`report` (`id`, `name`, `paperSizeFk`, `method`)
VALUES

File diff suppressed because it is too large Load Diff

View File

@ -312,8 +312,8 @@ export default {
clientDefaulter: {
anyClient: 'vn-client-defaulter tbody > tr',
firstClientName: 'vn-client-defaulter tbody > tr:nth-child(2) > td:nth-child(2) > span',
firstSalesPersonName: 'vn-client-defaulter tbody > tr:nth-child(2) > td:nth-child(3) > span',
firstObservation: 'vn-client-defaulter tbody > tr:nth-child(2) > td:nth-child(8) > vn-textarea[ng-model="defaulter.observation"]',
firstSalesPersonName: 'vn-client-defaulter tbody > tr:nth-child(2) > td:nth-child(4) > span',
firstObservation: 'vn-client-defaulter tbody > tr:nth-child(2) > td:nth-child(9) > vn-textarea[ng-model="defaulter.observation"]',
allDefaulterCheckbox: 'vn-client-defaulter thead vn-multi-check',
addObservationButton: 'vn-client-defaulter vn-button[icon="icon-notes"]',
observation: '.vn-dialog.shown vn-textarea[ng-model="$ctrl.defaulter.observation"]',
@ -547,6 +547,7 @@ export default {
moreMenuMakeInvoice: '.vn-menu [name="makeInvoice"]',
moreMenuRegenerateInvoice: '.vn-menu [name="regenerateInvoice"]',
moreMenuChangeShippedHour: '.vn-menu [name="changeShipped"]',
moreMenuSMSOptions: '.vn-menu [name="smsOptions"]',
moreMenuPaymentSMS: '.vn-menu [name="sendPaymentSms"]',
moreMenuSendImportSms: '.vn-menu [name="sendImportSms"]',
SMStext: 'textarea[name="message"]',
@ -894,6 +895,18 @@ export default {
extension: 'vn-worker-summary vn-one:nth-child(2) > vn-label-value:nth-child(5) > section > span',
},
department: {
firstDepartment: 'vn-worker-department-index vn-card > vn-treeview vn-treeview-childs vn-treeview-childs vn-treeview-childs a'
},
departmentSummary: {
header: 'vn-worker-department-summary h5',
name: 'vn-worker-department-summary vn-horizontal > vn-one > vn-vertical > vn-label-value:nth-child(1) > section > span',
code: 'vn-worker-department-summary vn-horizontal > vn-one > vn-vertical > vn-label-value:nth-child(2) > section > span',
chat: 'vn-worker-department-summary vn-horizontal > vn-one > vn-vertical > vn-label-value:nth-child(3) > section > span',
bossDepartment: 'vn-worker-department-summary vn-horizontal > vn-one > vn-vertical > vn-label-value:nth-child(4) > section > span',
email: 'vn-worker-department-summary vn-horizontal > vn-one > vn-vertical > vn-label-value:nth-child(5) > section > span',
clientFk: 'vn-worker-department-summary vn-horizontal > vn-one > vn-vertical > vn-label-value:nth-child(6) > section > span',
},
workerBasicData: {
name: 'vn-worker-basic-data vn-textfield[ng-model="$ctrl.worker.firstName"]',
surname: 'vn-worker-basic-data vn-textfield[ng-model="$ctrl.worker.lastName"]',
@ -901,6 +914,13 @@ export default {
locker: 'vn-worker-basic-data vn-input-number[ng-model="$ctrl.worker.locker"]',
saveButton: 'vn-worker-basic-data button[type=submit]'
},
departmentBasicData: {
Name: 'vn-worker-department-basic-data vn-textfield[ng-model="$ctrl.department.name"]',
Code: 'vn-worker-department-basic-data vn-textfield[ng-model="$ctrl.department.code"]',
Chat: 'vn-worker-department-basic-data vn-textfield[ng-model="$ctrl.department.chat"]',
Email: 'vn-worker-department-basic-data vn-textfield[ng-model="$ctrl.department.notificationEmail"]',
saveButton: 'vn-worker-department-basic-data button[type=submit]'
},
workerNotes: {
addNoteFloatButton: 'vn-worker-note vn-icon[icon="add"]',
note: 'vn-note-worker-create vn-textarea[ng-model="$ctrl.note.text"]',

View File

@ -16,6 +16,7 @@ describe('ChangePassword path', async() => {
await browser.close();
});
const badPassword = 'badpass';
const oldPassword = 'nightmare';
const newPassword = 'newPass.1234';
describe('Bad login', async() => {
@ -37,13 +38,22 @@ describe('ChangePassword path', async() => {
expect(message.text).toContain('Invalid current password');
// Bad attempt: password not meet requirements
message = await page.sendForm($.form, {
oldPassword: oldPassword,
newPassword: badPassword,
repeatPassword: badPassword
});
expect(message.text).toContain('Password does not meet requirements');
// Bad attempt: same password
message = await page.sendForm($.form, {
oldPassword: oldPassword,
newPassword: oldPassword,
repeatPassword: oldPassword
});
expect(message.text).toContain('Password does not meet requirements');
expect(message.text).toContain('You can not use the same password');
// Correct attempt: change password
message = await page.sendForm($.form, {

View File

@ -0,0 +1,29 @@
import selectors from '../../../helpers/selectors.js';
import getBrowser from '../../../helpers/puppeteer';
describe('department summary path', () => {
let browser;
let page;
beforeAll(async() => {
browser = await getBrowser();
page = browser.page;
await page.loginAndModule('hr', 'worker');
await page.accessToSection('worker.department');
await page.doSearch('INFORMATICA');
await page.click(selectors.department.firstDepartment);
});
afterAll(async() => {
await browser.close();
});
it('should reach the employee summary section and check all properties', async() => {
expect(await page.waitToGetProperty(selectors.departmentSummary.header, 'innerText')).toEqual('INFORMATICA');
expect(await page.getProperty(selectors.departmentSummary.name, 'innerText')).toEqual('INFORMATICA');
expect(await page.getProperty(selectors.departmentSummary.code, 'innerText')).toEqual('it');
expect(await page.getProperty(selectors.departmentSummary.chat, 'innerText')).toEqual('informatica-cau');
expect(await page.getProperty(selectors.departmentSummary.bossDepartment, 'innerText')).toEqual('');
expect(await page.getProperty(selectors.departmentSummary.email, 'innerText')).toEqual('-');
expect(await page.getProperty(selectors.departmentSummary.clientFk, 'innerText')).toEqual('-');
});
});

View File

@ -0,0 +1,43 @@
import getBrowser from '../../../helpers/puppeteer';
import selectors from '../../../helpers/selectors.js';
const $ = {
form: 'vn-worker-department-basic-data form',
};
describe('department summary path', () => {
let browser;
let page;
beforeAll(async() => {
browser = await getBrowser();
page = browser.page;
await page.loginAndModule('hr', 'worker');
await page.accessToSection('worker.department');
await page.doSearch('INFORMATICA');
await page.click(selectors.department.firstDepartment);
});
beforeEach(async() => {
await page.accessToSection('worker.department.card.basicData');
});
afterAll(async() => {
await browser.close();
});
it(`should edit the department basic data and confirm the department data was edited`, async() => {
const values = {
Name: 'Informatica',
Code: 'IT',
Chat: 'informatica-cau',
Email: 'it@verdnatura.es',
};
await page.fillForm($.form, values);
const formValues = await page.fetchForm($.form, Object.keys(values));
const message = await page.sendForm($.form, values);
expect(message.isSuccess).toBeTrue();
expect(formValues).toEqual(values);
});
});

View File

@ -19,7 +19,6 @@ describe('Item edit tax path', () => {
it(`should add the item tax to all countries`, async() => {
await page.autocompleteSearch(selectors.itemTax.firstClass, 'General VAT');
await page.autocompleteSearch(selectors.itemTax.secondClass, 'General VAT');
await page.autocompleteSearch(selectors.itemTax.thirdClass, 'General VAT');
await page.waitToClick(selectors.itemTax.submitTaxButton);
const message = await page.waitForSnackbar();
@ -40,13 +39,6 @@ describe('Item edit tax path', () => {
expect(secondVatType).toEqual('General VAT');
});
it(`should confirm the third item tax class was edited`, async() => {
const thirdVatType = await page
.waitToGetProperty(selectors.itemTax.thirdClass, 'value');
expect(thirdVatType).toEqual('General VAT');
});
it(`should edit the first class without saving the form`, async() => {
await page.autocompleteSearch(selectors.itemTax.firstClass, 'Reduced VAT');
const firstVatType = await page.waitToGetProperty(selectors.itemTax.firstClass, 'value');

View File

@ -124,6 +124,7 @@ describe('Ticket descriptor path', () => {
describe('SMS', () => {
it('should send the payment SMS using the descriptor menu', async() => {
await page.waitToClick(selectors.ticketDescriptor.moreMenu);
await page.waitToClick(selectors.ticketDescriptor.moreMenuSMSOptions);
await page.waitToClick(selectors.ticketDescriptor.moreMenuPaymentSMS);
await page.waitForSelector(selectors.ticketDescriptor.SMStext);
await page.waitPropertyLength(selectors.ticketDescriptor.SMStext, 'value', 128);
@ -134,8 +135,7 @@ describe('Ticket descriptor path', () => {
});
it('should send the import SMS using the descriptor menu', async() => {
await page.waitToClick(selectors.ticketDescriptor.moreMenu);
await page.waitForContentLoaded();
await page.waitToClick(selectors.ticketDescriptor.moreMenuSMSOptions);
await page.waitToClick(selectors.ticketDescriptor.moreMenuSendImportSms);
await page.waitForSelector(selectors.ticketDescriptor.SMStext);
await page.waitPropertyLength(selectors.ticketDescriptor.SMStext, 'value', 144);

View File

@ -81,6 +81,6 @@ describe('Account Role create and basic data path', () => {
await page.accessToSection('account.role.card.inherited');
const rolesCount = await page.countElement(selectors.accountRoleInheritance.anyResult);
expect(rolesCount).toEqual(6);
expect(rolesCount).toEqual(7);
});
});

View File

@ -24,7 +24,7 @@ export default class Auth {
initialize() {
let criteria = {
to: state => {
const outLayout = ['login', 'recover-password', 'reset-password', 'change-password'];
const outLayout = ['login', 'recover-password', 'reset-password', 'change-password', 'validate-email'];
return !outLayout.some(ol => ol == state.name);
}
};
@ -60,7 +60,25 @@ export default class Auth {
};
const now = new Date();
return this.$http.post('VnUsers/signIn', params)
return this.$http.post('VnUsers/sign-in', params).then(
json => this.onLoginOk(json, now, remember));
}
validateCode(user, password, code, remember) {
if (!user) {
let err = new UserError('Please enter your username');
err.code = 'EmptyLogin';
return this.$q.reject(err);
}
let params = {
user: user,
password: password || undefined,
code: code
};
const now = new Date();
return this.$http.post('VnUsers/validate-auth', params)
.then(json => this.onLoginOk(json, now, remember));
}

View File

@ -34,7 +34,6 @@ export default class Token {
remember
});
this.vnInterceptor.setToken(token);
try {
if (remember)
this.setStorage(localStorage, token, created, ttl);
@ -84,7 +83,6 @@ export default class Token {
this.renewPeriod = data.renewPeriod;
this.stopRenewer();
this.inservalId = setInterval(() => this.checkValidity(), data.renewInterval * 1000);
this.checkValidity();
});
}

View File

@ -1,402 +1,411 @@
@font-face {
font-family: 'salixfont';
src:
url('./salixfont.ttf?wtrl3') format('truetype'),
url('./salixfont.woff?wtrl3') format('woff'),
url('./salixfont.svg?wtrl3#salixfont') format('svg');
font-weight: normal;
font-style: normal;
}
font-family: 'salixfont';
src:
url('./salixfont.ttf?wtrl3') format('truetype'),
url('./salixfont.woff?wtrl3') format('woff'),
url('./salixfont.svg?wtrl3#salixfont') format('svg');
font-weight: normal;
font-style: normal;
}
[class^="icon-"], [class*=" icon-"] {
/* use !important to prevent issues with browser extensions that change fonts */
font-family: 'salixfont' !important;
speak: none;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
[class^="icon-"], [class*=" icon-"] {
/* use !important to prevent issues with browser extensions that change fonts */
font-family: 'salixfont' !important;
speak: none;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
/* Better Font Rendering =========== */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* Better Font Rendering =========== */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-agency-term:before {
content: "\e950";
}
.icon-defaulter:before {
content: "\e94b";
}
.icon-100:before {
content: "\e95a";
}
.icon-clientUnpaid:before {
content: "\e95b";
}
.icon-history:before {
content: "\e968";
}
.icon-Person:before {
content: "\e901";
}
.icon-accessory:before {
content: "\e90a";
}
.icon-account:before {
content: "\e92a";
}
.icon-actions:before {
content: "\e960";
}
.icon-addperson:before {
content: "\e90e";
}
.icon-agency:before {
content: "\e938";
}
.icon-albaran:before {
content: "\e94d";
}
.icon-anonymous:before {
content: "\e930";
}
.icon-apps:before {
content: "\e951";
}
.icon-artificial:before {
content: "\e90b";
}
.icon-attach:before {
content: "\e92e";
}
.icon-barcode:before {
content: "\e971";
}
.icon-basket:before {
content: "\e914";
}
.icon-basketadd:before {
content: "\e913";
}
.icon-bin:before {
content: "\e96f";
}
.icon-botanical:before {
content: "\e972";
}
.icon-bucket:before {
content: "\e97a";
}
.icon-buscaman:before {
content: "\e93b";
}
.icon-buyrequest:before {
content: "\e932";
}
.icon-calc_volum .path1:before {
content: "\e915";
}
.icon-calc_volum .path2:before {
content: "\e916";
margin-left: -1em;
}
.icon-calc_volum .path3:before {
content: "\e917";
margin-left: -1em;
}
.icon-calc_volum .path4:before {
content: "\e918";
margin-left: -1em;
}
.icon-calc_volum .path5:before {
content: "\e919";
margin-left: -1em;
}
.icon-calc_volum .path6:before {
content: "\e91a";
margin-left: -1em;
}
.icon-calendar:before {
content: "\e93d";
}
.icon-catalog:before {
content: "\e937";
}
.icon-claims:before {
content: "\e963";
}
.icon-client:before {
content: "\e928";
}
.icon-clone:before {
content: "\e973";
}
.icon-columnadd:before {
content: "\e954";
}
.icon-columndelete:before {
content: "\e953";
}
.icon-components:before {
content: "\e946";
}
.icon-consignatarios:before {
content: "\e93f";
}
.icon-control:before {
content: "\e949";
}
.icon-credit:before {
content: "\e927";
}
.icon-deletedTicket:before {
content: "\e935";
}
.icon-deleteline:before {
content: "\e955";
}
.icon-delivery:before {
content: "\e939";
}
.icon-deliveryprices:before {
content: "\e91c";
}
.icon-details:before {
content: "\e961";
}
.icon-dfiscales:before {
content: "\e984";
}
.icon-disabled:before {
content: "\e921";
}
.icon-doc:before {
content: "\e977";
}
.icon-entry:before {
content: "\e934";
}
.icon-exit:before {
content: "\e92f";
}
.icon-eye:before {
content: "\e976";
}
.icon-fixedPrice:before {
content: "\e90d";
}
.icon-flower:before {
content: "\e90c";
}
.icon-frozen:before {
content: "\e900";
}
.icon-fruit:before {
content: "\e903";
}
.icon-funeral:before {
content: "\e904";
}
.icon-greenery:before {
content: "\e907";
}
.icon-greuge:before {
content: "\e944";
}
.icon-grid:before {
content: "\e980";
}
.icon-handmade:before {
content: "\e909";
}
.icon-handmadeArtificial:before {
content: "\e902";
}
.icon-headercol:before {
content: "\e958";
}
.icon-info:before {
content: "\e952";
}
.icon-inventory:before {
content: "\e92b";
}
.icon-invoice:before {
content: "\e923";
}
.icon-invoice-in:before {
content: "\e911";
}
.icon-invoice-in-create:before {
content: "\e912";
}
.icon-invoice-out:before {
content: "\e910";
}
.icon-isTooLittle:before {
content: "\e91b";
}
.icon-item:before {
content: "\e956";
}
.icon-languaje:before {
content: "\e926";
}
.icon-lines:before {
content: "\e942";
}
.icon-linesprepaired:before {
content: "\e948";
}
.icon-logout:before {
content: "\e936";
}
.icon-mana:before {
content: "\e96a";
}
.icon-mandatory:before {
content: "\e97b";
}
.icon-net:before {
content: "\e931";
}
.icon-niche:before {
content: "\e96c";
}
.icon-no036:before {
content: "\e920";
}
.icon-noPayMethod:before {
content: "\e905";
}
.icon-notes:before {
content: "\e941";
}
.icon-noweb:before {
content: "\e91f";
}
.icon-onlinepayment:before {
content: "\e91d";
}
.icon-package:before {
content: "\e978";
}
.icon-payment:before {
content: "\e97e";
}
.icon-pbx:before {
content: "\e93c";
}
.icon-pets:before {
content: "\e947";
}
.icon-photo:before {
content: "\e924";
}
.icon-plant:before {
content: "\e908";
}
.icon-polizon:before {
content: "\e95e";
}
.icon-preserved:before {
content: "\e906";
}
.icon-recovery:before {
content: "\e97c";
}
.icon-regentry:before {
content: "\e964";
}
.icon-reserva:before {
content: "\e959";
}
.icon-revision:before {
content: "\e94a";
}
.icon-risk:before {
content: "\e91e";
}
.icon-services:before {
content: "\e94c";
}
.icon-settings:before {
content: "\e979";
}
.icon-shipment-01:before {
content: "\e929";
}
.icon-sign:before {
content: "\e95d";
}
.icon-sms:before {
content: "\e975";
}
.icon-solclaim:before {
content: "\e95f";
}
.icon-solunion:before {
content: "\e94e";
}
.icon-stowaway:before {
content: "\e94f";
}
.icon-splitline:before {
content: "\e93e";
}
.icon-splur:before {
content: "\e970";
}
.icon-supplier:before {
content: "\e925";
}
.icon-supplierfalse:before {
content: "\e90f";
}
.icon-tags:before {
content: "\e96d";
}
.icon-tax:before {
content: "\e940";
}
.icon-thermometer:before {
content: "\e933";
}
.icon-ticket:before {
content: "\e96b";
}
.icon-ticketAdd:before {
content: "\e945";
}
.icon-traceability:before {
content: "\e962";
}
.icon-transaction:before {
content: "\e966";
}
.icon-treatments:before {
content: "\e922";
}
.icon-unavailable:before {
content: "\e92c";
}
.icon-volume:before {
content: "\e96e";
}
.icon-wand:before {
content: "\e93a";
}
.icon-web:before {
content: "\e982";
}
.icon-wiki:before {
content: "\e92d";
}
.icon-worker:before {
content: "\e957";
}
.icon-zone:before {
content: "\e943";
}
.icon-trailer:before {
content: "\e967";
}
.icon-grafana:before {
content: "\e965";
}
.icon-trolley:before {
content: "\e95c";
}
.icon-agency-term:before {
content: "\e950";
}
.icon-defaulter:before {
content: "\e94b";
}
.icon-100:before {
content: "\e95a";
}
.icon-clientUnpaid:before {
content: "\e95b";
}
.icon-history:before {
content: "\e968";
}
.icon-Person:before {
content: "\e901";
}
.icon-accessory:before {
content: "\e90a";
}
.icon-account:before {
content: "\e92a";
}
.icon-actions:before {
content: "\e960";
}
.icon-addperson:before {
content: "\e90e";
}
.icon-agency:before {
content: "\e938";
}
.icon-albaran:before {
content: "\e94d";
}
.icon-anonymous:before {
content: "\e930";
}
.icon-apps:before {
content: "\e951";
}
.icon-artificial:before {
content: "\e90b";
}
.icon-attach:before {
content: "\e92e";
}
.icon-barcode:before {
content: "\e971";
}
.icon-basket:before {
content: "\e914";
}
.icon-basketadd:before {
content: "\e913";
}
.icon-bin:before {
content: "\e96f";
}
.icon-botanical:before {
content: "\e972";
}
.icon-bucket:before {
content: "\e97a";
}
.icon-buscaman:before {
content: "\e93b";
}
.icon-buyrequest:before {
content: "\e932";
}
.icon-calc_volum .path1:before {
content: "\e915";
}
.icon-calc_volum .path2:before {
content: "\e916";
margin-left: -1em;
}
.icon-calc_volum .path3:before {
content: "\e917";
margin-left: -1em;
}
.icon-calc_volum .path4:before {
content: "\e918";
margin-left: -1em;
}
.icon-calc_volum .path5:before {
content: "\e919";
margin-left: -1em;
}
.icon-calc_volum .path6:before {
content: "\e91a";
margin-left: -1em;
}
.icon-calendar:before {
content: "\e93d";
}
.icon-catalog:before {
content: "\e937";
}
.icon-claims:before {
content: "\e963";
}
.icon-client:before {
content: "\e928";
}
.icon-clone:before {
content: "\e973";
}
.icon-columnadd:before {
content: "\e954";
}
.icon-columndelete:before {
content: "\e953";
}
.icon-components:before {
content: "\e946";
}
.icon-consignatarios:before {
content: "\e93f";
}
.icon-control:before {
content: "\e949";
}
.icon-credit:before {
content: "\e927";
}
.icon-deletedTicket:before {
content: "\e935";
}
.icon-deleteline:before {
content: "\e955";
}
.icon-delivery:before {
content: "\e939";
}
.icon-deliveryprices:before {
content: "\e91c";
}
.icon-details:before {
content: "\e961";
}
.icon-dfiscales:before {
content: "\e984";
}
.icon-disabled:before {
content: "\e921";
}
.icon-doc:before {
content: "\e977";
}
.icon-entry:before {
content: "\e934";
}
.icon-exit:before {
content: "\e92f";
}
.icon-eye:before {
content: "\e976";
}
.icon-fixedPrice:before {
content: "\e90d";
}
.icon-flower:before {
content: "\e90c";
}
.icon-frozen:before {
content: "\e900";
}
.icon-fruit:before {
content: "\e903";
}
.icon-funeral:before {
content: "\e904";
}
.icon-greenery:before {
content: "\e907";
}
.icon-greuge:before {
content: "\e944";
}
.icon-grid:before {
content: "\e980";
}
.icon-handmade:before {
content: "\e909";
}
.icon-handmadeArtificial:before {
content: "\e902";
}
.icon-headercol:before {
content: "\e958";
}
.icon-info:before {
content: "\e952";
}
.icon-inventory:before {
content: "\e92b";
}
.icon-invoice:before {
content: "\e923";
}
.icon-invoice-in:before {
content: "\e911";
}
.icon-invoice-in-create:before {
content: "\e912";
}
.icon-invoice-out:before {
content: "\e910";
}
.icon-isTooLittle:before {
content: "\e91b";
}
.icon-item:before {
content: "\e956";
}
.icon-languaje:before {
content: "\e926";
}
.icon-lines:before {
content: "\e942";
}
.icon-linesprepaired:before {
content: "\e948";
}
.icon-logout:before {
content: "\e936";
}
.icon-mana:before {
content: "\e96a";
}
.icon-mandatory:before {
content: "\e97b";
}
.icon-net:before {
content: "\e931";
}
.icon-niche:before {
content: "\e96c";
}
.icon-no036:before {
content: "\e920";
}
.icon-noPayMethod:before {
content: "\e905";
}
.icon-notes:before {
content: "\e941";
}
.icon-noweb:before {
content: "\e91f";
}
.icon-onlinepayment:before {
content: "\e91d";
}
.icon-package:before {
content: "\e978";
}
.icon-payment:before {
content: "\e97e";
}
.icon-pbx:before {
content: "\e93c";
}
.icon-pets:before {
content: "\e947";
}
.icon-photo:before {
content: "\e924";
}
.icon-plant:before {
content: "\e908";
}
.icon-polizon:before {
content: "\e95e";
}
.icon-preserved:before {
content: "\e906";
}
.icon-recovery:before {
content: "\e97c";
}
.icon-regentry:before {
content: "\e964";
}
.icon-reserva:before {
content: "\e959";
}
.icon-revision:before {
content: "\e94a";
}
.icon-risk:before {
content: "\e91e";
}
.icon-services:before {
content: "\e94c";
}
.icon-settings:before {
content: "\e979";
}
.icon-shipment-01:before {
content: "\e929";
}
.icon-sign:before {
content: "\e95d";
}
.icon-sms:before {
content: "\e975";
}
.icon-solclaim:before {
content: "\e95f";
}
.icon-solunion:before {
content: "\e94e";
}
.icon-stowaway:before {
content: "\e94f";
}
.icon-splitline:before {
content: "\e93e";
}
.icon-splur:before {
content: "\e970";
}
.icon-supplier:before {
content: "\e925";
}
.icon-supplierfalse:before {
content: "\e90f";
}
.icon-tags:before {
content: "\e96d";
}
.icon-tax:before {
content: "\e940";
}
.icon-thermometer:before {
content: "\e933";
}
.icon-ticket:before {
content: "\e96b";
}
.icon-ticketAdd:before {
content: "\e945";
}
.icon-traceability:before {
content: "\e962";
}
.icon-transaction:before {
content: "\e966";
}
.icon-treatments:before {
content: "\e922";
}
.icon-unavailable:before {
content: "\e92c";
}
.icon-volume:before {
content: "\e96e";
}
.icon-wand:before {
content: "\e93a";
}
.icon-web:before {
content: "\e982";
}
.icon-wiki:before {
content: "\e92d";
}
.icon-worker:before {
content: "\e957";
}
.icon-zone:before {
content: "\e943";
}

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 162 KiB

After

Width:  |  Height:  |  Size: 173 KiB

View File

@ -21,6 +21,14 @@
type="password"
autocomplete="false">
</vn-textfield>
<vn-textfield
ng-if="$ctrl.$state.params.twoFactor == 'true'"
label="Verification code"
ng-model="$ctrl.code"
vn-name="code"
autocomplete="false"
class="vn-mt-md">
</vn-textfield>
<div class="footer">
<vn-submit label="Change password" ng-click="$ctrl.submit()"></vn-submit>
<div class="spinner-wrapper">

View File

@ -26,11 +26,13 @@ export default class Controller {
submit() {
const userId = this.$state.params.userId;
const newPassword = this.newPassword;
const oldPassword = this.oldPassword;
const newPassword = this.newPassword;
const repeatPassword = this.repeatPassword;
const code = this.code;
if (!newPassword)
throw new UserError(`You must enter a new password`);
if (!oldPassword || !newPassword || !repeatPassword)
throw new UserError(`You must fill all the fields`);
if (newPassword != this.repeatPassword)
throw new UserError(`Passwords don't match`);
@ -38,11 +40,12 @@ export default class Controller {
Authorization: this.$state.params.id
};
this.$http.post('VnUsers/change-password',
this.$http.patch('Accounts/change-password',
{
id: userId,
oldPassword,
newPassword
newPassword,
code
},
{headers}
).then(() => {

View File

@ -2,6 +2,10 @@ Change password: Cambiar contraseña
Old password: Antigua contraseña
New password: Nueva contraseña
Repeat password: Repetir contraseña
Passwords don't match: Las contraseñas no coinciden
You must fill all the fields: Debes rellenar todos los campos
You can not use the same password: No puedes usar la misma contraseña
Verification code: Código de verificación
Password updated!: ¡Contraseña actualizada!
Password requirements: >
La contraseña debe tener al menos {{ length }} caracteres de longitud,

View File

@ -9,6 +9,7 @@ import './login';
import './outLayout';
import './recover-password';
import './reset-password';
import './validate-email';
import './change-password';
import './module-card';
import './module-main';

View File

@ -24,13 +24,23 @@ export default class Controller {
this.loading = false;
})
.catch(req => {
this.loading = false;
this.password = '';
this.focusUser();
if (req?.data?.error?.code === 'REQUIRES_2FA') {
this.outLayout.login = {
user: this.user,
password: this.password,
remember: this.remember
};
this.$state.go('validate-email');
return;
}
const err = req.data?.error;
if (err?.code == 'passExpired')
this.$state.go('change-password', err.details.token);
this.loading = false;
this.password = '';
this.focusUser();
throw req;
});
}
@ -44,5 +54,8 @@ Controller.$inject = ['$scope', '$element', '$state', 'vnAuth'];
ngModule.vnComponent('vnLogin', {
template: require('./index.html'),
controller: Controller
controller: Controller,
require: {
outLayout: '^vnOutLayout'
}
});

View File

@ -0,0 +1,10 @@
<h5 class="vn-mb-md vn-mt-lg" translate>Enter verification code</h5>
<span translate>Please enter the verification code that we have sent to your email address within 5 minutes</span>
<vn-textfield label="Code" ng-model="$ctrl.code" type="text" vn-focus>
</vn-textfield>
<div class="footer">
<vn-submit label="Validate" ng-click="$ctrl.submit()"></vn-submit>
<div class="spinner-wrapper">
<vn-spinner enable="$ctrl.loading"></vn-spinner>
</div>
</div>

View File

@ -0,0 +1,43 @@
import ngModule from '../../module';
import './style.scss';
export default class Controller {
constructor($scope, $element, vnAuth, $state) {
Object.assign(this, {
$scope,
$element,
vnAuth,
user: localStorage.getItem('lastUser'),
remember: true,
$state
});
}
$onInit() {
this.loginData = this.outLayout.login;
if (!this.loginData)
this.$state.go('login');
}
submit() {
this.loading = true;
this.vnAuth.validateCode(this.loginData.user, this.loginData.password, this.code, this.loginData.remember)
.then(() => {
localStorage.setItem('lastUser', this.user);
this.loading = false;
})
.catch(error => {
this.loading = false;
throw error;
});
}
}
Controller.$inject = ['$scope', '$element', 'vnAuth', '$state'];
ngModule.vnComponent('vnValidateEmail', {
template: require('./index.html'),
controller: Controller,
require: {
outLayout: '^vnOutLayout'
}
});

View File

@ -0,0 +1,5 @@
Validate email auth: Autenticar email
Enter verification code: Introduce código de verificación
Code: Código
Please enter the verification code that we have sent to your email address within 5 minutes: Por favor, introduce el código de verificación que te hemos enviado a tu email en los próximos 5 minutos
Validate: Validar

View File

@ -0,0 +1,24 @@
@import "variables";
vn-validate-email {
.footer {
margin-top: 32px;
text-align: center;
position: relative;
& > .vn-submit {
display: block;
& > input {
display: block;
width: 100%;
}
}
& > .spinner-wrapper {
position: absolute;
width: 0;
top: 3px;
right: -8px;
overflow: visible;
}
}
}

View File

@ -37,9 +37,15 @@ function config($stateProvider, $urlRouterProvider) {
description: 'Reset password',
template: '<vn-reset-password></vn-reset-password>'
})
.state('validate-email', {
parent: 'outLayout',
url: '/validate-email',
description: 'Validate email auth',
template: '<vn-validate-email></vn-validate-email>'
})
.state('change-password', {
parent: 'outLayout',
url: '/change-password?id&userId',
url: '/change-password?id&userId&twoFactor',
description: 'Change password',
template: '<vn-change-password></vn-change-password>'
})

View File

@ -39,7 +39,7 @@ module.exports = Self => {
return [html, 'text/html', `filename=${fileName}.pdf"`];
};
Self.sendTemplate = async function(ctx, templateName) {
Self.sendTemplate = async function(ctx, templateName, force) {
const args = Object.assign({}, ctx.args);
const params = {
recipient: args.recipient,
@ -52,6 +52,6 @@ module.exports = Self => {
const email = new Email(templateName, params);
return email.send();
return email.send({force: force});
};
};

View File

@ -147,14 +147,12 @@
"Receipt's bank was not found": "Receipt's bank was not found",
"This receipt was not compensated": "This receipt was not compensated",
"Client's email was not found": "Client's email was not found",
"Tickets with associated refunds": "Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº {{id}}",
"Tickets with associated refunds": "Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº %d",
"It is not possible to modify tracked sales": "It is not possible to modify tracked sales",
"It is not possible to modify sales that their articles are from Floramondo": "It is not possible to modify sales that their articles are from Floramondo",
"It is not possible to modify cloned sales": "It is not possible to modify cloned sales",
"Valid priorities: 1,2,3": "Valid priorities: 1,2,3",
"Warehouse inventory not set": "Almacén inventario no está establecido",
"Component cost not set": "Componente coste no está estabecido",
"Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº 2": "Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº 2",
"Description cannot be blank": "Description cannot be blank",
"company": "Company",
"country": "Country",
@ -177,5 +175,8 @@
"Invalid quantity": "Invalid quantity",
"Failed to upload delivery note": "Error to upload delivery note {{id}}",
"Mail not sent": "There has been an error sending the invoice to the client [{{clientId}}]({{{clientUrl}}}), please check the email address",
"The renew period has not been exceeded": "The renew period has not been exceeded"
}
"The renew period has not been exceeded": "The renew period has not been exceeded",
"You can not use the same password": "You can not use the same password",
"Valid priorities": "Valid priorities: %d",
"Negative basis of tickets": "Negative basis of tickets: {{ticketsIds}}"
}

View File

@ -268,7 +268,7 @@
"Invoice date can't be less than max date": "La fecha de factura no puede ser inferior a la fecha límite",
"Warehouse inventory not set": "El almacén inventario no está establecido",
"This locker has already been assigned": "Esta taquilla ya ha sido asignada",
"Tickets with associated refunds": "No se pueden borrar tickets con abonos asociados. Este ticket está asociado al abono Nº {{id}}",
"Tickets with associated refunds": "No se pueden borrar tickets con abonos asociados. Este ticket está asociado al abono Nº %d",
"Not exist this branch": "La rama no existe",
"This ticket cannot be signed because it has not been boxed": "Este ticket no puede firmarse porque no ha sido encajado",
"Collection does not exist": "La colección no existe",
@ -276,6 +276,8 @@
"Insert a date range": "Inserte un rango de fechas",
"Added observation": "{{user}} añadió esta observacion: {{text}}",
"Comment added to client": "Observación añadida al cliente {{clientFk}}",
"Invalid auth code": "Código de verificación incorrecto",
"Invalid or expired verification code": "Código de verificación incorrecto o expirado",
"Cannot create a new claimBeginning from a different ticket": "No se puede crear una línea de reclamación de un ticket diferente al origen",
"company": "Compañía",
"country": "País",
@ -293,10 +295,15 @@
"Invalid NIF for VIES": "Invalid NIF for VIES",
"Ticket does not exist": "Este ticket no existe",
"Ticket is already signed": "Este ticket ya ha sido firmado",
"Authentication failed": "Autenticación fallida",
"You can't use the same password": "No puedes usar la misma contraseña",
"You can only add negative amounts in refund tickets": "Solo se puede añadir cantidades negativas en tickets abono",
"Fecha fuera de rango": "Fecha fuera de rango",
"Error while generating PDF": "Error al generar PDF",
"Error when sending mail to client": "Error al enviar el correo al cliente",
"Mail not sent": "Se ha producido un fallo al enviar la factura al cliente [{{clientId}}]({{{clientUrl}}}), por favor revisa la dirección de correo electrónico",
"The renew period has not been exceeded": "El periodo de renovación no ha sido superado"
"Mail not sent": "Se ha producido un fallo al enviar la factura al cliente [{{clientId}}]({{{clientUrl}}}), por favor revisa la dirección de correo electrónico",
"The renew period has not been exceeded": "El periodo de renovación no ha sido superado",
"Valid priorities": "Prioridades válidas: %d",
"Negative basis of tickets": "Base negativa para los tickets: {{ticketsIds}}",
"You cannot assign an alias that you are not assigned to": "No puede asignar un alias que no tenga asignado"
}

View File

@ -0,0 +1,9 @@
module.exports = class ForbiddenError extends Error {
constructor(message, code, ...translateArgs) {
super(message);
this.name = 'ForbiddenError';
this.statusCode = 403;
this.code = code;
this.translateArgs = translateArgs;
}
};

View File

@ -1,15 +1,12 @@
const UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
Self.remoteMethod('changePassword', {
Self.remoteMethodCtx('changePassword', {
description: 'Changes the user password',
accessType: 'WRITE',
accessScopes: ['changePassword'],
accepts: [
{
arg: 'id',
type: 'number',
description: 'The user id',
http: {source: 'path'}
}, {
arg: 'oldPassword',
type: 'string',
description: 'The old password',
@ -19,15 +16,35 @@ module.exports = Self => {
type: 'string',
description: 'The new password',
required: true
}, {
arg: 'code',
type: 'string',
description: 'The 2FA code'
}
],
http: {
path: `/:id/changePassword`,
path: `/change-password`,
verb: 'PATCH'
}
});
Self.changePassword = async function(id, oldPassword, newPassword) {
await Self.app.models.VnUser.changePassword(id, oldPassword, newPassword);
Self.changePassword = async function(ctx, oldPassword, newPassword, code, options) {
const userId = ctx.req.accessToken.userId;
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const {VnUser} = Self.app.models;
const user = await VnUser.findById(userId, {fields: ['name', 'twoFactor']}, myOptions);
await user.hasPassword(oldPassword);
if (oldPassword == newPassword)
throw new UserError(`You can not use the same password`);
if (user.twoFactor)
await VnUser.validateCode(user.name, code, myOptions);
await VnUser.changePassword(userId, oldPassword, newPassword, myOptions);
};
};

View File

@ -1,5 +1,5 @@
module.exports = Self => {
Self.remoteMethod('login', {
Self.remoteMethodCtx('login', {
description: 'Login a user with username/email and password',
accepts: [
{
@ -23,5 +23,5 @@ module.exports = Self => {
}
});
Self.login = async(user, password) => Self.app.models.VnUser.signIn(user, password);
Self.login = async(ctx, user, password, options) => Self.app.models.VnUser.signIn(ctx, user, password, options);
};

View File

@ -21,7 +21,8 @@ module.exports = Self => {
}
});
Self.setPassword = async function(id, newPassword) {
await Self.app.models.VnUser.setPassword(id, newPassword);
Self.setPassword = async function(id, newPassword, options) {
options = typeof options == 'object' ? options : {};
await Self.app.models.VnUser.setPassword(id, newPassword, options);
};
};

View File

@ -1,22 +1,99 @@
const {models} = require('vn-loopback/server/server');
describe('account changePassword()', () => {
it('should throw an error when old password is wrong', async() => {
let error;
try {
await models.Account.changePassword(1, 'wrongPassword', 'nightmare.9999');
} catch (e) {
error = e.message;
}
const ctx = {req: {accessToken: {userId: 70}}};
const unauthCtx = {
req: {
headers: {},
connection: {
remoteAddress: '127.0.0.1'
},
getLocale: () => 'en'
},
args: {}
};
describe('Without 2FA', () => {
it('should throw an error when old password is wrong', async() => {
const tx = await models.Account.beginTransaction({});
expect(error).toContain('Invalid current password');
let error;
try {
const options = {transaction: tx};
await models.Account.changePassword(ctx, 'wrongPassword', 'nightmare.9999', null, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
error = e.message;
}
expect(error).toContain('Invalid current password');
});
it('should throw an error when old and new password are the same', async() => {
const tx = await models.Account.beginTransaction({});
let error;
try {
const options = {transaction: tx};
await models.Account.changePassword(ctx, 'nightmare', 'nightmare.9999', null, options);
await models.Account.changePassword(ctx, 'nightmare.9999', 'nightmare.9999', null, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
error = e.message;
}
expect(error).toContain('You can not use the same password');
});
it('should change password', async() => {
const tx = await models.Account.beginTransaction({});
try {
const options = {transaction: tx};
await models.Account.changePassword(ctx, 'nightmare', 'nightmare.9999', null, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
expect(e).toBeUndefined();
}
});
});
it('should change password', async() => {
try {
await models.Account.changePassword(70, 'nightmare', 'nightmare.9999');
} catch (e) {
expect(e).toBeUndefined();
}
describe('With 2FA', () => {
it('should change password when code is correct', async() => {
const tx = await models.Account.beginTransaction({});
const yesterday = Date.vnNew();
yesterday.setDate(yesterday.getDate() - 1);
const options = {transaction: tx};
try {
await models.VnUser.updateAll(
{id: 70},
{
twoFactor: 'email',
passExpired: yesterday
}
, options);
await models.VnUser.signIn(unauthCtx, 'trainee', 'nightmare', options);
} catch (e) {
if (e.message != 'Pass expired')
throw e;
}
try {
const authCode = await models.AuthCode.findOne({where: {userFk: 70}}, options);
await models.Account.changePassword(ctx, 'nightmare', 'nightmare.9999', authCode.code, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
expect(e).toBeUndefined();
}
});
});
});

View File

@ -8,8 +8,18 @@ describe('Account setPassword()', () => {
});
it('should update password when it passes requirements', async() => {
let req = models.Account.setPassword(1, 'Very$ecurePa22.');
const tx = await models.Account.beginTransaction({});
await expectAsync(req).toBeResolved();
let error;
try {
const options = {transaction: tx};
await models.Account.setPassword(1, 'Very$ecurePa22.', options);
await tx.rollback();
} catch (e) {
await tx.rollback();
error = e;
}
expect(error).not.toBeDefined();
});
});

View File

@ -37,6 +37,13 @@
"principalType": "ROLE",
"principalId": "$authenticated",
"permission": "ALLOW"
},
{
"property": "changePassword",
"accessType": "EXECUTE",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW"
}
]
}

View File

@ -17,9 +17,7 @@
<vn-icon-button
icon="delete"
translate-attr="{title: 'Unsubscribe'}"
ng-click="removeConfirm.show(row)"
vn-acl="itManagement"
vn-acl-action="remove">
ng-click="removeConfirm.show(row)">
</vn-icon-button>
</vn-item-section>
</vn-item>
@ -32,9 +30,7 @@
translate-attr="{title: 'Add'}"
vn-bind="+"
ng-click="$ctrl.onAddClick()"
fixed-bottom-right
vn-acl="itManagement"
vn-acl-action="remove">
fixed-bottom-right>
</vn-float-button>
<vn-dialog
vn-id="dialog"

View File

@ -21,12 +21,11 @@ export default class Controller extends Section {
}
onAddClick() {
this.addData = {account: this.$params.id};
this.$.dialog.show();
}
onAddSave() {
return this.$http.post(`MailAliasAccounts`, this.addData)
return this.$http.post(`VnUsers/${this.$params.id}/addAlias`, this.addData)
.then(() => this.refresh())
.then(() => this.vnApp.showSuccess(
this.$t('Subscribed to alias!'))
@ -34,11 +33,12 @@ export default class Controller extends Section {
}
onRemove(row) {
return this.$http.delete(`MailAliasAccounts/${row.id}`)
.then(() => {
this.$.data.splice(this.$.data.indexOf(row), 1);
this.vnApp.showSuccess(this.$t('Unsubscribed from alias!'));
});
const params = {
mailAlias: row.mailAlias
};
return this.$http.post(`VnUsers/${this.$params.id}/removeAlias`, params)
.then(() => this.refresh())
.then(() => this.vnApp.showSuccess(this.$t('Data saved!')));
}
}

View File

@ -25,8 +25,9 @@ describe('component vnUserAliases', () => {
describe('onAddSave()', () => {
it('should add the new row', () => {
controller.addData = {account: 1};
controller.$params = {id: 1};
$httpBackend.expectPOST('MailAliasAccounts').respond();
$httpBackend.expectPOST('VnUsers/1/addAlias').respond();
$httpBackend.expectGET('MailAliasAccounts').respond('foo');
controller.onAddSave();
$httpBackend.flush();
@ -41,12 +42,14 @@ describe('component vnUserAliases', () => {
{id: 1, alias: 'foo'},
{id: 2, alias: 'bar'}
];
controller.$params = {id: 1};
$httpBackend.expectDELETE('MailAliasAccounts/1').respond();
$httpBackend.expectPOST('VnUsers/1/removeAlias').respond();
$httpBackend.expectGET('MailAliasAccounts').respond(controller.$.data[1]);
controller.onRemove(controller.$.data[0]);
$httpBackend.flush();
expect(controller.$.data).toEqual([{id: 2, alias: 'bar'}]);
expect(controller.$.data).toEqual({id: 2, alias: 'bar'});
expect(controller.vnApp.showSuccess).toHaveBeenCalled();
});
});

View File

@ -95,7 +95,7 @@ module.exports = Self => {
// When claimState has been changed
if (args.claimStateFk) {
const newState = await models.ClaimState.findById(args.claimStateFk, null, options);
const newState = await models.ClaimState.findById(args.claimStateFk, null, myOptions);
if (newState.hasToNotify) {
if (newState.code == 'incomplete')
notifyStateChange(ctx, salesPerson.id, claim, newState.code);

View File

@ -28,7 +28,7 @@ module.exports = Self => {
const isAccount = await models.Account.findById(id);
if (isClient && !isAccount)
await models.Account.setPassword(id, newPassword);
await models.VnUser.setPassword(id, newPassword);
else
throw new UserError(`Modifiable password only via recovery or by an administrator`);
};

View File

@ -60,6 +60,7 @@ module.exports = Self => {
DISTINCT c.id clientFk,
c.name clientName,
c.salesPersonFk,
c.businessTypeFk,
u.name salesPersonName,
d.amount,
co.created,

View File

@ -89,7 +89,7 @@ module.exports = Self => {
};
const country = await Self.app.models.Country.findOne(filter);
const code = country ? country.code.toLowerCase() : null;
const countryCode = this.fi.toLowerCase().substring(0, 2);
const countryCode = this.fi?.toLowerCase().substring(0, 2);
if (!this.fi || !validateTin(this.fi, code) || (this.isVies && countryCode == code))
err();
@ -401,22 +401,32 @@ module.exports = Self => {
Self.changeCredit = async function changeCredit(ctx, finalState, changes) {
const models = Self.app.models;
const userId = ctx.options.accessToken.userId;
const accessToken = {req: {accessToken: ctx.options.accessToken} };
const accessToken = {req: {accessToken: ctx.options.accessToken}};
const canEditCredit = await models.ACL.checkAccessAcl(accessToken, 'Client', 'editCredit', 'WRITE');
if (!canEditCredit) {
const lastCredit = await models.ClientCredit.findOne({
field: ['workerFk', 'amount'],
where: {
clientFk: finalState.id
},
order: 'id DESC'
}, ctx.options);
const lastAmount = lastCredit && lastCredit.amount;
const lastCreditIsNotEditable = !await models.ACL.checkAccessAcl(accessToken, 'Client', 'isNotEditableCredit', 'WRITE');
if (lastCredit && lastCredit.amount == 0) {
const zeroCreditEditor =
await models.ACL.checkAccessAcl(accessToken, 'Client', 'zeroCreditEditor', 'WRITE');
const lastCreditIsNotEditable =
await models.ACL.checkAccessAcl(
{req: {accessToken: {userId: lastCredit.workerFk}}},
'Client',
'zeroCreditEditor',
'WRITE'
);
if (lastAmount == 0 && lastCreditIsNotEditable)
throw new UserError(`You can't change the credit set to zero from a financialBoss`);
if (lastCreditIsNotEditable && !zeroCreditEditor)
throw new UserError(`You can't change the credit set to zero from a financialBoss`);
}
const creditLimits = await models.ClientCreditLimit.find({
fields: ['roleFk'],

View File

@ -60,22 +60,22 @@ describe('Client Model', () => {
try {
const options = {transaction: tx};
const context = {options};
const ctx = {options};
// Set credit to zero by a financialBoss
const financialBoss = await models.VnUser.findOne({
where: {name: 'financialBoss'}
}, options);
context.options.accessToken = {userId: financialBoss.id};
ctx.options.accessToken = {userId: financialBoss.id};
await models.Client.changeCredit(context, instance, {credit: 0});
await models.Client.changeCredit(ctx, instance, {credit: 0});
const salesAssistant = await models.VnUser.findOne({
where: {name: 'salesAssistant'}
}, options);
context.options.accessToken = {userId: salesAssistant.id};
ctx.options.accessToken = {userId: salesAssistant.id};
await models.Client.changeCredit(context, instance, {credit: 300});
await models.Client.changeCredit(ctx, instance, {credit: 300});
await tx.rollback();
} catch (e) {
@ -93,14 +93,14 @@ describe('Client Model', () => {
try {
const options = {transaction: tx};
const context = {options};
const ctx = {options};
const salesAssistant = await models.VnUser.findOne({
where: {name: 'salesAssistant'}
}, options);
context.options.accessToken = {userId: salesAssistant.id};
ctx.options.accessToken = {userId: salesAssistant.id};
await models.Client.changeCredit(context, instance, {credit: 99999});
await models.Client.changeCredit(ctx, instance, {credit: 99999});
await tx.rollback();
} catch (e) {

View File

@ -68,7 +68,7 @@
</span>
</vn-td>
<vn-td number>{{::clientInforma.rating}}</vn-td>
<vn-td>{{::clientInforma.recommendedCredit | currency: 'EUR': 2}}</vn-td>
<vn-td number>{{::clientInforma.recommendedCredit | currency: 'EUR'}}</vn-td>
</vn-tr>
</vn-tbody>
</vn-table>

View File

@ -4,7 +4,7 @@
filter="::$ctrl.filter"
limit="20"
order="amount DESC"
data="defaulters"
data="$ctrl.defaulters"
on-data-change="$ctrl.reCheck()"
auto-load="true">
</vn-crud-model>
@ -34,7 +34,7 @@
</div>
<div class="vn-pa-md">
<vn-button
ng-show="$ctrl.checked.length > 0"
disabled="$ctrl.checked.length == 0"
ng-click="notesDialog.show()"
name="notesDialog"
vn-tooltip="Add observation"
@ -54,6 +54,9 @@
<th field="clientFk">
<span translate>Client</span>
</th>
<th>
<span translate>Es trabajador</span>
</th>
<th field="salesPersonFk">
<span translate>Comercial</span>
</th>
@ -94,7 +97,7 @@
</tr>
</thead>
<tbody>
<tr ng-repeat="defaulter in defaulters">
<tr ng-repeat="defaulter in $ctrl.defaulters">
<td shrink>
<vn-check
ng-model="defaulter.checked"
@ -110,6 +113,12 @@
{{::defaulter.clientName}}
</span>
</td>
<td>
<vn-check
ng-model="defaulter.isWorker"
disabled="true">
</vn-check>
</td>
<td>
<span
title="{{::defaulter.salesPersonName}}"

View File

@ -6,6 +6,7 @@ export default class Controller extends Section {
constructor($element, $) {
super($element, $);
this.defaulter = {};
this.defaulters = [];
this.checkedDefaulers = [];
this.smartTableOptions = {
@ -69,6 +70,18 @@ export default class Controller extends Section {
this.getBalanceDueTotal();
}
set defaulters(value) {
if (!value || !value.length) return;
for (let defaulter of value)
defaulter.isWorker = defaulter.businessTypeFk === 'worker';
this._defaulters = value;
}
get defaulters() {
return this._defaulters;
}
get checked() {
const clients = this.$.model.data || [];
const checkedLines = [];

View File

@ -64,7 +64,7 @@
<vn-label-value label="Channel"
value="{{$ctrl.summary.contactChannel.name}}">
</vn-label-value>
<vn-label-value label="Business type"
<vn-label-value label="Business type"
value="{{$ctrl.summary.businessType.description}}">
</vn-label-value>
</vn-one>
@ -270,7 +270,7 @@
info="Invoices minus payments plus orders not yet invoiced">
</vn-label-value>
<vn-label-value label="Credit"
value="{{$ctrl.summary.credit | currency: 'EUR':2 }} "
value="{{$ctrl.summary.credit | currency: 'EUR'}} "
ng-class="{alert: $ctrl.summary.credit > $ctrl.summary.creditInsurance ||
($ctrl.summary.credit && $ctrl.summary.creditInsurance == null)}"
info="Verdnatura's maximum risk">
@ -296,6 +296,9 @@
value="{{$ctrl.summary.rating}}"
info="Value from 1 to 20. The higher the better value">
</vn-label-value>
<vn-label-value label="Recommended credit"
value="{{$ctrl.summary.recommendedCredit | currency: 'EUR'}}">
</vn-label-value>
</vn-one>
</vn-horizontal>
<vn-horizontal>

View File

@ -8,7 +8,7 @@ vn-client-summary .summary {
}
vn-horizontal h4 .grafana:after {
content: 'contact_support';
font-size: 17px;
font-family: 'salixfont' !important;
content: "\e965";
}
}

View File

@ -3,14 +3,13 @@
vn-entry-buy-index vn-card {
max-width: $width-xl;
.dark-row {
background-color: lighten($color-marginal, 10%);
}
thead tr {
border-left: 1px solid white;
border-right: 1px solid white;
border: 1px solid white;;
}
tbody tr:nth-child(1),
@ -22,7 +21,7 @@ vn-entry-buy-index vn-card {
tbody tr:nth-child(2) {
border-bottom: 1px solid $color-spacer;
}
tbody{
border-bottom: 1px solid $color-spacer;
}
@ -40,4 +39,4 @@ vn-entry-buy-index vn-card {
}
}
$color-font-link-medium: lighten($color-font-link, 20%)
$color-font-link-medium: lighten($color-font-link, 20%)

View File

@ -1,5 +1,3 @@
const UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
Self.remoteMethodCtx('invoiceClient', {
description: 'Make a invoice of a client',
@ -56,7 +54,6 @@ module.exports = Self => {
const minShipped = Date.vnNew();
minShipped.setFullYear(args.maxShipped.getFullYear() - 1);
let invoiceId;
try {
const client = await models.Client.findById(args.clientId, {
fields: ['id', 'hasToInvoiceByAddress']
@ -77,56 +74,21 @@ module.exports = Self => {
], options);
}
// Check negative bases
let query =
`SELECT COUNT(*) isSpanishCompany
FROM supplier s
JOIN country c ON c.id = s.countryFk
AND c.code = 'ES'
WHERE s.id = ?`;
const [supplierCompany] = await Self.rawSql(query, [
args.companyFk
], options);
const isSpanishCompany = supplierCompany?.isSpanishCompany;
query = 'SELECT hasAnyNegativeBase() AS base';
const [result] = await Self.rawSql(query, null, options);
const hasAnyNegativeBase = result?.base;
if (hasAnyNegativeBase && isSpanishCompany)
throw new UserError('Negative basis');
// Invoicing
query = `SELECT invoiceSerial(?, ?, ?) AS serial`;
const [invoiceSerial] = await Self.rawSql(query, [
client.id,
const invoiceType = 'G';
const invoiceId = await models.Ticket.makeInvoice(
ctx,
invoiceType,
args.companyFk,
'G'
], options);
const serialLetter = invoiceSerial.serial;
query = `CALL invoiceOut_new(?, ?, NULL, @invoiceId)`;
await Self.rawSql(query, [
serialLetter,
args.invoiceDate
], options);
const [newInvoice] = await Self.rawSql(`SELECT @invoiceId id`, null, options);
if (!newInvoice)
throw new UserError('No tickets to invoice', 'notInvoiced');
await Self.rawSql('CALL invoiceOutBooking(?)', [newInvoice.id], options);
invoiceId = newInvoice.id;
args.invoiceDate,
options
);
if (tx) await tx.commit();
return invoiceId;
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
return invoiceId;
};
};

View File

@ -14,8 +14,7 @@ module.exports = Self => {
}, {
arg: 'printerFk',
type: 'number',
description: 'The printer to print',
required: true
description: 'The printer to print'
}
],
http: {
@ -51,7 +50,7 @@ module.exports = Self => {
const ref = invoiceOut.ref;
const client = invoiceOut.client();
if (client.isToBeMailed) {
if (client.isToBeMailed || !printerFk) {
try {
ctx.args = {
reference: ref,

View File

@ -17,6 +17,7 @@ describe('InvoiceOut refund()', () => {
const options = {transaction: tx};
try {
await models.TicketRefund.destroyAll(null, options);
const result = await models.InvoiceOut.refund(ctx, 'T1111111', withWarehouse, options);
expect(result).toBeDefined();

View File

@ -145,7 +145,7 @@ module.exports = Self => {
const stmts = [];
const stmt = new ParameterizedSQL(
`SELECT
`SELECT
i.id,
i.image,
i.name,
@ -164,6 +164,8 @@ module.exports = Self => {
i.stemMultiplier,
i.typeFk,
i.isFloramondo,
i.recycledPlastic,
i.nonRecycledPlastic,
pr.name AS producer,
it.name AS typeName,
it.workerFk AS buyerFk,

View File

@ -1,4 +1,4 @@
let UserError = require('vn-loopback/util/user-error');
const UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
Self.remoteMethodCtx('new', {
@ -49,7 +49,7 @@ module.exports = Self => {
try {
const itemConfig = await models.ItemConfig.findOne({fields: ['validPriorities']}, myOptions);
if (!itemConfig.validPriorities.includes(params.priority))
throw new UserError(`Valid priorities: ${[...itemConfig.validPriorities]}`);
throw new UserError('Valid priorities', 'VALID_PRIORITIES', [...itemConfig.validPriorities]);
const provisionalName = params.provisionalName;
delete params.provisionalName;

View File

@ -64,7 +64,7 @@ describe('item getBalance()', () => {
const secondItemBalance = await models.Item.getBalance(ctx, secondFilter, options);
expect(firstItemBalance[9].claimFk).toEqual(null);
expect(secondItemBalance[5].claimFk).toEqual(2);
expect(secondItemBalance[4].claimFk).toEqual(2);
await tx.rollback();
} catch (e) {

View File

@ -42,8 +42,9 @@ module.exports = Self => {
promises.push(Self.app.models.ItemTaxCountry.updateAll(
{id: tax.id},
{taxClassFk: tax.taxClassFk}
), myOptions);
{taxClassFk: tax.taxClassFk},
myOptions
));
}
await Promise.all(promises);

View File

@ -125,6 +125,12 @@
"minPrice": {
"type": "number"
},
"recycledPlastic": {
"type": "number"
},
"nonRecycledPlastic": {
"type": "number"
},
"packingOut": {
"type": "number"
},

View File

@ -82,6 +82,8 @@
vn-name="expence"
initial-data="$ctrl.item.expense">
</vn-autocomplete>
</vn-horizontal>
<vn-horizontal>
<vn-autocomplete
data="originsData"
label="Origin"
@ -91,21 +93,6 @@
vn-name="origin"
initial-data="$ctrl.item.origin">
</vn-autocomplete>
<vn-textfield
label="Reference"
ng-model="$ctrl.item.comment"
vn-name="comment"
rule>
</vn-textfield>
</vn-horizontal>
<vn-horizontal>
<vn-input-number
min="0"
label="Relevancy"
ng-model="$ctrl.item.relevancy"
vn-name="relevancy"
rule>
</vn-input-number>
<vn-input-number
min="0"
label="Size"
@ -113,6 +100,21 @@
vn-name="size"
rule>
</vn-input-number>
<vn-textfield
label="Reference"
ng-model="$ctrl.item.comment"
vn-name="comment"
rule>
</vn-textfield>
<vn-input-number
min="0"
label="Relevancy"
ng-model="$ctrl.item.relevancy"
vn-name="relevancy"
rule>
</vn-input-number>
</vn-horizontal>
<vn-horizontal>
<vn-input-number
min="0"
label="stems"
@ -126,22 +128,6 @@
ng-model="$ctrl.item.stemMultiplier"
vn-name="stemMultiplier">
</vn-input-number>
</vn-horizontal>
<vn-horizontal>
<vn-input-number
min="0"
label="Weight/Piece"
ng-model="$ctrl.item.weightByPiece"
vn-name="weightByPiece"
rule>
</vn-input-number>
<vn-input-number
min="0"
label="Units/Box"
ng-model="$ctrl.item.packingOut"
vn-name="packingOut"
rule>
</vn-input-number>
<vn-autocomplete
label="Generic"
url="Items/withName"
@ -167,6 +153,36 @@
</append>
</vn-autocomplete>
</vn-horizontal>
<vn-horizontal>
<vn-input-number
min="0"
label="Weight/Piece"
ng-model="$ctrl.item.weightByPiece"
vn-name="weightByPiece"
rule>
</vn-input-number>
<vn-input-number
min="0"
label="Units/Box"
ng-model="$ctrl.item.packingOut"
vn-name="packingOut"
rule>
</vn-input-number>
<vn-input-number
min="0"
label="Recycled Plastic"
ng-model="$ctrl.item.recycledPlastic"
vn-name="recycledPlastic"
rule>
</vn-input-number>
<vn-input-number
min="0"
label="Non recycled plastic"
ng-model="$ctrl.item.nonRecycledPlastic"
vn-name="nonRecycledPlastic"
rule>
</vn-input-number>
</vn-horizontal>
<vn-horizontal>
<vn-textarea
label="Description"

View File

@ -1,7 +1,7 @@
Reference: Referencia
Full name calculates based on tags 1-3. Is not recommended to change it manually: >-
El nombre completo se calcula
basado en los tags 1-3.
Full name calculates based on tags 1-3. Is not recommended to change it manually: >-
El nombre completo se calcula
basado en los tags 1-3.
No se recomienda cambiarlo manualmente
Is active: Activo
Expense: Gasto
@ -13,4 +13,6 @@ Is shown at website, app that this item cannot travel (wreath, palms, ...): Se m
Multiplier: Multiplicador
Generic: Genérico
This item does need a photo: Este artículo necesita una foto
Do photo: Hacer foto
Do photo: Hacer foto
Recycled Plastic: Plástico reciclado
Non recycled plastic: Plástico no reciclado

View File

@ -85,7 +85,7 @@
show-field="id"
value-field="id"
search-function="$ctrl.itemSearchFunc($search)"
on-change="$ctrl.upsertPrice(price, true)"
ng-change="$ctrl.upsertPrice(price, true)"
order="id DESC"
tabindex="1">
<tpl-item>

View File

@ -113,9 +113,21 @@
<vn-label-value label="Weight/Piece"
value="{{$ctrl.summary.item.weightByPiece}}">
</vn-label-value>
<vn-label-value label="Units/Box"
value="{{$ctrl.summary.item.packingOut}}">
</vn-label-value>
<vn-label-value label="Expense"
value="{{$ctrl.summary.item.expense.name}}">
</vn-label-value>
<vn-label-value label="Generic"
value="{{$ctrl.summary.item.genericFk}}">
</vn-label-value>
<vn-label-value label="Recycled Plastic"
value="{{$ctrl.summary.item.recycledPlastic}}">
</vn-label-value>
<vn-label-value label="Non recycled plastic"
value="{{$ctrl.summary.item.nonRecycledPlastic}}">
</vn-label-value>
</vn-one>
<vn-one name="tags">
<h4 ng-show="$ctrl.isBuyer || $ctrl.isReplenisher">

View File

@ -0,0 +1,81 @@
const UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
Self.remoteMethod('clone', {
description: 'Clones the selected routes',
accessType: 'WRITE',
accepts: [
{
arg: 'ids',
type: ['number'],
required: true,
description: 'The routes ids to clone'
},
{
arg: 'etd',
type: 'date',
required: true,
description: 'The estimated time of departure for all roadmaps'
}
],
returns: {
type: ['Object'],
root: true
},
http: {
path: `/clone`,
verb: 'POST'
}
});
Self.clone = async(ids, etd) => {
const tx = await Self.beginTransaction({});
try {
const models = Self.app.models;
const options = {transaction: tx};
const originalRoadmaps = await models.Roadmap.find({
where: {id: {inq: ids}},
fields: [
'id',
'name',
'tractorPlate',
'trailerPlate',
'phone',
'supplierFk',
'etd',
'observations',
'price'],
include: [{
relation: 'expeditionTruck',
scope: {
fields: ['roadmapFk', 'warehouseFk', 'eta', 'description']
}
}]
}, options);
if (ids.length != originalRoadmaps.length)
throw new UserError(`The amount of roadmaps found don't match`);
for (const roadmap of originalRoadmaps) {
roadmap.id = undefined;
roadmap.etd = etd;
const clone = await models.Roadmap.create(roadmap, options);
const expeditionTrucks = roadmap.expeditionTruck();
expeditionTrucks.map(expeditionTruck => {
expeditionTruck.roadmapFk = clone.id;
return expeditionTruck;
});
await models.ExpeditionTruck.create(expeditionTrucks, options);
}
await tx.commit();
return true;
} catch (e) {
await tx.rollback();
throw e;
}
};
};

View File

@ -0,0 +1,109 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('AgencyTerm filter()', () => {
const authUserId = 9;
const today = Date.vnNew();
today.setHours(2, 0, 0, 0);
it('should return all results matching the filter', async() => {
const tx = await models.AgencyTerm.beginTransaction({});
try {
const options = {transaction: tx};
const filter = {};
const ctx = {req: {accessToken: {userId: authUserId}}};
const agencyTerms = await models.AgencyTerm.filter(ctx, filter, options);
const firstAgencyTerm = agencyTerms[0];
expect(firstAgencyTerm.routeFk).toEqual(1);
expect(agencyTerms.length).toEqual(5);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return results matching "search" searching by integer', async() => {
let ctx = {
args: {
search: 1,
}
};
let result = await app.models.AgencyTerm.filter(ctx);
expect(result.length).toEqual(1);
expect(result[0].routeFk).toEqual(1);
});
it('should return results matching "search" searching by string', async() => {
let ctx = {
args: {
search: 'Plants SL',
}
};
let result = await app.models.AgencyTerm.filter(ctx);
expect(result.length).toEqual(2);
});
it('should return results matching "from" and "to"', async() => {
const tx = await models.Buy.beginTransaction({});
const options = {transaction: tx};
try {
const from = Date.vnNew();
from.setHours(0, 0, 0, 0);
const to = Date.vnNew();
to.setHours(23, 59, 59, 999);
const ctx = {
args: {
from: from,
to: to
}
};
const results = await models.AgencyTerm.filter(ctx, options);
expect(results.length).toBe(5);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return results matching "agencyModeFk"', async() => {
let ctx = {
args: {
agencyModeFk: 1,
}
};
let result = await app.models.AgencyTerm.filter(ctx);
expect(result.length).toEqual(1);
expect(result[0].routeFk).toEqual(1);
});
it('should return results matching "agencyFk"', async() => {
let ctx = {
args: {
agencyFk: 2,
}
};
let result = await app.models.AgencyTerm.filter(ctx);
expect(result.length).toEqual(1);
expect(result[0].routeFk).toEqual(2);
});
});

View File

@ -0,0 +1,27 @@
module.exports = Self => {
Self.remoteMethod('sorted', {
description: 'Sort the vehicles by warehouse',
accessType: 'WRITE',
accepts: [{
arg: 'warehouseFk',
type: 'number'
}],
returns: {
type: ['object'],
root: true
},
http: {
path: `/sorted`,
verb: `POST`
}
});
Self.sorted = async warehouseFk => {
return Self.rawSql(`
SELECT v.id, v.warehouseFk, v.numberPlate, w.name
FROM vehicle v
JOIN warehouse w ON w.id = v.warehouseFk
ORDER BY v.warehouseFk = ? DESC, w.id, v.numberPlate ASC;
`, [warehouseFk]);
};
};

View File

@ -5,18 +5,22 @@
"AgencyTermConfig": {
"dataSource": "vn"
},
"Route": {
"DeliveryPoint": {
"dataSource": "vn"
},
"Vehicle": {
"ExpeditionTruck": {
"dataSource": "vn"
},
"Roadmap": {
"dataSource": "vn"
},
"Route": {
"dataSource": "vn"
},
"RouteLog": {
"dataSource": "vn"
},
"DeliveryPoint": {
"Vehicle": {
"dataSource": "vn"
}
}

View File

@ -0,0 +1,43 @@
{
"name": "ExpeditionTruck",
"base": "VnModel",
"options": {
"mysql": {
"table": "expeditionTruck"
}
},
"properties": {
"id": {
"type": "number",
"id": true,
"description": "Identifier"
},
"roadmapFk": {
"type": "number"
},
"warehouseFk": {
"type": "number"
},
"eta": {
"type": "date"
},
"description": {
"type": "string"
},
"userFk": {
"type": "number"
}
},
"relations": {
"roadmap": {
"type": "belongsTo",
"model": "Roadmap",
"foreignKey": "roadmapFk"
},
"warehouse": {
"type": "belongsTo",
"model": "Warehouse",
"foreignKey": "warehouseFk"
}
}
}

View File

@ -0,0 +1,3 @@
module.exports = Self => {
require('../methods/roadmap/clone')(Self);
};

View File

@ -0,0 +1,63 @@
{
"name": "Roadmap",
"base": "VnModel",
"options": {
"mysql": {
"table": "roadmap"
}
},
"properties": {
"id": {
"type": "number",
"id": true,
"description": "Identifier"
},
"name": {
"type": "string"
},
"tractorPlate": {
"type": "string"
},
"trailerPlate": {
"type": "string"
},
"phone": {
"type": "string"
},
"supplierFk": {
"type": "number"
},
"etd": {
"type": "date"
},
"observations": {
"type": "string"
},
"userFk": {
"type": "number"
},
"price": {
"type": "number"
},
"driverName": {
"type": "string"
}
},
"relations": {
"worker": {
"type": "belongsTo",
"model": "Worker",
"foreignKey": "userFk"
},
"supplier": {
"type": "belongsTo",
"model": "Supplier",
"foreignKey": "supplierFk"
},
"expeditionTruck": {
"type": "hasMany",
"model": "ExpeditionTruck",
"foreignKey": "roadmapFk"
}
}
}

View File

@ -0,0 +1,3 @@
module.exports = Self => {
require('../methods/vehicle/sorted')(Self);
};

View File

@ -23,19 +23,21 @@
</tpl-item>
</vn-autocomplete>
<vn-autocomplete
label="Vehicle"
ng-model="$ctrl.route.vehicleFk"
url="Vehicles"
data="$ctrl.vehicles"
show-field="numberPlate"
value-field="id"
label="Vehicle"
order="false"
vn-name="vehicle">
<tpl-item>{{::numberPlate}} - {{::name}}</tpl-item>
</vn-autocomplete>
</vn-horizontal>
<vn-horizontal>
<vn-date-picker
label="Created"
ng-model="$ctrl.route.created"
vn-name="created">
vn-name="created">
</vn-date-picker>
<vn-autocomplete
ng-model="$ctrl.route.agencyModeFk"

View File

@ -2,6 +2,13 @@ import ngModule from '../module';
import Section from 'salix/components/section';
class Controller extends Section {
$onInit() {
this.$http.post(`Vehicles/sorted`, {warehouseFk: this.vnConfig.warehouseFk})
.then(res => {
this.vehicles = res.data;
});
}
onSubmit() {
this.$.watcher.submit().then(() =>
this.card.reload()

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