Compare commits

..

132 Commits

Author SHA1 Message Date
JOSE ANTONIO TUBAU RODRIGUEZ 1b05c10b50 Merge pull request 'ShowDptoLink' (!1076) from showDeptLink into dev
gitea/salix-front/pipeline/head This commit looks good Details
Reviewed-on: #1076
Reviewed-by: Javier Segarra <jsegarra@verdnatura.es>
2024-12-12 14:35:41 +00:00
JOSE ANTONIO TUBAU RODRIGUEZ 1d37d0dfb4 Merge branch 'dev' into showDeptLink
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-12 13:50:42 +00:00
JOSE ANTONIO TUBAU RODRIGUEZ d35c37bfdf fix: addLocales
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-12 14:47:21 +01:00
JOSE ANTONIO TUBAU RODRIGUEZ 013c07e51f feat: addDptoLink 2024-12-12 14:39:07 +01:00
Pablo Natek d72b507fd4 Merge pull request 'feat: refs #7301 add exclude inventory supplier from list' (!982) from 7301-itemLastEntries into dev
gitea/salix-front/pipeline/head This commit looks good Details
Reviewed-on: #982
Reviewed-by: Alex Moreno <alexm@verdnatura.es>
2024-12-12 13:23:30 +00:00
Pablo Natek 87bdf532a8 Merge branch 'dev' into 7301-itemLastEntries
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-12 13:11:45 +00:00
Carlos Satorres 59b034d0b4 Merge pull request 'fix: fix department filter' (!1075) from fix-6389departmentFilter into dev
gitea/salix-front/pipeline/head This commit looks good Details
gitea/salix-front/pipeline/pr-dev This commit looks good Details
Reviewed-on: #1075
Reviewed-by: Alex Moreno <alexm@verdnatura.es>
2024-12-12 10:03:24 +00:00
Carlos Satorres ac3ca3e243 fix: fix department filter
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-12 10:51:13 +01:00
Carlos Satorres b022ede6a9 Merge pull request 'fix: refs #6389 ipt' (!846) from 6389-changesMonitor into dev
gitea/salix-front/pipeline/head This commit looks good Details
Reviewed-on: #846
Reviewed-by: Alex Moreno <alexm@verdnatura.es>
2024-12-12 09:28:52 +00:00
Carlos Satorres e628a6c445 Merge branch 'dev' into 6389-changesMonitor
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-12 08:48:28 +00:00
Pablo Natek c043a7d99a Merge branch 'dev' into 7301-itemLastEntries
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-12 08:34:39 +00:00
Carlos Satorres 79c1709618 Merge pull request 'fix: refs #7031 add test e2e' (!1049) from 7031-zonePrice into dev
gitea/salix-front/pipeline/head This commit looks good Details
Reviewed-on: #1049
Reviewed-by: Alex Moreno <alexm@verdnatura.es>
Reviewed-by: Jon Elias <jon@verdnatura.es>
2024-12-12 08:33:55 +00:00
Carlos Satorres 964cf68b9c Merge branch 'dev' into 7031-zonePrice
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-12 08:32:17 +00:00
Pablo Natek d4bb5a063f Merge branch 'dev' into 7301-itemLastEntries
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-12 08:31:51 +00:00
Pablo Natek 8bccb959ed fix: refs #7301 unnecessary console logs from ItemLastEntries.vue
gitea/salix-front/pipeline/pr-dev Build queued... Details
2024-12-12 09:31:33 +01:00
Jon Elias cd9b433a45 Merge pull request 'FIX: added restore ticket function in TicketDescriptorMenu' (!1072) from Fix-TicketDescriptorMenuOption into dev
gitea/salix-front/pipeline/head This commit looks good Details
Reviewed-on: #1072
Reviewed-by: Alex Moreno <alexm@verdnatura.es>
2024-12-12 08:28:37 +00:00
Pablo Natek 52cacd8c16 Merge branch 'dev' of https: refs #7301//gitea.verdnatura.es/verdnatura/salix-front into 7301-itemLastEntries 2024-12-12 09:03:09 +01:00
Jon Elias ba300ec065 Merge branch 'Fix-TicketDescriptorMenuOption' of https://gitea.verdnatura.es/verdnatura/salix-front into Fix-TicketDescriptorMenuOption
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-12 08:04:07 +01:00
Jon Elias e01f1fe5d2 refactor: deleted log 2024-12-12 08:04:06 +01:00
Jon Elias d7d1e4d691 Merge branch 'dev' into Fix-TicketDescriptorMenuOption
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-12 06:52:31 +00:00
Jon Elias 983c86ffa5 feat: added restore ticket function in ticket descriptor menu
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-12 07:35:20 +01:00
Carlos Satorres 3d666338ce fix: refs #6389 front add packing filter
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-11 11:50:37 +01:00
Jorge Penadés 5b5a935021 Merge pull request '#8002 addSupportService' (!894) from xxxx-addSupportService into dev
gitea/salix-front/pipeline/head This commit looks good Details
Reviewed-on: #894
Reviewed-by: Juan Ferrer <juan@verdnatura.es>
Reviewed-by: Carlos Satorres <carlossa@verdnatura.es>
2024-12-11 09:49:39 +00:00
Jorge Penadés 273c879879 Merge branch 'dev' into xxxx-addSupportService
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-11 09:39:59 +00:00
Carlos Satorres 0ecc103fc2 fix: refs #6389 front
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-11 09:59:05 +01:00
Carlos Satorres 7697caa85a Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix-front into 6389-changesMonitor
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-11 06:49:38 +01:00
Alex Moreno 4fc9ad3f76 Merge branch 'test' of https://gitea.verdnatura.es/verdnatura/salix-front into dev
gitea/salix-front/pipeline/head This commit looks good Details
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-10 13:40:47 +01:00
Javier Segarra ee445aca83 Merge pull request 'perf: emit options from VnSelectProvince' (!1062) from hotfix_improve_cp into master
gitea/salix-front/pipeline/head This commit looks good Details
Reviewed-on: #1062
Reviewed-by: Carlos Satorres <carlossa@verdnatura.es>
2024-12-10 12:24:00 +00:00
Javier Segarra 854e72fe51 perf: emit options from VnSelectProvince
gitea/salix-front/pipeline/pr-master This commit looks good Details
2024-12-10 13:17:31 +01:00
Alex Moreno 4a6f859a86 fix(RouteExtendedList): fix cloneRoutes
gitea/salix-front/pipeline/head This commit looks good Details
2024-12-10 13:15:03 +01:00
Alex Moreno b2fe1a6b6a Merge branch 'test' of https://gitea.verdnatura.es/verdnatura/salix-front into dev
gitea/salix-front/pipeline/head This commit looks good Details
2024-12-10 11:29:06 +01:00
Javier Segarra b97ee919a6 Merge pull request 'Hotfix: Bugs detected after 24.50' (!1060) from hotfix_minor_24-50 into master
gitea/salix-front/pipeline/head This commit looks good Details
Reviewed-on: #1060
Reviewed-by: Alex Moreno <alexm@verdnatura.es>
2024-12-10 08:49:07 +00:00
Alex Moreno 629531cce4 Merge branch 'test' of https://gitea.verdnatura.es/verdnatura/salix-front into dev
gitea/salix-front/pipeline/head This commit looks good Details
2024-12-09 14:32:42 +01:00
Jorge Penadés 2fb179803c refactor: add useCau composable
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-09 13:42:00 +01:00
Jon Elias 91afc3ddab Merge pull request '#7283: Fix Item module' (!1042) from Fix-Items-Module into dev
gitea/salix-front/pipeline/head This commit looks good Details
Reviewed-on: #1042
Reviewed-by: Alex Moreno <alexm@verdnatura.es>
Reviewed-by: Javi Gallego <jgallego@verdnatura.es>
2024-12-09 12:29:54 +00:00
Jon Elias d4682248fd Merge branch 'Fix-Items-Module' of https://gitea.verdnatura.es/verdnatura/salix-front into Fix-Items-Module
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-09 13:24:36 +01:00
Jon Elias 1de74dec8e fix: fix conflicts 2024-12-09 13:24:34 +01:00
Jon Elias bf68eab480 Merge pull request '#8194 created VnSelectWorker component' (!977) from 8194-VnSelectWorker into dev
gitea/salix-front/pipeline/head This commit looks good Details
Reviewed-on: #977
Reviewed-by: Javier Segarra <jsegarra@verdnatura.es>
2024-12-09 12:04:18 +00:00
Jon Elias 853bb9e5aa Merge branch 'dev' into 8194-VnSelectWorker
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-09 12:02:16 +00:00
Jon Elias e4837b45be Merge branch 'dev' into Fix-Items-Module
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-09 12:01:07 +00:00
Jorge Penadés fca380897f Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix-front into xxxx-addSupportService
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-09 12:41:45 +01:00
Jorge Penadés 9342cd0408 Merge pull request 'Mixin performance' (!875) from performance_mixins into dev
gitea/salix-front/pipeline/head This commit looks good Details
Reviewed-on: #875
Reviewed-by: Alex Moreno <alexm@verdnatura.es>
2024-12-09 11:38:51 +00:00
Jorge Penadés 7a9edfd88f Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix-front into xxxx-addSupportService 2024-12-09 12:38:38 +01:00
Jorge Penadés f16c45b01a Merge branch 'dev' into performance_mixins
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-09 11:37:52 +00:00
Carlos Satorres 5fc7d66425 Merge branch '7031-zonePrice' of https://gitea.verdnatura.es/verdnatura/salix-front into 7031-zonePrice
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-09 11:43:22 +01:00
Carlos Satorres a20afa5f35 fix: refs #7031 fix zoneTest 2024-12-09 11:43:20 +01:00
Jon Elias 92b05db9d2 refactor: deleted useless hidden tag
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-09 11:27:30 +01:00
Carlos Satorres d9fe5be6fe Merge branch 'dev' into 7031-zonePrice
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-09 08:11:53 +00:00
Jon Elias b26d07f605 Merge branch 'Fix-Items-Module' of https://gitea.verdnatura.es/verdnatura/salix-front into Fix-Items-Module
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-09 08:49:27 +01:00
Jon Elias f5f77a50bc refactor: added again search emit 2024-12-09 08:49:26 +01:00
Jon Elias 338058c1a4 Merge branch 'dev' into Fix-Items-Module
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-09 07:22:17 +00:00
Jon Elias 0c88db5931 refactor: deleted onUnmounted code
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-09 08:20:35 +01:00
Carlos Satorres dc4ae1fd92 Merge branch 'dev' of https: refs #6389//gitea.verdnatura.es/verdnatura/salix-front into 6389-changesMonitor
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-09 06:57:47 +01:00
Jon Elias fea161d5c2 perf: refs #8194 select worker component
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-05 14:19:58 +01:00
Jon Elias 96920dd540 refactor: refs #8194 modified select worker template
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-05 14:13:31 +01:00
Jon Elias cf522684d6 refactor: refs #8194 deleted unnecessary label
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-05 14:00:45 +01:00
Jon Elias 6c05347219 refactor: refs #8194 modified select worker to allow no one filter from monitor ticket
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-05 13:45:18 +01:00
Jon Elias accf61517a refactor: refs #8194 requested changes
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-05 13:31:39 +01:00
Jon Elias c7115f4781 refactor: refs #8194 moved translation to the correct place
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-05 11:14:15 +01:00
Jon Elias 2d2187090c Merge branch 'dev' of https: refs #8194//gitea.verdnatura.es/verdnatura/salix-front into 8194-VnSelectWorker
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-05 11:04:02 +01:00
Jon Elias 1e1032b3da refactor: refs #8194 structure changes in component and related files
gitea/salix-front/pipeline/pr-dev There was a failure building this commit Details
2024-12-05 11:00:40 +01:00
Jon Elias 646007ea63 refactor: log error
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-05 10:30:43 +01:00
Guillermo Bonet dcbaa7529d Merge branch 'test' into dev
gitea/salix-front/pipeline/head This commit looks good Details
2024-12-05 09:24:45 +01:00
Carlos Satorres 47f81f2b2c Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix-front into 6389-changesMonitor
gitea/salix-front/pipeline/pr-dev There was a failure building this commit Details
2024-12-05 09:19:55 +01:00
Carlos Satorres 3d0245553e Merge pull request 'fix-7355AccountCreate' (!1051) from fix-7355AccountCreate into dev
gitea/salix-front/pipeline/head This commit looks good Details
Reviewed-on: #1051
Reviewed-by: Alex Moreno <alexm@verdnatura.es>
2024-12-05 08:17:23 +00:00
Carlos Satorres c3c10b2238 fix: account create
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-05 09:03:13 +01:00
Carlos Satorres 91c9a4a559 Merge branch 'dev' into 7031-zonePrice
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-05 07:32:10 +00:00
Carlos Satorres cb15652dd6 fix: refs #7031 add test e2e
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-05 08:28:43 +01:00
Jon Elias 58a18bfb69 refactor: deleted warnings and corrected itemTag
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-05 06:26:02 +01:00
Carlos Satorres 95551d9f99 fix: account 2024-12-05 06:03:10 +01:00
Carlos Satorres f5c6810d9e fix: accountList create 2024-12-04 13:58:59 +01:00
Jorge Penadés e0090c29c9 Merge branch 'dev' into performance_mixins
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-04 12:22:09 +00:00
Carlos Satorres a6a21f3925 Merge pull request 'remove autocomplete address' (!935) from 8114-removeAutoAddress into dev
gitea/salix-front/pipeline/head This commit looks good Details
Reviewed-on: #935
Reviewed-by: Alex Moreno <alexm@verdnatura.es>
2024-12-04 09:43:24 +00:00
Carlos Satorres fc3c80d60d fix: refs #8114 fix lifeCycle hooks
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-04 10:35:33 +01:00
Carlos Satorres e55d116398 fix: refs #8114 fix pr
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-04 10:31:59 +01:00
Carlos Satorres 41292e467b Merge branch '8114-removeAutoAddress' of https://gitea.verdnatura.es/verdnatura/salix-front into 8114-removeAutoAddress
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-04 09:27:24 +01:00
Carlos Satorres 55627a5b47 Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix-front into 8114-removeAutoAddress 2024-12-04 09:24:35 +01:00
Carlos Satorres 29b923130f Merge branch 'dev' into 8114-removeAutoAddress
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-04 08:22:58 +00:00
Jon Elias 4276cefd7a feat: requested changes in item module
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-04 09:14:00 +01:00
Alex Moreno b4a4c4a0a4 build: new version
gitea/salix-front/pipeline/head This commit looks good Details
2024-12-03 14:34:01 +01:00
Carlos Satorres 1f80229bc8 Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix-front into 6389-changesMonitor
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-03 11:54:58 +01:00
Carlos Satorres ce83879960 Merge branch 'dev' of https: refs #8114//gitea.verdnatura.es/verdnatura/salix-front into 8114-removeAutoAddress
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-03 10:33:48 +01:00
Carlos Satorres 1291dc1723 fix: refs #8114 clean
gitea/salix-front/pipeline/pr-dev There was a failure building this commit Details
2024-12-02 13:28:13 +01:00
Carlos Satorres 50360523b3 fix: refs #8114 remove logs
gitea/salix-front/pipeline/pr-dev There was a failure building this commit Details
2024-12-02 13:26:26 +01:00
Carlos Satorres 48482efe3b fix: refs #8114 fix agencyList
gitea/salix-front/pipeline/pr-dev There was a failure building this commit Details
2024-12-02 13:25:07 +01:00
Jorge Penadés a3f14bc39f refactor: drop logic
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-02 12:12:23 +01:00
Jorge Penadés cfa22bbc85 Merge branch 'performance_mixins' of https://gitea.verdnatura.es/verdnatura/salix-front into performance_mixins
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-02 11:58:57 +01:00
Jorge Penadés bfa7300651 Merge branch 'dev' into performance_mixins
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-12-02 10:58:52 +00:00
Jorge Penadés 1710ae718e Merge branch 'performance_mixins' of https://gitea.verdnatura.es/verdnatura/salix-front into performance_mixins 2024-12-02 11:58:44 +01:00
Jorge Penadés b00a3d7acf Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix-front into performance_mixins 2024-12-02 11:55:54 +01:00
Carlos Satorres aaeabefdfe fix: refs #8114 fix removeAddress
gitea/salix-front/pipeline/pr-dev There was a failure building this commit Details
2024-11-28 11:11:45 +01:00
Carlos Satorres 2d656faf58 Merge branch '6389-changesMonitor' of https://gitea.verdnatura.es/verdnatura/salix-front into 6389-changesMonitor
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-11-27 11:28:34 +01:00
Carlos Satorres 954a777182 Merge branch 'dev' of https: refs #6389//gitea.verdnatura.es/verdnatura/salix-front into 6389-changesMonitor 2024-11-27 11:28:31 +01:00
Carlos Satorres 59648d14f0 fix: refs #8114 orderList
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-11-27 06:18:41 +01:00
Pablo Natek 104348b94b Merge branch 'dev' into 7301-itemLastEntries
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-11-21 09:30:42 +00:00
Pablo Natek c006b4cb37 Merge branch 'dev' into 7301-itemLastEntries
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-11-21 09:20:54 +00:00
Pablo Natek 46cb18b5ef feat: refs #7301 add exclude inventory supplier from list
gitea/salix-front/pipeline/pr-dev Build queued... Details
2024-11-21 10:19:30 +01:00
Alex Moreno e817e51b28 Merge branch 'dev' into performance_mixins
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-11-21 06:57:47 +00:00
Jon Elias 2b235e93e7 feat: refs #8194 created VnSelectWorker component and use it in Lilium
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-11-20 11:25:17 +01:00
Jorge Penadés 9e0f54ea9b fix: e2e
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-11-19 13:49:53 +01:00
Jorge Penadés 26e777cdd5 fix: test
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-11-19 13:36:58 +01:00
Jorge Penadés 8f8fcfe440 feat: focus menu searchbar
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-11-19 12:38:19 +01:00
Jorge Penadés 93144439d2 Merge branch 'dev' into performance_mixins
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-11-19 11:21:56 +00:00
Carlos Satorres eac476781f Merge branch 'dev' into 6389-changesMonitor
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-11-19 10:42:33 +00:00
Carlos Satorres af7f7aa8f3 fix: refs #6389 fix filter trad
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-11-19 10:54:51 +01:00
Carlos Satorres 1844e15239 Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix-front into 6389-changesMonitor
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-11-19 08:52:02 +01:00
Jorge Penadés 0fe740e415 fix: e2e
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-11-14 13:20:23 +01:00
Jorge Penadés fa43f270ca fix: prevent null
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-11-14 12:02:40 +01:00
Jorge Penadés 43af96eb05 Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix-front into xxxx-addSupportService
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-11-14 11:41:05 +01:00
Jorge Penadés f7c64fe6ff Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix-front into xxxx-addSupportService
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-11-14 09:37:24 +01:00
Jorge Penadés 81f1c447ad fix: rollback
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-11-13 17:45:02 +01:00
Jorge Penadés a5d032f022 feat: make additional data object
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-11-13 17:29:19 +01:00
Jorge Penadés 34df9cf254 fix: rollback
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-11-13 15:33:41 +01:00
Jorge Penadés 0c476725ae refactor: use locale keys
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-11-13 13:11:02 +01:00
Jorge Penadés 00c712469f Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix-front into xxxx-addSupportService
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-11-13 12:37:33 +01:00
Javier Segarra 4dc2be291f perf: remove comments
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-11-13 12:32:53 +01:00
Javier Segarra a4ccbe66c7 Merge branch 'dev' into performance_mixins
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-11-13 12:27:49 +01:00
Javier Segarra c3c51e01d4 perf: qFormMixin 2024-11-13 12:27:33 +01:00
Javier Segarra 9b681d806b perf: qFormMixin improvement
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-11-13 10:13:00 +01:00
Jorge Penadés 8a4589910c Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix-front into xxxx-addSupportService
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-11-11 13:16:22 +01:00
Javier Segarra d55764d2bc Merge branch 'dev' into performance_mixins 2024-11-11 09:58:50 +01:00
Jorge Penadés f6d200405c feat: message to grant access
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-11-05 09:33:16 +01:00
Jorge Penadés 3ca26a97dc Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix-front into xxxx-addSupportService 2024-11-05 09:22:46 +01:00
Jorge Penadés 8817fd7c55 feat: add support service wip 2024-10-30 13:55:51 +01:00
Carlos Satorres 8dd2c94b37 fix: refs #6389 packing
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-10-28 09:01:00 +01:00
Carlos Satorres c0c1d3e3a9 Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix-front into 6389-changesMonitor
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-10-28 08:08:19 +01:00
Javier Segarra 4df05b7522 feat: #8110 apply mixin in quasar components
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-10-25 13:41:06 +02:00
Carlos Satorres fee51db30d Merge branch 'dev' of https: refs #6389//gitea.verdnatura.es/verdnatura/salix-front into 6389-changesMonitor
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-10-24 08:09:09 +02:00
Carlos Satorres e8fd3c0a8f fix: refs #6389 fix front, filters, itp
gitea/salix-front/pipeline/pr-dev There was a failure building this commit Details
2024-10-23 14:58:03 +02:00
Carlos Satorres daf57c9b2b fix: refs #6389 front filters
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-10-23 12:20:53 +02:00
Carlos Satorres 861a507e10 Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix-front into 6389-changesMonitor
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-10-22 14:52:10 +02:00
Carlos Satorres 1bafdf1b85 fix: refs #6389 ipt
gitea/salix-front/pipeline/pr-dev This commit looks good Details
2024-10-20 15:01:37 +02:00
79 changed files with 1067 additions and 794 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "salix-front", "name": "salix-front",
"version": "24.50.0", "version": "24.52.0",
"description": "Salix frontend", "description": "Salix frontend",
"productName": "Salix", "productName": "Salix",
"author": "Verdnatura", "author": "Verdnatura",

View File

@ -0,0 +1,36 @@
import routes from 'src/router/modules';
import { useRouter } from 'vue-router';
let isNotified = false;
export default {
created: function () {
const router = useRouter();
const keyBindingMap = routes
.filter((route) => route.meta.keyBinding)
.reduce((map, route) => {
map['Key' + route.meta.keyBinding.toUpperCase()] = route.path;
return map;
}, {});
const handleKeyDown = (event) => {
const { ctrlKey, altKey, code } = event;
if (ctrlKey && altKey && keyBindingMap[code] && !isNotified) {
event.preventDefault();
router.push(keyBindingMap[code]);
isNotified = true;
}
};
const handleKeyUp = (event) => {
const { ctrlKey, altKey } = event;
if (!ctrlKey || !altKey) {
isNotified = false;
}
};
window.addEventListener('keydown', handleKeyDown);
window.addEventListener('keyup', handleKeyUp);
},
};

View File

@ -1,13 +1,37 @@
import { getCurrentInstance } from 'vue'; function focusFirstInput(input) {
input.focus();
return;
}
export default { export default {
mounted: function () { mounted: function () {
const vm = getCurrentInstance();
if (vm.type.name === 'QForm') {
if (!['searchbarForm', 'filterPanelForm'].includes(this.$el?.id)) {
// TODO: AUTOFOCUS IS NOT FOCUSING
const that = this; const that = this;
this.$el.addEventListener('keyup', function (evt) {
const form = document.querySelector('.q-form#formModel');
if (!form) return;
try {
const inputsFormCard = form.querySelectorAll(
`input:not([disabled]):not([type="checkbox"])`
);
if (inputsFormCard.length) {
focusFirstInput(inputsFormCard[0]);
}
const textareas = document.querySelectorAll(
'textarea:not([disabled]), [contenteditable]:not([disabled])'
);
if (textareas.length) {
focusFirstInput(textareas[textareas.length - 1]);
}
const inputs = document.querySelectorAll(
'form#formModel input:not([disabled]):not([type="checkbox"])'
);
const input = inputs[0];
if (!input) return;
focusFirstInput(input);
} catch (error) {
console.error(error);
}
form.addEventListener('keyup', function (evt) {
if (evt.key === 'Enter') { if (evt.key === 'Enter') {
const input = evt.target; const input = evt.target;
if (input.type == 'textarea' && evt.shiftKey) { if (input.type == 'textarea' && evt.shiftKey) {
@ -24,7 +48,5 @@ export default {
that.onSubmit(); that.onSubmit();
} }
}); });
}
}
}, },
}; };

View File

@ -1,15 +1,18 @@
import axios from 'axios';
import { boot } from 'quasar/wrappers'; import { boot } from 'quasar/wrappers';
import qFormMixin from './qformMixin'; import qFormMixin from './qformMixin';
import keyShortcut from './keyShortcut'; import keyShortcut from './keyShortcut';
import useNotify from 'src/composables/useNotify.js'; import { QForm } from 'quasar';
import { CanceledError } from 'axios'; import { QLayout } from 'quasar';
import mainShortcutMixin from './mainShortcutMixin';
const { notify } = useNotify(); import { useCau } from 'src/composables/useCau';
export default boot(({ app }) => { export default boot(({ app }) => {
app.mixin(qFormMixin); QForm.mixins = [qFormMixin];
QLayout.mixins = [mainShortcutMixin];
app.directive('shortcut', keyShortcut); app.directive('shortcut', keyShortcut);
app.config.errorHandler = (error) => { app.config.errorHandler = async (error) => {
let message; let message;
const response = error.response; const response = error.response;
const responseData = response?.data; const responseData = response?.data;
@ -40,12 +43,12 @@ export default boot(({ app }) => {
} }
console.error(error); console.error(error);
if (error instanceof CanceledError) { if (error instanceof axios.CanceledError) {
const env = process.env.NODE_ENV; const env = process.env.NODE_ENV;
if (env && env !== 'development') return; if (env && env !== 'development') return;
message = 'Duplicate request'; message = 'Duplicate request';
} }
notify(message ?? 'globals.error', 'negative', 'error'); await useCau(response, message);
}; };
}); });

View File

@ -25,7 +25,6 @@ const townsFetchDataRef = ref(false);
const townFilter = ref({}); const townFilter = ref({});
const countriesRef = ref(false); const countriesRef = ref(false);
const provincesFetchDataRef = ref(false);
const provincesOptions = ref([]); const provincesOptions = ref([]);
const townsOptions = ref([]); const townsOptions = ref([]);
const town = ref({}); const town = ref({});
@ -71,9 +70,6 @@ async function setProvince(id, data) {
await fetchTowns(); await fetchTowns();
} }
async function onProvinceCreated(data) { async function onProvinceCreated(data) {
await provincesFetchDataRef.value.fetch({
where: { countryFk: postcodeFormData.countryFk },
});
postcodeFormData.provinceFk = data.id; postcodeFormData.provinceFk = data.id;
} }
function provinceByCountry(countryFk = postcodeFormData.countryFk) { function provinceByCountry(countryFk = postcodeFormData.countryFk) {
@ -92,7 +88,6 @@ function setTown(newTown, data) {
data.countryFk = newTown?.province?.countryFk ?? newTown; data.countryFk = newTown?.province?.countryFk ?? newTown;
} }
async function onCityCreated(newTown, formData) { async function onCityCreated(newTown, formData) {
await provincesFetchDataRef.value.fetch();
newTown.province = provincesOptions.value.find( newTown.province = provincesOptions.value.find(
(province) => province.id === newTown.provinceFk (province) => province.id === newTown.provinceFk
); );
@ -125,14 +120,6 @@ async function filterTowns(name) {
</script> </script>
<template> <template>
<FetchData
ref="provincesFetchDataRef"
@on-fetch="handleProvinces"
:sort-by="['name ASC']"
:limit="30"
auto-load
url="Provinces/location"
/>
<FetchData <FetchData
ref="townsFetchDataRef" ref="townsFetchDataRef"
:sort-by="['name ASC']" :sort-by="['name ASC']"
@ -205,6 +192,11 @@ async function filterTowns(name) {
:country-fk="data.countryFk" :country-fk="data.countryFk"
:province-selected="data.provinceFk" :province-selected="data.provinceFk"
@update:model-value="(value) => setProvince(value, data)" @update:model-value="(value) => setProvince(value, data)"
@update:options="
(data) => {
provincesOptions = data;
}
"
v-model="data.provinceFk" v-model="data.provinceFk"
@on-province-created="onProvinceCreated" @on-province-created="onProvinceCreated"
required required

View File

@ -177,6 +177,7 @@ function normalize(text) {
class="full-width" class="full-width"
filled filled
dense dense
autofocus
/> />
</QItem> </QItem>
<QSeparator /> <QSeparator />

View File

@ -7,7 +7,7 @@ import VnSelectDialog from 'components/common/VnSelectDialog.vue';
import FetchData from 'components/FetchData.vue'; import FetchData from 'components/FetchData.vue';
import CreateNewProvinceForm from './CreateNewProvinceForm.vue'; import CreateNewProvinceForm from './CreateNewProvinceForm.vue';
const emit = defineEmits(['onProvinceCreated', 'onProvinceFetched']); const emit = defineEmits(['onProvinceCreated', 'onProvinceFetched', 'update:options']);
const $props = defineProps({ const $props = defineProps({
countryFk: { countryFk: {
type: Number, type: Number,
@ -41,6 +41,7 @@ async function onProvinceCreated(_, data) {
} }
async function handleProvinces(data) { async function handleProvinces(data) {
provincesOptions.value = data; provincesOptions.value = data;
emit('update:options', data);
} }
watch( watch(

View File

@ -610,6 +610,7 @@ function handleSelection({ evt, added, rows: selectedRows }, rows) {
$props.rowClick && $props.rowClick(row); $props.rowClick && $props.rowClick(row);
} }
" "
style="height: 100%"
> >
<QCardSection <QCardSection
vertical vertical

View File

@ -0,0 +1,31 @@
<script setup>
import { toDateFormat } from 'src/filters/date.js';
defineProps({ date: { type: [Date, String], required: true } });
function getBadgeAttrs(date) {
let today = Date.vnNew();
today.setHours(0, 0, 0, 0);
let timeTicket = new Date(date);
timeTicket.setHours(0, 0, 0, 0);
let timeDiff = today - timeTicket;
if (timeDiff == 0) return { color: 'warning', 'text-color': 'black' };
if (timeDiff < 0) return { color: 'success', 'text-color': 'black' };
return { color: 'transparent', 'text-color': 'white' };
}
function formatShippedDate(date) {
if (!date) return '-';
const dateSplit = date.split('T');
const [year, month, day] = dateSplit[0].split('-');
const newDate = new Date(year, month - 1, day);
return toDateFormat(newDate);
}
</script>
<template>
<QBadge v-bind="getBadgeAttrs(date)" class="q-pa-sm" style="font-size: 14px">
{{ formatShippedDate(date) }}
</QBadge>
</template>

View File

@ -238,6 +238,7 @@ async function openPointRecord(id, modelLog) {
pointRecord.value = parseProps(propNames, locale, data); pointRecord.value = parseProps(propNames, locale, data);
} }
async function setLogTree(data) { async function setLogTree(data) {
if (!data) return;
logTree.value = getLogTree(data); logTree.value = getLogTree(data);
} }

View File

@ -0,0 +1,85 @@
<script setup>
import { computed, useAttrs } from 'vue';
import VnSelect from 'components/common/VnSelect.vue';
import VnAvatar from 'src/components/ui/VnAvatar.vue';
const emit = defineEmits(['update:modelValue']);
const $props = defineProps({
hasAvatar: {
type: Boolean,
default: false,
},
hasInfo: {
type: Boolean,
default: false,
},
modelValue: {
type: [String, Number, Object],
default: null,
},
});
const $attrs = useAttrs();
const value = computed({
get() {
return $props.modelValue;
},
set(val) {
emit('update:modelValue', val);
},
});
const url = computed(() => {
let url = 'Workers/search';
const { departmentCodes } = $attrs.params ?? {};
if (!departmentCodes) return url;
const params = new URLSearchParams({
departmentCodes: JSON.stringify(departmentCodes),
});
return url.concat(`?${params.toString()}`);
});
</script>
<template>
<VnSelect
:label="$t('globals.worker')"
v-bind="$attrs"
v-model="value"
:url="url"
option-value="id"
option-label="nickname"
:fields="['id', 'name', 'nickname', 'code']"
sort-by="nickname ASC"
>
<template #prepend v-if="$props.hasAvatar">
<VnAvatar :worker-id="value" color="primary" :title="title" />
</template>
<template #append v-if="$props.hasInfo">
<QIcon name="info" class="cursor-pointer">
<QTooltip>{{ $t($props.hasInfo) }}</QTooltip>
</QIcon>
</template>
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection>
<QItemLabel>
{{ scope.opt.name }}
</QItemLabel>
<QItemLabel v-if="!scope.opt.id">
{{ scope.opt.nickname }}
</QItemLabel>
<QItemLabel caption v-else>
{{ scope.opt.nickname }}, {{ scope.opt.code }}
</QItemLabel>
</QItemSection>
</QItem>
</template>
</VnSelect>
</template>
<i18n>
es:
Responsible for approving invoices: Responsable de aprobar las facturas
</i18n>

View File

@ -222,8 +222,8 @@ const toModule = computed(() =>
/> />
</template> </template>
<style lang="scss"> <style lang="scss" scoped>
.body { :deep(.body) {
background-color: var(--vn-section-color); background-color: var(--vn-section-color);
.text-h5 { .text-h5 {
font-size: 20px; font-size: 20px;
@ -262,9 +262,7 @@ const toModule = computed(() =>
} }
} }
} }
</style>
<style lang="scss" scoped>
.title { .title {
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;

View File

@ -61,6 +61,7 @@ const emit = defineEmits([
'update:modelValue', 'update:modelValue',
'refresh', 'refresh',
'clear', 'clear',
'search',
'init', 'init',
'remove', 'remove',
'setUserParams', 'setUserParams',

73
src/composables/useCau.js Normal file
View File

@ -0,0 +1,73 @@
import VnInput from 'src/components/common/VnInput.vue';
import { useVnConfirm } from 'src/composables/useVnConfirm';
import axios from 'axios';
import { ref } from 'vue';
import { i18n } from 'src/boot/i18n';
import useNotify from 'src/composables/useNotify.js';
export async function useCau(res, message) {
const { notify } = useNotify();
const { openConfirmationModal } = useVnConfirm();
const { config, headers, request, status, statusText, data } = res || {};
const { params, url, method, signal, headers: confHeaders } = config || {};
const { message: resMessage, code, name } = data?.error || {};
const additionalData = {
path: location.hash,
message: resMessage,
code,
request: request?.responseURL,
status,
name,
statusText: statusText,
config: {
url,
method,
params,
headers: confHeaders,
aborted: signal?.aborted,
version: headers?.['salix-version'],
},
};
const opts = {
actions: [
{
icon: 'support_agent',
color: 'primary',
dense: true,
flat: false,
round: true,
handler: async () => {
const locale = i18n.global.t;
const reason = ref(
code == 'ACCESS_DENIED' ? locale('cau.askPrivileges') : ''
);
openConfirmationModal(
locale('cau.title'),
locale('cau.subtitle'),
async () => {
await axios.post('OsTickets/send-to-support', {
reason: reason.value,
additionalData,
});
},
null,
{
component: VnInput,
props: {
modelValue: reason,
'onUpdate:modelValue': (val) => (reason.value = val),
label: locale('cau.inputLabel'),
class: 'full-width',
required: true,
autofocus: true,
},
}
);
},
},
],
};
notify(message ?? 'globals.error', 'negative', 'error', opts);
}

View File

@ -2,7 +2,7 @@ import { Notify } from 'quasar';
import { i18n } from 'src/boot/i18n'; import { i18n } from 'src/boot/i18n';
export default function useNotify() { export default function useNotify() {
const notify = (message, type, icon) => { const notify = (message, type, icon, opts = {}) => {
const defaultIcons = { const defaultIcons = {
warning: 'warning', warning: 'warning',
negative: 'error', negative: 'error',
@ -13,6 +13,7 @@ export default function useNotify() {
message: i18n.global.t(message), message: i18n.global.t(message),
type: type, type: type,
icon: icon ? icon : defaultIcons[type], icon: icon ? icon : defaultIcons[type],
...opts,
}); });
}; };

View File

@ -1,20 +1,27 @@
import { h } from 'vue';
import { Dialog } from 'quasar';
import VnConfirm from 'components/ui/VnConfirm.vue'; import VnConfirm from 'components/ui/VnConfirm.vue';
import { useQuasar } from 'quasar';
export function useVnConfirm() { export function useVnConfirm() {
const quasar = useQuasar(); const openConfirmationModal = (
title,
const openConfirmationModal = (title, message, promise, successFn) => { message,
quasar promise,
.dialog({ successFn,
component: VnConfirm, customHTML = {}
componentProps: { ) => {
const { component, props } = customHTML;
Dialog.create({
component: h(
VnConfirm,
{
title: title, title: title,
message: message, message: message,
promise: promise, promise: promise,
}, },
}) { customHTML: () => h(component, props) }
.onOk(async () => { ),
}).onOk(async () => {
if (successFn) successFn(); if (successFn) successFn();
}); });
}; };

View File

@ -129,6 +129,7 @@ globals:
small: Small small: Small
medium: Medium medium: Medium
big: Big big: Big
email: Email
pageTitles: pageTitles:
logIn: Login logIn: Login
addressEdit: Update address addressEdit: Update address
@ -329,6 +330,7 @@ globals:
email: Email email: Email
SSN: SSN SSN: SSN
fi: FI fi: FI
packing: ITP
myTeam: My team myTeam: My team
departmentFk: Department departmentFk: Department
countryFk: Country countryFk: Country
@ -369,6 +371,11 @@ resetPassword:
repeatPassword: Repeat password repeatPassword: Repeat password
passwordNotMatch: Passwords don't match passwordNotMatch: Passwords don't match
passwordChanged: Password changed passwordChanged: Password changed
cau:
title: Send cau
subtitle: By sending this ticket, all the data related to the error, the section, the user, etc., are already sent.
inputLabel: Explain why this error should not appear
askPrivileges: Ask for privileges
entry: entry:
list: list:
newEntry: New entry newEntry: New entry
@ -398,8 +405,8 @@ entry:
buys: Buys buys: Buys
stickers: Stickers stickers: Stickers
package: Package package: Package
packing: Packing packing: Pack.
grouping: Grouping grouping: Group.
buyingValue: Buying value buyingValue: Buying value
import: Import import: Import
pvp: PVP pvp: PVP

View File

@ -131,6 +131,7 @@ globals:
small: Pequeño/a small: Pequeño/a
medium: Mediano/a medium: Mediano/a
big: Grande big: Grande
email: Correo
pageTitles: pageTitles:
logIn: Inicio de sesión logIn: Inicio de sesión
addressEdit: Modificar consignatario addressEdit: Modificar consignatario
@ -335,6 +336,7 @@ globals:
SSN: NSS SSN: NSS
fi: NIF fi: NIF
myTeam: Mi equipo myTeam: Mi equipo
packing: ITP
countryFk: País countryFk: País
changePass: Cambiar contraseña changePass: Cambiar contraseña
deleteConfirmTitle: Eliminar los elementos seleccionados deleteConfirmTitle: Eliminar los elementos seleccionados
@ -371,6 +373,11 @@ resetPassword:
repeatPassword: Repetir contraseña repeatPassword: Repetir contraseña
passwordNotMatch: Las contraseñas no coinciden passwordNotMatch: Las contraseñas no coinciden
passwordChanged: Contraseña cambiada passwordChanged: Contraseña cambiada
cau:
title: Enviar cau
subtitle: Al enviar este cau ya se envían todos los datos relacionados con el error, la sección, el usuario, etc
inputLabel: Explique el motivo por el que no deberia aparecer este fallo
askPrivileges: Solicitar permisos
entry: entry:
list: list:
newEntry: Nueva entrada newEntry: Nueva entrada
@ -401,8 +408,8 @@ entry:
buys: Compras buys: Compras
stickers: Etiquetas stickers: Etiquetas
package: Embalaje package: Embalaje
packing: Packing packing: Pack.
grouping: Grouping grouping: Group.
buyingValue: Coste buyingValue: Coste
import: Importe import: Importe
pvp: PVP pvp: PVP

View File

@ -1,50 +1,10 @@
<script setup> <script setup>
import { useQuasar } from 'quasar';
import Navbar from 'src/components/NavBar.vue'; import Navbar from 'src/components/NavBar.vue';
import { useRouter } from 'vue-router';
import routes from 'src/router/modules';
import { onMounted } from 'vue';
const quasar = useQuasar();
onMounted(() => {
let isNotified = false;
const router = useRouter();
const keyBindingMap = routes
.filter((route) => route.meta.keyBinding)
.reduce((map, route) => {
map['Key' + route.meta.keyBinding.toUpperCase()] = route.path;
return map;
}, {});
const handleKeyDown = (event) => {
const { ctrlKey, altKey, code } = event;
if (ctrlKey && altKey && keyBindingMap[code] && !isNotified) {
event.preventDefault();
router.push(keyBindingMap[code]);
isNotified = true;
}
};
const handleKeyUp = (event) => {
const { ctrlKey, altKey } = event;
if (!ctrlKey || !altKey) {
isNotified = false;
}
};
window.addEventListener('keydown', handleKeyDown);
window.addEventListener('keyup', handleKeyUp);
});
</script> </script>
<template> <template>
<QLayout view="hHh LpR fFf" v-shortcut> <QLayout view="hHh LpR fFf" v-shortcut>
<Navbar /> <Navbar />
<RouterView></RouterView> <RouterView></RouterView>
<QFooter v-if="quasar.platform.is.mobile"></QFooter> <QFooter v-if="$q.platform.is.mobile"></QFooter>
</QLayout> </QLayout>
</template> </template>

View File

@ -31,7 +31,6 @@ const rolesOptions = ref([]);
<VnFilterPanel <VnFilterPanel
:data-key="props.dataKey" :data-key="props.dataKey"
:search-button="true" :search-button="true"
:hidden-tags="['search']"
:redirect="false" :redirect="false"
search-url="table" search-url="table"
> >

View File

@ -7,6 +7,7 @@ import AccountSummary from './Card/AccountSummary.vue';
import { useSummaryDialog } from 'src/composables/useSummaryDialog'; import { useSummaryDialog } from 'src/composables/useSummaryDialog';
import AccountFilter from './AccountFilter.vue'; import AccountFilter from './AccountFilter.vue';
import RightMenu from 'src/components/common/RightMenu.vue'; import RightMenu from 'src/components/common/RightMenu.vue';
import VnInput from 'src/components/common/VnInput.vue';
const { t } = useI18n(); const { t } = useI18n();
const { viewSummary } = useSummaryDialog(); const { viewSummary } = useSummaryDialog();
const tableRef = ref(); const tableRef = ref();
@ -22,10 +23,27 @@ const columns = computed(() => [
field: 'id', field: 'id',
cardVisible: true, cardVisible: true,
}, },
{
align: 'left',
name: 'name',
label: t('Name'),
component: 'input',
columnField: {
component: null,
},
cardVisible: true,
create: true,
},
{ {
align: 'left', align: 'left',
name: 'roleFk', name: 'roleFk',
label: t('role'), label: t('Role'),
component: 'select',
attrs: {
url: 'VnRoles',
optionValue: 'id',
optionLabel: 'name',
},
columnFilter: { columnFilter: {
component: 'select', component: 'select',
name: 'roleFk', name: 'roleFk',
@ -35,7 +53,11 @@ const columns = computed(() => [
optionLabel: 'name', optionLabel: 'name',
}, },
}, },
columnField: {
component: null,
},
format: ({ role }, dashIfEmpty) => dashIfEmpty(role?.name), format: ({ role }, dashIfEmpty) => dashIfEmpty(role?.name),
create: true,
}, },
{ {
align: 'left', align: 'left',
@ -51,20 +73,32 @@ const columns = computed(() => [
}, },
{ {
align: 'left', align: 'left',
name: 'name', name: 'email',
label: t('Name'), label: t('Email'),
component: 'input', component: 'input',
columnField: { columnField: {
component: null, component: null,
}, },
cardVisible: true,
create: true, create: true,
visible: false,
}, },
{ {
align: 'left', align: 'left',
name: 'email', name: 'password',
label: t('email'), label: t('Password'),
component: 'input', columnField: {
component: null,
},
attrs: {},
required: true,
visible: false,
},
{
align: 'left',
name: 'active',
label: t('Active'),
component: 'checkbox',
create: true, create: true,
visible: false, visible: false,
}, },
@ -101,7 +135,6 @@ const exprBuilder = (param, value) => {
} }
}; };
</script> </script>
<template> <template>
<VnSearchbar <VnSearchbar
data-key="AccountList" data-key="AccountList"
@ -119,6 +152,12 @@ const exprBuilder = (param, value) => {
ref="tableRef" ref="tableRef"
data-key="AccountList" data-key="AccountList"
url="VnUsers/preview" url="VnUsers/preview"
:create="{
urlCreate: 'VnUsers',
title: t('Create user'),
onDataSaved: ({ id }) => tableRef.redirect(id),
formInitialData: {},
}"
:filter="filter" :filter="filter"
order="id DESC" order="id DESC"
:columns="columns" :columns="columns"
@ -127,7 +166,19 @@ const exprBuilder = (param, value) => {
:use-model="true" :use-model="true"
:right-search="false" :right-search="false"
auto-load auto-load
>
<template #more-create-dialog="{ data }">
<QCardSection>
<VnInput
:label="t('Password')"
v-model="data.password"
type="password"
:required="true"
autocomplete="new-password"
/> />
</QCardSection>
</template>
</VnTable>
</template> </template>
<i18n> <i18n>
@ -135,4 +186,7 @@ const exprBuilder = (param, value) => {
Id: Id Id: Id
Nickname: Nickname Nickname: Nickname
Name: Nombre Name: Nombre
Password: Contraseña
Active: Activo
Role: Rol
</i18n> </i18n>

View File

@ -37,11 +37,7 @@ onBeforeMount(() => {
@on-fetch="(data) => (rolesOptions = data)" @on-fetch="(data) => (rolesOptions = data)"
auto-load auto-load
/> />
<VnFilterPanel <VnFilterPanel :data-key="props.dataKey" :search-button="true">
:data-key="props.dataKey"
:search-button="true"
:hidden-tags="['search']"
>
<template #tags="{ tag, formatFn }"> <template #tags="{ tag, formatFn }">
<div class="q-gutter-x-xs"> <div class="q-gutter-x-xs">
<strong>{{ t(`acls.aclFilter.${tag.label}`) }}: </strong> <strong>{{ t(`acls.aclFilter.${tag.label}`) }}: </strong>

View File

@ -13,12 +13,7 @@ const props = defineProps({
</script> </script>
<template> <template>
<VnFilterPanel <VnFilterPanel :data-key="props.dataKey" :search-button="true" :redirect="false">
:data-key="props.dataKey"
:search-button="true"
:hidden-tags="['search']"
:redirect="false"
>
<template #tags="{ tag, formatFn }"> <template #tags="{ tag, formatFn }">
<div class="q-gutter-x-xs"> <div class="q-gutter-x-xs">
<strong>{{ t(`role.${tag.label}`) }}: </strong> <strong>{{ t(`role.${tag.label}`) }}: </strong>

View File

@ -8,7 +8,7 @@ import FormModel from 'components/FormModel.vue';
import VnRow from 'components/ui/VnRow.vue'; import VnRow from 'components/ui/VnRow.vue';
import VnInput from 'src/components/common/VnInput.vue'; import VnInput from 'src/components/common/VnInput.vue';
import VnSelect from 'src/components/common/VnSelect.vue'; import VnSelect from 'src/components/common/VnSelect.vue';
import VnAvatar from 'src/components/ui/VnAvatar.vue'; import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
import { getDifferences, getUpdatedValues } from 'src/filters'; import { getDifferences, getUpdatedValues } from 'src/filters';
const route = useRoute(); const route = useRoute();
@ -16,7 +16,6 @@ const { t } = useI18n();
const businessTypes = ref([]); const businessTypes = ref([]);
const contactChannels = ref([]); const contactChannels = ref([]);
const title = ref();
const handleSalesModelValue = (val) => ({ const handleSalesModelValue = (val) => ({
or: [ or: [
{ id: val }, { id: val },
@ -117,41 +116,17 @@ function onBeforeSave(formData, originalData) {
/> />
</VnRow> </VnRow>
<VnRow> <VnRow>
<VnSelect <VnSelectWorker
url="Workers/search"
v-model="data.salesPersonFk"
:label="t('customer.summary.salesPerson')" :label="t('customer.summary.salesPerson')"
v-model="data.salesPersonFk"
:params="{ :params="{
departmentCodes: ['VT', 'shopping'], departmentCodes: ['VT', 'shopping'],
}" }"
:fields="['id', 'nickname']" :has-avatar="true"
sort-by="nickname ASC"
option-label="nickname"
option-value="id"
:rules="validate('client.salesPersonFk')" :rules="validate('client.salesPersonFk')"
:expr-builder="exprBuilder" :expr-builder="exprBuilder"
emit-value emit-value
auto-load
>
<template #prepend>
<VnAvatar
:worker-id="data.salesPersonFk"
color="primary"
:title="title"
/> />
</template>
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection>
<QItemLabel>{{ scope.opt?.name }}</QItemLabel>
<QItemLabel caption
>{{ scope.opt?.nickname }},
{{ scope.opt?.code }}</QItemLabel
>
</QItemSection>
</QItem>
</template>
</VnSelect>
<VnSelect <VnSelect
v-model="data.contactChannelFk" v-model="data.contactChannelFk"
:options="contactChannels" :options="contactChannels"

View File

@ -3,6 +3,7 @@ import { useI18n } from 'vue-i18n';
import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue'; import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
import VnSelect from 'components/common/VnSelect.vue'; import VnSelect from 'components/common/VnSelect.vue';
import VnInput from 'src/components/common/VnInput.vue'; import VnInput from 'src/components/common/VnInput.vue';
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
const { t } = useI18n(); const { t } = useI18n();
defineProps({ defineProps({
@ -65,19 +66,14 @@ const exprBuilder = (param, value) => {
</QItem> </QItem>
<QItem class="q-mb-sm"> <QItem class="q-mb-sm">
<QItemSection> <QItemSection>
<VnSelect <VnSelectWorker
url="Workers/search" :label="t('Salesperson')"
v-model="params.salesPersonFk"
:params="{ :params="{
departmentCodes: ['VT'], departmentCodes: ['VT'],
}" }"
auto-load
:label="t('Salesperson')"
:expr-builder="exprBuilder" :expr-builder="exprBuilder"
v-model="params.salesPersonFk"
@update:model-value="searchFn()" @update:model-value="searchFn()"
option-value="id"
option-label="name"
sort-by="nickname ASC"
emit-value emit-value
map-options map-options
use-input use-input
@ -86,18 +82,7 @@ const exprBuilder = (param, value) => {
outlined outlined
rounded rounded
:input-debounce="0" :input-debounce="0"
> />
<template #option="{ itemProps, opt }">
<QItem v-bind="itemProps">
<QItemSection>
<QItemLabel>{{ opt.name }}</QItemLabel>
<QItemLabel caption>
{{ opt.nickname }},{{ opt.code }}
</QItemLabel>
</QItemSection>
</QItem>
</template></VnSelect
>
</QItemSection> </QItemSection>
</QItem> </QItem>
<QItem class="q-mb-sm"> <QItem class="q-mb-sm">

View File

@ -2,7 +2,6 @@
import { ref, computed, markRaw } from 'vue'; import { ref, computed, markRaw } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import VnSelect from 'src/components/common/VnSelect.vue';
import VnTable from 'components/VnTable/VnTable.vue'; import VnTable from 'components/VnTable/VnTable.vue';
import VnLocation from 'src/components/common/VnLocation.vue'; import VnLocation from 'src/components/common/VnLocation.vue';
import VnSearchbar from 'components/ui/VnSearchbar.vue'; import VnSearchbar from 'components/ui/VnSearchbar.vue';
@ -12,7 +11,7 @@ import RightMenu from 'src/components/common/RightMenu.vue';
import VnLinkPhone from 'src/components/ui/VnLinkPhone.vue'; import VnLinkPhone from 'src/components/ui/VnLinkPhone.vue';
import { toDate } from 'src/filters'; import { toDate } from 'src/filters';
import CustomerFilter from './CustomerFilter.vue'; import CustomerFilter from './CustomerFilter.vue';
import VnAvatar from 'src/components/ui/VnAvatar.vue'; import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
const { t } = useI18n(); const { t } = useI18n();
const router = useRouter(); const router = useRouter();
@ -422,40 +421,17 @@ function handleLocation(data, location) {
auto-load auto-load
> >
<template #more-create-dialog="{ data }"> <template #more-create-dialog="{ data }">
<VnSelect <VnSelectWorker
url="Workers/search"
v-model="data.salesPersonFk"
:label="t('customer.summary.salesPerson')" :label="t('customer.summary.salesPerson')"
v-model="data.salesPersonFk"
:params="{ :params="{
departmentCodes: ['VT', 'shopping'], departmentCodes: ['VT', 'shopping'],
}" }"
:fields="['id', 'nickname', 'code']" :has-avatar="true"
sort-by="nickname ASC" :id-value="data.salesPersonFk"
option-label="nickname"
option-value="id"
emit-value emit-value
auto-load auto-load
>
<template #prepend>
<VnAvatar
:worker-id="data.salesPersonFk"
color="primary"
:title="title"
/> />
</template>
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection>
<QItemLabel>{{ scope.opt?.name }}</QItemLabel>
<QItemLabel caption
>{{ scope.opt?.nickname }},
{{ scope.opt?.code }}</QItemLabel
>
</QItemSection>
</QItem>
</template>
</VnSelect>
<VnLocation <VnLocation
:acls="[{ model: 'Province', props: '*', accessType: 'WRITE' }]" :acls="[{ model: 'Province', props: '*', accessType: 'WRITE' }]"
v-model="data.location" v-model="data.location"

View File

@ -6,6 +6,7 @@ import FormModel from 'components/FormModel.vue';
import VnRow from 'components/ui/VnRow.vue'; import VnRow from 'components/ui/VnRow.vue';
import VnInput from 'src/components/common/VnInput.vue'; import VnInput from 'src/components/common/VnInput.vue';
import VnSelect from 'src/components/common/VnSelect.vue'; import VnSelect from 'src/components/common/VnSelect.vue';
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
const route = useRoute(); const route = useRoute();
const { t } = useI18n(); const { t } = useI18n();
@ -48,14 +49,9 @@ const { t } = useI18n();
/> />
</VnRow> </VnRow>
<VnRow> <VnRow>
<VnSelect <VnSelectWorker
:label="t('department.bossDepartment')" :label="t('department.bossDepartment')"
v-model="data.workerFk" v-model="data.workerFk"
url="Workers/search"
option-value="id"
option-label="name"
hide-selected
map-options
:rules="validate('department.workerFk')" :rules="validate('department.workerFk')"
/> />
<VnSelect <VnSelect

View File

@ -83,7 +83,7 @@ const { openConfirmationModal } = useVnConfirm();
</template> </template>
<template #body="{ entity }"> <template #body="{ entity }">
<VnLv :label="t('department.chat')" :value="entity.chatName" /> <VnLv :label="t('department.chat')" :value="entity.chatName" />
<VnLv :label="t('department.email')" :value="entity.notificationEmail" copy /> <VnLv :label="t('globals.email')" :value="entity.notificationEmail" copy />
<VnLv <VnLv
:label="t('department.selfConsumptionCustomer')" :label="t('department.selfConsumptionCustomer')"
:value="entity.client?.name" :value="entity.client?.name"

View File

@ -58,7 +58,7 @@ onMounted(async () => {
dash dash
/> />
<VnLv <VnLv
:label="t('department.email')" :label="t('globals.email')"
:value="department.notificationEmail" :value="department.notificationEmail"
dash dash
/> />

View File

@ -2,12 +2,15 @@
import { ref, nextTick } from 'vue'; import { ref, nextTick } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import axios from 'axios';
import CrudModel from 'src/components/CrudModel.vue'; import CrudModel from 'src/components/CrudModel.vue';
import VnInput from 'src/components/common/VnInput.vue'; import VnInput from 'src/components/common/VnInput.vue';
import useNotify from 'src/composables/useNotify.js';
const route = useRoute(); const route = useRoute();
const { t } = useI18n(); const { t } = useI18n();
const { notify } = useNotify();
const itemBarcodeRef = ref(null); const itemBarcodeRef = ref(null);
@ -23,6 +26,24 @@ const focusLastInput = () => {
if (lastInput) lastInput.focus(); if (lastInput) lastInput.focus();
}); });
}; };
const removeRow = (row) => {
itemBarcodeRef.value.remove([row]);
};
const submit = async (rows) => {
const params = rows[rows.length - 1];
let { data } = await axios.get('ItemBarcodes');
const code = params.code;
if (data.some((codes) => codes.code === code)) {
notify(t('Codes can not be repeated'), 'negative');
itemBarcodeRef.value.reset();
return;
}
await axios.patch(`ItemBarcodes`, params);
notify(t('globals.dataSaved'), 'positive');
};
</script> </script>
<template> <template>
<div class="full-width flex justify-center"> <div class="full-width flex justify-center">
@ -39,6 +60,7 @@ const focusLastInput = () => {
ref="itemBarcodeRef" ref="itemBarcodeRef"
url="ItemBarcodes" url="ItemBarcodes"
auto-load auto-load
:save-fn="submit"
> >
<template #body="{ rows }"> <template #body="{ rows }">
<QCard class="q-px-lg q-py-md"> <QCard class="q-px-lg q-py-md">
@ -54,7 +76,7 @@ const focusLastInput = () => {
focusable-input focusable-input
/> />
<QIcon <QIcon
@click="itemBarcodeRef.remove([row])" @click="removeRow(row)"
class="cursor-pointer q-ml-md" class="cursor-pointer q-ml-md"
color="primary" color="primary"
name="delete" name="delete"
@ -89,4 +111,5 @@ es:
Code: Código Code: Código
Remove barcode: Quitar código de barras Remove barcode: Quitar código de barras
Add barcode: Añadir código de barras Add barcode: Añadir código de barras
Codes can not be repeated: Los códigos no puden ser repetidos
</i18n> </i18n>

View File

@ -70,6 +70,7 @@ const onIntrastatCreated = (response, formData) => {
option-label="name" option-label="name"
hide-selected hide-selected
map-options map-options
required
> >
<template #option="scope"> <template #option="scope">
<QItem v-bind="scope.itemProps"> <QItem v-bind="scope.itemProps">

View File

@ -16,7 +16,7 @@ import { cloneItem } from 'src/pages/Item/composables/cloneItem';
const $props = defineProps({ const $props = defineProps({
id: { id: {
type: Number, type: [Number, String],
required: false, required: false,
default: null, default: null,
}, },
@ -29,7 +29,7 @@ const $props = defineProps({
default: null, default: null,
}, },
saleFk: { saleFk: {
type: Number, type: [Number, String],
default: null, default: null,
}, },
warehouseFk: { warehouseFk: {
@ -61,7 +61,7 @@ onMounted(async () => {
const data = ref(useCardDescription()); const data = ref(useCardDescription());
const setData = async (entity) => { const setData = async (entity) => {
if (!entity) return; if (!entity) return;
data.value = useCardDescription(entity.name, entity.id); data.value = useCardDescription(entity?.name, entity?.id);
await updateStock(); await updateStock();
}; };

View File

@ -16,7 +16,7 @@ const $props = defineProps({
default: null, default: null,
}, },
entityId: { entityId: {
type: String, type: [String, Number],
default: null, default: null,
}, },
showEditButton: { showEditButton: {
@ -67,7 +67,7 @@ const handlePhotoUpdated = (evt = false) => {
<template> <template>
<div class="relative-position"> <div class="relative-position">
<VnImg ref="image" :id="$props.entityId" zoom-resolution="1600x900"> <VnImg ref="image" :id="parseInt($props.entityId)" zoom-resolution="1600x900">
<template #error> <template #error>
<div class="absolute-full picture text-center q-pa-md flex flex-center"> <div class="absolute-full picture text-center q-pa-md flex flex-center">
<div> <div>

View File

@ -1,21 +1,30 @@
<script setup> <script setup>
import { onMounted, computed, onUnmounted, ref, watch } from 'vue'; import { onMounted, computed, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { dateRange } from 'src/filters'; import { dateRange } from 'src/filters';
import EntryDescriptorProxy from 'src/pages/Entry/Card/EntryDescriptorProxy.vue'; import EntryDescriptorProxy from 'src/pages/Entry/Card/EntryDescriptorProxy.vue';
import VnInputDate from 'src/components/common/VnInputDate.vue'; import VnInputDate from 'src/components/common/VnInputDate.vue';
import VnDateBadge from 'src/components/common/VnDateBadge.vue';
import { useStateStore } from 'stores/useStateStore';
import { toDateTimeFormat } from 'src/filters/date.js';
import { dashIfEmpty } from 'src/filters'; import { dashIfEmpty } from 'src/filters';
import { toCurrency } from 'filters/index'; import { toCurrency } from 'filters/index';
import { useArrayData } from 'composables/useArrayData'; import { useArrayData } from 'composables/useArrayData';
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue'; import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
import axios from 'axios';
import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue';
const { t } = useI18n(); const { t } = useI18n();
const route = useRoute(); const route = useRoute();
const stateStore = useStateStore(); const from = ref();
const to = ref();
const hideInventory = ref(true);
const inventorySupplierFk = ref();
async function getInventorySupplier() {
inventorySupplierFk.value = (
await axios.get(`InventoryConfigs`)
)?.data[0]?.supplierFk;
}
const exprBuilder = (param, value) => { const exprBuilder = (param, value) => {
switch (param) { switch (param) {
@ -36,25 +45,27 @@ const exprBuilder = (param, value) => {
} }
}; };
const from = ref(); const where = {
const to = ref(); itemFk: route.params.id,
};
if (hideInventory.value) {
where.supplierFk = { neq: inventorySupplierFk };
}
const arrayData = useArrayData('ItemLastEntries', { const arrayData = useArrayData('ItemLastEntries', {
url: 'Items/lastEntriesFilter', url: 'Items/lastEntriesFilter',
order: ['landed DESC', 'buyFk DESC'], order: ['landed DESC', 'buyFk DESC'],
exprBuilder: exprBuilder, exprBuilder: exprBuilder,
userFilter: { userFilter: {
where: { where: where,
itemFk: route.params.id,
},
}, },
}); });
const itemLastEntries = ref([]); const itemLastEntries = ref([]);
const columns = computed(() => [ const columns = computed(() => [
{ {
label: t('lastEntries.ig'), label: 'Nv',
name: 'ig', name: 'ig',
align: 'center', align: 'center',
}, },
@ -62,33 +73,38 @@ const columns = computed(() => [
label: t('itemDiary.warehouse'), label: t('itemDiary.warehouse'),
name: 'warehouse', name: 'warehouse',
field: 'warehouse', field: 'warehouse',
align: 'left', align: 'center',
}, },
{ {
label: t('lastEntries.landed'), label: t('lastEntries.landed'),
name: 'id', name: 'date',
field: 'landed', field: 'landed',
align: 'left', align: 'center',
format: (val) => toDateTimeFormat(val),
}, },
{ {
label: t('lastEntries.entry'), label: t('lastEntries.entry'),
name: 'entry', name: 'entry',
field: 'stateName', field: 'stateName',
align: 'left', align: 'center',
format: (val) => dashIfEmpty(val), format: (val) => dashIfEmpty(val),
}, },
{ {
label: t('lastEntries.pvp'), label: t('lastEntries.pvp'),
name: 'pvp', name: 'pvp',
field: 'reference', field: 'reference',
align: 'left', align: 'center',
format: (_, row) => toCurrency(row.price2) + ' / ' + toCurrency(row.price3), format: (_, row) => toCurrency(row.price2) + ' / ' + toCurrency(row.price3),
}, },
{
label: t('lastEntries.printedStickers'),
name: 'printedStickers',
field: 'printedStickers',
align: 'center',
format: (val) => dashIfEmpty(val),
},
{ {
label: t('lastEntries.label'), label: t('lastEntries.label'),
name: 'label', name: 'stickers',
field: 'stickers', field: 'stickers',
align: 'center', align: 'center',
format: (val) => dashIfEmpty(val), format: (val) => dashIfEmpty(val),
@ -96,11 +112,13 @@ const columns = computed(() => [
{ {
label: t('shelvings.packing'), label: t('shelvings.packing'),
name: 'packing', name: 'packing',
field: 'packing',
align: 'center', align: 'center',
}, },
{ {
label: t('lastEntries.grouping'), label: t('lastEntries.grouping'),
name: 'grouping', name: 'grouping',
field: 'grouping',
align: 'center', align: 'center',
}, },
{ {
@ -111,18 +129,19 @@ const columns = computed(() => [
}, },
{ {
label: t('lastEntries.quantity'), label: t('lastEntries.quantity'),
name: 'stems', name: 'quantity',
field: 'quantity', field: 'quantity',
align: 'center', align: 'center',
}, },
{ {
label: t('lastEntries.cost'), label: t('lastEntries.cost'),
name: 'cost', name: 'cost',
align: 'left', field: 'cost',
align: 'center',
}, },
{ {
label: t('lastEntries.kg'), label: 'Kg',
name: 'stems', name: 'weight',
field: 'weight', field: 'weight',
align: 'center', align: 'center',
}, },
@ -134,9 +153,9 @@ const columns = computed(() => [
}, },
{ {
label: t('lastEntries.supplier'), label: t('lastEntries.supplier'),
name: 'stems', name: 'supplier',
field: 'supplier', field: 'supplier',
align: 'left', align: 'center',
}, },
]); ]);
@ -160,11 +179,18 @@ const updateFilter = async () => {
else if (from.value && !to.value) filter = { gte: from.value }; else if (from.value && !to.value) filter = { gte: from.value };
else if (from.value && to.value) filter = { between: [from.value, to.value] }; else if (from.value && to.value) filter = { between: [from.value, to.value] };
arrayData.store.userFilter.where.landed = filter; const userFilter = arrayData.store.userFilter.where;
userFilter.landed = filter;
if (hideInventory.value) userFilter.supplierFk = { neq: inventorySupplierFk };
else delete userFilter.supplierFk;
await fetchItemLastEntries(); await fetchItemLastEntries();
}; };
onMounted(async () => { onMounted(async () => {
await getInventorySupplier();
const _from = Date.vnNew(); const _from = Date.vnNew();
_from.setDate(_from.getDate() - 75); _from.setDate(_from.getDate() - 75);
from.value = getDate(_from, 'from'); from.value = getDate(_from, 'from');
@ -174,16 +200,13 @@ onMounted(async () => {
updateFilter(); updateFilter();
watch([from, to], ([nFrom, nTo], [oFrom, oTo]) => { watch([from, to, hideInventory], ([nFrom, nTo], [oFrom, oTo]) => {
if (nFrom && nFrom != oFrom) nFrom = getDate(new Date(nFrom), 'from'); if (nFrom && nFrom != oFrom) nFrom = getDate(new Date(nFrom), 'from');
if (nTo && nTo != oTo) nTo = getDate(new Date(nTo), 'to'); if (nTo && nTo != oTo) nTo = getDate(new Date(nTo), 'to');
updateFilter(); updateFilter();
}); });
}); });
onUnmounted(() => (stateStore.rightDrawer = false));
</script> </script>
<template> <template>
<VnSubToolbar> <VnSubToolbar>
<template #st-data> <template #st-data>
@ -192,27 +215,45 @@ onUnmounted(() => (stateStore.rightDrawer = false));
dense dense
v-model="from" v-model="from"
class="q-mr-lg" class="q-mr-lg"
data-cy="from"
/>
<VnInputDate
:label="t('lastEntries.to')"
v-model="to"
dense
class="q-mr-lg"
data-cy="to"
/>
<QCheckbox
:label="t('Hide inventory supplier')"
v-model="hideInventory"
dense
class="q-mr-lg"
data-cy="hideInventory"
/> />
<VnInputDate :label="t('lastEntries.to')" dense v-model="to" />
</template> </template>
</VnSubToolbar> </VnSubToolbar>
<QPage class="column items-center q-pa-xd"> <QPage class="column items-center q-pa-xd">
<QTable <QTable
:rows="itemLastEntries" :rows="itemLastEntries"
:columns="columns" :columns="columns"
class="full-width q-mt-md" class="table full-width q-mt-md"
:no-data-label="t('globals.noResults')" :no-data-label="t('globals.noResults')"
> >
<template #body-cell-ig="{ row }"> <template #body-cell-ig="{ row }">
<QTd @click.stop> <QTd class="text-center">
<QCheckbox <QIcon
v-model="row.isIgnored" :name="row.isIgnored ? 'check_box' : 'check_box_outline_blank'"
:disable="true" style="color: var(--vn-label-color)"
:false-value="0" size="sm"
:true-value="1"
/> />
</QTd> </QTd>
</template> </template>
<template #body-cell-date="{ row }">
<QTd class="text-center">
<VnDateBadge :date="row.landed" />
</QTd>
</template>
<template #body-cell-entry="{ row }"> <template #body-cell-entry="{ row }">
<QTd @click.stop> <QTd @click.stop>
<div class="full-width flex justify-center"> <div class="full-width flex justify-center">
@ -234,8 +275,8 @@ onUnmounted(() => (stateStore.rightDrawer = false));
</QTd> </QTd>
</template> </template>
<template #body-cell-pvp="{ value }"> <template #body-cell-pvp="{ value }">
<QTd @click.stop <QTd @click.stop class="text-center">
><span> {{ value }}</span> <span> {{ value }}</span>
<QTooltip> <QTooltip>
{{ t('lastEntries.grouping') }}/{{ t('lastEntries.packing') }} {{ t('lastEntries.grouping') }}/{{ t('lastEntries.packing') }}
</QTooltip></QTd </QTooltip></QTd
@ -254,7 +295,7 @@ onUnmounted(() => (stateStore.rightDrawer = false));
</QTd> </QTd>
</template> </template>
<template #body-cell-cost="{ row }"> <template #body-cell-cost="{ row }">
<QTd @click.stop> <QTd @click.stop class="text-center">
<span> <span>
{{ toCurrency(row.cost, 'EUR', 3) }} {{ toCurrency(row.cost, 'EUR', 3) }}
<QTooltip> <QTooltip>
@ -272,10 +313,25 @@ onUnmounted(() => (stateStore.rightDrawer = false));
</span> </span>
</QTd> </QTd>
</template> </template>
<template #body-cell-supplier="{ row }">
<QTd @click.stop>
<div class="full-width flex justify-center">
<SupplierDescriptorProxy
:id="row.supplierFk"
class="q-ma-none"
dense
/>
<span class="link">{{ row.supplier }}</span>
</div>
</QTd>
</template>
</QTable> </QTable>
</QPage> </QPage>
</template> </template>
<i18n>
es:
Hide inventory supplier: Ocultar proveedor inventario
</i18n>
<style lang="scss" scoped> <style lang="scss" scoped>
.q-badge--rounded { .q-badge--rounded {
border-radius: 50%; border-radius: 50%;
@ -287,4 +343,10 @@ onUnmounted(() => (stateStore.rightDrawer = false));
padding: 0 11px; padding: 0 11px;
height: 28px; height: 28px;
} }
.th :first-child {
.td {
text-align: center;
background-color: red;
}
}
</style> </style>

View File

@ -1,19 +1,15 @@
<script setup> <script setup>
import { onMounted, ref, computed, reactive } from 'vue'; import { onMounted, ref, computed, reactive, watchEffect } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import VnInput from 'src/components/common/VnInput.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue'; import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
import { toDateFormat } from 'src/filters/date.js'; import { toDateFormat } from 'src/filters/date.js';
import { dashIfEmpty } from 'src/filters';
import { useArrayData } from 'src/composables/useArrayData'; import { useArrayData } from 'src/composables/useArrayData';
import useNotify from 'src/composables/useNotify.js'; import useNotify from 'src/composables/useNotify.js';
import { useVnConfirm } from 'composables/useVnConfirm'; import { useVnConfirm } from 'composables/useVnConfirm';
import axios from 'axios'; import axios from 'axios';
import { useStateStore } from 'stores/useStateStore'; import { useStateStore } from 'stores/useStateStore';
import VnTable from 'src/components/VnTable/VnTable.vue';
const stateStore = useStateStore(); const stateStore = useStateStore();
@ -21,8 +17,9 @@ const route = useRoute();
const { t } = useI18n(); const { t } = useI18n();
const { notify } = useNotify(); const { notify } = useNotify();
const { openConfirmationModal } = useVnConfirm(); const { openConfirmationModal } = useVnConfirm();
const tableRef = ref();
const rowsSelected = ref([]); const selectedRows = ref([]);
const hasSelectedCards = computed(() => selectedRows.value.length > 0);
const exprBuilder = (param, value) => { const exprBuilder = (param, value) => {
switch (param) { switch (param) {
@ -36,6 +33,11 @@ const exprBuilder = (param, value) => {
}; };
const params = reactive({ itemFk: route.params.id }); const params = reactive({ itemFk: route.params.id });
const filter = reactive({
where: {
itemFk: route.params.id,
},
});
const arrayData = useArrayData('ItemShelvings', { const arrayData = useArrayData('ItemShelvings', {
url: 'ItemShelvingPlacementSupplyStocks', url: 'ItemShelvingPlacementSupplyStocks',
@ -44,58 +46,32 @@ const arrayData = useArrayData('ItemShelvings', {
}); });
const rows = computed(() => arrayData.store.data || []); const rows = computed(() => arrayData.store.data || []);
const applyColumnFilter = async (col) => {
const paramKey = col.columnFilter?.filterParamKey || col.field;
params[paramKey] = col.columnFilter.filterValue;
await arrayData.addFilter({ filter: null, params });
};
const getInputEvents = (col) => {
return col.columnFilter.type === 'select'
? { 'update:modelValue': () => applyColumnFilter(col) }
: {
'keyup.enter': () => applyColumnFilter(col),
};
};
const columns = computed(() => [ const columns = computed(() => [
{ {
label: t('shelvings.created'), label: t('shelvings.created'),
name: 'created', name: 'created',
field: 'created',
align: 'left', align: 'left',
sortable: true, columnFilter: false,
columnFilter: null, format: (row) => toDateFormat(row.created),
format: (val) => toDateFormat(val),
}, },
{ {
label: t('shelvings.item'), label: t('shelvings.item'),
name: 'item', name: 'itemFk',
field: 'itemFk',
align: 'left', align: 'left',
sortable: true, columnFilter: false,
columnFilter: null,
}, },
{ {
label: t('shelvings.concept'), label: t('shelvings.concept'),
name: 'concept', name: 'longName',
align: 'left', align: 'left',
sortable: true, columnFilter: false,
columnFilter: null,
}, },
{ {
label: t('shelvings.parking'), label: t('shelvings.parking'),
name: 'parking', name: 'parking',
field: 'parking',
align: 'left', align: 'left',
sortable: true, component: 'select',
format: (val) => dashIfEmpty(val),
columnFilter: {
component: VnSelect,
type: 'select',
filterValue: null,
event: getInputEvents,
attrs: { attrs: {
url: 'parkings', url: 'parkings',
fields: ['code'], fields: ['code'],
@ -104,20 +80,13 @@ const columns = computed(() => [
'option-label': 'code', 'option-label': 'code',
dense: true, dense: true,
}, },
}, columnField: { component: null },
}, },
{ {
label: t('shelvings.shelving'), label: t('shelvings.shelving'),
name: 'shelving', name: 'shelving',
field: 'shelving',
align: 'left', align: 'left',
sortable: true, component: 'select',
format: (val) => dashIfEmpty(val),
columnFilter: {
component: VnSelect,
type: 'select',
filterValue: null,
event: getInputEvents,
attrs: { attrs: {
url: 'shelvings', url: 'shelvings',
fields: ['code'], fields: ['code'],
@ -126,41 +95,20 @@ const columns = computed(() => [
'option-label': 'code', 'option-label': 'code',
dense: true, dense: true,
}, },
}, columnField: { component: null },
}, },
{ {
label: t('shelvings.label'), label: t('shelvings.label'),
name: 'label', name: 'label',
align: 'left', align: 'left',
sortable: true, columnFilter: { inWhere: true },
format: (_, row) => (row.stock / row.packing).toFixed(2), format: (row) => (row.stock / row.packing).toFixed(2),
columnFilter: {
component: VnInput,
type: 'text',
filterParamKey: 'label',
filterValue: null,
event: getInputEvents,
attrs: {
dense: true,
},
},
}, },
{ {
label: t('shelvings.packing'), label: t('shelvings.packing'),
field: 'packing',
name: 'packing', name: 'packing',
attrs: { inWhere: true },
align: 'left', align: 'left',
sortable: true,
columnFilter: {
component: VnInput,
type: 'text',
filterValue: null,
event: getInputEvents,
attrs: {
dense: true,
},
},
format: (val) => dashIfEmpty(val),
}, },
]); ]);
@ -169,15 +117,16 @@ const totalLabels = computed(() =>
); );
const removeLines = async () => { const removeLines = async () => {
const itemShelvingIds = rowsSelected.value.map((row) => row.itemShelvingFk); const itemShelvingIds = selectedRows.value.map((row) => row.itemShelvingFk);
await axios.post('ItemShelvings/deleteItemShelvings', { itemShelvingIds }); await axios.post('ItemShelvings/deleteItemShelvings', { itemShelvingIds });
rowsSelected.value = []; selectedRows.value = [];
notify('shelvings.shelvingsRemoved', 'positive'); notify('shelvings.shelvingsRemoved', 'positive');
await arrayData.fetch({ append: false }); await tableRef.value.reload();
}; };
onMounted(async () => { onMounted(async () => {
await arrayData.fetch({ append: false }); await arrayData.fetch({ append: false });
}); });
watchEffect(selectedRows);
</script> </script>
<template> <template>
@ -203,7 +152,7 @@ onMounted(async () => {
<QBtn <QBtn
color="primary" color="primary"
icon="delete" icon="delete"
:disabled="!rowsSelected.length" :disabled="!hasSelectedCards"
@click=" @click="
openConfirmationModal( openConfirmationModal(
t('shelvings.removeConfirmTitle'), t('shelvings.removeConfirmTitle'),
@ -219,41 +168,27 @@ onMounted(async () => {
</Teleport> </Teleport>
</template> </template>
<QPage class="column items-center q-pa-md"> <QPage class="column items-center q-pa-md">
<QTable <VnTable
:rows="rows" ref="tableRef"
data-key="ItemShelving"
:columns="columns" :columns="columns"
row-key="id" :url="`ItemShelvingPlacementSupplyStocks`"
:pagination="{ rowsPerPage: 0 }" :filter="filter"
class="full-width q-mt-md" :expr-builder="exprBuilder"
selection="multiple" :right-search="false"
v-model:selected="rowsSelected" v-model:selected="selectedRows"
:no-data-label="t('globals.noResults')" :table="{
'row-key': 'itemShelvingFk',
selection: 'multiple',
}"
auto-load
> >
<template #top-row="{ cols }"> <template #column-longName="{ row }">
<QTr> <span class="link" @click.stop>
<QTd /> {{ row.longName }}
<QTd
v-for="(col, index) in cols"
:key="index"
style="max-width: 100px"
>
<component
:is="col.columnFilter.component"
v-if="col.columnFilter"
v-model="col.columnFilter.filterValue"
v-bind="col.columnFilter.attrs"
v-on="col.columnFilter.event(col)"
dense
/>
</QTd>
</QTr>
</template>
<template #body-cell-concept="{ row }">
<QTd @click.stop>
<span class="link">{{ row.longName }}</span>
<ItemDescriptorProxy :id="row.itemFk" /> <ItemDescriptorProxy :id="row.itemFk" />
</QTd> </span>
</template> </template>
</QTable> </VnTable>
</QPage> </QPage>
</template> </template>

View File

@ -46,7 +46,7 @@ const getUrl = (id, param) => `#/Item/${id}/${param}`;
<template #body="{ entity: { item, tags, visible, available, botanical } }"> <template #body="{ entity: { item, tags, visible, available, botanical } }">
<QCard class="vn-one photo"> <QCard class="vn-one photo">
<ItemDescriptorImage <ItemDescriptorImage
:entity-id="entityId" :entity-id="Number(entityId)"
:visible="visible" :visible="visible"
:available="available" :available="available"
:show-edit-button="false" :show-edit-button="false"
@ -89,7 +89,7 @@ const getUrl = (id, param) => `#/Item/${id}/${param}`;
<QCard class="vn-one"> <QCard class="vn-one">
<VnTitle <VnTitle
:url="getUrl(entityId, 'basic-data')" :url="getUrl(entityId, 'basic-data')"
:text="t('item.summary.otherData')" :text="t('item.summary.basicData')"
/> />
<VnLv <VnLv
:label="t('item.summary.intrastatCode')" :label="t('item.summary.intrastatCode')"

View File

@ -8,7 +8,6 @@ import VnRow from 'components/ui/VnRow.vue';
import VnInput from 'src/components/common/VnInput.vue'; import VnInput from 'src/components/common/VnInput.vue';
import FetchData from 'components/FetchData.vue'; import FetchData from 'components/FetchData.vue';
import VnSelect from 'src/components/common/VnSelect.vue'; import VnSelect from 'src/components/common/VnSelect.vue';
import axios from 'axios'; import axios from 'axios';
const route = useRoute(); const route = useRoute();
@ -60,6 +59,10 @@ const insertTag = (rows) => {
itemTagsRef.value.formData[itemTagsRef.value.formData.length - 1].priority = itemTagsRef.value.formData[itemTagsRef.value.formData.length - 1].priority =
getHighestPriority(rows); getHighestPriority(rows);
}; };
const submitTags = async (data) => {
itemTagsRef.value.onSubmit(data);
};
</script> </script>
<template> <template>
@ -77,7 +80,6 @@ const insertTag = (rows) => {
data-key="ItemTags" data-key="ItemTags"
model="ItemTags" model="ItemTags"
url="ItemTags" url="ItemTags"
update-url="Tags/onSubmit"
:data-required="{ :data-required="{
$index: undefined, $index: undefined,
itemFk: route.params.id, itemFk: route.params.id,
@ -147,6 +149,7 @@ const insertTag = (rows) => {
v-model="row.value" v-model="row.value"
:label="t('itemTags.value')" :label="t('itemTags.value')"
:is-clearable="false" :is-clearable="false"
@keyup.enter.stop="submitTags(row)"
/> />
<VnInput <VnInput
:label="t('itemBasicData.relevancy')" :label="t('itemBasicData.relevancy')"
@ -154,6 +157,7 @@ const insertTag = (rows) => {
v-model="row.priority" v-model="row.priority"
:required="true" :required="true"
:rules="validate('itemTag.priority')" :rules="validate('itemTag.priority')"
@keyup.enter.stop="submitTags(row)"
/> />
<div class="row justify-center" style="flex: 0"> <div class="row justify-center" style="flex: 0">
<QIcon <QIcon
@ -189,3 +193,8 @@ const insertTag = (rows) => {
</QPage> </QPage>
</div> </div>
</template> </template>
<i18n>
es:
Tags can not be repeated: Las etiquetas no pueden repetirse
</i18n>

View File

@ -28,7 +28,7 @@ const taxesFilter = {
], ],
}; };
const ItemTaxRef = ref(null); const ItemTaxRef = ref();
const taxesOptions = ref([]); const taxesOptions = ref([]);
const submitTaxes = async (data) => { const submitTaxes = async (data) => {
@ -36,7 +36,10 @@ const submitTaxes = async (data) => {
id: tax.id, id: tax.id,
taxClassFk: tax.taxClassFk, taxClassFk: tax.taxClassFk,
})); }));
if (payload.some((item) => item.taxClassFk === null)) {
notify(t('Tax class cannot be blank'), 'negative');
return;
}
await axios.post(`Items/updateTaxes`, payload); await axios.post(`Items/updateTaxes`, payload);
notify(t('globals.dataSaved'), 'positive'); notify(t('globals.dataSaved'), 'positive');
}; };

View File

@ -55,17 +55,6 @@ const columns = computed(() => [
label: '', label: '',
name: 'image', name: 'image',
align: 'left', align: 'left',
columnField: {
component: VnImg,
attrs: ({ row }) => {
return {
id: row?.id,
zoomResolution: '1600x900',
zoom: true,
class: 'rounded',
};
},
},
columnFilter: false, columnFilter: false,
cardVisible: true, cardVisible: true,
}, },
@ -184,7 +173,7 @@ const columns = computed(() => [
cardVisible: true, cardVisible: true,
}, },
{ {
label: t('globals.origin'), label: t('item.list.origin'),
name: 'origin', name: 'origin',
align: 'left', align: 'left',
component: 'select', component: 'select',
@ -228,7 +217,8 @@ const columns = computed(() => [
}, },
}, },
{ {
label: t('item.list.weightByPiece'), label: t('item.list.weight'),
toolTip: t('item.list.weightByPiece'),
name: 'weightByPiece', name: 'weightByPiece',
align: 'left', align: 'left',
component: 'input', component: 'input',
@ -322,7 +312,6 @@ const columns = computed(() => [
ref="tableRef" ref="tableRef"
data-key="ItemList" data-key="ItemList"
url="Items/filter" url="Items/filter"
url-create="Items"
:create="{ :create="{
urlCreate: 'Items', urlCreate: 'Items',
title: t('Create Item'), title: t('Create Item'),
@ -333,12 +322,19 @@ const columns = computed(() => [
}" }"
:order="['isActive DESC', 'name', 'id']" :order="['isActive DESC', 'name', 'id']"
:columns="columns" :columns="columns"
auto-load
redirect="Item" redirect="Item"
:is-editable="false" :is-editable="false"
:right-search="false" :right-search="false"
:filer="itemFilter" :filter="itemFilter"
> >
<template #column-image="{ row }">
<VnImg
:id="row?.id"
zoom-resolution="1600x900"
:zoom="true"
class="rounded"
/>
</template>
<template #column-id="{ row }"> <template #column-id="{ row }">
<span class="link" @click.stop> <span class="link" @click.stop>
{{ row.id }} {{ row.id }}
@ -348,7 +344,7 @@ const columns = computed(() => [
<template #column-userName="{ row }"> <template #column-userName="{ row }">
<span class="link" @click.stop> <span class="link" @click.stop>
{{ row.userName }} {{ row.userName }}
<WorkerDescriptorProxy :id="row.workerFk" /> <WorkerDescriptorProxy :id="row.buyerFk" />
</span> </span>
</template> </template>
<template #column-description="{ row }"> <template #column-description="{ row }">

View File

@ -199,7 +199,17 @@ onMounted(async () => {
dense dense
outlined outlined
rounded rounded
/> >
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection>
<QItemLabel>{{
t(`params.${scope.opt?.name}`)
}}</QItemLabel>
</QItemSection>
</QItem>
</template>
</VnSelect>
</QItemSection> </QItemSection>
</QItem> </QItem>
<QItem> <QItem>
@ -434,6 +444,13 @@ en:
description: Description description: Description
name: Name name: Name
id: Id id: Id
Accessories: Accessories
Artificial: Artificial
Flower: Flower
Fruit: Fruit
Green: Green
Handmade: Handmade
Plant: Plant
es: es:
More fields: Más campos More fields: Más campos
params: params:
@ -450,4 +467,11 @@ es:
description: Descripción description: Descripción
name: Nombre name: Nombre
id: Id id: Id
Accessories: Accesorios
Artificial: Artificial
Flower: Flor
Fruit: Fruta
Green: Verde
Handmade: Hecho a mano
Plant: Planta
</i18n> </i18n>

View File

@ -5,13 +5,16 @@ import TicketDescriptorProxy from 'src/pages/Ticket/Card/TicketDescriptorProxy.v
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue'; import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
import { useStateStore } from 'stores/useStateStore'; import { useStateStore } from 'stores/useStateStore';
import { useArrayData } from 'composables/useArrayData'; import { useArrayData } from 'composables/useArrayData';
import { dashIfEmpty, toCurrency } from 'filters/index'; import { toCurrency } from 'filters/index';
import useNotify from 'src/composables/useNotify.js'; import useNotify from 'src/composables/useNotify.js';
import axios from 'axios'; import axios from 'axios';
import ItemRequestDenyForm from './ItemRequestDenyForm.vue'; import ItemRequestDenyForm from './ItemRequestDenyForm.vue';
import { toDate } from 'src/filters'; import { toDate } from 'src/filters';
import VnTable from 'components/VnTable/VnTable.vue'; import VnTable from 'components/VnTable/VnTable.vue';
import VnInput from 'src/components/common/VnInput.vue'; import VnInput from 'src/components/common/VnInput.vue';
import VnInputNumber from 'src/components/common/VnInputNumber.vue';
import ItemRequestFilter from './ItemRequestFilter.vue';
import RightMenu from 'src/components/common/RightMenu.vue';
const { t } = useI18n(); const { t } = useI18n();
const { notify } = useNotify(); const { notify } = useNotify();
const stateStore = useStateStore(); const stateStore = useStateStore();
@ -228,6 +231,11 @@ onMounted(async () => {
</script> </script>
<template> <template>
<RightMenu>
<template #right-panel>
<ItemRequestFilter data-key="itemRequest" />
</template>
</RightMenu>
<VnTable <VnTable
ref="tableRef" ref="tableRef"
data-key="itemRequest" data-key="itemRequest"
@ -239,6 +247,7 @@ onMounted(async () => {
auto-load auto-load
:disable-option="{ card: true }" :disable-option="{ card: true }"
chip-locale="item.params" chip-locale="item.params"
:right-search="false"
> >
<template #column-ticketFk="{ row }"> <template #column-ticketFk="{ row }">
<span class="link"> <span class="link">
@ -306,7 +315,6 @@ onMounted(async () => {
/> />
</template> </template>
<template #column-denyOptions="{ row, rowIndex }"> <template #column-denyOptions="{ row, rowIndex }">
<QTd class="sticky no-padding">
<QIcon <QIcon
v-if="row.response?.length" v-if="row.response?.length"
name="insert_drive_file" name="insert_drive_file"
@ -329,7 +337,6 @@ onMounted(async () => {
{{ t('Discard') }} {{ t('Discard') }}
</QTooltip> </QTooltip>
</QIcon> </QIcon>
</QTd>
</template> </template>
</VnTable> </VnTable>
<QDialog ref="denyFormRef" transition-show="scale" transition-hide="scale"> <QDialog ref="denyFormRef" transition-show="scale" transition-hide="scale">

View File

@ -1,5 +1,5 @@
<script setup> <script setup>
import { ref } from 'vue'; import { onMounted, ref } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { dateRange } from 'src/filters'; import { dateRange } from 'src/filters';
import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue'; import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
@ -7,6 +7,8 @@ import VnSelect from 'src/components/common/VnSelect.vue';
import VnInput from 'src/components/common/VnInput.vue'; import VnInput from 'src/components/common/VnInput.vue';
import FetchData from 'components/FetchData.vue'; import FetchData from 'components/FetchData.vue';
import VnInputDate from 'src/components/common/VnInputDate.vue'; import VnInputDate from 'src/components/common/VnInputDate.vue';
import { useArrayData } from 'src/composables/useArrayData';
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
const { t } = useI18n(); const { t } = useI18n();
const props = defineProps({ const props = defineProps({
@ -21,7 +23,8 @@ const stateOptions = [
{ code: 'accepted', name: t('accepted') }, { code: 'accepted', name: t('accepted') },
{ code: 'denied', name: t('denied') }, { code: 'denied', name: t('denied') },
]; ];
const arrayData = useArrayData(props.dataKey);
const fieldFiltersValues = ref([]);
const itemTypesOptions = ref([]); const itemTypesOptions = ref([]);
const warehousesOptions = ref([]); const warehousesOptions = ref([]);
@ -56,6 +59,19 @@ const decrement = (paramsObj, key) => {
paramsObj[key]--; paramsObj[key]--;
}; };
onMounted(async () => {
if (arrayData.store?.userParams) {
fieldFiltersValues.value = Object.entries(arrayData.store.userParams).map(
([key, value]) => ({
name: key,
value,
selectedField: { name: key, label: t(`params.${key}`) },
})
);
}
exprBuilder('state', arrayData.store?.userParams?.state);
});
</script> </script>
<template> <template>
@ -145,33 +161,17 @@ const decrement = (paramsObj, key) => {
</QItem> </QItem>
<QItem> <QItem>
<QItemSection> <QItemSection>
<VnSelect <VnSelectWorker
:label="t('params.requesterFk')" :label="t('params.requesterFk')"
v-model="params.requesterFk" v-model="params.requesterFk"
@update:model-value="searchFn()" @update:model-value="searchFn()"
url="Workers/search"
:fields="['id', 'name']" :fields="['id', 'name']"
order="name ASC"
:params="{ departmentCodes: ['VT'] }" :params="{ departmentCodes: ['VT'] }"
option-value="id"
option-label="name"
hide-selected hide-selected
dense dense
outlined outlined
rounded rounded
> />
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection>
<QItemLabel>{{ scope.opt?.name }}</QItemLabel>
<QItemLabel caption
>{{ scope.opt?.nickname }},
{{ scope.opt?.code }}</QItemLabel
>
</QItemSection>
</QItem>
</template>
</VnSelect>
</QItemSection> </QItemSection>
</QItem> </QItem>
<QItem> <QItem>

View File

@ -10,7 +10,6 @@ const { t } = useI18n();
url="ItemTypes" url="ItemTypes"
:label="t('Search item type')" :label="t('Search item type')"
:info="t('Search itemType by id, name or code')" :info="t('Search itemType by id, name or code')"
search-url="table"
/> />
</template> </template>
<i18n> <i18n>

View File

@ -6,6 +6,7 @@ import VnTable from 'components/VnTable/VnTable.vue';
import FetchData from 'components/FetchData.vue'; import FetchData from 'components/FetchData.vue';
import RightMenu from 'src/components/common/RightMenu.vue'; import RightMenu from 'src/components/common/RightMenu.vue';
import ItemTypeFilter from './ItemType/ItemTypeFilter.vue'; import ItemTypeFilter from './ItemType/ItemTypeFilter.vue';
import WorkerDescriptorProxy from '../Worker/Card/WorkerDescriptorProxy.vue';
const { t } = useI18n(); const { t } = useI18n();
const tableRef = ref(); const tableRef = ref();
@ -31,13 +32,14 @@ const columns = computed(() => [
{ {
align: 'left', align: 'left',
name: 'name', name: 'name',
label: t('name'), label: t('globals.name'),
cardVisible: true, cardVisible: true,
create: true, create: true,
}, },
{ {
align: 'left', align: 'left',
label: t('worker'), label: t('worker'),
name: 'workerFk',
create: true, create: true,
component: 'select', component: 'select',
attrs: { attrs: {
@ -45,20 +47,20 @@ const columns = computed(() => [
optionLabel: 'nickname', optionLabel: 'nickname',
optionValue: 'id', optionValue: 'id',
}, },
format: (row) => row.worker?.user?.name,
cardVisible: true, cardVisible: true,
visible: true, columnField: { component: null },
columnField: {
component: 'userLink',
attrs: ({ row }) => {
return {
workerId: row?.worker?.id,
name: row.worker?.user?.name,
defaultName: true,
};
},
},
columnFilter: { columnFilter: {
name: 'workerFk', attrs: {
url: 'Workers/activeWithInheritedRole',
fields: ['id', 'name'],
where: { role: 'buyer' },
optionFilter: 'firstName',
optionLabel: 'name',
optionValue: 'id',
useLike: false,
},
inWhere: true,
}, },
}, },
{ {
@ -135,24 +137,27 @@ const columns = computed(() => [
:columns="columns" :columns="columns"
auto-load auto-load
:right-search="false" :right-search="false"
:is-editable="false"
:use-model="true"
redirect="item/item-type" redirect="item/item-type"
/> >
<template #column-workerFk="{ row }">
<span class="link" @click.stop>
{{ row.worker?.user?.name }}
<WorkerDescriptorProxy :id="row.workerFk" />
</span>
</template>
</VnTable>
</template> </template>
<i18n> <i18n>
es: es:
id: Id id: Id
code: Código code: Código
name: Nombre
worker: Trabajador worker: Trabajador
ItemCategory: Reino ItemCategory: Reino
Temperature: Temperatura Temperature: Temperatura
Create ItemTypes: Crear familia Create ItemTypes: Crear familia
en: en:
code: Code code: Code
name: Name
worker: Worker worker: Worker
ItemCategory: ItemCategory ItemCategory: ItemCategory
Temperature: Temperature Temperature: Temperature

View File

@ -66,6 +66,7 @@ lastEntries:
package: Package package: Package
freight: Freight freight: Freight
comission: Comission comission: Comission
printedStickers: Pri.
itemTags: itemTags:
removeTag: Remove tag removeTag: Remove tag
addTag: Add tag addTag: Add tag
@ -95,6 +96,15 @@ item:
mine: For me mine: For me
state: State state: State
myTeam: My team myTeam: My team
shipped: Shipped
description: Description
quantity: Quantity
price: Price
item: Item
achieved: Achieved
concept: Concept
denyOptions: Deny
scopeDays: Scope days
searchbar: searchbar:
label: Search item label: Search item
descriptor: descriptor:
@ -112,7 +122,7 @@ item:
title: All its properties will be copied title: All its properties will be copied
subTitle: Do you want to clone this item? subTitle: Do you want to clone this item?
list: list:
id: Identifier id: Id
grouping: Grouping grouping: Grouping
packing: Packing packing: Packing
description: Description description: Description
@ -122,8 +132,9 @@ item:
intrastat: Intrastat intrastat: Intrastat
isActive: Active isActive: Active
size: Size size: Size
origin: Origin origin: Orig.
userName: Buyer userName: Buyer
weight: Weight
weightByPiece: Weight/Piece weightByPiece: Weight/Piece
stemMultiplier: Multiplier stemMultiplier: Multiplier
producer: Producer producer: Producer

View File

@ -56,7 +56,7 @@ lastEntries:
landed: F. Entrega landed: F. Entrega
entry: Entrada entry: Entrada
pvp: PVP pvp: PVP
label: Etiquetas label: Eti.
grouping: Grouping grouping: Grouping
quantity: Cantidad quantity: Cantidad
cost: Coste cost: Coste
@ -66,6 +66,7 @@ lastEntries:
package: Embalaje package: Embalaje
freight: Porte freight: Porte
comission: Comisión comission: Comisión
printedStickers: Imp.
itemTags: itemTags:
removeTag: Quitar etiqueta removeTag: Quitar etiqueta
addTag: Añadir etiqueta addTag: Añadir etiqueta
@ -97,6 +98,15 @@ item:
mine: Para mi mine: Para mi
state: Estado state: Estado
myTeam: Mi equipo myTeam: Mi equipo
shipped: Enviado
description: Descripción
quantity: Cantidad
price: Precio
item: Artículo
achieved: Conseguido
concept: Concepto
denyOptions: Denegado
scopeDays: Días en adelante
searchbar: searchbar:
label: Buscar artículo label: Buscar artículo
descriptor: descriptor:
@ -114,7 +124,7 @@ item:
title: Todas sus propiedades serán copiadas title: Todas sus propiedades serán copiadas
subTitle: ¿Desea clonar este artículo? subTitle: ¿Desea clonar este artículo?
list: list:
id: Identificador id: Id
grouping: Grouping grouping: Grouping
packing: Packing packing: Packing
description: Descripción description: Descripción
@ -124,7 +134,8 @@ item:
intrastat: Intrastat intrastat: Intrastat
isActive: Activo isActive: Activo
size: Medida size: Medida
origin: Origen origin: Orig.
weight: Peso
weightByPiece: Peso (gramos)/tallo weightByPiece: Peso (gramos)/tallo
userName: Comprador userName: Comprador
stemMultiplier: Multiplicador stemMultiplier: Multiplicador

View File

@ -9,6 +9,7 @@ import VnInput from 'src/components/common/VnInput.vue';
import VnInputNumber from 'src/components/common/VnInputNumber.vue'; import VnInputNumber from 'src/components/common/VnInputNumber.vue';
import FetchData from 'src/components/FetchData.vue'; import FetchData from 'src/components/FetchData.vue';
import { dateRange } from 'src/filters'; import { dateRange } from 'src/filters';
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
defineProps({ dataKey: { type: String, required: true } }); defineProps({ dataKey: { type: String, required: true } });
const { t, te } = useI18n(); const { t, te } = useI18n();
@ -112,33 +113,16 @@ const getLocale = (label) => {
</QItem> </QItem>
<QItem> <QItem>
<QItemSection> <QItemSection>
<VnSelect <VnSelectWorker
outlined outlined
dense dense
rounded rounded
:label="t('globals.params.salesPersonFk')" :label="t('globals.params.salesPersonFk')"
v-model="params.salesPersonFk" v-model="params.salesPersonFk"
url="Workers/search"
:params="{ departmentCodes: ['VT'] }" :params="{ departmentCodes: ['VT'] }"
is-outlined
option-value="id"
option-label="name"
:no-one="true" :no-one="true"
> >
<template #option="{ opt, itemProps }"> </VnSelectWorker>
<QItem v-bind="itemProps">
<QItemSection>
<QItemLabel>{{ opt.name }}</QItemLabel>
<QItemLabel
v-if="opt.code"
class="text-grey text-caption"
>
{{ `${opt.nickname}, ${opt.code}` }}
</QItemLabel>
</QItemSection>
</QItem>
</template>
</VnSelect>
</QItemSection> </QItemSection>
</QItem> </QItem>
<QItem> <QItem>
@ -150,6 +134,7 @@ const getLocale = (label) => {
/> />
</QItemSection> </QItemSection>
</QItem> </QItem>
<QItem> <QItem>
<QItemSection> <QItemSection>
<VnSelect <VnSelect
@ -225,6 +210,34 @@ const getLocale = (label) => {
/> />
</QItemSection> </QItemSection>
</QItem> </QItem>
<QItem>
<QItemSection>
<VnSelect
outlined
dense
rounded
:label="t('globals.params.departmentFk')"
v-model="params.department"
option-label="name"
option-value="name"
url="Departments"
/>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<VnSelect
outlined
dense
rounded
:label="t('globals.params.packing')"
v-model="params.packing"
url="ItemPackingTypes"
option-label="code"
option-value="code"
/>
</QItemSection>
</QItem>
<QItem> <QItem>
<QItemSection> <QItemSection>
<QCheckbox <QCheckbox

View File

@ -10,20 +10,23 @@ import ZoneDescriptorProxy from 'src/pages/Zone/Card/ZoneDescriptorProxy.vue';
import TicketSummary from 'src/pages/Ticket/Card/TicketSummary.vue'; import TicketSummary from 'src/pages/Ticket/Card/TicketSummary.vue';
import VnTable from 'components/VnTable/VnTable.vue'; import VnTable from 'components/VnTable/VnTable.vue';
import { useSummaryDialog } from 'src/composables/useSummaryDialog'; import { useSummaryDialog } from 'src/composables/useSummaryDialog';
import { toDateFormat } from 'src/filters/date.js';
import { toCurrency, dateRange, dashIfEmpty } from 'src/filters'; import { toCurrency, dateRange, dashIfEmpty } from 'src/filters';
import RightMenu from 'src/components/common/RightMenu.vue'; import RightMenu from 'src/components/common/RightMenu.vue';
import MonitorTicketSearchbar from './MonitorTicketSearchbar.vue'; import MonitorTicketSearchbar from './MonitorTicketSearchbar.vue';
import MonitorTicketFilter from './MonitorTicketFilter.vue'; import MonitorTicketFilter from './MonitorTicketFilter.vue';
import TicketProblems from 'src/components/TicketProblems.vue'; import TicketProblems from 'src/components/TicketProblems.vue';
import VnDateBadge from 'src/components/common/VnDateBadge.vue';
const DEFAULT_AUTO_REFRESH = 2 * 60 * 1000; // 2min in ms const DEFAULT_AUTO_REFRESH = 2 * 60 * 1000;
const { t } = useI18n(); const { t } = useI18n();
const autoRefresh = ref(false); const autoRefresh = ref(false);
const tableRef = ref(null); const tableRef = ref(null);
const provinceOpts = ref([]); const provinceOpts = ref([]);
const stateOpts = ref([]); const stateOpts = ref([]);
const zoneOpts = ref([]); const zoneOpts = ref([]);
const DepartmentOpts = ref([]);
const ItemPackingTypeOpts = ref([]);
const visibleColumns = ref([]);
const { viewSummary } = useSummaryDialog(); const { viewSummary } = useSummaryDialog();
const [from, to] = dateRange(Date.vnNew()); const [from, to] = dateRange(Date.vnNew());
@ -51,6 +54,8 @@ function exprBuilder(param, value) {
case 'nickname': case 'nickname':
return { [`t.nickname`]: { like: `%${value}%` } }; return { [`t.nickname`]: { like: `%${value}%` } };
case 'zoneFk': case 'zoneFk':
case 'department':
return { 'd.name': value };
case 'totalWithVat': case 'totalWithVat':
return { [`t.${param}`]: value }; return { [`t.${param}`]: value };
} }
@ -137,6 +142,7 @@ const columns = computed(() => [
align: 'left', align: 'left',
format: (row) => row.practicalHour, format: (row) => row.practicalHour,
columnFilter: false, columnFilter: false,
dense: true,
}, },
{ {
label: t('salesTicketsTable.preparation'), label: t('salesTicketsTable.preparation'),
@ -190,6 +196,7 @@ const columns = computed(() => [
'false-value': 0, 'false-value': 0,
'true-value': 1, 'true-value': 1,
}, },
component: false,
}, },
{ {
label: t('salesTicketsTable.zone'), label: t('salesTicketsTable.zone'),
@ -206,6 +213,12 @@ const columns = computed(() => [
}, },
}, },
}, },
{
label: t('salesTicketsTable.payMethod'),
name: 'payMethod',
align: 'left',
columnFilter: false,
},
{ {
label: t('salesTicketsTable.total'), label: t('salesTicketsTable.total'),
name: 'totalWithVat', name: 'totalWithVat',
@ -219,6 +232,36 @@ const columns = computed(() => [
}, },
}, },
}, },
{
label: t('salesTicketsTable.department'),
name: 'department',
align: 'left',
columnFilter: {
component: 'select',
url: 'Departments',
attrs: {
options: DepartmentOpts.value,
optionValue: 'name',
optionLabel: 'name',
dense: true,
},
},
},
{
label: t('salesTicketsTable.packing'),
name: 'packing',
align: 'left',
columnFilter: {
component: 'select',
url: 'ItemPackingTypes',
attrs: {
options: ItemPackingTypeOpts.value,
'option-value': 'code',
'option-label': 'code',
dense: true,
},
},
},
{ {
align: 'right', align: 'right',
name: 'tableActions', name: 'tableActions',
@ -250,19 +293,6 @@ const columns = computed(() => [
}, },
]); ]);
const getBadgeAttrs = (date) => {
let today = Date.vnNew();
today.setHours(0, 0, 0, 0);
let timeTicket = new Date(date);
timeTicket.setHours(0, 0, 0, 0);
let timeDiff = today - timeTicket;
if (timeDiff == 0) return { color: 'warning', 'text-color': 'black' };
if (timeDiff < 0) return { color: 'success', 'text-color': 'black' };
return { color: 'transparent', 'text-color': 'white' };
};
let refreshTimer = null; let refreshTimer = null;
const autoRefreshHandler = (value) => { const autoRefreshHandler = (value) => {
@ -279,14 +309,6 @@ const totalPriceColor = (ticket) => {
if (total > 0 && total < 50) return 'warning'; if (total > 0 && total < 50) return 'warning';
}; };
const formatShippedDate = (date) => {
if (!date) return '-';
const dateSplit = date.split('T');
const [year, month, day] = dateSplit[0].split('-');
const newDate = new Date(year, month - 1, day);
return toDateFormat(newDate);
};
const openTab = (id) => const openTab = (id) =>
window.open(`#/ticket/${id}/sale`, '_blank', 'noopener, noreferrer'); window.open(`#/ticket/${id}/sale`, '_blank', 'noopener, noreferrer');
</script> </script>
@ -318,6 +340,24 @@ const openTab = (id) =>
auto-load auto-load
@on-fetch="(data) => (zoneOpts = data)" @on-fetch="(data) => (zoneOpts = data)"
/> />
<FetchData
url="ItemPackingTypes"
:filter="{
fields: ['code'],
order: 'code ASC',
}"
auto-load
@on-fetch="(data) => (ItemPackingTypeOpts = data)"
/>
<FetchData
url="Departments"
:filter="{
fields: ['id', 'name'],
order: 'id ASC',
}"
auto-load
@on-fetch="(data) => (DepartmentOpts = data)"
/>
<MonitorTicketSearchbar /> <MonitorTicketSearchbar />
<RightMenu> <RightMenu>
<template #right-panel> <template #right-panel>
@ -337,7 +377,7 @@ const openTab = (id) =>
auto-load auto-load
:row-click="({ id }) => openTab(id)" :row-click="({ id }) => openTab(id)"
:disable-option="{ card: true }" :disable-option="{ card: true }"
:user-params="{ from, to, scopeDays: 0 }" :user-params="{ from, to, scopeDays: 0, packing }"
> >
<template #top-left> <template #top-left>
<QBtn <QBtn
@ -382,13 +422,7 @@ const openTab = (id) =>
</div> </div>
</template> </template>
<template #column-shippedDate="{ row }"> <template #column-shippedDate="{ row }">
<QBadge <VnDateBadge :date="row.shippedDate" />
v-bind="getBadgeAttrs(row.shippedDate)"
class="q-pa-sm"
style="font-size: 14px"
>
{{ formatShippedDate(row.shippedDate) }}
</QBadge>
</template> </template>
<template #column-provinceFk="{ row }"> <template #column-provinceFk="{ row }">
<span :title="row.province" v-text="row.province" /> <span :title="row.province" v-text="row.province" />

View File

@ -26,8 +26,8 @@ salesTicketsTable:
componentLack: Component lack componentLack: Component lack
tooLittle: Ticket too little tooLittle: Ticket too little
identifier: Identifier identifier: Identifier
theoretical: Theoretical theoretical: H.Theor
practical: Practical practical: H.Prac
province: Province province: Province
state: State state: State
isFragile: Is fragile isFragile: Is fragile
@ -35,7 +35,10 @@ salesTicketsTable:
goToLines: Go to lines goToLines: Go to lines
preview: Preview preview: Preview
total: Total total: Total
preparation: Preparation preparation: H.Prep
payMethod: Pay method
department: Department
packing: ITP
searchBar: searchBar:
label: Search tickets label: Search tickets
info: Search tickets by id or alias info: Search tickets by id or alias

View File

@ -26,8 +26,8 @@ salesTicketsTable:
componentLack: Faltan componentes componentLack: Faltan componentes
tooLittle: Ticket demasiado pequeño tooLittle: Ticket demasiado pequeño
identifier: Identificador identifier: Identificador
theoretical: Teórica theoretical: H.Teór
practical: Práctica practical: H.Prác
province: Provincia province: Provincia
state: Estado state: Estado
isFragile: Es frágil isFragile: Es frágil
@ -35,7 +35,10 @@ salesTicketsTable:
goToLines: Ir a líneas goToLines: Ir a líneas
preview: Vista previa preview: Vista previa
total: Total total: Total
preparation: Preparación preparation: H.Prep
payMethod: Método de pago
department: Departamento
packing: ITP
searchBar: searchBar:
label: Buscar tickets label: Buscar tickets
info: Buscar tickets por identificador o alias info: Buscar tickets por identificador o alias

View File

@ -1,7 +1,7 @@
<script setup> <script setup>
import { useStateStore } from 'stores/useStateStore'; import { useStateStore } from 'stores/useStateStore';
import { useRoute, useRouter } from 'vue-router'; import { useRoute, useRouter } from 'vue-router';
import { onMounted, onUnmounted, ref, computed, watch, provide, nextTick } from 'vue'; import { onMounted, ref, computed, watch, provide } from 'vue';
import axios from 'axios'; import axios from 'axios';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import VnPaginate from 'src/components/ui/VnPaginate.vue'; import VnPaginate from 'src/components/ui/VnPaginate.vue';
@ -30,8 +30,6 @@ onMounted(() => {
checkOrderConfirmation(); checkOrderConfirmation();
}); });
onUnmounted(() => (stateStore.rightDrawer = false));
async function checkOrderConfirmation() { async function checkOrderConfirmation() {
const response = await axios.get(`Orders/${route.params.id}`); const response = await axios.get(`Orders/${route.params.id}`);
if (response.data.isConfirmed === 1) { if (response.data.isConfirmed === 1) {

View File

@ -1,9 +1,8 @@
<script setup> <script setup>
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { reactive, onMounted, ref } from 'vue'; import { reactive, ref } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import axios from 'axios'; import axios from 'axios';
import { useState } from 'composables/useState';
import FormModelPopup from 'components/FormModelPopup.vue'; import FormModelPopup from 'components/FormModelPopup.vue';
import VnRow from 'components/ui/VnRow.vue'; import VnRow from 'components/ui/VnRow.vue';
import VnSelect from 'components/common/VnSelect.vue'; import VnSelect from 'components/common/VnSelect.vue';
@ -11,29 +10,12 @@ import VnInputDate from 'components/common/VnInputDate.vue';
import { useDialogPluginComponent } from 'quasar'; import { useDialogPluginComponent } from 'quasar';
const { t } = useI18n(); const { t } = useI18n();
const state = useState();
const ORDER_MODEL = 'order'; const ORDER_MODEL = 'order';
const router = useRouter(); const router = useRouter();
const agencyList = ref([]); const agencyList = ref([]);
const addressList = ref([]);
defineEmits(['confirm', ...useDialogPluginComponent.emits]); defineEmits(['confirm', ...useDialogPluginComponent.emits]);
const fetchAddressList = async (addressId) => {
const { data } = await axios.get('addresses', {
params: {
filter: JSON.stringify({
fields: ['id', 'nickname', 'street', 'city'],
where: { id: addressId },
}),
},
});
addressList.value = data;
if (addressList.value?.length === 1) {
state.get(ORDER_MODEL).addressId = addressList.value[0].id;
}
};
const fetchAgencyList = async (landed, addressFk) => { const fetchAgencyList = async (landed, addressFk) => {
if (!landed || !addressFk) { if (!landed || !addressFk) {
return; return;
@ -59,17 +41,9 @@ const initialFormState = reactive({
clientFk: $props.clientFk, clientFk: $props.clientFk,
}); });
const onClientChange = async (clientId = $props.clientFk) => {
const { data } = await axios.get(`Clients/${clientId}`);
await fetchAddressList(data.defaultAddressFk);
};
async function onDataSaved(_, id) { async function onDataSaved(_, id) {
await router.push({ path: `/order/${id}/catalog` }); await router.push({ path: `/order/${id}/catalog` });
} }
onMounted(async () => {
await onClientChange();
});
</script> </script>
<template> <template>
@ -90,10 +64,9 @@ onMounted(async () => {
option-value="id" option-value="id"
option-label="name" option-label="name"
:filter="{ :filter="{
fields: ['id', 'name', 'defaultAddressFk'], fields: ['id', 'name'],
}" }"
hide-selected hide-selected
@update:model-value="onClientChange"
> >
<template #option="scope"> <template #option="scope">
<QItem v-bind="scope.itemProps"> <QItem v-bind="scope.itemProps">
@ -110,7 +83,7 @@ onMounted(async () => {
:label="t('order.form.addressFk')" :label="t('order.form.addressFk')"
v-model="data.addressId" v-model="data.addressId"
url="addresses" url="addresses"
:fields="['id', 'nickname', 'defaultAddressFk', 'street', 'city']" :fields="['id', 'nickname', 'street', 'city']"
sort-by="id" sort-by="id"
option-value="id" option-value="id"
option-label="street" option-label="street"

View File

@ -6,6 +6,7 @@ import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
import VnSelect from 'components/common/VnSelect.vue'; import VnSelect from 'components/common/VnSelect.vue';
import VnInputDate from 'components/common/VnInputDate.vue'; import VnInputDate from 'components/common/VnInputDate.vue';
import VnInput from 'components/common/VnInput.vue'; import VnInput from 'components/common/VnInput.vue';
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
const { t } = useI18n(); const { t } = useI18n();
const props = defineProps({ const props = defineProps({
@ -61,28 +62,16 @@ const sourceList = ref([]);
outlined outlined
rounded rounded
/> />
<VnSelect <VnSelectWorker
:label="t('salesPerson')" :label="t('globals.salesPerson')"
v-model="params.workerFk" v-model="params.workerFk"
url="Workers/search" :params="{
:filter="{ departmentCodes: ['VT'] }" departmentCodes: ['VT'],
sort-by="nickname ASC" }"
option-label="nickname"
dense dense
outlined outlined
rounded rounded
> />
<template #option="{ itemProps, opt }">
<QItem v-bind="itemProps">
<QItemSection>
<QItemLabel>{{ opt.name }}</QItemLabel>
<QItemLabel caption>
{{ opt.nickname }},{{ opt.code }}
</QItemLabel>
</QItemSection>
</QItem>
</template>
</VnSelect>
<VnInputDate <VnInputDate
v-model="params.from" v-model="params.from"
:label="t('fromLanded')" :label="t('fromLanded')"

View File

@ -1,7 +1,7 @@
<script setup> <script setup>
import axios from 'axios'; import axios from 'axios';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { computed, onMounted, ref } from 'vue'; import { computed, ref, onMounted } from 'vue';
import { dashIfEmpty, toCurrency, toDate } from 'src/filters'; import { dashIfEmpty, toCurrency, toDate } from 'src/filters';
import OrderSummary from 'pages/Order/Card/OrderSummary.vue'; import OrderSummary from 'pages/Order/Card/OrderSummary.vue';
import { useSummaryDialog } from 'src/composables/useSummaryDialog'; import { useSummaryDialog } from 'src/composables/useSummaryDialog';
@ -15,14 +15,13 @@ import CustomerDescriptorProxy from '../Customer/Card/CustomerDescriptorProxy.vu
import WorkerDescriptorProxy from '../Worker/Card/WorkerDescriptorProxy.vue'; import WorkerDescriptorProxy from '../Worker/Card/WorkerDescriptorProxy.vue';
import { toDateTimeFormat } from 'src/filters/date'; import { toDateTimeFormat } from 'src/filters/date';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import dataByOrder from 'src/utils/dataByOrder';
const { t } = useI18n(); const { t } = useI18n();
const { viewSummary } = useSummaryDialog(); const { viewSummary } = useSummaryDialog();
const tableRef = ref(); const tableRef = ref();
const agencyList = ref([]); const agencyList = ref([]);
const addressesList = ref([]);
const route = useRoute(); const route = useRoute();
const addressOptions = ref([]);
const columns = computed(() => [ const columns = computed(() => [
{ {
align: 'left', align: 'left',
@ -148,16 +147,12 @@ onMounted(() => {
const id = JSON.parse(clientId); const id = JSON.parse(clientId);
fetchClientAddress(id.clientFk); fetchClientAddress(id.clientFk);
}); });
async function fetchClientAddress(id, formData = {}) { async function fetchClientAddress(id, formData = {}) {
const { data } = await axios.get(`Clients/${id}`, { const { data } = await axios.get(
params: { `Clients/${id}/addresses?filter[order]=isActive DESC`
filter: { );
order: ['isDefaultAddress DESC', 'isActive DESC', 'nickname ASC'], addressOptions.value = data;
include: { relation: 'addresses' },
},
},
});
addressesList.value = data.addresses;
formData.addressId = data.defaultAddressFk; formData.addressId = data.defaultAddressFk;
fetchAgencies(formData); fetchAgencies(formData);
} }
@ -168,7 +163,7 @@ async function fetchAgencies({ landed, addressId }) {
const { data } = await axios.get('Agencies/landsThatDay', { const { data } = await axios.get('Agencies/landsThatDay', {
params: { addressFk: addressId, landed }, params: { addressFk: addressId, landed },
}); });
agencyList.value = dataByOrder(data, 'agencyMode ASC'); agencyList.value = data;
} }
const getDateColor = (date) => { const getDateColor = (date) => {
@ -252,34 +247,29 @@ const getDateColor = (date) => {
</VnSelect> </VnSelect>
<VnSelect <VnSelect
v-model="data.addressId" v-model="data.addressId"
:options="addressesList" :options="addressOptions"
:label="t('module.address')" :label="t('module.address')"
option-value="id" option-value="id"
option-label="nickname" option-label="nickname"
@update:model-value="() => fetchAgencies(data)" @update:model-value="() => fetchAgencies(data)"
> >
<template #option="scope"> <template #option="scope">
<QItem <QItem v-bind="scope.itemProps">
v-bind="scope.itemProps"
:class="{ disabled: !scope.opt.isActive }"
>
<QItemSection style="min-width: min-content" avatar>
<QIcon
v-if="
scope.opt.isActive && data.addressId === scope.opt.id
"
size="sm"
color="grey"
name="star"
class="fill-icon"
/>
</QItemSection>
<QItemSection> <QItemSection>
<QItemLabel> <QItemLabel
{{ scope.opt.nickname }} :class="{
</QItemLabel> 'color-vn-label': !scope.opt?.isActive,
<QItemLabel caption> }"
{{ `${scope.opt.street}, ${scope.opt.city}` }} >
{{
`${
!scope.opt?.isActive
? t('basicData.inactive')
: ''
} `
}}
{{ scope.opt?.nickname }}: {{ scope.opt?.street }},
{{ scope.opt?.city }}
</QItemLabel> </QItemLabel>
</QItemSection> </QItemSection>
</QItem> </QItem>

View File

@ -4,6 +4,7 @@ import VnFilterPanel from 'components/ui/VnFilterPanel.vue';
import VnSelect from 'components/common/VnSelect.vue'; import VnSelect from 'components/common/VnSelect.vue';
import VnInputDate from 'components/common/VnInputDate.vue'; import VnInputDate from 'components/common/VnInputDate.vue';
import VnInput from 'components/common/VnInput.vue'; import VnInput from 'components/common/VnInput.vue';
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
const { t } = useI18n(); const { t } = useI18n();
const props = defineProps({ const props = defineProps({
@ -31,29 +32,13 @@ const emit = defineEmits(['search']);
<template #body="{ params }"> <template #body="{ params }">
<QItem class="q-my-sm"> <QItem class="q-my-sm">
<QItemSection> <QItemSection>
<VnSelect <VnSelectWorker
:label="t('Worker')"
v-model="params.workerFk" v-model="params.workerFk"
url="Workers/search"
sort-by="nickname ASC"
option-value="id"
option-label="nickname"
dense dense
outlined outlined
rounded rounded
:input-debounce="0" :input-debounce="0"
> />
<template #option="{ itemProps, opt }">
<QItem v-bind="itemProps">
<QItemSection>
<QItemLabel>{{ opt.name }}</QItemLabel>
<QItemLabel caption>
{{ opt.nickname }},{{ opt.code }}
</QItemLabel>
</QItemSection>
</QItem>
</template>
</VnSelect>
</QItemSection> </QItemSection>
</QItem> </QItem>
<QItem class="q-my-sm"> <QItem class="q-my-sm">

View File

@ -11,6 +11,7 @@ import VnInputDate from 'components/common/VnInputDate.vue';
import VnInput from 'components/common/VnInput.vue'; import VnInput from 'components/common/VnInput.vue';
import axios from 'axios'; import axios from 'axios';
import VnInputTime from 'components/common/VnInputTime.vue'; import VnInputTime from 'components/common/VnInputTime.vue';
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
const { t } = useI18n(); const { t } = useI18n();
const route = useRoute(); const route = useRoute();
@ -94,26 +95,7 @@ const onSave = (data, response) => {
> >
<template #form="{ data }"> <template #form="{ data }">
<VnRow> <VnRow>
<VnSelect <VnSelectWorker v-model="data.workerFk" />
:label="t('Worker')"
v-model="data.workerFk"
url="Workers/search"
sort-by="nickname ASC"
option-value="id"
option-label="nickname"
:input-debounce="0"
>
<template #option="{ itemProps, opt }">
<QItem v-bind="itemProps">
<QItemSection>
<QItemLabel>{{ opt.name }}</QItemLabel>
<QItemLabel caption>
{{ opt.nickname }}, {{ opt.code }}
</QItemLabel>
</QItemSection>
</QItem>
</template>
</VnSelect>
<VnSelect <VnSelect
:label="t('Vehicle')" :label="t('Vehicle')"
v-model="data.vehicleFk" v-model="data.vehicleFk"

View File

@ -223,10 +223,10 @@ function navigate(id) {
router.push({ path: `/route/${id}` }); router.push({ path: `/route/${id}` });
} }
const cloneRoutes = () => { const cloneRoutes = async () => {
if (!selectedRows.value.length || !startingDate.value) return; if (!selectedRows.value.length || !startingDate.value) return;
axios.post('Routes/clone', { await axios.post('Routes/clone', {
created: startingDate.value, dated: startingDate.value,
ids: selectedRows.value.map((row) => row?.id), ids: selectedRows.value.map((row) => row?.id),
}); });
startingDate.value = null; startingDate.value = null;
@ -274,7 +274,6 @@ const openTicketsDialog = (id) => {
<QCardSection> <QCardSection>
<p class="text-h6 q-ma-none">{{ t('route.Select the starting date') }}</p> <p class="text-h6 q-ma-none">{{ t('route.Select the starting date') }}</p>
</QCardSection> </QCardSection>
<QCardSection class="q-pt-none"> <QCardSection class="q-pt-none">
<VnInputDate <VnInputDate
:label="t('route.Stating date')" :label="t('route.Stating date')"

View File

@ -2,7 +2,7 @@
import VnPaginate from 'components/ui/VnPaginate.vue'; import VnPaginate from 'components/ui/VnPaginate.vue';
import { useStateStore } from 'stores/useStateStore'; import { useStateStore } from 'stores/useStateStore';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { onMounted, onUnmounted } from 'vue'; import { onMounted } from 'vue';
import CardList from 'components/ui/CardList.vue'; import CardList from 'components/ui/CardList.vue';
import VnLv from 'components/ui/VnLv.vue'; import VnLv from 'components/ui/VnLv.vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
@ -21,7 +21,6 @@ const filter = {
}; };
onMounted(() => (stateStore.rightDrawer = true)); onMounted(() => (stateStore.rightDrawer = true));
onUnmounted(() => (stateStore.rightDrawer = false));
function navigate(id) { function navigate(id) {
router.push({ path: `/shelving/${id}` }); router.push({ path: `/shelving/${id}` });

View File

@ -5,6 +5,7 @@ import FormModel from 'components/FormModel.vue';
import VnRow from 'components/ui/VnRow.vue'; import VnRow from 'components/ui/VnRow.vue';
import VnInput from 'src/components/common/VnInput.vue'; import VnInput from 'src/components/common/VnInput.vue';
import VnSelect from 'src/components/common/VnSelect.vue'; import VnSelect from 'src/components/common/VnSelect.vue';
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
const route = useRoute(); const route = useRoute();
const { t } = useI18n(); const { t } = useI18n();
@ -30,31 +31,11 @@ const companySizes = [
:rules="validate('supplier.nickname')" :rules="validate('supplier.nickname')"
clearable clearable
/> />
<VnSelect <VnSelectWorker
:label="t('supplier.basicData.workerFk')"
v-model="data.workerFk" v-model="data.workerFk"
url="Workers/search" has-info="Responsible for approving invoices"
sort-by="nickname ASC"
:rules="validate('supplier.workerFk')" :rules="validate('supplier.workerFk')"
> />
<template #append>
<QIcon name="info" class="cursor-pointer">
<QTooltip>{{
t('Responsible for approving invoices')
}}</QTooltip>
</QIcon>
</template>
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection>
<QItemLabel>{{ scope.opt?.name }}</QItemLabel>
<QItemLabel caption>
{{ scope.opt?.nickname }}, {{ scope.opt?.id }}
</QItemLabel>
</QItemSection>
</QItem>
</template>
</VnSelect>
<VnSelect <VnSelect
:label="t('supplier.basicData.size')" :label="t('supplier.basicData.size')"
v-model="data.companySize" v-model="data.companySize"
@ -102,6 +83,5 @@ const companySizes = [
<i18n> <i18n>
es: es:
Responsible for approving invoices: Responsable de aprobar las facturas
Small(1-5), Medium(6-50), Big(> 50): Pequeño(1-5), Mediano(6-50), Grande(> 50) Small(1-5), Medium(6-50), Big(> 50): Pequeño(1-5), Mediano(6-50), Grande(> 50)
</i18n> </i18n>

View File

@ -1,5 +1,5 @@
<script setup> <script setup>
import { ref, computed, onMounted, onUnmounted, watch } from 'vue'; import { ref, computed, onMounted, watch } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue'; import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
@ -134,8 +134,6 @@ onMounted(() => {
loadDefaultTicketAction(); loadDefaultTicketAction();
ticketHaveNegatives(); ticketHaveNegatives();
}); });
onUnmounted(() => (stateStore.rightDrawer = false));
</script> </script>
<template> <template>

View File

@ -1,5 +1,5 @@
<script setup> <script setup>
import { ref, computed, onMounted, onUnmounted, watch, nextTick } from 'vue'; import { ref, computed, onMounted, watch, nextTick } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
@ -168,8 +168,6 @@ const getTicketVolume = async () => {
onMounted(() => { onMounted(() => {
stateStore.rightDrawer = true; stateStore.rightDrawer = true;
}); });
onUnmounted(() => (stateStore.rightDrawer = false));
</script> </script>
<template> <template>

View File

@ -9,6 +9,7 @@ import VnSelect from 'src/components/common/VnSelect.vue';
import FetchData from 'components/FetchData.vue'; import FetchData from 'components/FetchData.vue';
import { useState } from 'src/composables/useState'; import { useState } from 'src/composables/useState';
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
const emit = defineEmits(['onRequestCreated']); const emit = defineEmits(['onRequestCreated']);
@ -46,29 +47,7 @@ const onStateFkChange = (formData) => (formData.userFk = user.value.id);
option-label="name" option-label="name"
option-value="id" option-value="id"
/> />
<VnSelect <VnSelectWorker v-model="data.userFk" :fields="['id', 'name']" />
:label="t('expedition.worker')"
v-model="data.userFk"
url="Workers/search"
fields=" ['id', 'name']"
sort-by="name ASC"
hide-selected
option-label="name"
option-value="id"
>
<template #option="{ opt, itemProps }">
<QItem v-bind="itemProps">
<QItemSection>
<QItemLabel>
{{ opt.name }}
</QItemLabel>
<QItemLabel caption>
{{ opt.nickname }}, {{ opt.code }}
</QItemLabel>
</QItemSection>
</QItem>
</template></VnSelect
>
</VnRow> </VnRow>
</template> </template>
</FormModelPopup> </FormModelPopup>

View File

@ -1,6 +1,6 @@
<script setup> <script setup>
import axios from 'axios'; import axios from 'axios';
import { computed, ref, toRefs } from 'vue'; import { computed, onMounted, ref, toRefs, watch } from 'vue';
import { useQuasar } from 'quasar'; import { useQuasar } from 'quasar';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
@ -24,6 +24,15 @@ const props = defineProps({
}, },
}); });
onMounted(() => {
restoreTicket();
});
watch(
() => props.ticket,
() => restoreTicket
);
const { push, currentRoute } = useRouter(); const { push, currentRoute } = useRouter();
const { dialog, notify } = useQuasar(); const { dialog, notify } = useQuasar();
const { t } = useI18n(); const { t } = useI18n();
@ -42,6 +51,7 @@ const hasPdf = ref();
const weight = ref(); const weight = ref();
const hasDocuwareFile = ref(); const hasDocuwareFile = ref();
const quasar = useQuasar(); const quasar = useQuasar();
const canRestoreTicket = ref(false);
const actions = { const actions = {
clone: async () => { clone: async () => {
const opts = { message: t('Ticket cloned'), type: 'positive' }; const opts = { message: t('Ticket cloned'), type: 'positive' };
@ -373,6 +383,54 @@ async function uploadDocuware(force) {
if (data) notify({ message: t('PDF sent!'), type: 'positive' }); if (data) notify({ message: t('PDF sent!'), type: 'positive' });
} }
const restoreTicket = async () => {
const filter = {
fields: ['id', 'originFk', 'creationDate', 'newInstance'],
where: {
originFk: ticketId.value,
newInstance: { like: '%"isDeleted":true%' },
},
order: 'creationDate DESC',
limit: 1,
};
const params = { filter: JSON.stringify(filter) };
const { data } = await axios.get(`TicketLogs`, { params });
if (data && data.length) {
const now = Date.vnNew();
const maxDate = new Date(data[0].creationDate);
maxDate.setHours(maxDate.getHours() + 1);
if (now <= maxDate) {
return (canRestoreTicket.value = true);
}
return (canRestoreTicket.value = false);
}
return (canRestoreTicket.value = false);
};
async function openRestoreConfirmation(force) {
if (!force)
return quasar
.dialog({
component: VnConfirm,
componentProps: {
title: t('Are you sure you want to restore the ticket?'),
message: t('You are going to restore this ticket'),
},
})
.onOk(async () => {
ticketToRestore();
});
}
async function ticketToRestore() {
const { data } = await axios.post(`Tickets/${ticketId.value}/restore`);
if (data) {
notify({ message: t('Ticket restored'), type: 'positive' });
}
}
</script> </script>
<template> <template>
<FetchData <FetchData
@ -560,6 +618,12 @@ async function uploadDocuware(force) {
</QItemSection> </QItemSection>
<QItemSection>{{ t('Show Proforma') }}</QItemSection> <QItemSection>{{ t('Show Proforma') }}</QItemSection>
</QItem> </QItem>
<QItem v-if="canRestoreTicket" @click="openRestoreConfirmation()" v-ripple clickable>
<QItemSection avatar>
<QIcon name="restore" />
</QItemSection>
<QItemSection>{{ t('Restore ticket') }}</QItemSection>
</QItem>
<QItem <QItem
v-if="isEditable" v-if="isEditable"
@click="showChangeTimeDialog = !showChangeTimeDialog" @click="showChangeTimeDialog = !showChangeTimeDialog"
@ -746,4 +810,8 @@ es:
You are going to delete this ticket: Vas a eliminar este ticket You are going to delete this ticket: Vas a eliminar este ticket
as PDF signed: como PDF firmado as PDF signed: como PDF firmado
Are you sure you want to replace this delivery note?: ¿Seguro que quieres reemplazar este albarán? Are you sure you want to replace this delivery note?: ¿Seguro que quieres reemplazar este albarán?
Restore ticket: Restaurar ticket
Are you sure you want to restore the ticket?: ¿Seguro que quieres restaurar el ticket?
You are going to restore this ticket: Vas a restaurar este ticket
Ticket restored: Ticket restaurado
</i18n> </i18n>

View File

@ -1,5 +1,5 @@
<script setup> <script setup>
import { onMounted, ref, computed, onUnmounted } from 'vue'; import { onMounted, ref, computed } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
@ -197,8 +197,6 @@ onMounted(async () => {
const filteredColumns = columns.value.filter((col) => col.name !== 'history'); const filteredColumns = columns.value.filter((col) => col.name !== 'history');
allColumnNames.value = filteredColumns.map((col) => col.name); allColumnNames.value = filteredColumns.map((col) => col.name);
}); });
onUnmounted(() => (stateStore.rightDrawer = false));
</script> </script>
<template> <template>

View File

@ -1,5 +1,5 @@
<script setup> <script setup>
import { onMounted, ref, computed, onUnmounted, watch } from 'vue'; import { onMounted, ref, computed, watch } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useRouter, useRoute } from 'vue-router'; import { useRouter, useRoute } from 'vue-router';
import { useQuasar } from 'quasar'; import { useQuasar } from 'quasar';
@ -421,8 +421,6 @@ onMounted(async () => {
getConfig(); getConfig();
}); });
onUnmounted(() => (stateStore.rightDrawer = false));
const items = ref([]); const items = ref([]);
const newRow = ref({}); const newRow = ref({});

View File

@ -1,5 +1,5 @@
<script setup> <script setup>
import { ref, computed, onMounted, onUnmounted, watch, nextTick } from 'vue'; import { ref, computed, onMounted, watch, nextTick } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
@ -90,8 +90,6 @@ const applyVolumes = async (salesData) => {
}; };
onMounted(() => (stateStore.rightDrawer = true)); onMounted(() => (stateStore.rightDrawer = true));
onUnmounted(() => (stateStore.rightDrawer = false));
</script> </script>
<template> <template>

View File

@ -57,7 +57,6 @@ onMounted(async () => await getItemPackingTypes());
search-url="advanceTickets" search-url="advanceTickets"
:data-key="props.dataKey" :data-key="props.dataKey"
:search-button="true" :search-button="true"
:hidden-tags="['search']"
:unremovable-params="['warehouseFk', 'dateFuture', 'dateToAdvance']" :unremovable-params="['warehouseFk', 'dateFuture', 'dateToAdvance']"
> >
<template #tags="{ tag, formatFn }"> <template #tags="{ tag, formatFn }">

View File

@ -59,7 +59,6 @@ onMounted(async () => {
/> />
<VnFilterPanel <VnFilterPanel
:data-key="props.dataKey" :data-key="props.dataKey"
:hidden-tags="['search']"
:un-removable-params="['warehouseFk', 'originScopeDays ', 'futureScopeDays']" :un-removable-params="['warehouseFk', 'originScopeDays ', 'futureScopeDays']"
> >
<template #tags="{ tag, formatFn }"> <template #tags="{ tag, formatFn }">

View File

@ -1,5 +1,5 @@
<script setup> <script setup>
import { onMounted, ref, computed, onUnmounted } from 'vue'; import { onMounted, ref, computed } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import VnSelect from 'src/components/common/VnSelect.vue'; import VnSelect from 'src/components/common/VnSelect.vue';
import VnSelectCache from 'src/components/common/VnSelectCache.vue'; import VnSelectCache from 'src/components/common/VnSelectCache.vue';
@ -170,8 +170,6 @@ onMounted(async () => {
const filteredColumns = columns.value.filter((col) => col.name !== 'actions'); const filteredColumns = columns.value.filter((col) => col.name !== 'actions');
allColumnNames.value = filteredColumns.map((col) => col.name); allColumnNames.value = filteredColumns.map((col) => col.name);
}); });
onUnmounted(() => (stateStore.rightDrawer = false));
</script> </script>
<template> <template>

View File

@ -10,6 +10,7 @@ import { useState } from 'src/composables/useState';
import axios from 'axios'; import axios from 'axios';
import VnImg from 'src/components/ui/VnImg.vue'; import VnImg from 'src/components/ui/VnImg.vue';
import EditPictureForm from 'components/EditPictureForm.vue'; import EditPictureForm from 'components/EditPictureForm.vue';
import DepartmentDescriptorProxy from 'src/pages/Department/Card/DepartmentDescriptorProxy.vue';
const $props = defineProps({ const $props = defineProps({
id: { id: {
@ -143,10 +144,14 @@ const handlePhotoUpdated = (evt = false) => {
:value="entity.user?.emailUser?.email" :value="entity.user?.emailUser?.email"
copy copy
/> />
<VnLv <VnLv :label="t('worker.list.department')">
:label="t('worker.list.department')" <template #value>
:value="entity.department ? entity.department.department.name : null" <span class="link" v-text="entity.department?.department?.name" />
<DepartmentDescriptorProxy
:id="entity.department?.department?.id"
/> />
</template>
</VnLv>
<VnLv :value="entity.phone"> <VnLv :value="entity.phone">
<template #label> <template #label>
{{ t('globals.phone') }} {{ t('globals.phone') }}

View File

@ -133,6 +133,7 @@ function reloadData() {
option-value="id" option-value="id"
id="deviceProductionFk" id="deviceProductionFk"
hide-selected hide-selected
data-cy="pda-dialog-select"
> >
<template #option="scope"> <template #option="scope">
<QItem v-bind="scope.itemProps"> <QItem v-bind="scope.itemProps">

View File

@ -14,6 +14,7 @@ import FormModel from 'components/FormModel.vue';
import CreateBankEntityForm from 'src/components/CreateBankEntityForm.vue'; import CreateBankEntityForm from 'src/components/CreateBankEntityForm.vue';
import VnRadio from 'src/components/common/VnRadio.vue'; import VnRadio from 'src/components/common/VnRadio.vue';
import { useState } from 'src/composables/useState'; import { useState } from 'src/composables/useState';
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
const { t } = useI18n(); const { t } = useI18n();
const user = useState().getUser(); const user = useState().getUser();
@ -149,27 +150,11 @@ async function autofillBic(worker) {
hide-selected hide-selected
:rules="validate('Worker.company')" :rules="validate('Worker.company')"
/> />
<VnSelect <VnSelectWorker
:label="t('worker.summary.boss')" :label="t('worker.summary.boss')"
v-model="data.bossFk" v-model="data.bossFk"
url="Workers/search"
option-value="id"
option-label="name"
hide-selected
:rules="validate('Worker.boss')" :rules="validate('Worker.boss')"
> />
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection>
<QItemLabel>{{ scope.opt.name }}</QItemLabel>
<QItemLabel caption
>{{ scope.opt.nickname }},
{{ scope.opt.code }}
</QItemLabel>
</QItemSection>
</QItem>
</template>
</VnSelect>
</VnRow> </VnRow>
<VnRow> <VnRow>
<VnInput <VnInput

View File

@ -18,6 +18,7 @@ import RightMenu from 'src/components/common/RightMenu.vue';
import WorkerFilter from './WorkerFilter.vue'; import WorkerFilter from './WorkerFilter.vue';
import { useState } from 'src/composables/useState'; import { useState } from 'src/composables/useState';
import axios from 'axios'; import axios from 'axios';
import VnSelectWorker from 'src/components/common/VnSelectWorker.vue';
const { t } = useI18n(); const { t } = useI18n();
const tableRef = ref(); const tableRef = ref();
@ -260,26 +261,10 @@ async function autofillBic(worker) {
option-label="code" option-label="code"
hide-selected hide-selected
/> />
<VnSelect <VnSelectWorker
:label="t('worker.summary.boss')" :label="t('worker.summary.boss')"
v-model="data.bossFk" v-model="data.bossFk"
url="Workers/search" />
option-value="id"
option-label="name"
hide-selected
>
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection>
<QItemLabel>{{ scope.opt.name }}</QItemLabel>
<QItemLabel caption
>{{ scope.opt.nickname }},
{{ scope.opt.code }}
</QItemLabel>
</QItemSection>
</QItem>
</template>
</VnSelect>
</VnRow> </VnRow>
<VnRow> <VnRow>
<VnInput v-model="data.fi" :label="t('worker.create.fi')" /> <VnInput v-model="data.fi" :label="t('worker.create.fi')" />
@ -376,6 +361,7 @@ async function autofillBic(worker) {
<i18n> <i18n>
es: es:
Create worker: Crear trabajador
Search worker: Buscar trabajador Search worker: Buscar trabajador
You can search by worker id or name: Puedes buscar por id o nombre del trabajador You can search by worker id or name: Puedes buscar por id o nombre del trabajador
</i18n> </i18n>

View File

@ -32,7 +32,12 @@ const agencyOptions = ref([]);
<FormModel :url="`Zones/${route.params.id}`" auto-load model="zone"> <FormModel :url="`Zones/${route.params.id}`" auto-load model="zone">
<template #form="{ data, validate }"> <template #form="{ data, validate }">
<VnRow> <VnRow>
<VnInput :label="t('Name')" clearable v-model="data.name" /> <VnInput
data-cy="zone-basic-data-name"
:label="t('Name')"
clearable
v-model="data.name"
/>
</VnRow> </VnRow>
<VnRow> <VnRow>

View File

@ -1,5 +1,5 @@
<script setup> <script setup>
import { ref, onUnmounted } from 'vue'; import { ref } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import ZoneEventsPanel from './ZoneEventsPanel.vue'; import ZoneEventsPanel from './ZoneEventsPanel.vue';
@ -40,8 +40,6 @@ const onZoneEventFormClose = () => {
showZoneEventForm.value = false; showZoneEventForm.value = false;
zoneEventsFormProps.value = {}; zoneEventsFormProps.value = {};
}; };
onUnmounted(() => (stateStore.rightDrawer = false));
</script> </script>
<template> <template>

View File

@ -28,11 +28,7 @@ const agencies = ref([]);
@on-fetch="(data) => (agencies = data)" @on-fetch="(data) => (agencies = data)"
auto-load auto-load
/> />
<VnFilterPanel <VnFilterPanel :data-key="props.dataKey" :search-button="true">
:data-key="props.dataKey"
:search-button="true"
:hidden-tags="['search']"
>
<template #tags="{ tag }"> <template #tags="{ tag }">
<div class="q-gutter-x-xs"> <div class="q-gutter-x-xs">
<strong>{{ t(`filterPanel.${tag.label}`) }}: </strong> <strong>{{ t(`filterPanel.${tag.label}`) }}: </strong>

View File

@ -0,0 +1,20 @@
describe('ItemLastEntries', () => {
beforeEach(() => {
cy.viewport(1280, 720);
cy.login('buyer');
cy.visit('/#/item/1/last-entries');
cy.intercept('GET', /.*lastEntriesFilter/).as('item');
cy.waitForElement('tbody');
});
it('should filter by agency', () => {
cy.get('tbody > tr')
.its('length')
.then((rowCount) => {
cy.get('[data-cy="hideInventory"]').click();
cy.wait('@item');
cy.waitForElement('tbody');
cy.get('tbody > tr').should('have.length.greaterThan', rowCount);
});
});
});

View File

@ -1,6 +1,5 @@
describe('WorkerPda', () => { describe('WorkerPda', () => {
const deviceProductionField = const select = '[data-cy="pda-dialog-select"]';
'.vn-row > .q-field > .q-field__inner > .q-field__control > .q-field__control-container';
beforeEach(() => { beforeEach(() => {
cy.viewport(1920, 1080); cy.viewport(1920, 1080);
cy.login('developer'); cy.login('developer');
@ -9,7 +8,8 @@ describe('WorkerPda', () => {
it('assign pda', () => { it('assign pda', () => {
cy.get('.q-page-sticky > div > .q-btn > .q-btn__content > .q-icon').click(); cy.get('.q-page-sticky > div > .q-btn > .q-btn__content > .q-icon').click();
cy.get(deviceProductionField).type('{downArrow}{enter}'); cy.get(select).click();
cy.get(select).type('{downArrow}{enter}');
cy.get('.q-notification__message').should('have.text', 'Data created'); cy.get('.q-notification__message').should('have.text', 'Data created');
}); });

View File

@ -1,5 +1,6 @@
describe('ZoneBasicData', () => { describe('ZoneBasicData', () => {
const notification = '.q-notification__message'; const notification = '.q-notification__message';
const priceBasicData = '[data-cy="Price_input"]';
beforeEach(() => { beforeEach(() => {
cy.viewport(1280, 720); cy.viewport(1280, 720);
@ -8,14 +9,20 @@ describe('ZoneBasicData', () => {
}); });
it('should throw an error if the name is empty', () => { it('should throw an error if the name is empty', () => {
cy.get('.q-card > :nth-child(1)').clear(); cy.get('[data-cy="zone-basic-data-name"] input').type('{selectall}{backspace}');
cy.get('.q-btn-group > .q-btn--standard').click(); cy.get('.q-btn-group > .q-btn--standard').click();
cy.get(notification).should('contains.text', "can't be blank"); cy.get(notification).should('contains.text', "can't be blank");
}); });
it('should throw an error if the price is empty', () => {
cy.get(priceBasicData).clear();
cy.get('.q-btn-group > .q-btn--standard').click();
cy.get(notification).should('contains.text', 'cannot be blank');
});
it("should edit the basicData's zone", () => { it("should edit the basicData's zone", () => {
cy.get('.q-card > :nth-child(1)').type(' modified'); cy.get('.q-card > :nth-child(1)').type(' modified');
cy.get('.q-btn-group > .q-btn--standard').click(); cy.get('.q-btn-group > .q-btn--standard').click();
cy.get(notification).should('contains.text', 'Data saved'); cy.checkNotification('Data saved');
}); });
}); });