diff --git a/.eslintrc.yml b/.eslintrc.yml index edbc47195..0d74348f2 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -36,3 +36,7 @@ rules: jasmine/no-focused-tests: 0 jasmine/prefer-toHaveBeenCalledWith: 0 arrow-spacing: ["error", { "before": true, "after": true }] + no-restricted-syntax: + - "error" + - selector: "NewExpression[callee.name='Date']" + message: "Use Date.vnNew() instead of new Date()." diff --git a/CHANGELOG.md b/CHANGELOG.md index 57848aa7f..73ebecabc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,117 @@ +# Version 24.48 - 2024-11-25 + +### Added 🆕 + +- feat: refs #4948 Added ticket_selfConsumptionPackaging by:guillermo +- feat: refs #6818 add config table by:jorgep +- feat: refs #6818 add records by:jorgep +- feat: refs #6818 saysimple integration by:jorgep +- feat: refs #6845 userInterface by:sergiodt +- feat: refs #6869 add back by:jorgep +- feat: refs #6869 define model by:jorgep +- feat: refs #6869 refs#6869 itemShelving_get (origin/6869-createGetDetails) by:sergiodt +- feat: refs #7006 itemTypeLog by:guillermo +- feat: refs #7006 itemTypeLog created by:guillermo +- feat: refs #7006 Requested changes by:guillermo +- feat: refs #7193 added scope in parking model by:Jon +- feat: refs #7244 Requested changes by:guillermo +- feat: refs #7266 Added details and improvements in item label reports by:guillermo +- feat: refs #7266 buyFkForPrint by:sergiodt +- feat: refs #7266 First commit by:guillermo +- feat: refs #7266 Item label barcode by:guillermo +- feat: refs #7266 Item label QR by:guillermo +- feat: refs #7266 Item label QR finished by:guillermo +- feat: refs #7266 Minor change by:guillermo +- feat: refs #7266 Print corrections by:guillermo +- feat: refs #7266 Requested changes and improvements by:guillermo +- feat: refs #7266 Requested changes and query optimization by:guillermo +- feat: refs #7266 Version by:guillermo +- feat: refs #7289 #7289 apply option 1 by:Javier Segarra +- feat: refs #7289 #7289 remove bad translation by:Javier Segarra +- feat: refs #7524 restrict fields by:jorgep +- feat: refs #7641 fine tunning by:jorgep +- feat: refs #7641 improve style by:jorgep +- feat: refs #7743 add simple spec for sendMail by:pablone +- feat: refs #7743 add try catch stmt to the test by:pablone +- feat: refs #7874 add default type by:jorgep +- feat: refs #7874 use name by:jorgep +- feat: refs #7920 Added ItemShelving in shelvingLog by:guillermo +- feat: refs #7921 refs#7921 sendLostExpedition by:sergiodt +- feat: refs #7922 refs #792 scanOrder by:sergiodt +- feat: refs #7943 quitar lectura en metodos comunes by:jgallego +- feat: refs #7943 return just the required content by:jorgep +- feat: refs #7943 usa back con permisos by:jgallego +- feat: refs #8020 machineWorkerDeprecated by:sergiodt +- feat: refs #8057 Added data updates by:guillermo +- feat: refs #8057 Added data updates (origin/8057-geoFk) by:guillermo +- feat: refs #8057 Added geoFk columns by:guillermo +- feat: refs #8057 Fix version by:guillermo +- feat: refs #8057 More precision in getGeo by:guillermo +- feat: refs #8057 Requested changes by:guillermo +- feat: refs #8071 quitar esquema by:robert +- feat: refs #8071 travel_weeklyClone by:robert +- feat: refs #8080 Added column comment by:guillermo +- feat: refs #8083 add prop by:jorgep +- feat: refs #8087 Traspasar redadas a travels by:Carlos Andrés +- feat: refs #8099 refs#8099 addComplmentSalary by:sergiodt +- feat: refs #8124 Enrutadores nuevos requerimientos by:Carlos Andrés +- feat: refs #8124 Enrutadores nuevos requerimientos (origin/8124-enrutadoresNuevosRequerimientos) by:Carlos Andrés +- feat: refs #8127 entry_getCommission by:robert +- feat: refs #8127 quitar esquemas by:robert +- feat: refs #8135 refs#8135 updateTicketACL (origin/8135-ticketACL) by:sergiodt +- feat: refs #8143 deprecate recoverPass and sync from account.user by:ivanm +- feat: refs #8150 movExpeditions by:sergiodt +- feat: refs #8151 Added test by:guillermo +- feat: refs #8151 moveExpeditions by:guillermo +- feat: refs #8151 Requested changes by:guillermo +- feat(Supplier): refs #6828 add companySize by:alexm +- refactor: refs #7641 entry report style by:jorgep + +### Changed 📦 + +- refactor: refs #6920 add correct role by:alexm +- refactor: refs #7242 Deleted select column by:guillermo +- refactor: refs #7457 Added from param if not exists by:guillermo +- refactor: refs #7641 entry report style by:jorgep +- refactor: refs #7715 Deleted hasNewLabelMrwMethod column by:guillermo +- refactor: refs #7920 Fix tests by:guillermo +- refactor: refs #7920 Fix version by:guillermo +- refactor: refs #7920 itemShelvingLog by:guillermo +- refactor: refs #7920 Main change by:guillermo +- refactor: refs #7920 Major changes by:guillermo +- refactor: refs #7920 No changes in itemShelvingLog table by:guillermo +- refactor: refs #7920 Requested changes by:guillermo +- refactor: refs #7950 Created cmr model (7950-cmrModelUnify) by:guillermo +- refactor: refs #7950 Requested changes by:guillermo +- refactor: refs #8153 Optimized order_getTax by:guillermo + +### Fixed 🛠️ + +- fix: clean deletes also zoneEvent range records by:jgallego +- fix: more data for fixture.before by:Pako +- fix: refs #4948 Tests by:guillermo +- fix: refs #6644 email and translations by:carlossa +- fix: refs #6818 add config by:jorgep +- fix: refs #6818 add defaultChannel by:jorgep +- fix: refs #6818 use right col type by:jorgep +- fix: refs #6869 use id as primaryKey by:jorgep +- fix: refs #7244 Added collection ACL by:guillermo +- fix: refs #7283 item filters by:carlossa +- fix: refs #7283 remove by:carlossa +- fix: refs #7283 remove tests by:carlossa +- fix: refs #7283 tback by:carlossa +- fix: refs #7323 add remaining fields (origin/7323-warfix-addRemainingFields) by:jorgep +- fix: refs #7457 add with on select to reduce by:pablone +- fix: refs #7457 empty commit for gitea by:pablone +- fix: refs #7457 error on empty from param and add translate by:pablone +- fix: refs #7457 remove group by calc time reduce bellow 1s by:pablone +- fix: refs #7457 remove translate and use param definition for restriction by:pablone +- fix: refs #7641 align columns by:jorgep +- fix: refs #7641 drop boilerplate code by:jorgep +- fix: refs #7920 refs#7920 itemShelvingLog by:sergiodt +- fix: refs #8153 Version by:guillermo +- revert cd7ed6987a88e00275b562d3248f368b6333620c by:Javier Segarra + # Version 24.38 - 2024-09-17 ### Added 🆕 diff --git a/back/methods/collection/getSales.js b/back/methods/collection/getSales.js index a9e5f2e60..f3575672f 100644 --- a/back/methods/collection/getSales.js +++ b/back/methods/collection/getSales.js @@ -29,10 +29,8 @@ module.exports = Self => { }); Self.getSales = async(ctx, collectionOrTicketFk, print, source, options) => { - const models = Self.app.models; const userId = ctx.req.accessToken.userId; const myOptions = {userId}; - const $t = ctx.req.__; if (typeof options == 'object') Object.assign(myOptions, options); @@ -59,22 +57,6 @@ module.exports = Self => { if (print) await Self.rawSql('CALL vn.collection_printSticker(?,NULL)', [id], myOptions); - for (let ticket of tickets) { - if (ticket.observaciones) { - let observations = ticket.observaciones.split(' '); - - for (let observation of observations) { - const salesPerson = ticket.salesPersonFk; - if (observation.startsWith('#') || observation.startsWith('@')) { - await models.Chat.send(ctx, - observation, - $t('ticketCommercial', {ticket: ticket.ticketFk, salesPerson}) - ); - } - } - } - } - return getCollection(id, tickets, sales, placements, myOptions); }; diff --git a/back/methods/collection/getTickets.js b/back/methods/collection/getTickets.js index 3c2f6cb2d..677c9e444 100644 --- a/back/methods/collection/getTickets.js +++ b/back/methods/collection/getTickets.js @@ -63,7 +63,8 @@ module.exports = Self => { p.pickingOrder pickingOrder, iss.id itemShelvingSaleFk, iss.isPicked, - iss.itemShelvingFk + iss.itemShelvingFk, + st.code stateCode FROM ticketCollection tc LEFT JOIN collection c ON c.id = tc.collectionFk JOIN sale s ON s.ticketFk = tc.ticketFk @@ -77,6 +78,7 @@ module.exports = Self => { LEFT JOIN parking p ON p.id = sh.parkingFk LEFT JOIN itemColor ic ON ic.itemFk = s.itemFk LEFT JOIN origin o ON o.id = i.originFk + LEFT JOIN state st ON st.id = sg.stateFk WHERE tc.collectionFk = ? GROUP BY s.id, ish.id, p.code, p2.code UNION ALL @@ -104,7 +106,8 @@ module.exports = Self => { p.pickingOrder, iss.id itemShelvingSaleFk, iss.isPicked, - iss.itemShelvingFk + iss.itemShelvingFk, + st.code stateCode FROM sectorCollection sc JOIN sectorCollectionSaleGroup ss ON ss.sectorCollectionFk = sc.id JOIN saleGroup sg ON sg.id = ss.saleGroupFk @@ -118,6 +121,7 @@ module.exports = Self => { LEFT JOIN parking p ON p.id = sh.parkingFk LEFT JOIN itemColor ic ON ic.itemFk = s.itemFk LEFT JOIN origin o ON o.id = i.originFk + LEFT JOIN state st ON st.id = sg.stateFk WHERE sc.id = ? AND sgd.saleGroupFk GROUP BY s.id, ish.id, p.code, p2.code`, [id, id], myOptions); diff --git a/back/methods/collection/spec/assign.spec.js b/back/methods/collection/spec/assign.spec.js index 745343819..b00631d22 100644 --- a/back/methods/collection/spec/assign.spec.js +++ b/back/methods/collection/spec/assign.spec.js @@ -28,9 +28,10 @@ describe('ticket assign()', () => { await tx.rollback(); }); - it('should throw an error when there is not picking tickets', async() => { + it('should throw an error when there are no picking tickets', async() => { try { await models.Collection.assign(ctx, options); + fail('Expected an error to be thrown, but none was thrown.'); } catch (e) { expect(e.message).toEqual('There are not picking tickets'); } diff --git a/back/methods/mrw-config/cancelShipment.js b/back/methods/mrw-config/cancelShipment.js index 98aa8be39..e96d6d694 100644 --- a/back/methods/mrw-config/cancelShipment.js +++ b/back/methods/mrw-config/cancelShipment.js @@ -24,12 +24,13 @@ module.exports = Self => { Self.cancelShipment = async expeditionFk => { const models = Self.app.models; - const mrw = await models.MrwConfig.findOne(); const {externalId} = await models.Expedition.findById(expeditionFk); const clientType = await models.MrwConfig.getClientType(expeditionFk); const template = fs.readFileSync(__dirname + '/cancelShipment.ejs', 'utf-8'); const renderedXml = ejs.render(template, {mrw, externalId, clientType}); + + await Self.rawSql('CALL util.debugAdd(?,?);', ['cancelShipment', renderedXml]); const response = await axios.post(mrw.url, renderedXml, { headers: { 'Content-Type': 'application/soap+xml; charset=utf-8' @@ -37,12 +38,11 @@ module.exports = Self => { }); const xmlString = response.data; + await Self.rawSql('CALL util.debugAdd(?,?);', ['cancelShipmentResponse', xmlString]); const parser = new DOMParser(); const xmlDoc = parser.parseFromString(xmlString, 'text/xml'); - await Self.rawSql('CALL util.debugAdd(?,?);', ['cancelShipment', xmlDoc]); - const result = xmlDoc.getElementsByTagName('Mensaje')[0].textContent; - return result.toLowerCase().includes('se ha cancelado correctamente'); + return ['no se ha encontrado', 'se ha cancelado correctamente'].some(res => result.toLowerCase().includes(res)); }; }; diff --git a/back/methods/url/getUrl.js b/back/methods/url/getUrl.js index 5c6e5655f..fa3f7fdad 100644 --- a/back/methods/url/getUrl.js +++ b/back/methods/url/getUrl.js @@ -22,7 +22,7 @@ module.exports = Self => { const url = await Self.app.models.Url.findOne({ where: { appName, - environment: process.env.NODE_ENV || 'dev' + environment: process.env.NODE_ENV || 'development' } }); return url?.url; diff --git a/back/methods/workerActivity/add.js b/back/methods/workerActivity/add.js index 4592a0797..89131491d 100644 --- a/back/methods/workerActivity/add.js +++ b/back/methods/workerActivity/add.js @@ -31,7 +31,7 @@ module.exports = Self => { return await Self.rawSql(` INSERT INTO workerActivity (workerFk, workerActivityTypeFk, model) SELECT ?, ?, ? - FROM workerTimeControlParams wtcp + FROM workerTimeControlConfig wtcc LEFT JOIN ( SELECT wa.workerFk, wa.created, @@ -44,7 +44,7 @@ module.exports = Self => { ) sub ON TRUE WHERE sub.workerFk IS NULL OR sub.code <> ? - OR TIMESTAMPDIFF(SECOND, sub.created, util.VN_NOW()) > wtcp.dayBreak;` + OR TIMESTAMPDIFF(SECOND, sub.created, util.VN_NOW()) > wtcc.dayBreak;` , [userId, code, model, userId, code], myOptions); }; }; diff --git a/back/model-config.json b/back/model-config.json index b543071c9..e0bc92200 100644 --- a/back/model-config.json +++ b/back/model-config.json @@ -133,6 +133,9 @@ "Postcode": { "dataSource": "vn" }, + "Prefix": { + "dataSource": "vn" + }, "ReferenceRate": { "dataSource": "vn" }, diff --git a/back/models/expedition_PrintOut.json b/back/models/expedition_PrintOut.json index dd49b0234..23a2fdbc4 100644 --- a/back/models/expedition_PrintOut.json +++ b/back/models/expedition_PrintOut.json @@ -14,9 +14,6 @@ }, "itemFk": { "type": "number" - }, - "isChecked": { - "type": "boolean" } } } \ No newline at end of file diff --git a/back/models/prefix.json b/back/models/prefix.json new file mode 100644 index 000000000..762354caa --- /dev/null +++ b/back/models/prefix.json @@ -0,0 +1,27 @@ +{ + "name": "Prefix", + "base": "VnModel", + "options": { + "mysql": { + "table": "pbx.prefix" + } + }, + "properties": { + "country": { + "type": "string", + "id": true + }, + "prefix": { + "type": "string" + } + }, + "acls": [ + { + "property": "*", + "accessType": "READ", + "principalType": "ROLE", + "principalId": "employee", + "permission": "ALLOW" + } + ] +} \ No newline at end of file diff --git a/db/dump/.dump/data.sql b/db/dump/.dump/data.sql index 6bcfe2c9f..4700d0066 100644 --- a/db/dump/.dump/data.sql +++ b/db/dump/.dump/data.sql @@ -4,7 +4,7 @@ USE `util`; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; -INSERT INTO `version` VALUES ('vn-database','11311','315864403260623fede9f0471ef3d9036faf23b1','2024-11-12 08:00:59','11336'); +INSERT INTO `version` VALUES ('vn-database','11358','45f7b60f1b43b24505a3e9abc6738dc484ad4fd5','2024-11-26 12:27:58','11365'); INSERT INTO `versionLog` VALUES ('vn-database','10107','00-firstScript.sql','jenkins@10.0.2.69','2022-04-23 10:53:53',NULL,NULL); INSERT INTO `versionLog` VALUES ('vn-database','10112','00-firstScript.sql','jenkins@10.0.2.69','2022-05-09 09:14:53',NULL,NULL); @@ -1065,11 +1065,50 @@ INSERT INTO `versionLog` VALUES ('vn-database','11290','00-firstScript.sql','jen INSERT INTO `versionLog` VALUES ('vn-database','11291','00-firstScript.sql','jenkins@db-proxy1.servers.dc.verdnatura.es','2024-10-17 09:10:30',NULL,NULL); INSERT INTO `versionLog` VALUES ('vn-database','11294','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-12 08:00:37',NULL,NULL); INSERT INTO `versionLog` VALUES ('vn-database','11295','00-firstScript.sql','jenkins@db-proxy1.servers.dc.verdnatura.es','2024-10-10 08:45:13',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11297','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-26 07:05:29',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11297','01-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-26 07:05:30',NULL,NULL); INSERT INTO `versionLog` VALUES ('vn-database','11298','00-closure.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-12 08:00:37',NULL,NULL); INSERT INTO `versionLog` VALUES ('vn-database','11300','00-firstScript.sql','jenkins@db-proxy1.servers.dc.verdnatura.es','2024-10-18 08:27:05',NULL,NULL); INSERT INTO `versionLog` VALUES ('vn-database','11302','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-12 08:00:57',NULL,NULL); INSERT INTO `versionLog` VALUES ('vn-database','11308','00-firstScript.sql','jenkins@db-proxy1.servers.dc.verdnatura.es','2024-10-23 12:41:55',NULL,NULL); INSERT INTO `versionLog` VALUES ('vn-database','11311','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-12 08:00:57',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11314','00-restrictedAsterisk.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-26 07:05:30',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11315','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-26 07:05:30',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11316','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-26 07:05:30',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11317','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-26 07:05:30',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11319','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-26 07:05:30',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11321','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-26 07:05:30',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11324','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-13 10:49:47',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11325','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-26 07:05:30',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11326','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-26 07:05:30',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11330','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-26 07:05:30',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11331','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-26 07:05:30',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11336','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-26 07:05:30',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11337','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-26 07:05:30',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11338','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-12 09:14:12',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11339','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-26 07:05:30',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11342','00-itemShelving.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-26 07:06:34',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11342','01-itemShelving.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-26 07:06:35',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11342','02-itemShelving.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-26 07:06:37',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11342','03-itemShelving.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-26 07:11:07',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11342','04-itemShelvingLog.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-26 07:11:07',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11342','05-itemShelvingLog.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-26 07:11:07',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11342','06-itemShelvingLog.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-26 07:11:07',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11343','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-26 07:11:07',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11344','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-13 17:36:45',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11344','01-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-13 17:46:26',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11345','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-26 07:11:08',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11346','00-address.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-26 07:15:02',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11346','01-client.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-26 07:16:29',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11346','02-supplier.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-26 07:27:57',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11347','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-26 07:27:57',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11348','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-26 07:28:14',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11349','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-26 07:28:14',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11350','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-26 07:28:14',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11353','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-26 07:28:14',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11355','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-26 07:28:14',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11357','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-26 07:28:16',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11358','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-26 07:28:21',NULL,NULL); /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; @@ -1973,13 +2012,11 @@ INSERT INTO `ACL` VALUES (605,'Ticket','sendSms','WRITE','ALLOW','ROLE','employe INSERT INTO `ACL` VALUES (606,'Ticket','isLocked','READ','ALLOW','ROLE','employee',NULL); INSERT INTO `ACL` VALUES (607,'Ticket','freightCost','READ','ALLOW','ROLE','employee',NULL); INSERT INTO `ACL` VALUES (608,'Ticket','getComponentsSum','READ','ALLOW','ROLE','employee',NULL); -INSERT INTO `ACL` VALUES (609,'Ticket','updateAttributes','WRITE','ALLOW','ROLE','delivery',NULL); +INSERT INTO `ACL` VALUES (609,'Ticket','updateAttributes','WRITE','ALLOW','ROLE','deliveryAssistant',10578); INSERT INTO `ACL` VALUES (610,'Ticket','deliveryNoteCsv','READ','ALLOW','ROLE','employee',NULL); INSERT INTO `ACL` VALUES (611,'State','find','READ','ALLOW','ROLE','employee',NULL); INSERT INTO `ACL` VALUES (612,'State','findById','READ','ALLOW','ROLE','employee',NULL); INSERT INTO `ACL` VALUES (613,'State','findOne','READ','ALLOW','ROLE','employee',NULL); -INSERT INTO `ACL` VALUES (614,'Worker','find','READ','ALLOW','ROLE','employee',NULL); -INSERT INTO `ACL` VALUES (616,'Worker','findOne','READ','ALLOW','ROLE','employee',NULL); INSERT INTO `ACL` VALUES (617,'Worker','filter','READ','ALLOW','ROLE','employee',NULL); INSERT INTO `ACL` VALUES (618,'Worker','getWorkedHours','READ','ALLOW','ROLE','employee',NULL); INSERT INTO `ACL` VALUES (619,'Worker','active','READ','ALLOW','ROLE','employee',NULL); @@ -2045,7 +2082,6 @@ INSERT INTO `ACL` VALUES (716,'ExpeditionMistake','*','WRITE','ALLOW','ROLE','em INSERT INTO `ACL` VALUES (717,'WorkerMistake','*','WRITE','ALLOW','ROLE','coolerAssist',NULL); INSERT INTO `ACL` VALUES (718,'MistakesTypes','*','WRITE','ALLOW','ROLE','coolerAssist',NULL); INSERT INTO `ACL` VALUES (719,'MistakeType','*','READ','ALLOW','ROLE','employee',NULL); -INSERT INTO `ACL` VALUES (720,'MachineWorker','*','READ','ALLOW','ROLE','coolerAssist',NULL); INSERT INTO `ACL` VALUES (721,'Printer','*','READ','ALLOW','ROLE','employee',NULL); INSERT INTO `ACL` VALUES (722,'SaleMistake','*','WRITE','ALLOW','ROLE','production',NULL); INSERT INTO `ACL` VALUES (723,'Item','setVisibleDiscard','WRITE','ALLOW','ROLE','employee',NULL); @@ -2083,13 +2119,10 @@ INSERT INTO `ACL` VALUES (755,'Route','findById','READ','ALLOW','ROLE','employee INSERT INTO `ACL` VALUES (756,'Route','findOne','READ','ALLOW','ROLE','employee',NULL); INSERT INTO `ACL` VALUES (757,'Route','getRoutesByWorker','READ','ALLOW','ROLE','employee',NULL); INSERT INTO `ACL` VALUES (758,'Route','canViewAllRoute','READ','ALLOW','ROLE','deliveryAssistant',NULL); -INSERT INTO `ACL` VALUES (759,'Route','cmr','READ','ALLOW','ROLE','employee',NULL); -INSERT INTO `ACL` VALUES (760,'Cmr','downloadZip','READ','ALLOW','ROLE','employee',NULL); INSERT INTO `ACL` VALUES (761,'Route','downloadZip','READ','ALLOW','ROLE','employee',NULL); INSERT INTO `ACL` VALUES (762,'Route','filter','READ','ALLOW','ROLE','employee',NULL); INSERT INTO `ACL` VALUES (763,'Route','getByWorker','READ','ALLOW','ROLE','employee',NULL); INSERT INTO `ACL` VALUES (764,'Route','getDeliveryPoint','READ','ALLOW','ROLE','employee',NULL); -INSERT INTO `ACL` VALUES (765,'Route','cmrs','READ','ALLOW','ROLE','employee',NULL); INSERT INTO `ACL` VALUES (766,'Route','getSuggestedTickets','READ','ALLOW','ROLE','employee',NULL); INSERT INTO `ACL` VALUES (767,'Route','getTickets','READ','ALLOW','ROLE','employee',NULL); INSERT INTO `ACL` VALUES (768,'Route','guessPriority','WRITE','ALLOW','ROLE','employee',NULL); @@ -2130,7 +2163,6 @@ INSERT INTO `ACL` VALUES (802,'MailAliasAccount','deleteById','WRITE','ALLOW','R INSERT INTO `ACL` VALUES (804,'DeviceProduction','*','READ','ALLOW','ROLE','employee',NULL); INSERT INTO `ACL` VALUES (805,'Collection','assign','WRITE','ALLOW','ROLE','production',NULL); INSERT INTO `ACL` VALUES (806,'ExpeditionPallet','getPallet','READ','ALLOW','ROLE','production',NULL); -INSERT INTO `ACL` VALUES (807,'MachineWorker','updateInTime','WRITE','ALLOW','ROLE','production',NULL); INSERT INTO `ACL` VALUES (808,'MobileAppVersionControl','getVersion','READ','ALLOW','ROLE','employee',NULL); INSERT INTO `ACL` VALUES (809,'SaleTracking','delete','WRITE','ALLOW','ROLE','production',NULL); INSERT INTO `ACL` VALUES (810,'SaleTracking','updateTracking','WRITE','ALLOW','ROLE','production',NULL); @@ -2216,7 +2248,7 @@ INSERT INTO `ACL` VALUES (895,'ItemShelvingLog','*','READ','ALLOW','ROLE','produ INSERT INTO `ACL` VALUES (901,'WorkerTimeControl','sendMail','WRITE','ALLOW','ROLE','system',NULL); INSERT INTO `ACL` VALUES (902,'Entry','filter','READ','ALLOW','ROLE','supplier',NULL); INSERT INTO `ACL` VALUES (903,'Entry','getBuys','READ','ALLOW','ROLE','supplier',NULL); -INSERT INTO `ACL` VALUES (904,'Entry','buyLabel','READ','ALLOW','ROLE','supplier',NULL); +INSERT INTO `ACL` VALUES (904,'Entry','buyLabelSupplier','READ','ALLOW','ROLE','supplier',10578); INSERT INTO `ACL` VALUES (905,'AddressWaste','*','READ','ALLOW','ROLE','production',NULL); INSERT INTO `ACL` VALUES (906,'Entry','print','READ','ALLOW','ROLE','supplier',NULL); INSERT INTO `ACL` VALUES (907,'Expedition_PrintOut','*','*','ALLOW','ROLE','production',NULL); @@ -2230,7 +2262,6 @@ INSERT INTO `ACL` VALUES (914,'VnToken','killSession','*','ALLOW','ROLE','develo INSERT INTO `ACL` VALUES (915,'ACL','*','WRITE','ALLOW','ROLE','developerBoss',10578); INSERT INTO `ACL` VALUES (917,'InvoiceOut','refundAndInvoice','WRITE','ALLOW','ROLE','administrative',10578); INSERT INTO `ACL` VALUES (918,'Worker','__get__descriptor','READ','ALLOW','ROLE','employee',10578); -INSERT INTO `ACL` VALUES (919,'Worker','findById','READ','ALLOW','ROLE','employee',10578); INSERT INTO `ACL` VALUES (920,'QuadmindsApiConfig','*','*','ALLOW','ROLE','delivery',19295); INSERT INTO `ACL` VALUES (922,'SaleGroup','*','WRITE','ALLOW','ROLE','production',19294); INSERT INTO `ACL` VALUES (923,'Worker','__get__advancedSummary','READ','ALLOW','ROLE','hr',10578); @@ -2250,6 +2281,23 @@ INSERT INTO `ACL` VALUES (936,'Device','handleUser','*','ALLOW','ROLE','employee INSERT INTO `ACL` VALUES (937,'WorkerTimeControlMail','count','READ','ALLOW','ROLE','employee',10578); INSERT INTO `ACL` VALUES (938,'Worker','__get__mail','READ','ALLOW','ROLE','hr',10578); INSERT INTO `ACL` VALUES (939,'Machine','*','*','ALLOW','ROLE','productionBoss',10578); +INSERT INTO `ACL` VALUES (940,'ItemTypeLog','find','READ','ALLOW','ROLE','employee',10578); +INSERT INTO `ACL` VALUES (941,'Entry','buyLabel','READ','ALLOW','ROLE','employee',10578); +INSERT INTO `ACL` VALUES (942,'Cmr','filter','READ','ALLOW','ROLE','production',10578); +INSERT INTO `ACL` VALUES (943,'Cmr','downloadZip','READ','ALLOW','ROLE','production',10578); +INSERT INTO `ACL` VALUES (944,'Cmr','print','READ','ALLOW','ROLE','production',10578); +INSERT INTO `ACL` VALUES (945,'Collection','create','WRITE','ALLOW','ROLE','productionBoss',10578); +INSERT INTO `ACL` VALUES (946,'Collection','upsert','WRITE','ALLOW','ROLE','productionBoss',10578); +INSERT INTO `ACL` VALUES (947,'Collection','replaceById','WRITE','ALLOW','ROLE','productionBoss',10578); +INSERT INTO `ACL` VALUES (948,'Collection','updateAll','WRITE','ALLOW','ROLE','productionBoss',10578); +INSERT INTO `ACL` VALUES (949,'Collection','updateAttributes','WRITE','ALLOW','ROLE','productionBoss',10578); +INSERT INTO `ACL` VALUES (950,'Collection','deleteById','WRITE','ALLOW','ROLE','productionBoss',10578); +INSERT INTO `ACL` VALUES (951,'Collection','destroyAll','WRITE','ALLOW','ROLE','productionBoss',10578); +INSERT INTO `ACL` VALUES (952,'Collection','destroyById','WRITE','ALLOW','ROLE','productionBoss',10578); +INSERT INTO `ACL` VALUES (953,'RouteAction','find','READ','ALLOW','ROLE','delivery',10578); +INSERT INTO `ACL` VALUES (954,'RouteComplement','find','READ','ALLOW','ROLE','delivery',10578); +INSERT INTO `ACL` VALUES (955,'RouteComplement','create','WRITE','ALLOW','ROLE','delivery',10578); +INSERT INTO `ACL` VALUES (956,'RouteComplement','deleteById','WRITE','ALLOW','ROLE','delivery',10578); INSERT INTO `fieldAcl` VALUES (1,'Client','name','update','employee'); INSERT INTO `fieldAcl` VALUES (2,'Client','contact','update','employee'); @@ -2581,13 +2629,13 @@ INSERT INTO `department` VALUES (1,'VN','VERDNATURA',1,116,763,0,0,0,0,26,NULL,' INSERT INTO `department` VALUES (22,'shopping','COMPRAS',2,5,NULL,72,0,0,1,1,1,'/1/',NULL,1,NULL,0,0,0,0,NULL,NULL,NULL,NULL); INSERT INTO `department` VALUES (23,'CMA','CAMARA',15,16,NULL,72,1,1,2,0,37,'/1/37/',NULL,0,NULL,0,1,1,1,NULL,NULL,NULL,'PREVIOUS'); INSERT INTO `department` VALUES (31,'it','INFORMATICA',6,7,NULL,72,0,0,1,0,1,'/1/','informatica-cau',1,NULL,0,0,0,0,NULL,NULL,NULL,NULL); -INSERT INTO `department` VALUES (34,'accounting','CONTABILIDAD',8,9,NULL,0,0,0,1,0,1,'/1/',NULL,1,NULL,0,0,0,0,NULL,NULL,NULL,NULL); +INSERT INTO `department` VALUES (34,'accounting','CONTABILIDAD',8,9,NULL,0,0,0,1,0,1,'/1/',NULL,1,NULL,1,0,0,0,NULL,NULL,NULL,NULL); INSERT INTO `department` VALUES (35,'finance','FINANZAS',10,11,NULL,0,0,0,1,0,1,'/1/',NULL,1,'begonya@verdnatura.es',0,0,0,0,NULL,NULL,NULL,NULL); INSERT INTO `department` VALUES (36,'labor','LABORAL',12,13,NULL,0,0,0,1,0,1,'/1/',NULL,1,NULL,0,0,0,0,NULL,NULL,NULL,NULL); INSERT INTO `department` VALUES (37,'PROD','PRODUCCION',14,37,NULL,72,1,1,1,11,1,'/1/',NULL,0,NULL,0,1,1,1,NULL,NULL,NULL,NULL); INSERT INTO `department` VALUES (38,'picking','SACADO',17,18,NULL,72,1,0,2,0,37,'/1/37/',NULL,0,NULL,0,1,0,1,NULL,NULL,NULL,'ON_PREPARATION'); INSERT INTO `department` VALUES (39,'packing','ENCAJADO',19,20,NULL,72,1,0,2,0,37,'/1/37/',NULL,0,NULL,0,0,0,1,NULL,NULL,NULL,'PACKING'); -INSERT INTO `department` VALUES (41,'administration','ADMINISTRACION',38,39,NULL,72,0,0,1,0,1,'/1/',NULL,1,NULL,0,0,0,0,NULL,NULL,NULL,NULL); +INSERT INTO `department` VALUES (41,'administration','ADMINISTRACION',38,39,NULL,72,0,0,1,0,1,'/1/',NULL,1,NULL,1,0,0,0,NULL,NULL,NULL,NULL); INSERT INTO `department` VALUES (43,'VT','VENTAS',40,75,NULL,0,0,0,1,17,1,'/1/',NULL,1,NULL,0,0,0,0,NULL,NULL,NULL,NULL); INSERT INTO `department` VALUES (44,'management','GERENCIA',76,77,NULL,72,0,0,1,0,1,'/1/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,NULL); INSERT INTO `department` VALUES (45,'logistic','LOGISTICA',78,79,NULL,72,0,0,1,0,1,'/1/',NULL,1,NULL,0,0,0,0,NULL,NULL,NULL,NULL); @@ -2630,7 +2678,7 @@ INSERT INTO `department` VALUES (135,'routers','ENRUTADORES',110,111,NULL,0,0,0, INSERT INTO `department` VALUES (136,'heavyVehicles','VEHICULOS PESADOS',112,113,NULL,0,0,0,1,0,1,'/1/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,NULL); INSERT INTO `department` VALUES (137,'sorter','SORTER',114,115,NULL,0,0,0,1,0,1,'/1/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,NULL); INSERT INTO `department` VALUES (139,'spainTeam4','EQUIPO ESPAÑA 4',67,68,3803,0,0,0,2,0,43,'/1/43/','es4_equipo',1,'es4@verdnatura.es',0,0,0,0,NULL,NULL,'5400',NULL); -INSERT INTO `department` VALUES (140,'internationalTeam','EQUIPO INTERNACIONAL',69,70,33320,0,0,0,2,0,43,'/1/43/','int_equipo',1,'international@verdnatura.es',0,0,0,0,NULL,NULL,NULL,NULL); +INSERT INTO `department` VALUES (140,'internationalTeam','EQUIPO INTERNACIONAL',69,70,24065,0,0,0,2,0,43,'/1/43/','int_equipo',1,'international@verdnatura.es',0,0,0,0,NULL,NULL,NULL,NULL); INSERT INTO `department` VALUES (141,NULL,'PREVIA',35,36,NULL,0,1,0,2,0,37,'/1/37/',NULL,0,NULL,0,0,0,1,NULL,NULL,NULL,'PREVIOUS'); INSERT INTO `department` VALUES (146,NULL,'VERDNACOLOMBIA',3,4,NULL,72,0,0,2,0,22,'/1/22/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,NULL); INSERT INTO `department` VALUES (147,'spainTeamAsia','EQUIPO ESPAÑA ASIA',71,72,40214,0,0,0,2,0,43,'/1/43/','esA_equipo',0,'esA@verdnatura.es',0,0,0,0,NULL,NULL,'5500',NULL); diff --git a/db/dump/.dump/privileges.sql b/db/dump/.dump/privileges.sql index 486bec661..d754e62c5 100644 --- a/db/dump/.dump/privileges.sql +++ b/db/dump/.dump/privileges.sql @@ -49,6 +49,7 @@ INSERT IGNORE INTO `db` VALUES ('','geo','developerBoss','Y','Y','Y','Y','N','N' INSERT IGNORE INTO `db` VALUES ('','floranet','developer','Y','Y','Y','Y','N','N','N','N','N','N','N','N','N','N','N','N','Y','N','N','N'); INSERT IGNORE INTO `db` VALUES ('','tmp','guest','Y','Y','Y','Y','N','Y','N','N','N','N','Y','N','N','N','N','N','N','N','N','N'); INSERT IGNORE INTO `db` VALUES ('','util','salix','Y','Y','Y','Y','N','N','N','N','N','N','Y','N','N','N','N','N','Y','N','N','N'); +INSERT IGNORE INTO `db` VALUES ('','srt','maintenanceBoss','Y','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N'); INSERT IGNORE INTO `db` VALUES ('','dipole','developerBoss','Y','Y','Y','Y','N','N','Y','N','N','N','N','N','N','N','N','N','Y','N','N','N'); INSERT IGNORE INTO `db` VALUES ('','bi','developerBoss','Y','Y','Y','Y','N','N','Y','N','N','N','N','N','N','N','N','N','Y','N','N','N'); INSERT IGNORE INTO `db` VALUES ('','sage','developerBoss','Y','Y','Y','Y','N','N','Y','N','N','N','N','N','N','N','N','N','Y','N','N','N'); @@ -941,7 +942,6 @@ INSERT IGNORE INTO `tables_priv` VALUES ('','vn','employee','volumeConfig','alex INSERT IGNORE INTO `tables_priv` VALUES ('','vn','coolerBoss','ticketTrackingState','alexm@%','0000-00-00 00:00:00','Select,Insert,Update',''); INSERT IGNORE INTO `tables_priv` VALUES ('','vn','employee','warehouse','alexm@%','0000-00-00 00:00:00','Select',''); INSERT IGNORE INTO `tables_priv` VALUES ('','vn','employee','role','alexm@%','0000-00-00 00:00:00','Select',''); -INSERT IGNORE INTO `tables_priv` VALUES ('','vn','hr','workCenter','alexm@%','0000-00-00 00:00:00','Select',''); INSERT IGNORE INTO `tables_priv` VALUES ('','vn','grafana','clientCredit','juan@db-proxy2.static.verdnatura.es','0000-00-00 00:00:00','Select',''); INSERT IGNORE INTO `tables_priv` VALUES ('','vn','employee','worker','alexm@%','0000-00-00 00:00:00','Select',''); INSERT IGNORE INTO `tables_priv` VALUES ('','vn','coolerAssist','workerAppTester','alexm@%','0000-00-00 00:00:00','Select',''); @@ -1246,7 +1246,6 @@ INSERT IGNORE INTO `tables_priv` VALUES ('','bs','deliveryAssistant','m3','alexm INSERT IGNORE INTO `tables_priv` VALUES ('','vn','deliveryAssistant','ticketDms','alexm@db-proxy2.static.verdnatura.es','0000-00-00 00:00:00','Select',''); INSERT IGNORE INTO `tables_priv` VALUES ('','vn','deliveryAssistant','time','alexm@db-proxy2.static.verdnatura.es','0000-00-00 00:00:00','Select',''); INSERT IGNORE INTO `tables_priv` VALUES ('','vn2008','deliveryAssistant','v_Articles_botanical','alexm@db-proxy2.static.verdnatura.es','0000-00-00 00:00:00','Select',''); -INSERT IGNORE INTO `tables_priv` VALUES ('','vn','deliveryAssistant','workCenter','alexm@db-proxy2.static.verdnatura.es','0000-00-00 00:00:00','Select',''); INSERT IGNORE INTO `tables_priv` VALUES ('','vn','deliveryAssistant','workerDepartment','alexm@db-proxy2.static.verdnatura.es','0000-00-00 00:00:00','Select',''); INSERT IGNORE INTO `tables_priv` VALUES ('','vn','deliveryAssistant','zoneEvent','alexm@db-proxy2.static.verdnatura.es','0000-00-00 00:00:00','Select,Insert,Delete',''); INSERT IGNORE INTO `tables_priv` VALUES ('','bi','deliveryAssistant','rotacion','alexm@db-proxy2.static.verdnatura.es','0000-00-00 00:00:00','Select',''); @@ -1388,7 +1387,7 @@ INSERT IGNORE INTO `tables_priv` VALUES ('','vn','administrative','entry','jenki INSERT IGNORE INTO `tables_priv` VALUES ('','vn2008','buyer','Cubos_Retorno','guillermo@db-proxy2.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); INSERT IGNORE INTO `tables_priv` VALUES ('','vn','grafana','claimDestination','guillermo@db-proxy1.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); INSERT IGNORE INTO `tables_priv` VALUES ('','vn','grafana','entryConfig','guillermo@db-proxy2.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); -INSERT IGNORE INTO `tables_priv` VALUES ('','vn','administrative','farmingDeliveryNote','guillermo@db-proxy1.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); +INSERT IGNORE INTO `tables_priv` VALUES ('','vn','administrative','farmingDeliveryNote','carlosap@db-proxy2.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select,Insert,Update,Delete',''); INSERT IGNORE INTO `tables_priv` VALUES ('','sage','grafana','TiposIva','guillermo@db-proxy2.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); INSERT IGNORE INTO `tables_priv` VALUES ('','bs','buyer','waste','alexm@db-proxy1.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); INSERT IGNORE INTO `tables_priv` VALUES ('','vn','grafana','clientObservation','guillermo@db-proxy1.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); @@ -1419,13 +1418,9 @@ INSERT IGNORE INTO `tables_priv` VALUES ('','vn','financialBoss','accountDetail' INSERT IGNORE INTO `tables_priv` VALUES ('','vn','adminOfficer','accountDetail','guillermo@db-proxy2.servers.dc.verdnatura.es','0000-00-00 00:00:00','Update',''); INSERT IGNORE INTO `tables_priv` VALUES ('','vn','maintenanceBoss','project','guillermo@db-proxy1.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); INSERT IGNORE INTO `tables_priv` VALUES ('','vn','maintenanceBoss','machineDetail','guillermo@db-proxy1.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); -INSERT IGNORE INTO `tables_priv` VALUES ('','srt','maintenanceBoss','antenna','guillermo@db-proxy1.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); -INSERT IGNORE INTO `tables_priv` VALUES ('','srt','maintenanceBoss','bufferPool','guillermo@db-proxy1.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); -INSERT IGNORE INTO `tables_priv` VALUES ('','srt','maintenanceBoss','enteringLog','guillermo@db-proxy1.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); -INSERT IGNORE INTO `tables_priv` VALUES ('','srt','maintenanceBoss','expeditionLoading','guillermo@db-proxy1.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); -INSERT IGNORE INTO `tables_priv` VALUES ('','srt','maintenanceBoss','failureLog','guillermo@db-proxy1.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); -INSERT IGNORE INTO `tables_priv` VALUES ('','srt','maintenanceBoss','movingLog','guillermo@db-proxy1.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); -INSERT IGNORE INTO `tables_priv` VALUES ('','srt','maintenanceBoss','sorterLog','guillermo@db-proxy1.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); +INSERT IGNORE INTO `tables_priv` VALUES ('','vn','buyerSalesAssistant','route','guillermo@db-proxy2.servers.dc.verdnatura.es','0000-00-00 00:00:00','Update',''); +INSERT IGNORE INTO `tables_priv` VALUES ('','vn','employee','workCenter','guillermo@db-proxy2.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); +INSERT IGNORE INTO `tables_priv` VALUES ('','vn2008','buyerSalesAssistant','Rutas','guillermo@db-proxy2.servers.dc.verdnatura.es','0000-00-00 00:00:00','Update',''); INSERT IGNORE INTO `tables_priv` VALUES ('','vn','buyer','genericAllocation','guillermo@db-proxy2.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select,Insert,Update,Delete',''); INSERT IGNORE INTO `tables_priv` VALUES ('','vn','hr','businessReasonEnd','guillermo@db-proxy2.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); INSERT IGNORE INTO `tables_priv` VALUES ('','vn2008','buyer','buy_edi','alexm@db-proxy2.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); @@ -1463,7 +1458,7 @@ INSERT IGNORE INTO `tables_priv` VALUES ('','vn','deliveryBoss','vehicleDms','gu INSERT IGNORE INTO `tables_priv` VALUES ('','vn','deliveryBoss','vehicleInvoiceIn','guillermo@db-proxy2.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); INSERT IGNORE INTO `tables_priv` VALUES ('','vn','deliveryBoss','vehicleNotes','guillermo@db-proxy2.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); INSERT IGNORE INTO `tables_priv` VALUES ('','vn','production','saleGroup','guillermo@db-proxy1.servers.dc.verdnatura.es','0000-00-00 00:00:00','Insert,Update,Delete',''); -INSERT IGNORE INTO `tables_priv` VALUES ('','srt','maintenanceBoss','bufferLog','guillermo@db-proxy1.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); +INSERT IGNORE INTO `tables_priv` VALUES ('','vn','grafana','shelvingLog','guillermo@db-proxy2.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); INSERT IGNORE INTO `tables_priv` VALUES ('','vn','financialBoss','supplierAccount','guillermo@db-proxy2.servers.dc.verdnatura.es','0000-00-00 00:00:00','Insert,Update,Delete',''); INSERT IGNORE INTO `tables_priv` VALUES ('','vn','productionAssi','tillSerial','alexm@db-proxy2.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); INSERT IGNORE INTO `tables_priv` VALUES ('','vn','grafana','stockBuyed','guillermo@db-proxy1.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); @@ -1494,6 +1489,7 @@ INSERT IGNORE INTO `tables_priv` VALUES ('','vn','logisticAssist','itemStemTag', INSERT IGNORE INTO `tables_priv` VALUES ('','vn','logisticAssist','itemBaseTag','jenkins@db-proxy2.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select,Insert,Update,Delete',''); INSERT IGNORE INTO `tables_priv` VALUES ('','vn','logisticAssist','itemBreederTag','jenkins@db-proxy2.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select,Insert,Update,Delete',''); INSERT IGNORE INTO `tables_priv` VALUES ('','vn','grafana','itemShelvingLog','guillermo@db-proxy2.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); +INSERT IGNORE INTO `tables_priv` VALUES ('','vn','logisticAssist','itemTextureTag','jenkins@db-proxy2.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select,Insert,Update,Delete',''); /*!40000 ALTER TABLE `tables_priv` ENABLE KEYS */; /*!40000 ALTER TABLE `columns_priv` DISABLE KEYS */; @@ -1873,6 +1869,7 @@ INSERT IGNORE INTO `procs_priv` VALUES ('','vn','claimManager','buy_getVolumeByE INSERT IGNORE INTO `procs_priv` VALUES ('','vn','buyer','buy_getVolumeByEntry','PROCEDURE','alexm@%','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','employee','entry_moveNotPrinted','PROCEDURE','alexm@%','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','employee','buy_getVolume','FUNCTION','alexm@%','Execute','0000-00-00 00:00:00'); +INSERT IGNORE INTO `procs_priv` VALUES ('','vn','buyer','stockBuyedByWorker','PROCEDURE','guillermo@db-proxy2.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','employee','buy_getsplit','PROCEDURE','juan@db-proxy2.static.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','salesAssistant','subordinategetlist','PROCEDURE','alexm@%','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','buyer','buy_afterUpsert','PROCEDURE','alexm@%','Execute','0000-00-00 00:00:00'); @@ -1925,7 +1922,7 @@ INSERT IGNORE INTO `procs_priv` VALUES ('','util','grafana','firstdayofyear','FU INSERT IGNORE INTO `procs_priv` VALUES ('','util','claimManager','dayend','FUNCTION','alexm@%','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','util','employee','log_add','PROCEDURE','alexm@%','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','srt','employee','moving_between','PROCEDURE','alexm@%','Execute','0000-00-00 00:00:00'); -INSERT IGNORE INTO `procs_priv` VALUES ('','bi','financial','defaultersfromdate','PROCEDURE','juan@db-proxy2.static.verdnatura.es','Execute','0000-00-00 00:00:00'); +INSERT IGNORE INTO `procs_priv` VALUES ('','bi','financial','defaultersfromdate','PROCEDURE','guillermo@db-proxy2.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','employee','getuser','FUNCTION','alexm@%','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','administrative','hasanynegativebase','FUNCTION','alexm@%','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','marketingBoss','hasanynegativebase','FUNCTION','alexm@%','Execute','0000-00-00 00:00:00'); @@ -2020,6 +2017,7 @@ INSERT IGNORE INTO `procs_priv` VALUES ('','vn','hr','logshow','PROCEDURE','alex INSERT IGNORE INTO `procs_priv` VALUES ('','vn','buyerBoss','supplierpackaging_reportsource','PROCEDURE','alexm@%','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','financialBoss','supplierexpenses','PROCEDURE','alexm@%','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','grafana','firstdayofweek','FUNCTION','juan@db-proxy2.static.verdnatura.es','Execute','0000-00-00 00:00:00'); +INSERT IGNORE INTO `procs_priv` VALUES ('','vn','buyer','stockBuyed_add','PROCEDURE','guillermo@db-proxy2.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','administrative','mail_insert','PROCEDURE','alexm@%','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','administrative','duaParcialMake','PROCEDURE','alexm@%','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','palletizerBoss','packingsite_startcollection','PROCEDURE','alexm@db-proxy2.static.verdnatura.es','Execute','0000-00-00 00:00:00'); @@ -2099,7 +2097,6 @@ INSERT IGNORE INTO `procs_priv` VALUES ('','vn','production','collection_printst INSERT IGNORE INTO `procs_priv` VALUES ('','vn','production','deviceproductionuser_getworker','PROCEDURE','alexm@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','production','ticket_printlabelprevious','PROCEDURE','alexm@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','production','ticket_isoutclosurezone','FUNCTION','alexm@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); -INSERT IGNORE INTO `procs_priv` VALUES ('','vn','production','workermachinery_isregistered','FUNCTION','alexm@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','production','ticketstatetoday_setstate','PROCEDURE','alexm@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','production','device_checklogin','PROCEDURE','alexm@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','production','worker_getfromhasmistake','PROCEDURE','alexm@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); @@ -2107,7 +2104,7 @@ INSERT IGNORE INTO `procs_priv` VALUES ('','vn','production','sectorcollection_n INSERT IGNORE INTO `procs_priv` VALUES ('','vn','production','sectorcollection_get','PROCEDURE','alexm@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','production','setparking','PROCEDURE','alexm@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','production','shelvingparking_get','PROCEDURE','alexm@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); -INSERT IGNORE INTO `procs_priv` VALUES ('','vn','production','machine_getworkerplate','PROCEDURE','alexm@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); +INSERT IGNORE INTO `procs_priv` VALUES ('','vn','employee','report_print','PROCEDURE','guillermo@db-proxy2.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','production','saletracking_addprevok','PROCEDURE','alexm@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','production','sectorcollectionsalegroup_add','PROCEDURE','alexm@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','production','saletracking_updateischecked','PROCEDURE','alexm@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); @@ -2116,7 +2113,7 @@ INSERT IGNORE INTO `procs_priv` VALUES ('','vn','production','travel_updatepacki INSERT IGNORE INTO `procs_priv` VALUES ('','vn','production','freelance_getinfo','PROCEDURE','alexm@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','production','company_getfiscaldata','PROCEDURE','alexm@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','production','expedition_getfromroute','PROCEDURE','alexm@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); -INSERT IGNORE INTO `procs_priv` VALUES ('','vn','production','machineworker_gethistorical','PROCEDURE','alexm@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); +INSERT IGNORE INTO `procs_priv` VALUES ('','vn','production','buy_getUltimate','FUNCTION','guillermo@db-proxy2.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','production','itemplacementsupplyaiming','PROCEDURE','alexm@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','production','expeditionstate_addbypallet','PROCEDURE','alexm@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','srt','production','expeditionloading_add','PROCEDURE','alexm@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); @@ -2150,7 +2147,6 @@ INSERT IGNORE INTO `procs_priv` VALUES ('','vn','delivery','collection_printstic INSERT IGNORE INTO `procs_priv` VALUES ('','vn','delivery','deviceproductionuser_getworker','PROCEDURE','guillermo@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','delivery','ticket_printlabelprevious','PROCEDURE','guillermo@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','delivery','ticket_isoutclosurezone','FUNCTION','guillermo@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); -INSERT IGNORE INTO `procs_priv` VALUES ('','vn','delivery','workermachinery_isregistered','FUNCTION','guillermo@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','delivery','ticketstatetoday_setstate','PROCEDURE','guillermo@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','delivery','device_checklogin','PROCEDURE','guillermo@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','delivery','worker_getfromhasmistake','PROCEDURE','guillermo@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); @@ -2158,7 +2154,6 @@ INSERT IGNORE INTO `procs_priv` VALUES ('','vn','delivery','sectorcollection_new INSERT IGNORE INTO `procs_priv` VALUES ('','vn','delivery','sectorcollection_get','PROCEDURE','guillermo@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','delivery','setparking','PROCEDURE','guillermo@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','delivery','shelvingparking_get','PROCEDURE','guillermo@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); -INSERT IGNORE INTO `procs_priv` VALUES ('','vn','delivery','machine_getworkerplate','PROCEDURE','guillermo@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','delivery','saletracking_addprevok','PROCEDURE','guillermo@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','delivery','sectorcollectionsalegroup_add','PROCEDURE','guillermo@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','delivery','saletracking_updateischecked','PROCEDURE','guillermo@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); @@ -2167,7 +2162,6 @@ INSERT IGNORE INTO `procs_priv` VALUES ('','vn','delivery','travel_updatepacking INSERT IGNORE INTO `procs_priv` VALUES ('','vn','delivery','freelance_getinfo','PROCEDURE','guillermo@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','delivery','company_getfiscaldata','PROCEDURE','guillermo@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','delivery','expedition_getfromroute','PROCEDURE','guillermo@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); -INSERT IGNORE INTO `procs_priv` VALUES ('','vn','delivery','machineworker_gethistorical','PROCEDURE','guillermo@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','delivery','itemplacementsupplyaiming','PROCEDURE','guillermo@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','delivery','expeditionstate_addbypallet','PROCEDURE','guillermo@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','srt','delivery','expeditionloading_add','PROCEDURE','guillermo@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); @@ -2257,6 +2251,7 @@ INSERT IGNORE INTO `global_priv` VALUES ('','assetManager','{\"access\":0,\"vers INSERT IGNORE INTO `global_priv` VALUES ('','buyer','{\"access\": 0, \"version_id\": 101106, \"is_role\": true}'); INSERT IGNORE INTO `global_priv` VALUES ('','buyerAssistant','{\"access\":0,\"version_id\":101106,\"is_role\":true}'); INSERT IGNORE INTO `global_priv` VALUES ('','buyerBoss','{\"access\": 0, \"version_id\": 101106, \"is_role\": true}'); +INSERT IGNORE INTO `global_priv` VALUES ('','buyerSalesAssistant','{\"access\":0,\"version_id\":101106,\"is_role\":true}'); INSERT IGNORE INTO `global_priv` VALUES ('','claimManager','{\"access\":0,\"version_id\":101106,\"is_role\":true}'); INSERT IGNORE INTO `global_priv` VALUES ('','cooler','{\"access\":0,\"version_id\":101106,\"is_role\":true}'); INSERT IGNORE INTO `global_priv` VALUES ('','coolerAssist','{\"access\":0,\"version_id\":100707,\"is_role\":true}'); diff --git a/db/dump/.dump/structure.sql b/db/dump/.dump/structure.sql index e6c0e6674..c3f622d5f 100644 --- a/db/dump/.dump/structure.sql +++ b/db/dump/.dump/structure.sql @@ -246,8 +246,7 @@ SET character_set_client = utf8; 1 AS `email`, 1 AS `nickname`, 1 AS `lang`, - 1 AS `role`, - 1 AS `recoverPass` */; + 1 AS `role` */; SET character_set_client = @saved_cs_client; -- @@ -423,8 +422,8 @@ CREATE TABLE `user` ( `created` timestamp NOT NULL DEFAULT current_timestamp(), `updated` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), `image` varchar(255) DEFAULT NULL, - `recoverPass` tinyint(3) unsigned NOT NULL DEFAULT 1 COMMENT 'Deprecated', - `sync` tinyint(4) NOT NULL DEFAULT 0 COMMENT 'Deprecated', + `recoverPass__` tinyint(3) unsigned NOT NULL DEFAULT 1 COMMENT '@deprecated 2024-11-13', + `sync__` tinyint(4) NOT NULL DEFAULT 0 COMMENT '@deprecated 2024-11-13', `hasGrant` tinyint(1) NOT NULL, `editorFk` int(10) unsigned DEFAULT NULL, `passExpired` date DEFAULT NULL, @@ -2955,55 +2954,55 @@ DELIMITER ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; CREATE DEFINER=`root`@`localhost` PROCEDURE `analisis_ventas_update`() -BEGIN - DECLARE vLastMonth DATE; - - SET vLastMonth = util.firstDayOfMonth(TIMESTAMPADD(MONTH, -1, util.VN_CURDATE())); - - DELETE FROM analisis_ventas - WHERE Año > YEAR(vLastMonth) - OR (Año = YEAR(vLastMonth) AND Mes >= MONTH(vLastMonth)); - - INSERT INTO analisis_ventas ( - Familia, - Reino, - Comercial, - Comprador, - Provincia, - almacen, - Año, - Mes, - Semana, - Vista, - Importe - ) - SELECT - it.name, - ic.name, - w.code, - w2.code, - p.name, - wa.name, - tm.year, - tm.month, - tm.week, - dm.description, - bt.importe - FROM bs.ventas bt - LEFT JOIN vn.itemType it ON it.id = bt.tipo_id - LEFT JOIN vn.itemCategory ic ON ic.id = it.categoryFk - LEFT JOIN vn.client c on c.id = bt.Id_Cliente - LEFT JOIN vn.worker w ON w.id = c.salesPersonFk - LEFT JOIN vn.worker w2 ON w2.id = it.workerFk - JOIN vn.time tm ON tm.dated = bt.fecha - JOIN vn.sale s ON s.id = bt.Id_Movimiento - LEFT JOIN vn.ticket t ON t.id = s.ticketFk - JOIN vn.agencyMode am ON am.id = t.agencyModeFk - LEFT JOIN vn.deliveryMethod dm ON dm.id = am.deliveryMethodFk - LEFT JOIN vn.address a ON a.id = t.addressFk - LEFT JOIN vn.province p ON p.id = a.provinceFk - LEFT JOIN vn.warehouse wa ON wa.id = t.warehouseFk - WHERE bt.fecha >= vLastMonth AND ic.merchandise; +BEGIN + DECLARE vLastMonth DATE; + + SET vLastMonth = util.firstDayOfMonth(TIMESTAMPADD(MONTH, -1, util.VN_CURDATE())); + + DELETE FROM analisis_ventas + WHERE Año > YEAR(vLastMonth) + OR (Año = YEAR(vLastMonth) AND Mes >= MONTH(vLastMonth)); + + INSERT INTO analisis_ventas ( + Familia, + Reino, + Comercial, + Comprador, + Provincia, + almacen, + Año, + Mes, + Semana, + Vista, + Importe + ) + SELECT + it.name, + ic.name, + w.code, + w2.code, + p.name, + wa.name, + tm.year, + tm.month, + tm.week, + dm.description, + bt.importe + FROM bs.ventas bt + LEFT JOIN vn.itemType it ON it.id = bt.tipo_id + LEFT JOIN vn.itemCategory ic ON ic.id = it.categoryFk + LEFT JOIN vn.client c on c.id = bt.Id_Cliente + LEFT JOIN vn.worker w ON w.id = c.salesPersonFk + LEFT JOIN vn.worker w2 ON w2.id = it.workerFk + JOIN vn.time tm ON tm.dated = bt.fecha + JOIN vn.sale s ON s.id = bt.Id_Movimiento + LEFT JOIN vn.ticket t ON t.id = s.ticketFk + JOIN vn.agencyMode am ON am.id = t.agencyModeFk + LEFT JOIN vn.deliveryMethod dm ON dm.id = am.deliveryMethodFk + LEFT JOIN vn.address a ON a.id = t.addressFk + LEFT JOIN vn.province p ON p.id = a.provinceFk + LEFT JOIN vn.warehouse wa ON wa.id = t.warehouseFk + WHERE bt.fecha >= vLastMonth AND ic.merchandise; END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -3021,21 +3020,21 @@ DELIMITER ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; CREATE DEFINER=`root`@`localhost` PROCEDURE `clean`() -BEGIN - DECLARE vDateShort DATETIME; - DECLARE vDateLong DATETIME; - DECLARE vOneYearAgo DATETIME; - - SET vDateShort = TIMESTAMPADD(MONTH, -2, util.VN_CURDATE()); - SET vDateLong = TIMESTAMPADD(MONTH, -18,util.VN_CURDATE()); - SET vOneYearAgo = TIMESTAMPADD(YEAR, -1,util.VN_CURDATE()); - - DELETE FROM bi.Greuge_Evolution - WHERE (Fecha < vDateShort AND weekday(Fecha) != 1) - OR Fecha < vOneYearAgo; - - DELETE FROM bi.defaulters WHERE `date` < vDateLong; - DELETE FROM bi.defaulting WHERE `date` < vDateLong; +BEGIN + DECLARE vDateShort DATETIME; + DECLARE vDateLong DATETIME; + DECLARE vOneYearAgo DATETIME; + + SET vDateShort = TIMESTAMPADD(MONTH, -2, util.VN_CURDATE()); + SET vDateLong = TIMESTAMPADD(MONTH, -18,util.VN_CURDATE()); + SET vOneYearAgo = TIMESTAMPADD(YEAR, -1,util.VN_CURDATE()); + + DELETE FROM bi.Greuge_Evolution + WHERE (Fecha < vDateShort AND weekday(Fecha) != 1) + OR Fecha < vOneYearAgo; + + DELETE FROM bi.defaulters WHERE `date` < vDateLong; + DELETE FROM bi.defaulting WHERE `date` < vDateLong; END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -3224,18 +3223,18 @@ DELIMITER ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; CREATE DEFINER=`root`@`localhost` PROCEDURE `facturacion_media_anual_update`() -BEGIN - TRUNCATE TABLE bs.clientAnnualConsumption; - - REPLACE bi.facturacion_media_anual(Id_Cliente, Consumo) - SELECT clientFk, avg(Facturacion) - FROM ( - SELECT clientFk, YEAR(issued) year, MONTH(issued) month, sum(amount) as Facturacion - FROM vn.invoiceOut - WHERE issued BETWEEN TIMESTAMPADD(YEAR,-1,util.VN_CURDATE()) AND TIMESTAMPADD(DAY, - DAY(util.VN_CURDATE()),util.VN_CURDATE()) - GROUP BY clientFk, year, month - ) vol - GROUP BY clientFk; +BEGIN + TRUNCATE TABLE bs.clientAnnualConsumption; + + REPLACE bi.facturacion_media_anual(Id_Cliente, Consumo) + SELECT clientFk, avg(Facturacion) + FROM ( + SELECT clientFk, YEAR(issued) year, MONTH(issued) month, sum(amount) as Facturacion + FROM vn.invoiceOut + WHERE issued BETWEEN TIMESTAMPADD(YEAR,-1,util.VN_CURDATE()) AND TIMESTAMPADD(DAY, - DAY(util.VN_CURDATE()),util.VN_CURDATE()) + GROUP BY clientFk, year, month + ) vol + GROUP BY clientFk; END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -4516,29 +4515,29 @@ DELIMITER ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; CREATE DEFINER=`root`@`localhost` PROCEDURE `carteras_add`() -BEGIN -/** - * Inserta en la tabla @bs.carteras las ventas desde el año pasado - * agrupadas por trabajador, año y mes - */ - DECLARE vYear INT DEFAULT YEAR(util.VN_CURDATE()) - 1; - - DELETE FROM bs.carteras WHERE Año >= vYear; - - CALL util.time_generate( - MAKEDATE(vYear, 1), - (SELECT MAX(fecha) FROM ventas) - ); - - INSERT INTO carteras(Año, Mes , CodigoTrabajador, Peso) - SELECT t.`year`, t.`month`, w.code, SUM(v.importe) - FROM tmp.time t - JOIN ventas v on t.dated = v.fecha - JOIN vn.client c on c.id = v.Id_Cliente - JOIN vn.worker w ON w.id = c.salesPersonFk - GROUP BY w.code, t.`year`, t.`month`; - - DROP TEMPORARY TABLE tmp.time; +BEGIN +/** + * Inserta en la tabla @bs.carteras las ventas desde el año pasado + * agrupadas por trabajador, año y mes + */ + DECLARE vYear INT DEFAULT YEAR(util.VN_CURDATE()) - 1; + + DELETE FROM bs.carteras WHERE Año >= vYear; + + CALL util.time_generate( + MAKEDATE(vYear, 1), + (SELECT MAX(fecha) FROM ventas) + ); + + INSERT INTO carteras(Año, Mes , CodigoTrabajador, Peso) + SELECT t.`year`, t.`month`, w.code, SUM(v.importe) + FROM tmp.time t + JOIN ventas v on t.dated = v.fecha + JOIN vn.client c on c.id = v.Id_Cliente + JOIN vn.worker w ON w.id = c.salesPersonFk + GROUP BY w.code, t.`year`, t.`month`; + + DROP TEMPORARY TABLE tmp.time; END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -5198,7 +5197,7 @@ BEGIN CREATE OR REPLACE TEMPORARY TABLE tVisible SELECT itemFk, SUM(visible) totalVisible FROM vn.itemShelving ish - JOIN vn.shelving sh ON sh.code = ish.shelvingFk + JOIN vn.shelving sh ON sh.id = ish.shelvingFk JOIN vn.parking p ON p.id = sh.parkingFk JOIN vn.sector sc ON sc.id = p.sectorFk WHERE sc.warehouseFk = vWarehouseFk @@ -5465,82 +5464,82 @@ DELIMITER ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; CREATE DEFINER=`root`@`localhost` PROCEDURE `nightTask_launchAll`() -BEGIN -/** - * Runs all nightly tasks. - */ - DECLARE vDone BOOL; - DECLARE vError VARCHAR(255); - DECLARE vErrorCode VARCHAR(255); - DECLARE vSchema VARCHAR(255); - DECLARE vProcedure VARCHAR(255); - DECLARE vLogMail VARCHAR(255); - DECLARE vNightTaskFk INT; - - DECLARE vQueue CURSOR FOR - SELECT id, `schema`, `procedure` - FROM nightTask - WHERE finished <= util.VN_CURDATE() - OR finished IS NULL - ORDER BY `order`; - - DECLARE CONTINUE HANDLER FOR NOT FOUND - SET vDone = TRUE; - - SET max_sp_recursion_depth = 3; - - SELECT logMail INTO vLogMail - FROM nightTaskConfig LIMIT 1; - - OPEN vQueue; - l: LOOP - SET vDone = FALSE; - FETCH vQueue INTO vNightTaskFk, vSchema, vProcedure; - - IF vDone THEN - LEAVE l; - END IF; - - UPDATE nightTask - SET `started` = util.VN_NOW(), - `finished` = NULL, - `error` = NULL, - `errorCode` = NULL - WHERE id = vNightTaskFk; - - SET vError = NULL; - CALL nightTask_launchTask( - vSchema, - vProcedure, - vError, - vErrorCode - ); - - IF vError IS NOT NULL THEN - IF vLogMail IS NOT NULL THEN - CALL vn.mail_insert( - vLogMail, - NULL, - CONCAT('Nightly task failed (', vSchema, '.', vProcedure, ')'), - CONCAT( - '[', vErrorCode, '] ', vError, CHAR(13, 10), -- Line break - 'See ', SCHEMA(), '.nightTask table for more info.' - ) - ); - END IF; - - UPDATE nightTask - SET `error` = vError, - `errorCode` = vErrorCode - WHERE id = vNightTaskFk; - ELSE - UPDATE nightTask - SET finished = util.VN_NOW(), - lastFinished = util.VN_NOW() - WHERE id = vNightTaskFk; - END IF; - END LOOP; - CLOSE vQueue; +BEGIN +/** + * Runs all nightly tasks. + */ + DECLARE vDone BOOL; + DECLARE vError VARCHAR(255); + DECLARE vErrorCode VARCHAR(255); + DECLARE vSchema VARCHAR(255); + DECLARE vProcedure VARCHAR(255); + DECLARE vLogMail VARCHAR(255); + DECLARE vNightTaskFk INT; + + DECLARE vQueue CURSOR FOR + SELECT id, `schema`, `procedure` + FROM nightTask + WHERE finished <= util.VN_CURDATE() + OR finished IS NULL + ORDER BY `order`; + + DECLARE CONTINUE HANDLER FOR NOT FOUND + SET vDone = TRUE; + + SET max_sp_recursion_depth = 3; + + SELECT logMail INTO vLogMail + FROM nightTaskConfig LIMIT 1; + + OPEN vQueue; + l: LOOP + SET vDone = FALSE; + FETCH vQueue INTO vNightTaskFk, vSchema, vProcedure; + + IF vDone THEN + LEAVE l; + END IF; + + UPDATE nightTask + SET `started` = util.VN_NOW(), + `finished` = NULL, + `error` = NULL, + `errorCode` = NULL + WHERE id = vNightTaskFk; + + SET vError = NULL; + CALL nightTask_launchTask( + vSchema, + vProcedure, + vError, + vErrorCode + ); + + IF vError IS NOT NULL THEN + IF vLogMail IS NOT NULL THEN + CALL vn.mail_insert( + vLogMail, + NULL, + CONCAT('Nightly task failed (', vSchema, '.', vProcedure, ')'), + CONCAT( + '[', vErrorCode, '] ', vError, CHAR(13, 10), -- Line break + 'See ', SCHEMA(), '.nightTask table for more info.' + ) + ); + END IF; + + UPDATE nightTask + SET `error` = vError, + `errorCode` = vErrorCode + WHERE id = vNightTaskFk; + ELSE + UPDATE nightTask + SET finished = util.VN_NOW(), + lastFinished = util.VN_NOW() + WHERE id = vNightTaskFk; + END IF; + END LOOP; + CLOSE vQueue; END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -6958,7 +6957,7 @@ proc: BEGIN WHERE t.landed BETWEEN vInventoryDate AND vStartDate AND t.warehouseInFk = vWarehouse AND s.name != 'INVENTARIO' - AND NOT e.isRaid + AND NOT t.isRaid GROUP BY b.itemFk ) c JOIN vn.item i ON i.id = c.itemFk @@ -7285,27 +7284,27 @@ DELIMITER ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; CREATE DEFINER=`root`@`localhost` PROCEDURE `cache_calc_end`(IN `v_calc` INT) -BEGIN - DECLARE v_cache_name VARCHAR(255); - DECLARE v_params VARCHAR(255); - - -- Libera el bloqueo y actualiza la fecha de ultimo refresco. - - UPDATE cache_calc cc JOIN cache c ON c.id = cc.cache_id - SET - cc.last_refresh = NOW(), - cc.expires = ADDTIME(NOW(), c.lifetime), - cc.connection_id = NULL - WHERE cc.id = v_calc; - - SELECT c.name, ca.params INTO v_cache_name, v_params - FROM cache c - JOIN cache_calc ca ON c.id = ca.cache_id - WHERE ca.id = v_calc; - - IF v_cache_name IS NOT NULL THEN - DO RELEASE_LOCK(CONCAT_WS('/', v_cache_name, IFNULL(v_params, ''))); - END IF; +BEGIN + DECLARE v_cache_name VARCHAR(255); + DECLARE v_params VARCHAR(255); + + -- Libera el bloqueo y actualiza la fecha de ultimo refresco. + + UPDATE cache_calc cc JOIN cache c ON c.id = cc.cache_id + SET + cc.last_refresh = NOW(), + cc.expires = ADDTIME(NOW(), c.lifetime), + cc.connection_id = NULL + WHERE cc.id = v_calc; + + SELECT c.name, ca.params INTO v_cache_name, v_params + FROM cache c + JOIN cache_calc ca ON c.id = ca.cache_id + WHERE ca.id = v_calc; + + IF v_cache_name IS NOT NULL THEN + DO RELEASE_LOCK(CONCAT_WS('/', v_cache_name, IFNULL(v_params, ''))); + END IF; END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -7323,89 +7322,89 @@ DELIMITER ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; CREATE DEFINER=`root`@`localhost` PROCEDURE `cache_calc_start`(OUT `v_calc` INT, INOUT `v_refresh` INT, IN `v_cache_name` VARCHAR(50), IN `v_params` VARCHAR(100)) -proc: BEGIN - DECLARE v_valid BOOL; - DECLARE v_lock_id VARCHAR(100); - DECLARE v_cache_id INT; - DECLARE v_expires DATETIME; - DECLARE v_clean_time DATETIME; - DECLARE vLastRefresh DATETIME; - - DECLARE EXIT HANDLER FOR SQLEXCEPTION - BEGIN - IF v_lock_id IS NOT NULL THEN - DO RELEASE_LOCK(v_lock_id); - END IF; - - RESIGNAL; - END; - - SET v_params = IFNULL(v_params, ''); - - -- Si el servidor se ha reiniciado invalida todos los calculos. - - SELECT COUNT(*) > 0 INTO v_valid FROM cache_valid; - - IF !v_valid - THEN - DELETE FROM cache_calc; - INSERT INTO cache_valid (valid) VALUES (TRUE); - END IF; - - -- Obtiene un bloqueo exclusivo para que no haya problemas de concurrencia. - - SET v_lock_id = CONCAT_WS('/', v_cache_name, v_params); - - IF !GET_LOCK(v_lock_id, 30) - THEN - SET v_calc = NULL; - SET v_refresh = FALSE; - LEAVE proc; - END IF; - - -- Comprueba si el calculo solicitado existe y esta actualizado. - - SELECT c.id, ca.id, ca.expires, ca.last_refresh - INTO v_cache_id, v_calc, v_expires, vLastRefresh - FROM cache c - LEFT JOIN cache_calc ca - ON ca.cache_id = c.id AND ca.params = v_params COLLATE 'utf8_general_ci' - WHERE c.name = v_cache_name COLLATE 'utf8_general_ci'; - - -- Si existe una calculo valido libera el bloqueo y devuelve su identificador. - - IF !v_refresh AND NOW() < v_expires AND vLastRefresh >= CURDATE() - THEN - DO RELEASE_LOCK(v_lock_id); - SET v_refresh = FALSE; - LEAVE proc; - END IF; - - -- Si el calculo no existe le crea una entrada en la tabla de calculos. - - IF v_calc IS NULL - THEN - INSERT INTO cache_calc SET - cache_id = v_cache_id, - cacheName = v_cache_name, - params = v_params, - last_refresh = NULL, - expires = NULL, - connection_id = CONNECTION_ID(); - - SET v_calc = LAST_INSERT_ID(); - ELSE - UPDATE cache_calc - SET - last_refresh = NULL, - expires = NULL, - connection_id = CONNECTION_ID() - WHERE id = v_calc; - END IF; - - -- Si se debe recalcular mantiene el bloqueo y devuelve su identificador. - - SET v_refresh = TRUE; +proc: BEGIN + DECLARE v_valid BOOL; + DECLARE v_lock_id VARCHAR(100); + DECLARE v_cache_id INT; + DECLARE v_expires DATETIME; + DECLARE v_clean_time DATETIME; + DECLARE vLastRefresh DATETIME; + + DECLARE EXIT HANDLER FOR SQLEXCEPTION + BEGIN + IF v_lock_id IS NOT NULL THEN + DO RELEASE_LOCK(v_lock_id); + END IF; + + RESIGNAL; + END; + + SET v_params = IFNULL(v_params, ''); + + -- Si el servidor se ha reiniciado invalida todos los calculos. + + SELECT COUNT(*) > 0 INTO v_valid FROM cache_valid; + + IF !v_valid + THEN + DELETE FROM cache_calc; + INSERT INTO cache_valid (valid) VALUES (TRUE); + END IF; + + -- Obtiene un bloqueo exclusivo para que no haya problemas de concurrencia. + + SET v_lock_id = CONCAT_WS('/', v_cache_name, v_params); + + IF !GET_LOCK(v_lock_id, 30) + THEN + SET v_calc = NULL; + SET v_refresh = FALSE; + LEAVE proc; + END IF; + + -- Comprueba si el calculo solicitado existe y esta actualizado. + + SELECT c.id, ca.id, ca.expires, ca.last_refresh + INTO v_cache_id, v_calc, v_expires, vLastRefresh + FROM cache c + LEFT JOIN cache_calc ca + ON ca.cache_id = c.id AND ca.params = v_params COLLATE 'utf8_general_ci' + WHERE c.name = v_cache_name COLLATE 'utf8_general_ci'; + + -- Si existe una calculo valido libera el bloqueo y devuelve su identificador. + + IF !v_refresh AND NOW() < v_expires AND vLastRefresh >= CURDATE() + THEN + DO RELEASE_LOCK(v_lock_id); + SET v_refresh = FALSE; + LEAVE proc; + END IF; + + -- Si el calculo no existe le crea una entrada en la tabla de calculos. + + IF v_calc IS NULL + THEN + INSERT INTO cache_calc SET + cache_id = v_cache_id, + cacheName = v_cache_name, + params = v_params, + last_refresh = NULL, + expires = NULL, + connection_id = CONNECTION_ID(); + + SET v_calc = LAST_INSERT_ID(); + ELSE + UPDATE cache_calc + SET + last_refresh = NULL, + expires = NULL, + connection_id = CONNECTION_ID() + WHERE id = v_calc; + END IF; + + -- Si se debe recalcular mantiene el bloqueo y devuelve su identificador. + + SET v_refresh = TRUE; END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -10429,28 +10428,28 @@ DELIMITER ; /*!50003 SET character_set_results = utf8mb4 */ ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; -CREATE DEFINER=`root`@`localhost` PROCEDURE `contact_request`( - vName VARCHAR(100), - vPhone VARCHAR(15), - vEmail VARCHAR(100), +CREATE DEFINER=`root`@`localhost` PROCEDURE `contact_request`( + vName VARCHAR(100), + vPhone VARCHAR(15), + vEmail VARCHAR(100), vMessage TEXT) READS SQL DATA -BEGIN -/** - * Set actions for contact request - * - * @param vName Name - * @param vPhone Phone number - * @param vEmail e-mail - * @param vMessage text of the message - */ - - CALL vn.mail_insert( - 'floranet@verdnatura.es', - vEmail, - 'Contact request', - CONCAT('Phone: ',vPhone, ' Message: ', vMessage) - ); +BEGIN +/** + * Set actions for contact request + * + * @param vName Name + * @param vPhone Phone number + * @param vEmail e-mail + * @param vMessage text of the message + */ + + CALL vn.mail_insert( + 'floranet@verdnatura.es', + vEmail, + 'Contact request', + CONCAT('Phone: ',vPhone, ' Message: ', vMessage) + ); END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -10469,27 +10468,27 @@ DELIMITER ; DELIMITER ;; CREATE DEFINER=`root`@`localhost` PROCEDURE `deliveryDate_get`(vPostalCode VARCHAR(15)) READS SQL DATA -BEGIN -/** - * Returns available dates for this postalCode, in the next seven days. - * - * @param vPostalCode Delivery address postal code - */ - DECLARE vCurrentDayOfWeek INT; - - SET vCurrentDayOfWeek = DAYOFWEEK(NOW()); - - SELECT DISTINCT nextDay - FROM ( - SELECT CURDATE() + INTERVAL IF( - apc.dayOfWeek >= vCurrentDayOfWeek, - apc.dayOfWeek - vCurrentDayOfWeek, - 7 - apc.dayOfWeek - ) DAY nextDay, - NOW() + INTERVAL apc.hoursInAdvance HOUR minDeliveryTime - FROM addressPostCode apc - WHERE apc.postCode = vPostalCode - HAVING nextDay > minDeliveryTime) sub; +BEGIN +/** + * Returns available dates for this postalCode, in the next seven days. + * + * @param vPostalCode Delivery address postal code + */ + DECLARE vCurrentDayOfWeek INT; + + SET vCurrentDayOfWeek = DAYOFWEEK(NOW()); + + SELECT DISTINCT nextDay + FROM ( + SELECT CURDATE() + INTERVAL IF( + apc.dayOfWeek >= vCurrentDayOfWeek, + apc.dayOfWeek - vCurrentDayOfWeek, + 7 - apc.dayOfWeek + ) DAY nextDay, + NOW() + INTERVAL apc.hoursInAdvance HOUR minDeliveryTime + FROM addressPostCode apc + WHERE apc.postCode = vPostalCode + HAVING nextDay > minDeliveryTime) sub; END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -12263,7 +12262,7 @@ BEGIN JOIN vn.travel t ON t.id = e.travelFk WHERE t.landed BETWEEN vDateInv AND vDate AND t.warehouseInFk = vWarehouse - AND NOT e.isRaid + AND NOT t.isRaid UNION ALL SELECT b.itemFk, -b.quantity FROM vn.buy b @@ -12271,7 +12270,7 @@ BEGIN JOIN vn.travel t ON t.id = e.travelFk WHERE t.shipped BETWEEN vDateInv AND util.VN_CURDATE() AND t.warehouseOutFk = vWarehouse - AND NOT e.isRaid + AND NOT t.isRaid AND t.isDelivered UNION ALL SELECT m.itemFk, -m.quantity @@ -14114,45 +14113,54 @@ BEGIN * @param vOrder El identificador del pedido * @return tmp.orderTax Bases imponibles, IVA y recargo de equivalencia */ + -- No poner create or replace, ya que da problemas DROP TEMPORARY TABLE IF EXISTS tmp.addressCompany; CREATE TEMPORARY TABLE tmp.addressCompany (INDEX (addressFk, companyFk)) ENGINE = MEMORY SELECT DISTINCT o.address_id addressFk, o.company_id companyFk FROM tmp.`order` tmpOrder - JOIN hedera.`order` o ON o.id = tmpOrder.orderFk; + JOIN `order` o ON o.id = tmpOrder.orderFk; - CALL vn.addressTaxArea; + CALL vn.addressTaxArea(); -- Calcula el IVA y el recargo desglosado. - - DROP TEMPORARY TABLE IF EXISTS tmp.orderTax; - CREATE TEMPORARY TABLE tmp.orderTax - (INDEX (orderFk)) + CREATE OR REPLACE TEMPORARY TABLE tmp.orderTax + (PRIMARY KEY (orderFk, code, rate)) ENGINE = MEMORY - SELECT o.id orderFk, + WITH orders AS ( + SELECT tor.orderFk, + oro.amount * oro.price total, + s.countryFk, + ata.areaFk, + itc.taxClassFk + FROM hedera.orderRow oro + JOIN tmp.order tor ON tor.orderFk = oro.orderFk + JOIN hedera.`order` o ON o.id = tor.orderFk + JOIN vn.item i ON i.id = oro.itemFk + JOIN vn.`client` c ON c.id = o.customer_id + JOIN vn.supplier s ON s.id = o.company_id + JOIN tmp.addressTaxArea ata ON ata.addressFk = o.address_id + AND ata.companyFk = o.company_id + JOIN vn.itemTaxCountry itc ON itc.itemFk = i.id + AND itc.countryFk = s.countryFk + HAVING total + ) + SELECT o.orderFk, tc.code, - SUM(m.amount * m.price) taxableBase, + SUM(o.total) taxableBase, pgc.rate - FROM tmp.`order` tmpOrder - JOIN `order` o ON o.id = tmpOrder.orderFk - JOIN orderRow m ON m.orderFk = o.id - JOIN vn.item i ON i.id = m.itemFk - JOIN vn.`client` c ON c.id = o.customer_id - JOIN vn.supplier s ON s.id = o.company_id - JOIN tmp.addressTaxArea ata - ON ata.addressFk = o.address_id AND ata.companyFk = o.company_id - JOIN vn.itemTaxCountry itc - ON itc.itemFk = i.id AND itc.countryFk = s.countryFk - JOIN vn.bookingPlanner bp - ON bp.countryFk = s.countryFk - AND bp.taxAreaFk = ata.areaFk - AND bp.taxClassFk = itc.taxClassFk - JOIN vn.pgc ON pgc.`code` = bp.pgcFk + FROM orders o + JOIN vn.bookingPlanner bp ON bp.countryFk = o.countryFk + AND bp.taxAreaFk = o.areaFk + AND bp.taxClassFk = o.taxClassFk + JOIN vn.pgc ON pgc.code = bp.pgcFk JOIN vn.taxClass tc ON tc.id = bp.taxClassFk - GROUP BY tmpOrder.orderFk, pgc.`code`, pgc.rate - HAVING taxableBase != 0; + GROUP BY o.orderFk, pgc.code, pgc.rate + HAVING taxableBase + ORDER BY bp.priority; + -- No poner create or replace, ya que da problemas DROP TEMPORARY TABLE IF EXISTS tmp.orderAmount; CREATE TEMPORARY TABLE tmp.orderAmount (INDEX (orderFk)) @@ -22753,7 +22761,7 @@ BEGIN e.id entryFk, t.id travelFk, b.itemFk, - e.isRaid, + t.isRaid, ADDTIME(t.shipped, IFNULL(t.shipmentHour, '00:00:00')) shipped, t.warehouseOutFk, @@ -22792,7 +22800,7 @@ BEGIN itemFk, TIMESTAMPADD(DAY, life, @dated), quantity, - IF(isIn, isReceived, isDelivered) AND !isRaid + IF(isIn, isReceived, isDelivered) AND NOT isRaid FROM tValues WHERE isIn OR !lessThanInventory; @@ -22807,7 +22815,7 @@ BEGIN itemFk, created, quantity, - IF(isIn, isDelivered, isReceived) AND !isRaid + IF(isIn, isDelivered, isReceived) AND NOT isRaid FROM tValues WHERE !isIn OR !lessThanInventory; @@ -25910,6 +25918,7 @@ CREATE TABLE `address` ( `customsAgentFk` int(11) DEFAULT NULL, `incotermsFk` varchar(3) DEFAULT NULL, `isLogifloraAllowed` tinyint(4) NOT NULL DEFAULT 0, + `geoFk` int(11) DEFAULT NULL, `editorFk` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`id`), KEY `Id_Agencia` (`agencyModeFk`), @@ -25921,12 +25930,14 @@ CREATE TABLE `address` ( KEY `address_customsAgentFk_idx` (`customsAgentFk`), KEY `address_incotermsFk_idx` (`incotermsFk`), KEY `address_fk_editor` (`editorFk`), + KEY `address_zoneGeo_FK` (`geoFk`), CONSTRAINT `address_customer_id` FOREIGN KEY (`clientFk`) REFERENCES `client` (`id`) ON UPDATE CASCADE, CONSTRAINT `address_customsAgentFk` FOREIGN KEY (`customsAgentFk`) REFERENCES `customsAgent` (`id`) ON UPDATE CASCADE, CONSTRAINT `address_fk_editor` FOREIGN KEY (`editorFk`) REFERENCES `account`.`user` (`id`), CONSTRAINT `address_ibfk_3` FOREIGN KEY (`provinceFk`) REFERENCES `province` (`id`) ON UPDATE CASCADE, CONSTRAINT `address_ibfk_4` FOREIGN KEY (`agencyModeFk`) REFERENCES `agencyMode` (`id`) ON UPDATE CASCADE, - CONSTRAINT `address_incotermsFk` FOREIGN KEY (`incotermsFk`) REFERENCES `incoterms` (`code`) ON UPDATE CASCADE + CONSTRAINT `address_incotermsFk` FOREIGN KEY (`incotermsFk`) REFERENCES `incoterms` (`code`) ON UPDATE CASCADE, + CONSTRAINT `address_zoneGeo_FK` FOREIGN KEY (`geoFk`) REFERENCES `zoneGeo` (`id`) ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; /*!40101 SET character_set_client = @saved_cs_client */; @@ -27748,8 +27759,9 @@ CREATE TABLE `client` ( `businessTypeFk` varchar(20) NOT NULL DEFAULT 'florist', `rating` int(10) unsigned DEFAULT NULL COMMENT 'información proporcionada por Informa', `recommendedCredit` int(10) unsigned DEFAULT NULL COMMENT 'información proporcionada por Informa', - `editorFk` int(10) unsigned DEFAULT NULL, `hasDailyInvoice` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'Indica si el cliente requiere facturación diaria por defecto se copiará lo que tenga country.hasDailyInvoice', + `geoFk` int(11) DEFAULT NULL, + `editorFk` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `IF` (`fi`), KEY `Id_Trabajador` (`salesPersonFk`), @@ -27771,6 +27783,7 @@ CREATE TABLE `client` ( KEY `codpos` (`postcode`), KEY `client_fk_editor` (`editorFk`), KEY `client_isTaxDataChecked_IDX` (`isTaxDataChecked`) USING BTREE, + KEY `client_zoneGeo_FK` (`geoFk`), CONSTRAINT `canal_nuevo_cliente` FOREIGN KEY (`contactChannelFk`) REFERENCES `contactChannel` (`id`) ON UPDATE CASCADE, CONSTRAINT `client_FK` FOREIGN KEY (`businessTypeFk`) REFERENCES `businessType` (`code`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `client_FK_1` FOREIGN KEY (`bankEntityFk`) REFERENCES `bankEntity` (`id`) ON UPDATE CASCADE, @@ -27784,6 +27797,7 @@ CREATE TABLE `client` ( CONSTRAINT `client_ibfk_5` FOREIGN KEY (`provinceFk`) REFERENCES `province` (`id`) ON UPDATE CASCADE, CONSTRAINT `client_taxTypeSageFk` FOREIGN KEY (`taxTypeSageFk`) REFERENCES `sage`.`TiposIva` (`CodigoIva`) ON UPDATE CASCADE, CONSTRAINT `client_transactionTypeSageFk` FOREIGN KEY (`transactionTypeSageFk`) REFERENCES `sage`.`TiposTransacciones` (`CodigoTransaccion`) ON UPDATE CASCADE, + CONSTRAINT `client_zoneGeo_FK` FOREIGN KEY (`geoFk`) REFERENCES `zoneGeo` (`id`) ON UPDATE CASCADE, CONSTRAINT `typeFk` FOREIGN KEY (`typeFk`) REFERENCES `clientType` (`code`) ON DELETE NO ACTION ON UPDATE NO ACTION ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; /*!40101 SET character_set_client = @saved_cs_client */; @@ -28032,7 +28046,7 @@ CREATE TABLE `clientObservation` ( `text` text NOT NULL, `created` timestamp NOT NULL DEFAULT current_timestamp(), `editorFk` int(10) unsigned DEFAULT NULL, - `observationTypeFk` tinyint(3) unsigned DEFAULT NULL, + `observationTypeFk` tinyint(3) unsigned NOT NULL DEFAULT 4, PRIMARY KEY (`id`), KEY `Id_Trabajador` (`workerFk`), KEY `Id_Cliente` (`clientFk`), @@ -29726,6 +29740,7 @@ CREATE TABLE `dua` ( `customsValue` decimal(10,2) DEFAULT NULL, `companyFk` int(10) unsigned NOT NULL DEFAULT 442, `ASIEN` double DEFAULT NULL, + `comment` text DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `code_UNIQUE` (`code`), KEY `fk_dua_gestdoc1_idx` (`gestdocFk`), @@ -29970,7 +29985,7 @@ CREATE TABLE `entry` ( `isExcludedFromAvailable` tinyint(1) NOT NULL DEFAULT 0, `isConfirmed` tinyint(1) NOT NULL DEFAULT 0, `isOrdered` tinyint(1) NOT NULL DEFAULT 0, - `isRaid` tinyint(1) NOT NULL DEFAULT 0, + `isRaid_` tinyint(1) NOT NULL DEFAULT 0 COMMENT '@deprecated 2024-11-05', `commission` float DEFAULT 0, `created` timestamp NOT NULL DEFAULT current_timestamp(), `evaNotes` varchar(45) DEFAULT NULL, @@ -30137,17 +30152,17 @@ CREATE TABLE `entryType` ( /*!40101 SET character_set_client = @saved_cs_client */; -- --- Table structure for table `entryVirtual` +-- Table structure for table `entryVirtual__` -- -DROP TABLE IF EXISTS `entryVirtual`; +DROP TABLE IF EXISTS `entryVirtual__`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; -CREATE TABLE `entryVirtual` ( +CREATE TABLE `entryVirtual__` ( `entryFk` int(11) NOT NULL, PRIMARY KEY (`entryFk`), - CONSTRAINT `entryVirtual_ibfk_1` FOREIGN KEY (`entryFk`) REFERENCES `entry` (`id`) ON DELETE CASCADE ON UPDATE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci COMMENT='entradas que se van moviendo automaticamente al futuro'; + CONSTRAINT `entryVirtual___ibfk_1` FOREIGN KEY (`entryFk`) REFERENCES `entry` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci COMMENT='@deprecated 2024-11-05'; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -30614,6 +30629,7 @@ CREATE TABLE `expeditionState` ( `typeFk` int(11) NOT NULL, `userFk` int(10) unsigned DEFAULT NULL, `isScanned` tinyint(1) NOT NULL DEFAULT 0, + `scanOrder` int(11) DEFAULT NULL COMMENT 'Indica la posición al cargar la furgoneta', PRIMARY KEY (`id`), KEY `expeditionState_FK` (`expeditionFk`), KEY `expeditionState_FK_1` (`typeFk`), @@ -32609,7 +32625,7 @@ DROP TABLE IF EXISTS `itemShelving`; CREATE TABLE `itemShelving` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `itemFk` int(11) NOT NULL, - `shelvingFk` varchar(10) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL, + `shelvingFk` int(11) NOT NULL, `visible` int(11) NOT NULL DEFAULT 0, `created` timestamp NOT NULL DEFAULT current_timestamp(), `grouping` smallint(5) unsigned DEFAULT NULL, @@ -32630,8 +32646,8 @@ CREATE TABLE `itemShelving` ( KEY `itemShelvingBuy_FK` (`buyFk`), CONSTRAINT `itemShelvingBuy_FK` FOREIGN KEY (`buyFk`) REFERENCES `buy` (`id`), CONSTRAINT `itemShelving_fk1` FOREIGN KEY (`itemFk`) REFERENCES `item` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT `itemShelving_fk2` FOREIGN KEY (`shelvingFk`) REFERENCES `shelving` (`code`) ON UPDATE CASCADE, - CONSTRAINT `itemShelving_fk3` FOREIGN KEY (`packagingFk`) REFERENCES `packaging` (`id`) ON UPDATE CASCADE + CONSTRAINT `itemShelving_fk3` FOREIGN KEY (`packagingFk`) REFERENCES `packaging` (`id`) ON UPDATE CASCADE, + CONSTRAINT `itemShelving_shelving_FK` FOREIGN KEY (`shelvingFk`) REFERENCES `shelving` (`id`) ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci COMMENT='Tabla utilizada para localizar los artículos dentro de los carros. Usado para la gestión del almacén en el altillo '; /*!40101 SET character_set_client = @saved_cs_client */; @@ -33009,6 +33025,21 @@ SET character_set_client = utf8; 1 AS `taxClassFk` */; SET character_set_client = @saved_cs_client; +-- +-- Table structure for table `itemTextureTag` +-- + +DROP TABLE IF EXISTS `itemTextureTag`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `itemTextureTag` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `name_UNIQUE` (`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + -- -- Temporary table structure for view `itemTicketOut` -- @@ -33057,6 +33088,7 @@ CREATE TABLE `itemType` ( `maxRefs` int(10) unsigned DEFAULT NULL COMMENT 'Indica el número máximo de referencias', `isMergeable` tinyint(1) NOT NULL DEFAULT 1 COMMENT 'Articulos que al mergear los tickets se fusionara la linea', `isFragile` tinyint(1) NOT NULL DEFAULT 0, + `editorFk` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `Tipo_UNIQUE` (`name`,`categoryFk`), UNIQUE KEY `itemType_UN` (`code`), @@ -33064,9 +33096,13 @@ CREATE TABLE `itemType` ( KEY `reino_id` (`categoryFk`), KEY `Tipos_fk3_idx` (`making`), KEY `temperatureFk` (`temperatureFk`), + KEY `itemType_user_FK` (`editorFk`), + KEY `itemType_itemPackingType_FK` (`itemPackingTypeFk`), CONSTRAINT `Tipos_fk3` FOREIGN KEY (`making`) REFERENCES `confectionType` (`id`) ON DELETE SET NULL ON UPDATE CASCADE, CONSTRAINT `Trabajador` FOREIGN KEY (`workerFk`) REFERENCES `worker` (`id`) ON UPDATE CASCADE, CONSTRAINT `itemType_ibfk_1` FOREIGN KEY (`categoryFk`) REFERENCES `itemCategory` (`id`) ON UPDATE CASCADE, + CONSTRAINT `itemType_itemPackingType_FK` FOREIGN KEY (`itemPackingTypeFk`) REFERENCES `itemPackingType` (`code`) ON UPDATE CASCADE, + CONSTRAINT `itemType_user_FK` FOREIGN KEY (`editorFk`) REFERENCES `account`.`user` (`id`), CONSTRAINT `temperatureFk` FOREIGN KEY (`temperatureFk`) REFERENCES `temperature` (`code`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci COMMENT='Protege la tabla tipos de updates para los 4 parámetros de los compradores, en funcion del valor del campo CodigoRojo de tblContadores.'; /*!40101 SET character_set_client = @saved_cs_client */; @@ -33099,6 +33135,35 @@ SET character_set_client = utf8; 1 AS `name` */; SET character_set_client = @saved_cs_client; +-- +-- Table structure for table `itemTypeLog` +-- + +DROP TABLE IF EXISTS `itemTypeLog`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `itemTypeLog` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `originFk` int(11) DEFAULT NULL, + `userFk` int(10) unsigned DEFAULT NULL, + `action` set('insert','update','delete') NOT NULL, + `creationDate` timestamp NULL DEFAULT current_timestamp(), + `description` text CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL, + `changedModel` enum('ItemType') NOT NULL DEFAULT 'ItemType', + `oldInstance` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`oldInstance`)), + `newInstance` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`newInstance`)), + `changedModelId` int(11) NOT NULL, + `changedModelValue` varchar(45) DEFAULT NULL, + `summaryId` varchar(30) DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `itemTypeLogUserFk_idx` (`userFk`), + KEY `itemTypeLog_changedModel` (`changedModel`,`changedModelId`,`creationDate`), + KEY `itemTypeLog_originFk` (`originFk`,`creationDate`), + KEY `itemTypeLog_creationDate_IDX` (`creationDate` DESC) USING BTREE, + CONSTRAINT `itemTypeLogUserFk` FOREIGN KEY (`userFk`) REFERENCES `account`.`user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci `PAGE_COMPRESSED`=1; +/*!40101 SET character_set_client = @saved_cs_client */; + -- -- Table structure for table `itemTypeRestriction` -- @@ -33423,13 +33488,28 @@ CREATE TABLE `machineDms` ( /*!40101 SET character_set_client = @saved_cs_client */; -- --- Table structure for table `machineWorker` +-- Table structure for table `machineWorkerConfig__` -- -DROP TABLE IF EXISTS `machineWorker`; +DROP TABLE IF EXISTS `machineWorkerConfig__`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; -CREATE TABLE `machineWorker` ( +CREATE TABLE `machineWorkerConfig__` ( + `id` int(10) unsigned NOT NULL, + `maxHours` smallint(5) unsigned NOT NULL COMMENT 'Indicates how many hours a user record is reviewed to update or insert', + PRIMARY KEY (`id`), + CONSTRAINT `machineWorkerConfig_check` CHECK (`id` = 1) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci COMMENT='@deprecated 2024-10-23 not used'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `machineWorker__` +-- + +DROP TABLE IF EXISTS `machineWorker__`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `machineWorker__` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `workerFk` int(10) unsigned NOT NULL, `machineFk` int(11) NOT NULL, @@ -33440,22 +33520,7 @@ CREATE TABLE `machineWorker` ( KEY `machineWorker_FK` (`workerFk`), CONSTRAINT `machineWorker_FK` FOREIGN KEY (`workerFk`) REFERENCES `worker` (`id`) ON UPDATE CASCADE, CONSTRAINT `machineWorker_FK_1` FOREIGN KEY (`machineFk`) REFERENCES `machine` (`id`) ON UPDATE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci COMMENT='Registros horarios de vehículos de almacén por empleado'; -/*!40101 SET character_set_client = @saved_cs_client */; - --- --- Table structure for table `machineWorkerConfig` --- - -DROP TABLE IF EXISTS `machineWorkerConfig`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `machineWorkerConfig` ( - `id` int(10) unsigned NOT NULL, - `maxHours` smallint(5) unsigned NOT NULL COMMENT 'Indicates how many hours a user record is reviewed to update or insert', - PRIMARY KEY (`id`), - CONSTRAINT `machineWorkerConfig_check` CHECK (`id` = 1) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci COMMENT='@deprecated 2024-10-23 not used'; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -35363,7 +35428,6 @@ CREATE TABLE `productionConfig` ( `sectorToCode` varchar(15) DEFAULT NULL COMMENT 'Sector destino que se revisa ítems más nuevos al parkinear', `orderMode` enum('Location','Age') NOT NULL DEFAULT 'Location', `editorFk` int(10) unsigned DEFAULT NULL, - `hasNewLabelMrwMethod` tinyint(1) NOT NULL DEFAULT 1 COMMENT 'column to activate the new mrw integration', `minPlantTrayLength` int(11) NOT NULL DEFAULT 53 COMMENT 'minimum length for plant tray restriction. Avoid to make collection of the ticket with this kind of item', PRIMARY KEY (`id`), KEY `productionConfig_FK` (`shortageAddressFk`), @@ -36267,10 +36331,14 @@ CREATE TABLE `routeCommission` ( `cat4m3` decimal(5,2) DEFAULT NULL, `cat5m3` decimal(5,2) DEFAULT NULL, `freelanceYearlyM3` decimal(5,2) DEFAULT NULL, + `countryFk` mediumint(8) unsigned DEFAULT NULL, + `isKmTruckRate` tinyint(1) DEFAULT NULL, PRIMARY KEY (`id`), KEY `routeCommission_routeFk_idx` (`routeFk`), KEY `routeCommission_workCenterFk_idx` (`workCenterFk`), KEY `routeCommission_firstEditorFk` (`firstEditorFk`), + KEY `routeCommission_country_FK` (`countryFk`), + CONSTRAINT `routeCommission_country_FK` FOREIGN KEY (`countryFk`) REFERENCES `country` (`id`) ON UPDATE CASCADE, CONSTRAINT `routeCommission_routeFk` FOREIGN KEY (`routeFk`) REFERENCES `route` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `routeCommission_workCenterFk` FOREIGN KEY (`workCenterFk`) REFERENCES `workCenter` (`id`) ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; @@ -36517,7 +36585,7 @@ CREATE TABLE `sale` ( `ticketFk` int(11) NOT NULL, `concept` varchar(50) DEFAULT NULL, `quantity` decimal(10,2) NOT NULL DEFAULT 0.00, - `originalQuantity` double(9,1) DEFAULT NULL COMMENT 'Se utiliza para notificar a través de rocket los cambios de quantity', + `originalQuantity` decimal(10,2) NOT NULL DEFAULT 0.00 COMMENT 'Se utiliza para notificar a través de rocket los cambios de quantity', `price` decimal(10,2) NOT NULL DEFAULT 0.00, `discount` tinyint(2) unsigned NOT NULL DEFAULT 0, `priceFixed` decimal(10,2) NOT NULL DEFAULT 0.00, @@ -37062,6 +37130,36 @@ CREATE TABLE `sample` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; /*!40101 SET character_set_client = @saved_cs_client */; +-- +-- Table structure for table `saySimpleConfig` +-- + +DROP TABLE IF EXISTS `saySimpleConfig`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `saySimpleConfig` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `url` varchar(255) NOT NULL, + `defaultChannel` varchar(128) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `saySimpleCountry` +-- + +DROP TABLE IF EXISTS `saySimpleCountry`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `saySimpleCountry` ( + `countryFk` mediumint(8) unsigned NOT NULL, + `channel` varchar(128) DEFAULT NULL, + PRIMARY KEY (`countryFk`), + CONSTRAINT `saySimpleCountry_FK` FOREIGN KEY (`countryFk`) REFERENCES `country` (`id`) ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + -- -- Table structure for table `scanner` -- @@ -37391,7 +37489,7 @@ CREATE TABLE `shelvingLog` ( `action` set('insert','update','delete','select') NOT NULL, `creationDate` timestamp NULL DEFAULT current_timestamp(), `description` text CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL, - `changedModel` enum('Shelving') NOT NULL DEFAULT 'Shelving', + `changedModel` enum('Shelving','ItemShelving') NOT NULL DEFAULT 'Shelving', `oldInstance` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`oldInstance`)), `newInstance` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`newInstance`)), `changedModelId` int(11) NOT NULL, @@ -37867,13 +37965,13 @@ CREATE TABLE `stockBought` ( /*!40101 SET character_set_client = @saved_cs_client */; -- --- Table structure for table `stockBuyed__` +-- Table structure for table `stockBuyed` -- -DROP TABLE IF EXISTS `stockBuyed__`; +DROP TABLE IF EXISTS `stockBuyed`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; -CREATE TABLE `stockBuyed__` ( +CREATE TABLE `stockBuyed` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `userFk` int(10) unsigned DEFAULT NULL, `buyed` decimal(10,2) DEFAULT NULL, @@ -37943,6 +38041,8 @@ CREATE TABLE `supplier` ( `isPayMethodChecked` tinyint(4) NOT NULL DEFAULT 0 COMMENT 'Se ha validado la forma de pago', `isVies` tinyint(4) NOT NULL DEFAULT 0, `stamp` longblob DEFAULT NULL, + `companySize` enum('small','medium','big') DEFAULT NULL, + `geoFk` int(11) DEFAULT NULL, `editorFk` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `cuenta` (`account`), @@ -37958,6 +38058,7 @@ CREATE TABLE `supplier` ( KEY `suppplier_supplierActivityFk` (`supplierActivityFk`), KEY `supplier_workerFk` (`workerFk`), KEY `supplier_fk_editor` (`editorFk`), + KEY `supplier_zoneGeo_FK` (`geoFk`), CONSTRAINT `Id_Pais` FOREIGN KEY (`countryFk`) REFERENCES `country` (`id`) ON UPDATE CASCADE, CONSTRAINT `pay_dem_id` FOREIGN KEY (`payDemFk`) REFERENCES `payDem` (`id`) ON UPDATE CASCADE, CONSTRAINT `pay_met_id` FOREIGN KEY (`payMethodFk`) REFERENCES `payMethod` (`id`) ON UPDATE CASCADE, @@ -37967,6 +38068,7 @@ CREATE TABLE `supplier` ( CONSTRAINT `supplier_transactionFk` FOREIGN KEY (`transactionTypeSageFk`) REFERENCES `sage`.`TiposTransacciones` (`CodigoTransaccion`) ON UPDATE CASCADE, CONSTRAINT `supplier_withholdingFk` FOREIGN KEY (`withholdingSageFk`) REFERENCES `sage`.`TiposRetencion` (`CodigoRetencion`) ON UPDATE CASCADE, CONSTRAINT `supplier_workerFk` FOREIGN KEY (`workerFk`) REFERENCES `worker` (`id`) ON UPDATE CASCADE, + CONSTRAINT `supplier_zoneGeo_FK` FOREIGN KEY (`geoFk`) REFERENCES `zoneGeo` (`id`) ON UPDATE CASCADE, CONSTRAINT `suppplier_supplierActivityFk` FOREIGN KEY (`supplierActivityFk`) REFERENCES `supplierActivity` (`code`) ON UPDATE CASCADE, CONSTRAINT `supplierAccountTooShort` CHECK (octet_length(`account`) = 10) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci; @@ -39470,6 +39572,8 @@ CREATE TABLE `travel` ( `clonedFrom` int(11) DEFAULT NULL, `editorFk` int(10) unsigned DEFAULT NULL, `awbFk` smallint(11) unsigned DEFAULT NULL, + `daysInForward` int(10) unsigned DEFAULT NULL COMMENT 'Cuando es una redada, indica el número de días que se añadirán a la fecha de hoy para establecer el landed. NULL si no es una redada', + `isRaid` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'Redada', PRIMARY KEY (`id`), UNIQUE KEY `shipment_1` (`shipped`,`landed`,`warehouseInFk`,`warehouseOutFk`,`agencyModeFk`,`ref`), KEY `shipment` (`shipped`), @@ -40211,6 +40315,25 @@ CREATE TABLE `workCenter` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci; /*!40101 SET character_set_client = @saved_cs_client */; +-- +-- Table structure for table `workCenterCommission` +-- + +DROP TABLE IF EXISTS `workCenterCommission`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `workCenterCommission` ( + `workCenterFk` int(11) NOT NULL, + `deliveryManAdjustment` decimal(4,2) DEFAULT NULL COMMENT 'Número de trabajadores para equilibrar los repartidores de diferentes centros.\n Utilizado en repartidores de grafana', + `distributionM3Category1` decimal(5,2) DEFAULT NULL, + `distributionM3Category2` decimal(5,2) DEFAULT NULL, + `distributionCat4M3` decimal(5,2) DEFAULT NULL COMMENT 'Comisión por gestión de la distribución Cat IV', + `distributionCat5M3` decimal(5,2) DEFAULT NULL COMMENT 'Comisión por gestión de la distribución Cat V', + PRIMARY KEY (`workCenterFk`), + CONSTRAINT `workCenterCommission_workCenterFk` FOREIGN KEY (`workCenterFk`) REFERENCES `workCenter` (`id`) ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + -- -- Table structure for table `workCenterHoliday` -- @@ -40480,8 +40603,13 @@ CREATE TABLE `workerDistributionCategory` ( `id` int(11) NOT NULL AUTO_INCREMENT, `workerFk` int(10) unsigned NOT NULL, `category` int(11) NOT NULL, + `countryFk` mediumint(8) unsigned DEFAULT NULL, + `isKmTruckRate` tinyint(1) DEFAULT NULL, + `commissionSplitWorkers` int(10) unsigned NOT NULL DEFAULT 1 COMMENT 'Número de enrutadores entr los que se reparte la comsión', PRIMARY KEY (`id`), KEY `workerDistributionCategory_workerFk_idx` (`workerFk`), + KEY `workerDistributionCategory_country_FK` (`countryFk`), + CONSTRAINT `workerDistributionCategory_country_FK` FOREIGN KEY (`countryFk`) REFERENCES `country` (`id`) ON UPDATE CASCADE, CONSTRAINT `workerDistributionCategory_workerFk` FOREIGN KEY (`workerFk`) REFERENCES `worker` (`id`) ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; /*!40101 SET character_set_client = @saved_cs_client */; @@ -41817,24 +41945,6 @@ END */ ;; /*!50003 SET character_set_client = @saved_cs_client */ ;; /*!50003 SET character_set_results = @saved_cs_results */ ;; /*!50003 SET collation_connection = @saved_col_connection */ ;; -/*!50106 DROP EVENT IF EXISTS `raidUpdate` */;; -DELIMITER ;; -/*!50003 SET @saved_cs_client = @@character_set_client */ ;; -/*!50003 SET @saved_cs_results = @@character_set_results */ ;; -/*!50003 SET @saved_col_connection = @@collation_connection */ ;; -/*!50003 SET character_set_client = utf8mb4 */ ;; -/*!50003 SET character_set_results = utf8mb4 */ ;; -/*!50003 SET collation_connection = utf8mb4_unicode_ci */ ;; -/*!50003 SET @saved_sql_mode = @@sql_mode */ ;; -/*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ;; -/*!50003 SET @saved_time_zone = @@time_zone */ ;; -/*!50003 SET time_zone = 'SYSTEM' */ ;; -/*!50106 CREATE*/ /*!50117 DEFINER=`vn`@`localhost`*/ /*!50106 EVENT `raidUpdate` ON SCHEDULE EVERY 1 DAY STARTS '2017-12-29 00:05:00' ON COMPLETION PRESERVE ENABLE DO CALL raidUpdate */ ;; -/*!50003 SET time_zone = @saved_time_zone */ ;; -/*!50003 SET sql_mode = @saved_sql_mode */ ;; -/*!50003 SET character_set_client = @saved_cs_client */ ;; -/*!50003 SET character_set_results = @saved_cs_results */ ;; -/*!50003 SET collation_connection = @saved_col_connection */ ;; /*!50106 DROP EVENT IF EXISTS `route_doRecalc` */;; DELIMITER ;; /*!50003 SET @saved_cs_client = @@character_set_client */ ;; @@ -42037,9 +42147,12 @@ BEGIN SELECT p.geoFk INTO vGeoFk FROM address a JOIN town t ON t.provinceFk = a.provinceFk - JOIN postCode p ON p.townFk = t.id AND p.`code` = a.postalCode + JOIN postCode p ON p.townFk = t.id + AND (p.code = a.postalCode OR a.postalCode IS NULL) + JOIN zoneGeo zg ON zg.id = p.geoFk WHERE a.id = vSelf - ORDER BY (a.city SOUNDS LIKE t.`name`) DESC + ORDER BY (a.city SOUNDS LIKE t.name) DESC, + (p.code = a.postalCode) DESC LIMIT 1; RETURN vGeoFk; @@ -42114,6 +42227,48 @@ DELIMITER ; /*!50003 SET collation_connection = @saved_col_connection */ ; /*!50003 SET @saved_sql_mode = @@sql_mode */ ; /*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; +/*!50003 DROP FUNCTION IF EXISTS `buy_getUltimate` */; +/*!50003 SET @saved_cs_client = @@character_set_client */ ; +/*!50003 SET @saved_cs_results = @@character_set_results */ ; +/*!50003 SET @saved_col_connection = @@collation_connection */ ; +/*!50003 SET character_set_client = utf8mb4 */ ; +/*!50003 SET character_set_results = utf8mb4 */ ; +/*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; +DELIMITER ;; +CREATE DEFINER=`vn`@`localhost` FUNCTION `buy_getUltimate`(vItemFk INT, + vWarehouseFk INT, + vDated DATE +) RETURNS int(11) + DETERMINISTIC +BEGIN +/** + * Calcula las últimas compras realizadas hasta una fecha. + * + * @param vItemFk Id del artículo + * @param vWarehouseFk Id del almacén + * @param vDated Compras hasta fecha + * @return Id de compra + */ + DECLARE vBuyFk INT; + + CALL buy_getUltimate(vItemFk, vWarehouseFk, vDated); + + SELECT buyFk INTO vBuyFk + FROM tmp.buyUltimate; + + DROP TEMPORARY TABLE IF EXISTS + tmp.buyUltimate, + tmp.buyUltimateFromInterval; + + RETURN vBuyFk; +END ;; +DELIMITER ; +/*!50003 SET sql_mode = @saved_sql_mode */ ; +/*!50003 SET character_set_client = @saved_cs_client */ ; +/*!50003 SET character_set_results = @saved_cs_results */ ; +/*!50003 SET collation_connection = @saved_col_connection */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; /*!50003 DROP FUNCTION IF EXISTS `buy_getUnitVolume` */; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; @@ -42397,37 +42552,37 @@ DELIMITER ; DELIMITER ;; CREATE DEFINER=`vn`@`localhost` FUNCTION `client_getDebt`(`vClient` INT, `vDate` DATE) RETURNS decimal(10,2) READS SQL DATA -BEGIN -/** - * Returns the risk of a customer. - * - * @param vClient client id - * @param vDate date to check the risk - * @return Client risk - */ - DECLARE vDebt DECIMAL(10,2); - DECLARE vHasDebt BOOLEAN; - - SELECT COUNT(*) INTO vHasDebt - FROM `client` c - WHERE c.id = vClient AND c.typeFk = 'normal'; - - IF NOT vHasDebt THEN - RETURN 0; - END IF; - - CREATE OR REPLACE TEMPORARY TABLE tmp.clientGetDebt (clientFk INT); - INSERT INTO tmp.clientGetDebt SET clientFk = vClient; - - CALL vn.client_getDebt(vDate); - - SELECT risk INTO vDebt FROM tmp.risk; - - DROP TEMPORARY TABLE - tmp.clientGetDebt, - tmp.risk; - - RETURN vDebt; +BEGIN +/** + * Returns the risk of a customer. + * + * @param vClient client id + * @param vDate date to check the risk + * @return Client risk + */ + DECLARE vDebt DECIMAL(10,2); + DECLARE vHasDebt BOOLEAN; + + SELECT COUNT(*) INTO vHasDebt + FROM `client` c + WHERE c.id = vClient AND c.typeFk = 'normal'; + + IF NOT vHasDebt THEN + RETURN 0; + END IF; + + CREATE OR REPLACE TEMPORARY TABLE tmp.clientGetDebt (clientFk INT); + INSERT INTO tmp.clientGetDebt SET clientFk = vClient; + + CALL vn.client_getDebt(vDate); + + SELECT risk INTO vDebt FROM tmp.risk; + + DROP TEMPORARY TABLE + tmp.clientGetDebt, + tmp.risk; + + RETURN vDebt; END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -42489,6 +42644,45 @@ DELIMITER ; /*!50003 SET collation_connection = @saved_col_connection */ ; /*!50003 SET @saved_sql_mode = @@sql_mode */ ; /*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; +/*!50003 DROP FUNCTION IF EXISTS `client_getGeo` */; +/*!50003 SET @saved_cs_client = @@character_set_client */ ; +/*!50003 SET @saved_cs_results = @@character_set_results */ ; +/*!50003 SET @saved_col_connection = @@collation_connection */ ; +/*!50003 SET character_set_client = utf8mb4 */ ; +/*!50003 SET character_set_results = utf8mb4 */ ; +/*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; +DELIMITER ;; +CREATE DEFINER=`vn`@`localhost` FUNCTION `client_getGeo`(vSelf INT) RETURNS int(11) + DETERMINISTIC +BEGIN +/** + * Returns the geo for the passed client. + * + * @param vSelf The address id + * @return The geo id + */ + DECLARE vGeoFk INT; + + SELECT p.geoFk INTO vGeoFk + FROM client c + JOIN town t ON t.provinceFk = c.provinceFk + JOIN postCode p ON p.townFk = t.id + AND (p.code = c.postcode OR c.postcode IS NULL) + JOIN zoneGeo zg ON zg.id = p.geoFk + WHERE c.id = vSelf + ORDER BY (c.city SOUNDS LIKE t.name) DESC, + (p.code = c.postcode) DESC + LIMIT 1; + + RETURN vGeoFk; +END ;; +DELIMITER ; +/*!50003 SET sql_mode = @saved_sql_mode */ ; +/*!50003 SET character_set_client = @saved_cs_client */ ; +/*!50003 SET character_set_results = @saved_cs_results */ ; +/*!50003 SET collation_connection = @saved_col_connection */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; /*!50003 DROP FUNCTION IF EXISTS `client_getSalesPerson` */; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; @@ -43038,58 +43232,51 @@ DELIMITER ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; CREATE DEFINER=`vn`@`localhost` FUNCTION `entry_getCommission`(vTravelFk INT, - vCurrencyFk INT, - vSupplierFk INT + vCurrencyFk INT, + vSupplierFk INT ) RETURNS int(11) READS SQL DATA BEGIN - DECLARE vCommission INT; - DECLARE vCurrentCommission INT; - DECLARE vIsCurrencyUsd INT; - DECLARE vLastEntryFk INT; - - SELECT count(*) INTO vIsCurrencyUsd - FROM currency c - WHERE c.code = 'USD' AND id = vCurrencyFk; - - IF NOT vIsCurrencyUsd THEN - - SELECT e.id INTO vLastEntryFk - FROM vn.entry e - JOIN vn.travel tr ON tr.id = e.travelFk - WHERE e.supplierFk = vSupplierFk - ORDER BY tr.landed DESC - LIMIT 1; - - IF vLastEntryFk THEN - - SELECT commission INTO vCurrentCommission - FROM vn.entry - WHERE id = vLastEntryFk; - - ELSE - - SELECT commission INTO vCurrentCommission - FROM supplier s - WHERE s.id = vSupplierFk; - - END IF; - - RETURN vCurrentCommission; - - ELSE + DECLARE vCommission INT; + DECLARE vCurrentCommission INT; + DECLARE vIsNotEUR INT; + DECLARE vLastEntryFk INT; + SELECT count(*) INTO vIsNotEUR + FROM currency c + WHERE c.code <> 'EUR' AND id = vCurrencyFk; + + IF vIsNotEUR THEN SELECT ROUND(-100 * (1 - (1 / r.value))) INTO vCommission FROM travel t LEFT JOIN referenceCurrent r ON r.currencyFk = vCurrencyFk AND r.`dated` <= t.shipped WHERE t.id = vTravelFk ORDER BY r.`dated` DESC LIMIT 1; - + RETURN IFNULL(vCommission, 0); - - END IF; - + ELSE + SELECT e.id INTO vLastEntryFk + FROM `entry` e + JOIN travel tr ON tr.id = e.travelFk + WHERE e.supplierFk = vSupplierFk + ORDER BY tr.landed DESC + LIMIT 1; + + IF vLastEntryFk THEN + SELECT commission INTO vCurrentCommission + FROM `entry` + WHERE id = vLastEntryFk; + + ELSE + SELECT commission INTO vCurrentCommission + FROM supplier s + WHERE s.id = vSupplierFk; + + END IF; + + RETURN vCurrentCommission; + END IF; END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -43719,7 +43906,7 @@ BEGIN SELECT count(*) INTO vItemCount FROM vn.sale s JOIN vn.itemShelving ish ON ish.itemFk = s.itemFk - JOIN vn.shelving sh ON sh.code = ish.shelvingFk + JOIN vn.shelving sh ON sh.id = ish.shelvingFk JOIN vn.parking p ON p.id = sh.parkingFk WHERE s.ticketFk = vTicketFk AND p.sectorFk = vSectorFk; @@ -44169,7 +44356,7 @@ BEGIN SELECT count(*) INTO vItemCount FROM vn.sale s JOIN vn.itemShelving ish ON ish.itemFk = s.itemFk - JOIN vn.shelving sh ON sh.code = ish.shelvingFk + JOIN vn.shelving sh ON sh.id = ish.shelvingFk JOIN vn.parking p ON p.id = sh.parkingFk WHERE s.ticketFk = vTicketFk AND p.sectorFk = vSectorFk; @@ -44867,6 +45054,47 @@ DELIMITER ; /*!50003 SET collation_connection = @saved_col_connection */ ; /*!50003 SET @saved_sql_mode = @@sql_mode */ ; /*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; +/*!50003 DROP FUNCTION IF EXISTS `supplier_getGeo` */; +/*!50003 SET @saved_cs_client = @@character_set_client */ ; +/*!50003 SET @saved_cs_results = @@character_set_results */ ; +/*!50003 SET @saved_col_connection = @@collation_connection */ ; +/*!50003 SET character_set_client = utf8mb4 */ ; +/*!50003 SET character_set_results = utf8mb4 */ ; +/*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; +DELIMITER ;; +CREATE DEFINER=`vn`@`localhost` FUNCTION `supplier_getGeo`(vSelf INT) RETURNS int(11) + DETERMINISTIC +BEGIN +/** + * Returns the geo for the passed supplier. + * + * @param vSelf The address id + * @return The geo id + */ + DECLARE vGeoFk INT; + + SELECT p.geoFk INTO vGeoFk + FROM supplier s + JOIN town t ON t.provinceFk = s.provinceFk + JOIN postCode p ON p.townFk = t.id + AND (p.code = s.postCode OR s.postCode IS NULL) + LEFT JOIN supplierAddress sad ON sad.supplierFk = s.id + JOIN zoneGeo zg ON zg.id = p.geoFk + WHERE s.id = vSelf + ORDER BY (s.city SOUNDS LIKE t.name) DESC, + (p.code = s.postCode) DESC, + (p.code = sad.postalCode) DESC + LIMIT 1; + + RETURN vGeoFk; +END ;; +DELIMITER ; +/*!50003 SET sql_mode = @saved_sql_mode */ ; +/*!50003 SET character_set_client = @saved_cs_client */ ; +/*!50003 SET character_set_results = @saved_cs_results */ ; +/*!50003 SET collation_connection = @saved_col_connection */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; /*!50003 DROP FUNCTION IF EXISTS `testCIF` */; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; @@ -45976,40 +46204,6 @@ DELIMITER ; /*!50003 SET collation_connection = @saved_col_connection */ ; /*!50003 SET @saved_sql_mode = @@sql_mode */ ; /*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; -/*!50003 DROP FUNCTION IF EXISTS `workerMachinery_isRegistered` */; -/*!50003 SET @saved_cs_client = @@character_set_client */ ; -/*!50003 SET @saved_cs_results = @@character_set_results */ ; -/*!50003 SET @saved_col_connection = @@collation_connection */ ; -/*!50003 SET character_set_client = utf8mb4 */ ; -/*!50003 SET character_set_results = utf8mb4 */ ; -/*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; -DELIMITER ;; -CREATE DEFINER=`vn`@`localhost` FUNCTION `workerMachinery_isRegistered`(vWorkerFk VARCHAR(10)) RETURNS tinyint(1) - READS SQL DATA -BEGIN -/** - * Comprueba si existen registros en las últimas horas (maxHours de machineWorkerConfig) del trabajador vWorkerFk y si tiene a nulo la hora outTimed (indica la hora que deja el vehículo) - * - * @param vWorkerFk id del trabajador - * @return Devuelve TRUE/FALSE en caso de que haya o no registros - */ - IF (SELECT COUNT(*) - FROM machineWorker m - WHERE m.workerFk = vWorkerFk - AND m.inTimed >= TIMESTAMPADD(HOUR , -(SELECT maxHours from machineWorkerConfig), util.VN_NOW()) AND ISNULL(m.outTimed)) - THEN - RETURN TRUE; - ELSE - RETURN FALSE; - END IF; -END ;; -DELIMITER ; -/*!50003 SET sql_mode = @saved_sql_mode */ ; -/*!50003 SET character_set_client = @saved_cs_client */ ; -/*!50003 SET character_set_results = @saved_cs_results */ ; -/*!50003 SET collation_connection = @saved_col_connection */ ; -/*!50003 SET @saved_sql_mode = @@sql_mode */ ; -/*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; /*!50003 DROP FUNCTION IF EXISTS `workerNigthlyHours_calculate` */; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; @@ -46300,7 +46494,7 @@ BEGIN AND vWarehouseFk IN (tr.warehouseInFk, 0) AND b.itemFk = vItemFk AND NOT e.isExcludedFromAvailable - AND NOT e.isRaid + AND NOT tr.isRaid UNION ALL SELECT tr.shipped, NULL, @@ -46319,7 +46513,7 @@ BEGIN AND s.id <> (SELECT supplierFk FROM inventoryConfig) AND b.itemFk = vItemFk AND NOT e.isExcludedFromAvailable - AND NOT e.isRaid + AND NOT tr.isRaid UNION ALL SELECT t.shipped, NULL, @@ -46342,7 +46536,7 @@ BEGIN FROM tHistoricalPast WHERE `date` < vDate; - SELECT p1.*, NULL v_virtual + SELECT p1.*, NULL v_virtual FROM ( SELECT vDate `date`, vCalculatedInventory input, @@ -46357,7 +46551,7 @@ BEGIN FROM tHistoricalPast WHERE `date` >= vDate ) p1; - + DROP TEMPORARY TABLE tHistoricalPast; END ;; DELIMITER ; @@ -46911,7 +47105,7 @@ CREATE DEFINER=`vn`@`localhost` PROCEDURE `available_traslate`( vWarehouseShipment INT) proc: BEGIN /** - * Calcular la disponibilidad dependiendo del almacen + * Calcular la disponibilidad dependiendo del almacen * de origen y destino según la fecha. * * @param vWarehouseLanding Almacén de llegada @@ -46948,10 +47142,10 @@ proc: BEGIN WHERE t.landed BETWEEN vDatedInventory AND vDatedFrom AND t.warehouseInFk = vWarehouseLanding AND NOT e.isExcludedFromAvailable - AND NOT e.isRaid + AND NOT t.isRaid GROUP BY c.itemFk; - -- Tabla con el ultimo dia de last_buy para cada producto + -- Tabla con el ultimo dia de last_buy para cada producto -- que hace un replace de la anterior. CALL buy_getUltimate (NULL, vWarehouseShipment, util.VN_CURDATE()); @@ -46963,7 +47157,7 @@ proc: BEGIN JOIN travel tr ON tr.id = e.travelFk LEFT JOIN tItemRange i ON t.itemFk = i.itemFk WHERE t.warehouseFk = vWarehouseShipment - AND NOT e.isRaid + AND NOT tr.isRaid ON DUPLICATE KEY UPDATE tItemRange.dated = GREATEST(tItemRange.dated, tr.landed); @@ -47000,7 +47194,7 @@ proc: BEGIN JOIN tItemRangeLive ir ON ir.itemFk = b.itemFk WHERE NOT e.isExcludedFromAvailable AND b.quantity <> 0 - AND NOT e.isRaid + AND NOT t.isRaid AND t.warehouseInFk = vWarehouseLanding AND t.landed >= vDatedFrom AND (ir.dated IS NULL OR t.landed <= ir.dated) @@ -47994,7 +48188,7 @@ DELIMITER ; DELIMITER ;; CREATE DEFINER=`vn`@`localhost` PROCEDURE `buy_getUltimate`( vItemFk INT, - vWarehouseFk SMALLINT, + vWarehouseFk INT, vDated DATE ) BEGIN @@ -49547,7 +49741,7 @@ BEGIN AND ts.id IS NULL; DELETE FROM claim WHERE ticketCreated < v4Years; -- Robert ubicacion anterior de travelLog comentario para debug - DELETE FROM zoneEvent WHERE `type` = 'day' AND dated < v3Months; + DELETE FROM zoneEvent WHERE dated < v2Months OR ended < v2Months; DELETE b FROM buy b JOIN entryConfig e ON e.defaultEntry = b.entryFk WHERE b.created < v2Months; @@ -49758,7 +49952,7 @@ BEGIN JOIN agencyMode am ON am.id = tr.agencyModeFk WHERE NOT b.quantity AND am.code = 'logiflora' - AND e.isRaid; + AND tr.daysInForward; START TRANSACTION; @@ -51071,7 +51265,7 @@ BEGIN AND s.semaphore = 1 GROUP BY st.saleFk) st ON st.saleFk = ts.saleFk JOIN itemShelving ish ON ish.itemFk = ts.itemFk - JOIN shelving sh ON sh.code = ish.shelvingFk + JOIN shelving sh ON sh.id = ish.shelvingFk JOIN parking p ON p.id = sh.parkingFk JOIN sector sc ON sc.id = p.sectorFk JOIN sectorType st ON st.id = sc.typeFk @@ -51221,93 +51415,93 @@ DELIMITER ; /*!50003 SET character_set_results = utf8mb4 */ ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; -CREATE DEFINER=`vn`@`localhost` PROCEDURE `collection_addWithReservation`( - vItemFk INT, - vQuantity INT, - vTicketFk INT, - vSaleGroupFk INT, - vSectorFk INT +CREATE DEFINER=`vn`@`localhost` PROCEDURE `collection_addWithReservation`( + vItemFk INT, + vQuantity INT, + vTicketFk INT, + vSaleGroupFk INT, + vSectorFk INT ) -BEGIN -/** - * En el ámbito de las colecciones se añade una línea de sale a un ticket - * de una colección en caso de tener disponible y se realiza la reserva. - * - * @param vItemFk id of item - * @param vQuantity quantity to be added to the ticket - * @param vTicketFk ticket to which the sales line is added - * @param vSaleGroupFk saleGroupFk id to add saleGroupDetail - */ - - DECLARE vWarehouseFk INT; - DECLARE vCacheAvailableFk INT; - DECLARE vAvailable INT; - DECLARE vSaleFk INT; - DECLARE vConcept VARCHAR(50); - DECLARE vItemName VARCHAR(50); - DECLARE vHasThrow BOOLEAN DEFAULT FALSE; - - DECLARE EXIT HANDLER FOR SQLEXCEPTION - BEGIN - ROLLBACK; - RESIGNAL; - END; - - SELECT t.warehouseFk INTO vWarehouseFk - FROM ticket t - JOIN ticketCollection tc ON tc.ticketFk = t.id - WHERE t.id = vTicketFk; - - CALL cache.available_refresh( - vCacheAvailableFk, - FALSE, - vWarehouseFk, - util.VN_CURDATE()); - - SELECT available INTO vAvailable - FROM cache.available - WHERE calc_id = vCacheAvailableFk - AND item_id = vItemFk; - - IF vAvailable < vQuantity THEN - SET vHasThrow = TRUE; - ELSE - SELECT `name`, - CONCAT(getUser(), ' ', DATE_FORMAT(util.VN_NOW(), '%H:%i'), ' ', name) - INTO vItemName, vConcept - FROM item - WHERE id = vItemFk; - - START TRANSACTION; - - INSERT INTO sale - SET itemFk = vItemFk, - ticketFk = vTicketFk, - concept = vConcept, - quantity = vQuantity, - isAdded = TRUE; - - SELECT LAST_INSERT_ID() INTO vSaleFk; - - CALL sale_calculateComponent(vSaleFk, NULL); - CALL itemShelvingSale_addBySale(vSaleFk, vSectorFk); - - IF NOT EXISTS (SELECT TRUE FROM itemShelvingSale WHERE saleFk = vSaleFk LIMIT 1) THEN - SET vHasThrow = TRUE; - END IF; - END IF; - - IF vHasThrow THEN - CALL util.throw("There is no available for the selected item"); - END IF; - - IF vSaleGroupFk THEN - INSERT INTO saleGroupDetail - SET saleFk = vSaleFk, - saleGroupFk = vSaleGroupFk; - END IF; - - COMMIT; +BEGIN +/** + * En el ámbito de las colecciones se añade una línea de sale a un ticket + * de una colección en caso de tener disponible y se realiza la reserva. + * + * @param vItemFk id of item + * @param vQuantity quantity to be added to the ticket + * @param vTicketFk ticket to which the sales line is added + * @param vSaleGroupFk saleGroupFk id to add saleGroupDetail + */ + + DECLARE vWarehouseFk INT; + DECLARE vCacheAvailableFk INT; + DECLARE vAvailable INT; + DECLARE vSaleFk INT; + DECLARE vConcept VARCHAR(50); + DECLARE vItemName VARCHAR(50); + DECLARE vHasThrow BOOLEAN DEFAULT FALSE; + + DECLARE EXIT HANDLER FOR SQLEXCEPTION + BEGIN + ROLLBACK; + RESIGNAL; + END; + + SELECT t.warehouseFk INTO vWarehouseFk + FROM ticket t + JOIN ticketCollection tc ON tc.ticketFk = t.id + WHERE t.id = vTicketFk; + + CALL cache.available_refresh( + vCacheAvailableFk, + FALSE, + vWarehouseFk, + util.VN_CURDATE()); + + SELECT available INTO vAvailable + FROM cache.available + WHERE calc_id = vCacheAvailableFk + AND item_id = vItemFk; + + IF vAvailable < vQuantity THEN + SET vHasThrow = TRUE; + ELSE + SELECT `name`, + CONCAT(getUser(), ' ', DATE_FORMAT(util.VN_NOW(), '%H:%i'), ' ', name) + INTO vItemName, vConcept + FROM item + WHERE id = vItemFk; + + START TRANSACTION; + + INSERT INTO sale + SET itemFk = vItemFk, + ticketFk = vTicketFk, + concept = vConcept, + quantity = vQuantity, + isAdded = TRUE; + + SELECT LAST_INSERT_ID() INTO vSaleFk; + + CALL sale_calculateComponent(vSaleFk, NULL); + CALL itemShelvingSale_addBySale(vSaleFk, vSectorFk); + + IF NOT EXISTS (SELECT TRUE FROM itemShelvingSale WHERE saleFk = vSaleFk LIMIT 1) THEN + SET vHasThrow = TRUE; + END IF; + END IF; + + IF vHasThrow THEN + CALL util.throw("There is no available for the selected item"); + END IF; + + IF vSaleGroupFk THEN + INSERT INTO saleGroupDetail + SET saleFk = vSaleFk, + saleGroupFk = vSaleGroupFk; + END IF; + + COMMIT; END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -51324,145 +51518,145 @@ DELIMITER ; /*!50003 SET character_set_results = utf8mb4 */ ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; -CREATE DEFINER=`vn`@`localhost` PROCEDURE `collection_assign`( - vUserFk INT, - OUT vCollectionFk INT +CREATE DEFINER=`vn`@`localhost` PROCEDURE `collection_assign`( + vUserFk INT, + OUT vCollectionFk INT ) -BEGIN -/** - * Comprueba si existen colecciones libres que se ajustan - * al perfil del usuario y le asigna la más antigua. - * Añade un registro al semillero de colecciones. - * - * @param vUserFk Id de usuario - * @param vCollectionFk Id de colección - */ - DECLARE vHasTooMuchCollections BOOL; - DECLARE vDone BOOL DEFAULT FALSE; - DECLARE vCollectionWorker INT; - DECLARE vMaxNotAssignedCollectionLifeTime TIME; - - DECLARE vCollections CURSOR FOR - WITH collections AS ( - SELECT tc.collectionFk, - SUM(sv.volume) volume, - c.saleTotalCount, - c.itemPackingTypeFk, - c.trainFk, - c.warehouseFk, - c.wagons - FROM vn.ticketCollection tc - JOIN vn.collection c ON c.id = tc.collectionFk - JOIN vn.saleVolume sv ON sv.ticketFk = tc.ticketFk - WHERE c.workerFk IS NULL - AND sv.shipped >= util.VN_CURDATE() - GROUP BY tc.collectionFk - ) SELECT c.collectionFk - FROM collections c - JOIN vn.operator o - WHERE o.workerFk = vUserFk - AND (c.saleTotalCount <= o.linesLimit OR o.linesLimit IS NULL) - AND (c.itemPackingTypeFk = o.itemPackingTypeFk OR o.itemPackingTypeFk IS NULL) - AND o.numberOfWagons = c.wagons - AND o.trainFk = c.trainFk - AND o.warehouseFk = c.warehouseFk; - - DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE; - -- Si hay colecciones sin terminar, sale del proceso - - DECLARE EXIT HANDLER FOR SQLEXCEPTION - BEGIN - ROLLBACK; - RESIGNAL; - END; - - CALL collection_get(vUserFk); - - SELECT (pc.maxNotReadyCollections - COUNT(*)) <= 0, pc.maxNotAssignedCollectionLifeTime - INTO vHasTooMuchCollections, vMaxNotAssignedCollectionLifeTime - FROM productionConfig pc - LEFT JOIN tmp.collection ON TRUE; - - DROP TEMPORARY TABLE tmp.collection; - - IF vHasTooMuchCollections THEN - CALL util.throw('Hay colecciones pendientes'); - END IF; - - -- Se eliminan las colecciones sin asignar que estan obsoletas - - INSERT INTO ticketTracking(stateFk, ticketFk) - SELECT s.id, tc.ticketFk - FROM `collection` c - JOIN ticketCollection tc ON tc.collectionFk = c.id - JOIN `state` s ON s.code = 'PRINTED_AUTO' - WHERE c.workerFk IS NULL - AND TIMEDIFF(util.VN_NOW(), c.created) > vMaxNotAssignedCollectionLifeTime; - - DELETE FROM `collection` - WHERE workerFk IS NULL - AND TIMEDIFF(util.VN_NOW(), created) > vMaxNotAssignedCollectionLifeTime; - - -- Se añade registro al semillero - - INSERT INTO collectionHotbed(userFk) VALUES(vUserFk); - - -- Comprueba si hay colecciones disponibles que se ajustan a su configuracion - - OPEN vCollections; - l: LOOP - SET vDone = FALSE; - FETCH vCollections INTO vCollectionFk; - - IF vDone THEN - LEAVE l; - END IF; - - BEGIN - DECLARE EXIT HANDLER FOR SQLEXCEPTION - BEGIN - ROLLBACK; - SET vCollectionFk = NULL; - RESIGNAL; - END; - - START TRANSACTION; - - SELECT workerFk INTO vCollectionWorker - FROM `collection` - WHERE id = vCollectionFk FOR UPDATE; - - IF vCollectionWorker IS NULL THEN - UPDATE `collection` - SET workerFk = vUserFk - WHERE id = vCollectionFk; - - COMMIT; - LEAVE l; - END IF; - - ROLLBACK; - END; - END LOOP; - CLOSE vCollections; - - IF vCollectionFk IS NULL THEN - CALL collection_new(vUserFk, vCollectionFk); - - START TRANSACTION; - - SELECT workerFk INTO vCollectionWorker - FROM `collection` - WHERE id = vCollectionFk FOR UPDATE; - - IF vCollectionWorker IS NULL THEN - UPDATE `collection` - SET workerFk = vUserFk - WHERE id = vCollectionFk; - END IF; - - COMMIT; - END IF; +BEGIN +/** + * Comprueba si existen colecciones libres que se ajustan + * al perfil del usuario y le asigna la más antigua. + * Añade un registro al semillero de colecciones. + * + * @param vUserFk Id de usuario + * @param vCollectionFk Id de colección + */ + DECLARE vHasTooMuchCollections BOOL; + DECLARE vDone BOOL DEFAULT FALSE; + DECLARE vCollectionWorker INT; + DECLARE vMaxNotAssignedCollectionLifeTime TIME; + + DECLARE vCollections CURSOR FOR + WITH collections AS ( + SELECT tc.collectionFk, + SUM(sv.volume) volume, + c.saleTotalCount, + c.itemPackingTypeFk, + c.trainFk, + c.warehouseFk, + c.wagons + FROM vn.ticketCollection tc + JOIN vn.collection c ON c.id = tc.collectionFk + JOIN vn.saleVolume sv ON sv.ticketFk = tc.ticketFk + WHERE c.workerFk IS NULL + AND sv.shipped >= util.VN_CURDATE() + GROUP BY tc.collectionFk + ) SELECT c.collectionFk + FROM collections c + JOIN vn.operator o + WHERE o.workerFk = vUserFk + AND (c.saleTotalCount <= o.linesLimit OR o.linesLimit IS NULL) + AND (c.itemPackingTypeFk = o.itemPackingTypeFk OR o.itemPackingTypeFk IS NULL) + AND o.numberOfWagons = c.wagons + AND o.trainFk = c.trainFk + AND o.warehouseFk = c.warehouseFk; + + DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE; + -- Si hay colecciones sin terminar, sale del proceso + + DECLARE EXIT HANDLER FOR SQLEXCEPTION + BEGIN + ROLLBACK; + RESIGNAL; + END; + + CALL collection_get(vUserFk); + + SELECT (pc.maxNotReadyCollections - COUNT(*)) <= 0, pc.maxNotAssignedCollectionLifeTime + INTO vHasTooMuchCollections, vMaxNotAssignedCollectionLifeTime + FROM productionConfig pc + LEFT JOIN tmp.collection ON TRUE; + + DROP TEMPORARY TABLE tmp.collection; + + IF vHasTooMuchCollections THEN + CALL util.throw('Hay colecciones pendientes'); + END IF; + + -- Se eliminan las colecciones sin asignar que estan obsoletas + + INSERT INTO ticketTracking(stateFk, ticketFk) + SELECT s.id, tc.ticketFk + FROM `collection` c + JOIN ticketCollection tc ON tc.collectionFk = c.id + JOIN `state` s ON s.code = 'PRINTED_AUTO' + WHERE c.workerFk IS NULL + AND TIMEDIFF(util.VN_NOW(), c.created) > vMaxNotAssignedCollectionLifeTime; + + DELETE FROM `collection` + WHERE workerFk IS NULL + AND TIMEDIFF(util.VN_NOW(), created) > vMaxNotAssignedCollectionLifeTime; + + -- Se añade registro al semillero + + INSERT INTO collectionHotbed(userFk) VALUES(vUserFk); + + -- Comprueba si hay colecciones disponibles que se ajustan a su configuracion + + OPEN vCollections; + l: LOOP + SET vDone = FALSE; + FETCH vCollections INTO vCollectionFk; + + IF vDone THEN + LEAVE l; + END IF; + + BEGIN + DECLARE EXIT HANDLER FOR SQLEXCEPTION + BEGIN + ROLLBACK; + SET vCollectionFk = NULL; + RESIGNAL; + END; + + START TRANSACTION; + + SELECT workerFk INTO vCollectionWorker + FROM `collection` + WHERE id = vCollectionFk FOR UPDATE; + + IF vCollectionWorker IS NULL THEN + UPDATE `collection` + SET workerFk = vUserFk + WHERE id = vCollectionFk; + + COMMIT; + LEAVE l; + END IF; + + ROLLBACK; + END; + END LOOP; + CLOSE vCollections; + + IF vCollectionFk IS NULL THEN + CALL collection_new(vUserFk, vCollectionFk); + + START TRANSACTION; + + SELECT workerFk INTO vCollectionWorker + FROM `collection` + WHERE id = vCollectionFk FOR UPDATE; + + IF vCollectionWorker IS NULL THEN + UPDATE `collection` + SET workerFk = vUserFk + WHERE id = vCollectionFk; + END IF; + + COMMIT; + END IF; END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -51530,146 +51724,146 @@ DELIMITER ; /*!50003 SET character_set_results = utf8mb4 */ ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; -CREATE DEFINER=`vn`@`localhost` PROCEDURE `collection_getAssigned`( - vUserFk INT, - OUT vCollectionFk INT +CREATE DEFINER=`vn`@`localhost` PROCEDURE `collection_getAssigned`( + vUserFk INT, + OUT vCollectionFk INT ) -BEGIN -/** - * Comprueba si existen colecciones libres que se ajustan - * al perfil del usuario y le asigna la más antigua. - * Añade un registro al semillero de colecciones. - * - * @param vUserFk Id de usuario - * @param vCollectionFk Id de colección - */ - DECLARE vHasTooMuchCollections BOOL; - DECLARE vDone BOOL DEFAULT FALSE; - DECLARE vCollectionWorker INT; - DECLARE vMaxNotAssignedCollectionLifeTime TIME; - - DECLARE vCollections CURSOR FOR - WITH collections AS ( - SELECT tc.collectionFk, - SUM(sv.volume) volume, - c.saleTotalCount, - c.itemPackingTypeFk, - c.trainFk, - c.warehouseFk, - c.wagons - FROM vn.ticketCollection tc - JOIN vn.collection c ON c.id = tc.collectionFk - JOIN vn.saleVolume sv ON sv.ticketFk = tc.ticketFk - WHERE c.workerFk IS NULL - AND sv.shipped >= util.VN_CURDATE() - GROUP BY tc.collectionFk - ) SELECT c.collectionFk - FROM collections c - JOIN vn.operator o - WHERE o.workerFk = vUserFk - AND (c.saleTotalCount <= o.linesLimit OR o.linesLimit IS NULL) - AND (c.itemPackingTypeFk = o.itemPackingTypeFk OR o.itemPackingTypeFk IS NULL) - AND o.numberOfWagons = c.wagons - AND o.trainFk = c.trainFk - AND o.warehouseFk = c.warehouseFk; - - DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE; - -- Si hay colecciones sin terminar, sale del proceso - - DECLARE EXIT HANDLER FOR SQLEXCEPTION - BEGIN - ROLLBACK; - RESIGNAL; - END; - - CALL collection_get(vUserFk); - - SELECT (pc.maxNotReadyCollections - COUNT(*)) <= 0, pc.maxNotAssignedCollectionLifeTime - INTO vHasTooMuchCollections, vMaxNotAssignedCollectionLifeTime - FROM productionConfig pc - LEFT JOIN tmp.collection ON TRUE; - - DROP TEMPORARY TABLE tmp.collection; - - IF vHasTooMuchCollections THEN - CALL util.throw('Hay colecciones pendientes'); - END IF; - - -- Se eliminan las colecciones sin asignar que estan obsoletas - - INSERT INTO ticketTracking(stateFk, ticketFk) - SELECT s.id, tc.ticketFk - FROM `collection` c - JOIN ticketCollection tc ON tc.collectionFk = c.id - JOIN `state` s ON s.code = 'PRINTED_AUTO' - WHERE c.workerFk IS NULL - AND TIMEDIFF(util.VN_NOW(), c.created) > vMaxNotAssignedCollectionLifeTime; - - DELETE FROM `collection` - WHERE workerFk IS NULL - AND TIMEDIFF(util.VN_NOW(), created) > vMaxNotAssignedCollectionLifeTime; - - -- Se añade registro al semillero - - INSERT INTO collectionHotbed(userFk) VALUES(vUserFk); - - -- Comprueba si hay colecciones disponibles que se ajustan a su configuracion - - OPEN vCollections; - l: LOOP - SET vDone = FALSE; - FETCH vCollections INTO vCollectionFk; - - IF vDone THEN - LEAVE l; - END IF; - - BEGIN - DECLARE EXIT HANDLER FOR SQLEXCEPTION - BEGIN - ROLLBACK; - SET vCollectionFk = NULL; - RESIGNAL; - END; - - START TRANSACTION; - - SELECT workerFk INTO vCollectionWorker - FROM `collection` - WHERE id = vCollectionFk FOR UPDATE; - - IF vCollectionWorker IS NULL THEN - UPDATE `collection` - SET workerFk = vUserFk - WHERE id = vCollectionFk; - - COMMIT; - LEAVE l; - END IF; - - ROLLBACK; - END; - END LOOP; - CLOSE vCollections; - - IF vCollectionFk IS NULL THEN - CALL collection_new(vUserFk, vCollectionFk); - - START TRANSACTION; - - SELECT workerFk INTO vCollectionWorker - FROM `collection` - WHERE id = vCollectionFk FOR UPDATE; - - IF vCollectionWorker IS NULL THEN - UPDATE `collection` - SET workerFk = vUserFk - WHERE id = vCollectionFk; - END IF; - - COMMIT; - END IF; - CALL itemShelvingSale_addByCollection(vCollectionFk); +BEGIN +/** + * Comprueba si existen colecciones libres que se ajustan + * al perfil del usuario y le asigna la más antigua. + * Añade un registro al semillero de colecciones. + * + * @param vUserFk Id de usuario + * @param vCollectionFk Id de colección + */ + DECLARE vHasTooMuchCollections BOOL; + DECLARE vDone BOOL DEFAULT FALSE; + DECLARE vCollectionWorker INT; + DECLARE vMaxNotAssignedCollectionLifeTime TIME; + + DECLARE vCollections CURSOR FOR + WITH collections AS ( + SELECT tc.collectionFk, + SUM(sv.volume) volume, + c.saleTotalCount, + c.itemPackingTypeFk, + c.trainFk, + c.warehouseFk, + c.wagons + FROM vn.ticketCollection tc + JOIN vn.collection c ON c.id = tc.collectionFk + JOIN vn.saleVolume sv ON sv.ticketFk = tc.ticketFk + WHERE c.workerFk IS NULL + AND sv.shipped >= util.VN_CURDATE() + GROUP BY tc.collectionFk + ) SELECT c.collectionFk + FROM collections c + JOIN vn.operator o + WHERE o.workerFk = vUserFk + AND (c.saleTotalCount <= o.linesLimit OR o.linesLimit IS NULL) + AND (c.itemPackingTypeFk = o.itemPackingTypeFk OR o.itemPackingTypeFk IS NULL) + AND o.numberOfWagons = c.wagons + AND o.trainFk = c.trainFk + AND o.warehouseFk = c.warehouseFk; + + DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE; + -- Si hay colecciones sin terminar, sale del proceso + + DECLARE EXIT HANDLER FOR SQLEXCEPTION + BEGIN + ROLLBACK; + RESIGNAL; + END; + + CALL collection_get(vUserFk); + + SELECT (pc.maxNotReadyCollections - COUNT(*)) <= 0, pc.maxNotAssignedCollectionLifeTime + INTO vHasTooMuchCollections, vMaxNotAssignedCollectionLifeTime + FROM productionConfig pc + LEFT JOIN tmp.collection ON TRUE; + + DROP TEMPORARY TABLE tmp.collection; + + IF vHasTooMuchCollections THEN + CALL util.throw('Hay colecciones pendientes'); + END IF; + + -- Se eliminan las colecciones sin asignar que estan obsoletas + + INSERT INTO ticketTracking(stateFk, ticketFk) + SELECT s.id, tc.ticketFk + FROM `collection` c + JOIN ticketCollection tc ON tc.collectionFk = c.id + JOIN `state` s ON s.code = 'PRINTED_AUTO' + WHERE c.workerFk IS NULL + AND TIMEDIFF(util.VN_NOW(), c.created) > vMaxNotAssignedCollectionLifeTime; + + DELETE FROM `collection` + WHERE workerFk IS NULL + AND TIMEDIFF(util.VN_NOW(), created) > vMaxNotAssignedCollectionLifeTime; + + -- Se añade registro al semillero + + INSERT INTO collectionHotbed(userFk) VALUES(vUserFk); + + -- Comprueba si hay colecciones disponibles que se ajustan a su configuracion + + OPEN vCollections; + l: LOOP + SET vDone = FALSE; + FETCH vCollections INTO vCollectionFk; + + IF vDone THEN + LEAVE l; + END IF; + + BEGIN + DECLARE EXIT HANDLER FOR SQLEXCEPTION + BEGIN + ROLLBACK; + SET vCollectionFk = NULL; + RESIGNAL; + END; + + START TRANSACTION; + + SELECT workerFk INTO vCollectionWorker + FROM `collection` + WHERE id = vCollectionFk FOR UPDATE; + + IF vCollectionWorker IS NULL THEN + UPDATE `collection` + SET workerFk = vUserFk + WHERE id = vCollectionFk; + + COMMIT; + LEAVE l; + END IF; + + ROLLBACK; + END; + END LOOP; + CLOSE vCollections; + + IF vCollectionFk IS NULL THEN + CALL collection_new(vUserFk, vCollectionFk); + + START TRANSACTION; + + SELECT workerFk INTO vCollectionWorker + FROM `collection` + WHERE id = vCollectionFk FOR UPDATE; + + IF vCollectionWorker IS NULL THEN + UPDATE `collection` + SET workerFk = vUserFk + WHERE id = vCollectionFk; + END IF; + + COMMIT; + END IF; + CALL itemShelvingSale_addByCollection(vCollectionFk); END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -51717,7 +51911,9 @@ BEGIN t.warehouseFk, w.id salesPersonFk, IFNULL(ob.description,'') observaciones, - cc.rgb + cc.rgb, + p.code parkingCode, + IF (ps.ticketFk, TRUE, FALSE) isAdvanced FROM vn.ticket t LEFT JOIN vn.ticketCollection tc ON t.id = tc.ticketFk LEFT JOIN vn.collection c2 ON c2.id = tc.collectionFk @@ -51729,7 +51925,10 @@ BEGIN LEFT JOIN vn.agencyMode am ON am.id = z.agencyModeFk LEFT JOIN vn.client c ON c.id = t.clientFk LEFT JOIN vn.worker w ON w.id = c.salesPersonFk - LEFT JOIN observation ob ON ob.ticketFk = t.id + LEFT JOIN observation ob ON ob.ticketFk = t.id + LEFT JOIN vn.ticketParking tp ON tp.ticketFk = t.id + LEFT JOIN vn.parking p ON tp.parkingFk = p.id + LEFT JOIN vn.packingSiteAdvanced ps ON ps.ticketFk = t.id WHERE t.id = vParamFk AND t.shipped >= vYesterday UNION @@ -51739,7 +51938,9 @@ BEGIN t.warehouseFk, w.id salesPersonFk, ob.description, - IF(NOT (vItemPackingTypeFk <=> 'V'), cc.rgb, NULL) `rgb` + IF(NOT (vItemPackingTypeFk <=> 'V'), cc.rgb, NULL) `rgb`, + p.code parkingCode, + IF (ps.ticketFk, TRUE, FALSE) isAdvanced FROM vn.ticket t JOIN vn.ticketCollection tc ON t.id = tc.ticketFk LEFT JOIN vn.collection c2 ON c2.id = tc.collectionFk @@ -51751,7 +51952,10 @@ BEGIN LEFT JOIN vn.agencyMode am ON am.id = z.agencyModeFk LEFT JOIN vn.client c ON c.id = t.clientFk LEFT JOIN vn.worker w ON w.id = c.salesPersonFk - LEFT JOIN observation ob ON ob.ticketFk = t.id + LEFT JOIN observation ob ON ob.ticketFk = t.id + LEFT JOIN vn.ticketParking tp ON tp.ticketFk = t.id + LEFT JOIN vn.parking p ON tp.parkingFk = p.id + LEFT JOIN vn.packingSiteAdvanced ps ON ps.ticketFk = t.id WHERE tc.collectionFk = vParamFk UNION SELECT sg.ticketFk, @@ -51760,7 +51964,9 @@ BEGIN t.warehouseFk, c.salesPersonFk, ob.description, - NULL `rgb` + NULL `rgb`, + p.code parkingCode, + IF (ps.ticketFk, TRUE, FALSE) isAdvanced FROM vn.sectorCollection sc JOIN vn.sectorCollectionSaleGroup ss ON ss.sectorCollectionFk = sc.id JOIN vn.saleGroup sg ON sg.id = ss.saleGroupFk @@ -51768,7 +51974,10 @@ BEGIN LEFT JOIN vn.zone z ON z.id = t.zoneFk LEFT JOIN vn.agencyMode am ON am.id = z.agencyModeFk LEFT JOIN observation ob ON ob.ticketFk = t.id - LEFT JOIN vn.client c ON c.id = t.clientFk + LEFT JOIN vn.client c ON c.id = t.clientFk + LEFT JOIN vn.ticketParking tp ON tp.ticketFk = t.id + LEFT JOIN vn.parking p ON tp.parkingFk = p.id + LEFT JOIN vn.packingSiteAdvanced ps ON ps.ticketFk = t.id WHERE sc.id = vParamFk AND t.shipped >= vYesterday GROUP BY ticketFk; @@ -54483,7 +54692,6 @@ BEGIN supplierFk, dated, isExcludedFromAvailable, - isRaid, commission, currencyFk, companyFk, @@ -54494,7 +54702,6 @@ BEGIN supplierFk, dated, isExcludedFromAvailable, - isRaid, commission, currencyFk, companyFk, @@ -54701,7 +54908,7 @@ CREATE DEFINER=`vn`@`localhost` PROCEDURE `entry_getTransfer`( BEGIN /** * Retorna los artículos trasladables a partir de una entrada. - * + * * @param vSelf Id de entrada */ DECLARE vDateShipped DATE; @@ -54862,7 +55069,7 @@ BEGIN LEFT JOIN tmp.buyUltimateFromInterval bufi ON bufi.itemFk = i.id LEFT JOIN buy b3 ON b3.id = bufi.buyFk WHERE ic.display - AND NOT e.isRaid + AND NOT tr.isRaid AND (ti.visible OR ti.available) ORDER BY i.typeFk, i.name, i.id, i.size, i.category, o.name; @@ -55255,12 +55462,17 @@ DELIMITER ; /*!50003 SET character_set_results = utf8mb4 */ ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; -CREATE DEFINER=`vn`@`localhost` PROCEDURE `entry_splitByShelving`(vShelvingFk VARCHAR(3), vFromEntryFk INT, vToEntryFk INT) +CREATE DEFINER=`vn`@`localhost` PROCEDURE `entry_splitByShelving`( + vShelvingCode VARCHAR(10), + vFromEntryFk INT, + vToEntryFk INT +) BEGIN /** - * Divide las compras entre dos entradas de acuerdo con lo ubicado en una matr�cula + * Divide las compras entre dos entradas de + * acuerdo con lo ubicado en una matricula. * - * @param vShelvingFk Identificador de vn.shelving + * @param vShelvingCode Código de vn.shelving * @param vFromEntryFk Entrada origen * @param vToEntryFk Entrada destino */ @@ -55270,7 +55482,7 @@ BEGIN DECLARE vDone BOOLEAN DEFAULT FALSE; DECLARE cur CURSOR FOR - SELECT bb.id buyFk, + SELECT bb.id buyFk, LEAST(bb.stickers, FLOOR(ish.visible / ish.packing)) ishStickers, bb.stickers buyStickers FROM itemShelving ish @@ -55279,7 +55491,7 @@ BEGIN WHERE b.entryFk = vFromEntryFk ORDER BY b.stickers DESC LIMIT 10000000000000000000) bb ON bb.itemFk = ish.itemFk - WHERE ish.shelvingFk = vShelvingFk COLLATE utf8_general_ci + WHERE ish.shelvingFk = vShelvingCode COLLATE utf8_general_ci AND NOT ish.isSplit GROUP BY ish.id; @@ -55363,9 +55575,10 @@ BEGIN UPDATE buy SET printedStickers = vIshStickers WHERE id = LAST_INSERT_ID(); END IF; - UPDATE itemShelving - SET isSplit = TRUE - WHERE shelvingFk = vShelvingFk COLLATE utf8_general_ci; + UPDATE itemShelving ish + JOIN shelving sh ON sh.id = ish.shelvingFk + SET ish.isSplit = TRUE + WHERE sh.code = vShelvingCode COLLATE utf8_general_ci; END LOOP; CLOSE cur; END ;; @@ -55480,7 +55693,7 @@ BEGIN FROM vn.entry e JOIN vn.travel t ON t.id = e.travelFk JOIN vn.warehouse w ON w.id = t.warehouseInFk - WHERE t.shipped >= util.VN_CURDATE() + WHERE t.landed >= util.VN_CURDATE() AND e.currencyFk = vCurrency AND NOT e.isBooked; @@ -55491,7 +55704,7 @@ BEGIN SET e.commission = vComission; SELECT `name` INTO vCurrencyName - FROM currency + FROM currency WHERE id = vCurrency; CALL entry_recalc(); @@ -55930,12 +56143,12 @@ CREATE DEFINER=`vn`@`localhost` PROCEDURE `expeditionScan_Put`( vExpeditionFk INT ) BEGIN - IF NOT (SELECT TRUE FROM expedition WHERE id = vExpeditionFk LIMIT 1) THEN - CALL util.throw('Expedition not exists'); + IF NOT EXISTS (SELECT id FROM expeditionPallet WHERE id = vPalletFk) THEN + CALL util.throw('Pallet not exists'); END IF; - IF NOT (SELECT TRUE FROM expeditionPallet WHERE id = vPalletFk LIMIT 1) THEN - CALL util.throw('Pallet not exists'); + IF NOT EXISTS (SELECT id FROM expedition WHERE id = vExpeditionFk) THEN + CALL util.throw('Expedition not exists'); END IF; REPLACE expeditionScan(expeditionFk, palletFk) @@ -56159,7 +56372,8 @@ BEGIN a.nickname, sub2.itemPackingTypeConcat, est.code, - es.isScanned + es2.isScanned, + es2.scanOrder FROM expedition e JOIN ticket t ON t.id = e.ticketFk JOIN ticketState ts ON ts.ticketFk = e.ticketFk @@ -56181,6 +56395,7 @@ BEGIN SELECT MAX(id) FROM expeditionState es WHERE expeditionFk = e.id) + LEFT JOIN expeditionState es2 ON es2.id = es.id WHERE t.routeFk = vRouteFk AND e.freightItemFk <> FALSE ORDER BY r.created, t.priority DESC; END ;; @@ -56261,6 +56476,112 @@ DELIMITER ; /*!50003 SET collation_connection = @saved_col_connection */ ; /*!50003 SET @saved_sql_mode = @@sql_mode */ ; /*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; +/*!50003 DROP PROCEDURE IF EXISTS `expedition_selfConsumptionPackaging` */; +/*!50003 SET @saved_cs_client = @@character_set_client */ ; +/*!50003 SET @saved_cs_results = @@character_set_results */ ; +/*!50003 SET @saved_col_connection = @@collation_connection */ ; +/*!50003 SET character_set_client = utf8mb4 */ ; +/*!50003 SET character_set_results = utf8mb4 */ ; +/*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; +DELIMITER ;; +CREATE DEFINER=`vn`@`localhost` PROCEDURE `expedition_selfConsumptionPackaging`( + vSelf INT, + vAction ENUM('add', 'remove') +) +proc:BEGIN +/** + * Maneja el consumo de cajas para autoconsumo, permitiendo + * añadir o quitar cajas utilizadas según la acción indicada. + * + * @param vSelf Id de expedición + */ + DECLARE vClientFk INT; + DECLARE vAddressFk INT; + DECLARE vItemFk INT; + DECLARE vItemName VARCHAR(50); + DECLARE vWarehouseFk INT; + DECLARE vCreated DATE; + DECLARE vTicketFk INT; + DECLARE vSaleFk INT; + DECLARE vQuantity INT; + + IF vAction NOT IN ('add', 'remove') THEN + CALL util.throw('Action not supported'); + END IF; + + SELECT pc.clientSelfConsumptionFk, + pc.addressSelfConsumptionFk, + i.id, + i.name, + t.warehouseFk, + e.created + INTO vClientFk, + vAddressFk, + vItemFk, + vItemName, + vWarehouseFk, + vCreated + FROM expedition e + LEFT JOIN packaging p ON p.id = e.packagingFk + LEFT JOIN item i ON i.id = p.itemFk + JOIN ticket t ON t.id = e.ticketFk + JOIN productionConfig pc + WHERE e.id = vSelf; + + IF vClientFk IS NULL OR vItemFk IS NULL THEN + LEAVE proc; + END IF; + + SET vCreated = DATE(vCreated); + + SELECT id INTO vTicketFk + FROM ticket + WHERE shipped BETWEEN vCreated AND util.dayEnd(vCreated) + AND clientFk = vClientFk + AND addressFk = vAddressFk + AND warehouseFk = vWarehouseFk; + + IF vTicketFk IS NULL AND vAction = 'add' THEN + INSERT INTO ticket(clientFk, warehouseFk, shipped, nickname, addressFk) + VALUES (vClientFk, vWarehouseFk, vCreated, 'CAJAS AUTOCONSUMO', vAddressFk); + + SET vTicketFk = LAST_INSERT_ID(); + END IF; + + SELECT id, quantity INTO vSaleFk, vQuantity + FROM sale + WHERE itemFk = vItemFk + AND ticketFk = vTicketFk + LIMIT 1; + + IF vAction = 'add' THEN + IF vSaleFk IS NOT NULL THEN + UPDATE sale + SET quantity = quantity + 1 + WHERE id = vSaleFk; + ELSE + INSERT INTO sale(itemFk, ticketFk, concept, quantity) + VALUES (vItemFk, vTicketFk, vItemName, 1); + END IF; + ELSE + IF vSaleFk IS NOT NULL THEN + IF vQuantity > 1 THEN + UPDATE sale + SET quantity = quantity - 1 + WHERE id = vSaleFk; + ELSE + DELETE FROM sale WHERE id = vSaleFk; + END IF; + END IF; + END IF; +END ;; +DELIMITER ; +/*!50003 SET sql_mode = @saved_sql_mode */ ; +/*!50003 SET character_set_client = @saved_cs_client */ ; +/*!50003 SET character_set_results = @saved_cs_results */ ; +/*!50003 SET collation_connection = @saved_col_connection */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; /*!50003 DROP PROCEDURE IF EXISTS `expedition_StateGet` */; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; @@ -56819,7 +57140,7 @@ BEGIN JOIN travel tr ON tr.id = e.travelFk WHERE tr.warehouseInFk = vWarehouseFk AND tr.landed BETWEEN vDateLastInventory AND vDateYesterday - AND NOT isRaid + AND NOT tr.isRaid GROUP BY b.itemFk; -- Transfers @@ -56832,7 +57153,7 @@ BEGIN JOIN travel tr ON tr.id = e.travelFk WHERE tr.warehouseOutFk = vWarehouseFk AND tr.shipped BETWEEN vDateLastInventory AND vDateYesterday - AND NOT isRaid + AND NOT tr.isRaid GROUP BY b.itemFk ) sub ON DUPLICATE KEY UPDATE quantity = IFNULL(quantity, 0) + sub.quantityOut; @@ -59198,7 +59519,11 @@ DELIMITER ; /*!50003 SET character_set_results = utf8mb4 */ ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; -CREATE DEFINER=`vn`@`localhost` PROCEDURE `itemPlacementSupplyAiming`(vShelvingFk VARCHAR(10), quantity INT, vItemFk INT) +CREATE DEFINER=`vn`@`localhost` PROCEDURE `itemPlacementSupplyAiming`( + vShelvingCode VARCHAR(10), + vQuantity INT, + vItemFk INT +) BEGIN SELECT ish.itemFk, @@ -59208,21 +59533,21 @@ BEGIN ish.itemShelvingFk, ish.shelving, ish.stock, - LEAST(ish.stock,quantity) as total, + LEAST(ish.stock,vQuantity) total, CONCAT( - CAST(FLOOR(LEAST(ish.stock,quantity) / ish.packing) AS DECIMAL(10,0)), + CAST(FLOOR(LEAST(ish.stock, vQuantity) / ish.packing) AS DECIMAL(10,0)), ' x ', ish.packing, IF ( - LEAST(ish.stock,quantity) MOD ish.packing, - CONCAT(' + ',CAST(LEAST(ish.stock,quantity) MOD ish.packing AS DECIMAL(10,0))), + LEAST(ish.stock, vQuantity) MOD ish.packing, + CONCAT(' + ',CAST(LEAST(ish.stock, vQuantity) MOD ish.packing AS DECIMAL(10,0))), '' ), ' = ', - LEAST(ish.stock,quantity) - ) as proposal - FROM vn.itemShelvingPlacementSupplyStock ish - WHERE ish.shelving = vShelvingFk COLLATE utf8_general_ci + LEAST(ish.stock, vQuantity) + ) proposal + FROM itemShelvingPlacementSupplyStock ish + WHERE ish.shelving = vShelvingCode COLLATE utf8_general_ci AND ish.itemFk = vItemFk; END ;; @@ -59264,7 +59589,9 @@ DELIMITER ; /*!50003 SET character_set_results = utf8mb4 */ ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; -CREATE DEFINER=`vn`@`localhost` PROCEDURE `itemPlacementSupplyGetOrder`(vSector INT ) +CREATE DEFINER=`vn`@`localhost` PROCEDURE `itemPlacementSupplyGetOrder`( + vSectorFk INT +) BEGIN DECLARE vId INT; @@ -59272,31 +59599,35 @@ BEGIN DECLARE vNextParkingFk INT; SELECT sh.parkingFk INTO vLastParkingFk - FROM vn.itemShelvingPlacementSupply isps - JOIN vn.itemShelving ish ON ish.id = isps.itemShelvingFk - JOIN vn.shelving sh ON sh.code = ish.shelvingFk + FROM itemShelvingPlacementSupply isps + JOIN itemShelving ish ON ish.id = isps.itemShelvingFk + JOIN shelving sh ON sh.id = ish.shelvingFk WHERE isps.userFk = getUser() ORDER BY isps.created DESC LIMIT 1; - SET vNextParkingFk = vn.itemShelvingPlacementSupply_ClosestGet(vLastParkingFk); + SET vNextParkingFk = itemShelvingPlacementSupply_ClosestGet(vLastParkingFk); SELECT ipsl.id INTO vId - FROM vn.itemPlacementSupplyList ipsl - JOIN vn.itemShelvingPlacementSupplyStock ispss ON ispss.itemFk = ipsl.itemFk + FROM itemPlacementSupplyList ipsl + JOIN itemShelvingPlacementSupplyStock ispss ON ispss.itemFk = ipsl.itemFk WHERE ipsl.saldo > 0 AND (ipsl.repoUserFk is NULL OR ipsl.repoUserFk = getUser()) - AND ipsl.sectorFk = vSector - ORDER BY ipsl.repoUserFk DESC, ipsl.priority DESC, (ispss.parkingFk = vNextParkingFk) DESC, ispss.parking DESC, ipsl.created + AND ipsl.sectorFk = vSectorFk + ORDER BY ipsl.repoUserFk DESC, + ipsl.priority DESC, + (ispss.parkingFk = vNextParkingFk) DESC, + ispss.parking DESC, + ipsl.created LIMIT 1; - UPDATE vn.itemPlacementSupply + UPDATE itemPlacementSupply SET repoUserFk = getUser() WHERE id = vId; - SELECT * FROM vn.itemPlacementSupplyList + SELECT * FROM itemPlacementSupplyList WHERE id = vId - AND sectorFk = vSector; + AND sectorFk = vSectorFk; END ;; DELIMITER ; @@ -59314,7 +59645,10 @@ DELIMITER ; /*!50003 SET character_set_results = utf8mb4 */ ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; -CREATE DEFINER=`vn`@`localhost` PROCEDURE `itemPlacementSupplyStockGetTargetList`(vItemFk INT,vSectorFk INT) +CREATE DEFINER=`vn`@`localhost` PROCEDURE `itemPlacementSupplyStockGetTargetList`( + vItemFk INT, + vSectorFk INT +) BEGIN /** * Devuelve la lista de ubicaciones para itemFk en ese sector. Se utiliza en la preparación previa. @@ -59328,11 +59662,11 @@ BEGIN SUM(ish.visible) stockTotal, ish.created, p.pickingOrder - FROM vn.itemShelving ish - JOIN vn.shelving sh ON sh.code = ish.shelvingFk - JOIN vn.parking p ON p.id = sh.parkingFk - JOIN vn.sector sc ON sc.id = p.sectorFk - JOIN vn.warehouse w ON w.id = sc.warehouseFk + FROM itemShelving ish + JOIN shelving sh ON sh.id = ish.shelvingFk + JOIN parking p ON p.id = sh.parkingFk + JOIN sector sc ON sc.id = p.sectorFk + JOIN warehouse w ON w.id = sc.warehouseFk WHERE ish.visible > 0 AND ish.itemFk = vItemFk GROUP BY ish.id @@ -59517,16 +59851,16 @@ DELIMITER ; /*!50003 SET character_set_results = utf8mb4 */ ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; -CREATE DEFINER=`vn`@`localhost` PROCEDURE `itemShelvingLog_get`(vShelvingFk VARCHAR(10) ) +CREATE DEFINER=`vn`@`localhost` PROCEDURE `itemShelvingLog_get`( + vShelvingCode VARCHAR(10) +) BEGIN - /** * Devuelve el log de los item en cada carro * - * @param vShelvingFk Matrícula del carro + * @param vShelvingCode Matrícula del carro * */ - SELECT isl.itemShelvingFk, isl.created, isl.accion, @@ -59546,9 +59880,10 @@ BEGIN FROM item JOIN itemShelvingLog isl ON item.id = isl.itemFk JOIN worker ON isl.workerFk = worker.id - WHERE shelvingFk = vShelvingFk OR isl.itemFk = vShelvingFk - ORDER BY isl.created DESC; - + JOIN shelving sh ON sh.id = isl.shelvingFk + WHERE sh.code = vShelvingCode COLLATE utf8mb3_unicode_ci + OR isl.itemFk = vShelvingCode -- ?? Respeto porque ya estaba + ORDER BY isl.created DESC; END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -59586,7 +59921,7 @@ BEGIN LEFT JOIN ( SELECT itemFk, sum(cast(visible / packing AS DECIMAL(10,0))) AS etiquetas FROM itemShelving ish - JOIN shelving sh ON sh.code = ish.shelvingFk + JOIN shelving sh ON sh.id = ish.shelvingFk LEFT JOIN parking pk ON pk.id = sh.parkingFk WHERE ish.created BETWEEN vFromTimed AND vToTimed GROUP BY itemFk @@ -60050,53 +60385,53 @@ DELIMITER ; /*!50003 SET character_set_results = utf8mb4 */ ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; -CREATE DEFINER=`vn`@`localhost` PROCEDURE `itemShelvingSale_addByCollection`( - vCollectionFk INT(11) +CREATE DEFINER=`vn`@`localhost` PROCEDURE `itemShelvingSale_addByCollection`( + vCollectionFk INT(11) ) -BEGIN -/** - * Reserva cantidades con ubicaciones para el contenido de una colección - * - * @param vCollectionFk Identificador de collection - */ - DECLARE vDone BOOL DEFAULT FALSE; - DECLARE vSaleFk INT; - DECLARE vSales CURSOR FOR - WITH sales AS ( - SELECT s.id saleFk, s.quantity, SUM(IFNULL(iss.quantity, 0)) quantityReserved - FROM vn.ticketCollection tc - JOIN vn.sale s ON s.ticketFk = tc.ticketFk - LEFT JOIN vn.itemShelvingSale iss ON iss.saleFk = s.id - WHERE tc.collectionFk = vCollectionFk - GROUP BY s.id - HAVING quantity <> quantityReserved - ), trackedSales AS ( - SELECT sa.saleFk - FROM sales sa - JOIN vn.saleTracking st ON st.saleFk = sa.saleFk - JOIN vn.`state` s ON s.id = st.stateFk - WHERE st.isChecked - AND s.`code` IN ('PREVIOUS_PREPARATION', 'OK PREVIOUS', 'OK STOWAWAY') - GROUP BY sa.saleFk - ) SELECT s.saleFk - FROM sales s - LEFT JOIN trackedSales ts ON ts.saleFk = s.saleFk - WHERE ts.saleFk IS NULL; - - DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE; - - OPEN vSales; - l: LOOP - SET vDone = FALSE; - FETCH vSales INTO vSaleFk; - - IF vDone THEN - LEAVE l; - END IF; - - CALL itemShelvingSale_addBySale(vSaleFk, NULL); - END LOOP; - CLOSE vSales; +BEGIN +/** + * Reserva cantidades con ubicaciones para el contenido de una colección + * + * @param vCollectionFk Identificador de collection + */ + DECLARE vDone BOOL DEFAULT FALSE; + DECLARE vSaleFk INT; + DECLARE vSales CURSOR FOR + WITH sales AS ( + SELECT s.id saleFk, s.quantity, SUM(IFNULL(iss.quantity, 0)) quantityReserved + FROM vn.ticketCollection tc + JOIN vn.sale s ON s.ticketFk = tc.ticketFk + LEFT JOIN vn.itemShelvingSale iss ON iss.saleFk = s.id + WHERE tc.collectionFk = vCollectionFk + GROUP BY s.id + HAVING quantity <> quantityReserved + ), trackedSales AS ( + SELECT sa.saleFk + FROM sales sa + JOIN vn.saleTracking st ON st.saleFk = sa.saleFk + JOIN vn.`state` s ON s.id = st.stateFk + WHERE st.isChecked + AND s.`code` IN ('PREVIOUS_PREPARATION', 'OK PREVIOUS', 'OK STOWAWAY') + GROUP BY sa.saleFk + ) SELECT s.saleFk + FROM sales s + LEFT JOIN trackedSales ts ON ts.saleFk = s.saleFk + WHERE ts.saleFk IS NULL; + + DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE; + + OPEN vSales; + l: LOOP + SET vDone = FALSE; + FETCH vSales INTO vSaleFk; + + IF vDone THEN + LEAVE l; + END IF; + + CALL itemShelvingSale_addBySale(vSaleFk, NULL); + END LOOP; + CLOSE vSales; END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -60141,7 +60476,7 @@ proc: BEGIN ish.available FROM sale s JOIN itemShelving ish ON ish.itemFk = s.itemFk - JOIN shelving sh ON sh.code = ish.shelvingFk + JOIN shelving sh ON sh.id = ish.shelvingFk JOIN parking p ON p.id = sh.parkingFk JOIN sector sc ON sc.id = p.sectorFk JOIN productionConfig pc @@ -60175,7 +60510,7 @@ proc: BEGIN FROM sale s LEFT JOIN itemShelvingSale iss ON iss.saleFk = s.id LEFT JOIN itemShelving ish ON ish.id = iss.itemShelvingFk - LEFT JOIN shelving sh ON sh.code = ish.shelvingFk + LEFT JOIN shelving sh ON sh.id = ish.shelvingFk LEFT JOIN parking p ON p.id = sh.parkingFk WHERE s.id = vSaleFk; @@ -60437,56 +60772,56 @@ DELIMITER ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; CREATE DEFINER=`vn`@`localhost` PROCEDURE `itemShelvingSale_doReserve`() -proc: BEGIN -/** - * Genera reservas de la tabla vn.itemShelvingSaleReserve - */ - DECLARE vDone BOOL; - DECLARE vSaleFk INT; - DECLARE vSectorFk INT; - - DECLARE vSales CURSOR FOR - SELECT DISTINCT saleFk, sectorFk FROM tSale; - - DECLARE CONTINUE HANDLER FOR NOT FOUND - SET vDone = TRUE; - - DECLARE CONTINUE HANDLER FOR SQLEXCEPTION - BEGIN - DO RELEASE_LOCK('vn.itemShelvingSale_doReserve'); - ROLLBACK; - RESIGNAL; - END; - - IF !GET_LOCK('vn.itemShelvingSale_doReserve', 0) THEN - LEAVE proc; - END IF; - - CREATE OR REPLACE TEMPORARY TABLE tSale - ENGINE = MEMORY - SELECT id, saleFk, sectorFk FROM itemShelvingSaleReserve; - - OPEN vSales; - - myLoop: LOOP - SET vDone = FALSE; - FETCH vSales INTO vSaleFk, vSectorFk; - - IF vDone THEN - LEAVE myLoop; - END IF; - - CALL itemShelvingSale_addBySale (vSaleFk, vSectorFk); - END LOOP; - - CLOSE vSales; - - DELETE iss FROM itemShelvingSaleReserve iss - JOIN tSale s ON s.id = iss.id AND s.sectorFk = iss.sectorFk; - - DROP TEMPORARY TABLE tSale; - - DO RELEASE_LOCK('vn.itemShelvingSale_doReserve'); +proc: BEGIN +/** + * Genera reservas de la tabla vn.itemShelvingSaleReserve + */ + DECLARE vDone BOOL; + DECLARE vSaleFk INT; + DECLARE vSectorFk INT; + + DECLARE vSales CURSOR FOR + SELECT DISTINCT saleFk, sectorFk FROM tSale; + + DECLARE CONTINUE HANDLER FOR NOT FOUND + SET vDone = TRUE; + + DECLARE CONTINUE HANDLER FOR SQLEXCEPTION + BEGIN + DO RELEASE_LOCK('vn.itemShelvingSale_doReserve'); + ROLLBACK; + RESIGNAL; + END; + + IF !GET_LOCK('vn.itemShelvingSale_doReserve', 0) THEN + LEAVE proc; + END IF; + + CREATE OR REPLACE TEMPORARY TABLE tSale + ENGINE = MEMORY + SELECT id, saleFk, sectorFk FROM itemShelvingSaleReserve; + + OPEN vSales; + + myLoop: LOOP + SET vDone = FALSE; + FETCH vSales INTO vSaleFk, vSectorFk; + + IF vDone THEN + LEAVE myLoop; + END IF; + + CALL itemShelvingSale_addBySale (vSaleFk, vSectorFk); + END LOOP; + + CLOSE vSales; + + DELETE iss FROM itemShelvingSaleReserve iss + JOIN tSale s ON s.id = iss.id AND s.sectorFk = iss.sectorFk; + + DROP TEMPORARY TABLE tSale; + + DO RELEASE_LOCK('vn.itemShelvingSale_doReserve'); END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -60571,37 +60906,37 @@ DELIMITER ; /*!50003 SET character_set_results = utf8mb4 */ ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; -CREATE DEFINER=`vn`@`localhost` PROCEDURE `itemShelvingSale_setPicked`( - vSaleGroupFk INT(10) +CREATE DEFINER=`vn`@`localhost` PROCEDURE `itemShelvingSale_setPicked`( + vSaleGroupFk INT(10) ) -BEGIN -/** - * Gestiona la reserva de un vn.saleGroup actualizando vn.itemShelvingSale.isPicked - * y cambiando el estado de la vn.sale - * - * @param vSaleGroupFk Id saleGroupFk - */ - DECLARE EXIT HANDLER FOR SQLEXCEPTION - BEGIN - ROLLBACK; - RESIGNAL; - END; - - IF NOT (SELECT COUNT(*) FROM saleGroup WHERE id = vSaleGroupFk) THEN - CALL util.throw('Sale group not exists'); - END IF; - - START TRANSACTION; - - UPDATE itemShelvingSale iss - JOIN sale s ON s.id = iss.saleFk - JOIN saleGroupDetail sg ON sg.saleFk = s.id - SET iss.isPicked = TRUE - WHERE sg.saleGroupFk = vSaleGroupFk; - - CALL saleTracking_addPreparedSaleGroup(vSaleGroupFk); - - COMMIT; +BEGIN +/** + * Gestiona la reserva de un vn.saleGroup actualizando vn.itemShelvingSale.isPicked + * y cambiando el estado de la vn.sale + * + * @param vSaleGroupFk Id saleGroupFk + */ + DECLARE EXIT HANDLER FOR SQLEXCEPTION + BEGIN + ROLLBACK; + RESIGNAL; + END; + + IF NOT (SELECT COUNT(*) FROM saleGroup WHERE id = vSaleGroupFk) THEN + CALL util.throw('Sale group not exists'); + END IF; + + START TRANSACTION; + + UPDATE itemShelvingSale iss + JOIN sale s ON s.id = iss.saleFk + JOIN saleGroupDetail sg ON sg.saleFk = s.id + SET iss.isPicked = TRUE + WHERE sg.saleGroupFk = vSaleGroupFk; + + CALL saleTracking_addPreparedSaleGroup(vSaleGroupFk); + + COMMIT; END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -60618,114 +60953,124 @@ DELIMITER ; /*!50003 SET character_set_results = utf8mb4 */ ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; -CREATE DEFINER=`vn`@`localhost` PROCEDURE `itemShelvingSale_setQuantity`( - vItemShelvingSaleFk INT(10), - vQuantity DECIMAL(10,0), - vIsItemShelvingSaleEmpty BOOLEAN, - vSectorFk INT +CREATE DEFINER=`vn`@`localhost` PROCEDURE `itemShelvingSale_setQuantity`( + vItemShelvingSaleFk INT(10), + vQuantity DECIMAL(10,0), + vIsItemShelvingSaleEmpty BOOLEAN, + vSectorFk INT, + vShelvingFk VARCHAR(10) ) -BEGIN -/** - * Gestiona la reserva de un itemShelvingFk, actualizando isPicked y quantity - * en itemShelvingSale y sale.isPicked en caso necesario. - * Si la reserva de la ubicación es fallida, se regulariza la situación - * - * @param vItemShelvingSaleFk Id itemShelvingSaleFK - * @param vQuantity Cantidad real que se ha cogido de la ubicación - * @param vIsItemShelvingSaleEmpty determina si la ubicación itemShelvingSale se ha - * quedado vacio tras el movimiento - * @param vSectorFk Id del sector - */ - DECLARE vSaleFk INT; - DECLARE vItemShelvingFk INT; - DECLARE vReservedQuantity INT; - DECLARE vRemainingQuantity INT; - DECLARE vItemFk INT; - DECLARE vTotalQuantity INT; - DECLARE vStateCode VARCHAR(45); - - DECLARE EXIT HANDLER FOR SQLEXCEPTION - BEGIN - ROLLBACK; - RESIGNAL; - END; - - IF vQuantity > vReservedQuantity - OR (vQuantity < vReservedQuantity AND NOT vIsItemShelvingSaleEmpty) - OR (vQuantity = vReservedQuantity AND vIsItemShelvingSaleEmpty) THEN - CALL util.throw('The quantity cannot be different from the reserved'); - END IF; - - IF (SELECT isPicked FROM itemShelvingSale WHERE id = vItemShelvingSaleFk) THEN - CALL util.throw('Reservation completed'); - END IF; - - SELECT s.itemFk, - iss.saleFk, - iss.itemShelvingFk, - SUM(IFNULL(iss.quantity,0)), - IF(sgd.id, 'PREVIOUS_PREPARATION', 'PREPARED') - INTO vItemFk, - vSaleFk, - vItemShelvingFk, - vReservedQuantity, - vStateCode - FROM itemShelvingSale iss - JOIN sale s ON s.id = iss.saleFk - LEFT JOIN vn.saleGroupDetail sgd ON sgd.saleFk = iss.saleFk - WHERE iss.id = vItemShelvingSaleFk - AND NOT iss.isPicked; - - IF vQuantity > vReservedQuantity - OR (vQuantity < vReservedQuantity AND NOT vIsItemShelvingSaleEmpty) - OR (vQuantity = vReservedQuantity AND vIsItemShelvingSaleEmpty) THEN - CALL util.throw('The quantity cannot be different from the reserved'); - END IF; - - START TRANSACTION; - - UPDATE itemShelvingSale - SET isPicked = TRUE, - quantity = vQuantity - WHERE id = vItemShelvingSaleFk; - - SELECT id INTO vItemShelvingFk - FROM itemShelving - WHERE id = vItemShelvingFk - FOR UPDATE; - - UPDATE itemShelving - SET visible = GREATEST(0, visible - vQuantity) - WHERE id = vItemShelvingFk; - - SELECT SUM(IF(isPicked OR id = vItemShelvingSaleFk, 0, quantity)), SUM(quantity) - INTO vRemainingQuantity, vTotalQuantity - FROM itemShelvingSale - WHERE saleFk = vSaleFk; - - IF vRemainingQuantity = 0 AND NOT vIsItemShelvingSaleEmpty THEN - CALL saleTracking_new( - vSaleFk, - TRUE, - vTotalQuantity, - `account`.`myUser_getId`(), - NULL, - vStateCode, - TRUE); - - UPDATE sale s - SET s.quantity = vTotalQuantity, - isPicked = TRUE - WHERE s.id = vSaleFk; - END IF; - - COMMIT; - - IF vIsItemShelvingSaleEmpty AND vQuantity <> vReservedQuantity THEN - INSERT INTO itemShelvingSaleReserve (saleFk, sectorFk) - SELECT vSaleFk, vSectorFk; - CALL itemShelvingSale_reallocate(vItemShelvingFk, vItemFk, vSectorFk); - END IF; +BEGIN +/** + * Gestiona la reserva de un itemShelvingFk, actualizando isPicked y quantity + * en itemShelvingSale y sale.isPicked en caso necesario. + * Si la reserva de la ubicación es fallida, se regulariza la situación + * + * @param vItemShelvingSaleFk Id itemShelvingSaleFK + * @param vQuantity Cantidad real que se ha cogido de la ubicación + * @param vIsItemShelvingSaleEmpty determina si la ubicación itemShelvingSale se ha + * quedado vacio tras el movimiento + * @param vSectorFk Id del sector + */ + DECLARE vSaleFk INT; + DECLARE vItemShelvingFk INT; + DECLARE vReservedQuantity INT; + DECLARE vRemainingQuantity INT; + DECLARE vItemFk INT; + DECLARE vTotalQuantity INT; + DECLARE vStateCode VARCHAR(45); + DECLARE vCurrentShelvingFk VARCHAR(10); + + DECLARE EXIT HANDLER FOR SQLEXCEPTION + BEGIN + ROLLBACK; + RESIGNAL; + END; + + IF vQuantity > vReservedQuantity + OR (vQuantity < vReservedQuantity AND NOT vIsItemShelvingSaleEmpty) + OR (vQuantity = vReservedQuantity AND vIsItemShelvingSaleEmpty) THEN + CALL util.throw('The quantity cannot be different from the reserved'); + END IF; + + IF (SELECT isPicked FROM itemShelvingSale WHERE id = vItemShelvingSaleFk) THEN + CALL util.throw('Reservation completed'); + END IF; + + SELECT s.itemFk, + iss.saleFk, + iss.itemShelvingFk, + SUM(IFNULL(iss.quantity,0)), + IF(sgd.id, 'PREVIOUS_PREPARATION', 'PREPARED'), + sh.code + INTO vItemFk, + vSaleFk, + vItemShelvingFk, + vReservedQuantity, + vStateCode, + vCurrentShelvingFk + FROM itemShelvingSale iss + JOIN sale s ON s.id = iss.saleFk + JOIN itemShelving ish ON ish.id = iss.itemShelvingFk + LEFT JOIN saleGroupDetail sgd ON sgd.saleFk = iss.saleFk + LEFT JOIN shelving sh ON sh.id = ish.shelvingFk + WHERE iss.id = vItemShelvingSaleFk + AND NOT iss.isPicked; + + IF NOT (vCurrentShelvingFk <=> vShelvingFk) THEN + CALL util.throw('The shelving can not be different from the shelving reserved'); + END IF; + + IF vQuantity > vReservedQuantity + OR (vQuantity < vReservedQuantity AND NOT vIsItemShelvingSaleEmpty) + OR (vQuantity = vReservedQuantity AND vIsItemShelvingSaleEmpty) THEN + CALL util.throw('The quantity cannot be different from the reserved'); + END IF; + + START TRANSACTION; + + UPDATE itemShelvingSale + SET isPicked = TRUE, + quantity = vQuantity + WHERE id = vItemShelvingSaleFk; + + SELECT id INTO vItemShelvingFk + FROM itemShelving + WHERE id = vItemShelvingFk + FOR UPDATE; + + UPDATE itemShelving + SET visible = GREATEST(0, visible - vQuantity) + WHERE id = vItemShelvingFk; + + SELECT SUM(IF(isPicked OR id = vItemShelvingSaleFk, 0, quantity)), SUM(quantity) + INTO vRemainingQuantity, vTotalQuantity + FROM itemShelvingSale + WHERE saleFk = vSaleFk; + + IF vRemainingQuantity = 0 AND NOT vIsItemShelvingSaleEmpty THEN + CALL saleTracking_new( + vSaleFk, + TRUE, + vTotalQuantity, + `account`.`myUser_getId`(), + NULL, + vStateCode, + TRUE); + + UPDATE sale s + SET s.quantity = vTotalQuantity, + isPicked = TRUE + WHERE s.id = vSaleFk; + END IF; + + COMMIT; + + IF vIsItemShelvingSaleEmpty AND vQuantity <> vReservedQuantity THEN + INSERT INTO itemShelvingSaleReserve (saleFk, sectorFk) + SELECT vSaleFk, vSectorFk; + CALL itemShelvingSale_reallocate(vItemShelvingFk, vItemFk, vSectorFk); + END IF; END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -60742,63 +61087,63 @@ DELIMITER ; /*!50003 SET character_set_results = utf8mb4 */ ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; -CREATE DEFINER=`vn`@`localhost` PROCEDURE `itemShelvingSale_unpicked`( - vSelf INT(11) +CREATE DEFINER=`vn`@`localhost` PROCEDURE `itemShelvingSale_unpicked`( + vSelf INT(11) ) -BEGIN -/** - * Desmarca una línea que ya estaba sacada, devolviendo la cantidad al itemShelving - * - * @param vSelf Identificador del itemShelvingSale - */ - DECLARE vSaleFk INT; - DECLARE vReservedQuantity INT; - DECLARE vIsSaleGroup BOOL; - DECLARE EXIT HANDLER FOR SQLEXCEPTION - BEGIN - ROLLBACK; - RESIGNAL; - END; - - IF (SELECT NOT isPicked FROM itemShelvingSale WHERE id = vSelf) THEN - CALL util.throw('Reserva no completada'); - END IF; - - SELECT ish.saleFk, ish.quantity, IF(sg.id, TRUE, FALSE) - INTO vSaleFk, vReservedQuantity, vIsSaleGroup - FROM itemShelvingSale ish - LEFT JOIN saleGroupDetail sg ON sg.saleFk = ish.saleFk - WHERE ish.id = vSelf; - - /*IF vIsSaleGroup THEN - CALL util.throw('Can not unpicked a sale group'); - END IF;*/ - - START TRANSACTION; - - UPDATE itemShelvingSale - SET isPicked = FALSE - WHERE id = vSelf; - - UPDATE sale s - JOIN itemShelvingSale ish ON ish.saleFk = s.id - SET s.isPicked = FALSE - WHERE ish.id = vSelf; - - UPDATE itemShelvingSale iss - JOIN itemShelving ish ON ish.id = iss.itemShelvingFk - SET ish.visible = ish.visible + iss.quantity - WHERE iss.id = vSelf; - - CALL saleTracking_new( - vSaleFk, - FALSE, - vReservedQuantity, - `account`.`myUser_getId`(), - NULL, - 'ON_PREPARATION', - TRUE); - COMMIT; +BEGIN +/** + * Desmarca una línea que ya estaba sacada, devolviendo la cantidad al itemShelving + * + * @param vSelf Identificador del itemShelvingSale + */ + DECLARE vSaleFk INT; + DECLARE vReservedQuantity INT; + DECLARE vIsSaleGroup BOOL; + DECLARE EXIT HANDLER FOR SQLEXCEPTION + BEGIN + ROLLBACK; + RESIGNAL; + END; + + IF (SELECT NOT isPicked FROM itemShelvingSale WHERE id = vSelf) THEN + CALL util.throw('Reserva no completada'); + END IF; + + SELECT ish.saleFk, ish.quantity, IF(sg.id, TRUE, FALSE) + INTO vSaleFk, vReservedQuantity, vIsSaleGroup + FROM itemShelvingSale ish + LEFT JOIN saleGroupDetail sg ON sg.saleFk = ish.saleFk + WHERE ish.id = vSelf; + + /*IF vIsSaleGroup THEN + CALL util.throw('Can not unpicked a sale group'); + END IF;*/ + + START TRANSACTION; + + UPDATE itemShelvingSale + SET isPicked = FALSE + WHERE id = vSelf; + + UPDATE sale s + JOIN itemShelvingSale ish ON ish.saleFk = s.id + SET s.isPicked = FALSE + WHERE ish.id = vSelf; + + UPDATE itemShelvingSale iss + JOIN itemShelving ish ON ish.id = iss.itemShelvingFk + SET ish.visible = ish.visible + iss.quantity + WHERE iss.id = vSelf; + + CALL saleTracking_new( + vSaleFk, + FALSE, + vReservedQuantity, + `account`.`myUser_getId`(), + NULL, + 'ON_PREPARATION', + TRUE); + COMMIT; END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -60816,7 +61161,7 @@ DELIMITER ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; CREATE DEFINER=`vn`@`localhost` PROCEDURE `itemShelving_add`( - vShelvingFk VARCHAR(8), + vShelvingCode VARCHAR(10), vBarcode VARCHAR(22), vQuantity INT, vPackagingFk VARCHAR(10), @@ -60828,7 +61173,7 @@ BEGIN /** * Añade registro o lo actualiza si ya existe. * - * @param vShelvingFk matrícula del carro + * @param vShelvingCode matrícula del carro * @param vBarcode el id del registro * @param vQuantity indica la cantidad del producto * @param vPackagingFk el packaging del producto en itemShelving, NULL para coger el de la ultima compra @@ -60839,10 +61184,15 @@ BEGIN **/ DECLARE vItemFk INT; DECLARE vBuyFk INT; + DECLARE vShelvingFk INT; SELECT id INTO vBuyFk FROM buy WHERE id = vBarcode; + SELECT id INTO vShelvingFk + FROM shelving + WHERE code COLLATE utf8_unicode_ci = vShelvingCode; + SELECT barcodeToItem(vBarcode) INTO vItemFk; IF vBuyFk IS NULL THEN @@ -60856,7 +61206,7 @@ BEGIN END IF; IF (SELECT COUNT(*) FROM itemShelving - WHERE shelvingFk COLLATE utf8_unicode_ci = vShelvingFk + WHERE shelvingFk = vShelvingFk AND itemFk = vItemFk AND packing = vPacking AND buyFk = vBuyFk) THEN @@ -60864,7 +61214,9 @@ BEGIN UPDATE itemShelving SET visible = visible + vQuantity, available = available + vQuantity - WHERE shelvingFk COLLATE utf8_unicode_ci = vShelvingFk AND itemFk = vItemFk AND packing = vPacking; + WHERE shelvingFk = vShelvingFk + AND itemFk = vItemFk + AND packing = vPacking; ELSE @@ -60902,31 +61254,40 @@ DELIMITER ; /*!50003 SET character_set_results = utf8mb4 */ ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; -CREATE DEFINER=`vn`@`localhost` PROCEDURE `itemShelving_addByClaim`(vClaimFk INT, vShelvingFk VARCHAR(3)) +CREATE DEFINER=`vn`@`localhost` PROCEDURE `itemShelving_addByClaim`( + vClaimFk INT, + vShelvingCode VARCHAR(10) +) BEGIN /** * Insert items of claim into itemShelving. * * @param vClaimFk The claim - * @param vShelvingFk The shelving + * @param vShelvingCode The shelving code * @table tmp.buyUltimate */ DECLARE vWarehouseFk INT; + DECLARE vShelvingFk INT; SELECT t.warehouseFk INTO vWarehouseFk FROM claim c JOIN ticket t ON t.id = c.ticketFk WHERE c.id = vClaimFk; + SELECT id INTO vShelvingFk + FROM shelving + WHERE code COLLATE utf8_unicode_ci = vShelvingCode; + CALL buy_getUltimate(NULL, vWarehouseFk, util.VN_CURDATE()); INSERT INTO itemShelving (itemFk, shelvingFk, packing, `grouping`, visible) - SELECT s.itemFk, vShelvingFk, b.packing, b.`grouping`, cb.quantity AS visible + SELECT s.itemFk, vShelvingFk, b.packing, b.`grouping`, cb.quantity visible FROM claim c JOIN claimBeginning cb ON c.id = cb.claimFk JOIN sale s ON s.id = cb.saleFk JOIN ticket t ON t.id = s.ticketFk - JOIN tmp.buyUltimate bu ON bu.itemFk = s.itemFk AND bu.warehouseFk = t.warehouseFk + JOIN tmp.buyUltimate bu ON bu.itemFk = s.itemFk + AND bu.warehouseFk = t.warehouseFk JOIN buy b ON b.id = bu.buyFk WHERE c.id = vClaimFk; END ;; @@ -60946,7 +61307,7 @@ DELIMITER ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; CREATE DEFINER=`vn`@`localhost` PROCEDURE `itemShelving_addList`( - vShelvingFk VARCHAR(3), + vShelvingCode VARCHAR(10), vList TEXT, vIsChecking BOOL, vWarehouseFk INT @@ -60959,7 +61320,7 @@ BEGIN * Cuando es TRUE sólo inserta los elementos de la colección que no están ya en * ese shelving, actualizando los valores del campo itemShelving.isChecked * - * @param vShelvingFk Identificador de shelving + * @param vShelvingCode Código de shelving * @param vList JSON array con esta estructura: '[value1, value2, ...]' * @param vIsChecking Define si hay que añadir o comprobar los items * @param vWarehouseFk Identificador de warehouse @@ -60970,6 +61331,11 @@ BEGIN DECLARE vPath VARCHAR(6); DECLARE vItemFk INT; DECLARE vIsChecked BOOL; + DECLARE vShelvingFk INT; + + SELECT id INTO vShelvingFk + FROM shelving + WHERE code COLLATE utf8_unicode_ci = vShelvingCode; WHILE vCounter < vListLength DO SET vPath = CONCAT('$[', vCounter, ']'); @@ -60980,17 +61346,17 @@ BEGIN SELECT IF(COUNT(*), TRUE, FALSE) INTO vIsChecked FROM itemShelving - WHERE shelvingFk COLLATE utf8_unicode_ci = vShelvingFk + WHERE shelvingFk = vShelvingFk AND itemFk = vItemFk; END IF; IF NOT vIsChecking OR NOT vIsChecked THEN - CALL itemShelving_add(vShelvingFk, vBarcode, 1, NULL, NULL, NULL, vWarehouseFk); + CALL itemShelving_add(vShelvingCode, vBarcode, 1, NULL, NULL, NULL, vWarehouseFk); END IF; UPDATE itemShelving SET isChecked = vIsChecked - WHERE shelvingFk COLLATE utf8_unicode_ci = vShelvingFk + WHERE shelvingFk = vShelvingFk AND itemFk = vItemFk AND isChecked IS NULL; @@ -61111,17 +61477,20 @@ DELIMITER ; /*!50003 SET character_set_results = utf8mb4 */ ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; -CREATE DEFINER=`vn`@`localhost` PROCEDURE `itemShelving_get`(IN vSelf VARCHAR(8)) +CREATE DEFINER=`vn`@`localhost` PROCEDURE `itemShelving_get`( + vShelvingCode VARCHAR(10) +) BEGIN /** -* Lista artículos de itemshelving +* Lista artículos de itemShelving. * -* @param vSelf matrícula del carro +* @param vShelvingCode Matrícula del carro **/ SELECT ish.itemFk item, - IFNULL(i.longName, CONCAT(i.name, ' ', i.size)) description, + i.name, + i.longName, + i.size, ish.visible, - CEIL(ish.visible/ish.packing) stickers, ish.packing, ish.grouping, p.code, @@ -61129,13 +61498,15 @@ BEGIN s.priority, ish.isChecked, ic.url, - ish.available + ish.available, + ish.buyFk, + ish.shelvingFk FROM itemShelving ish JOIN item i ON i.id = ish.itemFk - JOIN shelving s ON vSelf = s.code COLLATE utf8_unicode_ci - LEFT JOIN parking p ON s.parkingFk = p.id + JOIN shelving s ON s.id = ish.shelvingFk + LEFT JOIN parking p ON p.id = s.parkingFk JOIN hedera.imageConfig ic - WHERE ish.shelvingFk COLLATE utf8_unicode_ci = vSelf; + WHERE s.code COLLATE utf8_unicode_ci = vShelvingCode; END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -61152,23 +61523,33 @@ DELIMITER ; /*!50003 SET character_set_results = utf8mb4 */ ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; -CREATE DEFINER=`vn`@`localhost` PROCEDURE `itemShelving_getAlternatives`(vShelvingFk VARCHAR(10)) +CREATE DEFINER=`vn`@`localhost` PROCEDURE `itemShelving_getAlternatives`( + vShelvingCode VARCHAR(10) +) BEGIN /** - * Devuelve un listado de posibles ubicaciones alternativas a ubicar los item de la matricula - * del carro que se le ha pasado. + * Devuelve un listado de posibles ubicaciones alternativas a ubicar + * los item de la matricula del carro que se le ha pasado. * - * @param vShelvingFk matricula del carro + * @param vShelvingCode Matricula del carro */ - SELECT is2.id,is2.shelvingFk , p.code, is2.itemFk , is2.visible, p.pickingOrder + DECLARE vShelvingFk INT; + + SELECT id INTO vShelvingFk + FROM shelving + WHERE code COLLATE utf8_unicode_ci = vShelvingCode; + + SELECT is2.id,is2.shelvingFk, p.code, is2.itemFk , is2.visible, p.pickingOrder FROM itemShelving is2 - JOIN shelving sh ON sh.code = is2.shelvingFk + JOIN shelving sh ON sh.id = is2.shelvingFk JOIN parking p ON p.id = sh.parkingFk JOIN sector s ON s.id = p.sectorFk - LEFT JOIN operator o ON o.sectorFk = s.id AND o.workerFk = account.myUser_getId() + LEFT JOIN operator o ON o.sectorFk = s.id + AND o.workerFk = account.myUser_getId() JOIN warehouse wh ON wh.id = s.warehouseFk - JOIN itemShelving is3 ON is3.itemFk = is2.itemFk AND is3.shelvingFk = vShelvingFk COLLATE utf8_unicode_ci - WHERE is2.shelvingFk <> vShelvingFk COLLATE utf8_unicode_ci + JOIN itemShelving is3 ON is3.itemFk = is2.itemFk + AND is3.shelvingFk = vShelvingFk + WHERE is2.shelvingFk <> vShelvingFk GROUP BY is2.id ORDER BY p.pickingOrder DESC; END ;; @@ -61204,7 +61585,7 @@ BEGIN ish.itemFk itemFk, sh.priority FROM vn.itemShelving ish - JOIN vn.shelving sh ON sh.`code` = ish.shelvingFk + JOIN vn.shelving sh ON sh.id = ish.shelvingFk JOIN vn.parking pk ON pk.id = sh.parkingFk WHERE ish.itemFk = vItemFk ORDER BY sh.priority DESC, created ASC; @@ -61226,14 +61607,14 @@ DELIMITER ; DELIMITER ;; CREATE DEFINER=`vn`@`localhost` PROCEDURE `itemShelving_getItemDetails`( vBarcodeItem INT, - vShelvingFK VARCHAR(10) + vShelvingCode VARCHAR(10) ) BEGIN /** * Obtiene el precio y visible de un item * * @param vBarcodeItem barcode de artículo - * @param vShelvingFK Ubicación actual del artículo + * @param vShelvingCode Ubicación actual del artículo */ DECLARE vIsItem BOOL; DECLARE vBuyFk INT; @@ -61263,19 +61644,20 @@ BEGIN WITH visible AS( SELECT itemFk, IFNULL(buyingValue, 0) + - IFNULL(freightValue, 0) + - IFNULL(comissionValue, 0) + - IFNULL(packageValue, 0) itemCost - FROM vn.buy b + IFNULL(freightValue, 0) + + IFNULL(comissionValue, 0) + + IFNULL(packageValue, 0) itemCost + FROM vn.buy b WHERE b.id = vBuyFk ) SELECT v.itemFk, - vShelvingFK, + vShelvingCode, v.itemCost, SUM(ish.visible) visible FROM vn.itemShelving ish + JOIN vn.shelving sh ON sh.id = ish.shelvingFK JOIN visible v - WHERE ish.shelvingFK = vShelvingFK COLLATE utf8mb3_general_ci - AND ish.itemFk = v.itemFk; + WHERE sh.code = vShelvingCode COLLATE utf8mb3_general_ci + AND ish.itemFk = v.itemFk; END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -61292,168 +61674,174 @@ DELIMITER ; /*!50003 SET character_set_results = utf8mb4 */ ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; -CREATE DEFINER=`vn`@`localhost` PROCEDURE `itemShelving_getSaleDate`(vShelvingFk VARCHAR(3)) -BEGIN - - /* Devuelve la mínima fecha en que se necesita cada producto en esa matrícula. - * - * @param vShelvingFk Matrícula del carro o pallet - */ - - DECLARE vWarehouseFk INT; - DECLARE vStockScopeDays INT; - - SELECT s.warehouseFk, stockScopeDays - INTO vWarehouseFk, vStockScopeDays - FROM sector s - JOIN operator o ON s.id = o.sectorFk - JOIN productionConfig pc - WHERE o.workerFk = account.myUser_getId(); - - IF vWarehouseFk IS NULL - THEN CALL util.throw('WarehouseFk not setted'); - END IF; - - IF vStockScopeDays IS NULL - THEN CALL util.throw('StockScopeDays not setted'); - END IF; - - CREATE OR REPLACE TEMPORARY TABLE tmp.tItems - (PRIMARY KEY (itemFk)) - ENGINE = MEMORY - SELECT itemFk, SUM(visible) visible - FROM itemShelving - WHERE shelvingFk = vShelvingFk COLLATE utf8_unicode_ci - GROUP BY itemFk; - - CREATE OR REPLACE TEMPORARY TABLE tmp.tStockByDay - (INDEX (itemFk, dated)) - ENGINE = MEMORY - SELECT dated, - SUM(t3.amount) OVER (PARTITION BY t3.itemFk ORDER BY dated) stock, - t3.itemFk - FROM ( - SELECT t.itemFk, dated, SUM(amount) amount - FROM ( - SELECT t2.itemFk, t2.amount, t2.dated - FROM ( - SELECT item_id itemFk, amount, util.VN_CURDATE() dated - FROM cache.stock s - JOIN tmp.tItems i ON i.itemFk = s.item_id - WHERE s.warehouse_id = vWarehouseFk - UNION ALL - SELECT ish.itemFk, - SUM(ish.visible), util.VN_CURDATE() - FROM itemShelving ish - JOIN tmp.tItems i ON i.itemFk = ish.itemFk - JOIN shelving sh ON sh.code = ish.shelvingFk - JOIN parking p ON sh.parkingFk = p.id - JOIN sector s ON s.id = p.sectorFk - WHERE s.isReserve - GROUP BY ish.itemFk - UNION ALL - SELECT iei.itemFk, SUM(quantity), landed - FROM itemEntryIn iei - JOIN tmp.tItems i ON i.itemFk = iei.itemFk - WHERE iei.landed BETWEEN util.VN_CURDATE() AND util.VN_CURDATE() + INTERVAL vStockScopeDays DAY - AND iei.warehouseInFk = vWarehouseFk - AND NOT isVirtualStock - GROUP BY iei.itemFk, iei.landed - UNION ALL - SELECT ieo.itemFk, SUM(quantity), shipped - FROM itemEntryOut ieo - JOIN tmp.tItems i ON i.itemFk = ieo.itemFk - WHERE ieo.shipped BETWEEN util.VN_CURDATE() AND util.VN_CURDATE() + INTERVAL vStockScopeDays DAY - AND ieo.warehouseOutFk = vWarehouseFk - GROUP BY ieo.itemFk, ieo.shipped - UNION ALL - SELECT i.itemFk, SUM(ito.quantity), DATE(ito.shipped) - FROM itemTicketOut ito - JOIN tmp.tItems i ON i.itemFk = ito.itemFk - WHERE ito.shipped BETWEEN util.VN_CURDATE() AND util.VN_CURDATE() + INTERVAL vStockScopeDays DAY - AND ito.warehouseFk = vWarehouseFk - GROUP BY ito.itemFk, ito.shipped - ) t2 - JOIN tmp.tItems i ON i.itemFk = t2.itemFk)t - GROUP BY t.itemFk, dated - ) t3; - - -- Se restan las entradas de hoy - UPDATE tmp.tStockByDay sbd - JOIN (SELECT iei.itemFk, SUM(quantity) todayEntry - FROM itemEntryIn iei - JOIN tmp.tItems i ON i.itemFk = iei.itemFk - WHERE iei.landed = util.VN_CURDATE() - AND iei.warehouseInFk = vWarehouseFk - AND NOT iei.isVirtualStock) sub ON sub.itemFk = sbd.itemFk - SET sbd.stock = sbd.stock - sub.todayEntry - WHERE sbd.dated = util.VN_CURDATE(); - - -- Se añaden las lineas de venta servidas - UPDATE tmp.tStockByDay sbd - JOIN (SELECT s.itemFK, SUM(quantity) amount - FROM sale s - JOIN ticket t ON t.id = s.ticketFk - WHERE t.warehouseFk = vWarehouseFk - AND t.shipped BETWEEN util.VN_CURDATE() AND util.midnight() - AND s.isPicked - GROUP BY s.itemFk) sub ON sub.itemFk = sbd.itemFk - SET sbd.stock = sbd.stock + sub.amount; - - -- Se añaden los items ubicados hoy - UPDATE tmp.tStockByDay sbd - JOIN (SELECT ish.itemFK, SUM(ish.visible) amount - FROM itemShelving ish - JOIN shelving sh ON sh.code = ish.shelvingFk - JOIN parking p ON p.id = sh.parkingFk - JOIN sector s ON s.id = p.sectorFk - WHERE s.warehouseFk = vWarehouseFk - AND NOT s.isReserve - AND ish.created BETWEEN util.VN_CURDATE() AND util.midnight() - GROUP BY ish.itemFk) sub ON sub.itemFk = sbd.itemFk - SET sbd.stock = sbd.stock + sub.amount; - - SELECT ts.itemFk, - i.longName, - IF(ts.stock<=0, ts.dated, NULL) dated, - ts.stock, - sub4.visible, - sub4.shelvingFk - FROM( - SELECT IFNULL(sub2.minDated, sub.minDated) dated, - IFNULL(sub2.itemFk, sub.itemFk) itemFk - FROM(SELECT sbd.itemFk, - MIN(dated) minDated, - sbd.stock - FROM tmp.tItems ti - LEFT JOIN tmp.tStockByDay sbd ON sbd.itemFk = ti.itemFk - GROUP BY itemFk)sub - LEFT JOIN ( - SELECT sbd.itemFk, - MIN(dated) minDated, - sbd.stock - FROM tmp.tItems ti - LEFT JOIN tmp.tStockByDay sbd ON sbd.itemFk = ti.itemFk - WHERE sbd.stock <= 0 - GROUP BY itemFk)sub2 ON sub2.itemFk =sub.itemFk - WHERE sub2.itemFk IS NOT NULL - OR (sub2.itemFk IS NULL AND sub.itemFk IS NOT NULL)) sub3 - LEFT JOIN tmp.tStockByDay ts ON ts.itemFk = sub3.itemFk AND ts.dated = sub3.dated - JOIN (SELECT ish.itemFk, - ish.visible, - p.sectorFk, - ish.shelvingFk - FROM itemShelving ish - JOIN vn.shelving sh ON sh.code = ish.shelvingFk - LEFT JOIN parking p ON p.id = parkingFk - LEFT JOIN vn.sector s ON s.id = p.sectorFk - WHERE ish.shelvingFk = vShelvingFk COLLATE utf8_unicode_ci - ) sub4 ON sub4.itemFk = ts.itemFk - LEFT JOIN sector s ON s.id = sub4.sectorFk - LEFT JOIN item i ON i.id = ts.itemFk - WHERE NOT s.isReserve; - - DROP TEMPORARY TABLE tmp.tStockByDay, tmp.tItems; - +CREATE DEFINER=`vn`@`localhost` PROCEDURE `itemShelving_getSaleDate`( + vShelvingCode VARCHAR(10) +) +BEGIN +/** + * Devuelve la mínima fecha en que se necesita cada producto en esa matrícula. + * + * @param vShelvingCode Matrícula del carro o pallet + */ + DECLARE vWarehouseFk INT; + DECLARE vStockScopeDays INT; + DECLARE vShelvingFk INT; + + SELECT id INTO vShelvingFk + FROM shelving + WHERE code COLLATE utf8_unicode_ci = vShelvingCode; + + SELECT s.warehouseFk, stockScopeDays + INTO vWarehouseFk, vStockScopeDays + FROM sector s + JOIN operator o ON s.id = o.sectorFk + JOIN productionConfig pc + WHERE o.workerFk = account.myUser_getId(); + + IF vWarehouseFk IS NULL + THEN CALL util.throw('WarehouseFk not setted'); + END IF; + + IF vStockScopeDays IS NULL + THEN CALL util.throw('StockScopeDays not setted'); + END IF; + + CREATE OR REPLACE TEMPORARY TABLE tmp.tItems + (PRIMARY KEY (itemFk)) + ENGINE = MEMORY + SELECT itemFk, SUM(visible) visible + FROM itemShelving + WHERE shelvingFk = vShelvingFk + GROUP BY itemFk; + + CREATE OR REPLACE TEMPORARY TABLE tmp.tStockByDay + (INDEX (itemFk, dated)) + ENGINE = MEMORY + SELECT dated, + SUM(t3.amount) OVER (PARTITION BY t3.itemFk ORDER BY dated) stock, + t3.itemFk + FROM ( + SELECT t.itemFk, dated, SUM(amount) amount + FROM ( + SELECT t2.itemFk, t2.amount, t2.dated + FROM ( + SELECT item_id itemFk, amount, util.VN_CURDATE() dated + FROM cache.stock s + JOIN tmp.tItems i ON i.itemFk = s.item_id + WHERE s.warehouse_id = vWarehouseFk + UNION ALL + SELECT ish.itemFk, - SUM(ish.visible), util.VN_CURDATE() + FROM itemShelving ish + JOIN tmp.tItems i ON i.itemFk = ish.itemFk + JOIN shelving sh ON sh.id = ish.shelvingFk + JOIN parking p ON sh.parkingFk = p.id + JOIN sector s ON s.id = p.sectorFk + WHERE s.isReserve + GROUP BY ish.itemFk + UNION ALL + SELECT iei.itemFk, SUM(quantity), landed + FROM itemEntryIn iei + JOIN tmp.tItems i ON i.itemFk = iei.itemFk + WHERE iei.landed BETWEEN util.VN_CURDATE() AND util.VN_CURDATE() + INTERVAL vStockScopeDays DAY + AND iei.warehouseInFk = vWarehouseFk + AND NOT isVirtualStock + GROUP BY iei.itemFk, iei.landed + UNION ALL + SELECT ieo.itemFk, SUM(quantity), shipped + FROM itemEntryOut ieo + JOIN tmp.tItems i ON i.itemFk = ieo.itemFk + WHERE ieo.shipped BETWEEN util.VN_CURDATE() AND util.VN_CURDATE() + INTERVAL vStockScopeDays DAY + AND ieo.warehouseOutFk = vWarehouseFk + GROUP BY ieo.itemFk, ieo.shipped + UNION ALL + SELECT i.itemFk, SUM(ito.quantity), DATE(ito.shipped) + FROM itemTicketOut ito + JOIN tmp.tItems i ON i.itemFk = ito.itemFk + WHERE ito.shipped BETWEEN util.VN_CURDATE() AND util.VN_CURDATE() + INTERVAL vStockScopeDays DAY + AND ito.warehouseFk = vWarehouseFk + GROUP BY ito.itemFk, ito.shipped + ) t2 + JOIN tmp.tItems i ON i.itemFk = t2.itemFk)t + GROUP BY t.itemFk, dated + ) t3; + + -- Se restan las entradas de hoy + UPDATE tmp.tStockByDay sbd + JOIN (SELECT iei.itemFk, SUM(quantity) todayEntry + FROM itemEntryIn iei + JOIN tmp.tItems i ON i.itemFk = iei.itemFk + WHERE iei.landed = util.VN_CURDATE() + AND iei.warehouseInFk = vWarehouseFk + AND NOT iei.isVirtualStock) sub ON sub.itemFk = sbd.itemFk + SET sbd.stock = sbd.stock - sub.todayEntry + WHERE sbd.dated = util.VN_CURDATE(); + + -- Se añaden las lineas de venta servidas + UPDATE tmp.tStockByDay sbd + JOIN (SELECT s.itemFK, SUM(quantity) amount + FROM sale s + JOIN ticket t ON t.id = s.ticketFk + WHERE t.warehouseFk = vWarehouseFk + AND t.shipped BETWEEN util.VN_CURDATE() AND util.midnight() + AND s.isPicked + GROUP BY s.itemFk) sub ON sub.itemFk = sbd.itemFk + SET sbd.stock = sbd.stock + sub.amount; + + -- Se añaden los items ubicados hoy + UPDATE tmp.tStockByDay sbd + JOIN (SELECT ish.itemFK, SUM(ish.visible) amount + FROM itemShelving ish + JOIN shelving sh ON sh.id = ish.shelvingFk + JOIN parking p ON p.id = sh.parkingFk + JOIN sector s ON s.id = p.sectorFk + WHERE s.warehouseFk = vWarehouseFk + AND NOT s.isReserve + AND ish.created BETWEEN util.VN_CURDATE() AND util.midnight() + GROUP BY ish.itemFk) sub ON sub.itemFk = sbd.itemFk + SET sbd.stock = sbd.stock + sub.amount; + + SELECT ts.itemFk, + i.longName, + IF(ts.stock<=0, ts.dated, NULL) dated, + ts.stock, + sub4.visible, + sub4.shelvingFk + FROM( + SELECT IFNULL(sub2.minDated, sub.minDated) dated, + IFNULL(sub2.itemFk, sub.itemFk) itemFk + FROM(SELECT sbd.itemFk, + MIN(dated) minDated, + sbd.stock + FROM tmp.tItems ti + LEFT JOIN tmp.tStockByDay sbd ON sbd.itemFk = ti.itemFk + GROUP BY itemFk)sub + LEFT JOIN ( + SELECT sbd.itemFk, + MIN(dated) minDated, + sbd.stock + FROM tmp.tItems ti + LEFT JOIN tmp.tStockByDay sbd ON sbd.itemFk = ti.itemFk + WHERE sbd.stock <= 0 + GROUP BY itemFk)sub2 ON sub2.itemFk =sub.itemFk + WHERE sub2.itemFk IS NOT NULL + OR (sub2.itemFk IS NULL AND sub.itemFk IS NOT NULL)) sub3 + LEFT JOIN tmp.tStockByDay ts ON ts.itemFk = sub3.itemFk AND ts.dated = sub3.dated + JOIN (SELECT ish.itemFk, + ish.visible, + p.sectorFk, + ish.shelvingFk + FROM itemShelving ish + JOIN vn.shelving sh ON sh.id = ish.shelvingFk + LEFT JOIN parking p ON p.id = parkingFk + LEFT JOIN vn.sector s ON s.id = p.sectorFk + WHERE ish.shelvingFk = vShelvingFk + ) sub4 ON sub4.itemFk = ts.itemFk + LEFT JOIN sector s ON s.id = sub4.sectorFk + LEFT JOIN item i ON i.id = ts.itemFk + WHERE NOT s.isReserve; + + DROP TEMPORARY TABLE tmp.tStockByDay, tmp.tItems; + END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -61513,7 +61901,7 @@ BEGIN JOIN item i ON i.id = ish.itemFk JOIN itemType it ON it.id = i.typeFk JOIN tmp.stockMisfit sm ON sm.itemFk = ish.itemFk - JOIN shelving sh ON sh.code = ish.shelvingFk + JOIN shelving sh ON sh.id = ish.shelvingFk JOIN parking p ON p.id = sh.parkingFk LEFT JOIN ( SELECT s.itemFk, sum(s.quantity) notPrepared @@ -61549,7 +61937,7 @@ DELIMITER ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; CREATE DEFINER=`vn`@`localhost` PROCEDURE `itemShelving_selfConsumption`( - vShelvingFk VARCHAR(10) COLLATE utf8_general_ci, + vShelvingCode VARCHAR(10) COLLATE utf8_general_ci, vItemFk INT, vQuantity INT ) @@ -61558,9 +61946,9 @@ BEGIN * Leave the indicated amount on the shelve * and create a ticket with the difference. * - * @param vShelvingFk id of the shelve where the item is located. - * @param vItemFk article of which the self-consumption ticket is to be created. - * @param vQuantity amount that will stay on the shelve + * @param vShelvingCode Code of the shelve where the item is located + * @param vItemFk Item of which the self-consumption ticket is to be created + * @param vQuantity Amount that will stay on the shelve */ DECLARE vVisible INT; DECLARE vClientFk INT; @@ -61570,6 +61958,11 @@ BEGIN DECLARE vAgencyModeFk INT; DECLARE vItemShelvingFk INT; DECLARE vAddressFk INT; + DECLARE vShelvingFk INT; + + SELECT id INTO vShelvingFk + FROM shelving + WHERE code = vShelvingCode; SELECT c.id, pc.clientSelfConsumptionFk, @@ -61586,7 +61979,7 @@ BEGIN JOIN parking p ON p.sectorFk = s.id JOIN shelving s2 ON s2.parkingFk = p.id JOIN productionConfig pc - WHERE s2.code = vShelvingFk; + WHERE s2.id = vShelvingFk; IF vClientFk IS NULL THEN CALL util.throw('The company does not have a customer assigned'); @@ -61596,7 +61989,7 @@ BEGIN CALL util.throw('The shelf cannot have NULL or negative quantities'); END IF; - IF vShelvingFk IS NULL THEN + IF vShelvingCode IS NULL THEN CALL util.throw('The shelf is necessary'); END IF; @@ -61653,7 +62046,7 @@ DELIMITER ; DELIMITER ;; CREATE DEFINER=`vn`@`localhost` PROCEDURE `itemShelving_transfer`( vItemShelvingFk INT, - vShelvingFk VARCHAR(10) + vShelvingCode VARCHAR(10) ) BEGIN /** @@ -61661,9 +62054,14 @@ BEGIN * fusionando si coincide el packing y la fecha. * * @param vItemShelvingFk Identificador de itemShelving - * @param vShelvingFk Identificador de shelving + * @param vShelvingCode Código de shelving */ DECLARE vNewItemShelvingFk INT; + DECLARE vShelvingFk INT; + + SELECT id INTO vShelvingFk + FROM shelving + WHERE code COLLATE utf8_unicode_ci = vShelvingCode; SELECT MAX(ish.id) INTO vNewItemShelvingFk FROM itemShelving ish @@ -61678,7 +62076,7 @@ BEGIN AND ish2.packing = ish.packing AND DATE(ish2.created) = DATE(ish.created) AND ish2.buyFk = ish.buyFk - WHERE ish.shelvingFk = vShelvingFk COLLATE utf8_unicode_ci; + WHERE ish.shelvingFk = vShelvingFk; IF vNewItemShelvingFk THEN UPDATE itemShelving ish @@ -61690,9 +62088,7 @@ BEGIN DELETE FROM itemShelving WHERE id = vItemShelvingFk; ELSE - IF (SELECT EXISTS(SELECT id FROM shelving - WHERE code = vShelvingFk COLLATE utf8_unicode_ci)) THEN - + IF (SELECT EXISTS(SELECT id FROM shelving WHERE id = vShelvingFk)) THEN UPDATE itemShelving SET shelvingFk = vShelvingFk WHERE id = vItemShelvingFk; @@ -62772,7 +63168,7 @@ DELIMITER ; DELIMITER ;; CREATE DEFINER=`vn`@`localhost` PROCEDURE `item_devalueA2`( vSelf INT, - vShelvingFK VARCHAR(10), + vShelvingCode VARCHAR(10) COLLATE utf8mb3_general_ci, vBuyingValue DECIMAL(10,4), vQuantity INT ) @@ -62783,7 +63179,7 @@ BEGIN * de almacén y shelvings correspondientes * * @param vSelf Id de artículo a devaluar - * @param vShelvingFK Ubicación actual del artículo + * @param vShelvingCode Código de shelving / ubicación * @param vBuyingValue Nuevo precio de coste * @param vQuantity Cantidad del ítem a pasar a A2 */ @@ -62880,10 +63276,11 @@ BEGIN CALL util.throw ('The item has not a buy'); END IF; - SELECT id,visible INTO vTargetItemShelvingFk, vCurrentVisible - FROM itemShelving - WHERE shelvingFk = vShelvingFK COLLATE utf8mb3_general_ci - AND itemFk = vSelf + SELECT ish.id, ish.visible INTO vTargetItemShelvingFk, vCurrentVisible + FROM itemShelving ish + JOIN shelving sh ON sh.id = ish.shelvingFk + WHERE sh.code = vShelvingCode + AND ish.itemFk = vSelf LIMIT 1; IF vCurrentVisible IS NULL THEN @@ -63159,16 +63556,17 @@ BEGIN userFk, isChecked) SELECT vItemA2Fk, - shelvingFk, + ish.shelvingFk, vQuantity , - `grouping`, - packing, - packagingFk, + ish.`grouping`, + ish.packing, + ish.packagingFk, account.myUser_getId(), - isChecked - FROM itemShelving - WHERE itemFK = vSelf - AND shelvingFk = vShelvingFK COLLATE utf8mb3_general_ci + ish.isChecked + FROM itemShelving ish + JOIN shelving sh ON sh.id = ish.shelvingFk + WHERE ish.itemFK = vSelf + AND sh.code = vShelvingCode ON DUPLICATE KEY UPDATE visible = vQuantity + VALUES(visible); @@ -63193,50 +63591,50 @@ DELIMITER ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; CREATE DEFINER=`vn`@`localhost` PROCEDURE `item_getAtp`(vDated DATE) -BEGIN -/** - * Calcula el valor mínimo acumulado para cada artículo ordenado por fecha y - * almacén. - * - * @param vDated Si no hay movimientos en la fecha indicada, debe devolver 0 - * @table tmp.itemCalc(itemFk, wareHouseFk, dated, quantity) - * @return tmp.itemAtp(itemFk, warehouseFk, quantity) - */ - CREATE OR REPLACE TEMPORARY TABLE tItemOrdered - (UNIQUE(itemFk, warehouseFk, dated)) - ENGINE = MEMORY - SELECT itemFk, warehouseFk, dated, SUM(quantity) quantity - FROM ( - SELECT itemFk, warehouseFk, dated, quantity - FROM tmp.itemCalc - UNION ALL - SELECT itemFk, warehouseFk, vDated, 0 - FROM (SELECT DISTINCT itemFk, warehouseFk FROM tmp.itemCalc) t2 - ) t1 - GROUP BY itemFk, warehouseFk, dated - ORDER BY itemFk, warehouseFk, dated; - - SET @lastItemFk := 0; - SET @lastWareHouseFk := 0; - SET @lastQuantity := 0; - - CREATE OR REPLACE TEMPORARY TABLE tmp.itemAtp - (INDEX (itemFk, wareHouseFk)) - SELECT itemFk, wareHouseFk, MIN(quantityAccumulated) quantity - FROM ( - SELECT - itemFk, - IF(itemFk <> @lastItemFk OR wareHouseFk <> @lastWareHouseFk, - @lastQuantity := quantity, - @lastQuantity := @lastQuantity + quantity) quantityAccumulated, - wareHouseFk, - @lastItemFk := itemFk, - @lastWareHouseFk := wareHouseFk - FROM tItemOrdered - )sub - GROUP BY itemFk, wareHouseFk; - - DROP TEMPORARY TABLE tItemOrdered; +BEGIN +/** + * Calcula el valor mínimo acumulado para cada artículo ordenado por fecha y + * almacén. + * + * @param vDated Si no hay movimientos en la fecha indicada, debe devolver 0 + * @table tmp.itemCalc(itemFk, wareHouseFk, dated, quantity) + * @return tmp.itemAtp(itemFk, warehouseFk, quantity) + */ + CREATE OR REPLACE TEMPORARY TABLE tItemOrdered + (UNIQUE(itemFk, warehouseFk, dated)) + ENGINE = MEMORY + SELECT itemFk, warehouseFk, dated, SUM(quantity) quantity + FROM ( + SELECT itemFk, warehouseFk, dated, quantity + FROM tmp.itemCalc + UNION ALL + SELECT itemFk, warehouseFk, vDated, 0 + FROM (SELECT DISTINCT itemFk, warehouseFk FROM tmp.itemCalc) t2 + ) t1 + GROUP BY itemFk, warehouseFk, dated + ORDER BY itemFk, warehouseFk, dated; + + SET @lastItemFk := 0; + SET @lastWareHouseFk := 0; + SET @lastQuantity := 0; + + CREATE OR REPLACE TEMPORARY TABLE tmp.itemAtp + (INDEX (itemFk, wareHouseFk)) + SELECT itemFk, wareHouseFk, MIN(quantityAccumulated) quantity + FROM ( + SELECT + itemFk, + IF(itemFk <> @lastItemFk OR wareHouseFk <> @lastWareHouseFk, + @lastQuantity := quantity, + @lastQuantity := @lastQuantity + quantity) quantityAccumulated, + wareHouseFk, + @lastItemFk := itemFk, + @lastWareHouseFk := wareHouseFk + FROM tItemOrdered + )sub + GROUP BY itemFk, wareHouseFk; + + DROP TEMPORARY TABLE tItemOrdered; END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -63304,16 +63702,16 @@ BEGIN JOIN vn.entry e ON e.id = b.entryFk JOIN vn.travel tr ON tr.id = e.travelFk JOIN vn.supplier s ON s.id = e.supplierFk - JOIN vn.state st ON st.`code` = IF(tr.landed < util.VN_CURDATE() + JOIN vn.state st ON st.`code` = IF(tr.landed < util.VN_CURDATE() OR (util.VN_CURDATE() AND tr.isReceived), 'DELIVERED', 'FREE') WHERE tr.landed >= vDateInventory AND tr.warehouseInFk = vWarehouseFk - AND (s.id <> vSupplierInventoryFk OR vDated IS NULL) + AND (s.id <> vSupplierInventoryFk OR vDated IS NULL) AND b.itemFk = vItemFk AND NOT e.isExcludedFromAvailable - AND NOT e.isRaid + AND NOT tr.isRaid ), entriesOut AS ( SELECT 'entry', @@ -63349,7 +63747,7 @@ BEGIN AND b.itemFk = vItemFk AND NOT e.isExcludedFromAvailable AND NOT w.isFeedStock - AND NOT e.isRaid + AND NOT tr.isRaid ), sales AS ( WITH itemSales AS ( @@ -63401,10 +63799,10 @@ BEGIN NULL FROM itemSales s LEFT JOIN vn.state stPrep ON stPrep.`code` = 'PREPARED' - LEFT JOIN vn.saleTracking stk ON stk.saleFk = s.saleFk + LEFT JOIN vn.saleTracking stk ON stk.saleFk = s.saleFk AND stk.stateFk = stPrep.id GROUP BY s.saleFk - ), + ), orders AS ( SELECT 'order' originType, o.id originId, @@ -63469,9 +63867,9 @@ BEGIN t.`in` invalue, t.`out`, @a := @a + IFNULL(t.`in`, 0) - IFNULL(t.`out`, 0) balance, - @currentLineFk := IF (@shipped < util.VN_CURDATE() + @currentLineFk := IF (@shipped < util.VN_CURDATE() OR (@shipped = util.VN_CURDATE() AND (t.isPicked OR a.`code` >= 'ON_PREPARATION')), - t.lineFk, + t.lineFk, @currentLineFk) lastPreparedLineFk, t.isTicket, t.lineFk, @@ -63508,21 +63906,21 @@ BEGIN UNION ALL SELECT originType, originId, - shipped, - alertlevel, - stateName, + shipped, + alertlevel, + stateName, reference, entityType, - entityId, + entityId, entityName, - `in`, - `out`, - @a := @a + IFNULL(`in`, 0) - IFNULL(`out`, 0), - 0, - isTicket, - lineFk, - isPicked, - clientType, + `in`, + `out`, + @a := @a + IFNULL(`in`, 0) - IFNULL(`out`, 0), + 0, + isTicket, + lineFk, + isPicked, + clientType, claimFk, `order` FROM tItemDiary @@ -63589,7 +63987,6 @@ BEGIN i.minimum `min`, p.name producer, o.code origin, - v.visible - IFNULL(vVisibleItemShelving, 0) unlocated, a.available, vVisibleItemShelving, v.visible, @@ -63770,7 +64167,7 @@ BEGIN AND NOT e.isExcludedFromAvailable AND b.quantity <> 0 AND (vItemFk IS NULL OR b.itemFk = vItemFk) - AND NOT e.isRaid + AND NOT t.isRaid UNION ALL SELECT r.itemFk, r.shipment, @@ -64127,22 +64524,22 @@ BEGIN ALTER TABLE tmp.itemInventory ADD `buy_date` datetime NOT NULL; - + CREATE OR REPLACE TEMPORARY TABLE lastBuyScope SELECT i.id, MAX(t.landed) lastLanded - FROM item i - JOIN buy b ON b.itemFk = i.id + FROM item i + JOIN buy b ON b.itemFk = i.id JOIN entry e ON e.id = b.entryFk - JOIN travel t ON t.id = e.travelFk + JOIN travel t ON t.id = e.travelFk JOIN supplier s ON s.id = e.supplierFk JOIN warehouse w ON w.id = t.warehouseInFk WHERE t.landed BETWEEN (vDated + INTERVAL - vLastBuyScope DAY) AND vDated AND NOT s.name = 'INVENTARIO' AND (vWarehouseFk IS NULL OR t.warehouseInFk = vWarehouseFk) AND w.isComparative - AND NOT e.isRaid + AND NOT t.isRaid GROUP BY i.id; - + UPDATE tmp.itemInventory y JOIN lastBuyScope lbs ON lbs.id = y.id SET y.buy_date = lbs.lastLanded; @@ -64531,7 +64928,7 @@ BEGIN LIMIT 1; SET vHasNotInventory = (vInventoried IS NULL); - + IF vHasNotInventory THEN SELECT landed INTO vInventoryClone FROM travel tr @@ -64556,7 +64953,7 @@ BEGIN PRIMARY KEY (warehouseInventory, itemFk) USING HASH ) ENGINE = MEMORY; - + -- Inventario inicial IF vHasNotInventory THEN INSERT INTO tInventory(warehouseFk, itemFk, quantity, warehouseInventory) @@ -64615,7 +65012,7 @@ BEGIN JOIN warehouse w ON w.id = tr.warehouseInFk WHERE tr.landed BETWEEN vInventoried AND vDateDayEnd AND IF(tr.landed = util.VN_CURDATE(), tr.isReceived, TRUE) - AND NOT e.isRaid + AND NOT tr.isRaid AND w.valuatedInventory AND t.isInventory AND e.supplierFk <> vInventorySupplierFk @@ -64637,7 +65034,7 @@ BEGIN JOIN itemCategory ic ON ic.id = t.categoryFk JOIN warehouse w ON w.id = tr.warehouseOutFk WHERE tr.shipped BETWEEN vInventoried AND vDateDayEnd - AND NOT e.isRaid + AND NOT tr.isRaid AND w.valuatedInventory AND t.isInventory AND (t.id = vItemTypeFk OR vItemTypeFk IS NULL) @@ -64665,7 +65062,7 @@ BEGIN ON DUPLICATE KEY UPDATE tInventory.quantity = tInventory.quantity + s.quantity * IF(vHasNotInventory, 1, -1); -- Volver a poner lo que esta aun en las estanterias - IF vDated = util.VN_CURDATE() THEN + IF vDated = util.VN_CURDATE() THEN INSERT INTO tInventory(warehouseFk, itemFk, quantity, warehouseInventory) SELECT w.id, s.itemFk, @@ -64702,14 +65099,14 @@ BEGIN JOIN warehouse wIn ON wIn.id = tr.warehouseInFk JOIN warehouse wOut ON wOut.id = tr.warehouseOutFk WHERE vDated >= tr.shipped AND vDated < tr.landed - AND NOT isRaid + AND NOT tr.isRaid AND wIn.valuatedInventory AND t.isInventory AND e.isConfirmed AND (t.id = vItemTypeFk OR vItemTypeFk IS NULL) AND (ic.id = vItemCategoryFk OR vItemCategoryFk IS NULL) ON DUPLICATE KEY UPDATE tInventory.quantity = tInventory.quantity + (b.quantity); - + CALL buy_getUltimate (NULL, NULL, vDateDayEnd); DELETE FROM tInventory WHERE quantity IS NULL OR NOT quantity; @@ -64739,7 +65136,7 @@ BEGIN JOIN warehouse w ON w.id = warehouseFk JOIN item i ON i.id = ti.itemFk JOIN itemType tp ON tp.id = i.typeFk - JOIN itemCategory ic ON ic.id = tp.categoryFk + JOIN itemCategory ic ON ic.id = tp.categoryFk WHERE w.valuatedInventory AND ti.total > 0; @@ -65078,155 +65475,6 @@ set @cajas := 0; -END ;; -DELIMITER ; -/*!50003 SET sql_mode = @saved_sql_mode */ ; -/*!50003 SET character_set_client = @saved_cs_client */ ; -/*!50003 SET character_set_results = @saved_cs_results */ ; -/*!50003 SET collation_connection = @saved_col_connection */ ; -/*!50003 SET @saved_sql_mode = @@sql_mode */ ; -/*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; -/*!50003 DROP PROCEDURE IF EXISTS `machineWorker_add` */; -/*!50003 SET @saved_cs_client = @@character_set_client */ ; -/*!50003 SET @saved_cs_results = @@character_set_results */ ; -/*!50003 SET @saved_col_connection = @@collation_connection */ ; -/*!50003 SET character_set_client = utf8mb4 */ ; -/*!50003 SET character_set_results = utf8mb4 */ ; -/*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; -DELIMITER ;; -CREATE DEFINER=`vn`@`localhost` PROCEDURE `machineWorker_add`(vPlate VARCHAR(10), vWorkerFk INT) -BEGIN - -/** - * Inserta registro si el vWorkerFk no ha registrado nada en las últimas 12 horas - * @param vPlate número de matrícula - * @param vWorkerFk id del worker - * -*/ - UPDATE vn.machineWorker mw - JOIN vn.machine m ON m.id = mw.machineFk - SET mw.outTimed = util.VN_NOW() - WHERE (mw.workerFk = vWorkerFk OR m.plate = vPlate) - AND ISNULL(mw.outTimed); - - INSERT INTO machineWorker (machineFk, workerFk) - SELECT m.id, vWorkerFk - FROM machine m - WHERE m.plate= vPlate; -END ;; -DELIMITER ; -/*!50003 SET sql_mode = @saved_sql_mode */ ; -/*!50003 SET character_set_client = @saved_cs_client */ ; -/*!50003 SET character_set_results = @saved_cs_results */ ; -/*!50003 SET collation_connection = @saved_col_connection */ ; -/*!50003 SET @saved_sql_mode = @@sql_mode */ ; -/*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; -/*!50003 DROP PROCEDURE IF EXISTS `machineWorker_getHistorical` */; -/*!50003 SET @saved_cs_client = @@character_set_client */ ; -/*!50003 SET @saved_cs_results = @@character_set_results */ ; -/*!50003 SET @saved_col_connection = @@collation_connection */ ; -/*!50003 SET character_set_client = utf8mb4 */ ; -/*!50003 SET character_set_results = utf8mb4 */ ; -/*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; -DELIMITER ;; -CREATE DEFINER=`vn`@`localhost` PROCEDURE `machineWorker_getHistorical`(vPlate VARCHAR(20), vWorkerFk INT) -BEGIN -/** - * Obtiene historial de la matrícula vPlate que el trabajador vWorkerFk escanea, - * si es jefe de producción muestra el historial completo. - * - * @param vPlate número de matrícula - * @param vWorkerFk id del trabajador - * -*/ - DECLARE vWorkerName VARCHAR(255) DEFAULT account.user_getNameFromId(vWorkerFk); - - SELECT mw.inTimed,account.user_getNameFromId(mw.workerFk) as workerName, mw.outTimed - FROM machineWorker mw - JOIN machine m ON m.plate = vPlate - WHERE mw.machineFk = m.id - AND mw.workerFk = IF(account.user_hasRole(vWorkerName, 'coolerAssist'), mw.workerFk, vWorkerFk) - ORDER BY mw.inTimed DESC; -END ;; -DELIMITER ; -/*!50003 SET sql_mode = @saved_sql_mode */ ; -/*!50003 SET character_set_client = @saved_cs_client */ ; -/*!50003 SET character_set_results = @saved_cs_results */ ; -/*!50003 SET collation_connection = @saved_col_connection */ ; -/*!50003 SET @saved_sql_mode = @@sql_mode */ ; -/*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; -/*!50003 DROP PROCEDURE IF EXISTS `machineWorker_update` */; -/*!50003 SET @saved_cs_client = @@character_set_client */ ; -/*!50003 SET @saved_cs_results = @@character_set_results */ ; -/*!50003 SET @saved_col_connection = @@collation_connection */ ; -/*!50003 SET character_set_client = utf8mb4 */ ; -/*!50003 SET character_set_results = utf8mb4 */ ; -/*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; -DELIMITER ;; -CREATE DEFINER=`vn`@`localhost` PROCEDURE `machineWorker_update`(vPlate VARCHAR(10), vWorkerFk INT) -BEGIN - -/** - * Actualiza el registro correspondiente si el vWorkerFk se ha registrado en las últimas horas (campo maxHours de machineWorkerConfig) con vPlate, - * - * @param vPlate número de matrícula - * @param vWorkerFk id del trabajador - * -*/ - - DECLARE vMachineFk INT(10); - DECLARE vMaxHours INT(10); - - SELECT m.id INTO vMachineFk - FROM machine m - WHERE m.plate = vPlate; - - SELECT maxHours INTO vMaxHours - FROM machineWorkerConfig; - - IF (SELECT COUNT(*) - FROM machineWorker m - WHERE m.workerFk = vWorkerFk - AND m.inTimed >= TIMESTAMPADD(HOUR , -vMaxHours, util.VN_NOW()) AND ISNULL(m.outTimed)) THEN - - UPDATE machineWorker m - SET m.outTimed = CURRENT_TIMESTAMP() - WHERE m.workerFk = vWorkerFk - AND m.inTimed >= TIMESTAMPADD(HOUR , -vMaxHours, util.VN_NOW()) - AND ISNULL(m.outTimed) - AND m.machineFk = vMachineFk; - - END IF; - -END ;; -DELIMITER ; -/*!50003 SET sql_mode = @saved_sql_mode */ ; -/*!50003 SET character_set_client = @saved_cs_client */ ; -/*!50003 SET character_set_results = @saved_cs_results */ ; -/*!50003 SET collation_connection = @saved_col_connection */ ; -/*!50003 SET @saved_sql_mode = @@sql_mode */ ; -/*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; -/*!50003 DROP PROCEDURE IF EXISTS `machine_getWorkerPlate` */; -/*!50003 SET @saved_cs_client = @@character_set_client */ ; -/*!50003 SET @saved_cs_results = @@character_set_results */ ; -/*!50003 SET @saved_col_connection = @@collation_connection */ ; -/*!50003 SET character_set_client = utf8mb4 */ ; -/*!50003 SET character_set_results = utf8mb4 */ ; -/*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; -DELIMITER ;; -CREATE DEFINER=`vn`@`localhost` PROCEDURE `machine_getWorkerPlate`(vWorkerFk INT) -BEGIN -/** - * Selecciona la matrícula del vehículo del workerfk - * - * @param vWorkerFk el id del trabajador - */ - SELECT m.plate - FROM machine m - JOIN machineWorker mw ON mw.machineFk = m.id - WHERE mw.inTimed >= TIMESTAMPADD(HOUR , -12,util.VN_NOW()) - AND ISNULL(mw.outTimed) - AND mw.workerFk = vWorkerFk; END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -65485,7 +65733,7 @@ proc: BEGIN AND IFNULL(vWarehouseFk, t.warehouseInFk) = t.warehouseInFk AND w.isComparative AND NOT e.isExcludedFromAvailable - AND NOT e.isRaid + AND NOT t.isRaid UNION ALL SELECT b.itemFk, - b.quantity FROM buy b @@ -65496,7 +65744,7 @@ proc: BEGIN AND IFNULL(vWarehouseFk, t.warehouseOutFk) = t.warehouseOutFk AND w.isComparative AND NOT e.isExcludedFromAvailable - AND NOT e.isRaid + AND NOT t.isRaid ) sub GROUP BY itemFk; @@ -65546,7 +65794,7 @@ proc: BEGIN AND IFNULL(vWarehouseFk, t.warehouseInFk) = t.warehouseInFk AND w.isComparative AND NOT e.isExcludedFromAvailable - AND NOT e.isRaid + AND NOT t.isRaid UNION ALL SELECT b.itemFk, t.shipped, - b.quantity FROM buy b @@ -65557,7 +65805,7 @@ proc: BEGIN AND IFNULL(vWarehouseFk, t.warehouseOutFk) = t.warehouseOutFk AND w.isComparative AND NOT e.isExcludedFromAvailable - AND NOT e.isRaid + AND NOT t.isRaid ) sub GROUP BY sub.itemFk, sub.dated; @@ -66732,7 +66980,7 @@ proc: BEGIN st.code = 'previousPrepared' isPreviousPrepared, sc.itemPackingTypeFk FROM itemShelving ish - JOIN shelving sh ON sh.code = ish.shelvingFk + JOIN shelving sh ON sh.id = ish.shelvingFk JOIN parking p ON p.id = sh.parkingFk JOIN sector sc ON sc.id = p.sectorFk JOIN sectorType st ON st.id = sc.typeFk @@ -67204,50 +67452,6 @@ DELIMITER ; /*!50003 SET collation_connection = @saved_col_connection */ ; /*!50003 SET @saved_sql_mode = @@sql_mode */ ; /*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; -/*!50003 DROP PROCEDURE IF EXISTS `raidUpdate` */; -/*!50003 SET @saved_cs_client = @@character_set_client */ ; -/*!50003 SET @saved_cs_results = @@character_set_results */ ; -/*!50003 SET @saved_col_connection = @@collation_connection */ ; -/*!50003 SET character_set_client = utf8mb4 */ ; -/*!50003 SET character_set_results = utf8mb4 */ ; -/*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; -DELIMITER ;; -CREATE DEFINER=`vn`@`localhost` PROCEDURE `raidUpdate`() -BEGIN -/** - * Actualiza el travel de las entradas de redadas - */ - UPDATE entry e - JOIN entryVirtual ev ON ev.entryFk = e.id - JOIN travel t ON t.id = e.travelFk - JOIN ( - SELECT * - FROM ( - SELECT t.id, t.landed, tt.warehouseInFk, tt.warehouseOutFk - FROM travel t - JOIN ( - SELECT t.warehouseInFk, t.warehouseOutFk - FROM entryVirtual ev - JOIN entry e ON e.id = ev.entryFk - JOIN travel t ON t.id = e.travelFk - GROUP BY t.warehouseInFk, t.warehouseOutFk - ) tt ON t.warehouseInFk = tt.warehouseInFk AND t.warehouseOutFk = tt.warehouseOutFk - WHERE shipped > util.VN_CURDATE() AND NOT isDelivered - ORDER BY t.landed - LIMIT 10000000000000000000 - ) t - GROUP BY t.warehouseInFk, t.warehouseOutFk - ) tt ON t.warehouseInFk = tt.warehouseInFk AND t.warehouseOutFk = tt.warehouseOutFk - SET e.travelFk = t.id; - -END ;; -DELIMITER ; -/*!50003 SET sql_mode = @saved_sql_mode */ ; -/*!50003 SET character_set_client = @saved_cs_client */ ; -/*!50003 SET character_set_results = @saved_cs_results */ ; -/*!50003 SET collation_connection = @saved_col_connection */ ; -/*!50003 SET @saved_sql_mode = @@sql_mode */ ; -/*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; /*!50003 DROP PROCEDURE IF EXISTS `rangeDateInfo` */; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; @@ -67974,6 +68178,8 @@ BEGIN */ DECLARE vIsUpdatable, vIsFreelance BOOL DEFAULT 0; DECLARE vAgencyModePricePercentage DOUBLE; + DECLARE vIsKmTruckRate BOOL; + DECLARE vCountryFk INT; SELECT r.created >= rc.cutoffDated INTO vIsUpdatable FROM route r @@ -67984,10 +68190,16 @@ BEGIN DELETE FROM routeCommission WHERE routeFk = vSelf; - SELECT w.isFreelance INTO vIsFreelance + SELECT w.isFreelance, v.isKmTruckRate, c.countryFk INTO vIsFreelance, vIsKmTruckRate, vCountryFk FROM route r JOIN worker w ON w.id = r.workerFk - WHERE r.id = vSelf; + JOIN vehicle v ON v.id = r.vehicleFk + LEFT JOIN ticket t ON t.routeFk = r.id + LEFT JOIN client c ON c.id = t.clientFk + WHERE r.id = vSelf + GROUP BY c.countryFk + ORDER BY COUNT(*) DESC + LIMIT 1; SELECT ampp.percentage INTO vAgencyModePricePercentage FROM route r @@ -68002,7 +68214,9 @@ BEGIN workCenterFk, freelanceYearlyM3, cat4m3, - cat5m3 + cat5m3, + isKmTruckRate, + countryFk ) SELECT vSelf, r.commissionWorkCenterFk, @@ -68014,11 +68228,14 @@ BEGIN IFNULL(r.m3, 0), 0 ), - rc.distributionCat4M3 * IFNULL(r.m3, 0), - rc.distributionCat5M3 * IFNULL(r.m3, 0) + IFNULL(wc.distributionCat4M3, rc.distributionCat4M3) * IFNULL(r.m3, 0), + IFNULL(wc.distributionCat5M3, rc.distributionCat5M3) * IFNULL(r.m3, 0), + vIsKmTruckRate, + vCountryFk FROM route r JOIN vehicle v ON v.id = r.vehicleFk JOIN routeConfig rc + LEFT JOIN workCenterCommission wc ON wc.workCenterFk = r.commissionWorkCenterFk WHERE r.id = vSelf AND r.workerFk AND r.commissionWorkCenterFk; @@ -68031,7 +68248,9 @@ BEGIN yearlyKm, yearlyM3, cat4m3, - cat5m3 + cat5m3, + isKmTruckRate, + countryFk ) SELECT vSelf, r.commissionWorkCenterFk, @@ -68041,11 +68260,14 @@ BEGIN IF(v.isKmTruckRate, rc.deliveryM3Cat5, rc.deliveryM3Cat4), (r.kmEnd - r.kmStart) * rc.kmYearly, IFNULL(r.m3, 0) * rc.m3Yearly, - rc.distributionCat4M3 * IFNULL(r.m3, 0), - rc.distributionCat5M3 * IFNULL(r.m3, 0) + IFNULL(wc.distributionCat4M3, rc.distributionCat4M3) * IFNULL(r.m3, 0), + IFNULL(wc.distributionCat5M3, rc.distributionCat5M3) * IFNULL(r.m3, 0), + vIsKmTruckRate, + vCountryFk FROM route r JOIN vehicle v ON v.id = r.vehicleFk JOIN routeConfig rc + LEFT JOIN workCenterCommission wc ON wc.workCenterFk = r.commissionWorkCenterFk WHERE r.id = vSelf AND r.kmStart AND r.kmEnd @@ -68814,7 +69036,7 @@ BEGIN DECLARE vQuantity INT; DECLARE vRemainder INT DEFAULT 0; DECLARE vRemainderSaleFk INT; - DECLARE vShelving VARCHAR(10); + DECLARE vShelvingFk VARCHAR(10); DECLARE vTicketFk INT; SELECT s.quantity, @@ -68861,7 +69083,7 @@ w1: WHILE vQuantity >= vPacking DO p.pickingOrder, ish.created FROM itemShelving ish - JOIN shelving sh ON sh.code = ish.shelvingFk + JOIN shelving sh ON sh.id = ish.shelvingFk JOIN parking p ON p.id = sh.parkingFk LEFT JOIN itemShelvingSale iss ON iss.itemShelvingFk = ish.id @@ -69049,9 +69271,9 @@ w1: WHILE vQuantity >= vPacking DO CALL dipole.expedition_Add(vExpeditionFk,vPrinterFk, TRUE); SELECT shelvingFk, p.code - INTO vShelving, vParkingCode + INTO vShelvingFk, vParkingCode FROM itemShelving ish - JOIN shelving sh ON sh.code = ish.shelvingFk + JOIN shelving sh ON sh.id = ish.shelvingFk JOIN parking p ON p.id = sh.parkingFk WHERE ish.id = vItemShelvingFk; @@ -69060,7 +69282,7 @@ w1: WHILE vQuantity >= vPacking DO itemFk = vItemFk, quantity = vPacking, longName = vConcept, - shelvingFk = vShelving, + shelvingFk = vShelvingFk, parkingCode = vParkingCode, phone = RIGHT(phone,vMaxPhoneLength), street = RIGHT(street, vMAxStreetLength) @@ -69162,7 +69384,7 @@ BEGIN AND iss.created >= vDated GROUP BY iss.itemShelvingFk, s.itemFk) tISS ON tISS.itemFk = ish.itemFk AND tISS.itemShelvingFk = ish.id - JOIN shelving sh ON sh.code = ish.shelvingFk + JOIN shelving sh ON sh.id = ish.shelvingFk JOIN parking p ON p.id = sh.parkingFk JOIN tmp.productionBuffer pb ON pb.ticketFk = s.ticketFk JOIN agencyMode am ON am.id = pb.agencyModeFk @@ -69427,7 +69649,7 @@ BEGIN SUM(ish.visible) visible, s.warehouseFk warehouseFk FROM itemShelving ish - JOIN shelving sh ON sh.code = ish.shelvingFk + JOIN shelving sh ON sh.id = ish.shelvingFk JOIN parking p ON p.id = sh.parkingFk JOIN sector s ON s.id = p.sectorFk GROUP BY ish.itemFk, s.warehouseFk; @@ -69467,7 +69689,7 @@ BEGIN LEFT JOIN tItemShelvingStock_byWarehouse issw ON issw.itemFk = i.id AND issw.warehouseFk = t.warehouseFk WHERE IFNULL(v.visible, 0) < s.quantity - AND IFNULL(av.available, 0) < s.quantity + AND IFNULL(av.available, 0) < 0 AND IFNULL(issw.visible, 0) < s.quantity AND NOT s.isPicked AND NOT s.reserved @@ -69530,7 +69752,7 @@ BEGIN LEFT JOIN tItemShelvingStock_byWarehouse issw ON issw.itemFk = i.id AND issw.warehouseFk = t.warehouseFk WHERE IFNULL(v.visible, 0) < s.quantity - AND IFNULL(av.available, 0) >= s.quantity + AND IFNULL(av.available, 0) >= 0 AND IFNULL(issw.visible, 0) < s.quantity AND s.quantity > 0 AND NOT s.isPicked @@ -70251,30 +70473,30 @@ DELIMITER ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; CREATE DEFINER=`vn`@`localhost` PROCEDURE `sectorCollection_new`(vSectorFk INT) -BEGIN -/** - * Inserta una nueva colección, si el usuario no tiene ninguna vacia. - * Esto se hace para evitar que por error se generen colecciones sin sentido. - * - * @param vSectorFk Identificador de #vn.sector - */ - DECLARE hasEmptyCollections BOOL; - DECLARE vUserFk INT; - - SET vUserFk = account.myUser_getId(); - - SELECT (COUNT(sc.id) > 0) INTO hasEmptyCollections - FROM vn.sectorCollection sc - LEFT JOIN vn.sectorCollectionSaleGroup scsg ON scsg.sectorCollectionFk = sc.id - WHERE ISNULL(scsg.id) - AND sc.userFk = vUserFk - AND sc.sectorFk = vSectorFk - AND sc.created >= util.VN_CURDATE(); - - IF NOT hasEmptyCollections THEN - INSERT INTO vn.sectorCollection(userFk, sectorFk) - VALUES(vUserFk, vSectorFk); - END IF; +BEGIN +/** + * Inserta una nueva colección, si el usuario no tiene ninguna vacia. + * Esto se hace para evitar que por error se generen colecciones sin sentido. + * + * @param vSectorFk Identificador de #vn.sector + */ + DECLARE hasEmptyCollections BOOL; + DECLARE vUserFk INT; + + SET vUserFk = account.myUser_getId(); + + SELECT (COUNT(sc.id) > 0) INTO hasEmptyCollections + FROM vn.sectorCollection sc + LEFT JOIN vn.sectorCollectionSaleGroup scsg ON scsg.sectorCollectionFk = sc.id + WHERE ISNULL(scsg.id) + AND sc.userFk = vUserFk + AND sc.sectorFk = vSectorFk + AND sc.created >= util.VN_CURDATE(); + + IF NOT hasEmptyCollections THEN + INSERT INTO vn.sectorCollection(userFk, sectorFk) + VALUES(vUserFk, vSectorFk); + END IF; END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -70455,14 +70677,16 @@ DELIMITER ; /*!50003 SET character_set_results = utf8mb4 */ ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; -CREATE DEFINER=`vn`@`localhost` PROCEDURE `shelvingChange`(IN `vShelvingO` VARCHAR(8), IN `vShelvingD` VARCHAR(8)) +CREATE DEFINER=`vn`@`localhost` PROCEDURE `shelvingChange`( + `vShelvingO` VARCHAR(10), + `vShelvingD` VARCHAR(10) +) BEGIN - - UPDATE vn.itemShelving - SET shelvingFk = vShelvingD COLLATE utf8_unicode_ci - WHERE shelvingFk = vShelvingO COLLATE utf8_unicode_ci; - - + UPDATE itemShelving ish + JOIN shelving sh1 ON sh1.code = vShelvingD COLLATE utf8_unicode_ci + JOIN shelving sh2 ON sh2.code = vShelvingO COLLATE utf8_unicode_ci + SET ish.shelvingFk = sh1.id + WHERE ish.shelvingFk = sh2.id; END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -70510,10 +70734,12 @@ DELIMITER ; /*!50003 SET character_set_results = utf8mb4 */ ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; -CREATE DEFINER=`vn`@`localhost` PROCEDURE `shelvingParking_get`(vShelvingFk VARCHAR(10), vWarehouseFk INT, vDayRange INT) -BEGIN - - +CREATE DEFINER=`vn`@`localhost` PROCEDURE `shelvingParking_get`( + vShelvingCode VARCHAR(10), + vWarehouseFk INT, + vDayRange INT +) +BEGIN SELECT s.itemFk, s.concept, CAST(SUM(s.quantity) AS DECIMAL(10,0)) as sinServir, @@ -70521,15 +70747,16 @@ SELECT s.itemFk, FROM vn.sale s LEFT JOIN vn.itemShelvingSale iss ON iss.saleFk = s.id JOIN vn.ticket t ON t.id = s.ticketFk - LEFT JOIN vn.itemShelvingStock ist ON ist.itemFk = s.itemFk AND ist.warehouseFk = vWarehouseFk - JOIN vn.itemShelving ish ON ish.itemFk = s.itemFk AND ish.shelvingFk = vShelvingFk COLLATE utf8_general_ci + LEFT JOIN vn.itemShelvingStock ist ON ist.itemFk = s.itemFk + AND ist.warehouseFk = vWarehouseFk + JOIN vn.itemShelving ish ON ish.itemFk = s.itemFk + JOIN shelving sh ON sh.id = ish.shelvingFk + AND sh.code = vShelvingCode COLLATE utf8_general_ci WHERE t.shipped BETWEEN util.VN_CURDATE() AND util.dayend(TIMESTAMPADD(DAY, GREATEST(0,vDayRange), util.VN_CURDATE())) AND iss.saleFk IS NULL AND t.warehouseFk = vWarehouseFk GROUP BY s.itemFk HAVING sinServir > aparcado; - - END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -70580,12 +70807,12 @@ BEGIN DELETE ish.* FROM itemShelving ish - JOIN vn.shelving sh ON sh.code = ish.shelvingFk + JOIN vn.shelving sh ON sh.id = ish.shelvingFk WHERE sh.parkingFk IS NULL AND ish.created < TIMESTAMPADD(WEEK,-1,util.VN_CURDATE()); UPDATE shelving sh - LEFT JOIN itemShelving its ON its.shelvingFk = sh.`code` + LEFT JOIN itemShelving its ON its.shelvingFk = sh.id SET isPrinted = 0, parkingFk = NULL WHERE its.id IS NULL @@ -70595,11 +70822,11 @@ UPDATE shelving sh OR sh.parked < util.VN_CURDATE() - INTERVAL 2 WEEK ) - AND IF(code REGEXP '^[A-Za-z]{2}[0-9]', LEFT (code, 2) NOT IN ( - SELECT DISTINCT LEFT(its.shelvingFk, 2) + SELECT DISTINCT LEFT(sh.code, 2) FROM itemShelving its - WHERE its.shelvingFk REGEXP '^[A-Za-z]{2}[0-9]' + JOIN shelving sh ON sh.id = its.shelvingFk + WHERE sh.code REGEXP '^[A-Za-z]{2}[0-9]' ), TRUE); END ;; @@ -70644,7 +70871,7 @@ BEGIN LEFT JOIN ( SELECT ish.itemFk, CAST(SUM(ish.visible) AS DECIMAL(10,0)) AS reserva FROM vn.itemShelving ish - JOIN vn.shelving sh ON sh.code = ish.shelvingFk + JOIN vn.shelving sh ON sh.id = ish.shelvingFk JOIN vn.parking p ON p.id = sh.parkingFk JOIN vn.sector s ON s.id = p.sectorFk WHERE s.code = 'FUENTES_PICASSE' @@ -70687,7 +70914,7 @@ BEGIN sh.isSpam FROM vn.itemShelving ish JOIN vn.item i ON i.id = ish.itemFk - JOIN vn.shelving sh ON sh.code = ish.shelvingFk + JOIN vn.shelving sh ON sh.id = ish.shelvingFk JOIN vn.parking p ON p.id = sh.parkingFk JOIN vn.sector s ON s.id = p.sectorFk JOIN vn.warehouse w ON w.id = s.warehouseFk @@ -70836,7 +71063,7 @@ proc: BEGIN INSERT INTO stockBought(workerFk, bought, dated) SELECT tb.workerFk, - ROUND(GREATEST(tb.bought - IFNULL(ts.sold, 0), 0), 1), + ROUND(GREATEST(tb.bought - IFNULL(ts.sold, 0), 0), 2), vDated FROM tStockBought tb LEFT JOIN tStockSold ts ON ts.workerFk = tb.workerFk; @@ -70857,7 +71084,7 @@ proc: BEGIN UPDATE stockBought s JOIN tStockSold ts ON ts.workerFk = s.workerFk - SET s.bought = IF(s.bought < ts.sold, ROUND(s.bought - ts.sold, 1), 0) + SET s.bought = IF(s.bought < ABS(ts.sold), 0, ROUND(s.bought - ABS(ts.sold), 1)) WHERE s.dated = vDated; DROP TEMPORARY TABLE tCurrentData, tmp.item, tmp.buyUltimate, tStockSold; @@ -70869,6 +71096,176 @@ DELIMITER ; /*!50003 SET collation_connection = @saved_col_connection */ ; /*!50003 SET @saved_sql_mode = @@sql_mode */ ; /*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; +/*!50003 DROP PROCEDURE IF EXISTS `stockBuyedByWorker` */; +/*!50003 SET @saved_cs_client = @@character_set_client */ ; +/*!50003 SET @saved_cs_results = @@character_set_results */ ; +/*!50003 SET @saved_col_connection = @@collation_connection */ ; +/*!50003 SET character_set_client = utf8mb4 */ ; +/*!50003 SET character_set_results = utf8mb4 */ ; +/*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; +DELIMITER ;; +CREATE DEFINER=`vn`@`localhost` PROCEDURE `stockBuyedByWorker`( + vDated DATE, + vWorker INT +) +BEGIN +/** + * Inserta el volumen de compra de un comprador + * en stockBuyed de acuerdo con la fecha. + * + * @param vDated Fecha de compra + * @param vWorker Id de trabajador + */ + CREATE OR REPLACE TEMPORARY TABLE tStockBuyed + (INDEX (userFk)) + ENGINE = MEMORY + SELECT requested, reserved, userFk + FROM stockBuyed + WHERE dated = vDated + AND userFk = vWorker; + + DELETE FROM stockBuyed + WHERE dated = vDated + AND userFk = vWorker; + + CALL item_calculateStock(vDated); + + INSERT INTO stockBuyed(userFk, buyed, `dated`, reserved, requested, description) + SELECT it.workerFk, + SUM((ti.quantity / b.packing) * buy_getVolume(b.id)) / vc.palletM3 / 1000000, + vDated, + sb.reserved, + sb.requested, + u.name + FROM itemType it + JOIN item i ON i.typeFk = it.id + LEFT JOIN tmp.item ti ON ti.itemFk = i.id + JOIN itemCategory ic ON ic.id = it.categoryFk + JOIN warehouse wh ON wh.code = 'VNH' + JOIN tmp.buyUltimate bu ON bu.itemFk = i.id + AND bu.warehouseFk = wh.id + JOIN buy b ON b.id = bu.buyFk + JOIN volumeConfig vc + JOIN account.`user` u ON u.id = it.workerFk + LEFT JOIN tStockBuyed sb ON sb.userFk = it.workerFk + WHERE ic.display + AND it.workerFk = vWorker; + + SELECT b.entryFk Id_Entrada, + i.id Id_Article, + i.name Article, + ti.quantity Cantidad, + (ac.conversionCoefficient * (ti.quantity / b.packing) * buy_getVolume(b.id)) + / (vc.trolleyM3 * 1000000) buyed, + b.packagingFk id_cubo, + b.packing + FROM tmp.item ti + JOIN item i ON i.id = ti.itemFk + JOIN itemType it ON i.typeFk = it.id + JOIN itemCategory ic ON ic.id = it.categoryFk + JOIN worker w ON w.id = it.workerFk + JOIN auctionConfig ac + JOIN tmp.buyUltimate bu ON bu.itemFk = i.id + AND bu.warehouseFk = ac.warehouseFk + JOIN buy b ON b.id = bu.buyFk + JOIN volumeConfig vc + WHERE ic.display + AND w.id = vWorker; + + DROP TEMPORARY TABLE tmp.buyUltimate, + tmp.item, + tStockBuyed; +END ;; +DELIMITER ; +/*!50003 SET sql_mode = @saved_sql_mode */ ; +/*!50003 SET character_set_client = @saved_cs_client */ ; +/*!50003 SET character_set_results = @saved_cs_results */ ; +/*!50003 SET collation_connection = @saved_col_connection */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; +/*!50003 DROP PROCEDURE IF EXISTS `stockBuyed_add` */; +/*!50003 SET @saved_cs_client = @@character_set_client */ ; +/*!50003 SET @saved_cs_results = @@character_set_results */ ; +/*!50003 SET @saved_col_connection = @@collation_connection */ ; +/*!50003 SET character_set_client = utf8mb4 */ ; +/*!50003 SET character_set_results = utf8mb4 */ ; +/*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; +DELIMITER ;; +CREATE DEFINER=`vn`@`localhost` PROCEDURE `stockBuyed_add`( + vDated DATE +) +BEGIN +/** + * Inserta el volumen de compra por comprador + * en stockBuyed de acuerdo con la fecha. + * + * @param vDated Fecha de compra + */ + CREATE OR REPLACE TEMPORARY TABLE tStockBuyed + (INDEX (userFk)) + ENGINE = MEMORY + SELECT requested, reserved, userFk + FROM stockBuyed + WHERE dated = vDated; + + DELETE FROM stockBuyed WHERE dated = vDated; + + CALL item_calculateStock(vDated); + + INSERT INTO stockBuyed(userFk, buyed, `dated`, description) + SELECT it.workerFk, + SUM((ti.quantity / b.packing) * buy_getVolume(b.id)) / vc.palletM3 / 1000000, + vDated, + u.name + FROM itemType it + JOIN item i ON i.typeFk = it.id + LEFT JOIN tmp.item ti ON ti.itemFk = i.id + JOIN itemCategory ic ON ic.id = it.categoryFk + JOIN warehouse wh ON wh.code = 'VNH' + JOIN tmp.buyUltimate bu ON bu.itemFk = i.id AND bu.warehouseFk = wh.id + JOIN buy b ON b.id = bu.buyFk + JOIN volumeConfig vc + JOIN account.`user` u ON u.id = it.workerFk + JOIN workerDepartment wd ON wd.workerFk = u.id + JOIN department d ON d.id = wd.departmentFk + WHERE ic.display + AND d.code IN ('shopping', 'logistic', 'franceTeam') + GROUP BY it.workerFk; + + INSERT INTO stockBuyed(buyed, dated, description) + SELECT SUM(ic.cm3 * ito.quantity / vc.palletM3 / 1000000), + vDated, + IF(c.code = 'ES', p.name, c.name) destiny + FROM itemTicketOut ito + JOIN ticket t ON t.id = ito.ticketFk + JOIN `address` a ON a.id = t.addressFk + JOIN province p ON p.id = a.provinceFk + JOIN country c ON c.id = p.countryFk + JOIN warehouse wh ON wh.id = t.warehouseFk + JOIN itemCost ic ON ic.itemFk = ito.itemFk + AND ic.warehouseFk = t.warehouseFk + JOIN volumeConfig vc + WHERE ito.shipped BETWEEN vDated AND util.dayend(vDated) + AND wh.code = 'VNH' + GROUP BY destiny; + + UPDATE stockBuyed s + JOIN tStockBuyed ts ON ts.userFk = s.userFk + SET s.requested = ts.requested, + s.reserved = ts.reserved + WHERE s.dated = vDated; + + DROP TEMPORARY TABLE tmp.buyUltimate, + tmp.item, + tStockBuyed; +END ;; +DELIMITER ; +/*!50003 SET sql_mode = @saved_sql_mode */ ; +/*!50003 SET character_set_client = @saved_cs_client */ ; +/*!50003 SET character_set_results = @saved_cs_results */ ; +/*!50003 SET collation_connection = @saved_col_connection */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; /*!50003 DROP PROCEDURE IF EXISTS `subordinateGetList` */; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; @@ -72060,7 +72457,7 @@ BEGIN JOIN vn.sale s ON s.ticketFk = t.id JOIN vn.itemShelvingSale iss ON iss.saleFk = s.id JOIN vn.itemShelving ish ON ish.id = iss.itemShelvingFk - JOIN vn.shelving sh ON sh.code = ish.shelvingFk + JOIN vn.shelving sh ON sh.id = ish.shelvingFk JOIN vn.parking p ON p.id = sh.parkingFk WHERE p.sectorFk = vSectorFk ) sub ON sub.id = td.ticketFk @@ -74173,62 +74570,62 @@ DELIMITER ; /*!50003 SET character_set_results = utf8mb4 */ ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; -CREATE DEFINER=`vn`@`localhost` PROCEDURE `ticket_DelayTruckSplit`( - vTicketFk INT +CREATE DEFINER=`vn`@`localhost` PROCEDURE `ticket_DelayTruckSplit`( + vTicketFk INT ) -BEGIN -/** - * Splita las lineas de ticket que no estan ubicadas - * - * @param vTicketFk Id ticket - */ - DECLARE vNewTicketFk INT; - DECLARE vTotalLines INT; - DECLARE vLinesToSplit INT; - - DROP TEMPORARY TABLE IF EXISTS tmp.SalesToSplit; - - SELECT COUNT(*) INTO vTotalLines - FROM sale - WHERE ticketFk = vTicketFk; - - CREATE TEMPORARY TABLE tmp.SalesToSplit - SELECT s.id saleFk - FROM ticket t - JOIN sale s ON t.id = s.ticketFk - LEFT JOIN ( - SELECT ish.itemFk itemFk, - SUM(ish.visible) visible, - s.warehouseFk warehouseFk - FROM itemShelving ish - JOIN shelving sh ON sh.code = ish.shelvingFk - JOIN parking p ON p.id = sh.parkingFk - JOIN sector s ON s.id = p.sectorFk - GROUP BY ish.itemFk, - s.warehouseFk - ) issw ON issw.itemFk = s.itemFk - AND issw.warehouseFk = t.warehouseFk - WHERE s.quantity > IFNULL(issw.visible, 0) - AND s.quantity > 0 - AND NOT s.isPicked - AND NOT s.reserved - AND t.id = vTicketFk; - - SELECT COUNT(*) INTO vLinesToSplit - FROM tmp.SalesToSplit; - - IF vLinesToSplit = vTotalLines AND vLinesToSplit > 0 THEN - SET vNewTicketFk = vTicketFk; - ELSE - CALL ticket_Clone(vTicketFk, vNewTicketFk); - UPDATE sale s - JOIN tmp.SalesToSplit sts ON sts.saleFk = s.id - SET s.ticketFk = vNewTicketFk; - END IF; - - CALL ticket_setState(vNewTicketFk, 'FIXING'); - - DROP TEMPORARY TABLE tmp.SalesToSplit; +BEGIN +/** + * Splita las lineas de ticket que no estan ubicadas + * + * @param vTicketFk Id ticket + */ + DECLARE vNewTicketFk INT; + DECLARE vTotalLines INT; + DECLARE vLinesToSplit INT; + + DROP TEMPORARY TABLE IF EXISTS tmp.SalesToSplit; + + SELECT COUNT(*) INTO vTotalLines + FROM sale + WHERE ticketFk = vTicketFk; + + CREATE TEMPORARY TABLE tmp.SalesToSplit + SELECT s.id saleFk + FROM ticket t + JOIN sale s ON t.id = s.ticketFk + LEFT JOIN ( + SELECT ish.itemFk itemFk, + SUM(ish.visible) visible, + s.warehouseFk warehouseFk + FROM itemShelving ish + JOIN shelving sh ON sh.id = ish.shelvingFk + JOIN parking p ON p.id = sh.parkingFk + JOIN sector s ON s.id = p.sectorFk + GROUP BY ish.itemFk, + s.warehouseFk + ) issw ON issw.itemFk = s.itemFk + AND issw.warehouseFk = t.warehouseFk + WHERE s.quantity > IFNULL(issw.visible, 0) + AND s.quantity > 0 + AND NOT s.isPicked + AND NOT s.reserved + AND t.id = vTicketFk; + + SELECT COUNT(*) INTO vLinesToSplit + FROM tmp.SalesToSplit; + + IF vLinesToSplit = vTotalLines AND vLinesToSplit > 0 THEN + SET vNewTicketFk = vTicketFk; + ELSE + CALL ticket_Clone(vTicketFk, vNewTicketFk); + UPDATE sale s + JOIN tmp.SalesToSplit sts ON sts.saleFk = s.id + SET s.ticketFk = vNewTicketFk; + END IF; + + CALL ticket_setState(vNewTicketFk, 'FIXING'); + + DROP TEMPORARY TABLE tmp.SalesToSplit; END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -74246,84 +74643,84 @@ DELIMITER ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; CREATE DEFINER=`vn`@`localhost` PROCEDURE `ticket_doCmr`(vSelf INT) -BEGIN -/** -* Crea u actualiza la información del CMR asociado con -* un ticket específico en caso de que sea necesario. -* -* @param vSelf El id del ticket -*/ - DECLARE vCmrFk INT; - SELECT cmrFk INTO vCmrFk - FROM ticket - WHERE id = vSelf; - - CREATE OR REPLACE TEMPORARY TABLE tTicket - SELECT wo.firstName, - v.numberPlate, - com.id companyFk, - a.id addressFk, - c2.defaultAddressFk, - IFNULL(sat.supplierFk, su.id) supplierFk, - t.landed - FROM ticket t - JOIN ticketState ts ON ts.ticketFk = t.id - JOIN `state` s ON s.id = ts.stateFk - JOIN alertLevel al ON al.id = s.alertLevel - JOIN client c ON c.id = t.clientFk - JOIN `address` a ON a.id = t.addressFk - JOIN province p ON p.id = a.provinceFk - JOIN country co ON co.id = p.countryFk - JOIN warehouse w ON w.id = t.warehouseFk - JOIN company com ON com.id = t.companyFk - JOIN client c2 ON c2.id = com.clientFk - JOIN supplierAccount sa ON sa.id = com.supplierAccountFk - JOIN supplier su ON su.id = sa.supplierFk - LEFT JOIN route r ON r.id = t.routeFk - LEFT JOIN worker wo ON wo.id = r.workerFk - LEFT JOIN vehicle v ON v.id = r.vehicleFk - LEFT JOIN agencyMode am ON am.id = r.agencyModeFk - LEFT JOIN agency ag ON ag.id = am.agencyFk - LEFT JOIN supplierAgencyTerm sat ON sat.agencyFk = ag.id - AND wo.isFreelance - WHERE al.code IN ('PACKED', 'DELIVERED') - AND co.code <> 'ES' - AND am.name <> 'ABONO' - AND w.code = 'ALG' - AND t.id = vSelf - GROUP BY t.id; - - IF vCmrFk THEN - UPDATE cmr c - JOIN tTicket t - SET c.senderInstruccions = t.firstName, - c.truckPlate = t.numberPlate, - c.companyFk = t.companyFk, - c.addressToFk = t.addressFk, - c.addressFromFk = t.defaultAddressFk, - c.supplierFk = t.supplierFk, - c.ead = t.landed - WHERE id = vCmrFk; - ELSE - INSERT INTO cmr ( - senderInstruccions, - truckPlate, - companyFk, - addressToFk, - addressFromFk, - supplierFk, - ead - ) - SELECT * FROM tTicket; - - IF (SELECT EXISTS(SELECT * FROM tTicket)) THEN - UPDATE ticket - SET cmrFk = LAST_INSERT_ID() - WHERE id = vSelf; - END IF; - END IF; - - DROP TEMPORARY TABLE tTicket; +BEGIN +/** +* Crea u actualiza la información del CMR asociado con +* un ticket específico en caso de que sea necesario. +* +* @param vSelf El id del ticket +*/ + DECLARE vCmrFk INT; + SELECT cmrFk INTO vCmrFk + FROM ticket + WHERE id = vSelf; + + CREATE OR REPLACE TEMPORARY TABLE tTicket + SELECT wo.firstName, + v.numberPlate, + com.id companyFk, + a.id addressFk, + c2.defaultAddressFk, + IFNULL(sat.supplierFk, su.id) supplierFk, + t.landed + FROM ticket t + JOIN ticketState ts ON ts.ticketFk = t.id + JOIN `state` s ON s.id = ts.stateFk + JOIN alertLevel al ON al.id = s.alertLevel + JOIN client c ON c.id = t.clientFk + JOIN `address` a ON a.id = t.addressFk + JOIN province p ON p.id = a.provinceFk + JOIN country co ON co.id = p.countryFk + JOIN warehouse w ON w.id = t.warehouseFk + JOIN company com ON com.id = t.companyFk + JOIN client c2 ON c2.id = com.clientFk + JOIN supplierAccount sa ON sa.id = com.supplierAccountFk + JOIN supplier su ON su.id = sa.supplierFk + LEFT JOIN route r ON r.id = t.routeFk + LEFT JOIN worker wo ON wo.id = r.workerFk + LEFT JOIN vehicle v ON v.id = r.vehicleFk + LEFT JOIN agencyMode am ON am.id = r.agencyModeFk + LEFT JOIN agency ag ON ag.id = am.agencyFk + LEFT JOIN supplierAgencyTerm sat ON sat.agencyFk = ag.id + AND wo.isFreelance + WHERE al.code IN ('PACKED', 'DELIVERED') + AND co.code <> 'ES' + AND am.name <> 'ABONO' + AND w.code = 'ALG' + AND t.id = vSelf + GROUP BY t.id; + + IF vCmrFk THEN + UPDATE cmr c + JOIN tTicket t + SET c.senderInstruccions = t.firstName, + c.truckPlate = t.numberPlate, + c.companyFk = t.companyFk, + c.addressToFk = t.addressFk, + c.addressFromFk = t.defaultAddressFk, + c.supplierFk = t.supplierFk, + c.ead = t.landed + WHERE id = vCmrFk; + ELSE + INSERT INTO cmr ( + senderInstruccions, + truckPlate, + companyFk, + addressToFk, + addressFromFk, + supplierFk, + ead + ) + SELECT * FROM tTicket; + + IF (SELECT EXISTS(SELECT * FROM tTicket)) THEN + UPDATE ticket + SET cmrFk = LAST_INSERT_ID() + WHERE id = vSelf; + END IF; + END IF; + + DROP TEMPORARY TABLE tTicket; END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -74643,7 +75040,7 @@ BEGIN SUM(ish.visible) visible, s.warehouseFk warehouseFk FROM itemShelving ish - JOIN shelving sh ON sh.code = ish.shelvingFk + JOIN shelving sh ON sh.id = ish.shelvingFk JOIN parking p ON p.id = sh.parkingFk JOIN sector s ON s.id = p.sectorFk GROUP BY ish.itemFk, @@ -76264,88 +76661,125 @@ CREATE DEFINER=`vn`@`localhost` PROCEDURE `ticket_splitItemPackingType`( vSelf INT, vOriginalItemPackingTypeFk VARCHAR(1) ) -proc:BEGIN +BEGIN /** - * Clona y reparte las líneas de ventas de un ticket en funcion del tipo de empaquetado. - * Respeta el id de ticket original para el tipo de empaquetado propuesto. + * Clona y reparte las ventas de un ticket en funcion del tipo de empaquetado. + * Respeta el id inicial para el tipo propuesto. * * @param vSelf Id ticket - * @param vOriginalItemPackingTypeFk Tipo empaquetado que se mantiene el ticket original + * @param vOriginalItemPackingTypeFk Tipo para el que se reserva el número de ticket original * @return table tmp.ticketIPT(ticketFk, itemPackingTypeFk) */ - DECLARE vDone INT DEFAULT FALSE; - DECLARE vHasItemPackingType BOOL; - DECLARE vItemPackingTypeFk INT; + DECLARE vItemPackingTypeFk VARCHAR(1) DEFAULT 'H'; DECLARE vNewTicketFk INT; + DECLARE vPackingTypesToSplit INT; + DECLARE vDone INT DEFAULT FALSE; - DECLARE vItemPackingTypes CURSOR FOR - SELECT DISTINCT itemPackingTypeFk - FROM tSalesToMove; + DECLARE vSaleGroup CURSOR FOR + SELECT itemPackingTypeFk + FROM tSaleGroup + WHERE itemPackingTypeFk IS NOT NULL + ORDER BY (itemPackingTypeFk = vOriginalItemPackingTypeFk) DESC; DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE; - SELECT COUNT(*) INTO vHasItemPackingType - FROM ticket t - JOIN sale s ON s.ticketFk = t.id - JOIN item i ON i.id = s.itemFk - WHERE t.id = vSelf - AND i.itemPackingTypeFk = vOriginalItemPackingTypeFk; + START TRANSACTION; + + SELECT id + FROM sale + WHERE ticketFk = vSelf + AND NOT quantity + FOR UPDATE; + + DELETE FROM sale + WHERE NOT quantity + AND ticketFk = vSelf; + + CREATE OR REPLACE TEMPORARY TABLE tSale + (PRIMARY KEY (id)) + ENGINE = MEMORY + SELECT s.id, i.itemPackingTypeFk, IFNULL(sv.litros, 0) litros + FROM sale s + JOIN item i ON i.id = s.itemFk + LEFT JOIN saleVolume sv ON sv.saleFk = s.id + WHERE s.ticketFk = vSelf; + + CREATE OR REPLACE TEMPORARY TABLE tSaleGroup + ENGINE = MEMORY + SELECT itemPackingTypeFk, SUM(litros) totalLitros + FROM tSale + GROUP BY itemPackingTypeFk; + + SELECT COUNT(*) INTO vPackingTypesToSplit + FROM tSaleGroup + WHERE itemPackingTypeFk IS NOT NULL; CREATE OR REPLACE TEMPORARY TABLE tmp.ticketIPT( ticketFk INT, itemPackingTypeFk VARCHAR(1) - ) ENGINE=MEMORY - SELECT vSelf ticketFk, vOriginalItemPackingTypeFk itemPackingTypeFk; + ) ENGINE = MEMORY; - IF NOT vHasItemPackingType THEN - LEAVE proc; - END IF; + CASE vPackingTypesToSplit + WHEN 0 THEN + INSERT INTO tmp.ticketIPT(ticketFk, itemPackingTypeFk) + VALUES(vSelf, vItemPackingTypeFk); + WHEN 1 THEN + INSERT INTO tmp.ticketIPT(ticketFk, itemPackingTypeFk) + SELECT vSelf, itemPackingTypeFk + FROM tSaleGroup + WHERE itemPackingTypeFk IS NOT NULL; + ELSE + OPEN vSaleGroup; + FETCH vSaleGroup INTO vItemPackingTypeFk; - CREATE OR REPLACE TEMPORARY TABLE tSalesToMove ( - ticketFk INT, - saleFk INT, - itemPackingTypeFk INT - ) ENGINE=MEMORY; + INSERT INTO tmp.ticketIPT(ticketFk, itemPackingTypeFk) + VALUES(vSelf, vItemPackingTypeFk); - INSERT INTO tSalesToMove (saleFk, itemPackingTypeFk) - SELECT s.id, i.itemPackingTypeFk - FROM ticket t - JOIN sale s ON s.ticketFk = t.id - JOIN item i ON i.id = s.itemFk - WHERE t.id = vSelf - AND i.itemPackingTypeFk <> vOriginalItemPackingTypeFk; + l: LOOP + SET vDone = FALSE; + FETCH vSaleGroup INTO vItemPackingTypeFk; - OPEN vItemPackingTypes; + IF vDone THEN + LEAVE l; + END IF; - l: LOOP - SET vDone = FALSE; - FETCH vItemPackingTypes INTO vItemPackingTypeFk; + CALL ticket_Clone(vSelf, vNewTicketFk); - IF vDone THEN - LEAVE l; - END IF; + INSERT INTO tmp.ticketIPT(ticketFk, itemPackingTypeFk) + VALUES(vNewTicketFk, vItemPackingTypeFk); + END LOOP; - CALL ticket_Clone(vSelf, vNewTicketFk); + CLOSE vSaleGroup; - UPDATE tSalesToMove - SET ticketFk = vNewTicketFk - WHERE itemPackingTypeFk = vItemPackingTypeFk; + SELECT s.id + FROM sale s + JOIN tSale ts ON ts.id = s.id + JOIN tmp.ticketIPT t ON t.itemPackingTypeFk = ts.itemPackingTypeFk + FOR UPDATE; - END LOOP; + UPDATE sale s + JOIN tSale ts ON ts.id = s.id + JOIN tmp.ticketIPT t ON t.itemPackingTypeFk = ts.itemPackingTypeFk + SET s.ticketFk = t.ticketFk; - CLOSE vItemPackingTypes; + SELECT itemPackingTypeFk INTO vItemPackingTypeFk + FROM tSaleGroup sg + WHERE sg.itemPackingTypeFk IS NOT NULL + ORDER BY sg.itemPackingTypeFk + LIMIT 1; - UPDATE sale s - JOIN tSalesToMove stm ON stm.saleFk = s.id - SET s.ticketFk = stm.ticketFk - WHERE stm.ticketFk; + UPDATE sale s + JOIN tSale ts ON ts.id = s.id + JOIN tmp.ticketIPT t ON t.itemPackingTypeFk = vItemPackingTypeFk + SET s.ticketFk = t.ticketFk + WHERE ts.itemPackingTypeFk IS NULL; + END CASE; - INSERT INTO tmp.ticketIPT (ticketFk, itemPackingTypeFk) - SELECT ticketFk, itemPackingTypeFk - FROM tSalesToMove - GROUP BY ticketFk; + COMMIT; - DROP TEMPORARY TABLE tSalesToMove; + DROP TEMPORARY TABLE + tSale, + tSaleGroup; END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -77324,7 +77758,7 @@ BEGIN JOIN vn.entry e ON e.travelFk = tr.id JOIN vn.buy b ON b.entryFk = e.id WHERE tr.landed BETWEEN vFromDated AND vToDated - AND e.isRaid = FALSE + AND NOT tr.isRaid AND tr.warehouseInFk = vWarehouseFk GROUP BY tr.landed , a.name ; END ;; @@ -77408,6 +77842,36 @@ DELIMITER ; /*!50003 SET collation_connection = @saved_col_connection */ ; /*!50003 SET @saved_sql_mode = @@sql_mode */ ; /*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; +/*!50003 DROP PROCEDURE IF EXISTS `travel_checkRaid` */; +/*!50003 SET @saved_cs_client = @@character_set_client */ ; +/*!50003 SET @saved_cs_results = @@character_set_results */ ; +/*!50003 SET @saved_col_connection = @@collation_connection */ ; +/*!50003 SET character_set_client = utf8mb4 */ ; +/*!50003 SET character_set_results = utf8mb4 */ ; +/*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; +DELIMITER ;; +CREATE DEFINER=`vn`@`localhost` PROCEDURE `travel_checkRaid`( + vIsRaid BOOL, + vDaysInForward INT +) +BEGIN +/** + * Check if the values of isRaid and daysInforward are correct + * + * @param vIsRaid idRaid value + * @param vDaysInForward daysInForward value + */ + IF (NOT vIsRaid AND vDaysInForward IS NOT NULL) OR (vIsRaid AND vDaysInForward IS NULL) THEN + CALL util.throw('The raid information is not correct'); + END IF; +END ;; +DELIMITER ; +/*!50003 SET sql_mode = @saved_sql_mode */ ; +/*!50003 SET character_set_client = @saved_cs_client */ ; +/*!50003 SET character_set_results = @saved_cs_results */ ; +/*!50003 SET collation_connection = @saved_col_connection */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; /*!50003 DROP PROCEDURE IF EXISTS `travel_checkWarehouseIsFeedStock` */; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; @@ -77570,7 +78034,7 @@ BEGIN END IF; CALL entry_cloneHeader(vAuxEntryFk, vNewEntryFk, vNewTravelFk); - CALL entry_copyBuys(vAuxEntryFk, vNewEntryFk); + CALL entry_copyBuys(vAuxEntryFk, vNewEntryFk); SELECT evaNotes INTO vEvaNotes FROM entry @@ -77579,6 +78043,8 @@ BEGIN UPDATE entry SET evaNotes = vEvaNotes WHERE id = vNewEntryFk; + + CALL buy_recalcPricesByEntry(vNewEntryFk); END LOOP; SET @isModeInventory = FALSE; @@ -77756,73 +78222,70 @@ DELIMITER ; DELIMITER ;; CREATE DEFINER=`vn`@`localhost` PROCEDURE `travel_moveRaids`() BEGIN - -/* - * Desplaza al dia siguiente los travels que contengan redadas y avisa a los compradores - * +/** + * Desplaza los travels en el futuro y avisa a los compradores + * */ DECLARE vDone BOOL DEFAULT FALSE; - DECLARE vWorkerName VARCHAR(50); - DECLARE vRaid TEXT; - DECLARE vWorker VARCHAR(50) DEFAULT ''; + DECLARE vBuyerEmail VARCHAR(40); + DECLARE vTravelLink TEXT; DECLARE vMailBody TEXT DEFAULT ''; DECLARE vCur CURSOR FOR - SELECT GROUP_CONCAT( DISTINCT CONCAT('https://salix.verdnatura.es/#!/travel/', ttr.id, '/summary ') ORDER BY ttr.id SEPARATOR '\n\r'), - u.name - FROM tmp.travel ttr - JOIN entry e ON e.travelFk = ttr.id + SELECT GROUP_CONCAT(DISTINCT + CONCAT('https://salix.verdnatura.es/#!/travel/', + ttm.travelFk, + '/summary ') + ORDER BY ttm.travelFk SEPARATOR '\n\r') travelLink, + CONCAT(u.name, '@verdnatura.es') buyerEmail + FROM tTravelToMove ttm + JOIN entry e ON e.travelFk = ttm.travelFk JOIN buy b ON b.entryFk = e.id JOIN item i ON i.id = b.itemFk JOIN itemType it ON it.id = i.typeFk JOIN account.user u ON u.id = it.workerFk GROUP BY u.name; - DECLARE CONTINUE HANDLER FOR NOT FOUND - SET vDone = TRUE; + DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE; DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN ROLLBACK; RESIGNAL; END; - - DROP TEMPORARY TABLE IF EXISTS tmp.travel; - CREATE TEMPORARY TABLE tmp.travel - SELECT tr.id,tr.landed - FROM travel tr - JOIN entry e ON e.travelFk = tr.id - WHERE tr.landed = util.tomorrow() - AND e.isRaid - GROUP BY tr.id; + + CREATE OR REPLACE TEMPORARY TABLE tTravelToMove + SELECT id travelFk, + util.VN_CURDATE() + INTERVAL daysInForward DAY newLanded + FROM travel + WHERE isRaid + AND daysInForward; START TRANSACTION; UPDATE travel tr - JOIN tmp.travel ttr ON ttr.id = tr.id - SET tr.landed = TIMESTAMPADD(DAY, 1, tr.landed); + JOIN tTravelToMove ttm ON ttm.travelFk = tr.id + SET tr.landed = ttm.newLanded; OPEN vCur; l: LOOP SET vDone = FALSE; - FETCH vCur INTO vRaid, vWorkerName; + FETCH vCur INTO vTravelLink, vBuyerEmail; IF vDone THEN LEAVE l; END IF; - CALL `vn`.`mail_insert`(CONCAT(vWorkerName, '@verdnatura.es'), - 'noreply@verdnatura.es', - 'Cambio de fecha en Redadas', - CONCAT('Se ha movido las siguientes redadas: \n\r ', vRaid) - ); - + CALL `vn`.`mail_insert`( + vBuyerEmail, + 'noreply@verdnatura.es', + 'Cambio de fecha en Redadas', + CONCAT('Se ha movido los siguientes travels: \n\r ', vTravelLink)); END LOOP; CLOSE vCur; COMMIT; - DROP TEMPORARY TABLE tmp.travel; - + DROP TEMPORARY TABLE tTravelToMove; END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -81979,126 +82442,126 @@ DELIMITER ; /*!50003 SET character_set_results = utf8mb4 */ ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; -CREATE DEFINER=`vn`@`localhost` PROCEDURE `zone_getLeaves`( - vSelf INT, - vParentFk INT, - vSearch VARCHAR(255), - vHasInsert BOOL +CREATE DEFINER=`vn`@`localhost` PROCEDURE `zone_getLeaves`( + vSelf INT, + vParentFk INT, + vSearch VARCHAR(255), + vHasInsert BOOL ) -BEGIN -/** - * Devuelve las ubicaciones incluidas en la ruta y que sean hijos de parentFk. - * @param vSelf Id de la zona - * @param vParentFk Id del geo a calcular - * @param vSearch Cadena a buscar - * @param vHasInsert Indica si inserta en tmp.zoneNodes - * Optional @table tmp.zoneNodes(geoFk, name, parentFk, sons, isChecked, zoneFk) - */ - DECLARE vIsNumber BOOL; - DECLARE vIsSearch BOOL DEFAULT vSearch IS NOT NULL AND vSearch <> ''; - - CREATE OR REPLACE TEMPORARY TABLE tNodes - (UNIQUE (id)) - ENGINE = MEMORY - SELECT id - FROM zoneGeo - LIMIT 0; - - IF vIsSearch THEN - SET vIsNumber = vSearch REGEXP '^[0-9]+$'; - - INSERT INTO tNodes - SELECT id - FROM zoneGeo - WHERE (vIsNumber AND `name` = vSearch) - OR (!vIsNumber AND `name` LIKE CONCAT('%', vSearch, '%')) - LIMIT 1000; - - ELSEIF vParentFk IS NULL THEN - INSERT INTO tNodes - SELECT geoFk - FROM zoneIncluded - WHERE zoneFk = vSelf; - END IF; - - IF vParentFk IS NULL THEN - CREATE OR REPLACE TEMPORARY TABLE tChilds - (INDEX(id)) - ENGINE = MEMORY - SELECT id FROM tNodes; - - CREATE OR REPLACE TEMPORARY TABLE tParents - (INDEX(id)) - ENGINE = MEMORY - SELECT id FROM zoneGeo LIMIT 0; - - myLoop: LOOP - DELETE FROM tParents; - INSERT INTO tParents - SELECT parentFk id - FROM zoneGeo g - JOIN tChilds c ON c.id = g.id - WHERE g.parentFk IS NOT NULL; - - INSERT IGNORE INTO tNodes - SELECT id FROM tParents; - - IF NOT ROW_COUNT() THEN - LEAVE myLoop; - END IF; - - DELETE FROM tChilds; - INSERT INTO tChilds - SELECT id FROM tParents; - END LOOP; - - DROP TEMPORARY TABLE tChilds, tParents; - END IF; - - IF NOT vIsSearch THEN - INSERT IGNORE INTO tNodes - SELECT id - FROM zoneGeo - WHERE parentFk <=> vParentFk; - END IF; - - CREATE OR REPLACE TEMPORARY TABLE tZones - SELECT g.id, - g.name, - g.parentFk, - g.sons, - NOT g.sons OR `type` = 'country' isChecked, - i.isIncluded selected, - g.`depth`, - vSelf - FROM zoneGeo g - JOIN tNodes n ON n.id = g.id - LEFT JOIN zoneIncluded i ON i.geoFk = g.id - AND i.zoneFk = vSelf - ORDER BY g.`depth`, selected DESC, g.name; - - IF vHasInsert THEN - INSERT IGNORE INTO tmp.zoneNodes(geoFk, name, parentFk, sons, isChecked, zoneFk) - SELECT id, - name, - parentFk, - sons, - isChecked, - vSelf - FROM tZones - WHERE selected - OR (selected IS NULL AND vParentFk IS NOT NULL); - ELSE - SELECT id, - name, - parentFk, - sons, - selected - FROM tZones - ORDER BY `depth`, selected DESC, name; - END IF; - - DROP TEMPORARY TABLE tNodes, tZones; +BEGIN +/** + * Devuelve las ubicaciones incluidas en la ruta y que sean hijos de parentFk. + * @param vSelf Id de la zona + * @param vParentFk Id del geo a calcular + * @param vSearch Cadena a buscar + * @param vHasInsert Indica si inserta en tmp.zoneNodes + * Optional @table tmp.zoneNodes(geoFk, name, parentFk, sons, isChecked, zoneFk) + */ + DECLARE vIsNumber BOOL; + DECLARE vIsSearch BOOL DEFAULT vSearch IS NOT NULL AND vSearch <> ''; + + CREATE OR REPLACE TEMPORARY TABLE tNodes + (UNIQUE (id)) + ENGINE = MEMORY + SELECT id + FROM zoneGeo + LIMIT 0; + + IF vIsSearch THEN + SET vIsNumber = vSearch REGEXP '^[0-9]+$'; + + INSERT INTO tNodes + SELECT id + FROM zoneGeo + WHERE (vIsNumber AND `name` = vSearch) + OR (!vIsNumber AND `name` LIKE CONCAT('%', vSearch, '%')) + LIMIT 1000; + + ELSEIF vParentFk IS NULL THEN + INSERT INTO tNodes + SELECT geoFk + FROM zoneIncluded + WHERE zoneFk = vSelf; + END IF; + + IF vParentFk IS NULL THEN + CREATE OR REPLACE TEMPORARY TABLE tChilds + (INDEX(id)) + ENGINE = MEMORY + SELECT id FROM tNodes; + + CREATE OR REPLACE TEMPORARY TABLE tParents + (INDEX(id)) + ENGINE = MEMORY + SELECT id FROM zoneGeo LIMIT 0; + + myLoop: LOOP + DELETE FROM tParents; + INSERT INTO tParents + SELECT parentFk id + FROM zoneGeo g + JOIN tChilds c ON c.id = g.id + WHERE g.parentFk IS NOT NULL; + + INSERT IGNORE INTO tNodes + SELECT id FROM tParents; + + IF NOT ROW_COUNT() THEN + LEAVE myLoop; + END IF; + + DELETE FROM tChilds; + INSERT INTO tChilds + SELECT id FROM tParents; + END LOOP; + + DROP TEMPORARY TABLE tChilds, tParents; + END IF; + + IF NOT vIsSearch THEN + INSERT IGNORE INTO tNodes + SELECT id + FROM zoneGeo + WHERE parentFk <=> vParentFk; + END IF; + + CREATE OR REPLACE TEMPORARY TABLE tZones + SELECT g.id, + g.name, + g.parentFk, + g.sons, + NOT g.sons OR `type` = 'country' isChecked, + i.isIncluded selected, + g.`depth`, + vSelf + FROM zoneGeo g + JOIN tNodes n ON n.id = g.id + LEFT JOIN zoneIncluded i ON i.geoFk = g.id + AND i.zoneFk = vSelf + ORDER BY g.`depth`, selected DESC, g.name; + + IF vHasInsert THEN + INSERT IGNORE INTO tmp.zoneNodes(geoFk, name, parentFk, sons, isChecked, zoneFk) + SELECT id, + name, + parentFk, + sons, + isChecked, + vSelf + FROM tZones + WHERE selected + OR (selected IS NULL AND vParentFk IS NOT NULL); + ELSE + SELECT id, + name, + parentFk, + sons, + selected + FROM tZones + ORDER BY `depth`, selected DESC, name; + END IF; + + DROP TEMPORARY TABLE tNodes, tZones; END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -82281,48 +82744,48 @@ DELIMITER ; /*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; DELIMITER ;; CREATE DEFINER=`vn`@`localhost` PROCEDURE `zone_getPostalCode`(vSelf INT) -BEGIN -/** - * Devuelve los códigos postales incluidos en una zona - */ - DECLARE vGeoFk INT DEFAULT NULL; - - CREATE OR REPLACE TEMPORARY TABLE tmp.zoneNodes ( - geoFk INT, - name VARCHAR(100), - parentFk INT, - sons INT, - isChecked BOOL DEFAULT 0, - zoneFk INT, - PRIMARY KEY zoneNodesPk (zoneFk, geoFk), - INDEX(geoFk)) - ENGINE = MEMORY; - - CALL zone_getLeaves(vSelf, NULL , NULL, TRUE); - - UPDATE tmp.zoneNodes - SET isChecked = 0 - WHERE parentFk IS NULL; - - myLoop: LOOP - SET vGeoFk = NULL; - SELECT geoFk INTO vGeoFk - FROM tmp.zoneNodes - WHERE NOT isChecked - LIMIT 1; - - CALL zone_getLeaves(vSelf, vGeoFk, NULL, TRUE); - UPDATE tmp.zoneNodes - SET isChecked = TRUE - WHERE geoFk = vGeoFk; - - IF vGeoFk IS NULL THEN - LEAVE myLoop; - END IF; - END LOOP; - - DELETE FROM tmp.zoneNodes - WHERE sons > 0; +BEGIN +/** + * Devuelve los códigos postales incluidos en una zona + */ + DECLARE vGeoFk INT DEFAULT NULL; + + CREATE OR REPLACE TEMPORARY TABLE tmp.zoneNodes ( + geoFk INT, + name VARCHAR(100), + parentFk INT, + sons INT, + isChecked BOOL DEFAULT 0, + zoneFk INT, + PRIMARY KEY zoneNodesPk (zoneFk, geoFk), + INDEX(geoFk)) + ENGINE = MEMORY; + + CALL zone_getLeaves(vSelf, NULL , NULL, TRUE); + + UPDATE tmp.zoneNodes + SET isChecked = 0 + WHERE parentFk IS NULL; + + myLoop: LOOP + SET vGeoFk = NULL; + SELECT geoFk INTO vGeoFk + FROM tmp.zoneNodes + WHERE NOT isChecked + LIMIT 1; + + CALL zone_getLeaves(vSelf, vGeoFk, NULL, TRUE); + UPDATE tmp.zoneNodes + SET isChecked = TRUE + WHERE geoFk = vGeoFk; + + IF vGeoFk IS NULL THEN + LEAVE myLoop; + END IF; + END LOOP; + + DELETE FROM tmp.zoneNodes + WHERE sons > 0; END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -82953,7 +83416,6 @@ SET character_set_client = utf8; 1 AS `Inventario`, 1 AS `Confirmada`, 1 AS `Pedida`, - 1 AS `Redada`, 1 AS `comision`, 1 AS `odbc_date`, 1 AS `Notas_Eva`, @@ -82973,18 +83435,6 @@ SET character_set_client = utf8; 1 AS `typeFk` */; SET character_set_client = @saved_cs_client; --- --- Temporary table structure for view `Entradas_Auto` --- - -DROP TABLE IF EXISTS `Entradas_Auto`; -/*!50001 DROP VIEW IF EXISTS `Entradas_Auto`*/; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; -/*!50001 CREATE VIEW `Entradas_Auto` AS SELECT - 1 AS `Id_Entrada` */; -SET character_set_client = @saved_cs_client; - -- -- Temporary table structure for view `Entradas_orden` -- @@ -84390,7 +84840,8 @@ SET character_set_client = utf8; 1 AS `Inventario`, 1 AS `Confirmada`, 1 AS `Pedida`, - 1 AS `Redada`, + 1 AS `isRaid`, + 1 AS `daysInForward`, 1 AS `notas`, 1 AS `Id_Proveedor`, 1 AS `shipment`, @@ -85125,7 +85576,9 @@ SET character_set_client = utf8; 1 AS `cargoSupplierFk`, 1 AS `totalEntries`, 1 AS `appointment`, - 1 AS `awbFk` */; + 1 AS `awbFk`, + 1 AS `isRaid`, + 1 AS `daysInForward` */; SET character_set_client = @saved_cs_client; -- @@ -85177,7 +85630,6 @@ SET character_set_client = utf8; 1 AS `Id_Proveedor`, 1 AS `Fecha`, 1 AS `Confirmada`, - 1 AS `Redada`, 1 AS `empresa_id`, 1 AS `travel_id`, 1 AS `Pedida`, @@ -85341,7 +85793,7 @@ USE `account`; /*!50001 SET collation_connection = utf8mb4_unicode_ci */; /*!50001 CREATE ALGORITHM=UNDEFINED */ /*!50013 DEFINER=`root`@`localhost` SQL SECURITY DEFINER */ -/*!50001 VIEW `myUser` AS select `u`.`id` AS `id`,`u`.`name` AS `name`,`u`.`active` AS `active`,`u`.`email` AS `email`,`u`.`nickname` AS `nickname`,`u`.`lang` AS `lang`,`u`.`role` AS `role`,`u`.`recoverPass` AS `recoverPass` from `user` `u` where `u`.`name` = `myUser_getName`() */ +/*!50001 VIEW `myUser` AS select `u`.`id` AS `id`,`u`.`name` AS `name`,`u`.`active` AS `active`,`u`.`email` AS `email`,`u`.`nickname` AS `nickname`,`u`.`lang` AS `lang`,`u`.`role` AS `role` from `user` `u` where `u`.`name` = `myUser_getName`() */ /*!50002 WITH CASCADED CHECK OPTION */; /*!50001 SET character_set_client = @saved_cs_client */; /*!50001 SET character_set_results = @saved_cs_results */; @@ -87154,7 +87606,7 @@ USE `vn`; /*!50001 SET collation_connection = utf8mb4_unicode_ci */; /*!50001 CREATE ALGORITHM=UNDEFINED */ /*!50013 DEFINER=`vn`@`localhost` SQL SECURITY DEFINER */ -/*!50001 VIEW `itemEntryIn` AS select `t`.`warehouseInFk` AS `warehouseInFk`,`t`.`landed` AS `landed`,`b`.`itemFk` AS `itemFk`,`b`.`quantity` AS `quantity`,`t`.`isReceived` AS `isReceived`,`e`.`isRaid` AS `isVirtualStock`,`e`.`id` AS `entryFk` from ((`buy` `b` join `entry` `e` on(`b`.`entryFk` = `e`.`id`)) join `travel` `t` on(`e`.`travelFk` = `t`.`id`)) where `e`.`isExcludedFromAvailable` = 0 and `b`.`quantity` <> 0 */; +/*!50001 VIEW `itemEntryIn` AS select `t`.`warehouseInFk` AS `warehouseInFk`,`t`.`landed` AS `landed`,`b`.`itemFk` AS `itemFk`,`b`.`quantity` AS `quantity`,`t`.`isReceived` AS `isReceived`,`t`.`isRaid` AS `isVirtualStock`,`e`.`id` AS `entryFk` from ((`buy` `b` join `entry` `e` on(`b`.`entryFk` = `e`.`id`)) join `travel` `t` on(`e`.`travelFk` = `t`.`id`)) where `e`.`isExcludedFromAvailable` = 0 and `b`.`quantity` <> 0 */; /*!50001 SET character_set_client = @saved_cs_client */; /*!50001 SET character_set_results = @saved_cs_results */; /*!50001 SET collation_connection = @saved_col_connection */; @@ -87172,7 +87624,7 @@ USE `vn`; /*!50001 SET collation_connection = utf8mb4_unicode_ci */; /*!50001 CREATE ALGORITHM=UNDEFINED */ /*!50013 DEFINER=`vn`@`localhost` SQL SECURITY DEFINER */ -/*!50001 VIEW `itemEntryOut` AS select `t`.`warehouseOutFk` AS `warehouseOutFk`,`t`.`shipped` AS `shipped`,`b`.`itemFk` AS `itemFk`,-`b`.`quantity` AS `quantity`,`t`.`isDelivered` AS `isDelivered`,`e`.`id` AS `entryFk` from ((`buy` `b` join `entry` `e` on(`b`.`entryFk` = `e`.`id`)) join `travel` `t` on(`e`.`travelFk` = `t`.`id`)) where `e`.`isExcludedFromAvailable` = 0 and `e`.`isRaid` = 0 and `b`.`quantity` <> 0 */; +/*!50001 VIEW `itemEntryOut` AS select `t`.`warehouseOutFk` AS `warehouseOutFk`,`t`.`shipped` AS `shipped`,`b`.`itemFk` AS `itemFk`,-`b`.`quantity` AS `quantity`,`t`.`isDelivered` AS `isDelivered`,`e`.`id` AS `entryFk` from ((`buy` `b` join `entry` `e` on(`b`.`entryFk` = `e`.`id`)) join `travel` `t` on(`e`.`travelFk` = `t`.`id`)) where `e`.`isExcludedFromAvailable` = 0 and `t`.`isRaid` = 0 and `b`.`quantity` <> 0 */; /*!50001 SET character_set_client = @saved_cs_client */; /*!50001 SET character_set_results = @saved_cs_results */; /*!50001 SET collation_connection = @saved_col_connection */; @@ -87280,7 +87732,7 @@ USE `vn`; /*!50001 SET collation_connection = utf8mb4_unicode_ci */; /*!50001 CREATE ALGORITHM=UNDEFINED */ /*!50013 DEFINER=`vn`@`localhost` SQL SECURITY DEFINER */ -/*!50001 VIEW `itemShelvingList` AS select `ish`.`shelvingFk` AS `shelvingFk`,`ish`.`visible` AS `visible`,`ish`.`created` AS `created`,`pk`.`code` AS `parking`,`ish`.`itemFk` AS `itemFk`,`i`.`longName` AS `longName`,`i`.`size` AS `size`,`i`.`subName` AS `subName`,`sh`.`parked` AS `parked`,`pk`.`sectorFk` AS `sectorFk` from (((`itemShelving` `ish` join `shelving` `sh` on(`sh`.`code` = `ish`.`shelvingFk`)) join `item` `i` on(`i`.`id` = `ish`.`itemFk`)) left join `parking` `pk` on(`pk`.`id` = `sh`.`parkingFk`)) order by `ish`.`created` */; +/*!50001 VIEW `itemShelvingList` AS select `ish`.`shelvingFk` AS `shelvingFk`,`ish`.`visible` AS `visible`,`ish`.`created` AS `created`,`pk`.`code` AS `parking`,`ish`.`itemFk` AS `itemFk`,`i`.`longName` AS `longName`,`i`.`size` AS `size`,`i`.`subName` AS `subName`,`sh`.`parked` AS `parked`,`pk`.`sectorFk` AS `sectorFk` from (((`itemShelving` `ish` join `shelving` `sh` on(`sh`.`id` = `ish`.`shelvingFk`)) join `item` `i` on(`i`.`id` = `ish`.`itemFk`)) left join `parking` `pk` on(`pk`.`id` = `sh`.`parkingFk`)) order by `ish`.`created` */; /*!50001 SET character_set_client = @saved_cs_client */; /*!50001 SET character_set_results = @saved_cs_results */; /*!50001 SET collation_connection = @saved_col_connection */; @@ -87298,7 +87750,7 @@ USE `vn`; /*!50001 SET collation_connection = utf8mb4_unicode_ci */; /*!50001 CREATE ALGORITHM=UNDEFINED */ /*!50013 DEFINER=`vn`@`localhost` SQL SECURITY DEFINER */ -/*!50001 VIEW `itemShelvingPlacementSupplyStock` AS select `ish`.`id` AS `itemShelvingFk`,`ish`.`itemFk` AS `itemFk`,`ish`.`packing` AS `packing`,`ish`.`visible` AS `stock`,`i`.`longName` AS `longName`,`i`.`size` AS `size`,`i`.`subName` AS `subName`,`sh`.`code` AS `shelving`,`p`.`code` AS `parking`,`ish`.`created` AS `created`,ifnull(`sh`.`priority`,1) AS `priority`,`p`.`id` AS `parkingFk`,`p`.`sectorFk` AS `sectorFk` from (((`itemShelving` `ish` join `shelving` `sh` on(`sh`.`code` = `ish`.`shelvingFk`)) left join `parking` `p` on(`p`.`id` = `sh`.`parkingFk`)) join `item` `i` on(`i`.`id` = `ish`.`itemFk`)) group by `ish`.`id` */; +/*!50001 VIEW `itemShelvingPlacementSupplyStock` AS select `ish`.`id` AS `itemShelvingFk`,`ish`.`itemFk` AS `itemFk`,`ish`.`packing` AS `packing`,`ish`.`visible` AS `stock`,`i`.`longName` AS `longName`,`i`.`size` AS `size`,`i`.`subName` AS `subName`,`sh`.`code` AS `shelving`,`p`.`code` AS `parking`,`ish`.`created` AS `created`,ifnull(`sh`.`priority`,1) AS `priority`,`p`.`id` AS `parkingFk`,`p`.`sectorFk` AS `sectorFk` from (((`itemShelving` `ish` join `shelving` `sh` on(`sh`.`id` = `ish`.`shelvingFk`)) left join `parking` `p` on(`p`.`id` = `sh`.`parkingFk`)) join `item` `i` on(`i`.`id` = `ish`.`itemFk`)) group by `ish`.`id` */; /*!50001 SET character_set_client = @saved_cs_client */; /*!50001 SET character_set_results = @saved_cs_results */; /*!50001 SET collation_connection = @saved_col_connection */; @@ -87316,7 +87768,7 @@ USE `vn`; /*!50001 SET collation_connection = utf8mb4_unicode_ci */; /*!50001 CREATE ALGORITHM=UNDEFINED */ /*!50013 DEFINER=`vn`@`localhost` SQL SECURITY DEFINER */ -/*!50001 VIEW `itemShelvingSaleSum` AS select `iss`.`id` AS `id`,`iss`.`itemShelvingFk` AS `itemShelvingFk`,`iss`.`saleFk` AS `saleFk`,sum(`iss`.`quantity`) AS `quantity`,`iss`.`created` AS `created`,`p`.`sectorFk` AS `sectorFk` from (((`itemShelvingSale` `iss` join `itemShelving` `ish` on(`ish`.`id` = `iss`.`itemShelvingFk`)) join `shelving` `sh` on(`sh`.`code` = `ish`.`shelvingFk`)) join `parking` `p` on(`p`.`id` = `sh`.`parkingFk`)) group by `iss`.`saleFk` */; +/*!50001 VIEW `itemShelvingSaleSum` AS select `iss`.`id` AS `id`,`iss`.`itemShelvingFk` AS `itemShelvingFk`,`iss`.`saleFk` AS `saleFk`,sum(`iss`.`quantity`) AS `quantity`,`iss`.`created` AS `created`,`p`.`sectorFk` AS `sectorFk` from (((`itemShelvingSale` `iss` join `itemShelving` `ish` on(`ish`.`id` = `iss`.`itemShelvingFk`)) join `shelving` `sh` on(`sh`.`id` = `ish`.`shelvingFk`)) join `parking` `p` on(`p`.`id` = `sh`.`parkingFk`)) group by `iss`.`saleFk` */; /*!50001 SET character_set_client = @saved_cs_client */; /*!50001 SET character_set_results = @saved_cs_results */; /*!50001 SET collation_connection = @saved_col_connection */; @@ -87334,7 +87786,7 @@ USE `vn`; /*!50001 SET collation_connection = utf8mb4_unicode_ci */; /*!50001 CREATE ALGORITHM=UNDEFINED */ /*!50013 DEFINER=`vn`@`localhost` SQL SECURITY DEFINER */ -/*!50001 VIEW `itemShelvingStock` AS select `ish`.`itemFk` AS `itemFk`,sum(`ish`.`visible`) AS `visible`,min(`ish`.`packing`) AS `packing`,min(`ish`.`grouping`) AS `grouping`,`s`.`description` AS `sector`,sum(`ish`.`visible`) AS `visibleOriginal`,0 AS `removed`,`p`.`sectorFk` AS `sectorFk`,`s`.`warehouseFk` AS `warehouseFk`,`ish`.`shelvingFk` AS `shelvingFk`,`p`.`code` AS `parkingCode`,`sh`.`parkingFk` AS `parkingFk`,`ish`.`id` AS `itemShelvingFk`,`ish`.`created` AS `created`,`st`.`code` = 'previousPrepared' AS `isPreviousPrepared` from ((((`itemShelving` `ish` left join `shelving` `sh` on(`sh`.`code` = `ish`.`shelvingFk`)) left join `parking` `p` on(`p`.`id` = `sh`.`parkingFk`)) left join `sector` `s` on(`s`.`id` = `p`.`sectorFk`)) left join `sectorType` `st` on(`st`.`id` = `s`.`typeFk`)) where `ish`.`visible` <> 0 and `p`.`sectorFk` <> 0 group by `ish`.`itemFk`,`p`.`sectorFk` */; +/*!50001 VIEW `itemShelvingStock` AS select `ish`.`itemFk` AS `itemFk`,sum(`ish`.`visible`) AS `visible`,min(`ish`.`packing`) AS `packing`,min(`ish`.`grouping`) AS `grouping`,`s`.`description` AS `sector`,sum(`ish`.`visible`) AS `visibleOriginal`,0 AS `removed`,`p`.`sectorFk` AS `sectorFk`,`s`.`warehouseFk` AS `warehouseFk`,`ish`.`shelvingFk` AS `shelvingFk`,`p`.`code` AS `parkingCode`,`sh`.`parkingFk` AS `parkingFk`,`ish`.`id` AS `itemShelvingFk`,`ish`.`created` AS `created`,`st`.`code` = 'previousPrepared' AS `isPreviousPrepared` from ((((`itemShelving` `ish` left join `shelving` `sh` on(`sh`.`id` = `ish`.`shelvingFk`)) left join `parking` `p` on(`p`.`id` = `sh`.`parkingFk`)) left join `sector` `s` on(`s`.`id` = `p`.`sectorFk`)) left join `sectorType` `st` on(`st`.`id` = `s`.`typeFk`)) where `ish`.`visible` <> 0 and `p`.`sectorFk` <> 0 group by `ish`.`itemFk`,`p`.`sectorFk` */; /*!50001 SET character_set_client = @saved_cs_client */; /*!50001 SET character_set_results = @saved_cs_results */; /*!50001 SET collation_connection = @saved_col_connection */; @@ -87352,7 +87804,7 @@ USE `vn`; /*!50001 SET collation_connection = utf8mb4_unicode_ci */; /*!50001 CREATE ALGORITHM=UNDEFINED */ /*!50013 DEFINER=`vn`@`localhost` SQL SECURITY DEFINER */ -/*!50001 VIEW `itemShelvingStockFull` AS select `ish`.`itemFk` AS `itemFk`,`ish`.`visible` AS `quantity`,`ish`.`packing` AS `packing`,`ish`.`grouping` AS `grouping`,`s`.`description` AS `sector`,`issr`.`removed` AS `removed`,`p`.`sectorFk` AS `sectorFk`,`s`.`warehouseFk` AS `warehouseFk`,`ish`.`shelvingFk` AS `shelvingFk`,`p`.`code` AS `parkingCode`,`sh`.`parkingFk` AS `parkingFk`,`ish`.`id` AS `itemShelvingFk`,`ish`.`created` AS `created` from ((((`itemShelving` `ish` join `shelving` `sh` on(`sh`.`code` = `ish`.`shelvingFk`)) join `parking` `p` on(`p`.`id` = `sh`.`parkingFk`)) join `sector` `s` on(`s`.`id` = `p`.`sectorFk`)) left join `itemShelvingStockRemoved` `issr` on(`issr`.`itemShelvingFk` = `ish`.`id`)) */; +/*!50001 VIEW `itemShelvingStockFull` AS select `ish`.`itemFk` AS `itemFk`,`ish`.`visible` AS `quantity`,`ish`.`packing` AS `packing`,`ish`.`grouping` AS `grouping`,`s`.`description` AS `sector`,`issr`.`removed` AS `removed`,`p`.`sectorFk` AS `sectorFk`,`s`.`warehouseFk` AS `warehouseFk`,`ish`.`shelvingFk` AS `shelvingFk`,`p`.`code` AS `parkingCode`,`sh`.`parkingFk` AS `parkingFk`,`ish`.`id` AS `itemShelvingFk`,`ish`.`created` AS `created` from ((((`itemShelving` `ish` join `shelving` `sh` on(`sh`.`id` = `ish`.`shelvingFk`)) join `parking` `p` on(`p`.`id` = `sh`.`parkingFk`)) join `sector` `s` on(`s`.`id` = `p`.`sectorFk`)) left join `itemShelvingStockRemoved` `issr` on(`issr`.`itemShelvingFk` = `ish`.`id`)) */; /*!50001 SET character_set_client = @saved_cs_client */; /*!50001 SET character_set_results = @saved_cs_results */; /*!50001 SET collation_connection = @saved_col_connection */; @@ -87514,7 +87966,7 @@ USE `vn`; /*!50001 SET collation_connection = utf8mb4_unicode_ci */; /*!50001 CREATE ALGORITHM=UNDEFINED */ /*!50013 DEFINER=`vn`@`localhost` SQL SECURITY DEFINER */ -/*!50001 VIEW `lastPurchases` AS select `tr`.`landed` AS `landed`,`w`.`id` AS `warehouseFk`,`w`.`name` AS `warehouse`,`i`.`longName` AS `longName`,`i`.`subName` AS `subName`,`e`.`id` AS `entryFk`,`b`.`stickers` AS `stickers`,`b`.`packing` AS `packing`,`e`.`invoiceNumber` AS `ref`,`b`.`itemFk` AS `itemFk`,`ek`.`pro` AS `pro`,`ek`.`ref` AS `ektRef`,`ek`.`agj` AS `agj` from (((((`vn`.`buy` `b` join `vn`.`entry` `e` on(`e`.`id` = `b`.`entryFk`)) join `vn`.`item` `i` on(`i`.`id` = `b`.`itemFk`)) join `vn`.`travel` `tr` on(`tr`.`id` = `e`.`travelFk`)) join `vn`.`warehouse` `w` on(`w`.`id` = `tr`.`warehouseInFk`)) left join `edi`.`ekt` `ek` on(`ek`.`id` = `b`.`ektFk`)) where `tr`.`landed` between `util`.`yesterday`() and `util`.`tomorrow`() and `e`.`isRaid` = 0 and `b`.`stickers` > 0 */; +/*!50001 VIEW `lastPurchases` AS select `tr`.`landed` AS `landed`,`w`.`id` AS `warehouseFk`,`w`.`name` AS `warehouse`,`i`.`longName` AS `longName`,`i`.`subName` AS `subName`,`e`.`id` AS `entryFk`,`b`.`stickers` AS `stickers`,`b`.`packing` AS `packing`,`e`.`invoiceNumber` AS `ref`,`b`.`itemFk` AS `itemFk`,`ek`.`pro` AS `pro`,`ek`.`ref` AS `ektRef`,`ek`.`agj` AS `agj` from (((((`vn`.`buy` `b` join `vn`.`entry` `e` on(`e`.`id` = `b`.`entryFk`)) join `vn`.`item` `i` on(`i`.`id` = `b`.`itemFk`)) join `vn`.`travel` `tr` on(`tr`.`id` = `e`.`travelFk`)) join `vn`.`warehouse` `w` on(`w`.`id` = `tr`.`warehouseInFk`)) left join `edi`.`ekt` `ek` on(`ek`.`id` = `b`.`ektFk`)) where `tr`.`landed` between `util`.`yesterday`() and `util`.`tomorrow`() and `tr`.`isRaid` = 0 and `b`.`stickers` > 0 */; /*!50001 SET character_set_client = @saved_cs_client */; /*!50001 SET character_set_results = @saved_cs_results */; /*!50001 SET collation_connection = @saved_col_connection */; @@ -88396,7 +88848,7 @@ USE `vn`; /*!50001 SET collation_connection = utf8mb4_unicode_ci */; /*!50001 CREATE ALGORITHM=UNDEFINED */ /*!50013 DEFINER=`vn`@`localhost` SQL SECURITY DEFINER */ -/*!50001 VIEW `workerWithoutTractor` AS select `c`.`workerFk` AS `workerFk`,`cl`.`name` AS `Trabajador`,count(distinct `c`.`id`) AS `Colecciones`,max(`c`.`created`) AS `created` from ((`collection` `c` join `client` `cl` on(`cl`.`id` = `c`.`workerFk`)) left join `machineWorker` `mw` on(`mw`.`workerFk` = `c`.`workerFk` and `mw`.`inTimed` > `util`.`VN_CURDATE`())) where `c`.`created` > `util`.`VN_CURDATE`() and `mw`.`workerFk` is null group by `c`.`workerFk` */; +/*!50001 VIEW `workerWithoutTractor` AS select `c`.`workerFk` AS `workerFk`,`cl`.`name` AS `Trabajador`,count(distinct `c`.`id`) AS `Colecciones`,max(`c`.`created`) AS `created` from ((`collection` `c` join `client` `cl` on(`cl`.`id` = `c`.`workerFk`)) join `operator` `o` on(`o`.`workerFk` = `c`.`workerFk`)) where `c`.`created` > `util`.`VN_CURDATE`() and `o`.`machineFk` is null group by `c`.`workerFk` */; /*!50001 SET character_set_client = @saved_cs_client */; /*!50001 SET character_set_results = @saved_cs_results */; /*!50001 SET collation_connection = @saved_col_connection */; @@ -88636,25 +89088,7 @@ USE `vn2008`; /*!50001 SET collation_connection = utf8mb4_unicode_ci */; /*!50001 CREATE ALGORITHM=UNDEFINED */ /*!50013 DEFINER=`root`@`localhost` SQL SECURITY DEFINER */ -/*!50001 VIEW `Entradas` AS select `e`.`id` AS `Id_Entrada`,`e`.`supplierFk` AS `Id_Proveedor`,`e`.`invoiceNumber` AS `Referencia`,`e`.`reference` AS `reference`,`e`.`isExcludedFromAvailable` AS `Inventario`,`e`.`isConfirmed` AS `Confirmada`,`e`.`isOrdered` AS `Pedida`,`e`.`isRaid` AS `Redada`,`e`.`commission` AS `comision`,`e`.`created` AS `odbc_date`,`e`.`evaNotes` AS `Notas_Eva`,`e`.`travelFk` AS `travel_id`,`e`.`currencyFk` AS `Id_Moneda`,`e`.`companyFk` AS `empresa_id`,`e`.`gestDocFk` AS `gestdoc_id`,`e`.`invoiceInFk` AS `recibida_id`,`e`.`dated` AS `Fecha`,`e`.`isBooked` AS `Anotadoencaja`,`e`.`loadPriority` AS `loadPriority`,`e`.`sub` AS `sub`,`e`.`kop` AS `kop`,`e`.`pro` AS `pro`,`e`.`invoiceAmount` AS `invoiceAmount`,`e`.`buyerFk` AS `buyerFk`,`e`.`typeFk` AS `typeFk` from `vn`.`entry` `e` */; -/*!50001 SET character_set_client = @saved_cs_client */; -/*!50001 SET character_set_results = @saved_cs_results */; -/*!50001 SET collation_connection = @saved_col_connection */; - --- --- Final view structure for view `Entradas_Auto` --- - -/*!50001 DROP VIEW IF EXISTS `Entradas_Auto`*/; -/*!50001 SET @saved_cs_client = @@character_set_client */; -/*!50001 SET @saved_cs_results = @@character_set_results */; -/*!50001 SET @saved_col_connection = @@collation_connection */; -/*!50001 SET character_set_client = utf8mb4 */; -/*!50001 SET character_set_results = utf8mb4 */; -/*!50001 SET collation_connection = utf8mb4_unicode_ci */; -/*!50001 CREATE ALGORITHM=UNDEFINED */ -/*!50013 DEFINER=`root`@`localhost` SQL SECURITY DEFINER */ -/*!50001 VIEW `Entradas_Auto` AS select `ev`.`entryFk` AS `Id_Entrada` from `vn`.`entryVirtual` `ev` */; +/*!50001 VIEW `Entradas` AS select `e`.`id` AS `Id_Entrada`,`e`.`supplierFk` AS `Id_Proveedor`,`e`.`invoiceNumber` AS `Referencia`,`e`.`reference` AS `reference`,`e`.`isExcludedFromAvailable` AS `Inventario`,`e`.`isConfirmed` AS `Confirmada`,`e`.`isOrdered` AS `Pedida`,`e`.`commission` AS `comision`,`e`.`created` AS `odbc_date`,`e`.`evaNotes` AS `Notas_Eva`,`e`.`travelFk` AS `travel_id`,`e`.`currencyFk` AS `Id_Moneda`,`e`.`companyFk` AS `empresa_id`,`e`.`gestDocFk` AS `gestdoc_id`,`e`.`invoiceInFk` AS `recibida_id`,`e`.`dated` AS `Fecha`,`e`.`isBooked` AS `Anotadoencaja`,`e`.`loadPriority` AS `loadPriority`,`e`.`sub` AS `sub`,`e`.`kop` AS `kop`,`e`.`pro` AS `pro`,`e`.`invoiceAmount` AS `invoiceAmount`,`e`.`buyerFk` AS `buyerFk`,`e`.`typeFk` AS `typeFk` from `vn`.`entry` `e` */; /*!50001 SET character_set_client = @saved_cs_client */; /*!50001 SET character_set_results = @saved_cs_results */; /*!50001 SET collation_connection = @saved_col_connection */; @@ -89986,7 +90420,7 @@ USE `vn2008`; /*!50001 SET collation_connection = utf8mb4_unicode_ci */; /*!50001 CREATE ALGORITHM=UNDEFINED */ /*!50013 DEFINER=`root`@`localhost` SQL SECURITY DEFINER */ -/*!50001 VIEW `entrySource` AS select `e`.`gestDocFk` AS `gestdoc_id`,`e`.`id` AS `Id_Entrada`,`e`.`invoiceNumber` AS `invoiceNumber`,`e`.`reference` AS `reference`,`e`.`isExcludedFromAvailable` AS `Inventario`,`e`.`isConfirmed` AS `Confirmada`,`e`.`isOrdered` AS `Pedida`,`e`.`isRaid` AS `Redada`,`e`.`evaNotes` AS `notas`,`e`.`supplierFk` AS `Id_Proveedor`,`tr`.`shipped` AS `shipment`,`tr`.`landed` AS `landing`,`w2`.`name` AS `wh_in`,`w1`.`name` AS `wh_out`,`am`.`name` AS `Agencia`,`e`.`commission` AS `comision`,`tr`.`warehouseInFk` AS `warehouse_id`,`w1`.`id` AS `warehouse_id_out`,`e`.`isBooked` AS `anotadoencaja`,`e`.`invoiceInFk` AS `invoiceInFk`,`e`.`companyFk` AS `empresa_id`,`e`.`currencyFk` AS `Id_Moneda`,`tr`.`id` AS `TravelFk`,`e`.`sub` AS `sub`,`e`.`kop` AS `kop`,`e`.`pro` AS `pro`,`e`.`invoiceAmount` AS `invoiceAmount`,`w`.`code` AS `buyerCode`,`e`.`typeFk` AS `typeFk`,`w3`.`code` AS `observationWorkerCode` from (((((((`vn`.`entry` `e` left join `vn`.`travel` `tr` on(`e`.`travelFk` = `tr`.`id`)) left join `vn`.`agencyMode` `am` on(`am`.`id` = `tr`.`agencyModeFk`)) left join `vn`.`warehouse` `w1` on(`tr`.`warehouseOutFk` = `w1`.`id`)) left join `vn`.`warehouse` `w2` on(`tr`.`warehouseInFk` = `w2`.`id`)) left join `vn`.`supplier` `s` on(`e`.`supplierFk` = `s`.`id`)) left join `vn`.`worker` `w` on(`w`.`id` = `e`.`buyerFk`)) left join `vn`.`worker` `w3` on(`w3`.`id` = `e`.`observationEditorFk`)) */; +/*!50001 VIEW `entrySource` AS select `e`.`gestDocFk` AS `gestdoc_id`,`e`.`id` AS `Id_Entrada`,`e`.`invoiceNumber` AS `invoiceNumber`,`e`.`reference` AS `reference`,`e`.`isExcludedFromAvailable` AS `Inventario`,`e`.`isConfirmed` AS `Confirmada`,`e`.`isOrdered` AS `Pedida`,`tr`.`isRaid` AS `isRaid`,`tr`.`daysInForward` AS `daysInForward`,`e`.`evaNotes` AS `notas`,`e`.`supplierFk` AS `Id_Proveedor`,`tr`.`shipped` AS `shipment`,`tr`.`landed` AS `landing`,`w2`.`name` AS `wh_in`,`w1`.`name` AS `wh_out`,`am`.`name` AS `Agencia`,`e`.`commission` AS `comision`,`tr`.`warehouseInFk` AS `warehouse_id`,`w1`.`id` AS `warehouse_id_out`,`e`.`isBooked` AS `anotadoencaja`,`e`.`invoiceInFk` AS `invoiceInFk`,`e`.`companyFk` AS `empresa_id`,`e`.`currencyFk` AS `Id_Moneda`,`tr`.`id` AS `TravelFk`,`e`.`sub` AS `sub`,`e`.`kop` AS `kop`,`e`.`pro` AS `pro`,`e`.`invoiceAmount` AS `invoiceAmount`,`w`.`code` AS `buyerCode`,`e`.`typeFk` AS `typeFk`,`w3`.`code` AS `observationWorkerCode` from (((((((`vn`.`entry` `e` left join `vn`.`travel` `tr` on(`e`.`travelFk` = `tr`.`id`)) left join `vn`.`agencyMode` `am` on(`am`.`id` = `tr`.`agencyModeFk`)) left join `vn`.`warehouse` `w1` on(`tr`.`warehouseOutFk` = `w1`.`id`)) left join `vn`.`warehouse` `w2` on(`tr`.`warehouseInFk` = `w2`.`id`)) left join `vn`.`supplier` `s` on(`e`.`supplierFk` = `s`.`id`)) left join `vn`.`worker` `w` on(`w`.`id` = `e`.`buyerFk`)) left join `vn`.`worker` `w3` on(`w3`.`id` = `e`.`observationEditorFk`)) */; /*!50001 SET character_set_client = @saved_cs_client */; /*!50001 SET character_set_results = @saved_cs_results */; /*!50001 SET collation_connection = @saved_col_connection */; @@ -90706,7 +91140,7 @@ USE `vn2008`; /*!50001 SET collation_connection = utf8mb4_unicode_ci */; /*!50001 CREATE ALGORITHM=UNDEFINED */ /*!50013 DEFINER=`root`@`localhost` SQL SECURITY DEFINER */ -/*!50001 VIEW `travel` AS select `t`.`id` AS `id`,`t`.`shipped` AS `shipment`,`t`.`shipmentHour` AS `shipment_hour`,`t`.`landed` AS `landing`,`t`.`landingHour` AS `landing_hour`,`t`.`warehouseInFk` AS `warehouse_id`,`t`.`warehouseOutFk` AS `warehouse_id_out`,`t`.`agencyModeFk` AS `agency_id`,`t`.`ref` AS `ref`,`t`.`isDelivered` AS `delivered`,`t`.`isReceived` AS `received`,`t`.`m3` AS `m3`,`t`.`kg` AS `kg`,`t`.`cargoSupplierFk` AS `cargoSupplierFk`,`t`.`totalEntries` AS `totalEntries`,`t`.`appointment` AS `appointment`,`t`.`awbFk` AS `awbFk` from `vn`.`travel` `t` */; +/*!50001 VIEW `travel` AS select `t`.`id` AS `id`,`t`.`shipped` AS `shipment`,`t`.`shipmentHour` AS `shipment_hour`,`t`.`landed` AS `landing`,`t`.`landingHour` AS `landing_hour`,`t`.`warehouseInFk` AS `warehouse_id`,`t`.`warehouseOutFk` AS `warehouse_id_out`,`t`.`agencyModeFk` AS `agency_id`,`t`.`ref` AS `ref`,`t`.`isDelivered` AS `delivered`,`t`.`isReceived` AS `received`,`t`.`m3` AS `m3`,`t`.`kg` AS `kg`,`t`.`cargoSupplierFk` AS `cargoSupplierFk`,`t`.`totalEntries` AS `totalEntries`,`t`.`appointment` AS `appointment`,`t`.`awbFk` AS `awbFk`,`t`.`isRaid` AS `isRaid`,`t`.`daysInForward` AS `daysInForward` from `vn`.`travel` `t` */; /*!50001 SET character_set_client = @saved_cs_client */; /*!50001 SET character_set_results = @saved_cs_results */; /*!50001 SET collation_connection = @saved_col_connection */; @@ -90742,7 +91176,7 @@ USE `vn2008`; /*!50001 SET collation_connection = utf8mb4_unicode_ci */; /*!50001 CREATE ALGORITHM=UNDEFINED */ /*!50013 DEFINER=`root`@`localhost` SQL SECURITY DEFINER */ -/*!50001 VIEW `v_compres` AS select `TP`.`Id_Tipo` AS `Familia`,`RN`.`id` AS `reino_id`,`C`.`Id_Compra` AS `Id_Compra`,`C`.`Id_Entrada` AS `Id_Entrada`,`C`.`Id_Article` AS `Id_Article`,`C`.`Cantidad` AS `Cantidad`,`C`.`Costefijo` AS `Costefijo`,`C`.`Portefijo` AS `Portefijo`,`C`.`Novincular` AS `Novincular`,`C`.`Etiquetas` AS `Etiquetas`,`C`.`Packing` AS `Packing`,`C`.`grouping` AS `grouping`,`C`.`Comisionfija` AS `Comisionfija`,`C`.`Embalajefijo` AS `Embalajefijo`,`C`.`Id_Cubo` AS `Id_Cubo`,`C`.`Tarifa1` AS `Tarifa1`,`C`.`Tarifa2` AS `Tarifa2`,`C`.`Tarifa3` AS `Tarifa3`,`C`.`PVP` AS `PVP`,`C`.`Vida` AS `Vida`,`C`.`Id_Trabajador` AS `Id_Trabajador`,`C`.`punteo` AS `punteo`,`C`.`odbc_date` AS `odbc_date`,`E`.`Inventario` AS `Inventario`,`E`.`Id_Proveedor` AS `Id_Proveedor`,`E`.`Fecha` AS `Fecha`,`E`.`Confirmada` AS `Confirmada`,`E`.`Redada` AS `Redada`,`E`.`empresa_id` AS `empresa_id`,`E`.`travel_id` AS `travel_id`,`E`.`Pedida` AS `Pedida`,`E`.`recibida_id` AS `recibida_id`,`TR`.`id` AS `id`,`TR`.`shipment` AS `shipment`,`TR`.`landing` AS `landing`,`TR`.`warehouse_id` AS `warehouse_id`,`TR`.`warehouse_id_out` AS `warehouse_id_out`,`TR`.`agency_id` AS `agency_id`,`TR`.`ref` AS `ref`,`TR`.`delivered` AS `delivered`,`TR`.`received` AS `received`,`A`.`Article` AS `Article`,`A`.`Medida` AS `Medida`,`A`.`Tallos` AS `Tallos`,`C`.`caja` AS `caja`,`A`.`Categoria` AS `Categoria`,`A`.`id_origen` AS `id_origen`,`TP`.`Id_Tipo` AS `Tipo`,`A`.`tipo_id` AS `tipo_id`,`A`.`Color` AS `Color`,`A`.`Min` AS `Min`,`C`.`Costefijo` + `C`.`Embalajefijo` + `C`.`Comisionfija` + `C`.`Portefijo` AS `Coste`,`W_OUT`.`isFeedStock` AS `fuente`,if(`cb`.`Volumen` > 0,`cb`.`Volumen`,`cb`.`X` * `cb`.`Y` * if(`cb`.`Z` = 0,`A`.`Medida` + 10,`cb`.`Z`)) * `C`.`Etiquetas` AS `cm3`,`A`.`producer_id` AS `producer_id` from ((((((((`vn2008`.`Compres` `C` join `vn2008`.`Entradas` `E` on(`C`.`Id_Entrada` = `E`.`Id_Entrada`)) join `vn2008`.`travel` `TR` on(`TR`.`id` = `E`.`travel_id`)) join `vn`.`warehouse` `W_IN` on(`W_IN`.`id` = `TR`.`warehouse_id`)) join `vn`.`warehouse` `W_OUT` on(`W_OUT`.`id` = `TR`.`warehouse_id_out`)) join `vn2008`.`Articles` `A` on(`C`.`Id_Article` = `A`.`Id_Article`)) join `vn2008`.`Tipos` `TP` on(`A`.`tipo_id` = `TP`.`tipo_id`)) join `vn2008`.`reinos` `RN` on(`RN`.`id` = `TP`.`reino_id`)) join `vn2008`.`Cubos` `cb` on(`cb`.`Id_Cubo` = `C`.`Id_Cubo`)) where `W_IN`.`isFeedStock` = 0 and `E`.`Inventario` = 0 and `E`.`Redada` = 0 */; +/*!50001 VIEW `v_compres` AS select `TP`.`Id_Tipo` AS `Familia`,`RN`.`id` AS `reino_id`,`C`.`Id_Compra` AS `Id_Compra`,`C`.`Id_Entrada` AS `Id_Entrada`,`C`.`Id_Article` AS `Id_Article`,`C`.`Cantidad` AS `Cantidad`,`C`.`Costefijo` AS `Costefijo`,`C`.`Portefijo` AS `Portefijo`,`C`.`Novincular` AS `Novincular`,`C`.`Etiquetas` AS `Etiquetas`,`C`.`Packing` AS `Packing`,`C`.`grouping` AS `grouping`,`C`.`Comisionfija` AS `Comisionfija`,`C`.`Embalajefijo` AS `Embalajefijo`,`C`.`Id_Cubo` AS `Id_Cubo`,`C`.`Tarifa1` AS `Tarifa1`,`C`.`Tarifa2` AS `Tarifa2`,`C`.`Tarifa3` AS `Tarifa3`,`C`.`PVP` AS `PVP`,`C`.`Vida` AS `Vida`,`C`.`Id_Trabajador` AS `Id_Trabajador`,`C`.`punteo` AS `punteo`,`C`.`odbc_date` AS `odbc_date`,`E`.`Inventario` AS `Inventario`,`E`.`Id_Proveedor` AS `Id_Proveedor`,`E`.`Fecha` AS `Fecha`,`E`.`Confirmada` AS `Confirmada`,`E`.`empresa_id` AS `empresa_id`,`E`.`travel_id` AS `travel_id`,`E`.`Pedida` AS `Pedida`,`E`.`recibida_id` AS `recibida_id`,`TR`.`id` AS `id`,`TR`.`shipment` AS `shipment`,`TR`.`landing` AS `landing`,`TR`.`warehouse_id` AS `warehouse_id`,`TR`.`warehouse_id_out` AS `warehouse_id_out`,`TR`.`agency_id` AS `agency_id`,`TR`.`ref` AS `ref`,`TR`.`delivered` AS `delivered`,`TR`.`received` AS `received`,`A`.`Article` AS `Article`,`A`.`Medida` AS `Medida`,`A`.`Tallos` AS `Tallos`,`C`.`caja` AS `caja`,`A`.`Categoria` AS `Categoria`,`A`.`id_origen` AS `id_origen`,`TP`.`Id_Tipo` AS `Tipo`,`A`.`tipo_id` AS `tipo_id`,`A`.`Color` AS `Color`,`A`.`Min` AS `Min`,`C`.`Costefijo` + `C`.`Embalajefijo` + `C`.`Comisionfija` + `C`.`Portefijo` AS `Coste`,`W_OUT`.`isFeedStock` AS `fuente`,if(`cb`.`Volumen` > 0,`cb`.`Volumen`,`cb`.`X` * `cb`.`Y` * if(`cb`.`Z` = 0,`A`.`Medida` + 10,`cb`.`Z`)) * `C`.`Etiquetas` AS `cm3`,`A`.`producer_id` AS `producer_id` from ((((((((`vn2008`.`Compres` `C` join `vn2008`.`Entradas` `E` on(`C`.`Id_Entrada` = `E`.`Id_Entrada`)) join `vn2008`.`travel` `TR` on(`TR`.`id` = `E`.`travel_id`)) join `vn`.`warehouse` `W_IN` on(`W_IN`.`id` = `TR`.`warehouse_id`)) join `vn`.`warehouse` `W_OUT` on(`W_OUT`.`id` = `TR`.`warehouse_id_out`)) join `vn2008`.`Articles` `A` on(`C`.`Id_Article` = `A`.`Id_Article`)) join `vn2008`.`Tipos` `TP` on(`A`.`tipo_id` = `TP`.`tipo_id`)) join `vn2008`.`reinos` `RN` on(`RN`.`id` = `TP`.`reino_id`)) join `vn2008`.`Cubos` `cb` on(`cb`.`Id_Cubo` = `C`.`Id_Cubo`)) where `W_IN`.`isFeedStock` = 0 and `E`.`Inventario` = 0 and `TR`.`isRaid` = 0 */; /*!50001 SET character_set_client = @saved_cs_client */; /*!50001 SET character_set_results = @saved_cs_results */; /*!50001 SET collation_connection = @saved_col_connection */; @@ -90810,4 +91244,4 @@ USE `vn2008`; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2024-11-12 7:06:20 +-- Dump completed on 2024-11-26 12:08:52 diff --git a/db/dump/.dump/triggers.sql b/db/dump/.dump/triggers.sql index 7152187bb..8f8fe9670 100644 --- a/db/dump/.dump/triggers.sql +++ b/db/dump/.dump/triggers.sql @@ -867,17 +867,17 @@ BEGIN UPDATE vn.buy b JOIN vn.entry e ON e.id = b.entryFk - JOIN vn.travel tr ON tr.id = e.travelFk - JOIN vn.agencyMode am ON am.id = tr.agencyModeFk + JOIN vn.travel tr ON tr.id = e.travelFk + JOIN vn.agencyMode am ON am.id = tr.agencyModeFk JOIN vn.item i ON i.id = b.itemFk JOIN edi.supplyResponse sr ON i.supplyResponseFk = sr.ID SET b.quantity = NEW.NumberOfItemsPerCask * NEW.NumberOfUnits, b.stickers = NEW.NumberOfUnits WHERE i.supplyResponseFk = NEW.ID AND am.name = 'LOGIFLORA' - AND e.isRaid + AND tr.isRaid AND tr.landed >= util.VN_CURDATE(); - + END */;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -1460,6 +1460,9 @@ DELIMITER ;; FOR EACH ROW BEGIN SET NEW.editorFk = account.myUser_getId(); + IF NEW.`property` = '*' THEN + CALL util.throw('The property field cannot be *'); + END IF; END */;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -2000,6 +2003,7 @@ BEGIN DECLARE vIsEqualizated BOOL; SET NEW.editorFk = account.myUser_getId(); + SET NEW.geoFk = address_getGeo(NEW.id); IF (NEW.phone <> '') THEN CALL pbx.phone_isValid(NEW.phone); @@ -2036,7 +2040,6 @@ DELIMITER ;; BEFORE UPDATE ON `address` FOR EACH ROW BEGIN - SET NEW.editorFk = account.myUser_getId(); IF !(NEW.phone <=> OLD.phone) AND (NEW.phone <> '') THEN @@ -2047,6 +2050,11 @@ BEGIN CALL pbx.phone_isValid(NEW.mobile); END IF; + IF NOT (NEW.provinceFk <=> OLD.provinceFk) + OR (NEW.postalCode <=> OLD.postalCode) THEN + + SET NEW.geoFk = address_getGeo(NEW.id); + END IF; END */;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -3423,8 +3431,10 @@ DELIMITER ;; BEFORE INSERT ON `client` FOR EACH ROW BEGIN - SET NEW.editorFk = account.myUser_getId(); + SET NEW.accountingAccount = 4300000000 + NEW.id; + SET NEW.lastSalesPersonFk = NEW.salesPersonFk; + SET NEW.geoFk = client_getGeo(NEW.id); IF (NEW.phone <> '') THEN CALL pbx.phone_isValid(NEW.phone); @@ -3433,10 +3443,6 @@ BEGIN IF (NEW.mobile <> '') THEN CALL pbx.phone_isValid(NEW.mobile); END IF; - - SET NEW.accountingAccount = 4300000000 + NEW.id; - - SET NEW.lastSalesPersonFk = NEW.salesPersonFk; END */;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -3550,6 +3556,12 @@ BEGIN IF NOT (NEW.businessTypeFk <=> OLD.businessTypeFk) AND (NEW.businessTypeFk = 'individual' OR OLD.businessTypeFk = 'individual') THEN SET NEW.isTaxDataChecked = 0; END IF; + + IF NOT (NEW.provinceFk <=> OLD.provinceFk) + OR (NEW.postcode <=> OLD.postcode) THEN + + SET NEW.geoFk = client_getGeo(NEW.id); + END IF; END */;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -4960,7 +4972,7 @@ DELIMITER ;; BEFORE UPDATE ON `entry` FOR EACH ROW BEGIN - DECLARE vIsVirtual BOOL; + DECLARE vIsRaid BOOL; DECLARE vPrintedCount INT; DECLARE vHasDistinctWarehouses BOOL; DECLARE vTotalBuy INT; @@ -4994,18 +5006,20 @@ BEGIN IF NEW.travelFk IS NOT NULL THEN CALL travel_throwAwb(NEW.travelFk); END IF; - - SELECT COUNT(*) > 0 INTO vIsVirtual - FROM entryVirtual WHERE entryFk = NEW.id; + + SELECT t.isRaid INTO vIsRaid + FROM travel t + JOIN entry e ON e.travelFk = t.id + WHERE e.id = NEW.id; SELECT NOT (o.warehouseInFk <=> n.warehouseInFk) - OR NOT (o.warehouseOutFk <=> n.warehouseOutFk) + OR NOT (o.warehouseOutFk <=> n.warehouseOutFk) INTO vHasDistinctWarehouses FROM travel o, travel n WHERE o.id = OLD.travelFk AND n.id = NEW.travelFk; - IF vIsVirtual AND vHasDistinctWarehouses THEN + IF vIsRaid AND vHasDistinctWarehouses THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'A cloned entry cannot be moved to a travel with different warehouses'; END IF; @@ -5028,7 +5042,7 @@ BEGIN SET NEW.currencyFk = entry_getCurrency(NEW.currencyFk, NEW.supplierFk); END IF; - IF NOT (NEW.travelFk <=> OLD.travelFk) + IF NOT (NEW.travelFk <=> OLD.travelFk) OR NOT (NEW.currencyFk <=> OLD.currencyFk) OR NOT (NEW.supplierFk <=> OLD.supplierFk) THEN @@ -5325,7 +5339,8 @@ BEGIN SET packages = (SELECT COUNT(counter)-1 FROM expedition e WHERE e.ticketFk = OLD.ticketFk and e.freightItemFk) WHERE t.id = OLD.ticketFk; - + + CALL expedition_selfConsumptionPackaging(OLD.id, 'remove'); END */;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -6909,10 +6924,31 @@ DELIMITER ; /*!50003 SET @saved_sql_mode = @@sql_mode */ ; /*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; DELIMITER ;; +/*!50003 CREATE*/ /*!50017 DEFINER=`vn`@`localhost`*/ /*!50003 TRIGGER `vn`.`itemType_beforeInsert` + BEFORE INSERT ON `itemType` + FOR EACH ROW +BEGIN + SET NEW.editorFk = account.myUser_getId(); +END */;; +DELIMITER ; +/*!50003 SET sql_mode = @saved_sql_mode */ ; +/*!50003 SET character_set_client = @saved_cs_client */ ; +/*!50003 SET character_set_results = @saved_cs_results */ ; +/*!50003 SET collation_connection = @saved_col_connection */ ; +/*!50003 SET @saved_cs_client = @@character_set_client */ ; +/*!50003 SET @saved_cs_results = @@character_set_results */ ; +/*!50003 SET @saved_col_connection = @@collation_connection */ ; +/*!50003 SET character_set_client = utf8mb4 */ ; +/*!50003 SET character_set_results = utf8mb4 */ ; +/*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; +DELIMITER ;; /*!50003 CREATE*/ /*!50017 DEFINER=`vn`@`localhost`*/ /*!50003 TRIGGER `vn`.`itemType_beforeUpdate` BEFORE UPDATE ON `itemType` FOR EACH ROW BEGIN + SET NEW.editorFk = account.myUser_getId(); IF NEW.itemPackingTypeFk = '' THEN SET NEW.itemPackingTypeFk = NULL; @@ -6939,6 +6975,30 @@ DELIMITER ; /*!50003 SET @saved_sql_mode = @@sql_mode */ ; /*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; DELIMITER ;; +/*!50003 CREATE*/ /*!50017 DEFINER=`vn`@`localhost`*/ /*!50003 TRIGGER `vn`.`itemType_afterDelete` + AFTER DELETE ON `itemType` + FOR EACH ROW +BEGIN + INSERT INTO itemTypeLog + SET `action` = 'delete', + `changedModel` = 'ItemType', + `changedModelId` = OLD.id, + `userFk` = account.myUser_getId(); +END */;; +DELIMITER ; +/*!50003 SET sql_mode = @saved_sql_mode */ ; +/*!50003 SET character_set_client = @saved_cs_client */ ; +/*!50003 SET character_set_results = @saved_cs_results */ ; +/*!50003 SET collation_connection = @saved_col_connection */ ; +/*!50003 SET @saved_cs_client = @@character_set_client */ ; +/*!50003 SET @saved_cs_results = @@character_set_results */ ; +/*!50003 SET @saved_col_connection = @@collation_connection */ ; +/*!50003 SET character_set_client = utf8mb4 */ ; +/*!50003 SET character_set_results = utf8mb4 */ ; +/*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; +DELIMITER ;; /*!50003 CREATE*/ /*!50017 DEFINER=`vn`@`localhost`*/ /*!50003 TRIGGER `vn`.`machine_beforeInsert` BEFORE INSERT ON `machine` FOR EACH ROW @@ -7584,7 +7644,7 @@ DELIMITER ;; AFTER DELETE ON `productionConfig` FOR EACH ROW BEGIN - INSERT INTO productionConfig + INSERT INTO productionConfigLog SET `action` = 'delete', `changedModel` = 'ProductionConfig', `changedModelId` = OLD.id, @@ -8168,18 +8228,18 @@ DELIMITER ;; /*!50003 CREATE*/ /*!50017 DEFINER=`vn`@`localhost`*/ /*!50003 TRIGGER `vn`.`route_afterUpdate` AFTER UPDATE ON `route` FOR EACH ROW -BEGIN +BEGIN IF IFNULL(NEW.gestdocFk,0) <> IFNULL(OLD.gestdocFk,0) AND NEW.gestdocFk > 0 THEN -- JGF 09/09/14 cuando se añade un gestdoc a una ruta, se le asigna automagicamente a todos sus Tickets - + -- Inserta el gestdoc en todos los tickets de la ruta INSERT INTO ticketDms(ticketFk,dmsFk) SELECT id, NEW.gestdocFk FROM ticket WHERE routeFk = NEW.id ON DUPLICATE KEY UPDATE dmsFk = NEW.gestdocFk; - -- Update del firmado - UPDATE ticket t - JOIN ticketDms tg ON t.id = tg.ticketFk + -- Update del firmado + UPDATE ticket t + JOIN ticketDms tg ON t.id = tg.ticketFk SET isSigned = 1 WHERE t.routeFk = NEW.id; END IF; @@ -8187,7 +8247,8 @@ BEGIN OR !(NEW.kmEnd <=> OLD.kmEnd) OR !(NEW.workerFk <=> OLD.workerFk) OR !(NEW.m3 <=> OLD.m3) - OR !(NEW.agencyModeFk <=> OLD.agencyModeFk)THEN + OR !(NEW.agencyModeFk <=> OLD.agencyModeFk) + OR !(NEW.vehicleFk <=> OLD.vehicleFk)THEN CALL route_calcCommission(NEW.id); END IF; @@ -9086,6 +9147,7 @@ DELIMITER ;; FOR EACH ROW BEGIN SET NEW.editorFk = account.myUser_getId(); + SET NEW.geoFk = supplier_getGeo(NEW.id); END */;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -9180,6 +9242,11 @@ BEGIN SET NEW.isPayMethodChecked = FALSE; END IF; + IF NOT (NEW.provinceFk <=> OLD.provinceFk) + OR (NEW.postCode <=> OLD.postCode) THEN + + SET NEW.geoFk = supplier_getGeo(NEW.id); + END IF; END */;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -10501,28 +10568,6 @@ DELIMITER ; /*!50003 SET @saved_sql_mode = @@sql_mode */ ; /*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; DELIMITER ;; -/*!50003 CREATE*/ /*!50017 DEFINER=`vn`@`localhost`*/ /*!50003 TRIGGER `vn`.`town_beforeUpdate` - BEFORE UPDATE ON `town` - FOR EACH ROW -BEGIN - -- IF !(OLD.geoFk <=> NEW.geoFk) THEN - -- CALL zoneGeo_throwNotEditable; - -- END IF; -END */;; -DELIMITER ; -/*!50003 SET sql_mode = @saved_sql_mode */ ; -/*!50003 SET character_set_client = @saved_cs_client */ ; -/*!50003 SET character_set_results = @saved_cs_results */ ; -/*!50003 SET collation_connection = @saved_col_connection */ ; -/*!50003 SET @saved_cs_client = @@character_set_client */ ; -/*!50003 SET @saved_cs_results = @@character_set_results */ ; -/*!50003 SET @saved_col_connection = @@collation_connection */ ; -/*!50003 SET character_set_client = utf8mb4 */ ; -/*!50003 SET character_set_results = utf8mb4 */ ; -/*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; -/*!50003 SET @saved_sql_mode = @@sql_mode */ ; -/*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; -DELIMITER ;; /*!50003 CREATE*/ /*!50017 DEFINER=`vn`@`localhost`*/ /*!50003 TRIGGER `vn`.`town_afterUpdate` AFTER UPDATE ON `town` FOR EACH ROW @@ -10580,7 +10625,11 @@ BEGIN CALL travel_checkDates(NEW.shipped, NEW.landed); CALL travel_checkWarehouseIsFeedStock(NEW.warehouseInFk); - + + IF NEW.isRaid IS NOT NULL OR NEW.daysInForward IS NOT NULL THEN + CALL travel_checkRaid(NEW.isRaid, NEW.daysInForward); + END IF; + IF NEW.awbFk IS NOT NULL THEN CALL travel_throwAwb(NEW.id); END IF; @@ -10607,7 +10656,7 @@ BEGIN SET NEW.editorFk = account.myUser_getId(); - IF NOT (NEW.landed <=> OLD.landed) + IF NOT (NEW.landed <=> OLD.landed) OR NOT (NEW.shipped <=> OLD.shipped) THEN CALL travel_checkDates(NEW.shipped, NEW.landed); END IF; @@ -10620,19 +10669,23 @@ BEGIN CALL travel_checkWarehouseIsFeedStock(NEW.warehouseInFk); END IF; + IF NOT (NEW.isRaid <=> OLD.isRaid) OR NOT (NEW.daysInForward <=> OLD.daysInForward) THEN + CALL travel_checkRaid(NEW.isRaid, NEW.daysInForward); + END IF; + IF NOT (NEW.awbFk <=> OLD.awbFk)THEN - SELECT COUNT(*) INTO vHasAnyInvoiceBooked + SELECT COUNT(*) INTO vHasAnyInvoiceBooked FROM travel t - JOIN entry e ON e.travelFk = t.id - JOIN invoiceIn ii ON ii.id = e.invoiceInFk + JOIN entry e ON e.travelFk = t.id + JOIN invoiceIn ii ON ii.id = e.invoiceInFk WHERE t.id = NEW.id - AND ii.isBooked; - + AND ii.isBooked; + IF vHasAnyInvoiceBooked THEN CALL util.throw('The travel has entries with booked invoices'); END IF; - END IF; - + END IF; + IF (NOT(NEW.awbFk <=> OLD.awbFk)) AND NEW.awbFk IS NOT NULL THEN CALL travel_throwAwb(NEW.id); END IF; @@ -11526,4 +11579,4 @@ USE `vn2008`; /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2024-11-12 7:06:44 +-- Dump completed on 2024-11-26 12:09:13 diff --git a/db/dump/fixtures.before.sql b/db/dump/fixtures.before.sql index 2dcedcc92..db853d5ca 100644 --- a/db/dump/fixtures.before.sql +++ b/db/dump/fixtures.before.sql @@ -1518,19 +1518,19 @@ INSERT INTO `vn`.`travel`(`id`,`shipped`, `landed`, `warehouseInFk`, `warehouseO (11, util.VN_CURDATE() - INTERVAL 1 DAY , util.VN_CURDATE(), 6, 3, 0, 50.00, 500, 'eleventh travel', 1, 2, 4, FALSE, NULL), (12, util.VN_CURDATE() , util.VN_CURDATE() + INTERVAL 1 DAY, 6, 3, 0, 50.00, 500, 'eleventh travel', 1, 2, 4, FALSE, NULL); -INSERT INTO `vn`.`entry`(`id`, `supplierFk`, `created`, `travelFk`, `isConfirmed`, `companyFk`, `invoiceNumber`, `reference`, `isExcludedFromAvailable`, `evaNotes`) - VALUES - (1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 1, 442, 'IN2001', 'Movement 1', 0, ''), - (2, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 2, 0, 442, 'IN2002', 'Movement 2', 0, 'observation two'), - (3, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 3, 0, 442, 'IN2003', 'Movement 3', 0, 'observation three'), - (4, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 2, 0, 69, 'IN2004', 'Movement 4', 0, 'observation four'), - (5, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 5, 0, 442, 'IN2005', 'Movement 5', 0, 'observation five'), - (6, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 6, 0, 442, 'IN2006', 'Movement 6', 0, 'observation six'), - (7, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 7, 0, 442, 'IN2007', 'Movement 7', 0, 'observation seven'), - (8, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 7, 0, 442, 'IN2008', 'Movement 8', 1,''), - (9, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL +2 DAY), 10, 0, 442, 'IN2009', 'Movement 9', 1, ''), - (10, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL +2 DAY), 10, 0, 442, 'IN2009', 'Movement 10', 1, ''), - (99, 69, '2000-12-01 00:00:00.000', 11, 0, 442, 'IN2009', 'Movement 99', 0, ''); +INSERT INTO `vn`.`entry`(`id`, `supplierFk`, `created`, `travelFk`, `isConfirmed`, `companyFk`, `invoiceNumber`, `reference`, `isExcludedFromAvailable`, `evaNotes`, `typeFk`) + VALUES + (1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 1, 442, 'IN2001', 'Movement 1', 0, '', 'packaging'), + (2, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 2, 0, 442, 'IN2002', 'Movement 2', 0, 'observation two', 'product'), + (3, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 3, 0, 442, 'IN2003', 'Movement 3', 0, 'observation three', 'product'), + (4, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 2, 0, 69, 'IN2004', 'Movement 4', 0, 'observation four', 'product'), + (5, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 5, 0, 442, 'IN2005', 'Movement 5', 0, 'observation five', 'product'), + (6, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 6, 0, 442, 'IN2006', 'Movement 6', 0, 'observation six', 'product'), + (7, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 7, 0, 442, 'IN2007', 'Movement 7', 0, 'observation seven', 'product'), + (8, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 7, 0, 442, 'IN2008', 'Movement 8', 1, '', 'product'), + (9, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL +2 DAY), 10, 0, 442, 'IN2009', 'Movement 9', 1, '', 'product'), + (10, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL +2 DAY), 10, 0, 442, 'IN2009', 'Movement 10', 1, '', 'product'), + (99, 69, util.VN_CURDATE() - INTERVAL 1 MONTH, 11, 0, 442, 'IN2009', 'Movement 99', 0, '', 'product'); INSERT INTO `vn`.`entryConfig` (`defaultEntry`, `inventorySupplierFk`, `defaultSupplierFk`) VALUES (2, 4, 1); @@ -2521,10 +2521,6 @@ INSERT INTO `vn`.`queuePriority`(`id`, `priority`, `code`) (2, 'Normal', 'normal'), (3, 'Baja', 'low'); -INSERT INTO `vn`.`workerTimeControlParams` (`id`, `dayBreak`, `weekBreak`, `weekScope`, `dayWorkMax`, `dayStayMax`, `weekMaxBreak`, `weekMaxScope`, `askInOut`) - VALUES - (1, 43200, 129600, 734400, 43200, 50400, 259200, 1296000, 36000); - INSERT IGNORE INTO `vn`.`greugeConfig` (`id`, `freightPickUpPrice`) VALUES ('1', '11'); INSERT INTO `vn`.`thermograph`(`id`, `model`) @@ -4008,6 +4004,9 @@ INSERT IGNORE INTO pbx.queueMember UPDATE vn.department SET pbxQueue = '1000' WHERE name = "CAMARA"; UPDATE vn.department SET pbxQueue = '2000' WHERE name = "VENTAS"; +INSERT INTO vn.workerRelatives (workerFk, isDescendant, disabilityGradeFk, birthed, adoptionYear, isDependend, isJointCustody, updated) + VALUES + (1106, 1, NULL, 0, NULL, 0, 0, '2024-10-29 08:42:44.000'); INSERT INTO vn.routeAction (id, name, price, isMainlineDelivered) VALUES(1, 'Pintar traje', 50.00, 0); INSERT INTO vn.routeComplement (id, dated, workerFk, price, routeActionFk) VALUES(1, util.VN_CURDATE(), 9, 50.00, 1); @@ -4025,7 +4024,6 @@ INSERT INTO srt.buffer (id, x, y, `size`, `length`, stateFk, typeFk, isActive, c (9, 1400, 1500, 500, 13000, 1, 1, 1, '04B', 4, 0, NULL, NULL, NULL, NULL, 0, 1, 1, NULL), (10, 0, 2000, 500, 13000, 1, 1, 1, '05A', 5, 0, NULL, NULL, NULL, NULL, 0, 1, 1, NULL); - INSERT IGNORE INTO vn.saySimpleCountry (countryFk, channel) VALUES (19, '1169'), (8, '1183'); @@ -4033,6 +4031,10 @@ INSERT IGNORE INTO vn.saySimpleCountry (countryFk, channel) INSERT IGNORE INTO vn.saySimpleConfig (url, defaultChannel) VALUES ('saysimle-url-mock', 1320); +INSERT INTO vn.workerIrpf (workerFk,spouseNif, geographicMobilityDate) + VALUES (1106,'26493101E','2019-09-20'); - INSERT INTO vn.payment (received,supplierFk,amount,currencyFk,divisa,bankFk,payMethodFk,bankingFees,concept,companyFk,created,isConciliated,dueDated,workerFk) VALUES + + +INSERT INTO vn.payment (received,supplierFk,amount,currencyFk,divisa,bankFk,payMethodFk,bankingFees,concept,companyFk,created,isConciliated,dueDated,workerFk) VALUES ('2024-09-15',1,1000.00,1,NULL,1,1,0.0,'n/pago',442,'2024-11-20 13:06:02.000',1,'2024-09-15',9); diff --git a/db/routines/sage/procedures/invoiceIn_add.sql b/db/routines/sage/procedures/invoiceIn_add.sql index 0898d6810..1d411cfd0 100644 --- a/db/routines/sage/procedures/invoiceIn_add.sql +++ b/db/routines/sage/procedures/invoiceIn_add.sql @@ -26,7 +26,7 @@ BEGIN DECLARE vCursor CURSOR FOR SELECT it.taxableBase, - CAST((( it.taxableBase / 100) * t.PorcentajeIva) AS DECIMAL (10,2)), + CAST(SUM((( it.taxableBase / 100) * t.PorcentajeIva)) AS DECIMAL (10,2)), t.PorcentajeIva, it.transactionTypeSageFk, it.taxTypeSageFk, @@ -39,7 +39,8 @@ BEGIN JOIN TiposTransacciones tt ON tt.CodigoTransaccion = it.transactionTypeSageFk LEFT JOIN vn.dua d ON d.id = vInvoiceInFk WHERE i.id = vInvoiceInFk - AND d.id IS NULL; + AND d.id IS NULL + GROUP BY it.taxTypeSageFk; DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE; diff --git a/db/routines/vn/functions/timeWorkerControl_getDirection.sql b/db/routines/vn/functions/timeWorkerControl_getDirection.sql deleted file mode 100644 index c0f1e67ea..000000000 --- a/db/routines/vn/functions/timeWorkerControl_getDirection.sql +++ /dev/null @@ -1,65 +0,0 @@ -DELIMITER $$ -CREATE OR REPLACE DEFINER=`vn`@`localhost` FUNCTION `vn`.`timeWorkerControl_getDirection`(vUserFk INT, vTimed DATETIME) - RETURNS varchar(6) CHARSET utf8mb3 COLLATE utf8mb3_unicode_ci - NOT DETERMINISTIC - READS SQL DATA -BEGIN -/** - * Verifica la dirección de la fichada - * @param vUserFk Identificador del trabajador - * @param vTimed Hora de la fichada - * @return Retorna sentido de la fichada 'in, out, middle' - */ - - DECLARE vPrevious DATETIME ; - DECLARE vNext DATETIME ; - DECLARE vPreviousDirection VARCHAR(3) ; - DECLARE vNextDirection VARCHAR(3) ; - DECLARE vDayStayMax INT; - DECLARE vTimedSeconds INT; - DECLARE vLastTimeIn INT; - - SELECT UNIX_TIMESTAMP(vTimed) INTO vTimedSeconds; - - SELECT dayStayMax INTO vDayStayMax - FROM vn.workerTimeControlParams; - - SELECT timed, direction INTO vNext,vNextDirection - FROM vn.workerTimeControl - WHERE userFk = vUserFk - AND direction IN ('in','out') - AND timed > vTimed - ORDER BY timed ASC - LIMIT 1; - - SELECT timed, direction INTO vPrevious, vPreviousDirection - FROM vn.workerTimeControl - WHERE userFk = vUserFk - AND direction IN ('in','out') - AND timed < vTimed - ORDER BY timed DESC - LIMIT 1; - - IF (vTimedSeconds - UNIX_TIMESTAMP(vPrevious) + UNIX_TIMESTAMP(vNext) - vTimedSeconds)<= vDayStayMax AND vPreviousDirection = 'in' AND vNextDirection = 'out' THEN - RETURN 'middle'; - END IF; - - - IF (vTimedSeconds> UNIX_TIMESTAMP(vPrevious)) THEN - IF vPreviousDirection = 'in' THEN - RETURN 'out'; - ELSE - SELECT UNIX_TIMESTAMP(MAX(timed)) INTO vLastTimeIn - FROM vn.workerTimeControl - WHERE userFk = vUserFk - AND direction ='in' - AND timed < vPrevious; - IF vTimedSeconds - vLastTimeIn <= vDayStayMax THEN - RETURN 'out'; - END IF; - END IF; - END IF; - - RETURN 'in'; -END$$ -DELIMITER ; diff --git a/db/routines/vn/procedures/entry_isEditable.sql b/db/routines/vn/procedures/entry_isEditable.sql index 12b6d0ef6..c417f6789 100644 --- a/db/routines/vn/procedures/entry_isEditable.sql +++ b/db/routines/vn/procedures/entry_isEditable.sql @@ -9,16 +9,18 @@ BEGIN * * @param vSelf Id de entrada */ - DECLARE vIsEditable BOOL; + DECLARE vIsNotEditable BOOL DEFAULT FALSE; - SELECT e.isBooked INTO vIsEditable + SELECT TRUE INTO vIsNotEditable FROM `entry` e - JOIN entryType et ON et.code = e.typeFk - WHERE NOT et.isInformal - AND e.id = vSelf; + LEFT JOIN entryType et ON et.code = e.typeFk + WHERE e.id = vSelf + AND e.isBooked + AND (e.typeFk IS NULL OR NOT et.isInformal); - IF vIsEditable AND NOT IFNULL(@isModeInventory, FALSE) THEN + IF vIsNotEditable AND NOT IFNULL(@isModeInventory, FALSE) THEN CALL util.throw(CONCAT('Entry ', vSelf, ' is not editable')); END IF; + END$$ DELIMITER ; diff --git a/db/routines/vn/procedures/entry_splitByShelving.sql b/db/routines/vn/procedures/entry_splitByShelving.sql index 3201900e6..f5de36098 100644 --- a/db/routines/vn/procedures/entry_splitByShelving.sql +++ b/db/routines/vn/procedures/entry_splitByShelving.sql @@ -23,12 +23,13 @@ BEGIN LEAST(bb.stickers, FLOOR(ish.visible / ish.packing)) ishStickers, bb.stickers buyStickers FROM itemShelving ish + JOIN shelving sh ON sh.id = ish.shelvingFk JOIN (SELECT b.id, b.itemFk, b.stickers FROM buy b WHERE b.entryFk = vFromEntryFk ORDER BY b.stickers DESC LIMIT 10000000000000000000) bb ON bb.itemFk = ish.itemFk - WHERE ish.shelvingFk = vShelvingCode COLLATE utf8_general_ci + WHERE sh.code = vShelvingCode COLLATE utf8_general_ci AND NOT ish.isSplit GROUP BY ish.id; diff --git a/db/routines/vn/procedures/expeditionScan_Put.sql b/db/routines/vn/procedures/expeditionScan_Put.sql index fc7d4da23..999b9af10 100644 --- a/db/routines/vn/procedures/expeditionScan_Put.sql +++ b/db/routines/vn/procedures/expeditionScan_Put.sql @@ -4,12 +4,12 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`expeditionScan_Put`( vExpeditionFk INT ) BEGIN - IF NOT (SELECT TRUE FROM expedition WHERE id = vExpeditionFk LIMIT 1) THEN - CALL util.throw('Expedition not exists'); + IF NOT EXISTS (SELECT id FROM expeditionPallet WHERE id = vPalletFk) THEN + CALL util.throw('Pallet not exists'); END IF; - IF NOT (SELECT TRUE FROM expeditionPallet WHERE id = vPalletFk LIMIT 1) THEN - CALL util.throw('Pallet not exists'); + IF NOT EXISTS (SELECT id FROM expedition WHERE id = vExpeditionFk) THEN + CALL util.throw('Expedition not exists'); END IF; REPLACE expeditionScan(expeditionFk, palletFk) diff --git a/db/routines/vn/procedures/expedition_selfConsumptionPackaging.sql b/db/routines/vn/procedures/expedition_selfConsumptionPackaging.sql index 43660f215..327934a43 100644 --- a/db/routines/vn/procedures/expedition_selfConsumptionPackaging.sql +++ b/db/routines/vn/procedures/expedition_selfConsumptionPackaging.sql @@ -3,7 +3,7 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`expedition_selfConsum vSelf INT, vAction ENUM('add', 'remove') ) -BEGIN +proc:BEGIN /** * Maneja el consumo de cajas para autoconsumo, permitiendo * añadir o quitar cajas utilizadas según la acción indicada. @@ -37,14 +37,14 @@ BEGIN vWarehouseFk, vCreated FROM expedition e - JOIN packaging p ON p.id = e.packagingFk - JOIN item i ON i.id = p.itemFk + LEFT JOIN packaging p ON p.id = e.packagingFk + LEFT JOIN item i ON i.id = p.itemFk JOIN ticket t ON t.id = e.ticketFk JOIN productionConfig pc WHERE e.id = vSelf; - IF vClientFk IS NULL OR vAddressFk IS NULL THEN - CALL util.throw('Some config parameters are not set'); + IF vClientFk IS NULL OR vItemFk IS NULL THEN + LEAVE proc; END IF; SET vCreated = DATE(vCreated); diff --git a/db/routines/vn/procedures/invoiceIn_booking.sql b/db/routines/vn/procedures/invoiceIn_booking.sql index 36189afcc..cfe3adb0b 100644 --- a/db/routines/vn/procedures/invoiceIn_booking.sql +++ b/db/routines/vn/procedures/invoiceIn_booking.sql @@ -219,7 +219,7 @@ BEGIN ) eWithheld ON TRUE WHERE tii.taxTypeSageFk IS NOT NULL AND (tii.taxCode IS NULL OR tii.taxCode NOT IN ('import10', 'import21')) - GROUP BY tii.PorcentajeIva, tii.expenseFk; + GROUP BY tii.CuentaIvaRepercutido; -- Línea iva inversor sujeto pasivo INSERT INTO XDiario( @@ -284,7 +284,7 @@ BEGIN AND NOT(tii.isVies AND c.nontaxableTransactionTypeFk = tii.transactionTypeSageFk AND tii.taxCode = 'nonTaxable') - GROUP BY tii.PorcentajeIva, tii.expenseFk; + GROUP BY tii.CuentaIvaRepercutido; -- Actualización del registro original UPDATE invoiceIn ii diff --git a/db/routines/vn/procedures/itemShelvingLog_get.sql b/db/routines/vn/procedures/itemShelvingLog_get.sql deleted file mode 100644 index 5a943e867..000000000 --- a/db/routines/vn/procedures/itemShelvingLog_get.sql +++ /dev/null @@ -1,36 +0,0 @@ -DELIMITER $$ -CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`itemShelvingLog_get`( - vShelvingCode VARCHAR(10) -) -BEGIN -/** - * Devuelve el log de los item en cada carro - * - * @param vShelvingCode Matrícula del carro - * - */ - SELECT isl.itemShelvingFk, - isl.created, - isl.accion, - isl.itemFk, - isl.shelvingFk, - isl.quantity, - isl.visible, - isl.available, - isl.grouping, - isl.packing, - isl.stars, - item.longName, - item.size, - item.subName, - worker.code, - isl.accion - FROM item - JOIN itemShelvingLog isl ON item.id = isl.itemFk - JOIN worker ON isl.workerFk = worker.id - JOIN shelving sh ON sh.id = isl.shelvingFk - WHERE sh.code = vShelvingCode COLLATE utf8mb3_unicode_ci - OR isl.itemFk = vShelvingCode -- ?? Respeto porque ya estaba - ORDER BY isl.created DESC; -END$$ -DELIMITER ; diff --git a/db/routines/vn/procedures/itemShelvingSale_setQuantity.sql b/db/routines/vn/procedures/itemShelvingSale_setQuantity.sql index f141762b5..1975180d1 100644 --- a/db/routines/vn/procedures/itemShelvingSale_setQuantity.sql +++ b/db/routines/vn/procedures/itemShelvingSale_setQuantity.sql @@ -48,7 +48,7 @@ BEGIN iss.itemShelvingFk, SUM(IFNULL(iss.quantity,0)), IF(sgd.id, 'PREVIOUS_PREPARATION', 'PREPARED'), - ish.shelvingFk + sh.code INTO vItemFk, vSaleFk, vItemShelvingFk, @@ -58,7 +58,8 @@ BEGIN FROM itemShelvingSale iss JOIN sale s ON s.id = iss.saleFk JOIN itemShelving ish ON ish.id = iss.itemShelvingFk - LEFT JOIN vn.saleGroupDetail sgd ON sgd.saleFk = iss.saleFk + LEFT JOIN saleGroupDetail sgd ON sgd.saleFk = iss.saleFk + LEFT JOIN shelving sh ON sh.id = ish.shelvingFk WHERE iss.id = vItemShelvingSaleFk AND NOT iss.isPicked; diff --git a/db/routines/vn/procedures/itemShelving_get.sql b/db/routines/vn/procedures/itemShelving_get.sql index 93022c2af..0038257c2 100644 --- a/db/routines/vn/procedures/itemShelving_get.sql +++ b/db/routines/vn/procedures/itemShelving_get.sql @@ -21,7 +21,8 @@ BEGIN ish.isChecked, ic.url, ish.available, - ish.buyFk + ish.buyFk, + ish.shelvingFk FROM itemShelving ish JOIN item i ON i.id = ish.itemFk JOIN shelving s ON s.id = ish.shelvingFk diff --git a/db/routines/vn/procedures/route_calcCommission.sql b/db/routines/vn/procedures/route_calcCommission.sql index 7c911a5e2..7db0b2682 100644 --- a/db/routines/vn/procedures/route_calcCommission.sql +++ b/db/routines/vn/procedures/route_calcCommission.sql @@ -11,6 +11,8 @@ BEGIN */ DECLARE vIsUpdatable, vIsFreelance BOOL DEFAULT 0; DECLARE vAgencyModePricePercentage DOUBLE; + DECLARE vIsKmTruckRate BOOL; + DECLARE vCountryFk INT; SELECT r.created >= rc.cutoffDated INTO vIsUpdatable FROM route r @@ -21,10 +23,17 @@ BEGIN DELETE FROM routeCommission WHERE routeFk = vSelf; - SELECT w.isFreelance INTO vIsFreelance + SELECT w.isFreelance, v.isKmTruckRate, p.countryFk INTO vIsFreelance, vIsKmTruckRate, vCountryFk FROM route r JOIN worker w ON w.id = r.workerFk - WHERE r.id = vSelf; + JOIN vehicle v ON v.id = r.vehicleFk + LEFT JOIN ticket t ON t.routeFk = r.id + LEFT JOIN address a ON a.id = t.addressFk + LEFT JOIN province p ON p.id = a.provinceFk + WHERE r.id = vSelf + GROUP BY p.countryFk + ORDER BY COUNT(*) DESC + LIMIT 1; SELECT ampp.percentage INTO vAgencyModePricePercentage FROM route r @@ -39,7 +48,9 @@ BEGIN workCenterFk, freelanceYearlyM3, cat4m3, - cat5m3 + cat5m3, + isKmTruckRate, + countryFk ) SELECT vSelf, r.commissionWorkCenterFk, @@ -51,11 +62,14 @@ BEGIN IFNULL(r.m3, 0), 0 ), - rc.distributionCat4M3 * IFNULL(r.m3, 0), - rc.distributionCat5M3 * IFNULL(r.m3, 0) + IFNULL(wc.distributionCat4M3, rc.distributionCat4M3) * IFNULL(r.m3, 0), + IFNULL(wc.distributionCat5M3, rc.distributionCat5M3) * IFNULL(r.m3, 0), + vIsKmTruckRate, + vCountryFk FROM route r JOIN vehicle v ON v.id = r.vehicleFk JOIN routeConfig rc + LEFT JOIN workCenterCommission wc ON wc.workCenterFk = r.commissionWorkCenterFk WHERE r.id = vSelf AND r.workerFk AND r.commissionWorkCenterFk; @@ -68,21 +82,28 @@ BEGIN yearlyKm, yearlyM3, cat4m3, - cat5m3 + cat5m3, + isKmTruckRate, + countryFk ) SELECT vSelf, r.commissionWorkCenterFk, (r.kmEnd - r.kmStart) * IF(v.isKmTruckRate, rc.kmHeavy, rc.kmLight), IFNULL(r.m3, 0) * - IF(v.isKmTruckRate, rc.deliveryM3Cat5, rc.deliveryM3Cat4), + IF(v.isKmTruckRate, + IFNULL(wc.deliveryM3Cat5, rc.deliveryM3Cat5), + IFNULL(wc.deliveryM3Cat4, rc.deliveryM3Cat4)), (r.kmEnd - r.kmStart) * rc.kmYearly, IFNULL(r.m3, 0) * rc.m3Yearly, - rc.distributionCat4M3 * IFNULL(r.m3, 0), - rc.distributionCat5M3 * IFNULL(r.m3, 0) + IFNULL(wc.distributionCat4M3, rc.distributionCat4M3) * IFNULL(r.m3, 0), + IFNULL(wc.distributionCat5M3, rc.distributionCat5M3) * IFNULL(r.m3, 0), + vIsKmTruckRate, + vCountryFk FROM route r JOIN vehicle v ON v.id = r.vehicleFk JOIN routeConfig rc + LEFT JOIN workCenterCommission wc ON wc.workCenterFk = r.commissionWorkCenterFk WHERE r.id = vSelf AND r.kmStart AND r.kmEnd diff --git a/db/routines/vn/procedures/ticket_splitItemPackingType.sql b/db/routines/vn/procedures/ticket_splitItemPackingType.sql index 0ee865af5..31e0c24e7 100644 --- a/db/routines/vn/procedures/ticket_splitItemPackingType.sql +++ b/db/routines/vn/procedures/ticket_splitItemPackingType.sql @@ -5,122 +5,122 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`ticket_splitItemPacki ) BEGIN /** - * Clona y reparte las ventas de un ticket en funcion del tipo de empaquetado. - * Respeta el id inicial para el tipo propuesto. + * Separa en diferentes tickets según el tipo de empaquetado + * El ticket original conserva las líneas del tipo de empaquetado especificado + * Las líneas sin tipo de empaquetado se asignan al ticket del tipo por defecto. * - * @param vSelf Id ticket - * @param vOriginalItemPackingTypeFk Tipo para el que se reserva el número de ticket original + * @param vSelf Id del ticket original + * @param vOriginalItemPackingTypeFk Tipo de empaquetado a mantener en el ticket original * @return table tmp.ticketIPT(ticketFk, itemPackingTypeFk) */ - DECLARE vItemPackingTypeFk VARCHAR(1) DEFAULT 'H'; + DECLARE vIsDone BOOLEAN DEFAULT FALSE; + DECLARE vCurrentPackingType VARCHAR(1); + DECLARE vDefaultPackingType VARCHAR(1); + DECLARE vHasOriginalPackingType BOOLEAN; DECLARE vNewTicketFk INT; - DECLARE vPackingTypesToSplit INT; - DECLARE vDone INT DEFAULT FALSE; + DECLARE vTicketFk INT; - DECLARE vSaleGroup CURSOR FOR - SELECT itemPackingTypeFk - FROM tSaleGroup - WHERE itemPackingTypeFk IS NOT NULL - ORDER BY (itemPackingTypeFk = vOriginalItemPackingTypeFk) DESC; + DECLARE vItemPackingTypes CURSOR FOR + SELECT DISTINCT itemPackingTypeFk FROM tSalesToMove; - DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE; + DECLARE CONTINUE HANDLER FOR NOT FOUND SET vIsDone = TRUE; + + DECLARE EXIT HANDLER FOR SQLEXCEPTION + BEGIN + ROLLBACK; + RESIGNAL; + END; + + CREATE OR REPLACE TEMPORARY TABLE tSalesToMove ( + ticketFk INT, + saleFk INT, + itemPackingTypeFk VARCHAR(1) + ) ENGINE=MEMORY; + + SELECT COALESCE(MAX(ic.defaultPackingTypeFk), MAX(i.itemPackingTypeFk)) INTO vDefaultPackingType + FROM vn.sale s + JOIN item i ON i.id = s.itemFk + LEFT JOIN itemConfig ic ON ic.defaultPackingTypeFk = i.itemPackingTypeFk + WHERE s.ticketFk = vSelf + GROUP BY s.ticketFk; + + SELECT EXISTS ( + SELECT TRUE + FROM sale s + JOIN item i ON i.id = s.itemFk + WHERE s.ticketFk = vSelf + AND i.itemPackingTypeFk = vOriginalItemPackingTypeFk + ) INTO vHasOriginalPackingType; + + IF vOriginalItemPackingTypeFk IS NULL OR NOT vHasOriginalPackingType THEN + SET vOriginalItemPackingTypeFk = vDefaultPackingType; + END IF; START TRANSACTION; - SELECT id - FROM sale - WHERE ticketFk = vSelf - AND NOT quantity + SELECT t.id INTO vTicketFk + FROM ticket t + JOIN sale s ON s.id = t.id + WHERE t.id = vSelf FOR UPDATE; - DELETE FROM sale - WHERE NOT quantity - AND ticketFk = vSelf; - - CREATE OR REPLACE TEMPORARY TABLE tSale - (PRIMARY KEY (id)) - ENGINE = MEMORY - SELECT s.id, i.itemPackingTypeFk, IFNULL(sv.litros, 0) litros + INSERT INTO tSalesToMove (saleFk, itemPackingTypeFk) + SELECT s.id, i.itemPackingTypeFk FROM sale s JOIN item i ON i.id = s.itemFk - LEFT JOIN saleVolume sv ON sv.saleFk = s.id - WHERE s.ticketFk = vSelf; + WHERE s.ticketFk = vSelf + AND i.itemPackingTypeFk <> vOriginalItemPackingTypeFk; - CREATE OR REPLACE TEMPORARY TABLE tSaleGroup - ENGINE = MEMORY - SELECT itemPackingTypeFk, SUM(litros) totalLitros - FROM tSale - GROUP BY itemPackingTypeFk; + OPEN vItemPackingTypes; + l: LOOP + SET vIsDone = FALSE; + FETCH vItemPackingTypes INTO vCurrentPackingType; - SELECT COUNT(*) INTO vPackingTypesToSplit - FROM tSaleGroup - WHERE itemPackingTypeFk IS NOT NULL; + IF vIsDone THEN + LEAVE l; + END IF; - CREATE OR REPLACE TEMPORARY TABLE tmp.ticketIPT( - ticketFk INT, - itemPackingTypeFk VARCHAR(1) - ) ENGINE = MEMORY; + CALL ticket_Clone(vSelf, vNewTicketFk); - CASE vPackingTypesToSplit - WHEN 0 THEN - INSERT INTO tmp.ticketIPT(ticketFk, itemPackingTypeFk) - VALUES(vSelf, vItemPackingTypeFk); - WHEN 1 THEN - INSERT INTO tmp.ticketIPT(ticketFk, itemPackingTypeFk) - SELECT vSelf, itemPackingTypeFk - FROM tSaleGroup - WHERE itemPackingTypeFk IS NOT NULL; - ELSE - OPEN vSaleGroup; - FETCH vSaleGroup INTO vItemPackingTypeFk; + SELECT id INTO vTicketFk + FROM ticket t + WHERE t.id = vNewTicketFk + FOR UPDATE; - INSERT INTO tmp.ticketIPT(ticketFk, itemPackingTypeFk) - VALUES(vSelf, vItemPackingTypeFk); + UPDATE tSalesToMove + SET ticketFk = vNewTicketFk + WHERE itemPackingTypeFk = vCurrentPackingType; - l: LOOP - SET vDone = FALSE; - FETCH vSaleGroup INTO vItemPackingTypeFk; + IF vCurrentPackingType = vDefaultPackingType THEN + INSERT INTO tSalesToMove (ticketFk, saleFk, itemPackingTypeFk) + SELECT vNewTicketFk, s.id, i.itemPackingTypeFk + FROM sale s + JOIN item i ON i.id = s.itemFk + WHERE s.ticketFk = vSelf + AND i.itemPackingTypeFk IS NULL; + END IF; - IF vDone THEN - LEAVE l; - END IF; + END LOOP; + CLOSE vItemPackingTypes; - CALL ticket_Clone(vSelf, vNewTicketFk); + UPDATE sale s + JOIN tSalesToMove t ON t.saleFk = s.id + SET s.ticketFk = t.ticketFk; - INSERT INTO tmp.ticketIPT(ticketFk, itemPackingTypeFk) - VALUES(vNewTicketFk, vItemPackingTypeFk); - END LOOP; - - CLOSE vSaleGroup; - - SELECT s.id - FROM sale s - JOIN tSale ts ON ts.id = s.id - JOIN tmp.ticketIPT t ON t.itemPackingTypeFk = ts.itemPackingTypeFk - FOR UPDATE; - - UPDATE sale s - JOIN tSale ts ON ts.id = s.id - JOIN tmp.ticketIPT t ON t.itemPackingTypeFk = ts.itemPackingTypeFk - SET s.ticketFk = t.ticketFk; - - SELECT itemPackingTypeFk INTO vItemPackingTypeFk - FROM tSaleGroup sg - WHERE sg.itemPackingTypeFk IS NOT NULL - ORDER BY sg.itemPackingTypeFk - LIMIT 1; - - UPDATE sale s - JOIN tSale ts ON ts.id = s.id - JOIN tmp.ticketIPT t ON t.itemPackingTypeFk = vItemPackingTypeFk - SET s.ticketFk = t.ticketFk - WHERE ts.itemPackingTypeFk IS NULL; - END CASE; + CREATE OR REPLACE TEMPORARY TABLE tmp.ticketIPT + ENGINE=MEMORY + SELECT s.ticketFk, MAX(i.itemPackingTypeFk) itemPackingTypeFk + FROM sale s + JOIN item i ON i.id = s.itemFk + WHERE s.ticketFk = vSelf + GROUP BY s.ticketFk + UNION + SELECT ticketFk, MAX(itemPackingTypeFk) + FROM tSalesToMove + GROUP BY ticketFk; COMMIT; - DROP TEMPORARY TABLE - tSale, - tSaleGroup; + DROP TEMPORARY TABLE tSalesToMove; END$$ DELIMITER ; diff --git a/db/routines/vn/procedures/workerTimeControl_check.sql b/db/routines/vn/procedures/workerTimeControl_check.sql deleted file mode 100644 index 30cf5c639..000000000 --- a/db/routines/vn/procedures/workerTimeControl_check.sql +++ /dev/null @@ -1,168 +0,0 @@ -DELIMITER $$ -CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`workerTimeControl_check`(vUserFk INT, vDated DATE,vTabletFk VARCHAR(100)) -proc: BEGIN -/** - * Verifica si el empleado puede fichar en el momento actual, si puede fichar llama a workerTimeControlAdd - * - * @param vUserFk Identificador del trabajador - * @return Retorna si encuentra un problema 'odd','maxTimeWork','breakDay','breakWeek' ; - * En caso de tener algun problema retorna el primero que encuentra - */ - DECLARE vLastIn DATETIME ; - DECLARE vLastOut DATETIME ; - DECLARE vDayWorkMax INT; - DECLARE vDayBreak INT; - DECLARE vWeekBreak INT ; - DECLARE vWeekScope INT; - DECLARE vDayStayMax INT; - DECLARE vProblem VARCHAR(20) DEFAULT NULL; - DECLARE vTimedWorked INT; - DECLARE vCalendarStateType VARCHAR(20) DEFAULT NULL; - DECLARE vDepartmentFk INT; - DECLARE vTo VARCHAR(50) DEFAULT NULL; - DECLARE vUserName VARCHAR(50) DEFAULT NULL; - DECLARE vBody VARCHAR(255) DEFAULT NULL; - - SELECT dayBreak, weekBreak, weekScope, dayWorkMax, dayStayMax - INTO vDayBreak, vWeekBreak, vWeekScope, vDayWorkMax, vDayStayMax - FROM workerTimeControlParams; - - SELECT MAX(timed) INTO vLastIn - FROM workerTimeControl - WHERE userFk = vUserFk - AND direction = 'in'; - - SELECT MAX(timed) INTO vLastOut - FROM workerTimeControl - WHERE userFk = vUserFk - AND direction = 'out'; - - SELECT CONCAT(u.name,'@verdnatura.es') INTO vTo - FROM account.user u - WHERE u.id = (SELECT bossFk FROM worker WHERE id = vUserFk); - - SELECT CONCAT(firstName,' ',lastName) INTO vUserName - FROM worker w - WHERE w.id = vUserFk; - - - IF UNIX_TIMESTAMP(util.VN_NOW()) - UNIX_TIMESTAMP(vLastIn) > vDayStayMax THEN -- NUEVA JORNADA - - -- VERIFICAR DESCANSO DIARIO - IF UNIX_TIMESTAMP(util.VN_NOW()) - UNIX_TIMESTAMP(vLastOut) < vDayBreak THEN - SELECT "Descansos 12 h" AS problem; - -- ENVIAMOS CORREO AL BOSSFK - SELECT CONCAT(vUserName,' No ha podido fichar por el siguiente problema: ',"Descansos 12 h") INTO vBody; - CALL mail_insert(vTo,vTo,'error al fichar',vBody); - LEAVE proc; - END IF; - - -- VERIFICAR FICHADAS IMPARES DEL ÚLTIMO DÍA QUE SE FICHÓ - IF (SELECT MOD(COUNT(*),2) -- <>0 - FROM workerTimeControl - WHERE userFk = vUserFk - AND timed >= vLastIn - ) THEN - SELECT "Dias con fichadas impares" AS problem; - -- ENVIAMOS CORREO AL BOSSFK - SELECT CONCAT(vUserName,' No ha podido fichar por el siguiente problema: ',"Dias con fichadas impares") INTO vBody; - CALL mail_insert(vTo,vTo,'error al fichar',vBody); - LEAVE proc; - END IF; - - -- VERIFICAR VACACIONES - SELECT at2.name INTO vCalendarStateType - FROM calendar c - JOIN business b ON b.id = c.businessFk - JOIN absenceType at2 ON at2.id = c.dayOffTypeFk - WHERE c.dated = util.VN_CURDATE() - AND at2.isAllowedToWork = FALSE - AND b.workerFk = vUserFk - LIMIT 1; - - IF(LENGTH(vCalendarStateType)) THEN - SELECT vCalendarStateType AS problem; - -- ENVIAMOS CORREO AL BOSSFK - SELECT CONCAT(vUserName,' No ha podido fichar por el siguiente problema: ',"Vacaciones") INTO vBody; - CALL mail_insert(vTo,vTo,'error al fichar',vBody); - LEAVE proc; - - END IF; - - -- VERIFICAR CONTRATO EN VIGOR - IF (SELECT COUNT(*) - FROM business b - WHERE b.workerFk = vUserFk - AND b.started <= vDated - AND IFNULL(b.ended, vDated) >= vDated - ) = 0 THEN - SELECT "No hay un contrato en vigor" AS problem; - -- ENVIAMOS CORREO AL BOSSFK - SELECT CONCAT(vUserName,' No ha podido fichar por el siguiente problema: ',"No hay un contrato en vigor") INTO vBody; - CALL mail_insert(vTo,vTo,'error al fichar',vBody); - LEAVE proc; - - END IF; - - -- VERIFICAR DESCANSO SEMANAL - SET @vHasBreakWeek:= FALSE; - SET @vLastTimed:= UNIX_TIMESTAMP((util.VN_NOW() - INTERVAL vWeekScope SECOND)); - - DROP TEMPORARY TABLE IF EXISTS tmp.trash; - CREATE TEMPORARY TABLE tmp.trash - SELECT IF(vWeekBreak-(UNIX_TIMESTAMP(timed)-@vLastTimed) <= 0, @vHasBreakWeek:=TRUE, TRUE) alias, - @vLastTimed:= UNIX_TIMESTAMP(timed) - FROM workerTimeControl - WHERE timed>= (util.VN_NOW() - INTERVAL vWeekScope SECOND) - AND userFk= vUserFk - AND direction IN ('in','out') - ORDER BY timed ASC; - - IF UNIX_TIMESTAMP(util.VN_NOW()) - UNIX_TIMESTAMP(vLastOut) < vWeekBreak AND @vHasBreakWeek = FALSE THEN -- REVISA SI EL DESCANSO SE HA REALIZADO DESPUÉS DE LA ÚLTIMA FICHADA - SELECT "Descansos 36 h" AS problem; - -- ENVIAMOS CORREO AL BOSSFK - SELECT CONCAT(vUserName,' No ha podido fichar por el siguiente problema: ',"Descansos 36 h") INTO vBody; - CALL mail_insert(vTo,vTo,'error al fichar',vBody); - LEAVE proc; - END IF; - - DROP TEMPORARY TABLE tmp.trash; - - ELSE -- DIA ACTUAL - - -- VERIFICA QUE EL TIEMPO EFECTIVO NO SUPERE EL MÁXIMO - SELECT IFNULL(SUM(if( mod(wtc.order,2)=1, -UNIX_TIMESTAMP(timed), UNIX_TIMESTAMP(timed))),0) - IF( MOD(COUNT(*),2), UNIX_TIMESTAMP(util.VN_NOW()), 0) INTO vTimedWorked - FROM workerTimeControl wtc - WHERE userFk = vUserFk - AND timed >= vLastIn - ORDER BY timed; - - IF vTimedWorked > vDayWorkMax THEN - SELECT "Jornadas" AS problem; - -- ENVIAMOS CORREO AL BOSSFK - SELECT CONCAT(vUserName,' No ha podido fichar por el siguiente problema: ',"Jornadas") INTO vBody; - CALL mail_insert(vTo,vTo,'error al fichar',vBody); - LEAVE proc; - END IF; - - END IF; - - -- VERIFICAR DEPARTAMENTO - /* IF vTabletFk IS NOT NULL THEN - SELECT wtcu.departmentFk INTO vDepartmentFk - FROM workerTimeControlUserInfo wtcu - WHERE wtcu.userFk = vUserFk; - IF (SELECT COUNT(td.tabletFk) - FROM tabletDepartment td - WHERE td.tabletFk = vTabletFk AND td.departmentFk = vDepartmentFk - ) = 0 THEN - SELECT "No perteneces a este departamento." AS problem; - -- ENVIAMOS CORREO AL BOSSFK - SELECT CONCAT(vUserName,' No a podido fichar por el siguiente problema: ',"No perteneces a este departamento.") INTO vBody; - CALL mail_insert(vTo,vTo,'error al fichar',vBody); - LEAVE proc; - END IF; - END IF;*/ - -END$$ -DELIMITER ; diff --git a/db/routines/vn/triggers/entry_beforeUpdate.sql b/db/routines/vn/triggers/entry_beforeUpdate.sql index 1d0c26fc1..4f2c5ed4a 100644 --- a/db/routines/vn/triggers/entry_beforeUpdate.sql +++ b/db/routines/vn/triggers/entry_beforeUpdate.sql @@ -38,10 +38,10 @@ BEGIN CALL travel_throwAwb(NEW.travelFk); END IF; - SELECT isRaid INTO vIsRaid + SELECT t.isRaid INTO vIsRaid FROM travel t JOIN entry e ON e.travelFk = t.id - WHERE entryFk = NEW.id; + WHERE e.id = NEW.id; SELECT NOT (o.warehouseInFk <=> n.warehouseInFk) OR NOT (o.warehouseOutFk <=> n.warehouseOutFk) diff --git a/db/routines/vn/triggers/itemShelving_afterInsert.sql b/db/routines/vn/triggers/itemShelving_afterInsert.sql deleted file mode 100644 index 92243ca03..000000000 --- a/db/routines/vn/triggers/itemShelving_afterInsert.sql +++ /dev/null @@ -1,18 +0,0 @@ -DELIMITER $$ -CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`itemShelving_afterInsert` - AFTER INSERT ON `itemShelving` - FOR EACH ROW -BEGIN - INSERT INTO itemShelvingLog - SET itemShelvingFk = NEW.id, - workerFk = account.myUser_getId(), - accion = 'CREA REGISTRO', - itemFk = NEW.itemFk, - shelvingFk = NEW.shelvingFk, - visible = NEW.visible, - `grouping` = NEW.`grouping`, - packing = NEW.packing, - available = NEW.available; - -END$$ -DELIMITER ; diff --git a/db/routines/vn/triggers/itemShelving_afterUpdate.sql b/db/routines/vn/triggers/itemShelving_afterUpdate.sql deleted file mode 100644 index e5e63db43..000000000 --- a/db/routines/vn/triggers/itemShelving_afterUpdate.sql +++ /dev/null @@ -1,18 +0,0 @@ -DELIMITER $$ -CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`itemShelving_afterUpdate` - AFTER UPDATE ON `itemShelving` - FOR EACH ROW -BEGIN - INSERT INTO itemShelvingLog - SET itemShelvingFk = NEW.id, - workerFk = account.myUser_getId(), - accion = 'CAMBIO', - itemFk = NEW.itemFk, - shelvingFk = NEW.shelvingFk, - visible = NEW.visible, - `grouping` = NEW.`grouping`, - packing = NEW.packing, - available = NEW.available; - -END$$ -DELIMITER ; diff --git a/db/routines/vn/triggers/itemShelving_beforeDelete.sql b/db/routines/vn/triggers/itemShelving_beforeDelete.sql deleted file mode 100644 index 89737a841..000000000 --- a/db/routines/vn/triggers/itemShelving_beforeDelete.sql +++ /dev/null @@ -1,15 +0,0 @@ -DELIMITER $$ -CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`itemShelving_beforeDelete` - BEFORE DELETE ON `itemShelving` - FOR EACH ROW -INSERT INTO vn.itemShelvingLog(itemShelvingFk, - workerFk, - accion, - shelvingFk, - itemFk) - VALUES( OLD.id, - account.myUser_getId(), - 'ELIMINADO', - OLD.shelvingFk, - OLD.itemFk)$$ -DELIMITER ; diff --git a/db/routines/vn/triggers/travel_beforeUpdate.sql b/db/routines/vn/triggers/travel_beforeUpdate.sql index 5a27b43b4..256dd35f8 100644 --- a/db/routines/vn/triggers/travel_beforeUpdate.sql +++ b/db/routines/vn/triggers/travel_beforeUpdate.sql @@ -20,10 +20,6 @@ BEGIN CALL travel_checkWarehouseIsFeedStock(NEW.warehouseInFk); END IF; - IF NOT (NEW.isRaid <=> OLD.isRaid) OR NOT (NEW.daysInForward <=> OLD.daysInForward) THEN - CALL travel_checkRaid(NEW.isRaid, NEW.daysInForward); - END IF; - IF NOT (NEW.awbFk <=> OLD.awbFk)THEN SELECT COUNT(*) INTO vHasAnyInvoiceBooked FROM travel t diff --git a/db/versions/11312-navyAralia/00-firstScript.sql b/db/versions/11312-navyAralia/00-firstScript.sql new file mode 100644 index 000000000..452b1feed --- /dev/null +++ b/db/versions/11312-navyAralia/00-firstScript.sql @@ -0,0 +1,23 @@ +ALTER TABLE vn.workerRelatives DROP FOREIGN KEY workerRelatives_disabilityGradeFk; +ALTER TABLE vn.workerRelatives DROP FOREIGN KEY workerRelatives_workerFk; + +INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId) + VALUES + ('WorkerRelative','updateAttributes','*','ALLOW','ROLE','hr'), + ('WorkerRelative','crud','WRITE','ALLOW','ROLE','hr'), + ('WorkerRelative','findById','*','ALLOW','ROLE','hr'), + ('WorkerRelative','find','*','ALLOW','ROLE','hr'), + ('WorkerRelative','upsert','*','ALLOW','ROLE','hr'), + ('WorkerRelative','filter','*','ALLOW','ROLE','hr'), + ('WorkerIrpf','updateAttributes','*','ALLOW','ROLE','hr'), + ('WorkerIrpf','crud','*','ALLOW','ROLE','hr'), + ('WorkerIrpf','findById','*','ALLOW','ROLE','hr'), + ('WorkerIrpf','find','*','ALLOW','ROLE','hr'), + ('WorkerIrpf','upsert','*','ALLOW','ROLE','hr'), + ('WorkerIrpf','filter','*','ALLOW','ROLE','hr'), + ('DisabilityGrade','updateAttributes','*','ALLOW','ROLE','hr'), + ('DisabilityGrade','crud','*','ALLOW','ROLE','hr'), + ('DisabilityGrade','findById','*','ALLOW','ROLE','hr'), + ('DisabilityGrade','find','*','ALLOW','ROLE','hr'), + ('DisabilityGrade','upsert','*','ALLOW','ROLE','hr'); + diff --git a/db/versions/11322-azureAspidistra/00-entryAcl.sql b/db/versions/11322-azureAspidistra/00-entryAcl.sql new file mode 100644 index 000000000..836737d4b --- /dev/null +++ b/db/versions/11322-azureAspidistra/00-entryAcl.sql @@ -0,0 +1,40 @@ +-- Eliminar registros existentes donde property = '*' +DELETE FROM `salix`.ACL WHERE model = 'entry' AND property = '*'; + +-- Insertar permisos para los métodos solicitados en el modelo Entry +INSERT INTO `salix`.ACL (model, property, accessType, permission, principalType, principalId) +VALUES + -- Permisos para administrative + ('Entry', 'upsert', 'WRITE', 'ALLOW', 'ROLE', 'administrative'), + ('Entry', 'updateAttributes', 'WRITE', 'ALLOW', 'ROLE', 'administrative'), + ('Entry', 'isBooked', 'READ', 'ALLOW', 'ROLE', 'administrative'), + ('Entry', 'findById', 'READ', 'ALLOW', 'ROLE', 'administrative'), + ('Entry', 'find', 'READ', 'ALLOW', 'ROLE', 'administrative'), + ('Entry', 'filter', 'READ', 'ALLOW', 'ROLE', 'administrative'), + ('Entry', 'count', 'READ', 'ALLOW', 'ROLE', 'administrative'), + ('Entry', 'getEntry', 'READ', 'ALLOW', 'ROLE', 'administrative'), + ('Entry', 'getBuys', 'READ', 'ALLOW', 'ROLE', 'administrative'), + ('Entry', 'findOne', 'READ', 'ALLOW', 'ROLE', 'administrative'), + ('Entry', 'deleteBuys', 'WRITE', 'ALLOW', 'ROLE', 'administrative'), + ('Entry', 'editLatestBuys', 'WRITE', 'ALLOW', 'ROLE', 'administrative'), + ('Entry', 'importBuys', 'WRITE', 'ALLOW', 'ROLE', 'administrative'), + ('Entry', 'importBuysPreview', 'READ', 'ALLOW', 'ROLE', 'administrative'), + ('Entry', 'lastItemBuys', 'READ', 'ALLOW', 'ROLE', 'administrative'), + ('Entry', 'latestBuysFilter', 'READ', 'ALLOW', 'ROLE', 'administrative'), + + -- Permisos para buyer (excluyendo isBooked) + ('Entry', 'upsert', 'WRITE', 'ALLOW', 'ROLE', 'buyer'), + ('Entry', 'updateAttributes', 'WRITE', 'ALLOW', 'ROLE', 'buyer'), + ('Entry', 'findById', 'READ', 'ALLOW', 'ROLE', 'buyer'), + ('Entry', 'find', 'READ', 'ALLOW', 'ROLE', 'buyer'), + ('Entry', 'filter', 'READ', 'ALLOW', 'ROLE', 'buyer'), + ('Entry', 'count', 'READ', 'ALLOW', 'ROLE', 'buyer'), + ('Entry', 'getEntry', 'READ', 'ALLOW', 'ROLE', 'buyer'), + ('Entry', 'getBuys', 'READ', 'ALLOW', 'ROLE', 'buyer'), + ('Entry', 'findOne', 'READ', 'ALLOW', 'ROLE', 'buyer'), + ('Entry', 'deleteBuys', 'WRITE', 'ALLOW', 'ROLE', 'buyer'), + ('Entry', 'editLatestBuys', 'WRITE', 'ALLOW', 'ROLE', 'buyer'), + ('Entry', 'importBuys', 'WRITE', 'ALLOW', 'ROLE', 'buyer'), + ('Entry', 'importBuysPreview', 'READ', 'ALLOW', 'ROLE', 'buyer'), + ('Entry', 'lastItemBuys', 'READ', 'ALLOW', 'ROLE', 'buyer'), + ('Entry', 'latestBuysFilter', 'READ', 'ALLOW', 'ROLE', 'buyer'); diff --git a/db/versions/11332-tealErica/00-firstScript.sql b/db/versions/11332-tealErica/00-firstScript.sql index 6358695b2..a7870632f 100644 --- a/db/versions/11332-tealErica/00-firstScript.sql +++ b/db/versions/11332-tealErica/00-firstScript.sql @@ -1,4 +1,4 @@ -ALTER TABLE vn.travel ADD isRaid tinyint(1) DEFAULT 0 NOT NULL COMMENT 'Redada'; +ALTER TABLE vn.travel ADD IF NOT EXISTS isRaid tinyint(1) DEFAULT 0 NOT NULL COMMENT 'Redada'; ALTER TABLE vn.travel MODIFY COLUMN daysInForward int(10) unsigned DEFAULT NULL - COMMENT 'Cuando es una redada, indica el número de días que se añadirán a la fecha de hoy para establecer el landed. NULL si no es una redada'; + COMMENT 'Cuando es una redada, indica el número de días que se añadirán a la fecha de hoy para establecer el landed. NULL si no es una redada'; \ No newline at end of file diff --git a/db/versions/11351-bronzeMedeola/00-firstScript.sql b/db/versions/11351-bronzeMedeola/00-firstScript.sql new file mode 100644 index 000000000..c94447a89 --- /dev/null +++ b/db/versions/11351-bronzeMedeola/00-firstScript.sql @@ -0,0 +1,2 @@ + +ALTER TABLE vn.itemConfig ADD defaultPackingTypeFk VARCHAR(1) DEFAULT 'H' NULL; diff --git a/db/versions/11354-aquaMastic/00-firstScript.sql b/db/versions/11354-aquaMastic/00-firstScript.sql new file mode 100644 index 000000000..dda3f4752 --- /dev/null +++ b/db/versions/11354-aquaMastic/00-firstScript.sql @@ -0,0 +1,2 @@ +RENAME TABLE vn.workerTimeControlParams TO vn.workerTimeControlParams__; +ALTER TABLE vn.workerTimeControlParams__ COMMENT='@deprecated 2024-11-19'; \ No newline at end of file diff --git a/db/versions/11355-pinkMedeola/00-firstScript.sql b/db/versions/11355-pinkMedeola/00-firstScript.sql new file mode 100644 index 000000000..fc89b386c --- /dev/null +++ b/db/versions/11355-pinkMedeola/00-firstScript.sql @@ -0,0 +1,3 @@ +-- Place your SQL code here +INSERT IGNORE INTO vn.saySimpleConfig (url, defaultChannel) + VALUES ('https://verdnatura.saysimple.io/start-conversation', 1320); \ No newline at end of file diff --git a/db/versions/11357-whiteGerbera/00-firstScript.sql b/db/versions/11357-whiteGerbera/00-firstScript.sql new file mode 100644 index 000000000..c10ec4d26 --- /dev/null +++ b/db/versions/11357-whiteGerbera/00-firstScript.sql @@ -0,0 +1,4 @@ +ALTER TABLE vn.travel ADD IF NOT EXISTS isRaid tinyint(1) DEFAULT 0 NOT NULL COMMENT 'Redada'; + +ALTER TABLE vn.travel MODIFY COLUMN daysInForward int(10) unsigned DEFAULT NULL + COMMENT 'Cuando es una redada, indica el número de días que se añadirán a la fecha de hoy para establecer el landed. NULL si no es una redada'; diff --git a/db/versions/11358-maroonPhormium/00-firstScript.sql b/db/versions/11358-maroonPhormium/00-firstScript.sql new file mode 100644 index 000000000..88762e5aa --- /dev/null +++ b/db/versions/11358-maroonPhormium/00-firstScript.sql @@ -0,0 +1,51 @@ + + ALTER TABLE vn.routeCommission ADD IF NOT EXISTS countryFk mediumint(8) unsigned DEFAULT NULL NULL; + ALTER TABLE vn.routeCommission ADD IF NOT EXISTS isKmTruckRate TINYINT(1) DEFAULT NULL NULL; + + ALTER TABLE vn.routeCommission DROP FOREIGN KEY IF EXISTS routeCommission_country_FK; + ALTER TABLE vn.routeCommission ADD CONSTRAINT routeCommission_country_FK FOREIGN KEY (countryFk) + REFERENCES vn.country(id) ON DELETE RESTRICT ON UPDATE CASCADE; + + CREATE TABLE IF NOT EXISTS vn.workCenterCommission ( + `workCenterFk` INT(11) NOT NULL, + `deliveryManAdjustment` DECIMAL(4,2) DEFAULT NULL + COMMENT 'Número de trabajadores para equilibrar los repartidores de diferentes centros. + Utilizado en repartidores de grafana', + `distributionM3Category1` decimal(5,2) DEFAULT NULL, + `distributionM3Category2` decimal(5,2) DEFAULT NULL, + `distributionCat4M3` DECIMAL(5,2) DEFAULT NULL + COMMENT 'Comisión por gestión de la distribución Cat IV', + `distributionCat5M3` DECIMAL(5,2) DEFAULT NULL + COMMENT 'Comisión por gestión de la distribución Cat V', + PRIMARY KEY (`workCenterFk`), + CONSTRAINT `workCenterCommission_workCenterFk` FOREIGN KEY (`workCenterFk`) + REFERENCES `workCenter` (`id`) ON UPDATE CASCADE ON DELETE RESTRICT + ); + + UPDATE vn.routeCommission rc + JOIN (SELECT id, countryFk, isKmTruckRate + FROM (SELECT r.id, c.countryFk, v.isKmTruckRate + FROM vn.route r + JOIN vn.routeCommission rc ON rc.routeFk = r.id + LEFT JOIN vn.ticket t ON t.routeFk = r.id + LEFT JOIN vn.client c ON c.id = t.clientFk + LEFT JOIN vn.vehicle v ON v.id = r.vehicleFk + WHERE r.created >= '2023-12-01' + GROUP BY r.id, c.countryFk + ORDER BY r.id, COUNT(*) DESC + LIMIT 100000000000 + )sub + GROUP BY id + )sub ON sub.id = rc.routeFk + SET rc.isKmTruckRate = sub.isKmTruckRate, + rc.countryFk = sub.countryFk; + + ALTER TABLE vn.workerDistributionCategory ADD IF NOT EXISTS countryFk mediumint(8) unsigned DEFAULT NULL NULL; + ALTER TABLE vn.workerDistributionCategory ADD IF NOT EXISTS isKmTruckRate TINYINT(1) DEFAULT NULL NULL; + + ALTER TABLE vn.workerDistributionCategory DROP FOREIGN KEY IF EXISTS workerDistributionCategory_country_FK; + ALTER TABLE vn.workerDistributionCategory ADD CONSTRAINT workerDistributionCategory_country_FK FOREIGN KEY (countryFk) + REFERENCES vn.country(id) ON DELETE RESTRICT ON UPDATE CASCADE; + + ALTER TABLE vn.workerDistributionCategory ADD IF NOT EXISTS commissionSplitWorkers INT UNSIGNED NOT NULL DEFAULT 1 + COMMENT 'Número de enrutadores entr los que se reparte la comsión'; diff --git a/db/versions/11359-navyPaniculata/00-firstScript.sql b/db/versions/11359-navyPaniculata/00-firstScript.sql new file mode 100644 index 000000000..de057b540 --- /dev/null +++ b/db/versions/11359-navyPaniculata/00-firstScript.sql @@ -0,0 +1,8 @@ +DELETE FROM vn.stateI18n + WHERE `name` IN ('Billed', 'Facturado', 'Assisted preparation', 'Preparación asistida', 'Shipped', 'Embarcado', 'Stowaway OK', 'Polizón OK'); + +UPDATE vn.`state` SET nextStateFk = 43 + WHERE nextStateFk IN (11, 27, 30, 32, 41); + +DELETE FROM vn.`state` + WHERE code IN ('INVOICED', 'ASSISTED_PREPARATION', 'BOARD', 'OK STOWAWAY', 'PARTIAL_PREPARATION'); \ No newline at end of file diff --git a/db/versions/11362-limeLilium/00-firstScript.sql b/db/versions/11362-limeLilium/00-firstScript.sql new file mode 100644 index 000000000..4a7c5b742 --- /dev/null +++ b/db/versions/11362-limeLilium/00-firstScript.sql @@ -0,0 +1,4 @@ + + +INSERT INTO salix.ACL (model, property, accessType, permission, principalType, principalId) +VALUES('SaleGroup', 'find', 'READ', 'ALLOW', 'ROLE', 'production'); \ No newline at end of file diff --git a/db/versions/11363-silverCarnation/00-firstScript.sql b/db/versions/11363-silverCarnation/00-firstScript.sql new file mode 100644 index 000000000..8c2e68ff4 --- /dev/null +++ b/db/versions/11363-silverCarnation/00-firstScript.sql @@ -0,0 +1,7 @@ +ALTER TABLE vn.workCenterCommission ADD IF NOT EXISTS deliveryM3Cat4 DECIMAL(5,2) DEFAULT NULL NULL; +ALTER TABLE vn.workCenterCommission ADD IF NOT EXISTS deliveryM3Cat5 DECIMAL(5,2) DEFAULT NULL NULL; + +INSERT IGNORE INTO vn.workCenterCommission (workCenterFk, deliveryM3Cat4, deliveryM3Cat5) + VALUES (5,8.0,8.0); + + diff --git a/db/versions/11366-navyBirch/00-firstScript.sql b/db/versions/11366-navyBirch/00-firstScript.sql new file mode 100644 index 000000000..4d56c13b8 --- /dev/null +++ b/db/versions/11366-navyBirch/00-firstScript.sql @@ -0,0 +1,2 @@ +RENAME TABLE vn.itemShelvingLog TO vn.itemShelvingLog__; +ALTER TABLE vn.itemShelvingLog__ COMMENT='@deprecated 2024-11-26'; diff --git a/db/versions/11367-grayOrchid/00-deprecate.sql b/db/versions/11367-grayOrchid/00-deprecate.sql new file mode 100644 index 000000000..19e82419e --- /dev/null +++ b/db/versions/11367-grayOrchid/00-deprecate.sql @@ -0,0 +1,7 @@ +ALTER TABLE `vn`.`creditInsurance` DROP COLUMN `creditClassification__`; +ALTER TABLE `vn`.`worker` DROP COLUMN `isF11Allowed__`; +ALTER TABLE `util`.`config` DROP COLUMN `dbVersion__`; +ALTER TABLE `util`.`config` DROP COLUMN `hasTriggersDisabled__`; +ALTER TABLE `vn`.`agencyMode` DROP COLUMN `showAgencyName__`; +DROP TABLE `account`.`accountLog__`; +DROP TABLE `vn`.`silexACL__`; diff --git a/db/versions/11369-azureChrysanthemum/00-firstScript.sql b/db/versions/11369-azureChrysanthemum/00-firstScript.sql new file mode 100644 index 000000000..3a86c0c59 --- /dev/null +++ b/db/versions/11369-azureChrysanthemum/00-firstScript.sql @@ -0,0 +1,5 @@ +ALTER TABLE vn.duaInvoiceIn DROP KEY IF EXISTS duaFk_UNIQUE; +ALTER TABLE vn.duaInvoiceIn DROP KEY IF EXISTS duaInvoiceIn_unique; +ALTER TABLE vn.duaInvoiceIn ADD CONSTRAINT duaInvoiceIn_unique + UNIQUE KEY (invoiceInFk); + diff --git a/e2e/paths/04-item/01_summary.spec.js b/e2e/paths/04-item/01_summary.spec.js new file mode 100644 index 000000000..51195be48 --- /dev/null +++ b/e2e/paths/04-item/01_summary.spec.js @@ -0,0 +1,133 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; + +describe('Item summary path', () => { + let browser; + let page; + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('employee', 'item'); + }); + + afterAll(async() => { + await browser.close(); + }); + + it('should search for an item', async() => { + await page.doSearch('Ranged weapon'); + const resultsCount = await page.countElement(selectors.itemsIndex.searchResult); + + await page.waitForTextInElement(selectors.itemsIndex.firstSearchResult, 'Ranged weapon'); + await page.waitToClick(selectors.itemsIndex.firstResultPreviewButton); + const isVisible = await page.isVisible(selectors.itemSummary.basicData); + + expect(resultsCount).toBe(4); + expect(isVisible).toBeTruthy(); + }); + + it(`should check the item summary preview shows fields from basic data`, async() => { + await page.waitForTextInElement(selectors.itemSummary.basicData, 'Ranged weapon longbow 200cm'); + const result = await page.waitToGetProperty(selectors.itemSummary.basicData, 'innerText'); + + expect(result).toContain('Ranged weapon longbow 200cm'); + }); + + it(`should check the item summary preview shows fields from tags`, async() => { + await page.waitForTextInElement(selectors.itemSummary.tags, 'Brown'); + const result = await page.waitToGetProperty(selectors.itemSummary.tags, 'innerText'); + + expect(result).toContain('Brown'); + }); + + it(`should check the item summary preview shows fields from botanical`, async() => { + await page.waitForTextInElement(selectors.itemSummary.botanical, 'Abelia'); + const result = await page.waitToGetProperty(selectors.itemSummary.botanical, 'innerText'); + + expect(result).toContain('Abelia'); + }); + + it(`should check the item summary preview shows fields from barcode`, async() => { + await page.waitForTextInElement(selectors.itemSummary.barcode, '1'); + const result = await page.waitToGetProperty(selectors.itemSummary.barcode, 'innerText'); + + expect(result).toContain('1'); + }); + + it(`should close the summary popup`, async() => { + await page.closePopup(); + await page.waitForSelector(selectors.itemSummary.basicData, {hidden: true}); + }); + + it('should search for other item', async() => { + await page.doSearch('Melee Reinforced'); + const resultsCount = await page.countElement(selectors.itemsIndex.searchResult); + + await page.waitToClick(selectors.itemsIndex.firstResultPreviewButton); + await page.waitForSelector(selectors.itemSummary.basicData, {visible: true}); + + expect(resultsCount).toBe(3); + }); + + it(`should now check the item summary preview shows fields from basic data`, async() => { + await page.waitForTextInElement(selectors.itemSummary.basicData, 'Melee Reinforced weapon combat fist 15cm'); + const result = await page.waitToGetProperty(selectors.itemSummary.basicData, 'innerText'); + + expect(result).toContain('Melee Reinforced weapon combat fist 15cm'); + }); + + it(`should now check the item summary preview shows fields from tags`, async() => { + await page.waitForTextInElement(selectors.itemSummary.tags, 'Silver'); + const result = await page.waitToGetProperty(selectors.itemSummary.tags, 'innerText'); + + expect(result).toContain('Silver'); + }); + + it(`should now check the item summary preview shows fields from botanical`, async() => { + await page.waitForTextInElement(selectors.itemSummary.botanical, '-'); + const result = await page.waitToGetProperty(selectors.itemSummary.botanical, 'innerText'); + + expect(result).toContain('-'); + }); + + it(`should now close the summary popup`, async() => { + await page.closePopup(); + await page.waitForSelector(selectors.itemSummary.basicData, {hidden: true}); + }); + + it(`should navigate to one of the items detailed section`, async() => { + await page.accessToSearchResult('Melee weapon combat fist 15cm'); + await page.waitForState('item.card.summary'); + }); + + it(`should check the descritor edit button is not visible for employee`, async() => { + const visibleButton = await page.isVisible(selectors.itemDescriptor.editButton); + + expect(visibleButton).toBeFalsy(); + }); + + it(`should check the item summary shows fields from basic data section`, async() => { + await page.waitForTextInElement(selectors.itemSummary.basicData, 'Melee weapon combat fist 15cm'); + const result = await page.waitToGetProperty(selectors.itemSummary.basicData, 'innerText'); + + expect(result).toContain('Melee weapon combat fist 15cm'); + }); + + it(`should check the item summary shows fields from tags section`, async() => { + const result = await page.waitToGetProperty(selectors.itemSummary.tags, 'innerText'); + + expect(result).toContain('Silver'); + }); + + it(`should check the item summary shows fields from botanical section`, async() => { + const result = await page.waitToGetProperty(selectors.itemSummary.botanical, 'innerText'); + + expect(result).toContain('procera'); + }); + + it(`should check the item summary shows fields from barcodes section`, async() => { + const result = await page.waitToGetProperty(selectors.itemSummary.barcode, 'innerText'); + + expect(result).toContain('4'); + }); +}); diff --git a/e2e/paths/04-item/02_basic_data.spec.js b/e2e/paths/04-item/02_basic_data.spec.js new file mode 100644 index 000000000..3bad18303 --- /dev/null +++ b/e2e/paths/04-item/02_basic_data.spec.js @@ -0,0 +1,64 @@ +import getBrowser from '../../helpers/puppeteer'; + +const $ = { + form: 'vn-item-basic-data form', + intrastatForm: '.vn-dialog.shown form', + newIntrastatButton: 'vn-item-basic-data vn-icon-button[vn-tooltip="New intrastat"] > button' +}; + +describe('Item Edit basic data path', () => { + let browser; + let page; + + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('buyer', 'item'); + await page.accessToSearchResult('Melee weapon combat fist 15cm'); + }); + + beforeEach(async() => { + await page.accessToSection('item.card.basicData'); + }); + + afterAll(async() => { + await browser.close(); + }); + + it(`should edit the item basic data and confirm the item data was edited`, async() => { + const values = { + type: 'Anthurium', + intrastat: 'Coral y materiales similares', + relevancy: 1, + generic: 'Pallet', + isActive: false, + priceInKg: true, + isFragile: true, + packingOut: 5 + }; + + const message = await page.sendForm($.form, values); + await page.reloadSection('item.card.basicData'); + const formValues = await page.fetchForm($.form, Object.keys(values)); + + expect(message.isSuccess).toBeTrue(); + expect(formValues).toEqual(values); + }); + + it(`should create a new intrastat and save it`, async() => { + await page.click($.newIntrastatButton); + await page.waitForSelector($.intrastatForm); + await page.fillForm($.intrastatForm, { + id: '588420239', + description: 'Tropical Flowers' + }); + await page.respondToDialog('accept'); + + const message = await page.sendForm($.form); + await page.reloadSection('item.card.basicData'); + const formValues = await page.fetchForm($.form, ['intrastat']); + + expect(message.isSuccess).toBeTrue(); + expect(formValues).toEqual({intrastat: 'Tropical Flowers'}); + }); +}); diff --git a/e2e/paths/04-item/03_tax.spec.js b/e2e/paths/04-item/03_tax.spec.js new file mode 100644 index 000000000..6013094e9 --- /dev/null +++ b/e2e/paths/04-item/03_tax.spec.js @@ -0,0 +1,48 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; + +describe('Item edit tax path', () => { + let browser; + let page; + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('buyer', 'item'); + await page.accessToSearchResult('Ranged weapon longbow 200cm'); + await page.accessToSection('item.card.tax'); + }); + + afterAll(async() => { + await browser.close(); + }); + + it(`should add the item tax to all countries`, async() => { + await page.autocompleteSearch(selectors.itemTax.firstClass, 'General VAT'); + await page.autocompleteSearch(selectors.itemTax.secondClass, 'General VAT'); + await page.waitToClick(selectors.itemTax.submitTaxButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it(`should confirm the first item tax class was edited`, async() => { + await page.reloadSection('item.card.tax'); + const firstVatType = await page.waitToGetProperty(selectors.itemTax.firstClass, 'value'); + + expect(firstVatType).toEqual('General VAT'); + }); + + it(`should confirm the second item tax class was edited`, async() => { + const secondVatType = await page + .waitToGetProperty(selectors.itemTax.secondClass, 'value'); + + expect(secondVatType).toEqual('General VAT'); + }); + + it(`should edit the first class without saving the form`, async() => { + await page.autocompleteSearch(selectors.itemTax.firstClass, 'Reduced VAT'); + const firstVatType = await page.waitToGetProperty(selectors.itemTax.firstClass, 'value'); + + expect(firstVatType).toEqual('Reduced VAT'); + }); +}); diff --git a/e2e/paths/04-item/04_tags.spec.js b/e2e/paths/04-item/04_tags.spec.js new file mode 100644 index 000000000..f13cf9aa4 --- /dev/null +++ b/e2e/paths/04-item/04_tags.spec.js @@ -0,0 +1,79 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; + +describe('Item create tags path', () => { + let browser; + let page; + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('buyer', 'item'); + await page.accessToSearchResult('Ranged weapon longbow 200cm'); + await page.accessToSection('item.card.tags'); + }); + + afterAll(async() => { + await browser.close(); + }); + + it('should create a new tag and delete a former one', async() => { + await page.waitToClick(selectors.itemTags.fourthRemoveTagButton); + await page.waitToClick(selectors.itemTags.addItemTagButton); + await page.autocompleteSearch(selectors.itemTags.seventhTag, 'Ancho de la base'); + await page.write(selectors.itemTags.seventhValue, '50'); + await page.clearInput(selectors.itemTags.seventhRelevancy); + await page.write(selectors.itemTags.seventhRelevancy, '4'); + await page.waitToClick(selectors.itemTags.submitItemTagsButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it('should confirm the fourth row data is the expected one', async() => { + await page.reloadSection('item.card.tags'); + await page.waitForSelector('vn-item-tags'); + let result = await page.waitToGetProperty(selectors.itemTags.fourthTag, 'value'); + + expect(result).toEqual('Ancho de la base'); + + result = await page + .waitToGetProperty(selectors.itemTags.fourthValue, 'value'); + + expect(result).toEqual('50'); + + result = await page + .waitToGetProperty(selectors.itemTags.fourthRelevancy, 'value'); + + expect(result).toEqual('4'); + }); + + it('should confirm the fifth row data is the expected one', async() => { + let tag = await page + .waitToGetProperty(selectors.itemTags.fifthTag, 'value'); + + let value = await page + .waitToGetProperty(selectors.itemTags.fifthValue, 'value'); + + let relevancy = await page + .waitToGetProperty(selectors.itemTags.fifthRelevancy, 'value'); + + expect(tag).toEqual('Color'); + expect(value).toEqual('Brown'); + expect(relevancy).toEqual('5'); + }); + + it('should confirm the sixth row data is the expected one', async() => { + let tag = await page + .waitToGetProperty(selectors.itemTags.sixthTag, 'value'); + + let value = await page + .waitToGetProperty(selectors.itemTags.sixthValue, 'value'); + + let relevancy = await page + .waitToGetProperty(selectors.itemTags.sixthRelevancy, 'value'); + + expect(tag).toEqual('Categoria'); + expect(value).toEqual('+1 precission'); + expect(relevancy).toEqual('6'); + }); +}); diff --git a/e2e/paths/04-item/05_botanical.spec.js b/e2e/paths/04-item/05_botanical.spec.js new file mode 100644 index 000000000..1671cc5d2 --- /dev/null +++ b/e2e/paths/04-item/05_botanical.spec.js @@ -0,0 +1,66 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; + +describe('Item Create botanical path', () => { + let browser; + let page; + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('buyer', 'item'); + await page.accessToSearchResult('Ranged weapon pistol 9mm'); + await page.accessToSection('item.card.botanical'); + }); + + afterAll(async() => { + await browser.close(); + }); + + it(`should create a new botanical for the item`, async() => { + await page.autocompleteSearch(selectors.itemBotanical.genus, 'Abelia'); + await page.autocompleteSearch(selectors.itemBotanical.species, 'dealbata'); + await page.waitToClick(selectors.itemBotanical.submitBotanicalButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it(`should confirm the Genus for the item was created`, async() => { + await page.waitForTextInField(selectors.itemBotanical.genus, 'Abelia'); + const result = await page + .waitToGetProperty(selectors.itemBotanical.genus, 'value'); + + expect(result).toEqual('Abelia'); + }); + + it(`should confirm the Species for the item was created`, async() => { + const result = await page + .waitToGetProperty(selectors.itemBotanical.species, 'value'); + + expect(result).toEqual('dealbata'); + }); + + it(`should edit botanical for the item`, async() => { + await page.autocompleteSearch(selectors.itemBotanical.genus, 'Abies'); + await page.autocompleteSearch(selectors.itemBotanical.species, 'decurrens'); + await page.waitToClick(selectors.itemBotanical.submitBotanicalButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it(`should confirm the Genus for the item was edited`, async() => { + await page.waitForTextInField(selectors.itemBotanical.genus, 'Abies'); + const result = await page + .waitToGetProperty(selectors.itemBotanical.genus, 'value'); + + expect(result).toEqual('Abies'); + }); + + it(`should confirm the Species for the item was edited`, async() => { + const result = await page + .waitToGetProperty(selectors.itemBotanical.species, 'value'); + + expect(result).toEqual('decurrens'); + }); +}); diff --git a/e2e/paths/04-item/06_barcode.spec.js b/e2e/paths/04-item/06_barcode.spec.js new file mode 100644 index 000000000..36c9c39ae --- /dev/null +++ b/e2e/paths/04-item/06_barcode.spec.js @@ -0,0 +1,37 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; + +describe('Item Create barcodes path', () => { + let browser; + let page; + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('buyer', 'item'); + await page.accessToSearchResult('Ranged weapon longbow 200cm'); + await page.accessToSection('item.card.itemBarcode'); + }); + + afterAll(async() => { + await browser.close(); + }); + + it(`should click create a new code and delete a former one`, async() => { + await page.waitToClick(selectors.itemBarcodes.firstCodeRemoveButton); + await page.waitToClick(selectors.itemBarcodes.addBarcodeButton); + await page.write(selectors.itemBarcodes.thirdCode, '5'); + await page.waitToClick(selectors.itemBarcodes.submitBarcodesButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it(`should confirm the barcode 5 is created and it is now the third barcode as the first was deleted`, async() => { + await page.reloadSection('item.card.itemBarcode'); + await page.waitForTextInField(selectors.itemBarcodes.thirdCode, '5'); + const result = await page + .waitToGetProperty(selectors.itemBarcodes.thirdCode, 'value'); + + expect(result).toEqual('5'); + }); +}); diff --git a/e2e/paths/04-item/07_create.spec.js b/e2e/paths/04-item/07_create.spec.js new file mode 100644 index 000000000..c20be9ebc --- /dev/null +++ b/e2e/paths/04-item/07_create.spec.js @@ -0,0 +1,65 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; + +const $ = { + form: 'vn-item-create form' +}; + +describe('Item Create', () => { + let browser; + let page; + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('buyer', 'item'); + }); + + afterAll(async() => { + await browser.close(); + }); + + it('should access to the create item view by clicking the create floating button', async() => { + await page.waitToClick(selectors.itemsIndex.createItemButton); + await page.waitForState('item.create'); + }); + + it('should return to the item index by clickig the cancel button', async() => { + await page.waitToClick(selectors.itemCreateView.cancelButton); + await page.waitForState('item.index'); + }); + + it('should now access to the create item view by clicking the create floating button', async() => { + await page.waitToClick(selectors.itemsIndex.createItemButton); + await page.waitForState('item.create'); + }); + + it('should throw an error when insert an invalid priority', async() => { + const values = { + name: 'Infinity Gauntlet', + type: 'Crisantemo', + intrastat: 'Coral y materiales similares', + origin: 'Holand', + priority: null + }; + const message = await page.sendForm($.form, values); + + expect(message.text).toContain('Valid priorities'); + }); + + it('should create the Infinity Gauntlet item', async() => { + const values = { + name: 'Infinity Gauntlet', + type: 'Crisantemo', + intrastat: 'Coral y materiales similares', + origin: 'Holand', + priority: '2' + }; + + await page.fillForm($.form, values); + const formValues = await page.fetchForm($.form, Object.keys(values)); + const message = await page.sendForm($.form); + + expect(message.isSuccess).toBeTrue(); + expect(formValues).toEqual(values); + }); +}); diff --git a/e2e/paths/04-item/08_regularize.spec.js b/e2e/paths/04-item/08_regularize.spec.js new file mode 100644 index 000000000..9b3074776 --- /dev/null +++ b/e2e/paths/04-item/08_regularize.spec.js @@ -0,0 +1,141 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; + +describe('Item regularize path', () => { + let browser; + let page; + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('employee', 'item'); + }); + + afterAll(async() => { + await browser.close(); + }); + + it('should edit the user local warehouse', async() => { + await page.waitForSpinnerLoad(); + await page.waitToClick(selectors.globalItems.userMenuButton); + await page.autocompleteSearch(selectors.globalItems.userLocalWarehouse, 'Warehouse Four'); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it('should check the local settings were saved', async() => { + const userLocalWarehouse = await page + .waitToGetProperty(selectors.globalItems.userLocalWarehouse, 'value'); + + await page.closePopup(); + + expect(userLocalWarehouse).toContain('Warehouse Four'); + }); + + it('should search for a specific item', async() => { + await page.accessToSearchResult('Ranged weapon pistol 9mm'); + await page.waitForState('item.card.summary'); + }); + + it('should open the regularize dialog and check the warehouse matches the local user settings', async() => { + await page.waitToClick(selectors.itemDescriptor.moreMenu); + await page.waitToClick(selectors.itemDescriptor.moreMenuRegularizeButton); + const result = await page.waitToGetProperty(selectors.itemDescriptor.regularizeWarehouse, 'value'); + + expect(result).toEqual('Warehouse Four'); + }); + + it('should regularize the item', async() => { + await page.write(selectors.itemDescriptor.regularizeQuantity, '100'); + await page.autocompleteSearch(selectors.itemDescriptor.regularizeWarehouse, 'Warehouse One'); + await page.waitToClick(selectors.itemDescriptor.regularizeSaveButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it('should click on the Tickets button of the top bar menu', async() => { + await page.waitToClick(selectors.globalItems.applicationsMenuButton); + await page.waitForSelector(selectors.globalItems.applicationsMenuVisible); + await Promise.all([ + page.waitForNavigation({waitUntil: ['load', 'networkidle0', 'domcontentloaded']}), + page.waitToClick(selectors.globalItems.ticketsButton) + ]); + await page.waitForState('ticket.index'); + }); + + it('should clear the user local settings now', async() => { + await page.waitToClick(selectors.globalItems.userMenuButton); + await page.waitForContentLoaded(); + await page.clearInput(selectors.globalItems.userConfigFirstAutocomplete); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it('should search for the ticket with alias missing', async() => { + await page.keyboard.press('Escape'); + await page.accessToSearchResult('missing'); + await page.waitForState('ticket.card.summary'); + }); + + it(`should check the ticket sale quantity is showing a negative value`, async() => { + await page.waitForTextInElement(selectors.ticketSummary.firstSaleQuantity, '-100'); + const result = await page + .waitToGetProperty(selectors.ticketSummary.firstSaleQuantity, 'innerText'); + + expect(result).toContain('-100'); + }); + + it(`should check the ticket sale discount is 100%`, async() => { + const result = await page + .waitToGetProperty(selectors.ticketSummary.firstSaleDiscount, 'innerText'); + + expect(result).toContain('100 %'); + }); + + it('should now click on the Items button of the top bar menu', async() => { + await page.waitToClick(selectors.globalItems.applicationsMenuButton); + await page.waitForSelector(selectors.globalItems.applicationsMenuVisible); + await page.waitToClick(selectors.globalItems.itemsButton); + await page.waitForState('item.index'); + }); + + it('should search for the item once again', async() => { + await page.accessToSearchResult('Ranged weapon pistol 9mm'); + await page.waitForState('item.card.summary'); + }); + + it('should regularize the item once more', async() => { + await page.waitToClick(selectors.itemDescriptor.moreMenu); + await page.waitToClick(selectors.itemDescriptor.moreMenuRegularizeButton); + await page.write(selectors.itemDescriptor.regularizeQuantity, '100'); + await page.autocompleteSearch(selectors.itemDescriptor.regularizeWarehouse, 'Warehouse One'); + await page.waitToClick(selectors.itemDescriptor.regularizeSaveButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it('should again click on the Tickets button of the top bar menu', async() => { + await page.waitToClick(selectors.globalItems.applicationsMenuButton); + await page.waitForSelector(selectors.globalItems.applicationsMenuVisible); + await Promise.all([ + page.waitForNavigation({waitUntil: ['load', 'networkidle0', 'domcontentloaded']}), + page.waitToClick(selectors.globalItems.ticketsButton) + ]); + await page.waitForState('ticket.index'); + }); + + it('should search for the ticket missing once again', async() => { + await page.accessToSearchResult('Missing'); + await page.waitForState('ticket.card.summary'); + }); + + it(`should check the ticket contains now two sales`, async() => { + await page.waitForTextInElement(selectors.ticketSummary.firstSaleQuantity, '-100'); + const result = await page.countElement(selectors.ticketSummary.sale); + + expect(result).toEqual(2); + }); +}); diff --git a/e2e/paths/04-item/09_index.spec.js b/e2e/paths/04-item/09_index.spec.js new file mode 100644 index 000000000..6e0a4bd5c --- /dev/null +++ b/e2e/paths/04-item/09_index.spec.js @@ -0,0 +1,84 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; + +describe('Item index path', () => { + let browser; + let page; + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('salesPerson', 'item'); + await page.waitToClick(selectors.globalItems.searchButton); + }); + + afterAll(async() => { + await browser.close(); + }); + + it('should click on the fields to show button to open the list of columns to show', async() => { + await page.waitToClick(selectors.itemsIndex.shownColumns); + const visible = await page.isVisible(selectors.itemsIndex.shownColumnsList); + + expect(visible).toBeTruthy(); + }); + + it('should unmark all checkboxes except the first and the last ones', async() => { + await page.waitToClick(selectors.itemsIndex.idCheckbox); + await page.waitToClick(selectors.itemsIndex.stemsCheckbox); + await page.waitToClick(selectors.itemsIndex.sizeCheckbox); + await page.waitToClick(selectors.itemsIndex.typeCheckbox); + await page.waitToClick(selectors.itemsIndex.categoryCheckbox); + await page.waitToClick(selectors.itemsIndex.intrastadCheckbox); + await page.waitToClick(selectors.itemsIndex.originCheckbox); + await page.waitToClick(selectors.itemsIndex.buyerCheckbox); + await page.waitToClick(selectors.itemsIndex.weightByPieceCheckbox); + await page.waitToClick(selectors.itemsIndex.saveFieldsButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it('should navigate forth and back to see the images column is still visible', async() => { + await page.closePopup(); + await page.waitToClick(selectors.itemsIndex.firstSearchResult); + await page.waitToClick(selectors.itemDescriptor.goBackToModuleIndexButton); + await page.waitToClick(selectors.globalItems.searchButton); + await page.waitForSelector(selectors.itemsIndex.searchResult); + await page.waitImgLoad(selectors.itemsIndex.firstItemImage); + const imageVisible = await page.isVisible(selectors.itemsIndex.firstItemImageTd); + + expect(imageVisible).toBeTruthy(); + }); + + it('should check the ids column is not visible', async() => { + await page.waitForSelector(selectors.itemsIndex.firstItemId, {hidden: true}); + }); + + it('should mark all unchecked boxes to leave the index as it was', async() => { + await page.waitToClick(selectors.itemsIndex.shownColumns); + await page.waitToClick(selectors.itemsIndex.idCheckbox); + await page.waitToClick(selectors.itemsIndex.stemsCheckbox); + await page.waitToClick(selectors.itemsIndex.sizeCheckbox); + await page.waitToClick(selectors.itemsIndex.typeCheckbox); + await page.waitToClick(selectors.itemsIndex.categoryCheckbox); + await page.waitToClick(selectors.itemsIndex.intrastadCheckbox); + await page.waitToClick(selectors.itemsIndex.originCheckbox); + await page.waitToClick(selectors.itemsIndex.buyerCheckbox); + await page.waitToClick(selectors.itemsIndex.weightByPieceCheckbox); + await page.waitToClick(selectors.itemsIndex.saveFieldsButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it('should now navigate forth and back to see the ids column is now visible', async() => { + await page.closePopup(); + await page.waitToClick(selectors.itemsIndex.firstSearchResult); + await page.waitToClick(selectors.itemDescriptor.goBackToModuleIndexButton); + await page.waitToClick(selectors.globalItems.searchButton); + await page.waitForSelector(selectors.itemsIndex.searchResult); + const idVisible = await page.isVisible(selectors.itemsIndex.firstItemId); + + expect(idVisible).toBeTruthy(); + }); +}); diff --git a/e2e/paths/04-item/10_item_log.spec.js b/e2e/paths/04-item/10_item_log.spec.js new file mode 100644 index 000000000..c88fbd337 --- /dev/null +++ b/e2e/paths/04-item/10_item_log.spec.js @@ -0,0 +1,45 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; + +describe('Item log path', () => { + let browser; + let page; + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('developer', 'item'); + }); + + afterAll(async() => { + await browser.close(); + }); + + it(`should search for the Knowledge artifact to confirm it isn't created yet`, async() => { + await page.doSearch('Knowledge artifact'); + const nResults = await page.countElement(selectors.itemsIndex.searchResult); + + expect(nResults).toEqual(1); + }); + + it('should access to the create item view by clicking the create floating button', async() => { + await page.waitToClick(selectors.itemsIndex.createItemButton); + await page.waitForState('item.create'); + }); + + it('should create the Knowledge artifact item', async() => { + await page.write(selectors.itemCreateView.temporalName, 'Knowledge artifact'); + await page.autocompleteSearch(selectors.itemCreateView.type, 'Crisantemo'); + await page.autocompleteSearch(selectors.itemCreateView.intrastat, 'Coral y materiales similares'); + await page.autocompleteSearch(selectors.itemCreateView.origin, 'Holand'); + await page.waitToClick(selectors.itemCreateView.createButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it('should return to the items index by clicking the return to items button', async() => { + await page.waitToClick(selectors.itemBasicData.goToItemIndexButton); + await page.waitForSelector(selectors.itemsIndex.createItemButton); + await page.waitForState('item.index'); + }); +}); diff --git a/e2e/paths/04-item/11_descriptor.spec.js b/e2e/paths/04-item/11_descriptor.spec.js new file mode 100644 index 000000000..eb9ed2573 --- /dev/null +++ b/e2e/paths/04-item/11_descriptor.spec.js @@ -0,0 +1,41 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; + +describe('Item descriptor path', () => { + let browser; + let page; + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('buyer', 'item'); + await page.accessToSearchResult('1'); + await page.accessToSection('item.card.basicData'); + }); + + afterAll(async() => { + await browser.close(); + }); + + it('should set the item to inactive', async() => { + await page.waitToClick(selectors.itemBasicData.isActiveCheckbox); + await page.waitToClick(selectors.itemBasicData.submitBasicDataButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it('should reload the section and check the inactive icon is visible', async() => { + await page.reloadSection('item.card.basicData'); + const visibleIcon = await page.isVisible(selectors.itemDescriptor.inactiveIcon); + + expect(visibleIcon).toBeTruthy(); + }); + + it('should set the item back to active', async() => { + await page.waitToClick(selectors.itemBasicData.isActiveCheckbox); + await page.waitToClick(selectors.itemBasicData.submitBasicDataButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); +}); diff --git a/e2e/paths/04-item/12_request.spec.js b/e2e/paths/04-item/12_request.spec.js new file mode 100644 index 000000000..e0f3a1b45 --- /dev/null +++ b/e2e/paths/04-item/12_request.spec.js @@ -0,0 +1,45 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; + +describe('Item request path', () => { + let browser; + let page; + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('buyer', 'item'); + await page.accessToSection('item.request'); + }); + + afterAll(async() => { + await browser.close(); + }); + + it('should reach the item request section', async() => { + await page.waitForState('item.request'); + }); + + it('should fill the id and quantity then check the concept was updated', async() => { + await page.writeOnEditableTD(selectors.itemRequest.firstRequestItemID, '4'); + await page.writeOnEditableTD(selectors.itemRequest.firstRequestQuantity, '10'); + await page.waitForTextInElement(selectors.itemRequest.firstRequestConcept, 'Melee weapon heavy shield 100cm'); + let filledConcept = await page.waitToGetProperty(selectors.itemRequest.firstRequestConcept, 'innerText'); + + expect(filledConcept).toContain('Melee weapon heavy shield 100cm'); + }); + + it('should check the status of the request should now be accepted', async() => { + let status = await page.waitToGetProperty(selectors.itemRequest.firstRequestStatus, 'innerText'); + + expect(status).toContain('Accepted'); + }); + + it('should now click on the second declain request icon then type the reason', async() => { + await page.waitToClick(selectors.itemRequest.secondRequestDecline); + await page.write(selectors.itemRequest.declineReason, 'Not quite as expected'); + await page.respondToDialog('accept'); + let status = await page.waitToGetProperty(selectors.itemRequest.secondRequestStatus, 'innerText'); + + expect(status).toContain('Denied'); + }); +}); diff --git a/e2e/paths/04-item/13_fixedPrice.spec.js b/e2e/paths/04-item/13_fixedPrice.spec.js new file mode 100644 index 000000000..f36138e18 --- /dev/null +++ b/e2e/paths/04-item/13_fixedPrice.spec.js @@ -0,0 +1,97 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; + +const $ = selectors.itemFixedPrice; + +describe('Item fixed prices path', () => { + let browser; + let page; + let httpRequest; + + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('buyer', 'item'); + await page.accessToSection('item.fixedPrice'); + page.on('request', req => { + if (req.url().includes(`FixedPrices/filter`)) + httpRequest = req.url(); + }); + }); + + afterAll(async() => { + await browser.close(); + }); + + it('should filter using all the fields', async() => { + await page.write($.generalSearchFilter, 'item'); + await page.keyboard.press('Enter'); + + expect(httpRequest).toContain('search=item'); + + await page.click($.chip); + await page.click($.reignFilter); + + expect(httpRequest).toContain('categoryFk'); + + await page.autocompleteSearch($.typeFilter, 'Alstroemeria'); + + expect(httpRequest).toContain('typeFk'); + + await page.click($.chip); + await page.autocompleteSearch($.buyerFilter, 'buyerNick'); + + expect(httpRequest).toContain('buyerFk'); + + await page.click($.chip); + await page.autocompleteSearch($.warehouseFilter, 'Algemesi'); + + expect(httpRequest).toContain('warehouseFk'); + + await page.click($.chip); + await page.click($.mineFilter); + + expect(httpRequest).toContain('mine=true'); + + await page.click($.chip); + await page.click($.hasMinPriceFilter); + + expect(httpRequest).toContain('hasMinPrice=true'); + + await page.click($.chip); + await page.click($.addTag); + await page.autocompleteSearch($.tagFilter, 'Color'); + await page.autocompleteSearch($.tagValueFilter, 'Brown'); + + expect(httpRequest).toContain('tags'); + + await page.click($.chip); + }); + + it('should click on the add new fixed price button', async() => { + await page.waitToClick($.add); + await page.waitForSelector($.fourthFixedPrice); + }); + + it('should fill the fixed price data', async() => { + const now = Date.vnNew(); + await page.autocompleteSearch($.fourthWarehouse, 'Warehouse one'); + await page.writeOnEditableTD($.fourthGroupingPrice, '1'); + await page.writeOnEditableTD($.fourthPackingPrice, '1'); + await page.write($.fourthMinPrice, '1'); + await page.pickDate($.fourthStarted, now); + await page.pickDate($.fourthEnded, now); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it('should reload the section and check the created price has the expected ID', async() => { + await page.goto(`http://localhost:5000/#!/item/fixed-price`); + await page.autocompleteSearch($.warehouseFilter, 'Warehouse one'); + await page.click($.chip); + const result = await page.waitToGetProperty($.fourthItemID, 'value'); + + expect(result).toContain('13'); + }); +}); diff --git a/e2e/paths/05-ticket/01-sale/01_list_sales.spec.js b/e2e/paths/05-ticket/01-sale/01_list_sales.spec.js new file mode 100644 index 000000000..ad0975889 --- /dev/null +++ b/e2e/paths/05-ticket/01-sale/01_list_sales.spec.js @@ -0,0 +1,99 @@ +import selectors from '../../../helpers/selectors.js'; +import getBrowser from '../../../helpers/puppeteer'; + +describe('Ticket List sale path', () => { + let browser; + let page; + + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('employee', 'ticket'); + await page.accessToSearchResult('13'); + await page.accessToSection('ticket.card.sale'); + }); + + afterAll(async() => { + await browser.close(); + }); + + it('should confirm the first ticket sale contains the colour tag', async() => { + const value = await page + .waitToGetProperty(selectors.ticketSales.firstSaleColour, 'innerText'); + + expect(value).toContain('Black'); + }); + + it('should confirm the first sale contains the price', async() => { + const value = await page + .waitToGetProperty(selectors.ticketSales.firstSalePrice, 'innerText'); + + expect(value).toContain('1.72'); + }); + + it('should confirm the first sale contains the discount', async() => { + const value = await page + .waitToGetProperty(selectors.ticketSales.firstSaleDiscount, 'innerText'); + + expect(value).toContain('0.00%'); + }); + + it('should confirm the first sale contains the total import', async() => { + const value = await page + .waitToGetProperty(selectors.ticketSales.firstSaleImport, 'innerText'); + + expect(value).toContain('34.40'); + }); + + it('should add an empty item to the sale list', async() => { + await page.waitToClick(selectors.ticketSales.newItemButton); + const sales = await page + .countElement(selectors.ticketSales.saleLine); + + expect(sales).toEqual(2); + }); + + it('should select a valid item to be added as the second item in the sales list', async() => { + let searchValue = 'Melee weapon heavy shield 100cm'; + await page.autocompleteSearch(selectors.ticketSales.secondSaleIdAutocomplete, searchValue); + await page.waitToClick(selectors.ticketSales.secondSaleQuantityCell); + await page.type(selectors.ticketSales.secondSaleQuantity, '8'); + await page.keyboard.press('Enter'); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it('should update the description of the new sale', async() => { + await page.click(selectors.ticketSales.secondSaleConceptCell); + await page.write(selectors.ticketSales.secondSaleConceptInput, 'Aegis of Valor'); + await page.keyboard.press('Enter'); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it('should add a third empty item to the sale list', async() => { + await page.waitToClick(selectors.ticketSales.newItemButton); + await page.waitForNumberOfElements(selectors.ticketSales.saleLine, 3); + const sales = await page.countElement(selectors.ticketSales.saleLine); + + expect(sales).toEqual(3); + }); + + it('should select the 2nd and 3th item and delete both', async() => { + await page.waitToClick(selectors.ticketSales.secondSaleCheckbox); + await page.waitToClick(selectors.ticketSales.thirdSaleCheckbox); + await page.waitToClick(selectors.ticketSales.deleteSaleButton); + await page.waitToClick(selectors.globalItems.acceptButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it(`should verify there's only 1 single line remaining`, async() => { + const sales = await page.countElement(selectors.ticketSales.saleLine); + + expect(sales).toEqual(1); + }); +}); diff --git a/e2e/paths/05-ticket/01-sale/02_edit_sale.spec.js b/e2e/paths/05-ticket/01-sale/02_edit_sale.spec.js new file mode 100644 index 000000000..d9689e31a --- /dev/null +++ b/e2e/paths/05-ticket/01-sale/02_edit_sale.spec.js @@ -0,0 +1,415 @@ +import selectors from '../../../helpers/selectors.js'; +import getBrowser from '../../../helpers/puppeteer'; + +describe('Ticket Edit sale path', () => { + let browser; + let page; + + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('salesPerson', 'ticket'); + await page.accessToSearchResult('16'); + await page.accessToSection('ticket.card.sale'); + }); + + afterAll(async() => { + await browser.close(); + }); + + it(`should click on the first sale claim icon to navigate over there`, async() => { + await page.waitToClick(selectors.ticketSales.firstSaleClaimIcon); + await page.waitForNavigation(); + await page.goBack(); + await page.goBack(); + }); + + it('should navigate to the tickets index', async() => { + await page.waitToClick(selectors.globalItems.applicationsMenuButton); + await page.waitForSelector(selectors.globalItems.applicationsMenuVisible); + await page.waitToClick(selectors.globalItems.ticketsButton); + await page.waitForState('ticket.index'); + }); + + it(`should search for a ticket and then navigate to it's sales`, async() => { + await page.accessToSearchResult('16'); + await page.accessToSection('ticket.card.sale'); + }); + + it(`should set the ticket as libre`, async() => { + const searchValue = 'libre'; + await page.waitToClick(selectors.ticketSales.stateMenuButton); + await page.write(selectors.ticketSales.moreMenuState, searchValue); + try { + await page.waitForFunction(searchValue => { + const element = document.querySelector('li.active'); + if (element) + return element.innerText.toLowerCase().includes(searchValue.toLowerCase()); + }, {}, searchValue); + } catch (error) { + const builtSelector = await page.selectorFormater(selectors.ticketSales.moreMenuState); + const inputValue = await page.evaluate(() => { + return document.querySelector('.vn-drop-down.shown vn-textfield input').value; + }); + throw new Error(`${builtSelector} value is ${inputValue}! ${error}`); + } + await page.waitForState('ticket.card.sale'); + await page.keyboard.press('Enter'); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it(`should check it's state is libre now`, async() => { + await page.waitForTextInElement(selectors.ticketDescriptor.stateLabelValue, 'Libre'); + const result = await page.waitToGetProperty(selectors.ticketDescriptor.stateLabelValue, 'innerText'); + + expect(result).toEqual('State Libre'); + }); + + it(`should set the ticket as OK`, async() => { + await page.waitToClick(selectors.ticketSales.setOk); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it(`should check it's state is OK now`, async() => { + await page.waitForTextInElement(selectors.ticketDescriptor.stateLabelValue, 'OK'); + const result = await page.waitToGetProperty(selectors.ticketDescriptor.stateLabelValue, 'innerText'); + + expect(result).toEqual('State OK'); + }); + + it(`should check the zoomed image isn't present`, async() => { + const result = await page.countElement(selectors.ticketSales.firstSaleZoomedImage); + + expect(result).toEqual(0); + }); + + it(`should click on the thumbnail image of the 1st sale and see the zoomed image`, async() => { + await page.waitToClick(selectors.ticketSales.firstSaleThumbnailImage); + const result = await page.countElement(selectors.ticketSales.firstSaleZoomedImage); + + expect(result).toEqual(1); + }); + + it(`should click on the zoomed image to close it`, async() => { + await page.waitToClick(selectors.ticketSales.firstSaleZoomedImage); + const result = await page.countElement(selectors.ticketSales.firstSaleZoomedImage); + + expect(result).toEqual(0); + }); + + it(`should click on the first sale ID making now the item descriptor visible`, async() => { + await page.waitToClick(selectors.ticketSales.firstSaleId); + await page.waitImgLoad(selectors.ticketSales.firstSaleDescriptorImage); + const visible = await page.isVisible(selectors.ticketSales.saleDescriptorPopover); + + expect(visible).toBeTruthy(); + }); + + it(`should click on the descriptor image of the 1st sale and see the zoomed image`, async() => { + await page.waitToClick('vn-item-descriptor img'); + const result = await page.countElement(selectors.ticketSales.firstSaleZoomedImage); + + expect(result).toEqual(1); + }); + + it(`should now click on the zoomed image to close it`, async() => { + await page.waitToClick(selectors.ticketSales.firstSaleZoomedImage); + const result = await page.countElement(selectors.ticketSales.firstSaleZoomedImage); + + expect(result).toEqual(0); + }); + + it(`should click on the summary icon of the item-descriptor to access to the item summary`, async() => { + await page.waitToClick(selectors.ticketSales.saleDescriptorPopoverSummaryButton); + await page.waitForState('item.card.summary'); + }); + + it('should return to ticket sales section', async() => { + await page.waitToClick(selectors.globalItems.applicationsMenuButton); + await page.waitForSelector(selectors.globalItems.applicationsMenuVisible); + await page.waitToClick(selectors.globalItems.ticketsButton); + await page.accessToSearchResult('16'); + await page.accessToSection('ticket.card.sale'); + }); + + it('should remove 1 from the first sale quantity', async() => { + await page.waitToClick(selectors.ticketSales.firstSaleQuantityCell); + await page.waitForSelector(selectors.ticketSales.firstSaleQuantity); + await page.type(selectors.ticketSales.firstSaleQuantity, '9\u000d'); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it('should update the price', async() => { + await page.waitToClick(selectors.ticketSales.firstSalePrice); + await page.waitForSelector(selectors.ticketSales.firstSalePriceInput); + await page.type(selectors.ticketSales.firstSalePriceInput, '5\u000d'); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it('should confirm the price have been updated', async() => { + const result = await page.waitToGetProperty(selectors.ticketSales.firstSalePrice, 'innerText'); + + expect(result).toContain('5.00'); + }); + + it('should confirm the total price for that item have been updated', async() => { + const result = await page.waitToGetProperty(selectors.ticketSales.firstSaleImport, 'innerText'); + + expect(result).toContain('45.00'); + }); + + it('should update the discount', async() => { + await page.waitToClick(selectors.ticketSales.firstSaleDiscount); + await page.waitForSelector(selectors.ticketSales.firstSaleDiscountInput); + await page.type(selectors.ticketSales.firstSaleDiscountInput, '50'); + await page.waitToClick(selectors.ticketSales.saveSaleDiscountButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it('should confirm the discount have been updated', async() => { + await page.waitForTextInElement(selectors.ticketSales.firstSaleDiscount, '50.00%'); + const result = await page.waitToGetProperty(selectors.ticketSales.firstSaleDiscount, 'innerText'); + + expect(result).toContain('50.00%'); + }); + + it('should confirm the total import for that item have been updated', async() => { + await page.waitForTextInElement(selectors.ticketSales.firstSaleImport, '22.50'); + const result = await page.waitToGetProperty(selectors.ticketSales.firstSaleImport, 'innerText'); + + expect(result).toContain('22.50'); + }); + + it('should recalculate price of sales', async() => { + await page.waitToClick(selectors.ticketSales.firstSaleCheckbox); + await page.waitToClick(selectors.ticketSales.secondSaleCheckbox); + + await page.waitToClick(selectors.ticketSales.moreMenu); + await page.waitToClick(selectors.ticketSales.moreMenuRecalculatePrice); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it('should log in as salesAssistant and navigate to ticket sales', async() => { + await page.loginAndModule('salesAssistant', 'ticket'); + await page.accessToSearchResult('15'); + await page.accessToSection('ticket.card.sale'); + }); + + it('should select the first sale and create a refund with warehouse', async() => { + await page.waitToClick(selectors.ticketSales.firstSaleCheckbox); + await page.waitToClick(selectors.ticketSales.moreMenu); + await page.waitToClick(selectors.ticketSales.moreMenuRefund); + await page.waitToClick(selectors.ticketSales.refundWithWarehouse); + await page.waitForSnackbar(); + await page.waitForState('ticket.card.sale'); + }); + + it('should select the first sale and create a refund without warehouse', async() => { + await page.accessToSearchResult('18'); + await page.waitToClick(selectors.ticketSales.firstSaleCheckbox); + await page.waitToClick(selectors.ticketSales.moreMenu); + await page.waitToClick(selectors.ticketSales.moreMenuRefund); + await page.waitToClick(selectors.ticketSales.refundWithoutWarehouse); + await page.waitForSnackbar(); + await page.waitForState('ticket.card.sale'); + }); + + it('should show error trying to delete a ticket with a refund', async() => { + await page.loginAndModule('salesPerson', 'ticket'); + await page.accessToSearchResult('8'); + await page.waitToClick(selectors.ticketDescriptor.moreMenu); + await page.waitToClick(selectors.ticketDescriptor.moreMenuDeleteTicket); + await page.waitToClick(selectors.globalItems.acceptButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Tickets with associated refunds can\'t be deleted'); + await page.waitToClick(selectors.globalItems.cancelButton); + }); + + it('should select the third sale and create a claim of it', async() => { + await page.accessToSearchResult('16'); + await page.accessToSection('ticket.card.sale'); + await page.waitToClick(selectors.ticketSales.thirdSaleCheckbox); + await page.waitToClick(selectors.ticketSales.moreMenu); + await page.waitToClick(selectors.ticketSales.moreMenuCreateClaim); + await page.waitToClick(selectors.globalItems.acceptButton); + await page.waitForNavigation(); + }); + + it('should search for a ticket then access to the sales section', async() => { + await page.goBack(); + await page.goBack(); + await page.loginAndModule('salesPerson', 'ticket'); + await page.accessToSearchResult('16'); + await page.accessToSection('ticket.card.sale'); + }); + + it('should select the third sale and delete it', async() => { + await page.waitToClick(selectors.ticketSales.thirdSaleCheckbox); + await page.waitToClick(selectors.ticketSales.deleteSaleButton); + await page.waitToClick(selectors.globalItems.acceptButton); + await page.waitForSpinnerLoad(); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it(`should confirm the third sale was deleted`, async() => { + const result = await page.countElement(selectors.ticketSales.saleLine); + + expect(result).toEqual(3); + }); + + it('should select the second sale and transfer it to a valid ticket', async() => { + const targetTicketId = '12'; + + await page.waitToClick(selectors.ticketSales.secondSaleCheckbox); + await page.waitToClick(selectors.ticketSales.transferSaleButton); + await page.waitToClick(selectors.ticketSales.transferQuantityCell); + await page.type(selectors.ticketSales.transferQuantityInput, '10\u000d'); + await page.type(selectors.ticketSales.moveToTicketInput, targetTicketId); + await page.waitToClick(selectors.ticketSales.moveToTicketButton); + await page.expectURL(`ticket/${targetTicketId}/sale`); + }); + + it('should confirm the transfered line is the correct one', async() => { + await page.waitForSelector(selectors.ticketSales.secondSaleText); + const result = await page.waitToGetProperty(selectors.ticketSales.secondSaleText, 'innerText'); + + expect(result).toContain(`Melee weapon heavy shield`); + }); + + it('should confirm the transfered quantity is the correct one', async() => { + const result = await page.waitToGetProperty(selectors.ticketSales.firstSaleQuantityCell, 'innerText'); + + expect(result).toContain('20'); + }); + + it('should go back to the original ticket sales section', async() => { + await page.waitToClick(selectors.ticketDescriptor.goBackToModuleIndexButton); + await page.accessToSearchResult('16'); + await page.accessToSection('ticket.card.sale'); + }); + + it(`should confirm the original ticket has still three lines`, async() => { + await page.waitForSelector(selectors.ticketSales.saleLine); + const result = await page.countElement(selectors.ticketSales.saleLine); + + expect(result).toEqual(3); + }); + + it(`should confirm the second sale quantity is now half of it's original value after the transfer`, async() => { + const result = await page.waitToGetProperty(selectors.ticketSales.secondSaleQuantityCell, 'innerText'); + + expect(result).toContain('10'); + }); + + it('should go back to the receiver ticket sales section', async() => { + await page.waitToClick(selectors.ticketDescriptor.goBackToModuleIndexButton); + await page.accessToSearchResult('12'); + await page.accessToSection('ticket.card.sale'); + }); + + it('should transfer the sale back to the original ticket', async() => { + const targetTicketId = '16'; + + await page.waitToClick(selectors.ticketSales.secondSaleCheckbox); + await page.waitToClick(selectors.ticketSales.transferSaleButton); + await page.type(selectors.ticketSales.moveToTicketInput, targetTicketId); + await page.waitToClick(selectors.ticketSales.moveToTicketButton); + await page.expectURL(`ticket/${targetTicketId}/sale`); + }); + + it('should confirm the original ticket received the line', async() => { + const expectedLines = 4; + await page.waitForNumberOfElements(selectors.ticketSales.saleLine, expectedLines); + const result = await page.countElement(selectors.ticketSales.saleLine); + + expect(result).toEqual(expectedLines); + }); + + it(`should throw an error when attempting to create a ticket for an inactive client`, async() => { + await page.waitToClick(selectors.ticketSales.firstSaleCheckbox); + await page.waitToClick(selectors.ticketSales.transferSaleButton); + await page.waitToClick(selectors.ticketSales.moveToNewTicketButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain(`You can't create a ticket for an inactive client`); + + await page.closePopup(); + }); + + it('should go now to the ticket sales section of an active, not frozen client', async() => { + await page.waitToClick(selectors.ticketDescriptor.goBackToModuleIndexButton); + await page.accessToSearchResult('13'); + await page.accessToSection('ticket.card.sale'); + }); + + it(`should select all sales, tranfer them to a new ticket and delete the sender ticket as it would've been left empty`, async() => { + const senderTicketId = '13'; + + await page.waitToClick(selectors.ticketSales.selectAllSalesCheckbox); + await page.waitToClick(selectors.ticketSales.transferSaleButton); + await page.waitToClick(selectors.ticketSales.moveToNewTicketButton); + await page.evaluate((selector, ticketId) => { + return document.querySelector(selector).innerText.toLowerCase().indexOf(`#${ticketId}`) == -1; + }, selectors.ticketDescriptor.id, senderTicketId); + await page.waitForState('ticket.card.sale'); + }); + + it('should confirm the new ticket received the line', async() => { + const expectedLines = 1; + const result = await page.countElement(selectors.ticketSales.saleLine); + + expect(result).toEqual(expectedLines); + }); + + it('should check the first sale reserved icon isnt visible', async() => { + const result = await page.isVisible(selectors.ticketSales.firstSaleReservedIcon); + + expect(result).toBeFalsy(); + }); + + it('should mark the first sale as reserved', async() => { + await page.waitToClick(selectors.ticketSales.firstSaleCheckbox); + + await page.waitToClick(selectors.ticketSales.moreMenu); + await page.waitToClick(selectors.ticketSales.moreMenuReserve); + await page.closePopup(); + await page.waitForClassNotPresent(selectors.ticketSales.firstSaleReservedIcon, 'ng-hide'); + const result = await page.isVisible(selectors.ticketSales.firstSaleReservedIcon); + + expect(result).toBeTruthy(); + }); + + it('should unmark the first sale as reserved', async() => { + await page.waitToClick(selectors.ticketSales.moreMenu); + await page.waitToClick(selectors.ticketSales.moreMenuUnmarkReseved); + await page.waitForClassPresent(selectors.ticketSales.firstSaleReservedIcon, 'ng-hide'); + const result = await page.isVisible(selectors.ticketSales.firstSaleReservedIcon); + + expect(result).toBeFalsy(); + }); + + it('should log in as Production role and go to a target ticket summary', async() => { + await page.loginAndModule('production', 'ticket'); + await page.accessToSearchResult('13'); + await page.waitForState('ticket.card.summary'); + }); + + it(`should check the ticket is deleted`, async() => { + await page.waitForSelector(selectors.ticketDescriptor.isDeletedIcon); + }); +}); diff --git a/e2e/paths/05-ticket/01_observations.spec.js b/e2e/paths/05-ticket/01_observations.spec.js new file mode 100644 index 000000000..cf37f9ff1 --- /dev/null +++ b/e2e/paths/05-ticket/01_observations.spec.js @@ -0,0 +1,50 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; + +describe('Ticket Create notes path', () => { + let browser; + let page; + + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('employee', 'ticket'); + await page.accessToSearchResult('5'); + await page.accessToSection('ticket.card.observation'); + }); + + afterAll(async() => { + await browser.close(); + }); + + it('should create a new note', async() => { + await page.waitToClick(selectors.ticketNotes.addNoteButton); + await page.autocompleteSearch(selectors.ticketNotes.firstNoteType, 'ItemPicker'); + await page.write(selectors.ticketNotes.firstDescription, 'description'); + await page.waitToClick(selectors.ticketNotes.submitNotesButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it('should confirm the note is the expected one', async() => { + await page.reloadSection('ticket.card.observation'); + const result = await page + .waitToGetProperty(selectors.ticketNotes.firstNoteType, 'value'); + + expect(result).toEqual('ItemPicker'); + + const firstDescription = await page + .waitToGetProperty(selectors.ticketNotes.firstDescription, 'value'); + + expect(firstDescription).toEqual('description'); + }); + + it('should delete the note', async() => { + await page.waitToClick(selectors.ticketNotes.firstNoteRemoveButton); + await page.waitToClick(selectors.ticketNotes.submitNotesButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); +}); diff --git a/e2e/paths/05-ticket/02_expeditions_and_log.spec.js b/e2e/paths/05-ticket/02_expeditions_and_log.spec.js new file mode 100644 index 000000000..4e8005043 --- /dev/null +++ b/e2e/paths/05-ticket/02_expeditions_and_log.spec.js @@ -0,0 +1,32 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; + +describe('Ticket expeditions and log path', () => { + let browser; + let page; + + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('production', 'ticket'); + await page.accessToSearchResult('1'); + await page.accessToSection('ticket.card.expedition'); + }); + + afterAll(async() => { + await browser.close(); + }); + + it(`should delete a former expedition and confirm the remaining expedition are the expected ones`, async() => { + await page.waitToClick(selectors.ticketExpedition.thirdSaleCheckbox); + await page.waitToClick(selectors.ticketExpedition.deleteExpeditionButton); + await page.waitToClick(selectors.globalItems.acceptButton); + await page.reloadSection('ticket.card.expedition'); + + await page.waitForSelector(selectors.ticketExpedition.expeditionRow, {}); + const result = await page + .countElement(selectors.ticketExpedition.expeditionRow); + + expect(result).toEqual(6); + }); +}); diff --git a/e2e/paths/05-ticket/04_packages.spec.js b/e2e/paths/05-ticket/04_packages.spec.js new file mode 100644 index 000000000..1e6a0a173 --- /dev/null +++ b/e2e/paths/05-ticket/04_packages.spec.js @@ -0,0 +1,78 @@ +import getBrowser from '../../helpers/puppeteer'; + +const $ = { + firstPackage: 'vn-autocomplete[label="Package"]', + firstQuantity: 'vn-ticket-package vn-horizontal:nth-child(1) vn-input-number[ng-model="package.quantity"]', + firstRemovePackageButton: 'vn-icon-button[vn-tooltip="Remove package"]', + addPackageButton: 'vn-icon-button[vn-tooltip="Add package"]', + savePackagesButton: `button[type=submit]` +}; + +describe('Ticket Create packages path', () => { + let browser; + let page; + + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('employee', 'ticket'); + await page.accessToSearchResult('1'); + await page.accessToSection('ticket.card.package'); + }); + + afterAll(async() => { + await browser.close(); + }); + + it(`should attempt create a new package but receive an error if package is blank`, async() => { + await page.waitToClick($.firstRemovePackageButton); + await page.waitToClick($.addPackageButton); + await page.write($.firstQuantity, '99'); + await page.waitToClick($.savePackagesButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Package cannot be blank'); + }); + + it(`should delete the first package and receive and error to save a new one with blank quantity`, async() => { + await page.clearInput($.firstQuantity); + await page.autocompleteSearch($.firstPackage, 'Container medical box 100cm'); + await page.waitToClick($.savePackagesButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Some fields are invalid'); + }); + + it(`should confirm the quantity input isn't invalid yet`, async() => { + const result = await page + .evaluate(selector => { + return document.querySelector(`${selector} input`).checkValidity(); + }, $.firstQuantity); + + expect(result).toBeTruthy(); + }); + + it(`should create a new package with correct data`, async() => { + await page.clearInput($.firstQuantity); + await page.write($.firstQuantity, '-99'); + await page.waitToClick($.savePackagesButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it(`should confirm the first select is the expected one`, async() => { + await page.reloadSection('ticket.card.package'); + await page.waitForTextInField($.firstPackage, 'Container medical box 100cm'); + const result = await page.waitToGetProperty($.firstPackage, 'value'); + + expect(result).toEqual('Container medical box 100cm'); + }); + + it(`should confirm quantity is just a number and the string part was ignored by the imput number`, async() => { + await page.waitForTextInField($.firstQuantity, '-99'); + const result = await page.waitToGetProperty($.firstQuantity, 'value'); + + expect(result).toEqual('-99'); + }); +}); diff --git a/e2e/paths/05-ticket/05_tracking_state.spec.js b/e2e/paths/05-ticket/05_tracking_state.spec.js new file mode 100644 index 000000000..5cfc1c9d4 --- /dev/null +++ b/e2e/paths/05-ticket/05_tracking_state.spec.js @@ -0,0 +1,72 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; + +describe('Ticket Create new tracking state path', () => { + let browser; + let page; + + afterAll(async() => { + await browser.close(); + }); + + describe('as production', () => { + it('should log into the ticket 1 tracking', async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('production', 'ticket'); + await page.accessToSearchResult('1'); + await page.accessToSection('ticket.card.tracking.index'); + }); + + it('should access to the create state view by clicking the create floating button', async() => { + await page.waitToClick(selectors.ticketTracking.createStateButton); + await page.waitForSelector(selectors.createStateView.state, {visible: true}); + await page.waitForState('ticket.card.tracking.edit'); + }); + + it(`should create a new state`, async() => { + await page.autocompleteSearch(selectors.createStateView.state, 'OK'); + await page.waitToClick(selectors.createStateView.saveStateButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + }); + + describe('as salesPerson', () => { + it('should now log into the ticket 1 tracking', async() => { + await page.loginAndModule('salesPerson', 'ticket'); + await page.accessToSearchResult('1'); + await page.accessToSection('ticket.card.tracking.index'); + }); + + it('should now access to the create state view by clicking the create floating button', async() => { + await page.waitForSelector('.vn-popup', {hidden: true}); + await page.waitToClick(selectors.ticketTracking.createStateButton); + await page.waitForState('ticket.card.tracking.edit'); + }); + + it(`should attemp to create an state for which salesPerson doesn't have permissions`, async() => { + await page.autocompleteSearch(selectors.createStateView.state, 'Encajado'); + await page.waitToClick(selectors.createStateView.saveStateButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain(`You don't have enough privileges`); + }); + + it(`should make sure the worker gets autocomplete uppon selecting the assigned state`, async() => { + await page.autocompleteSearch(selectors.createStateView.state, 'asignado'); + const result = await page + .waitToGetProperty(selectors.createStateView.worker, 'value'); + + expect(result).toEqual('salesperson'); + }); + + it(`should succesfully create a valid state`, async() => { + await page.waitToClick(selectors.createStateView.saveStateButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + }); +}); diff --git a/e2e/paths/05-ticket/06_basic_data_steps.spec.js b/e2e/paths/05-ticket/06_basic_data_steps.spec.js new file mode 100644 index 000000000..77f0e0459 --- /dev/null +++ b/e2e/paths/05-ticket/06_basic_data_steps.spec.js @@ -0,0 +1,143 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; + +describe('Ticket Edit basic data path', () => { + let browser; + let page; + + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('employee', 'ticket'); + await page.accessToSearchResult('11'); + await page.accessToSection('ticket.card.basicData.stepOne'); + }); + + afterAll(async() => { + await browser.close(); + }); + + it(`should confirm the zone autocomplete is disabled unless your role is productionBoss`, async() => { + await page.waitForSelector(selectors.ticketBasicData.zone, {}); + const disabled = await page.evaluate(selector => { + return document.querySelector(selector).disabled; + }, `${selectors.ticketBasicData.zone} input`); + + expect(disabled).toBeTruthy(); + }); + + it(`should now log as productionBoss to perform the rest of the tests`, async() => { + await page.loginAndModule('productionBoss', 'ticket'); + await page.accessToSearchResult('11'); + await page.accessToSection('ticket.card.basicData.stepOne'); + }); + + it(`should confirm the zone autocomplete is enabled for the role productionBoss`, async() => { + await page.waitForSpinnerLoad(); + await page.waitForSelector(selectors.ticketBasicData.zone); + const disabled = await page.evaluate(selector => { + return document.querySelector(selector).disabled; + }, `${selectors.ticketBasicData.zone} input`); + + expect(disabled).toBeFalsy(); + }); + + it(`should check the zone is for Gotham247`, async() => { + let zone = await page + .waitToGetProperty(selectors.ticketBasicData.zone, 'value'); + + expect(zone).toContain('Zone 247 A'); + }); + + it(`should edit the ticket agency then check there are no zones for it`, async() => { + await page.autocompleteSearch(selectors.ticketBasicData.agency, 'Super-Man delivery'); + let emptyZone = await page + .expectPropertyValue(selectors.ticketBasicData.zone, 'value', ''); + + expect(emptyZone).toBeTruthy(); + }); + + it(`should edit the ticket zone then check the agency is for the new zone`, async() => { + await page.clearInput(selectors.ticketBasicData.agency); + await page.autocompleteSearch(selectors.ticketBasicData.zone, 'Zone expensive A'); + let zone = await page + .waitToGetProperty(selectors.ticketBasicData.agency, 'value'); + + expect(zone).toContain('Gotham247Expensive'); + }); + + it(`should click next`, async() => { + await page.waitToClick(selectors.ticketBasicData.nextStepButton); + await page.waitForState('ticket.card.basicData.stepTwo'); + }); + + it(`should have a price diference`, async() => { + const result = await page + .waitToGetProperty(selectors.ticketBasicData.stepTwoTotalPriceDif, 'innerText'); + + expect(result).toContain('-€228.25'); + }); + + it(`should select a new reason for the changes made then click on finalize`, async() => { + await page.waitToClick(selectors.ticketBasicData.chargesReason); + await page.waitToClick(selectors.ticketBasicData.finalizeButton); + await page.waitForState('ticket.card.summary'); + }); + + it(`should not find ticket`, async() => { + await page.doSearch('29'); + const count = await page.countElement(selectors.ticketsIndex.searchResult); + + expect(count).toEqual(0); + }); + + it(`should split ticket without negatives`, async() => { + const newAgency = 'Gotham247'; + const newDate = Date.vnNew(); + newDate.setDate(newDate.getDate() - 1); + + await page.accessToSearchResult('14'); + await page.accessToSection('ticket.card.basicData.stepOne'); + + await page.autocompleteSearch(selectors.ticketBasicData.agency, newAgency); + await page.pickDate(selectors.ticketBasicData.shipped, newDate); + + await page.waitToClick(selectors.ticketBasicData.nextStepButton); + + await page.waitToClick(selectors.ticketBasicData.finalizeButton); + + await page.waitForState('ticket.card.summary'); + + const newTicketAgency = await page + .waitToGetProperty(selectors.ticketDescriptor.descriptorDeliveryAgency, 'innerText'); + const newTicketDate = await page + .waitToGetProperty(selectors.ticketDescriptor.descriptorDeliveryDate, 'innerText'); + + expect(newAgency).toEqual(newTicketAgency); + expect(newTicketDate).toContain(newDate.getDate()); + }); + + it(`should new ticket have sale of old ticket`, async() => { + await page.accessToSection('ticket.card.sale'); + await page.waitForState('ticket.card.sale'); + + const item = await page.waitToGetProperty(selectors.ticketSales.firstSaleId, 'innerText'); + + expect(item).toEqual('4'); + }); + + it(`should old ticket have old date and agency`, async() => { + const oldDate = Date.vnNew(); + const oldAgency = 'Super-Man delivery'; + + await page.accessToSearchResult('14'); + + const oldTicketAgency = await page + .waitToGetProperty(selectors.ticketDescriptor.descriptorDeliveryAgency, 'innerText'); + const oldTicketDate = await page + .waitToGetProperty(selectors.ticketDescriptor.descriptorDeliveryDate, 'innerText'); + + expect(oldTicketAgency).toEqual(oldAgency); + expect(oldTicketDate).toContain(oldDate.getDate()); + }); +}); diff --git a/e2e/paths/05-ticket/08_components.spec.js b/e2e/paths/05-ticket/08_components.spec.js new file mode 100644 index 000000000..ab2aa85b2 --- /dev/null +++ b/e2e/paths/05-ticket/08_components.spec.js @@ -0,0 +1,30 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; + +describe('Ticket List components path', () => { + let browser; + let page; + + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('employee', 'ticket'); + await page.accessToSearchResult('1'); + await page.accessToSection('ticket.card.components'); + }); + + afterAll(async() => { + await browser.close(); + }); + + it('should confirm the total base is correct', async() => { + const name = 'Base €'; + const minLength = name.length; + + await page.waitPropertyLength(selectors.ticketComponents.base, 'innerText', minLength); + const base = await page.waitToGetProperty(selectors.ticketComponents.base, 'innerText'); + + expect(base).toContain('Base'); + expect(base.length).toBeGreaterThan(minLength); + }); +}); diff --git a/e2e/paths/05-ticket/09_weekly.spec.js b/e2e/paths/05-ticket/09_weekly.spec.js new file mode 100644 index 000000000..370d422e6 --- /dev/null +++ b/e2e/paths/05-ticket/09_weekly.spec.js @@ -0,0 +1,123 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; + +describe('Ticket descriptor path', () => { + let browser; + let page; + + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('buyerBoss', 'ticket'); + await page.accessToSection('ticket.weekly.index'); + }); + + afterAll(async() => { + await browser.close(); + }); + + it('should count the amount of tickets in the turns section', async() => { + const result = await page.countElement(selectors.ticketsIndex.weeklyTicket); + + expect(result).toEqual(6); + }); + + it('should go back to the ticket index then search and access a ticket summary', async() => { + await page.accessToSection('ticket.index'); + await page.accessToSearchResult('33'); + }); + + it('should add the ticket to thursday turn using the descriptor more menu', async() => { + await page.waitToClick(selectors.ticketDescriptor.moreMenu); + await page.waitToClick(selectors.ticketDescriptor.moreMenuAddToTurn); + await page.waitToClick(selectors.ticketDescriptor.thursdayButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Current ticket deleted and added to shift'); + }); + + it('should again click on the Tickets button of the top bar menu', async() => { + await page.waitToClick(selectors.globalItems.applicationsMenuButton); + await page.waitForSelector(selectors.globalItems.applicationsMenuVisible); + await page.waitToClick(selectors.globalItems.ticketsButton); + await page.waitForState('ticket.index'); + }); + + it('should confirm the ticket 33 was added to thursday', async() => { + await page.accessToSection('ticket.weekly.index'); + const result = await page.waitToGetProperty(selectors.ticketsIndex.thirdWeeklyTicket, 'value'); + + expect(result).toEqual('Thursday'); + }); + + it('should click on the Tickets button of the top bar menu once more', async() => { + await page.waitToClick(selectors.globalItems.applicationsMenuButton); + await page.waitForSelector(selectors.globalItems.applicationsMenuVisible); + await page.waitToClick(selectors.globalItems.ticketsButton); + await page.waitForState('ticket.index'); + }); + + it('should now search for the ticket 33', async() => { + await page.accessToSearchResult('33'); + await page.waitForState('ticket.card.summary'); + }); + + it('should add the ticket to saturday turn using the descriptor more menu', async() => { + await page.waitToClick(selectors.ticketDescriptor.moreMenu); + await page.waitToClick(selectors.ticketDescriptor.moreMenuAddToTurn); + await page.waitToClick(selectors.ticketDescriptor.saturdayButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Current ticket deleted and added to shift'); + }); + + it('should click on the Tickets button of the top bar menu once again', async() => { + await page.waitToClick(selectors.globalItems.applicationsMenuButton); + await page.waitForSelector(selectors.globalItems.applicationsMenuVisible); + await page.waitToClick(selectors.globalItems.ticketsButton); + await page.waitForState('ticket.index'); + }); + + it('should confirm the ticket 33 was added on saturday', async() => { + await page.accessToSection('ticket.weekly.index'); + await page.waitForTimeout(5000); + + const result = await page.waitToGetProperty(selectors.ticketsIndex.thirdWeeklyTicket, 'value'); + + expect(result).toEqual('Saturday'); + }); + + it('should now search for the weekly ticket 33', async() => { + await page.doSearch('33'); + const nResults = await page.countElement(selectors.ticketsIndex.searchWeeklyResult); + + expect(nResults).toEqual(2); + }); + + it('should delete the weekly ticket 33', async() => { + await page.waitToClick(selectors.ticketsIndex.firstWeeklyTicketDeleteIcon); + await page.waitToClick(selectors.ticketsIndex.acceptDeleteTurn); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it('should confirm the sixth weekly ticket was deleted', async() => { + await page.doSearch(); + const nResults = await page.countElement(selectors.ticketsIndex.searchWeeklyResult); + + expect(nResults).toEqual(6); + }); + + it('should update the agency then remove it afterwards', async() => { + await page.autocompleteSearch(selectors.ticketsIndex.firstWeeklyTicketAgency, 'Gotham247'); + let message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + + await page.clearInput(selectors.ticketsIndex.firstWeeklyTicketAgency); + message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); +}); diff --git a/e2e/paths/05-ticket/10_request.spec.js b/e2e/paths/05-ticket/10_request.spec.js new file mode 100644 index 000000000..1b580aec2 --- /dev/null +++ b/e2e/paths/05-ticket/10_request.spec.js @@ -0,0 +1,77 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; + +describe('Ticket purchase request path', () => { + let browser; + let page; + + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('salesPerson', 'ticket'); + await page.accessToSearchResult('1'); + await page.accessToSection('ticket.card.request.index'); + }); + + afterAll(async() => { + await browser.close(); + }); + + it('should add a new request', async() => { + await page.waitToClick(selectors.ticketRequests.addRequestButton); + await page.write(selectors.ticketRequests.descriptionInput, 'New stuff'); + await page.write(selectors.ticketRequests.quantity, '9'); + await page.autocompleteSearch(selectors.ticketRequests.atender, 'buyerNick'); + await page.write(selectors.ticketRequests.price, '999'); + await page.waitToClick(selectors.ticketRequests.saveButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it('should have been redirected to the request index', async() => { + await page.waitForState('ticket.card.request.index'); + }); + + it(`should edit the third request quantity as it's state is still new`, async() => { + await page.write(selectors.ticketRequests.thirdRequestQuantity, '9'); + await page.keyboard.press('Enter'); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it('should check the new request was added', async() => { + await page.reloadSection('ticket.card.request.index'); + const result = await page.waitToGetProperty(selectors.ticketRequests.thirdRequestQuantity, 'value'); + + expect(result).toEqual('99'); + }); + + it(`should check the first request can't be edited as its state is different to new`, async() => { + await page.waitForClassPresent(selectors.ticketRequests.firstRequestQuantity, 'disabled'); + const result = await page.isDisabled(selectors.ticketRequests.firstRequestQuantity); + + expect(result).toBe(true); + }); + + it(`should check the second request can't be edited as its state is different to new`, async() => { + await page.waitForClassPresent(selectors.ticketRequests.secondRequestQuantity, 'disabled'); + const result = await page.isDisabled(selectors.ticketRequests.secondRequestQuantity); + + expect(result).toBe(true); + }); + + it('should delete the added request', async() => { + await page.waitToClick(selectors.ticketRequests.thirdRemoveRequestButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it('should check the request was deleted', async() => { + await page.reloadSection('ticket.card.request.index'); + await page.waitForSelector(selectors.ticketRequests.addRequestButton); + await page.waitForSelector(selectors.ticketRequests.thirdDescription, {hidden: true}); + }); +}); diff --git a/e2e/paths/05-ticket/12_descriptor.spec.js b/e2e/paths/05-ticket/12_descriptor.spec.js new file mode 100644 index 000000000..95a114c45 --- /dev/null +++ b/e2e/paths/05-ticket/12_descriptor.spec.js @@ -0,0 +1,148 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; + +describe('Ticket descriptor path', () => { + let browser; + let page; + + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('salesperson', 'ticket'); + }); + + afterAll(async() => { + await browser.close(); + }); + + describe('Delete ticket', () => { + it('should search for an specific ticket', async() => { + await page.accessToSearchResult('18'); + await page.waitForState('ticket.card.summary'); + }); + + it(`should update the shipped hour using the descriptor menu`, async() => { + await page.waitToClick(selectors.ticketDescriptor.moreMenu); + await page.waitToClick(selectors.ticketDescriptor.moreMenuChangeShippedHour); + await page.pickTime(selectors.ticketDescriptor.changeShippedHour, '08:15'); + await page.waitToClick(selectors.ticketDescriptor.acceptChangeHourButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Shipped hour updated'); + }); + + it(`should confirm the ticket descriptor shows the correct shipping hour`, async() => { + await page.waitForState('ticket.card.summary'); + const result = await page + .waitToGetProperty(selectors.ticketDescriptor.descriptorDeliveryDate, 'innerText'); + + expect(result).toContain('08:15'); + }); + + it('should delete the ticket using the descriptor menu', async() => { + await page.waitToClick(selectors.ticketDescriptor.moreMenu); + await page.waitToClick(selectors.ticketDescriptor.moreMenuDeleteTicket); + await page.waitToClick(selectors.ticketDescriptor.acceptDialog); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Ticket deleted. You can undo this action within the first hour'); + }); + + it('should have been relocated to the ticket index', async() => { + await page.waitForState('ticket.index'); + }); + + it(`should search for the deleted ticket and check the deletedTicket icon and it's date`, async() => { + await page.write(selectors.ticketsIndex.topbarSearch, '18'); + await page.waitToClick(selectors.globalItems.searchButton); + await page.waitForState('ticket.card.summary'); + await page.isVisible(selectors.ticketDescriptor.isDeletedIcon); + const result = await page.waitToGetProperty(selectors.ticketsIndex.searchResultDate, 'innerText'); + + expect(result).toContain(2000); + }); + }); + + describe('Restore ticket', () => { + it('should restore the ticket using the descriptor menu', async() => { + await page.waitToClick(selectors.ticketDescriptor.moreMenu); + await page.waitToClick(selectors.ticketDescriptor.moreMenuRestoreTicket); + await page.waitToClick(selectors.ticketDescriptor.acceptDialog); + await page.waitForState('ticket.card.summary'); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + }); + + describe('Make invoice', () => { + it('should login as administrative role then search for a ticket', async() => { + const invoiceableTicketId = '14'; + + await page.loginAndModule('administrative', 'ticket'); + await page.accessToSearchResult(invoiceableTicketId); + await page.waitForState('ticket.card.summary'); + }); + + it(`should make sure the ticket doesn't have an invoiceOutFk yet`, async() => { + const result = await page + .waitToGetProperty(selectors.ticketSummary.invoiceOutRef, 'innerText'); + + expect(result).toEqual('-'); + }); + + it('should invoice the ticket using the descriptor menu', async() => { + await page.waitToClick(selectors.ticketDescriptor.moreMenu); + await page.waitForContentLoaded(); + await page.waitToClick(selectors.ticketDescriptor.moreMenuMakeInvoice); + await page.waitToClick(selectors.ticketDescriptor.acceptInvoiceOutButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Ticket invoiced'); + }); + + it(`should make sure the ticket summary have an invoiceOutFk`, async() => { + await page.waitForTextInElement(selectors.ticketSummary.invoiceOutRef, 'T4444445'); + const result = await page.waitToGetProperty(selectors.ticketSummary.invoiceOutRef, 'innerText'); + + expect(result).toEqual('T4444445'); + }); + + it(`should regenerate the invoice using the descriptor menu`, async() => { + const expectedMessage = 'The invoice PDF document has been regenerated'; + + await page.waitToClick(selectors.ticketDescriptor.moreMenu); + await page.waitForContentLoaded(); + await page.waitToClick(selectors.ticketDescriptor.moreMenuRegenerateInvoice); + await page.respondToDialog('accept'); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain(expectedMessage); + }); + }); + + describe('SMS', () => { + it('should send the payment SMS using the descriptor menu', async() => { + await page.waitToClick(selectors.ticketDescriptor.moreMenu); + await page.waitToClick(selectors.ticketDescriptor.moreMenuSMSOptions); + await page.waitToClick(selectors.ticketDescriptor.moreMenuPaymentSMS); + await page.waitForSelector(selectors.ticketDescriptor.SMStext); + await page.waitPropertyLength(selectors.ticketDescriptor.SMStext, 'value', 128); + await page.waitToClick(selectors.ticketDescriptor.sendSMSbutton); + const message = await page.waitForSnackbar(); + + expect(message).toBeDefined(); + }); + + it('should send the import SMS using the descriptor menu', async() => { + await page.waitToClick(selectors.ticketDescriptor.moreMenuSMSOptions); + await page.waitToClick(selectors.ticketDescriptor.moreMenuSendImportSms); + await page.waitForSelector(selectors.ticketDescriptor.SMStext); + await page.waitPropertyLength(selectors.ticketDescriptor.SMStext, 'value', 144); + await page.waitToClick(selectors.ticketDescriptor.sendSMSbutton); + const message = await page.waitForSnackbar(); + + expect(message).toBeDefined(); + }); + }); +}); diff --git a/e2e/paths/05-ticket/13_services.spec.js b/e2e/paths/05-ticket/13_services.spec.js new file mode 100644 index 000000000..50df23582 --- /dev/null +++ b/e2e/paths/05-ticket/13_services.spec.js @@ -0,0 +1,127 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; + +describe('Ticket services path', () => { + let browser; + let page; + const invoicedTicketId = '1'; + + afterAll(async() => { + await browser.close(); + }); + + describe('as employee', () => { + it('should log in as employee, search for an invoice and get to services', async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('employee', 'ticket'); + await page.accessToSearchResult(invoicedTicketId); + await page.accessToSection('ticket.card.service'); + }); + + it('should find the add descripton button disabled for this user role', async() => { + await page.waitForClassPresent(selectors.ticketService.firstAddServiceTypeButton, 'disabled'); + await page.waitToClick(selectors.ticketService.addServiceButton); + await page.waitForSelector(selectors.ticketService.firstAddServiceTypeButton); + const disabled = await page.isDisabled(selectors.ticketService.firstAddServiceTypeButton); + + expect(disabled).toBe(true); + }); + + it('should receive an error if you attempt to save a service without access rights', async() => { + await page.clearInput(selectors.ticketService.firstPrice); + await page.write(selectors.ticketService.firstPrice, '999'); + await page.waitToClick(selectors.ticketService.saveServiceButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain(`The current ticket can't be modified`); + }); + }); + + describe('as administrative', () => { + let editableTicketId = '16'; + it('should navigate to the services of a target ticket', async() => { + await page.loginAndModule('administrative', 'ticket'); + await page.accessToSearchResult(editableTicketId); + await page.accessToSection('ticket.card.service'); + }); + + it('should click on the add button to prepare the form to create a new service', async() => { + await page.waitToClick(selectors.ticketService.addServiceButton); + const result = await page + .isVisible(selectors.ticketService.firstServiceType); + + expect(result).toBeTruthy(); + }); + + it('should receive an error if you attempt to save it with empty fields', async() => { + await page.waitToClick(selectors.ticketService.saveServiceButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain(`can't be blank`); + }); + + it('should click on the add new service type to open the dialog', async() => { + await page.waitToClick(selectors.ticketService.firstAddServiceTypeButton); + await page.waitForSelector('.vn-dialog.shown'); + const result = await page.isVisible(selectors.ticketService.newServiceTypeName); + + expect(result).toBeTruthy(); + }); + + it('should receive an error if service type is empty on submit', async() => { + await page.waitToClick(selectors.ticketService.saveServiceTypeButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain(`Name can't be empty`); + }); + + it('should create a new service type then add price then create the service', async() => { + await page.write(selectors.ticketService.newServiceTypeName, 'Documentos'); + await page.waitToClick(selectors.ticketService.saveServiceTypeButton); + await page.write(selectors.ticketService.firstPrice, '999'); + await page.waitToClick(selectors.ticketService.saveServiceButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it('should confirm the service description was created correctly', async() => { + await page.reloadSection('ticket.card.service'); + const result = await page + .waitToGetProperty(selectors.ticketService.firstServiceType, 'value'); + + expect(result).toEqual('Documentos'); + }); + + it('should confirm the service quantity was created correctly', async() => { + const result = await page + .waitToGetProperty(selectors.ticketService.firstQuantity, 'value'); + + expect(result).toEqual('1'); + }); + + it('should confirm the service price was created correctly', async() => { + const result = await page + .waitToGetProperty(selectors.ticketService.firstPrice, 'value'); + + expect(result).toEqual('999'); + }); + + it('should delete the service', async() => { + await page.waitToClick(selectors.ticketService.fistDeleteServiceButton); + await page.waitForNumberOfElements(selectors.ticketService.serviceLine, 0); + await page.waitToClick(selectors.ticketService.saveServiceButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it(`should confirm the service was removed`, async() => { + await page.reloadSection('ticket.card.service'); + const nResults = await page.countElement(selectors.ticketService.serviceLine); + + expect(nResults).toEqual(0); + }); + }); +}); diff --git a/e2e/paths/05-ticket/14_create_ticket.spec.js b/e2e/paths/05-ticket/14_create_ticket.spec.js new file mode 100644 index 000000000..1f9c0c40a --- /dev/null +++ b/e2e/paths/05-ticket/14_create_ticket.spec.js @@ -0,0 +1,69 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; + +describe('Ticket create path', () => { + let browser; + let page; + let nextMonth = Date.vnNew(); + nextMonth.setMonth(nextMonth.getMonth() + 1); + + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('salesPerson', 'ticket'); + }); + + afterAll(async() => { + await browser.close(); + }); + + it('should open the new ticket form', async() => { + await page.waitToClick(selectors.ticketsIndex.newTicketButton); + await page.waitForState('ticket.create'); + }); + + it('should succeed to create a ticket', async() => { + await page.autocompleteSearch(selectors.createTicketView.client, 'Clark Kent'); + await page.pickDate(selectors.createTicketView.deliveryDate, nextMonth); + await page.autocompleteSearch(selectors.createTicketView.warehouse, 'Warehouse Two'); + await page.autocompleteSearch(selectors.createTicketView.agency, 'Gotham247'); + await page.waitToClick(selectors.createTicketView.createButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it('should check the url is now the summary of the ticket', async() => { + await page.waitForState('ticket.card.summary'); + }); + + it('should again open the new ticket form', async() => { + await page.waitToClick(selectors.globalItems.returnToModuleIndexButton); + await page.waitToClick(selectors.ticketsIndex.newTicketButton); + await page.waitForState('ticket.create'); + }); + + it('should succeed to create another ticket for the same client', async() => { + await page.autocompleteSearch(selectors.createTicketView.client, 'Clark Kent'); + await page.pickDate(selectors.createTicketView.deliveryDate, nextMonth); + await page.autocompleteSearch(selectors.createTicketView.warehouse, 'Warehouse One'); + await page.autocompleteSearch(selectors.createTicketView.agency, 'Gotham247'); + await page.waitToClick(selectors.createTicketView.createButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it('should check the url is now the summary of the created ticket', async() => { + await page.waitForState('ticket.card.summary'); + }); + + it('should delete the current ticket', async() => { + await page.waitToClick(selectors.ticketDescriptor.moreMenu); + await page.waitToClick(selectors.ticketDescriptor.moreMenuDeleteTicket); + await page.waitToClick(selectors.ticketDescriptor.acceptDialog); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Ticket deleted. You can undo this action within the first hour'); + }); +}); diff --git a/e2e/paths/05-ticket/15_create_ticket_from_client.spec.js b/e2e/paths/05-ticket/15_create_ticket_from_client.spec.js new file mode 100644 index 000000000..51ead6461 --- /dev/null +++ b/e2e/paths/05-ticket/15_create_ticket_from_client.spec.js @@ -0,0 +1,37 @@ +import getBrowser from '../../helpers/puppeteer'; + +const $ = { + form: 'vn-ticket-create-card', + moreMenu: 'vn-client-descriptor vn-icon-button[icon=more_vert]', + simpleTicketButton: '.vn-menu [name="simpleTicket"]' +}; + +describe('Ticket create from client path', () => { + let browser; + let page; + + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('employee', 'client'); + await page.accessToSearchResult('Petter Parker'); + }); + + afterAll(async() => { + await browser.close(); + }); + + it('should create simple ticket and check if the client details are the expected ones', async() => { + await page.waitToClick($.moreMenu); + await page.waitToClick($.simpleTicketButton); + await page.waitForState('ticket.create'); + + const values = { + client: 'Petter Parker', + address: 'Petter Parker' + }; + const formValues = await page.fetchForm($.form, Object.keys(values)); + + expect(formValues).toEqual(values); + }); +}); diff --git a/e2e/paths/05-ticket/16_summary.spec.js b/e2e/paths/05-ticket/16_summary.spec.js new file mode 100644 index 000000000..a6017e454 --- /dev/null +++ b/e2e/paths/05-ticket/16_summary.spec.js @@ -0,0 +1,108 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; + +describe('Ticket Summary path', () => { + let browser; + let page; + const ticketId = '20'; + + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + }); + + afterAll(async() => { + await browser.close(); + }); + + it('should navigate to the target ticket summary section', async() => { + await page.loginAndModule('employee', 'ticket'); + await page.accessToSearchResult(ticketId); + await page.waitForState('ticket.card.summary'); + }); + + it(`should display details from the ticket and it's client on the top of the header`, async() => { + await page.waitForTextInElement(selectors.ticketSummary.header, 'Bruce Banner'); + const result = await page.waitToGetProperty(selectors.ticketSummary.header, 'innerText'); + + expect(result).toContain(`Ticket #${ticketId}`); + expect(result).toContain('Bruce Banner (1109)'); + expect(result).toContain('Somewhere in Thailand'); + }); + + it('should display ticket details', async() => { + let result = await page + .waitToGetProperty(selectors.ticketSummary.state, 'innerText'); + + expect(result).toContain('Arreglar'); + }); + + it('should display delivery details', async() => { + let result = await page + .waitToGetProperty(selectors.ticketSummary.route, 'innerText'); + + expect(result).toContain('3'); + }); + + it('should display the ticket total', async() => { + let result = await page + .waitToGetProperty(selectors.ticketSummary.total, 'innerText'); + + expect(result).toContain('€155.54'); + }); + + it('should display the ticket line(s)', async() => { + let result = await page + .waitToGetProperty(selectors.ticketSummary.firstSaleItemId, 'innerText'); + + expect(result).toContain('2'); + }); + + it(`should click on the first sale ID to make the item descriptor visible`, async() => { + await page.waitToClick(selectors.ticketSummary.firstSaleItemId); + await page.waitImgLoad(selectors.ticketSummary.firstSaleDescriptorImage); + const visible = await page.isVisible(selectors.ticketSummary.itemDescriptorPopover); + + expect(visible).toBeTruthy(); + }); + + it(`should check the url for the item diary link of the descriptor is for the right item id`, async() => { + await page.waitForSelector(selectors.ticketSummary.itemDescriptorPopoverItemDiaryButton, {visible: true}); + }); + + it('should log in as production then navigate to the summary of the same ticket', async() => { + await page.loginAndModule('production', 'ticket'); + await page.accessToSearchResult(ticketId); + await page.waitForState('ticket.card.summary'); + }); + + it('should set the ticket state to OK using the top right button', async() => { + const searchValue = 'OK'; + await page.waitToClick(selectors.ticketSummary.stateButton); + await page.write(selectors.ticketSummary.stateAutocomplete, searchValue); + try { + await page.waitForFunction(text => { + const element = document.querySelector('li.active'); + if (element) + return element.innerText.toLowerCase().includes(text.toLowerCase()); + }, {}, searchValue); + } catch (error) { + const state = await page.evaluate(() => { + const stateSelector = 'vn-ticket-summary vn-label-value:nth-child(1) > section > span'; + return document.querySelector(stateSelector).value; + }); + throw new Error(`${stateSelector} innerText is ${state}! ${error}`); + } + await page.keyboard.press('Enter'); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it('should confirm the ticket state was updated', async() => { + await page.waitForSpinnerLoad(); + const result = await page.waitToGetProperty(selectors.ticketSummary.state, 'innerText'); + + expect(result).toContain('OK'); + }); +}); diff --git a/e2e/paths/05-ticket/17_log.spec.js b/e2e/paths/05-ticket/17_log.spec.js new file mode 100644 index 000000000..e1da2df44 --- /dev/null +++ b/e2e/paths/05-ticket/17_log.spec.js @@ -0,0 +1,34 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; + +describe('Ticket log path', () => { + let browser; + let page; + const ticketId = '5'; + + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + }); + + afterAll(async() => { + await browser.close(); + }); + + it('should navigate to the target ticket notes section', async() => { + await page.loginAndModule('employee', 'ticket'); + await page.accessToSearchResult(ticketId); + await page.accessToSection('ticket.card.observation'); + await page.waitForState('ticket.card.observation'); + }); + + it('should create a new note for the test', async() => { + await page.waitToClick(selectors.ticketNotes.addNoteButton); + await page.autocompleteSearch(selectors.ticketNotes.firstNoteType, 'ItemPicker'); + await page.write(selectors.ticketNotes.firstDescription, 'description'); + await page.waitToClick(selectors.ticketNotes.submitNotesButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); +}); diff --git a/e2e/paths/05-ticket/18_index_payout.spec.js b/e2e/paths/05-ticket/18_index_payout.spec.js new file mode 100644 index 000000000..9c5518424 --- /dev/null +++ b/e2e/paths/05-ticket/18_index_payout.spec.js @@ -0,0 +1,70 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; +const $ = { + newPayment: '.vn-dialog.shown', + anyBalanceLine: 'vn-client-balance-index vn-tbody > vn-tr', + firstLineReference: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td-editable' +}; + +describe('Ticket index payout path', () => { + let browser; + let page; + + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('administrative', 'ticket'); + await page.waitForState('ticket.index'); + }); + + afterAll(async() => { + await browser.close(); + }); + + it('should check the second ticket from a client and 1 of another', async() => { + await page.waitToClick(selectors.globalItems.searchButton); + await page.waitToClick(selectors.ticketsIndex.thirdTicketCheckbox); + await page.waitToClick(selectors.ticketsIndex.fifthTicketCheckbox); + await page.waitToClick(selectors.ticketsIndex.payoutButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('You cannot make a payment on account from multiple clients'); + }); + + it('should search for tickets of the same client then open the payout form', async() => { + await page.waitToClick(selectors.ticketsIndex.openAdvancedSearchButton); + await page.write(selectors.ticketsIndex.advancedSearchClient, '1101'); + await page.keyboard.press('Enter'); + await page.waitForNumberOfElements(selectors.ticketsIndex.anySearchResult, 10); + await page.waitToClick(selectors.ticketsIndex.firstTicketCheckbox); + await page.waitToClick(selectors.ticketsIndex.secondTicketCheckbox); + + await page.waitToClick(selectors.ticketsIndex.payoutButton); + + await page.waitForSelector(selectors.ticketsIndex.payoutCompany); + }); + + it('should fill the company and bank to perform a payout and check a new balance line was entered', async() => { + await page.fillForm($.newPayment, { + company: 'VNL', + bank: 'cash', + amountPaid: 100, + description: 'Payment', + viewReceipt: false + }); + await page.respondToDialog('accept'); + const message = await page.waitForSnackbar(); + + await page.waitToClick(selectors.globalItems.homeButton); + await page.selectModule('client'); + await page.accessToSearchResult('1101'); + await page.accessToSection('client.card.balance.index'); + await page.waitForSelector($.anyBalanceLine); + const count = await page.countElement($.anyBalanceLine); + const reference = await page.innerText($.firstLineReference); + + expect(message.isSuccess).toBeTrue(); + expect(count).toEqual(4); + expect(reference).toContain('Payment'); + }); +}); diff --git a/e2e/paths/05-ticket/19_dms.spec.js b/e2e/paths/05-ticket/19_dms.spec.js new file mode 100644 index 000000000..be2ac4338 --- /dev/null +++ b/e2e/paths/05-ticket/19_dms.spec.js @@ -0,0 +1,49 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; + +describe('Ticket DMS path', () => { + let browser; + let page; + + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('employee', 'ticket'); + await page.accessToSearchResult('1'); + await page.accessToSection('ticket.card.dms.index'); + }); + + afterAll(async() => { + await browser.close(); + }); + + it('should import a document', async() => { + await page.waitToClick(selectors.ticketDms.import); + await page.autocompleteSearch(selectors.ticketDms.document, '1'); + await page.waitToClick(selectors.ticketDms.saveImport); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); + }); + + it(`should check there's a listed document now`, async() => { + const result = await page.countElement(selectors.ticketDms.anyDocument); + + expect(result).toEqual(1); + }); + + it('should attempt to import an existing document on this ticket', async() => { + await page.waitToClick(selectors.ticketDms.import); + await page.autocompleteSearch(selectors.ticketDms.document, '1'); + await page.waitToClick(selectors.ticketDms.saveImport); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('This document already exists on this ticket'); + }); + + it(`should check there's still one document`, async() => { + const result = await page.countElement(selectors.ticketDms.anyDocument); + + expect(result).toEqual(1); + }); +}); diff --git a/e2e/paths/05-ticket/20_moveExpedition.spec.js b/e2e/paths/05-ticket/20_moveExpedition.spec.js new file mode 100644 index 000000000..ae23c9c99 --- /dev/null +++ b/e2e/paths/05-ticket/20_moveExpedition.spec.js @@ -0,0 +1,50 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; + +describe('Ticket expeditions', () => { + let browser; + let page; + + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('production', 'ticket'); + await page.accessToSearchResult('1'); + await page.accessToSection('ticket.card.expedition'); + }); + + afterAll(async() => { + await browser.close(); + }); + + it(`should move one expedition to new ticket withoute route`, async() => { + await page.waitToClick(selectors.ticketExpedition.thirdSaleCheckbox); + await page.waitToClick(selectors.ticketExpedition.moveExpeditionButton); + await page.waitToClick(selectors.ticketExpedition.moreMenuWithoutRoute); + await page.waitToClick(selectors.ticketExpedition.saveButton); + await page.waitForState('ticket.card.summary'); + await page.accessToSection('ticket.card.expedition'); + + await page.waitForSelector(selectors.ticketExpedition.expeditionRow, {}); + const result = await page + .countElement(selectors.ticketExpedition.expeditionRow); + + expect(result).toEqual(2); + }); + + it(`should move one expedition to new ticket with route`, async() => { + await page.waitToClick(selectors.ticketExpedition.firstSaleCheckbox); + await page.waitToClick(selectors.ticketExpedition.moveExpeditionButton); + await page.waitToClick(selectors.ticketExpedition.moreMenuWithRoute); + await page.write(selectors.ticketExpedition.newRouteId, '1'); + await page.waitToClick(selectors.ticketExpedition.saveButton); + await page.waitForState('ticket.card.summary'); + await page.accessToSection('ticket.card.expedition'); + + await page.waitForSelector(selectors.ticketExpedition.expeditionRow, {}); + const result = await page + .countElement(selectors.ticketExpedition.expeditionRow); + + expect(result).toEqual(2); + }); +}); diff --git a/e2e/paths/05-ticket/21_future.spec.js b/e2e/paths/05-ticket/21_future.spec.js new file mode 100644 index 000000000..60bb9c38d --- /dev/null +++ b/e2e/paths/05-ticket/21_future.spec.js @@ -0,0 +1,99 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; + +describe('Ticket Future path', () => { + let browser; + let page; + let httpRequest; + + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('employee', 'ticket'); + await page.accessToSection('ticket.future'); + page.on('request', req => { + if (req.url().includes(`Tickets/getTicketsFuture`)) + httpRequest = req.url(); + }); + }); + + afterAll(async() => { + await browser.close(); + }); + + it('should search with required data, check three last tickets and move to the future', async() => { + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + await page.clearInput(selectors.ticketFuture.warehouseFk); + await page.waitToClick(selectors.ticketFuture.submit); + let message = await page.waitForSnackbar(); + + expect(message.text).toContain('warehouseFk is a required argument'); + + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + await page.clearInput(selectors.ticketFuture.futureScopeDays); + await page.waitToClick(selectors.ticketFuture.submit); + message = await page.waitForSnackbar(); + + expect(message.text).toContain('futureScopeDays is a required argument'); + + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + await page.clearInput(selectors.ticketFuture.originScopeDays); + await page.waitToClick(selectors.ticketFuture.submit); + message = await page.waitForSnackbar(); + + expect(message.text).toContain('originScopeDays is a required argument'); + + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + await page.waitToClick(selectors.ticketFuture.submit); + + expect(httpRequest).toBeDefined(); + + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + + await page.autocompleteSearch(selectors.ticketFuture.ipt, 'H'); + await page.waitToClick(selectors.ticketFuture.submit); + + expect(httpRequest).toContain('ipt=H'); + + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + + await page.clearInput(selectors.ticketFuture.ipt); + + await page.autocompleteSearch(selectors.ticketFuture.futureIpt, 'H'); + await page.waitToClick(selectors.ticketFuture.submit); + + expect(httpRequest).toContain('futureIpt=H'); + + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + + await page.clearInput(selectors.ticketFuture.futureIpt); + + await page.autocompleteSearch(selectors.ticketFuture.state, 'Free'); + await page.waitToClick(selectors.ticketFuture.submit); + + expect(httpRequest).toContain('state=0'); + + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + + await page.clearInput(selectors.ticketFuture.state); + + await page.autocompleteSearch(selectors.ticketFuture.futureState, 'Free'); + await page.waitToClick(selectors.ticketFuture.submit); + + expect(httpRequest).toContain('futureState=0'); + + await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); + await page.clearInput(selectors.ticketFuture.state); + await page.clearInput(selectors.ticketFuture.futureState); + await page.waitToClick(selectors.ticketFuture.submit); + + await page.waitForNumberOfElements(selectors.ticketFuture.searchResult, 5); + await page.waitToClick(selectors.ticketFuture.multiCheck); + await page.waitToClick(selectors.ticketFuture.firstCheck); + await page.waitToClick(selectors.ticketFuture.moveButton); + await page.waitToClick(selectors.globalItems.acceptButton); + message = await page.waitForSnackbar(); + + expect(message.text).toContain('Tickets moved successfully!'); + }); +}); diff --git a/e2e/paths/05-ticket/22_advance.spec.js b/e2e/paths/05-ticket/22_advance.spec.js new file mode 100644 index 000000000..0e5b5e0c3 --- /dev/null +++ b/e2e/paths/05-ticket/22_advance.spec.js @@ -0,0 +1,79 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; + +describe('Ticket Advance path', () => { + let browser; + let page; + let httpRequest; + + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('employee', 'ticket'); + await page.accessToSection('ticket.advance'); + page.on('request', req => { + if (req.url().includes(`Tickets/getTicketsAdvance`)) + httpRequest = req.url(); + }); + }); + + afterAll(async() => { + await browser.close(); + }); + + it('should search with the required data, check the first ticket and move to the present', async() => { + await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); + await page.clearInput(selectors.ticketAdvance.warehouseFk); + + await page.waitToClick(selectors.ticketAdvance.submit); + let message = await page.waitForSnackbar(); + + expect(message.text).toContain('warehouseFk is a required argument'); + + await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); + await page.clearInput(selectors.ticketAdvance.dateToAdvance); + await page.waitToClick(selectors.ticketAdvance.submit); + message = await page.waitForSnackbar(); + + expect(message.text).toContain('dateToAdvance is a required argument'); + + await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); + await page.clearInput(selectors.ticketAdvance.dateFuture); + await page.waitToClick(selectors.ticketAdvance.submit); + message = await page.waitForSnackbar(); + + expect(message.text).toContain('dateFuture is a required argument'); + + await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); + await page.waitToClick(selectors.ticketAdvance.submit); + + expect(httpRequest).toBeDefined(); + + await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); + await page.autocompleteSearch(selectors.ticketAdvance.futureIpt, 'H'); + await page.waitToClick(selectors.ticketAdvance.submit); + + expect(httpRequest).toContain('futureIpt=H'); + + await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); + await page.clearInput(selectors.ticketAdvance.futureIpt); + await page.waitToClick(selectors.ticketAdvance.submit); + + await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); + await page.autocompleteSearch(selectors.ticketAdvance.ipt, 'H'); + await page.waitToClick(selectors.ticketAdvance.submit); + + expect(httpRequest).toContain('ipt=H'); + + await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); + await page.clearInput(selectors.ticketAdvance.ipt); + await page.waitToClick(selectors.ticketAdvance.submit); + + await page.waitToClick(selectors.ticketAdvance.firstCheck); + await page.waitToClick(selectors.ticketAdvance.moveButton); + await page.waitToClick(selectors.ticketAdvance.acceptButton); + message = await page.waitForSnackbar(); + + expect(message.text).toContain('Tickets moved successfully!'); + }); +}); diff --git a/loopback/locale/en.json b/loopback/locale/en.json index 0336370d9..6756db37d 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -223,7 +223,6 @@ "Shelving not valid": "Shelving not valid", "printerNotExists": "The printer does not exist", "There are not picking tickets": "There are not picking tickets", - "ticketCommercial": "The ticket {{ ticket }} for the salesperson {{ salesMan }} is in preparation. (automatically generated message)", "This password can only be changed by the user themselves": "This password can only be changed by the user themselves", "They're not your subordinate": "They're not your subordinate", "InvoiceIn is already booked": "InvoiceIn is already booked", @@ -241,11 +240,11 @@ "The height must be greater than 50cm": "The height must be greater than 50cm", "The maximum height of the wagon is 200cm": "The maximum height of the wagon is 200cm", "The quantity claimed cannot be greater than the quantity of the line": "The quantity claimed cannot be greater than the quantity of the line", + "There are tickets for this area, delete them first": "There are tickets for this area, delete them first", + "You do not have permission to modify the booked field": "You do not have permission to modify the booked field", "Invalid or expired verification code": "Invalid or expired verification code", - "There are tickets for this area, delete them first": "There are tickets for this area, delete them first", "ticketLostExpedition": "The ticket [{{ticketId}}]({{{ticketUrl}}}) has the following lost expedition:{{ expeditionId }}", - "Payment method is required": "Payment method is required", "The raid information is not correct": "The raid information is not correct", + "Payment method is required": "Payment method is required", "Sales already moved": "Sales already moved" - } diff --git a/loopback/locale/es.json b/loopback/locale/es.json index f04eed0e8..0b10d4702 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -359,7 +359,6 @@ "This workCenter is already assigned to this agency": "Este centro de trabajo ya está asignado a esta agencia", "Select ticket or client": "Elija un ticket o un client", "It was not able to create the invoice": "No se pudo crear la factura", - "ticketCommercial": "El ticket {{ ticket }} para el vendedor {{ salesMan }} está en preparación. (mensaje generado automáticamente)", "Incoterms and Customs agent are required for a non UEE member": "Se requieren Incoterms y agente de aduanas para un no miembro de la UEE", "You can not use the same password": "No puedes usar la misma contraseña", "This PDA is already assigned to another user": "Este PDA ya está asignado a otro usuario", @@ -386,9 +385,10 @@ "type cannot be blank": "Se debe rellenar el tipo", "There are tickets for this area, delete them first": "Hay tickets para esta sección, borralos primero", "There is no company associated with that warehouse": "No hay ninguna empresa asociada a ese almacén", + "You do not have permission to modify the booked field": "No tienes permisos para modificar el campo contabilizada", "ticketLostExpedition": "El ticket [{{ticketId}}]({{{ticketUrl}}}) tiene la siguiente expedición perdida:{{ expeditionId }}", "The web user's email already exists": "El correo del usuario web ya existe", - "Sales already moved": "Ya han sido transferidas", + "Sales already moved": "Ya han sido transferidas", "The raid information is not correct": "La información de la redada no es correcta" } diff --git a/loopback/locale/fr.json b/loopback/locale/fr.json index 0e876f89c..9941358be 100644 --- a/loopback/locale/fr.json +++ b/loopback/locale/fr.json @@ -362,8 +362,9 @@ "The invoices have been created but the PDFs could not be generated": "La facture a été émise mais le PDF n'a pas pu être généré", "It has been invoiced but the PDF of refund not be generated": "Il a été facturé mais le PDF de remboursement n'a pas été généré", "Cannot send mail": "Impossible d'envoyer le mail", - "Original invoice not found": "Facture originale introuvable", - "The quantity claimed cannot be greater than the quantity of the line": "Le montant réclamé ne peut pas être supérieur au montant de la ligne", + "Original invoice not found": "Facture originale introuvable", + "The quantity claimed cannot be greater than the quantity of the line": "Le montant réclamé ne peut pas être supérieur au montant de la ligne", + "You do not have permission to modify the booked field": "Vous n'avez pas la permission de modifier le champ comptabilisé", "ticketLostExpedition": "Le ticket [{{ticketId}}]({{{ticketUrl}}}) a l'expédition perdue suivante : {{expeditionId}}", "The web user's email already exists": "L'email de l'internaute existe déjà" -} \ No newline at end of file +} diff --git a/loopback/locale/pt.json b/loopback/locale/pt.json index e08336273..e84b30f3d 100644 --- a/loopback/locale/pt.json +++ b/loopback/locale/pt.json @@ -366,4 +366,4 @@ "The quantity claimed cannot be greater than the quantity of the line": "O valor reclamado não pode ser superior ao valor da linha", "ticketLostExpedition": "O ticket [{{ticketId}}]({{{ticketUrl}}}) tem a seguinte expedição perdida: {{expeditionId}}", "The web user's email already exists": "O e-mail do utilizador da web já existe." -} \ No newline at end of file +} diff --git a/modules/client/back/methods/client/summary.js b/modules/client/back/methods/client/summary.js index 9242fbd44..9c1420b61 100644 --- a/modules/client/back/methods/client/summary.js +++ b/modules/client/back/methods/client/summary.js @@ -54,7 +54,7 @@ module.exports = Self => { { relation: 'country', scope: { - fields: ['id', 'name'], + fields: ['id', 'name', 'code'], include: { relation: 'saySimpleCountry', } diff --git a/modules/entry/back/methods/entry/print.js b/modules/entry/back/methods/entry/labelSupplier.js similarity index 87% rename from modules/entry/back/methods/entry/print.js rename to modules/entry/back/methods/entry/labelSupplier.js index 5b9de9a69..32d80c427 100644 --- a/modules/entry/back/methods/entry/print.js +++ b/modules/entry/back/methods/entry/labelSupplier.js @@ -1,6 +1,6 @@ const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { - Self.remoteMethodCtx('print', { + Self.remoteMethodCtx('labelSupplier', { description: 'Print stickers of all entries', accessType: 'READ', accepts: [ @@ -28,13 +28,13 @@ module.exports = Self => { } ], http: { - path: '/:id/print', + path: '/:id/labelSupplier', verb: 'GET' }, accessScopes: ['DEFAULT', 'read:multimedia'] }); - Self.print = async function(ctx, id, options) { + Self.labelSupplier = async function(ctx, id, options) { const models = Self.app.models; const myOptions = {}; if (typeof options == 'object') @@ -48,7 +48,8 @@ module.exports = Self => { for (const buy of buys) { if (buy.stickers < 1) continue; ctx.args.id = buy.id; - const pdfBuffer = await models.Entry.buyLabel(ctx, myOptions); + ctx.args.copies = buy.stickers; + const pdfBuffer = await models.Entry.buyLabelSupplier(ctx, myOptions); await merger.add(new Uint8Array(pdfBuffer[0])); } diff --git a/modules/entry/back/models/entry.js b/modules/entry/back/models/entry.js index 8ca79f531..55a23bb0a 100644 --- a/modules/entry/back/models/entry.js +++ b/modules/entry/back/models/entry.js @@ -1,3 +1,4 @@ +const UserError = require('vn-loopback/util/user-error'); const LoopBackContext = require('loopback-context'); module.exports = Self => { require('../methods/entry/filter')(Self); @@ -11,18 +12,28 @@ module.exports = Self => { require('../methods/entry/addFromPackaging')(Self); require('../methods/entry/addFromBuy')(Self); require('../methods/entry/buyLabel')(Self); - require('../methods/entry/print')(Self); + require('../methods/entry/labelSupplier')(Self); + require('../methods/entry/buyLabelSupplier')(Self); Self.observe('before save', async function(ctx, options) { if (ctx.isNewInstance) return; const changes = ctx.data || ctx.instance; const orgData = ctx.currentInstance; + const loopBackContext = LoopBackContext.getCurrentContext(); + const accessToken = {req: loopBackContext.active}; + const hasChanges = orgData && changes; + + const isBookedChanged = changes.isBooked !== undefined && orgData.isBooked !== changes.isBooked; + + if (isBookedChanged) { + const canEditIsBooked = await Self.app.models.ACL.checkAccessAcl(accessToken, 'Entry', 'isBooked', 'READ'); + if (!canEditIsBooked) + throw new UserError('You do not have permission to modify the booked field'); + } const observation = changes.observation || orgData.observation; - const hasChanges = orgData && changes; - const observationChanged = hasChanges - && orgData.observation != observation; + const observationChanged = hasChanges && orgData.observation != observation; if (observationChanged) { let tx; @@ -37,8 +48,7 @@ module.exports = Self => { } try { - const loopbackContext = LoopBackContext.getCurrentContext(); - const userId = loopbackContext.active.accessToken.userId; + const userId = loopBackContext.active.accessToken.userId; const id = changes.id || orgData.id; const entry = await Self.app.models.Entry.findById(id, null, myOptions); await entry.updateAttribute('observationEditorFk', userId, myOptions); diff --git a/modules/entry/back/models/specs/entry.spec.js b/modules/entry/back/models/specs/entry.spec.js new file mode 100644 index 000000000..15a8202c4 --- /dev/null +++ b/modules/entry/back/models/specs/entry.spec.js @@ -0,0 +1,97 @@ +const {models} = require('vn-loopback/server/server'); +const LoopBackContext = require('loopback-context'); + +describe('entry_isEditable trigger', () => { + const activeCtx = { + accessToken: {userId: 5}, + http: { + req: { + headers: {origin: 'http://localhost'} + } + } + }; + const ctx = {req: activeCtx}; + const entryId = 1; + let tx; + let options; + let entry; + + beforeEach(async() => { + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({active: ctx.req}); + tx = await models.Entry.beginTransaction({}); + options = {transaction: tx}; + + entry = await models.Entry.findById(entryId, null, options); + }); + + afterEach(async() => { + await tx.rollback(); + }); + + async function prepareEntry(isBooked, typeFk) { + let newCreated = Date.vnNew(); + await entry.updateAttributes({isBooked, typeFk}, options); + await entry.updateAttributes({dated: newCreated}, options); + } + + it('should throw an error when entry is booked and typeFk is null', async() => { + let error; + try { + await prepareEntry(true, null); + } catch (e) { + error = e; + } + + expect(error.message).toContain(`Entry ${entryId} is not editable`); + }); + + it('should throw an error when entry is booked and typeFk is not informal', async() => { + let error; + try { + const type = await models.EntryType.findOne({where: {isInformal: false}}, options); + await prepareEntry(true, type.code); + } catch (e) { + error = e; + } + + expect(error.message).toContain(`Entry ${entryId} is not editable`); + }); + + it('should not throw an error when entry is booked and typeFk is informal', async() => { + let error; + try { + const type = await models.EntryType.findOne({where: {isInformal: true}}, options); + await prepareEntry(true, type.code); + } catch (e) { + error = e; + } + + expect(error).toBeUndefined(); + }); + + it('should not throw an error when entry is not booked', async() => { + let error; + try { + const type = await models.EntryType.findOne({}, options); + await prepareEntry(false, type.code); + } catch (e) { + error = e; + } + + expect(error).toBeUndefined(); + }); + + it('should not throw an error when @isModeInventory is true', async() => { + let error; + try { + await models.Application.rawSql('SET @isModeInventory = TRUE;', null, options); + await prepareEntry(true, null); + } catch (e) { + error = e; + } finally { + await models.Application.rawSql('SET @isModeInventory = FALSE;', null, options); + } + + expect(error).toBeUndefined(); + }); +}); diff --git a/modules/item/back/methods/item-shelving/getListItemNewer.js b/modules/item/back/methods/item-shelving/getListItemNewer.js index 5c4ca277d..c806c0a7e 100644 --- a/modules/item/back/methods/item-shelving/getListItemNewer.js +++ b/modules/item/back/methods/item-shelving/getListItemNewer.js @@ -51,7 +51,7 @@ module.exports = Self => { JOIN vn.productionConfig pc WHERE sh.code = ? AND s.code = pc.sectorFromCode ), tItemInSector AS ( - SELECT is2.itemFk, is2.created, is2.shelvingFk + SELECT is2.itemFk, is2.created, sh.code FROM vn.itemShelving is2 JOIN vn.shelving sh ON sh.id = is2.shelvingFk JOIN vn.parking p ON p.id = sh.parkingFk @@ -59,7 +59,7 @@ module.exports = Self => { JOIN vn.productionConfig pc WHERE sh.code <> ? AND s.code = pc.sectorFromCode) - SELECT ti.itemFK, tis.shelvingFk + SELECT ti.itemFK, tis.code shelvingFk FROM tItemShelving ti JOIN tItemInSector tis ON tis.itemFk = ti.itemFk JOIN vn.productionConfig pc diff --git a/modules/item/back/model-config.json b/modules/item/back/model-config.json index dcd973524..c386a8eaa 100644 --- a/modules/item/back/model-config.json +++ b/modules/item/back/model-config.json @@ -56,9 +56,6 @@ "ItemShelving": { "dataSource": "vn" }, - "ItemShelvingLog": { - "dataSource": "vn" - }, "ItemShelvingSale": { "dataSource": "vn" }, diff --git a/modules/item/back/models/item-shelving-log.json b/modules/item/back/models/item-shelving-log.json deleted file mode 100644 index f976008f1..000000000 --- a/modules/item/back/models/item-shelving-log.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "name": "ItemShelvingLog", - "base": "VnModel", - "mixins": { - "Loggable": true - }, - "options": { - "mysql": { - "table": "itemShelvingLog" - } - }, - "properties": { - "id": { - "type": "number", - "id": true, - "description": "Identifier" - }, - "created": { - "type": "date" - }, - "shelvingFk": { - "type": "string" - }, - "itemFk": { - "type": "number" - }, - "visible": { - "type": "number" - }, - "accion": { - "type": "string" - } - }, - "relations": { - "item": { - "type": "belongsTo", - "model": "Item", - "foreignKey": "itemFk" - }, - "worker": { - "type": "belongsTo", - "model": "Worker", - "foreignKey": "workerFk" - }, - "shelving": { - "type": "belongsTo", - "model": "Shelving", - "foreignKey": "shelvingFk", - "primaryKey": "code" - } - } -} \ No newline at end of file diff --git a/modules/item/front/barcode/index.html b/modules/item/front/barcode/index.html new file mode 100644 index 000000000..8d6cb3af8 --- /dev/null +++ b/modules/item/front/barcode/index.html @@ -0,0 +1,57 @@ + + + + +
+ + + + + + + + + + + + + + + + + + + + +
diff --git a/modules/item/front/barcode/index.js b/modules/item/front/barcode/index.js new file mode 100644 index 000000000..4ceb87b9d --- /dev/null +++ b/modules/item/front/barcode/index.js @@ -0,0 +1,17 @@ +import ngModule from '../module'; +import Section from 'salix/components/section'; + +export default class Controller extends Section { + onSubmit() { + this.$.watcher.check(); + this.$.model.save().then(() => { + this.$.watcher.notifySaved(); + this.$.watcher.updateOriginalData(); + }); + } +} + +ngModule.vnComponent('vnItemBarcode', { + template: require('./index.html'), + controller: Controller +}); diff --git a/modules/item/front/basic-data/index.html b/modules/item/front/basic-data/index.html new file mode 100644 index 000000000..af76d5966 --- /dev/null +++ b/modules/item/front/basic-data/index.html @@ -0,0 +1,318 @@ + + + + + + +
+ + + + +
{{::name}}
+
+ {{::category.name}} +
+
+
+ + + + +
+ + + + + + + +
{{::name}}
+
+ #{{::id}} +
+
+ + + + +
+
+ + + +
{{::description}}
+
+ #{{::id}} +
+
+ + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ID + Item + Size + Producer + Color + + + + + + + {{::item.id}} + + + {{::item.name}} + {{::item.size}} + {{::item.producer.name}} + {{::item.ink.name}} + + + + + + + + diff --git a/modules/item/front/basic-data/index.js b/modules/item/front/basic-data/index.js new file mode 100644 index 000000000..5a303f15f --- /dev/null +++ b/modules/item/front/basic-data/index.js @@ -0,0 +1,87 @@ +import ngModule from '../module'; +import Section from 'salix/components/section'; + +class Controller extends Section { + showIntrastat(event) { + if (event.defaultPrevented) return; + event.preventDefault(); + + this.newIntrastat = { + taxClassFk: this.item.taxClassFk + }; + this.$.intrastat.show(); + } + + onIntrastatAccept() { + const query = `Items/${this.$params.id}/createIntrastat`; + return this.$http.patch(query, this.newIntrastat) + .then(res => this.item.intrastatFk = res.data.id); + } + + itemSearchFunc($search) { + return /^\d+$/.test($search) + ? {id: $search} + : {name: {like: '%' + $search + '%'}}; + } + + showFilterDialog(item) { + this.activeItem = item; + this.itemFilterParams = {}; + this.itemFilter = { + include: [ + { + relation: 'producer', + scope: { + fields: ['name'] + } + }, + { + relation: 'ink', + scope: { + fields: ['name'] + } + } + ] + }; + + this.$.filterDialog.show(); + } + + selectItem(id) { + this.activeItem['genericFk'] = id; + this.$.filterDialog.hide(); + } + + filter() { + const filter = this.itemFilter; + const params = this.itemFilterParams; + const where = {}; + for (let key in params) { + const value = params[key]; + if (!value) continue; + + switch (key) { + case 'name': + where[key] = {like: `%${value}%`}; + break; + case 'producerFk': + case 'typeFk': + case 'size': + case 'inkFk': + where[key] = value; + } + } + + filter.where = where; + + this.$.itemsModel.applyFilter(filter); + } +} + +ngModule.vnComponent('vnItemBasicData', { + template: require('./index.html'), + bindings: { + item: '<' + }, + controller: Controller +}); diff --git a/modules/item/front/basic-data/index.spec.js b/modules/item/front/basic-data/index.spec.js new file mode 100644 index 000000000..274453d30 --- /dev/null +++ b/modules/item/front/basic-data/index.spec.js @@ -0,0 +1,32 @@ +import './index.js'; + +describe('vnItemBasicData', () => { + describe('Component vnItemBasicData', () => { + let $httpBackend; + let $scope; + let controller; + + beforeEach(ngModule('item')); + + beforeEach(inject(($componentController, $rootScope, _$httpBackend_) => { + $httpBackend = _$httpBackend_; + $scope = $rootScope.$new(); + const $element = angular.element(''); + controller = $componentController('vnItemBasicData', {$element, $scope}); + controller.$.watcher = {}; + controller.$params.id = 1; + controller.item = {id: 1, name: 'Rainbow Coral'}; + })); + + describe('onIntrastatAccept()', () => { + it('should pass the data to the watcher', () => { + const newIntrastatId = 20; + $httpBackend.expect('PATCH', 'Items/1/createIntrastat').respond({id: 20}); + controller.onIntrastatAccept(); + $httpBackend.flush(); + + expect(controller.item.intrastatFk).toEqual(newIntrastatId); + }); + }); + }); +}); diff --git a/modules/item/front/basic-data/locale/es.yml b/modules/item/front/basic-data/locale/es.yml new file mode 100644 index 000000000..fc490e448 --- /dev/null +++ b/modules/item/front/basic-data/locale/es.yml @@ -0,0 +1,19 @@ +Reference: Referencia +Full name calculates based on tags 1-3. Is not recommended to change it manually: >- + El nombre completo se calcula + basado en los tags 1-3. + No se recomienda cambiarlo manualmente +Is active: Activo +Expense: Gasto +Price in kg: Precio en kg +New intrastat: Nuevo intrastat +Identifier: Identificador +Fragile: Frágil +Is shown at website, app that this item cannot travel (wreath, palms, ...): Se muestra en la web, app que este artículo no puede viajar (coronas, palmas, ...) +Multiplier: Multiplicador +Generic: Genérico +This item does need a photo: Este artículo necesita una foto +Do photo: Hacer foto +Recycled Plastic: Plástico reciclado +Non recycled plastic: Plástico no reciclado +Minimum sales quantity: Cantidad mínima de venta diff --git a/modules/item/front/botanical/index.html b/modules/item/front/botanical/index.html new file mode 100644 index 000000000..2388f4e8f --- /dev/null +++ b/modules/item/front/botanical/index.html @@ -0,0 +1,102 @@ + + +
+ + + + + + + + + + +
{{name}}
+
+ {{genus.name}} +
+
+ + + + +
+
+
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/item/front/botanical/index.js b/modules/item/front/botanical/index.js new file mode 100644 index 000000000..8ade0fd9d --- /dev/null +++ b/modules/item/front/botanical/index.js @@ -0,0 +1,99 @@ +import ngModule from '../module'; +import Section from 'salix/components/section'; +class Controller extends Section { + get item() { + return this._item; + } + + set item(value) { + this._item = value; + if (value) + this.getBotanicalData(); + } + + showGenus(event) { + if (event.defaultPrevented) return; + event.preventDefault(); + + this.$.genus.show(); + } + + showSpecies(event) { + if (event.defaultPrevented) return; + event.preventDefault(); + + this.$.species.show(); + } + + onGenusAccept() { + try { + if (!this.data.name) + throw new Error(`The name of the genus can't be empty`); + + this.$http.post(`genera`, this.data).then(res => { + this.vnApp.showMessage(this.$t('The genus has been created')); + this.emit('response', {$response: res.data}); + this.onGenusResponse(res.data); + }); + } catch (e) { + this.vnApp.showError(this.$t(e.message)); + return false; + } + return true; + } + + onSpeciesAccept() { + try { + if (!this.data.name) + throw new Error(`The name of the species can't be empty`); + + this.$http.post(`species`, this.data).then(res => { + this.vnApp.showMessage(this.$t('The species has been created')); + this.emit('response', {$response: res.data}); + this.onSpeciesResponse(res.data); + }); + } catch (e) { + this.vnApp.showError(this.$t(e.message)); + return false; + } + return true; + } + + getBotanicalData() { + const filter = { + where: {itemFk: this.item.id} + }; + const filterParams = encodeURIComponent(JSON.stringify(filter)); + this.$http.get(`ItemBotanicals?filter=${filterParams}`).then(res => { + if (res.data[0]) + this.botanical = res.data[0]; + + else + this.botanical = {itemFk: this.item.id}; + }); + } + + onSubmit() { + this.$.watcher.check(); + this.$http.patch(`ItemBotanicals`, this.botanical).then(() => { + this.$.watcher.notifySaved(); + this.$.watcher.updateOriginalData(); + }); + } + + onGenusResponse(response) { + this.botanical.genusFk = response.id; + } + + onSpeciesResponse(response) { + this.botanical.specieFk = response.id; + } +} + +ngModule.vnComponent('vnItemBotanical', { + template: require('./index.html'), + bindings: { + item: '<' + }, + controller: Controller +}); diff --git a/modules/item/front/botanical/index.spec.js b/modules/item/front/botanical/index.spec.js new file mode 100644 index 000000000..afec83cfd --- /dev/null +++ b/modules/item/front/botanical/index.spec.js @@ -0,0 +1,179 @@ +import './index.js'; + +describe('vnItemBotanical', () => { + describe('Component vnItemBotanical', () => { + let $httpBackend; + let $scope; + let controller; + let vnApp; + beforeEach(ngModule('item')); + + beforeEach(inject(($componentController, $rootScope, _$httpBackend_, _vnApp_) => { + $httpBackend = _$httpBackend_; + vnApp = _vnApp_; + jest.spyOn(vnApp, 'showError'); + $scope = $rootScope.$new(); + const $element = angular.element(''); + controller = $componentController('vnItemBotanical', {$element, $scope}); + controller.item = {id: 5}; + controller.$params = {itemFk: 5}; + controller.$ = { + watcher: { + check: () => {}, + notifySaved: () => {}, + updateOriginalData: () => {}}, + genus: { + show: () => {} + }, + species: { + show: () => {} + }}; + })); + + beforeEach(() => { + const response = {data: 'MyResult'}; + $httpBackend.whenRoute('GET', 'ItemBotanicals').respond(response); + }); + + describe('showGenus()', () => { + it('should do nothing in genus field if it default is prevented', () => { + const event = { + defaultPrevented: true, + preventDefault: () => {} + }; + jest.spyOn(event, 'preventDefault'); + jest.spyOn(controller.$.genus, 'show'); + + controller.showGenus(event); + + expect(event.preventDefault).not.toHaveBeenCalledWith(); + expect(controller.$.genus.show).not.toHaveBeenCalledWith(); + }); + + it('should call show function in genus field when the default is not prevented', () => { + const event = { + defaultPrevented: false, + preventDefault: () => {} + }; + + jest.spyOn(event, 'preventDefault'); + jest.spyOn(controller.$.genus, 'show'); + + controller.showGenus(event); + + expect(event.preventDefault).toHaveBeenCalledWith(); + expect(controller.$.genus.show).toHaveBeenCalledWith(); + }); + }); + + describe('showSpecies()', () => { + it('should do nothing in species field if it default is prevented', () => { + const event = { + defaultPrevented: true, + preventDefault: () => {} + }; + jest.spyOn(event, 'preventDefault'); + jest.spyOn(controller.$.species, 'show'); + + controller.showSpecies(event); + + expect(event.preventDefault).not.toHaveBeenCalledWith(); + expect(controller.$.species.show).not.toHaveBeenCalledWith(); + }); + + it('should call show function in species field when the default is not prevented', () => { + const event = { + defaultPrevented: false, + preventDefault: () => {} + }; + + jest.spyOn(event, 'preventDefault'); + jest.spyOn(controller.$.species, 'show'); + + controller.showSpecies(event); + + expect(event.preventDefault).toHaveBeenCalledWith(); + expect(controller.$.species.show).toHaveBeenCalledWith(); + }); + }); + + describe('onGenusAccept()', () => { + it('should throw an error if the item botanical has no genus name', () => { + jest.spyOn(controller.vnApp, 'showMessage'); + + controller.data = {}; + + controller.onGenusAccept(); + + expect(controller.vnApp.showError).toHaveBeenCalledWith(`The name of the genus can't be empty`); + }); + + it('should add the new genus', () => { + controller.data = { + id: 4, + name: 'Anilius' + }; + + $httpBackend.expectPOST('genera', controller.data).respond(200, controller.data); + + controller.onGenusAccept(); + $httpBackend.flush(); + + controller.onGenusResponse(controller.data); + + expect(controller.botanical.genusFk).toEqual(controller.data.id); + }); + }); + + describe('onSpeciesAccept()', () => { + it('should throw an error if the item botanical has no species name', () => { + jest.spyOn(controller.vnApp, 'showMessage'); + + controller.data = {}; + + controller.onSpeciesAccept(); + + expect(controller.vnApp.showError).toHaveBeenCalledWith(`The name of the species can't be empty`); + }); + + it('should add the new species', () => { + controller.data = { + id: 2, + name: 'Spasiva' + }; + + $httpBackend.expectPOST('species', controller.data).respond(200, controller.data); + + controller.onSpeciesAccept(); + $httpBackend.flush(); + controller.onSpeciesResponse(controller.data); + }); + }); + + describe('onSubmit()', () => { + it('should make HTTP POST request to save the genus and species data', () => { + jest.spyOn(controller.$.watcher, 'updateOriginalData'); + jest.spyOn(controller.$.watcher, 'check'); + jest.spyOn(controller.$.watcher, 'notifySaved'); + + $httpBackend.expectPATCH('ItemBotanicals').respond(); + controller.onSubmit(); + $httpBackend.flush(); + + expect(controller.$.watcher.updateOriginalData).toHaveBeenCalledWith(); + expect(controller.$.watcher.check).toHaveBeenCalledWith(); + expect(controller.$.watcher.notifySaved).toHaveBeenCalledWith(); + }); + }); + + describe('getBotanicalData()', () => { + it('should get the species and genus data references of the item', () => { + controller.getBotanicalData(); + $httpBackend.flush(); + + expect(controller.botanical).toEqual(controller.$params); + }); + }); + }); +}); + diff --git a/modules/item/front/botanical/locale/es.yml b/modules/item/front/botanical/locale/es.yml new file mode 100644 index 000000000..e1234bd71 --- /dev/null +++ b/modules/item/front/botanical/locale/es.yml @@ -0,0 +1,5 @@ +The genus has been created: El genus ha sido creado +The species has been created: La especie ha sido creada +Latin species name: Nombre de la especie en latín +Latin genus name: Nombre del genus en latín +Species: Especie \ No newline at end of file diff --git a/modules/item/front/card/index.html b/modules/item/front/card/index.html new file mode 100644 index 000000000..330d274c0 --- /dev/null +++ b/modules/item/front/card/index.html @@ -0,0 +1,8 @@ + + + + + diff --git a/modules/item/front/card/index.js b/modules/item/front/card/index.js new file mode 100644 index 000000000..2fe42fd04 --- /dev/null +++ b/modules/item/front/card/index.js @@ -0,0 +1,33 @@ +import ngModule from '../module'; +import ModuleCard from 'salix/components/module-card'; + +class Controller extends ModuleCard { + reload() { + this.$http.get(`Items/${this.$params.id}/getCard`) + .then(res => this.item = res.data); + + this.$http.get('ItemConfigs/findOne') + .then(res => { + if (this.$state.getCurrentPath()[4].state.name === 'item.card.diary') return; + this.warehouseFk = res.data.warehouseFk; + this.getWarehouseName(res.data.warehouseFk); + }); + } + + getWarehouseName(warehouseFk) { + const filter = { + where: {id: warehouseFk} + }; + this.$http.get('Warehouses/findOne', {filter}) + .then(res => { + this.warehouseText = this.$t('WarehouseFk', { + warehouseName: res.data.name + }); + }); + } +} + +ngModule.vnComponent('vnItemCard', { + template: require('./index.html'), + controller: Controller +}); diff --git a/modules/item/front/card/index.spec.js b/modules/item/front/card/index.spec.js new file mode 100644 index 000000000..6ebce3d36 --- /dev/null +++ b/modules/item/front/card/index.spec.js @@ -0,0 +1,32 @@ +import './index.js'; + +describe('Item', () => { + describe('Component vnItemCard', () => { + let controller; + let $httpBackend; + let $state; + let data = {id: 1, name: 'fooName'}; + + beforeEach(ngModule('item')); + + beforeEach(inject(($componentController, _$httpBackend_, $stateParams, _$state_) => { + $httpBackend = _$httpBackend_; + $state = _$state_; + $state.getCurrentPath = () => [null, null, null, null, {state: {name: 'item.card.diary'}}]; + + let $element = angular.element('
'); + controller = $componentController('vnItemCard', {$element}); + + $stateParams.id = data.id; + $httpBackend.whenRoute('GET', 'Items/:id/getCard').respond(data); + })); + + it('should request data and set it on the controller', () => { + $httpBackend.expect('GET', `ItemConfigs/findOne`).respond({}); + controller.reload(); + $httpBackend.flush(); + + expect(controller.item).toEqual(data); + }); + }); +}); diff --git a/modules/item/front/create/index.html b/modules/item/front/create/index.html new file mode 100644 index 000000000..b284abf06 --- /dev/null +++ b/modules/item/front/create/index.html @@ -0,0 +1,95 @@ + + + + +
+ + + + + + + + + + + + +
+
{{::code}}
+
{{::name}}
+
+
+ {{category.name}} +
+
+
+ + +
{{::description}}
+
+ #{{::id}} +
+
+
+
+ + + + +
+ + + + + + +
diff --git a/modules/item/front/create/index.js b/modules/item/front/create/index.js new file mode 100644 index 000000000..4ca5f8f9f --- /dev/null +++ b/modules/item/front/create/index.js @@ -0,0 +1,40 @@ +import ngModule from '../module'; +import Section from 'salix/components/section'; + +class Controller extends Section { + constructor($element, $) { + super($element, $); + this.fetchDefaultPriorityTag(); + } + + fetchDefaultPriorityTag() { + this.validPriorities = []; + const filter = {fields: ['defaultPriority', 'defaultTag', 'validPriorities'], limit: 1}; + this.$http.get(`ItemConfigs`, {filter}) + .then(res => { + if (res.data) { + const dataRow = res.data[0]; + dataRow.validPriorities.forEach(priority => { + this.validPriorities.push({priority}); + }); + this.item = { + priority: dataRow.defaultPriority, + tag: dataRow.defaultTag + }; + } + }); + } + + onSubmit() { + this.$.watcher.submit().then( + json => this.$state.go('item.card.basicData', {id: json.data.id}) + ); + } +} + +Controller.$inject = ['$element', '$scope']; + +ngModule.vnComponent('vnItemCreate', { + template: require('./index.html'), + controller: Controller +}); diff --git a/modules/item/front/create/index.spec.js b/modules/item/front/create/index.spec.js new file mode 100644 index 000000000..9e54988d7 --- /dev/null +++ b/modules/item/front/create/index.spec.js @@ -0,0 +1,37 @@ +import './index.js'; + +describe('Item', () => { + describe('Component vnItemCreate', () => { + let $scope; + let $state; + let controller; + + beforeEach(ngModule('item')); + + beforeEach(inject(($componentController, $rootScope, _$state_) => { + $scope = $rootScope.$new(); + $state = _$state_; + $scope.watcher = { + submit: () => { + return { + then: callback => { + callback({data: {id: 1}}); + } + }; + } + }; + const $element = angular.element(''); + controller = $componentController('vnItemCreate', {$element, $scope}); + })); + + describe('onSubmit()', () => { + it(`should call submit() on the watcher then expect a callback`, () => { + jest.spyOn($state, 'go'); + controller.onSubmit(); + + expect(controller.$state.go).toHaveBeenCalledWith('item.card.basicData', {id: 1}); + }); + }); + }); +}); + diff --git a/modules/item/front/create/locale/es.yml b/modules/item/front/create/locale/es.yml new file mode 100644 index 000000000..041826e1c --- /dev/null +++ b/modules/item/front/create/locale/es.yml @@ -0,0 +1 @@ +Temporal name: Nombre temporal \ No newline at end of file diff --git a/modules/item/front/diary/index.html b/modules/item/front/diary/index.html new file mode 100644 index 000000000..7fb3b870e --- /dev/null +++ b/modules/item/front/diary/index.html @@ -0,0 +1,2 @@ + + diff --git a/modules/item/front/diary/index.js b/modules/item/front/diary/index.js new file mode 100644 index 000000000..3d86b0b60 --- /dev/null +++ b/modules/item/front/diary/index.js @@ -0,0 +1,21 @@ +import ngModule from '../module'; +import Section from 'salix/components/section'; + +class Controller extends Section { + constructor($element, $) { + super($element, $); + } + + async $onInit() { + this.$state.go('item.card.summary', {id: this.$params.id}); + window.location.href = await this.vnApp.getUrl(`item/${this.$params.id}/diary`); + } +} + +ngModule.vnComponent('vnItemDiary', { + template: require('./index.html'), + controller: Controller, + bindings: { + item: '<' + } +}); diff --git a/modules/item/front/fetched-tags/index.html b/modules/item/front/fetched-tags/index.html new file mode 100644 index 000000000..df5936871 --- /dev/null +++ b/modules/item/front/fetched-tags/index.html @@ -0,0 +1,40 @@ + + +
+ {{::$ctrl.item.value5}} +
+
+ {{::$ctrl.item.value6}} +
+
+ {{::$ctrl.item.value7}} +
+
+ {{::$ctrl.item.value8}} +
+
+ {{::$ctrl.item.value9}} +
+
+ {{::$ctrl.item.value10}} +
+
+
diff --git a/modules/item/front/fetched-tags/index.js b/modules/item/front/fetched-tags/index.js new file mode 100644 index 000000000..e3584be23 --- /dev/null +++ b/modules/item/front/fetched-tags/index.js @@ -0,0 +1,12 @@ +import ngModule from '../module'; +import Component from 'core/lib/component'; +import './style.scss'; + +ngModule.vnComponent('vnFetchedTags', { + template: require('./index.html'), + controller: Component, + bindings: { + maxLength: '<', + item: '<', + } +}); diff --git a/modules/item/front/fetched-tags/style.scss b/modules/item/front/fetched-tags/style.scss new file mode 100644 index 000000000..250ca07ab --- /dev/null +++ b/modules/item/front/fetched-tags/style.scss @@ -0,0 +1,61 @@ +@import "variables"; + +[vn-fetched-tags] { + min-width: 155px; + & [wide] { + width: 430px; + } + & div { + display: flex; + flex-wrap: wrap; + align-items: center; + & vn-one { + min-width: 200px; + overflow: hidden; + text-overflow: ellipsis; + font-size: 1rem; + } + & vn-one h3 { + color: $color-font-secondary; + text-transform: uppercase; + line-height: initial; + font-size: 0.75rem; + margin-bottom: 0px; + } + } +} + +vn-fetched-tags { + & > vn-horizontal { + align-items: center; + max-width: 210px; + & > vn-auto { + flex-wrap: wrap; + + & > .inline-tag { + margin: 1px; + } + } + + & > vn-auto { + display: flex; + + & > .inline-tag { + color: $color-font-secondary; + text-align: center; + font-size: .8rem; + height: 13px; + padding: 1px; + width: 64px; + min-width: 64px; + max-width: 64px; + flex: 1; + border: 1px solid $color-font-secondary; + + &.empty { + border: 1px solid darken($color-font-secondary, 30%); + } + } + } + } +} diff --git a/modules/item/front/fixed-price-search-panel/index.html b/modules/item/front/fixed-price-search-panel/index.html new file mode 100644 index 000000000..347e65571 --- /dev/null +++ b/modules/item/front/fixed-price-search-panel/index.html @@ -0,0 +1,214 @@ + + + + + + + + + + + + + + + + + + +
{{name}}
+
+ {{category.name}} +
+
+
+
+ + + + + + + + + + + + + + + + + + + + Tags + + + + + + + + + + + + + +
+ + Id/{{$ctrl.$t('Name')}}: {{$ctrl.filter.search}} + + + {{$ctrl.$t('Category')}}: {{category.selection.name}} + + + {{$ctrl.$t('Type')}}: {{type.selection.name}} + + + {{$ctrl.$t('Buyer')}}: {{buyer.selection.nickname}} + + + {{$ctrl.$t('Warehouse')}}: {{warehouse.selection.name}} + + + {{$ctrl.$t('Started')}}: {{$ctrl.filter.started | date:'dd/MM/yyyy'}} + + + {{$ctrl.$t('Ended')}}: {{$ctrl.filter.ended | date:'dd/MM/yyyy'}} + + + {{$ctrl.$t('For me')}}: {{$ctrl.filter.mine ? '✓' : '✗'}} + + + {{$ctrl.$t('Minimum price')}}: {{$ctrl.filter.hasMinPrice ? '✓' : '✗'}} + + + {{$ctrl.showTagInfo(chipTag)}} + +
+
diff --git a/modules/item/front/fixed-price-search-panel/index.js b/modules/item/front/fixed-price-search-panel/index.js new file mode 100644 index 000000000..0882eb5ac --- /dev/null +++ b/modules/item/front/fixed-price-search-panel/index.js @@ -0,0 +1,60 @@ +import ngModule from '../module'; +import SearchPanel from 'core/components/searchbar/search-panel'; +import './style.scss'; + +class Controller extends SearchPanel { + constructor($element, $) { + super($element, $); + } + + $onInit() { + this.filter = { + tags: [] + }; + } + + changeCategory(id) { + if (this.filter.categoryFk != id) { + this.filter.categoryFk = id; + this.addFilters(); + } + } + + removeItemFilter(param) { + this.filter[param] = null; + if (param == 'categoryFk') this.filter['typeFk'] = null; + this.addFilters(); + } + + removeTag(tag) { + const index = this.filter.tags.indexOf(tag); + if (index > -1) this.filter.tags.splice(index, 1); + this.addFilters(); + } + + onKeyPress($event) { + if ($event.key === 'Enter') + this.addFilters(); + } + + addFilters() { + for (let i = 0; i < this.filter.tags.length; i++) { + if (!this.filter.tags[i].value) + this.filter.tags.splice(i, 1); + } + return this.model.addFilter({}, this.filter); + } + + showTagInfo(itemTag) { + if (!itemTag.tagFk) return itemTag.value; + return `${this.tags.find(tag => tag.id == itemTag.tagFk).name}: ${itemTag.value}`; + } +} + +ngModule.vnComponent('vnFixedPriceSearchPanel', { + template: require('./index.html'), + controller: Controller, + bindings: { + model: '<' + } +}); diff --git a/modules/item/front/fixed-price-search-panel/index.spec.js b/modules/item/front/fixed-price-search-panel/index.spec.js new file mode 100644 index 000000000..597bc108e --- /dev/null +++ b/modules/item/front/fixed-price-search-panel/index.spec.js @@ -0,0 +1,56 @@ +import './index.js'; + +describe('Item', () => { + describe('Component vnFixedPriceSearchPanel', () => { + let $element; + let controller; + + beforeEach(ngModule('item')); + + beforeEach(angular.mock.inject($componentController => { + $element = angular.element(``); + controller = $componentController('vnFixedPriceSearchPanel', {$element}); + controller.model = {addFilter: () => {}}; + })); + + describe('removeItemFilter()', () => { + it(`should remove param from filter`, () => { + controller.filter = {tags: [], categoryFk: 1, typeFk: 1}; + const expectFilter = {tags: [], categoryFk: null, typeFk: null}; + + controller.removeItemFilter('categoryFk'); + + expect(controller.filter).toEqual(expectFilter); + }); + }); + + describe('removeTag()', () => { + it(`should remove tag from filter`, () => { + const tag = {tagFk: 1, value: 'Value'}; + controller.filter = {tags: [tag]}; + const expectFilter = {tags: []}; + + controller.removeTag(tag); + + expect(controller.filter).toEqual(expectFilter); + }); + }); + + describe('showTagInfo()', () => { + it(`should show tag value`, () => { + const tag = {value: 'Value'}; + const result = controller.showTagInfo(tag); + + expect(result).toEqual('Value'); + }); + + it(`should show tag name and value`, () => { + const tag = {tagFk: 1, value: 'Value'}; + controller.tags = [{id: 1, name: 'tagName'}]; + const result = controller.showTagInfo(tag); + + expect(result).toEqual('tagName: Value'); + }); + }); + }); +}); diff --git a/modules/item/front/fixed-price-search-panel/locale/es.yml b/modules/item/front/fixed-price-search-panel/locale/es.yml new file mode 100644 index 000000000..06e5e6b26 --- /dev/null +++ b/modules/item/front/fixed-price-search-panel/locale/es.yml @@ -0,0 +1,4 @@ +Started: Inicio +Ended: Fin +Minimum price: Precio mínimo +Item ID: ID Artículo \ No newline at end of file diff --git a/modules/item/front/fixed-price-search-panel/style.scss b/modules/item/front/fixed-price-search-panel/style.scss new file mode 100644 index 000000000..e386033dd --- /dev/null +++ b/modules/item/front/fixed-price-search-panel/style.scss @@ -0,0 +1,71 @@ +@import "variables"; + +vn-fixed-price-search-panel vn-side-menu { + .menu { + min-width: $menu-width; + } + & > div { + .input { + padding-left: $spacing-md; + padding-right: $spacing-md; + border-color: $color-spacer; + border-bottom: $border-thin; + } + .horizontal { + padding-left: $spacing-md; + padding-right: $spacing-md; + grid-auto-flow: column; + grid-column-gap: $spacing-sm; + align-items: center; + } + .tags { + padding: $spacing-md; + padding-bottom: 0%; + padding-top: 0%; + align-items: center; + } + .chips { + display: flex; + flex-wrap: wrap; + padding: $spacing-md; + overflow: hidden; + max-width: 100%; + border-color: $color-spacer; + border-top: $border-thin; + } + .item-category { + padding: $spacing-sm; + justify-content: flex-start; + align-items: flex-start; + flex-wrap: wrap; + + vn-autocomplete[vn-id="category"] { + display: none; + } + + & > vn-one { + padding: $spacing-sm; + min-width: 33.33%; + text-align: center; + box-sizing: border-box; + + & > vn-icon { + padding: $spacing-sm; + background-color: $color-font-secondary; + border-radius: 50%; + cursor: pointer; + + &.active { + background-color: $color-main; + color: #fff; + } + & > i:before { + font-size: 2.6rem; + width: 16px; + height: 16px; + } + } + } + } + } +} diff --git a/modules/item/front/fixed-price/index.html b/modules/item/front/fixed-price/index.html new file mode 100644 index 000000000..f1f6e1419 --- /dev/null +++ b/modules/item/front/fixed-price/index.html @@ -0,0 +1,284 @@ + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Item ID + + Description + + Grouping price + + Packing price + + Min price + + Started + + Ended + + Warehouse +
+ + + + + +
{{id}}
+
+ {{name}} +
+
+
+
+
+ + {{itemFk.selection.name}} + + +

{{price.subName}}

+
+
+ + +
+ + + {{price.rate2 | currency: 'EUR':2}} + + + + + + + + + + {{price.rate3 | currency: 'EUR':2}} + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+
+
+
+
+ +
+ + + + +
+ + + Edit + + {{::$ctrl.totalChecked}} + + buy(s) + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/item/front/fixed-price/index.js b/modules/item/front/fixed-price/index.js new file mode 100644 index 000000000..fe6788e9c --- /dev/null +++ b/modules/item/front/fixed-price/index.js @@ -0,0 +1,254 @@ +import ngModule from '../module'; +import Section from 'salix/components/section'; +import './style.scss'; + +export default class Controller extends Section { + constructor($element, $) { + super($element, $); + this.editedColumn; + this.checkAll = false; + this.checkedFixedPrices = []; + + this.smartTableOptions = { + activeButtons: { + search: true + }, + columns: [ + { + field: 'warehouseFk', + autocomplete: { + url: 'Warehouses', + showField: 'name', + valueField: 'id', + } + }, + { + field: 'started', + searchable: false + }, + { + field: 'ended', + searchable: false + } + ] + }; + + this.filterParams = { + warehouseFk: this.vnConfig.warehouseFk + }; + } + + getFilterParams() { + return { + warehouseFk: this.vnConfig.warehouseFk + }; + } + + get columns() { + if (this._columns) return this._columns; + + this._columns = [ + {field: 'rate2', displayName: this.$t('Grouping price')}, + {field: 'rate3', displayName: this.$t('Packing price')}, + {field: 'hasMinPrice', displayName: this.$t('Has min price')}, + {field: 'minPrice', displayName: this.$t('Min price')}, + {field: 'started', displayName: this.$t('Started')}, + {field: 'ended', displayName: this.$t('Ended')}, + {field: 'warehouseFk', displayName: this.$t('Warehouse')} + ]; + + return this._columns; + } + + get checked() { + const fixedPrices = this.$.model.data || []; + const checkedBuys = []; + for (let fixedPrice of fixedPrices) { + if (fixedPrice.checked) + checkedBuys.push(fixedPrice); + } + + return checkedBuys; + } + + uncheck() { + this.checkAll = false; + this.checkedFixedPrices = []; + } + + get totalChecked() { + if (this.checkedDummyCount) + return this.checkedDummyCount; + + return this.checked.length; + } + + saveChecked(fixedPriceId) { + const index = this.checkedFixedPrices.indexOf(fixedPriceId); + if (index !== -1) + return this.checkedFixedPrices.splice(index, 1); + return this.checkedFixedPrices.push(fixedPriceId); + } + + reCheck() { + if (!this.$.model.data) return; + if (!this.checkedFixedPrices.length) return; + + this.$.model.data.forEach(fixedPrice => { + if (this.checkedFixedPrices.includes(fixedPrice.id)) + fixedPrice.checked = true; + }); + } + + onEditAccept() { + const rowsToEdit = []; + for (let row of this.checked) + rowsToEdit.push({id: row.id, itemFk: row.itemFk}); + + const data = { + field: this.editedColumn.field, + newValue: this.editedColumn.newValue, + lines: rowsToEdit + }; + + if (this.checkedDummyCount && this.checkedDummyCount > 0) { + const params = {}; + if (this.$.model.userParams) { + const userParams = this.$.model.userParams; + for (let param in userParams) { + let newParam = this.exprBuilder(param, userParams[param]); + if (!newParam) + newParam = {[param]: userParams[param]}; + Object.assign(params, newParam); + } + } + if (this.$.model.userFilter) + Object.assign(params, this.$.model.userFilter.where); + + data.filter = params; + } + + return this.$http.post('FixedPrices/editFixedPrice', data) + .then(() => { + this.uncheck(); + this.$.model.refresh(); + }); + } + + isBigger(date) { + let today = Date.vnNew(); + today.setHours(0, 0, 0, 0); + + date = new Date(date); + date.setHours(0, 0, 0, 0); + + const timeDifference = today - date; + if (timeDifference < 0) return 'warning'; + } + + isLower(date) { + let today = Date.vnNew(); + today.setHours(0, 0, 0, 0); + + date = new Date(date); + date.setHours(0, 0, 0, 0); + + const timeDifference = today - date; + if (timeDifference > 0) return 'warning'; + } + + add() { + if (!this.$.model.data || this.$.model.data.length == 0) { + this.$.model.data = []; + this.$.model.proxiedData = []; + + const today = Date.vnNew(); + + const millisecsInDay = 86400000; + const daysInWeek = 7; + const nextWeek = new Date(today.getTime() + daysInWeek * millisecsInDay); + + this.$.model.insert({ + started: today, + ended: nextWeek + }); + return; + } + + const lastIndex = this.$.model.data.length - 1; + const lastItem = this.$.model.data[lastIndex]; + this.$.model.insert({ + itemFk: lastItem.itemFk, + name: lastItem.name, + subName: lastItem.subName, + value5: lastItem.value5, + value6: lastItem.value6, + value7: lastItem.value7, + value8: lastItem.value8, + value9: lastItem.value9, + value10: lastItem.value10, + warehouseFk: lastItem.warehouseFk, + rate2: lastItem.rate2, + rate3: lastItem.rate3, + hasMinPrice: lastItem.hasMinPrice, + minPrice: lastItem.minPrice, + started: lastItem.started, + ended: lastItem.ended, + }); + } + + upsertPrice(price, resetMinPrice) { + if (resetMinPrice) + delete price['minPrice']; + + const requiredFields = ['itemFk', 'started', 'ended', 'rate2', 'rate3']; + for (const field of requiredFields) + if (price[field] == undefined) return; + + const query = 'FixedPrices/upsertFixedPrice'; + this.$http.patch(query, price) + .then(res => { + this.vnApp.showSuccess(this.$t('Data saved!')); + Object.assign(price, res.data); + }); + } + + removePrice($index) { + const price = this.$.model.data[$index]; + if (price.id) { + this.$http.delete(`FixedPrices/${price.id}`) + .then(() => { + this.$.model.remove($index); + this.vnApp.showSuccess(this.$t('Data saved!')); + }); + } else + this.$.model.remove($index); + } + + itemSearchFunc($search) { + return /^\d+$/.test($search) + ? {id: $search} + : {name: {like: '%' + $search + '%'}}; + } + + exprBuilder(param, value) { + switch (param) { + case 'name': + return {'i.name': {like: `%${value}%`}}; + case 'itemFk': + case 'warehouseFk': + case 'rate2': + case 'rate3': + param = `fp.${param}`; + return {[param]: value}; + case 'minPrice': + param = `i.${param}`; + return {[param]: value}; + } + } +} + +ngModule.vnComponent('vnFixedPrice', { + template: require('./index.html'), + controller: Controller +}); diff --git a/modules/item/front/fixed-price/index.spec.js b/modules/item/front/fixed-price/index.spec.js new file mode 100644 index 000000000..ae24da60b --- /dev/null +++ b/modules/item/front/fixed-price/index.spec.js @@ -0,0 +1,173 @@ +import './index'; + +describe('fixed price', () => { + describe('Component vnFixedPrice', () => { + let controller; + let $httpBackend; + + beforeEach(ngModule('item')); + + beforeEach(inject(($componentController, _$httpBackend_, $rootScope) => { + $httpBackend = _$httpBackend_; + const $scope = $rootScope.$new(); + const $element = angular.element(''); + controller = $componentController('vnFixedPrice', {$element, $scope}); + controller.$ = { + model: {refresh: () => {}}, + edit: {hide: () => {}} + }; + })); + + describe('get columns', () => { + it(`should return a set of columns`, () => { + let result = controller.columns; + + let length = result.length; + let anyColumn = Object.keys(result[Math.floor(Math.random() * Math.floor(length))]); + + expect(anyColumn).toContain('field', 'displayName'); + }); + }); + + describe('get checked', () => { + it(`should return a set of checked lines`, () => { + controller.$.model.data = [ + {checked: true, id: 1}, + {checked: true, id: 2}, + {checked: true, id: 3}, + {checked: false, id: 4}, + ]; + + let result = controller.checked; + + expect(result.length).toEqual(3); + }); + }); + + describe('reCheck()', () => { + it(`should recheck buys`, () => { + controller.$.model.data = [ + {checked: false, id: 1}, + {checked: false, id: 2}, + {checked: false, id: 3}, + {checked: false, id: 4}, + ]; + controller.checkedFixedPrices = [1, 2]; + + controller.reCheck(); + + expect(controller.$.model.data[0].checked).toEqual(true); + expect(controller.$.model.data[1].checked).toEqual(true); + expect(controller.$.model.data[2].checked).toEqual(false); + expect(controller.$.model.data[3].checked).toEqual(false); + }); + }); + + describe('saveChecked()', () => { + it(`should check buy`, () => { + const buyCheck = 3; + controller.checkedFixedPrices = [1, 2]; + + controller.saveChecked(buyCheck); + + expect(controller.checkedFixedPrices[2]).toEqual(buyCheck); + }); + + it(`should uncheck buy`, () => { + const buyUncheck = 3; + controller.checkedFixedPrices = [1, 2, 3]; + + controller.saveChecked(buyUncheck); + + expect(controller.checkedFixedPrices[2]).toEqual(undefined); + }); + }); + + describe('onEditAccept()', () => { + it(`should perform a query to update columns`, () => { + controller.editedColumn = {field: 'my field', newValue: 'the new value'}; + const query = 'FixedPrices/editFixedPrice'; + + $httpBackend.expectPOST(query).respond(); + controller.onEditAccept(); + $httpBackend.flush(); + + const result = controller.checked; + + expect(result.length).toEqual(0); + }); + }); + + describe('upsertPrice()', () => { + it('should do nothing if one or more required arguments are missing', () => { + jest.spyOn(controller.vnApp, 'showSuccess'); + + controller.upsertPrice({}); + + expect(controller.vnApp.showSuccess).not.toHaveBeenCalled(); + }); + + it('should perform an http request to update the price', () => { + const now = Date.vnNew(); + jest.spyOn(controller.vnApp, 'showSuccess'); + + $httpBackend.expectPATCH('FixedPrices/upsertFixedPrice').respond(); + controller.upsertPrice({ + itemFk: 1, + started: now, + ended: now, + rate2: 1, + rate3: 2 + }); + $httpBackend.flush(); + + expect(controller.vnApp.showSuccess).toHaveBeenCalled(); + }); + }); + + describe('removePrice()', () => { + it(`should only remove the created instance by the model as it doesn't have an ID yet`, () => { + const $index = 0; + controller.$ = { + model: { + remove: () => {}, + data: [{ + foo: 'bar' + }] + } + }; + jest.spyOn(controller.vnApp, 'showSuccess'); + jest.spyOn(controller.$.model, 'remove'); + + $httpBackend.expectGET('Warehouses').respond(); + + controller.removePrice($index); + + expect(controller.vnApp.showSuccess).not.toHaveBeenCalled(); + expect(controller.$.model.remove).toHaveBeenCalled(); + }); + + it('should remove the instance performing an delete http request', () => { + const $index = 0; + controller.$ = { + model: { + remove: () => {}, + data: [{ + id: '1' + }] + } + }; + jest.spyOn(controller.vnApp, 'showSuccess'); + jest.spyOn(controller.$.model, 'remove'); + + const query = `FixedPrices/${controller.$.model.data[0].id}`; + $httpBackend.expectDELETE(query).respond(); + controller.removePrice($index); + $httpBackend.flush(); + + expect(controller.vnApp.showSuccess).toHaveBeenCalled(); + expect(controller.$.model.remove).toHaveBeenCalled(); + }); + }); + }); +}); diff --git a/modules/item/front/fixed-price/locale/es.yml b/modules/item/front/fixed-price/locale/es.yml new file mode 100644 index 000000000..6dacf96c9 --- /dev/null +++ b/modules/item/front/fixed-price/locale/es.yml @@ -0,0 +1,7 @@ +Fixed prices: Precios fijados +Search prices by item ID or code: Buscar por ID de artículo o código +Search fixed prices: Buscar precios fijados +Add fixed price: Añadir precio fijado +This row will be removed: Esta linea se eliminará +Edit fixed price(s): Editar precio(s) fijado(s) +Has min price: Tiene precio mínimo diff --git a/modules/item/front/fixed-price/style.scss b/modules/item/front/fixed-price/style.scss new file mode 100644 index 000000000..f70ec2f50 --- /dev/null +++ b/modules/item/front/fixed-price/style.scss @@ -0,0 +1,46 @@ +@import "variables"; +vn-fixed-price{ + smart-table table{ + [shrink-field]{ + width: 90px; + max-width: 90px; + } + [shrink-field-expand]{ + width: 150px; + max-width: 150px; + } + } + + .minPrice { + align-items: center; + text-align: center; + vn-input-number { + width: 75px; + max-width: 75px; + } + } + + smart-table table tbody > * > td .chip { + padding: 0px; + } + + smart-table table tbody > * > td{ + padding: 0px; + padding-left: 5px; + padding-right: 5px; + } + + smart-table table tbody > * > td .chip.warning { + color: $color-font-bg + } + + .vn-field > .container > .infix > .control > input { + color: inherit; + } + + vn-input-number.inactive{ + input { + color: $color-font-light !important; + } + } +} diff --git a/modules/item/front/index.js b/modules/item/front/index.js index fb1aacd39..354477d4d 100644 --- a/modules/item/front/index.js +++ b/modules/item/front/index.js @@ -1,6 +1,27 @@ export * from './module'; import './main'; +import './index/'; +import './search-panel'; +import './diary'; +import './create'; +import './card'; import './descriptor'; import './descriptor-popover'; +import './basic-data'; +import './fetched-tags'; +import './tags'; +import './tax'; +import './log'; +import './request'; +import './request-search-panel'; +import './last-entries'; +import './botanical'; +import './barcode'; +import './summary'; +import './waste/index/'; +import './fixed-price'; +import './fixed-price-search-panel'; +import './item-type'; +import './item-shelving'; diff --git a/modules/item/front/index/index.html b/modules/item/front/index/index.html new file mode 100644 index 000000000..6f5cce7c0 --- /dev/null +++ b/modules/item/front/index/index.html @@ -0,0 +1,197 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Identifier + + Grouping + + Packing + + Description + + Stems + + Size + + Type + + Category + + Intrastat + + Origin + + Buyer + + Weight/Piece + + Multiplier + + Active + + Producer + + Landed +
+ + + + {{::item.id}} + + {{::item.grouping | dashIfEmpty}}{{::item.packing | dashIfEmpty}} +
+ {{::item.name}} + +

{{::item.subName}}

+
+
+ + +
{{::item.stems}}{{::item.size}} + {{::item.typeName}} + + {{::item.category}} + + {{::item.intrastat}} + {{::item.origin}} + + {{::item.userName}} + + {{::item.weightByPiece}}{{::item.stemMultiplier}} + + + {{::item.producer | dashIfEmpty}}{{::item.landed | date:'dd/MM/yyyy'}} + + + + + + +
+
+
+
+ + + + + + + + + + + + + + + + + Filter by selection + + + Exclude selection + + + Remove filter + + + Remove all filters + + + \ No newline at end of file diff --git a/modules/item/front/index/index.js b/modules/item/front/index/index.js new file mode 100644 index 000000000..2bcc2302a --- /dev/null +++ b/modules/item/front/index/index.js @@ -0,0 +1,112 @@ +import ngModule from '../module'; +import Section from 'salix/components/section'; +import './style.scss'; + +class Controller extends Section { + constructor($element, $) { + super($element, $); + + this.smartTableOptions = { + activeButtons: { + search: true, + shownColumns: true, + }, + columns: [ + { + field: 'category', + autocomplete: { + url: 'ItemCategories', + valueField: 'name', + } + }, + { + field: 'origin', + autocomplete: { + url: 'Origins', + showField: 'code', + valueField: 'code' + } + }, + { + field: 'typeFk', + autocomplete: { + url: 'ItemTypes', + } + }, + { + field: 'intrastat', + autocomplete: { + url: 'Intrastats', + showField: 'description', + valueField: 'description' + } + }, + { + field: 'buyerFk', + autocomplete: { + url: 'TicketRequests/getItemTypeWorker', + searchFunction: '{firstName: $search}', + showField: 'nickname', + valueField: 'id', + } + }, + { + field: 'active', + searchable: false + }, + { + field: 'landed', + searchable: false + }, + ] + }; + } + + exprBuilder(param, value) { + switch (param) { + case 'category': + return {'ic.name': value}; + case 'buyerFk': + return {'it.workerFk': value}; + case 'grouping': + return {'b.grouping': value}; + case 'packing': + return {'b.packing': value}; + case 'origin': + return {'ori.code': value}; + case 'typeFk': + return {'i.typeFk': value}; + case 'intrastat': + return {'intr.description': value}; + case 'name': + return {'i.name': {like: `%${value}%`}}; + case 'producer': + return {'pr.name': {like: `%${value}%`}}; + case 'id': + case 'size': + case 'subname': + case 'isActive': + case 'weightByPiece': + case 'stemMultiplier': + case 'stems': + return {[`i.${param}`]: value}; + } + } + + onCloneAccept(itemFk) { + return this.$http.post(`Items/${itemFk}/clone`) + .then(res => { + this.$state.go('item.card.tags', {id: res.data.id}); + }); + } + + preview(item) { + this.itemSelected = item; + this.$.preview.show(); + } +} + +ngModule.vnComponent('vnItemIndex', { + template: require('./index.html'), + controller: Controller +}); diff --git a/modules/item/front/index/index.spec.js b/modules/item/front/index/index.spec.js new file mode 100644 index 000000000..18abde581 --- /dev/null +++ b/modules/item/front/index/index.spec.js @@ -0,0 +1,30 @@ +import './index.js'; + +describe('Item', () => { + describe('Component vnItemIndex', () => { + let controller; + let $httpBackend; + let $scope; + + beforeEach(ngModule('item')); + + beforeEach(inject(($componentController, _$httpBackend_, $rootScope) => { + $httpBackend = _$httpBackend_; + $scope = $rootScope.$new(); + const $element = angular.element(''); + controller = $componentController('vnItemIndex', {$element, $scope}); + })); + + describe('onCloneAccept()', () => { + it('should perform a post query and then call go() then update itemSelected in the controller', () => { + jest.spyOn(controller.$state, 'go'); + + $httpBackend.expectRoute('POST', `Items/:id/clone`).respond({id: 99}); + controller.onCloneAccept(1); + $httpBackend.flush(); + + expect(controller.$state.go).toHaveBeenCalledWith('item.card.tags', {id: 99}); + }); + }); + }); +}); diff --git a/modules/item/front/index/locale/es.yml b/modules/item/front/index/locale/es.yml new file mode 100644 index 000000000..0d72edd28 --- /dev/null +++ b/modules/item/front/index/locale/es.yml @@ -0,0 +1,2 @@ +picture: Foto +Buy requests: Peticiones de compra \ No newline at end of file diff --git a/modules/item/front/index/preview.svg b/modules/item/front/index/preview.svg new file mode 100644 index 000000000..5d56b5f34 --- /dev/null +++ b/modules/item/front/index/preview.svg @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/modules/item/front/index/style.scss b/modules/item/front/index/style.scss new file mode 100644 index 000000000..e9fd9f935 --- /dev/null +++ b/modules/item/front/index/style.scss @@ -0,0 +1,34 @@ +@import "variables"; + +vn-item-product { + display: block; + + .id { + background-color: $color-main; + color: $color-font-dark; + margin-bottom: 0; + } + .image { + height: 112px; + width: 112px; + + & > img { + max-height: 100%; + max-width: 100%; + border-radius: 3px; + } + } + vn-label-value:first-of-type section{ + margin-top: 9px; + } +} + +vn-item-index { + table { + img { + border-radius: 50%; + width: 50px; + height: 50px; + } + } +} \ No newline at end of file diff --git a/modules/item/front/item-shelving/index.html b/modules/item/front/item-shelving/index.html new file mode 100644 index 000000000..fa7a70544 --- /dev/null +++ b/modules/item/front/item-shelving/index.html @@ -0,0 +1,118 @@ + + + + + +
+
+
Total
+ + +
+
+
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Created + + Item + + Concept + + Parking + + Shelving + + Etiqueta + + Packing +
+ + + {{::itemShelvingPlacementSupplyStock.created | date: 'dd/MM/yyyy'}} + {{::itemShelvingPlacementSupplyStock.itemFk}} + + + {{itemShelvingPlacementSupplyStock.longName}} + + + {{::itemShelvingPlacementSupplyStock.parking}} + + {{::itemShelvingPlacementSupplyStock.shelving}} + + {{(itemShelvingPlacementSupplyStock.stock / itemShelvingPlacementSupplyStock.packing).toFixed(2)}} + + {{::itemShelvingPlacementSupplyStock.packing}} +
+
+
+
+ + + + + \ No newline at end of file diff --git a/modules/item/front/item-shelving/index.js b/modules/item/front/item-shelving/index.js new file mode 100644 index 000000000..b8584039b --- /dev/null +++ b/modules/item/front/item-shelving/index.js @@ -0,0 +1,89 @@ +import ngModule from '../module'; +import Section from 'salix/components/section'; + +export default class Controller extends Section { + constructor($element, $) { + super($element, $); + + this.smartTableOptions = { + activeButtons: { + search: true + }, + columns: [ + { + field: 'parking', + autocomplete: { + url: 'Parkings', + showField: 'code', + valueField: 'code' + } + }, + { + field: 'shelving', + autocomplete: { + url: 'Shelvings', + showField: 'code', + valueField: 'code' + } + }, + { + field: 'created', + searchable: false + }, + { + field: 'itemFk', + searchable: false + }, + { + field: 'longName', + searchable: false + } + ] + }; + } + + get checked() { + const itemShelvings = this.$.model.data || []; + const checkedLines = []; + for (let itemShelving of itemShelvings) { + if (itemShelving.checked) + checkedLines.push(itemShelving.itemShelvingFk); + } + + return checkedLines; + } + + calculateTotals() { + this.labelTotal = 0; + const itemShelvings = this.$.model.data || []; + itemShelvings.forEach(itemShelving => { + const label = itemShelving.stock / itemShelving.packing; + this.labelTotal += label; + }); + } + + onRemove() { + const params = {itemShelvingIds: this.checked}; + const query = `ItemShelvings/deleteItemShelvings`; + this.$http.post(query, params) + .then(() => { + this.vnApp.showSuccess(this.$t('ItemShelvings removed')); + this.$.model.refresh(); + }); + } + + exprBuilder(param, value) { + switch (param) { + case 'parking': + case 'shelving': + case 'label': + case 'packing': + return {[param]: value}; + } + } +} + +ngModule.vnComponent('vnItemShelving', { + template: require('./index.html'), + controller: Controller +}); diff --git a/modules/item/front/item-shelving/index.spec.js b/modules/item/front/item-shelving/index.spec.js new file mode 100644 index 000000000..55df1c27d --- /dev/null +++ b/modules/item/front/item-shelving/index.spec.js @@ -0,0 +1,81 @@ +import './index'; +import crudModel from 'core/mocks/crud-model'; + +describe('item shelving', () => { + describe('Component vnItemShelving', () => { + let controller; + let $httpBackend; + + beforeEach(ngModule('item')); + + beforeEach(inject(($componentController, _$httpBackend_) => { + $httpBackend = _$httpBackend_; + const $element = angular.element(''); + controller = $componentController('vnItemShelving', {$element}); + controller.$.model = crudModel; + controller.$.model.data = [ + {itemShelvingFk: 1, packing: 10, stock: 1}, + {itemShelvingFk: 2, packing: 12, stock: 5}, + {itemShelvingFk: 4, packing: 20, stock: 10} + ]; + const modelData = controller.$.model.data; + modelData[0].checked = true; + modelData[1].checked = true; + })); + + describe('checked() getter', () => { + it('should return a the selected rows', () => { + const result = controller.checked; + + expect(result).toEqual(expect.arrayContaining([1, 2])); + }); + }); + + describe('calculateTotals()', () => { + it('should calculate the total of labels', () => { + controller.calculateTotals(); + + expect(controller.labelTotal).toEqual(1.0166666666666666); + }); + }); + + describe('onRemove()', () => { + it('shoud remove the selected lines', () => { + jest.spyOn(controller.$.model, 'refresh'); + const expectedParams = {itemShelvingIds: [1, 2]}; + + $httpBackend.expectPOST('ItemShelvings/deleteItemShelvings', expectedParams).respond(200); + controller.onRemove(); + $httpBackend.flush(); + + expect(controller.$.model.refresh).toHaveBeenCalled(); + }); + }); + + describe('exprBuilder()', () => { + it('should search by parking', () => { + const expr = controller.exprBuilder('parking', '700-01'); + + expect(expr).toEqual({'parking': '700-01'}); + }); + + it('should search by shelving', () => { + const expr = controller.exprBuilder('shelving', 'AAA'); + + expect(expr).toEqual({'shelving': 'AAA'}); + }); + + it('should search by label', () => { + const expr = controller.exprBuilder('label', 0.17); + + expect(expr).toEqual({'label': 0.17}); + }); + + it('should search by packing', () => { + const expr = controller.exprBuilder('packing', 10); + + expect(expr).toEqual({'packing': 10}); + }); + }); + }); +}); diff --git a/modules/item/front/item-shelving/locale/es.yml b/modules/item/front/item-shelving/locale/es.yml new file mode 100644 index 000000000..006363cfa --- /dev/null +++ b/modules/item/front/item-shelving/locale/es.yml @@ -0,0 +1,5 @@ +Shelving: Matrícula +Remove selected lines: Eliminar líneas seleccionadas +Selected lines will be deleted: Las líneas seleccionadas serán eliminadas +ItemShelvings removed: Carros eliminados +Total labels: Total etiquetas \ No newline at end of file diff --git a/modules/item/front/item-type/basic-data/index.html b/modules/item/front/item-type/basic-data/index.html new file mode 100644 index 000000000..c3f7a57f1 --- /dev/null +++ b/modules/item/front/item-type/basic-data/index.html @@ -0,0 +1,62 @@ + + +
+ + + + + + + + + + + + + + + + + + + + +
diff --git a/modules/item/front/item-type/basic-data/index.js b/modules/item/front/item-type/basic-data/index.js new file mode 100644 index 000000000..ec280fdf8 --- /dev/null +++ b/modules/item/front/item-type/basic-data/index.js @@ -0,0 +1,12 @@ +import ngModule from '../../module'; +import Section from 'salix/components/section'; + +export default class Controller extends Section {} + +ngModule.component('vnItemTypeBasicData', { + template: require('./index.html'), + controller: Controller, + bindings: { + itemType: '<' + } +}); diff --git a/modules/item/front/item-type/card/index.html b/modules/item/front/item-type/card/index.html new file mode 100644 index 000000000..80af6088e --- /dev/null +++ b/modules/item/front/item-type/card/index.html @@ -0,0 +1,5 @@ + + + + + diff --git a/modules/item/front/item-type/card/index.js b/modules/item/front/item-type/card/index.js new file mode 100644 index 000000000..fa6b37340 --- /dev/null +++ b/modules/item/front/item-type/card/index.js @@ -0,0 +1,23 @@ +import ngModule from '../../module'; +import ModuleCard from 'salix/components/module-card'; + +class Controller extends ModuleCard { + reload() { + const filter = { + include: [ + {relation: 'worker'}, + {relation: 'category'}, + {relation: 'itemPackingType'}, + {relation: 'temperature'} + ] + }; + + this.$http.get(`ItemTypes/${this.$params.id}`, {filter}) + .then(res => this.itemType = res.data); + } +} + +ngModule.vnComponent('vnItemTypeCard', { + template: require('./index.html'), + controller: Controller +}); diff --git a/modules/item/front/item-type/card/index.spec.js b/modules/item/front/item-type/card/index.spec.js new file mode 100644 index 000000000..ab2314bb9 --- /dev/null +++ b/modules/item/front/item-type/card/index.spec.js @@ -0,0 +1,27 @@ +import './index'; + +describe('component vnItemTypeCard', () => { + let controller; + let $httpBackend; + + beforeEach(ngModule('item')); + + beforeEach(inject(($componentController, _$httpBackend_) => { + $httpBackend = _$httpBackend_; + controller = $componentController('vnItemTypeCard', {$element: null}); + })); + + describe('reload()', () => { + it('should reload the controller data', () => { + controller.$params.id = 1; + + const itemType = {id: 1}; + + $httpBackend.expectGET('ItemTypes/1').respond(itemType); + controller.reload(); + $httpBackend.flush(); + + expect(controller.itemType).toEqual(itemType); + }); + }); +}); diff --git a/modules/item/front/item-type/create/index.html b/modules/item/front/item-type/create/index.html new file mode 100644 index 000000000..4a199a1b1 --- /dev/null +++ b/modules/item/front/item-type/create/index.html @@ -0,0 +1,62 @@ + + +
+ + + + + + + + + + + + + + + + + + + + +
diff --git a/modules/item/front/item-type/create/index.js b/modules/item/front/item-type/create/index.js new file mode 100644 index 000000000..ccf7744be --- /dev/null +++ b/modules/item/front/item-type/create/index.js @@ -0,0 +1,15 @@ +import ngModule from '../../module'; +import Section from 'salix/components/section'; + +export default class Controller extends Section { + onSubmit() { + return this.$.watcher.submit().then(res => + this.$state.go('item.itemType.card.basicData', {id: res.data.id}) + ); + } +} + +ngModule.component('vnItemTypeCreate', { + template: require('./index.html'), + controller: Controller +}); diff --git a/modules/item/front/item-type/create/index.spec.js b/modules/item/front/item-type/create/index.spec.js new file mode 100644 index 000000000..4b000df9a --- /dev/null +++ b/modules/item/front/item-type/create/index.spec.js @@ -0,0 +1,34 @@ +import './index'; + +describe('component vnItemTypeCreate', () => { + let $scope; + let $state; + let controller; + + beforeEach(ngModule('item')); + + beforeEach(inject(($componentController, $rootScope, _$state_) => { + $scope = $rootScope.$new(); + $state = _$state_; + $scope.watcher = { + submit: () => { + return { + then: callback => { + callback({data: {id: '1234'}}); + } + }; + } + }; + const $element = angular.element(''); + controller = $componentController('vnItemTypeCreate', {$element, $scope}); + })); + + describe('onSubmit()', () => { + it(`should call submit() on the watcher then expect a callback`, () => { + jest.spyOn($state, 'go'); + controller.onSubmit(); + + expect(controller.$state.go).toHaveBeenCalledWith('item.itemType.card.basicData', {id: '1234'}); + }); + }); +}); diff --git a/modules/item/front/item-type/descriptor/index.html b/modules/item/front/item-type/descriptor/index.html new file mode 100644 index 000000000..5a0e8ed49 --- /dev/null +++ b/modules/item/front/item-type/descriptor/index.html @@ -0,0 +1,25 @@ + + +
+ + + + + + + + +
+
+
\ No newline at end of file diff --git a/modules/item/front/item-type/descriptor/index.js b/modules/item/front/item-type/descriptor/index.js new file mode 100644 index 000000000..9322c599a --- /dev/null +++ b/modules/item/front/item-type/descriptor/index.js @@ -0,0 +1,20 @@ +import ngModule from '../../module'; +import Descriptor from 'salix/components/descriptor'; + +class Controller extends Descriptor { + get itemType() { + return this.entity; + } + + set itemType(value) { + this.entity = value; + } +} + +ngModule.component('vnItemTypeDescriptor', { + template: require('./index.html'), + controller: Controller, + bindings: { + itemType: '<' + } +}); diff --git a/modules/item/front/item-type/index.js b/modules/item/front/item-type/index.js new file mode 100644 index 000000000..5dcbe4097 --- /dev/null +++ b/modules/item/front/item-type/index.js @@ -0,0 +1,8 @@ +import './main'; +import './index/'; +import './summary'; +import './card'; +import './descriptor'; +import './create'; +import './basic-data'; +import './search-panel'; diff --git a/modules/item/front/item-type/index/index.html b/modules/item/front/item-type/index/index.html new file mode 100644 index 000000000..50b9eb172 --- /dev/null +++ b/modules/item/front/item-type/index/index.html @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/item/front/item-type/index/index.js b/modules/item/front/item-type/index/index.js new file mode 100644 index 000000000..54ecba997 --- /dev/null +++ b/modules/item/front/item-type/index/index.js @@ -0,0 +1,14 @@ +import ngModule from '../../module'; +import Section from 'salix/components/section'; + +export default class Controller extends Section { + preview(itemType) { + this.selectedItemType = itemType; + this.$.summary.show(); + } +} + +ngModule.component('vnItemTypeIndex', { + template: require('./index.html'), + controller: Controller +}); diff --git a/modules/item/front/item-type/index/index.spec.js b/modules/item/front/item-type/index/index.spec.js new file mode 100644 index 000000000..887c03f7f --- /dev/null +++ b/modules/item/front/item-type/index/index.spec.js @@ -0,0 +1,34 @@ +import './index'; + +describe('Item', () => { + describe('Component vnItemTypeIndex', () => { + let controller; + let $window; + + beforeEach(ngModule('item')); + + beforeEach(inject(($componentController, _$window_) => { + $window = _$window_; + const $element = angular.element(''); + controller = $componentController('vnItemTypeIndex', {$element}); + })); + + describe('preview()', () => { + it('should show the dialog summary', () => { + controller.$.summary = {show: () => {}}; + jest.spyOn(controller.$.summary, 'show'); + + const itemType = {id: 1}; + + const event = new MouseEvent('click', { + view: $window, + bubbles: true, + cancelable: true + }); + controller.preview(event, itemType); + + expect(controller.$.summary.show).toHaveBeenCalledWith(); + }); + }); + }); +}); diff --git a/modules/item/front/item-type/index/locale/es.yml b/modules/item/front/item-type/index/locale/es.yml new file mode 100644 index 000000000..1a71ff212 --- /dev/null +++ b/modules/item/front/item-type/index/locale/es.yml @@ -0,0 +1,2 @@ +Item Type: Familia +New itemType: Nueva familia \ No newline at end of file diff --git a/modules/item/front/item-type/main/index.html b/modules/item/front/item-type/main/index.html new file mode 100644 index 000000000..faba696c0 --- /dev/null +++ b/modules/item/front/item-type/main/index.html @@ -0,0 +1,18 @@ + + + + + + + + + \ No newline at end of file diff --git a/modules/item/front/item-type/main/index.js b/modules/item/front/item-type/main/index.js new file mode 100644 index 000000000..0dea00abb --- /dev/null +++ b/modules/item/front/item-type/main/index.js @@ -0,0 +1,24 @@ +import ngModule from '../../module'; +import ModuleMain from 'salix/components/module-main'; + +export default class ItemType extends ModuleMain { + exprBuilder(param, value) { + switch (param) { + case 'search': + return /^\d+$/.test(value) + ? {id: value} + : {or: [ + {name: {like: `%${value}%`}}, + {code: {like: `%${value}%`}} + ]}; + case 'name': + case 'code': + return {[param]: {like: `%${value}%`}}; + } + } +} + +ngModule.vnComponent('vnItemType', { + controller: ItemType, + template: require('./index.html') +}); diff --git a/modules/item/front/item-type/main/index.spec.js b/modules/item/front/item-type/main/index.spec.js new file mode 100644 index 000000000..dcb14ec0e --- /dev/null +++ b/modules/item/front/item-type/main/index.spec.js @@ -0,0 +1,31 @@ +import './index'; + +describe('Item', () => { + describe('Component vnItemType', () => { + let controller; + + beforeEach(ngModule('item')); + + beforeEach(inject($componentController => { + const $element = angular.element(''); + controller = $componentController('vnItemType', {$element}); + })); + + describe('exprBuilder()', () => { + it('should return a filter based on a search by id', () => { + const filter = controller.exprBuilder('search', '123'); + + expect(filter).toEqual({id: '123'}); + }); + + it('should return a filter based on a search by name or code', () => { + const filter = controller.exprBuilder('search', 'Alstroemeria'); + + expect(filter).toEqual({or: [ + {name: {like: '%Alstroemeria%'}}, + {code: {like: '%Alstroemeria%'}}, + ]}); + }); + }); + }); +}); diff --git a/modules/item/front/item-type/main/locale/es.yml b/modules/item/front/item-type/main/locale/es.yml new file mode 100644 index 000000000..7aceac46f --- /dev/null +++ b/modules/item/front/item-type/main/locale/es.yml @@ -0,0 +1 @@ +Search itemType by id, name or code: Buscar familia por id, nombre o código \ No newline at end of file diff --git a/modules/item/front/item-type/search-panel/index.html b/modules/item/front/item-type/search-panel/index.html new file mode 100644 index 000000000..4aa762900 --- /dev/null +++ b/modules/item/front/item-type/search-panel/index.html @@ -0,0 +1,22 @@ +
+
+ + + + + + + + + + + +
+
\ No newline at end of file diff --git a/modules/item/front/item-type/search-panel/index.js b/modules/item/front/item-type/search-panel/index.js new file mode 100644 index 000000000..17a439c39 --- /dev/null +++ b/modules/item/front/item-type/search-panel/index.js @@ -0,0 +1,7 @@ +import ngModule from '../../module'; +import SearchPanel from 'core/components/searchbar/search-panel'; + +ngModule.component('vnItemTypeSearchPanel', { + template: require('./index.html'), + controller: SearchPanel +}); diff --git a/modules/item/front/item-type/summary/index.html b/modules/item/front/item-type/summary/index.html new file mode 100644 index 000000000..d003c8f38 --- /dev/null +++ b/modules/item/front/item-type/summary/index.html @@ -0,0 +1,50 @@ + +
+ {{summary.id}} - {{summary.name}} - {{summary.worker.firstName}} {{summary.worker.lastName}} +
+ + +

Basic data

+ + + + + + + + + + + + + + + + + + + + +
+
+
\ No newline at end of file diff --git a/modules/item/front/item-type/summary/index.js b/modules/item/front/item-type/summary/index.js new file mode 100644 index 000000000..7645de8b1 --- /dev/null +++ b/modules/item/front/item-type/summary/index.js @@ -0,0 +1,33 @@ +import ngModule from '../../module'; +import Component from 'core/lib/component'; + +class Controller extends Component { + set itemType(value) { + this._itemType = value; + this.$.summary = null; + if (!value) return; + + const filter = { + include: [ + {relation: 'worker'}, + {relation: 'category'}, + {relation: 'itemPackingType'}, + {relation: 'temperature'} + ] + }; + this.$http.get(`ItemTypes/${value.id}`, {filter}) + .then(res => this.$.summary = res.data); + } + + get itemType() { + return this._itemType; + } +} + +ngModule.component('vnItemTypeSummary', { + template: require('./index.html'), + controller: Controller, + bindings: { + itemType: '<' + } +}); diff --git a/modules/item/front/item-type/summary/locale/es.yml b/modules/item/front/item-type/summary/locale/es.yml new file mode 100644 index 000000000..8f4cef70f --- /dev/null +++ b/modules/item/front/item-type/summary/locale/es.yml @@ -0,0 +1,4 @@ +Life: Vida +Promo: Promoción +Item packing type: Tipo de embalaje +Is unconventional size: Es de tamaño poco convencional \ No newline at end of file diff --git a/modules/item/front/last-entries/index.html b/modules/item/front/last-entries/index.html new file mode 100644 index 000000000..e3b84655c --- /dev/null +++ b/modules/item/front/last-entries/index.html @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + Ig + Warehouse + Landed + Entry + PVP + Label + Packing + Grouping + Stems + Quantity + Cost + Kg. + Cube + Provider + + + + + + + + + {{::entry.warehouse| dashIfEmpty}} + {{::entry.landed | date:'dd/MM/yyyy HH:mm'}} + + + {{::entry.entryFk | dashIfEmpty}} + + + + {{::entry.price2 | currency: 'EUR':2 | dashIfEmpty}} / {{::entry.price3 | currency: 'EUR':2 | dashIfEmpty}} + + {{entry.stickers | dashIfEmpty}} + + + {{::entry.packing | dashIfEmpty}} + + + + + {{::entry.grouping | dashIfEmpty}} + + + {{::entry.stems | dashIfEmpty}} + {{::entry.quantity}} + + + {{::entry.cost | currency: 'EUR':3 | dashIfEmpty}} + + + {{::entry.weight | dashIfEmpty}} + {{::entry.packagingFk | dashIfEmpty}} + {{::entry.supplier | dashIfEmpty}} + + + + + + + + + + + + + + Filter by selection + + + Exclude selection + + + Remove filter + + + Remove all filters + + + Copy value + + + diff --git a/modules/item/front/last-entries/index.js b/modules/item/front/last-entries/index.js new file mode 100644 index 000000000..a5f1f4d9d --- /dev/null +++ b/modules/item/front/last-entries/index.js @@ -0,0 +1,105 @@ +import ngModule from '../module'; +import Section from 'salix/components/section'; + +class Controller extends Section { + constructor($element, $) { + super($element, $); + + const from = Date.vnNew(); + from.setDate(from.getDate() - 75); + from.setHours(0, 0, 0, 0); + + const to = Date.vnNew(); + to.setDate(to.getDate() + 10); + to.setHours(23, 59, 59, 59); + + this.filter = { + where: { + itemFk: this.$params.id, + landed: { + between: [from, to] + } + } + }; + this._dateFrom = from; + this._dateTo = to; + } + + set dateFrom(value) { + this._dateFrom = value; + + if (!value) return; + + const from = new Date(value); + from.setHours(0, 0, 0, 0); + + const to = new Date(this._dateTo); + to.setHours(23, 59, 59, 59); + + this.filter.where.landed = { + between: [from, to] + }; + this.$.model.refresh(); + } + + set dateTo(value) { + this._dateTo = value; + + if (!value) return; + + const from = new Date(this._dateFrom); + from.setHours(0, 0, 0, 0); + + const to = new Date(value); + to.setHours(23, 59, 59, 59); + + this.filter.where.landed = { + between: [from, to] + }; + this.$.model.refresh(); + } + + get dateFrom() { + return this._dateFrom; + } + + get dateTo() { + return this._dateTo; + } + + exprBuilder(param, value) { + switch (param) { + case 'id': + case 'quantity': + case 'packagingFk': + return {[`b.${param}`]: value}; + case 'supplierFk': + return {[`s.id`]: value}; + case 'warehouseFk': + return {'tr.warehouseInFk': value}; + case 'landed': + return {'tr.landed': { + between: this.dateRange(value)} + }; + } + } + + dateRange(value) { + const minHour = new Date(value); + minHour.setHours(0, 0, 0, 0); + const maxHour = new Date(value); + maxHour.setHours(23, 59, 59, 59); + + return [minHour, maxHour]; + } +} + +Controller.$inject = ['$element', '$scope']; + +ngModule.vnComponent('vnItemLastEntries', { + template: require('./index.html'), + controller: Controller, + bindings: { + item: '<' + } +}); diff --git a/modules/item/front/last-entries/locale/es.yml b/modules/item/front/last-entries/locale/es.yml new file mode 100644 index 000000000..f2917bb63 --- /dev/null +++ b/modules/item/front/last-entries/locale/es.yml @@ -0,0 +1,15 @@ +Since: Desde +Landed: F. entrega +Stems: Tallos +Quantity: Cantidad +Cost: Coste +Label: Etiquetas +Entry: Entrada +Ignored: Ignorado +Provider: Proveedor +Cube: Cubo +Price Per Unit: Precio Por Unidad +Price Per Package: Precio Por Paquete +Freight: Porte +Package: Embalaje +Comission: Comision \ No newline at end of file diff --git a/modules/item/front/main/index.html b/modules/item/front/main/index.html index e69de29bb..44d125758 100644 --- a/modules/item/front/main/index.html +++ b/modules/item/front/main/index.html @@ -0,0 +1,23 @@ + + + + + + + + + + \ No newline at end of file diff --git a/modules/item/front/main/index.js b/modules/item/front/main/index.js index 33e5822c3..1d99c91a1 100644 --- a/modules/item/front/main/index.js +++ b/modules/item/front/main/index.js @@ -3,10 +3,11 @@ import ModuleMain from 'salix/components/module-main'; export default class Items extends ModuleMain { constructor($element, $) { super($element, $); - } - async $onInit() { - this.$state.go('home'); - window.location.href = await this.vnApp.getUrl(`claim/`); + + this.filterParams = { + isActive: true, + isFloramondo: false + }; } } diff --git a/modules/item/front/request-search-panel/index.html b/modules/item/front/request-search-panel/index.html new file mode 100644 index 000000000..6a51a429d --- /dev/null +++ b/modules/item/front/request-search-panel/index.html @@ -0,0 +1,104 @@ +
+ + +
+ + + + + + + + + + + + + + + + + + + + +
+ + + + + + Or + + + + + +
+ + + + + {{name}} + + + + + +
+
diff --git a/modules/item/front/request-search-panel/index.js b/modules/item/front/request-search-panel/index.js new file mode 100644 index 000000000..556bdd874 --- /dev/null +++ b/modules/item/front/request-search-panel/index.js @@ -0,0 +1,48 @@ +import ngModule from '../module'; +import SearchPanel from 'core/components/searchbar/search-panel'; + +class Controller extends SearchPanel { + constructor($element, $) { + super($element, $); + + this.states = [ + {code: 'pending', name: this.$t('Pending')}, + {code: 'accepted', name: this.$t('Accepted')}, + {code: 'denied', name: this.$t('Denied')} + ]; + } + + get from() { + return this._from; + } + + set from(value) { + this._from = value; + this.filter.scopeDays = null; + } + + get to() { + return this._to; + } + + set to(value) { + this._to = value; + this.filter.scopeDays = null; + } + + get scopeDays() { + return this._scopeDays; + } + + set scopeDays(value) { + this._scopeDays = value; + + this.filter.from = null; + this.filter.to = null; + } +} + +ngModule.vnComponent('vnRequestSearchPanel', { + template: require('./index.html'), + controller: Controller +}); diff --git a/modules/item/front/request-search-panel/index.spec.js b/modules/item/front/request-search-panel/index.spec.js new file mode 100644 index 000000000..56c76eabf --- /dev/null +++ b/modules/item/front/request-search-panel/index.spec.js @@ -0,0 +1,48 @@ +import './index'; + +describe(' Component vnRequestSearchPanel', () => { + let controller; + + beforeEach(ngModule('item')); + + beforeEach(inject($componentController => { + controller = $componentController('vnRequestSearchPanel', {$element: null}); + controller.$t = () => {}; + controller.filter = {}; + })); + + describe('from() setter', () => { + it('should clear the scope days when setting the from property', () => { + controller.filter.scopeDays = 1; + + controller.from = Date.vnNew(); + + expect(controller.filter.scopeDays).toBeNull(); + expect(controller.from).toBeDefined(); + }); + }); + + describe('to() setter', () => { + it('should clear the scope days when setting the to property', () => { + controller.filter.scopeDays = 1; + + controller.to = Date.vnNew(); + + expect(controller.filter.scopeDays).toBeNull(); + expect(controller.to).toBeDefined(); + }); + }); + + describe('scopeDays() setter', () => { + it('should clear the date range when setting the scopeDays property', () => { + controller.filter.from = Date.vnNew(); + controller.filter.to = Date.vnNew(); + + controller.scopeDays = 1; + + expect(controller.filter.from).toBeNull(); + expect(controller.filter.to).toBeNull(); + expect(controller.scopeDays).toBeDefined(); + }); + }); +}); diff --git a/modules/item/front/request-search-panel/locale/es.yml b/modules/item/front/request-search-panel/locale/es.yml new file mode 100644 index 000000000..8d5276194 --- /dev/null +++ b/modules/item/front/request-search-panel/locale/es.yml @@ -0,0 +1,4 @@ +Ink: Tinta +Origin: Origen +Producer: Productor +For me: Para mi \ No newline at end of file diff --git a/modules/item/front/request/index.html b/modules/item/front/request/index.html new file mode 100644 index 000000000..03c8db8ec --- /dev/null +++ b/modules/item/front/request/index.html @@ -0,0 +1,172 @@ + + + + + + + + + + + + Ticket ID + Shipped + Description + Requester + Requested + Price + Atender + Item + Achieved + Concept + State + + + + + + + + {{request.ticketFk}} + + + + + {{::request.shipped | date: 'dd/MM/yyyy'}} + + + {{::request.description}} + + + {{::request.requesterName}} + + + {{::request.quantity}} + {{::request.price | currency: 'EUR':2}} + + + {{::request.attenderName}} + + + + {{request.itemFk}} + + + + + + + {{request.saleQuantity}} + + + + + + + + {{request.itemDescription}} + + + {{$ctrl.getState(request.isOk)}} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Filter by selection + + + Exclude selection + + + Remove filter + + + Remove all filters + + + Copy value + + + diff --git a/modules/item/front/request/index.js b/modules/item/front/request/index.js new file mode 100644 index 000000000..747cbeff2 --- /dev/null +++ b/modules/item/front/request/index.js @@ -0,0 +1,143 @@ +import ngModule from '../module'; +import Section from 'salix/components/section'; +import './style.scss'; + +export default class Controller extends Section { + constructor($element, $) { + super($element, $); + + if (!this.$state.q) { + const today = Date.vnNew(); + today.setHours(0, 0, 0, 0); + + const nextWeek = Date.vnNew(); + nextWeek.setHours(23, 59, 59, 59); + nextWeek.setDate(nextWeek.getDate() + 7); + + this.filterParams = { + from: today, + to: nextWeek, + state: 'pending' + }; + } + } + + fetchParams($params) { + if (!Object.entries($params).length) + $params.scopeDays = 1; + + if (typeof $params.scopeDays === 'number') { + const from = Date.vnNew(); + from.setHours(0, 0, 0, 0); + + const to = new Date(from.getTime()); + to.setDate(to.getDate() + $params.scopeDays); + to.setHours(23, 59, 59, 999); + + Object.assign($params, {from, to}); + } + + return $params; + } + + getState(isOk) { + if (isOk === null) + return 'Pending'; + else if (isOk) + return 'Accepted'; + else + return 'Denied'; + } + + confirmRequest(request) { + if (request.itemFk && request.saleQuantity) { + let params = { + itemFk: request.itemFk, + quantity: request.saleQuantity + }; + + let query = `TicketRequests/${request.id}/confirm`; + this.$http.post(query, params).then(res => { + request.itemDescription = res.data.concept; + request.isOk = true; + + this.vnApp.showSuccess(this.$t('Data saved!')); + }); + } + } + + changeQuantity(request) { + if (request.saleFk) { + let params = { + quantity: request.saleQuantity + }; + + let endpoint = `Sales/${request.saleFk}`; + + this.$http.patch(endpoint, params) + .then(() => this.vnApp.showSuccess(this.$t('Data saved!'))) + .then(() => this.confirmRequest(request)); + } else + this.confirmRequest(request); + } + + compareDate(date) { + let today = Date.vnNew(); + today.setHours(0, 0, 0, 0); + let timeTicket = new Date(date); + timeTicket.setHours(0, 0, 0, 0); + + let comparation = today - timeTicket; + + if (comparation == 0) + return 'warning'; + if (comparation < 0) + return 'success'; + } + + onDenyAccept(request) { + let params = { + observation: this.denyObservation + }; + + return this.$http.post(`TicketRequests/${request.id}/deny`, params) + .then(res => { + const newRequest = res.data; + request.isOk = newRequest.isOk; + request.attenderFk = newRequest.attenderFk; + request.response = newRequest.response; + + this.vnApp.showSuccess(this.$t('Data saved!')); + }); + } + + exprBuilder(param, value) { + switch (param) { + case 'ticketFk': + case 'quantity': + case 'price': + case 'isOk': + return {[`tr.${param}`]: value}; + case 'attenderName': + return {[`ua.name`]: value}; + case 'shipped': + return {'t.shipped': { + between: this.dateRange(value)} + }; + } + } + + dateRange(value) { + const minHour = new Date(value); + minHour.setHours(0, 0, 0, 0); + const maxHour = new Date(value); + maxHour.setHours(23, 59, 59, 59); + + return [minHour, maxHour]; + } +} + +ngModule.vnComponent('vnItemRequest', { + template: require('./index.html'), + controller: Controller +}); diff --git a/modules/item/front/request/index.spec.js b/modules/item/front/request/index.spec.js new file mode 100644 index 000000000..aadeaddca --- /dev/null +++ b/modules/item/front/request/index.spec.js @@ -0,0 +1,120 @@ +import './index.js'; + +describe('Item', () => { + describe('Component vnItemRequest', () => { + let $scope; + let controller; + let $httpBackend; + + beforeEach(ngModule('item')); + + beforeEach(inject(($componentController, $rootScope, _$httpBackend_) => { + $httpBackend = _$httpBackend_; + $scope = $rootScope.$new(); + controller = $componentController('vnItemRequest', {$element: null, $scope}); + })); + + afterAll(() => { + $scope.$destroy(); + $element.remove(); + }); + + describe('getState()', () => { + it(`should return an string depending to the isOK value`, () => { + let isOk = null; + let result = controller.getState(isOk); + + expect(result).toEqual('Pending'); + + isOk = 1; + result = controller.getState(isOk); + + expect(result).toEqual('Accepted'); + + isOk = 0; + result = controller.getState(isOk); + + expect(result).toEqual('Denied'); + }); + }); + + describe('confirmRequest()', () => { + it(`should do nothing if the request does't have itemFk or saleQuantity`, () => { + let request = {}; + jest.spyOn(controller.vnApp, 'showSuccess'); + + controller.confirmRequest(request); + + expect(controller.vnApp.showSuccess).not.toHaveBeenCalled(); + }); + + it('should perform a query and call vnApp.showSuccess() and refresh if the conditions are met', () => { + jest.spyOn(controller.vnApp, 'showSuccess'); + + const expectedResult = {concept: 'Melee Weapon'}; + let request = {itemFk: 1, saleQuantity: 1, id: 1}; + + $httpBackend.expectPOST(`TicketRequests/${request.id}/confirm`).respond(expectedResult); + controller.confirmRequest(request); + $httpBackend.flush(); + + expect(controller.vnApp.showSuccess).toHaveBeenCalled(); + }); + }); + + describe('changeQuantity()', () => { + it(`should call confirmRequest() if there's no sale id in the request`, () => { + let request = {}; + jest.spyOn(controller, 'confirmRequest'); + + controller.changeQuantity(request); + + expect(controller.confirmRequest).toHaveBeenCalledWith(jasmine.any(Object)); + }); + + it(`should perform a query and call vnApp.showSuccess() if the conditions are met`, () => { + let request = {saleFk: 1, saleQuantity: 1}; + jest.spyOn(controller.vnApp, 'showSuccess'); + + $httpBackend.expectPATCH(`Sales/${request.saleFk}`).respond(); + controller.changeQuantity(request); + $httpBackend.flush(); + + expect(controller.vnApp.showSuccess).toHaveBeenCalled(); + }); + }); + + describe('compareDate()', () => { + it(`should return "success" if receives a future date`, () => { + let date = '3019-02-18T11:00:00.000Z'; + let result = controller.compareDate(date); + + expect(result).toEqual('success'); + }); + + it(`should return "warning" if date is today`, () => { + let date = Date.vnNew(); + let result = controller.compareDate(date); + + expect(result).toEqual('warning'); + }); + }); + + describe('onDenyAccept()', () => { + it(`should deny the request`, () => { + const request = { + id: 1, + response: 'new' + }; + + $httpBackend.expectPOST(`TicketRequests/${request.id}/deny`) + .respond({response: 'denied'}); + controller.onDenyAccept(request); + $httpBackend.flush(); + + expect(request.response).toBe('denied'); + }); + }); + }); +}); + diff --git a/modules/item/front/request/locale/es.yml b/modules/item/front/request/locale/es.yml new file mode 100644 index 000000000..c61a00130 --- /dev/null +++ b/modules/item/front/request/locale/es.yml @@ -0,0 +1,9 @@ +Discard: Descartar +Specify the reasons to deny this request: Especifica las razones para descartar la petición +Buy requests: Peticiones de compra +Search request by id or alias: Buscar peticiones por identificador o alias +Requested: Solicitado +Achieved: Conseguido +Pending: Pendiente +Accepted: Aceptada +Denied: Rechazada \ No newline at end of file diff --git a/modules/item/front/request/style.scss b/modules/item/front/request/style.scss new file mode 100644 index 000000000..59612bbd6 --- /dev/null +++ b/modules/item/front/request/style.scss @@ -0,0 +1,15 @@ +@import "variables"; + +vn-item-request { + vn-dialog[vn-id="denyReason"] { + button.close { + display: none + } + vn-button { + margin: 0 auto + } + vn-textarea { + width: 100% + } + } +} \ No newline at end of file diff --git a/modules/item/front/routes.json b/modules/item/front/routes.json index 205930466..05b887a96 100644 --- a/modules/item/front/routes.json +++ b/modules/item/front/routes.json @@ -6,7 +6,25 @@ "dependencies": ["worker", "client", "ticket", "entry"], "menus": { "main": [ - {"state": "item.index", "icon": "icon-item"} + {"state": "item.index", "icon": "icon-item"}, + {"state": "item.request", "icon": "icon-buyrequest"}, + {"state": "item.waste.index", "icon": "icon-claims"}, + {"state": "item.fixedPrice", "icon": "icon-fixedPrice"}, + {"state": "item.itemType", "icon": "contact_support"} + ], + "card": [ + {"state": "item.card.basicData", "icon": "settings"}, + {"state": "item.card.tags", "icon": "icon-tags"}, + {"state": "item.card.last-entries", "icon": "icon-regentry"}, + {"state": "item.card.tax", "icon": "icon-tax"}, + {"state": "item.card.botanical", "icon": "local_florist"}, + {"state": "item.card.shelving", "icon": "icon-inventory"}, + {"state": "item.card.itemBarcode", "icon": "icon-barcode"}, + {"state": "item.card.diary", "icon": "icon-transaction"}, + {"state": "item.card.log", "icon": "history"} + ], + "itemType": [ + {"state": "item.itemType.card.basicData", "icon": "settings"} ] }, "keybindings": [ @@ -26,11 +44,187 @@ "component": "vn-item-index", "description": "Items" }, + { + "url": "/create", + "state": "item.create", + "component": "vn-item-create", + "description": "New item" + }, { "url": "/:id", "state": "item.card", "abstract": true, "component": "vn-item-card" + }, + { + "url" : "/basic-data", + "state": "item.card.basicData", + "component": "vn-item-basic-data", + "description": "Basic data", + "params": { + "item": "$ctrl.item" + }, + "acl": ["buyer"] + }, + { + "url" : "/tags", + "state": "item.card.tags", + "component": "vn-item-tags", + "description": "Tags", + "params": { + "item-tags": "$ctrl.itemTags" + }, + "acl": ["buyer", "replenisher"] + }, + { + "url" : "/tax", + "state": "item.card.tax", + "component": "vn-item-tax", + "description": "Tax", + "acl": ["administrative","buyer"] + }, + { + "url" : "/botanical", + "state": "item.card.botanical", + "component": "vn-item-botanical", + "description": "Botanical", + "params": { + "item": "$ctrl.item" + }, + "acl": ["buyer"] + }, + { + "url" : "/shelving", + "state": "item.card.shelving", + "component": "vn-item-shelving", + "description": "Shelvings", + "params": { + "item": "$ctrl.item" + }, + "acl": ["employee"] + }, + { + "url" : "/barcode", + "state": "item.card.itemBarcode", + "component": "vn-item-barcode", + "description": "Barcodes", + "params": { + "item": "$ctrl.item" + }, + "acl": ["buyer","replenisher"] + }, + { + "url" : "/summary", + "state": "item.card.summary", + "component": "vn-item-summary", + "description": "Summary", + "params": { + "item": "$ctrl.item" + } + }, + { + "url" : "/diary?warehouseFk&lineFk", + "state": "item.card.diary", + "component": "vn-item-diary", + "description": "Diary", + "params": { + "item": "$ctrl.item" + }, + "acl": ["employee"] + }, + { + "url" : "/last-entries", + "state": "item.card.last-entries", + "component": "vn-item-last-entries", + "description": "Last entries", + "params": { + "item": "$ctrl.item" + }, + "acl": ["employee"] + }, + { + "url" : "/log", + "state": "item.card.log", + "component": "vn-item-log", + "description": "Log" + }, + { + "url" : "/request?q", + "state": "item.request", + "component": "vn-item-request", + "description": "Buy requests", + "params": { + "item": "$ctrl.item" + }, + "acl": ["employee"] + }, + { + "url": "/waste", + "state": "item.waste", + "component": "ui-view", + "abstract": true + }, + { + "url" : "/index", + "state": "item.waste.index", + "component": "vn-item-waste-index", + "description": "Waste breakdown", + "acl": ["buyer"] + }, + { + "url" : "/detail?buyer&family", + "state": "item.waste.detail", + "component": "vn-item-waste-detail", + "description": "Waste breakdown by item", + "acl": ["buyer"] + }, + { + "url" : "/fixed-price?q", + "state": "item.fixedPrice", + "component": "vn-fixed-price", + "description": "Fixed prices", + "acl": ["buyer"] + }, + { + "url" : "/item-type?q", + "state": "item.itemType", + "component": "vn-item-type", + "description": "Item Type", + "acl": ["buyer"] + }, + { + "url": "/create", + "state": "item.itemType.create", + "component": "vn-item-type-create", + "description": "New itemType", + "acl": ["buyer"] + }, + { + "url": "/:id", + "state": "item.itemType.card", + "component": "vn-item-type-card", + "abstract": true, + "description": "Detail" + }, + { + "url": "/summary", + "state": "item.itemType.card.summary", + "component": "vn-item-type-summary", + "description": "Summary", + "params": { + "item-type": "$ctrl.itemType" + }, + "acl": ["buyer"] + }, + { + "url": "/basic-data", + "state": "item.itemType.card.basicData", + "component": "vn-item-type-basic-data", + "description": "Basic data", + "params": { + "item-type": "$ctrl.itemType" + }, + "acl": ["buyer"] } ] } diff --git a/modules/item/front/search-panel/index.html b/modules/item/front/search-panel/index.html new file mode 100644 index 000000000..33f141b18 --- /dev/null +++ b/modules/item/front/search-panel/index.html @@ -0,0 +1,181 @@ + +
+
+ + + + + + + + + +
{{name}}
+
+ {{category.name}} +
+
> +
+
+ + + + + {{name}}: {{nickname}} + + + + + Tags + + + + + + + + + + + + + + + + + More fields + + + + + + + + +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ + + + + + + +
+
diff --git a/modules/item/front/search-panel/index.js b/modules/item/front/search-panel/index.js new file mode 100644 index 000000000..2448728be --- /dev/null +++ b/modules/item/front/search-panel/index.js @@ -0,0 +1,67 @@ +import ngModule from '../module'; +import SearchPanel from 'core/components/searchbar/search-panel'; + +class Controller extends SearchPanel { + constructor($element, $) { + super($element, $); + let model = 'Item'; + let moreFields = ['id', 'description', 'name', 'isActive']; + + let properties; + let validations = window.validations; + + if (validations && validations[model]) + properties = validations[model].properties; + else + properties = {}; + + this.moreFields = []; + for (let field of moreFields) { + let prop = properties[field]; + this.moreFields.push({ + name: field, + label: prop ? prop.description : field, + type: prop ? prop.type : null + }); + } + } + + get filter() { + let filter = this.$.filter; + + for (let fieldFilter of this.fieldFilters) + filter[fieldFilter.name] = fieldFilter.value; + + return filter; + } + + set filter(value) { + if (!value) + value = {}; + if (!value.tags) + value.tags = [{}]; + + this.fieldFilters = []; + for (let field of this.moreFields) { + if (value[field.name] != undefined) { + this.fieldFilters.push({ + name: field.name, + value: value[field.name], + info: field + }); + } + } + + this.$.filter = value; + } + + removeField(index, field) { + this.fieldFilters.splice(index, 1); + delete this.$.filter[field]; + } +} + +ngModule.vnComponent('vnItemSearchPanel', { + template: require('./index.html'), + controller: Controller +}); diff --git a/modules/item/front/search-panel/index.spec.js b/modules/item/front/search-panel/index.spec.js new file mode 100644 index 000000000..39b5b7aa5 --- /dev/null +++ b/modules/item/front/search-panel/index.spec.js @@ -0,0 +1,60 @@ +import './index.js'; + +describe('Item', () => { + describe('Component vnItemSearchPanel', () => { + let $element; + let controller; + + beforeEach(ngModule('item')); + + beforeEach(inject($componentController => { + $element = angular.element(`
`); + controller = $componentController('vnItemSearchPanel', {$element}); + })); + + describe('filter() setter', () => { + it(`should set the tags property to the scope filter with an empty array`, () => { + const expectedFilter = { + tags: [{}] + }; + controller.filter = null; + + expect(controller.filter).toEqual(expectedFilter); + }); + + it(`should set the tags property to the scope filter with an array of tags`, () => { + const expectedFilter = { + description: 'My item', + tags: [{}] + }; + const expectedFieldFilter = [{ + info: { + label: 'description', + name: 'description', + type: null + }, + name: 'description', + value: 'My item' + }]; + controller.filter = { + description: 'My item' + }; + + expect(controller.filter).toEqual(expectedFilter); + expect(controller.fieldFilters).toEqual(expectedFieldFilter); + }); + }); + + describe('removeField()', () => { + it(`should remove the description property from the fieldFilters and from the scope filter`, () => { + const expectedFilter = {tags: [{}]}; + controller.filter = {description: 'My item'}; + + controller.removeField(0, 'description'); + + expect(controller.filter).toEqual(expectedFilter); + expect(controller.fieldFilters).toEqual([]); + }); + }); + }); +}); diff --git a/modules/item/front/search-panel/locale/es.yml b/modules/item/front/search-panel/locale/es.yml new file mode 100644 index 000000000..67a5200d7 --- /dev/null +++ b/modules/item/front/search-panel/locale/es.yml @@ -0,0 +1,8 @@ +Ink: Tinta +Origin: Origen +Producer: Productor +With visible: Con visible +Field: Campo +More fields: Más campos +Add field: Añadir campo +Remove field: Quitar campo \ No newline at end of file diff --git a/modules/item/front/summary/index.html b/modules/item/front/summary/index.html new file mode 100644 index 000000000..0e4cfc955 --- /dev/null +++ b/modules/item/front/summary/index.html @@ -0,0 +1,227 @@ + +
+ + + + {{$ctrl.item.id}} - {{$ctrl.summary.item.name}} +
+ + + + + +

Visible

+

{{$ctrl.summary.visible}}

+
+ +

Available

+

{{$ctrl.summary.available}}

+
+ +

+ + +

+
+
+
+ +

+ + Basic data + +

+

+ Basic data +

+ + + + + + + + + + + + + + + + + {{$ctrl.summary.item.itemType.worker.user.name}} + + + + + + +
+ +

+ + Other data + +

+

+ Other data +

+ + + + + + + + + + + + + + + + + + + + +
+ +

+ + Tags + +

+

+ Tags +

+ + +
+ +

+ + Description + +

+

+ Description +

+

+ {{$ctrl.summary.item.description}} +

+
+ +

+ + Tax + +

+

+ Tax +

+ + +
+ +

+ + Botanical + +

+

+ Botanical +

+ + + + +
+ +

+ + Barcode + +

+

+ Barcode +

+

+ {{barcode.code}} +

+
+
+
+ + diff --git a/modules/item/front/summary/index.js b/modules/item/front/summary/index.js new file mode 100644 index 000000000..e17a6a8c4 --- /dev/null +++ b/modules/item/front/summary/index.js @@ -0,0 +1,61 @@ +import ngModule from '../module'; +import Summary from 'salix/components/summary'; +import './style.scss'; + +class Controller extends Summary { + getSummary() { + this.$http.get(`Items/${this.item.id}/getSummary`).then(response => { + this.summary = response.data; + }); + + this.$http.get('ItemConfigs/findOne') + .then(res => { + if (this.card) this.card.warehouseFk = res.data.warehouseFk; + this.getWarehouseName(res.data.warehouseFk); + }); + } + + getWarehouseName(warehouseFk) { + const filter = { + where: {id: warehouseFk} + }; + this.$http.get('Warehouses/findOne', {filter}) + .then(res => { + this.warehouseText = this.$t('WarehouseFk', { + warehouseName: res.data.name + }); + }); + } + + $onChanges() { + if (this.item && this.item.id) + this.getSummary(); + } + + get isBuyer() { + return this.aclService.hasAny(['buyer']); + } + + get isReplenisher() { + return this.aclService.hasAny(['replenisher']); + } + + get isAdministrative() { + return this.aclService.hasAny(['administrative']); + } + + get isEmployee() { + return this.aclService.hasAny(['employee']); + } +} + +ngModule.vnComponent('vnItemSummary', { + template: require('./index.html'), + controller: Controller, + bindings: { + item: '<', + }, + require: { + card: '?^vnItemCard' + } +}); diff --git a/modules/item/front/summary/index.spec.js b/modules/item/front/summary/index.spec.js new file mode 100644 index 000000000..d7821bea0 --- /dev/null +++ b/modules/item/front/summary/index.spec.js @@ -0,0 +1,42 @@ +import './index.js'; + +describe('Item', () => { + describe('Component summary', () => { + let controller; + let $httpBackend; + let $scope; + + beforeEach(ngModule('item')); + + beforeEach(inject(($componentController, _$httpBackend_, $rootScope) => { + $httpBackend = _$httpBackend_; + $scope = $rootScope.$new(); + const $element = angular.element(''); + controller = $componentController('vnItemSummary', {$element, $scope}); + controller.item = {id: 1}; + controller.card = {}; + })); + + describe('getSummary()', () => { + it('should perform a query to set summary', () => { + let data = {id: 1, name: 'Gem of mind'}; + $httpBackend.expect('GET', `Items/1/getSummary`).respond(200, data); + $httpBackend.expect('GET', `ItemConfigs/findOne`).respond({}); + $httpBackend.expect('GET', `Warehouses/findOne`).respond({}); + controller.getSummary(); + $httpBackend.flush(); + + expect(controller.summary).toEqual(data); + }); + }); + + describe('$onChanges()', () => { + it('should call getSummary when item.id is defined', () => { + jest.spyOn(controller, 'getSummary'); + controller.$onChanges(); + + expect(controller.getSummary).toHaveBeenCalledWith(); + }); + }); + }); +}); diff --git a/modules/item/front/summary/locale/en.yml b/modules/item/front/summary/locale/en.yml new file mode 100644 index 000000000..0ec208720 --- /dev/null +++ b/modules/item/front/summary/locale/en.yml @@ -0,0 +1 @@ +WarehouseFk: Calculated on the warehouse of {{ warehouseName }} diff --git a/modules/item/front/summary/locale/es.yml b/modules/item/front/summary/locale/es.yml new file mode 100644 index 000000000..80988c491 --- /dev/null +++ b/modules/item/front/summary/locale/es.yml @@ -0,0 +1,5 @@ +Barcode: Códigos de barras +Other data: Otros datos +Go to the item: Ir al artículo +WarehouseFk: Calculado sobre el almacén de {{ warehouseName }} +Minimum sales quantity: Cantidad mínima de venta diff --git a/modules/item/front/summary/style.scss b/modules/item/front/summary/style.scss new file mode 100644 index 000000000..d047f3e36 --- /dev/null +++ b/modules/item/front/summary/style.scss @@ -0,0 +1,39 @@ +@import "./variables"; + +vn-item-summary { + p { + margin: 0; + } +} + +.item-state { + padding: 6px; + background-color: $color-main; + color: $color-font-dark; + + p { + font-size: .75rem; + text-align: center; + margin: 0; + + &:first-child { + text-transform: uppercase; + line-height: 1; + } + &:last-child { + font-size: 1.5rem; + font-weight: bold; + } + } + vn-one { + padding: 0; + + &:nth-child(1) { + border-right: 1px solid white; + } + + &:nth-child(2) { + border-right: 1px solid white; + } + } +} diff --git a/modules/item/front/tags/index.html b/modules/item/front/tags/index.html new file mode 100644 index 000000000..f9b5370fa --- /dev/null +++ b/modules/item/front/tags/index.html @@ -0,0 +1,82 @@ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/modules/item/front/tags/index.js b/modules/item/front/tags/index.js new file mode 100644 index 000000000..2c3b39d45 --- /dev/null +++ b/modules/item/front/tags/index.js @@ -0,0 +1,54 @@ +import ngModule from '../module'; +import Section from 'salix/components/section'; + +class Controller extends Section { + constructor($element, $) { + super($element, $); + this.include = { + relation: 'tag', + scope: { + fields: ['id', 'name', 'isFree', 'sourceTable'] + } + }; + } + + add() { + this.$.model.insert({ + itemFk: this.$params.id, + priority: this.getHighestPriority() + }); + } + + getHighestPriority() { + let max = 0; + this.$.model.data.forEach(tag => { + if (tag.priority > max) + max = tag.priority; + }); + return max + 1; + } + + onSubmit() { + const changes = this.$.model.getChanges(); + const data = { + creates: changes.creates, + deletes: changes.deletes, + updates: changes.updates, + maxPriority: this.getHighestPriority() + }; + this.$http.patch(`Tags/onSubmit`, data).then(() => { + this.$.model.refresh(); + this.$.watcher.notifySaved(); + this.$.watcher.updateOriginalData(); + this.card.reload(); + }); + } +} + +ngModule.vnComponent('vnItemTags', { + template: require('./index.html'), + controller: Controller, + require: { + card: '^vnItemCard' + } +}); diff --git a/modules/item/front/tags/index.spec.js b/modules/item/front/tags/index.spec.js new file mode 100644 index 000000000..8b4b8596b --- /dev/null +++ b/modules/item/front/tags/index.spec.js @@ -0,0 +1,34 @@ +import './index.js'; +import crudModel from 'core/mocks/crud-model'; + +describe('Item', () => { + describe('Component vnItemTags', () => { + let $scope; + let controller; + + beforeEach(ngModule('item')); + + beforeEach(inject(($componentController, $rootScope) => { + $scope = $rootScope.$new(); + $scope.model = crudModel; + const $element = angular.element(''); + controller = $componentController('vnItemTags', {$element, $scope}); + })); + + describe('getHighestPriority', () => { + it('should return the highest priority value + 1 from the array', () => { + $scope.model.data = [{priority: 1}, {priority: 2}, {priority: 1}]; + let result = controller.getHighestPriority(); + + expect(result).toEqual(3); + }); + + it('should return 1 when there is no priority defined', () => { + $scope.model.data = []; + let result = controller.getHighestPriority(); + + expect(result).toEqual(1); + }); + }); + }); +}); diff --git a/modules/item/front/tax/index.html b/modules/item/front/tax/index.html new file mode 100644 index 000000000..78858704f --- /dev/null +++ b/modules/item/front/tax/index.html @@ -0,0 +1,43 @@ + + + + +
+ + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/modules/item/front/tax/index.js b/modules/item/front/tax/index.js new file mode 100644 index 000000000..2d70414ab --- /dev/null +++ b/modules/item/front/tax/index.js @@ -0,0 +1,41 @@ +import ngModule from '../module'; +import Section from 'salix/components/section'; + +export default class Controller extends Section { + $onInit() { + this.getTaxes(); + } + + getTaxes() { + let filter = { + fields: ['id', 'countryFk', 'taxClassFk'], + include: [{ + relation: 'country', + scope: {fields: ['name']} + }] + }; + + let url = `Items/${this.$params.id}/taxes`; + this.$http.get(url, {params: {filter}}).then(json => { + this.taxes = json.data; + }); + } + + submit() { + let data = []; + for (let tax of this.taxes) + data.push({id: tax.id, taxClassFk: tax.taxClassFk}); + + this.$.watcher.check(); + let url = `Items/updateTaxes`; + this.$http.post(url, data).then(() => { + this.$.watcher.notifySaved(); + this.$.watcher.updateOriginalData(); + }); + } +} + +ngModule.vnComponent('vnItemTax', { + template: require('./index.html'), + controller: Controller +}); diff --git a/modules/item/front/tax/index.spec.js b/modules/item/front/tax/index.spec.js new file mode 100644 index 000000000..9565a861d --- /dev/null +++ b/modules/item/front/tax/index.spec.js @@ -0,0 +1,64 @@ +import './index.js'; + +describe('Item', () => { + describe('Component vnItemTax', () => { + let $element; + let $stateParams; + let controller; + let $httpBackend; + + beforeEach(ngModule('item')); + + beforeEach(inject((_$httpBackend_, $rootScope, _$stateParams_, $compile) => { + $stateParams = _$stateParams_; + $stateParams.id = 1; + $httpBackend = _$httpBackend_; + + $httpBackend.whenRoute('GET', 'TaxClasses') + .respond([ + {id: 1, description: 'Reduced VAT', code: 'R'}, + {id: 2, description: 'General VAT', code: 'G'} + ]); + + $httpBackend.whenRoute('GET', 'Items/:id/taxes') + .respond([ + {id: 1, taxClassFk: 1} + ]); + + $element = $compile(` { + $element.remove(); + }); + + describe('getTaxes()', () => { + it('should perform a query to set the array of taxes into the controller', () => { + $httpBackend.flush(); + + expect(controller.taxes[0].id).toEqual(1); + expect(controller.taxes[0].taxClassFk).toEqual(1); + }); + }); + + describe('submit()', () => { + it('should perform a post to update taxes', () => { + jest.spyOn(controller.$.watcher, 'notifySaved'); + jest.spyOn(controller.$.watcher, 'updateOriginalData'); + + controller.$onInit(); + $httpBackend.flush(); + + controller.taxes.push({id: 3, description: 'General VAT', code: 'G'}); + + $httpBackend.whenPOST(`Items/updateTaxes`).respond(true); + controller.submit(); + $httpBackend.flush(); + + expect(controller.$.watcher.notifySaved).toHaveBeenCalledWith(); + expect(controller.$.watcher.updateOriginalData).toHaveBeenCalledWith(); + }); + }); + }); +}); diff --git a/modules/item/front/waste/index/index.html b/modules/item/front/waste/index/index.html new file mode 100644 index 000000000..7fb3b870e --- /dev/null +++ b/modules/item/front/waste/index/index.html @@ -0,0 +1,2 @@ + + diff --git a/modules/item/front/waste/index/index.js b/modules/item/front/waste/index/index.js new file mode 100644 index 000000000..86d9d3778 --- /dev/null +++ b/modules/item/front/waste/index/index.js @@ -0,0 +1,19 @@ +import ngModule from '../../module'; +import Section from 'salix/components/section'; +import './style.scss'; + +export default class Controller extends Section { + constructor($element, $) { + super($element, $); + } + + async $onInit() { + this.$state.go('item.index'); + window.location.href = 'https://grafana.verdnatura.es/d/TTNXQAxVk'; + } +} + +ngModule.vnComponent('vnItemWasteIndex', { + template: require('./index.html'), + controller: Controller +}); diff --git a/modules/item/front/waste/index/style.scss b/modules/item/front/waste/index/style.scss new file mode 100644 index 000000000..36fac3311 --- /dev/null +++ b/modules/item/front/waste/index/style.scss @@ -0,0 +1,27 @@ +@import "variables"; +@import "effects"; + +vn-item-waste-index, +vn-item-waste-detail { + .header { + padding: 12px 0 5px 0; + background-color: $color-bg; + font-size: 1.2rem; + margin-bottom: 10px; + } + + vn-table vn-th.waste-family, + vn-table vn-td.waste-family { + max-width: 64px; + width: 64px + } + + .hidden { + display: none; + } + + .arrow.hidden { + display: block; + transform: rotate(180deg); + } +} diff --git a/modules/item/front/waste/locale/es.yml b/modules/item/front/waste/locale/es.yml new file mode 100644 index 000000000..b9cd33dec --- /dev/null +++ b/modules/item/front/waste/locale/es.yml @@ -0,0 +1,4 @@ +Family: Familia +Percentage: Porcentaje +Dwindle: Mermas +Minimize/Maximize: Minimizar/Maximizar \ No newline at end of file diff --git a/modules/monitor/back/methods/sales-monitor/salesFilter.js b/modules/monitor/back/methods/sales-monitor/salesFilter.js index 927f49999..9f03c57a0 100644 --- a/modules/monitor/back/methods/sales-monitor/salesFilter.js +++ b/modules/monitor/back/methods/sales-monitor/salesFilter.js @@ -342,7 +342,6 @@ module.exports = Self => { 'CHECKED', 'PACKING', 'PACKED', - 'INVOICED', 'ON_DELIVERY', 'PREPARED', 'WAITING_FOR_PICKUP', @@ -350,10 +349,7 @@ module.exports = Self => { 'PRINTED_BACK', 'LAST_CALL', 'PREVIOUS_PREPARATION', - 'ASSISTED_PREPARATION', - 'BOARD', 'PRINTED STOWAWAY', - 'OK STOWAWAY', 'HALF_PACKED', 'COOLER_PREPARATION' ]}}; diff --git a/modules/order/back/methods/order/filter.js b/modules/order/back/methods/order/filter.js index ccc149958..2aeb1aac5 100644 --- a/modules/order/back/methods/order/filter.js +++ b/modules/order/back/methods/order/filter.js @@ -79,6 +79,7 @@ module.exports = Self => { const models = Self.app.models; const conn = Self.dataSource.connector; const myOptions = {}; + const userId = ctx.req.accessToken.userId; if (typeof options == 'object') Object.assign(myOptions, options); diff --git a/modules/supplier/back/methods/supplier/getWithPackaging.js b/modules/supplier/back/methods/supplier/getWithPackaging.js index 07e563412..41b080964 100644 --- a/modules/supplier/back/methods/supplier/getWithPackaging.js +++ b/modules/supplier/back/methods/supplier/getWithPackaging.js @@ -15,7 +15,7 @@ module.exports = Self => { Self.getWithPackaging = async options => { const models = Self.app.models; const myOptions = {}; - const oneYearAgo = new Date(); + const oneYearAgo = Date.vnNew(); oneYearAgo.setFullYear(oneYearAgo.getFullYear() - 1); if (typeof options == 'object') diff --git a/modules/supplier/back/methods/supplier/specs/getWithPackaging.spec.js b/modules/supplier/back/methods/supplier/specs/getWithPackaging.spec.js index bd30d7437..b6a780a10 100644 --- a/modules/supplier/back/methods/supplier/specs/getWithPackaging.spec.js +++ b/modules/supplier/back/methods/supplier/specs/getWithPackaging.spec.js @@ -1,26 +1,12 @@ const {models} = require('vn-loopback/server/server'); describe('Supplier getWithPackaging()', () => { + beforeAll.mockLoopBackContext(); it('should return a list of suppliers with an entry of type packaging', async() => { - const typeFk = 'packaging'; - const tx = await models.Supplier.beginTransaction({}); const myOptions = {transaction: tx}; try { - const entry = await models.Entry.findOne( - { - where: { - id: 1 - }, - myOptions - }); - - await entry.updateAttributes({ - typeFk: typeFk, - created: new Date() - }); - const result = await models.Supplier.getWithPackaging(myOptions); expect(result.length).toEqual(1); diff --git a/modules/ticket/back/methods/expedition/deleteExpeditions.js b/modules/ticket/back/methods/expedition/deleteExpeditions.js index 75993a485..267811d25 100644 --- a/modules/ticket/back/methods/expedition/deleteExpeditions.js +++ b/modules/ticket/back/methods/expedition/deleteExpeditions.js @@ -52,7 +52,8 @@ module.exports = Self => { const deletedExpedition = await models.Expedition.destroyById(expeditionId); deletedExpeditions.push(deletedExpedition); - } catch (e) { + } catch (error) { + console.error('error: ', error); notDeletedExpeditions.push(expeditionId); } } diff --git a/modules/ticket/back/methods/ticket/filter.js b/modules/ticket/back/methods/ticket/filter.js index d3e53c702..c61223470 100644 --- a/modules/ticket/back/methods/ticket/filter.js +++ b/modules/ticket/back/methods/ticket/filter.js @@ -265,7 +265,8 @@ module.exports = Self => { FROM sale s2 JOIN item i2 ON i2.id = s2.itemFk WHERE s2.ticketFk = t.id - ) AS packing + ) AS packing, + c.credit FROM ticket t LEFT JOIN invoiceOut io ON t.refFk = io.ref LEFT JOIN zone z ON z.id = t.zoneFk diff --git a/modules/ticket/back/models/saleGroup.json b/modules/ticket/back/models/saleGroup.json index aa78b4167..5f432b514 100644 --- a/modules/ticket/back/models/saleGroup.json +++ b/modules/ticket/back/models/saleGroup.json @@ -29,6 +29,11 @@ "type": "belongsTo", "model": "Parking", "foreignKey": "parkingFk" + }, + "state": { + "type": "belongsTo", + "model": "State", + "foreignKey": "stateFk" } } -} +} \ No newline at end of file diff --git a/modules/worker/back/methods/worker-dms/filter.js b/modules/worker/back/methods/worker-dms/filter.js index 597084e60..240a905d2 100644 --- a/modules/worker/back/methods/worker-dms/filter.js +++ b/modules/worker/back/methods/worker-dms/filter.js @@ -86,30 +86,30 @@ module.exports = Self => { 'Tipo Documento': 'description', 'Stored on': 'created', 'Document ID': 'id', - 'URL': 'download', + 'URL': 'url', 'Stored by': 'name', 'Estado': 'state' }; workerDocuware = - await models.Docuware.getById('hr', worker.lastName + ' ' + worker.firstName, docuwareParse) ?? []; - const url = (await Self.app.models.Url.getUrl('docuware')) + 'WebClient'; + await models.Docuware.getById('hr', worker?.lastName + ' ' + worker?.firstName, docuwareParse) ?? []; + for (document of workerDocuware) { - const docuwareId = document.id; + const {id: documentId, dmsFk} = document; const defaultData = { - id: docuwareId, + id: documentId, workerFk: id, - dmsFk: docuwareId, + dmsFk: dmsFk, dms: { - id: docuwareId, - file: docuwareId + '.pdf', + id: documentId, + file: dmsFk + '.pdf', isDocuware: true, hasFile: false, - reference: worker.fi, - dmsFk: docuwareId, - url, + reference: worker?.fi, + dmsFk: dmsFk, + url: document.url, + download: `WorkerDms/${document.dmsFk}/docuwareDownload`, description: document.description + ' - ' + document.state, - download: document.download, created: document.created, dmsType: {name: 'Docuware'}, worker: {id: null, user: {name: document.name}}, diff --git a/modules/worker/back/methods/worker-time-control-mail/checkInbox.js b/modules/worker/back/methods/worker-time-control-mail/checkInbox.js index 4d9f98cc3..688cbb634 100644 --- a/modules/worker/back/methods/worker-time-control-mail/checkInbox.js +++ b/modules/worker/back/methods/worker-time-control-mail/checkInbox.js @@ -16,7 +16,7 @@ module.exports = Self => { }); Self.checkInbox = async() => { - let imapConfig = await Self.app.models.WorkerTimeControlParams.findOne(); + let imapConfig = await Self.app.models.WorkerTimeControlConfig.findOne(); let imap = new Imap({ user: imapConfig.mailUser, password: imapConfig.mailPass, diff --git a/modules/worker/back/methods/worker/createAbsence.js b/modules/worker/back/methods/worker/createAbsence.js index 0397886cf..419659083 100644 --- a/modules/worker/back/methods/worker/createAbsence.js +++ b/modules/worker/back/methods/worker/createAbsence.js @@ -58,9 +58,8 @@ module.exports = Self => { if (!isSubordinate || (isSubordinate && userId == id && !isTeamBoss)) throw new UserError(`You don't have enough privileges`); - const labour = await models.WorkerLabour.findById(args.businessFk, { - include: {relation: 'department'} - }, myOptions); + const labour = await models.WorkerLabour.findById(args.businessFk, + {fields: ['started', 'ended', 'businessFk']}, myOptions); if (args.dated < labour.started || (labour.ended != null && args.dated > labour.ended)) throw new UserError(`The contract was not active during the selected date`); @@ -87,7 +86,8 @@ module.exports = Self => { `SELECT COUNT(*) halfHolidayCounter FROM vn.calendar c JOIN vn.business b ON b.id = c.businessFk - WHERE c.dayOffTypeFk = 6 + JOIN vn.absenceType at ON at.id = c.dayOffTypeFk + WHERE at.code = 'halfHoliday' AND b.workerFk = ? AND c.dated BETWEEN util.firstDayOfYear(?) AND LAST_DAY(DATE_ADD(?, INTERVAL 12 - MONTH(?) MONTH))`, [id, date, now, now]); @@ -119,25 +119,23 @@ module.exports = Self => { dated: args.dated }, myOptions); - const department = labour.department(); - if (department && department.notificationEmail) { - const absenceType = await models.AbsenceType.findById(args.absenceTypeId, null, myOptions); - const account = await models.VnUser.findById(userId, null, myOptions); - const subordinated = await models.VnUser.findById(id, null, myOptions); - const url = await Self.app.models.Url.getUrl(); - const body = $t('Created absence', { - author: account.nickname, - employee: subordinated.nickname, - absenceType: absenceType.name, - dated: formatDate(args.dated), - workerUrl: `${url}worker/${id}/calendar` - }); - await models.Mail.create({ - subject: $t('Absence change notification on the labour calendar'), - body: body, - receiver: department.notificationEmail - }, myOptions); - } + const account = await models.VnUser.findById(userId, null, myOptions); + const subordinated = await models.VnUser.findById(id, null, myOptions); + const worker = await models.Worker.findById(subordinated.id, null, myOptions); + const departmentBoss = await models.VnUser.findById(worker.bossFk, null, myOptions); + const url = await Self.app.models.Url.getUrl(); + const body = $t('Created absence', { + author: account.nickname, + employee: subordinated.nickname, + absenceType: absenceType.name, + dated: formatDate(args.dated), + workerUrl: `${url}worker/${id}/calendar` + }); + await models.Mail.create({ + subject: $t('Absence change notification on the labour calendar'), + body: body, + receiver: departmentBoss.email + }, myOptions); if (tx) await tx.commit(); diff --git a/modules/worker/back/model-config.json b/modules/worker/back/model-config.json index 7bfc667ac..10e55d956 100644 --- a/modules/worker/back/model-config.json +++ b/modules/worker/back/model-config.json @@ -113,9 +113,6 @@ "WorkerTimeControlConfig": { "dataSource": "vn" }, - "WorkerTimeControlParams": { - "dataSource": "vn" - }, "WorkerTimeControlMail": { "dataSource": "vn" }, @@ -125,6 +122,15 @@ "Locker": { "dataSource": "vn" }, + "WorkerIrpf": { + "dataSource": "vn" + }, + "DisabilityGrade": { + "dataSource": "vn" + }, + "WorkerRelative": { + "dataSource": "vn" + }, "MedicalReview": { "dataSource": "vn" }, diff --git a/modules/worker/back/models/disability-grade.json b/modules/worker/back/models/disability-grade.json new file mode 100644 index 000000000..506138225 --- /dev/null +++ b/modules/worker/back/models/disability-grade.json @@ -0,0 +1,18 @@ +{ + "name": "DisabilityGrade", + "base": "VnModel", + "options": { + "mysql": { + "table": "disabilityGrade" + } + }, + "properties": { + "id": { + "id": true, + "type": "number" + }, + "description": { + "type": "string" + } + } +} diff --git a/modules/worker/back/models/worker-irpf.json b/modules/worker/back/models/worker-irpf.json new file mode 100644 index 000000000..65f72a1fd --- /dev/null +++ b/modules/worker/back/models/worker-irpf.json @@ -0,0 +1,55 @@ +{ + "name": "WorkerIrpf", + "description": "Model 145 IRPF", + "base": "VnModel", + "options": { + "mysql": { + "table": "workerIrpf" + } + }, + "properties": { + "workerFk": { + "type": "number", + "id": 1, + "description": "Identifier" + }, + "spouseNif": { + "type": "string" + }, + "geographicMobilityDate": { + "type": "date" + }, + "disabilityGradeFk": { + "type" : "number" + }, + "isDependend": { + "type" : "number" + }, + "familySituation": { + "type" : "number" + }, + "spousePension": { + "type" : "number" + }, + "childPension": { + "type" : "number" + }, + "hasHousingPaymentBefore": { + "type" : "number" + }, + "hasHousingPaymentAfter": { + "type" : "number" + }, + "updated": { + "type" : "date" + } + + }, + "relations": { + "disabilityGrade": { + "type": "belongsTo", + "model": "disabilityGrade", + "foreignKey": "disabilityGradeFk" + } + } +} diff --git a/modules/worker/back/models/worker-relatives.json b/modules/worker/back/models/worker-relatives.json new file mode 100644 index 000000000..532a9446c --- /dev/null +++ b/modules/worker/back/models/worker-relatives.json @@ -0,0 +1,53 @@ +{ + "name": "WorkerRelative", + "description": "Model 145 IRPF", + "base": "VnModel", + "options": { + "mysql": { + "table": "workerRelatives" + } + }, + "properties": { + "id": { + "type": "number", + "id": true, + "description": "Identifier" + }, + "workerFk": { + "type": "number" + }, + "isDescendant": { + "type": "number" + }, + "disabilityGradeFk": { + "type" : "number" + }, + "birthed": { + "type" : "number" + }, + "adoptionYear": { + "type" : "number" + }, + "isDependend": { + "type" : "boolean" + }, + "isJointCustody": { + "type" : "boolean" + }, + "updated": { + "type" : "date" + } + }, + "relations": { + "disabilityGrade": { + "type": "belongsTo", + "model": "disabilityGrade", + "foreignKey": "disabilityGradeFk" + }, + "worker": { + "type": "belongsTo", + "model": "VnUser", + "foreignKey": "workerFK" + } + } +} diff --git a/modules/worker/back/models/worker-time-control-config.json b/modules/worker/back/models/worker-time-control-config.json index b96e2ae3b..53f1a14ea 100644 --- a/modules/worker/back/models/worker-time-control-config.json +++ b/modules/worker/back/models/worker-time-control-config.json @@ -11,6 +11,15 @@ "id": true, "type": "number" }, + "mailPass": { + "type": "string" + }, + "mailHost": { + "type": "string" + }, + "mailUser": { + "type": "string" + }, "breakTime": { "type": "number" }, @@ -23,5 +32,13 @@ "teleworkingStartBreakTime": { "type": "number" } - } + }, + "acls": [ + { + "accessType": "READ", + "principalType": "ROLE", + "principalId": "$everyone", + "permission": "ALLOW" + } + ] } diff --git a/modules/worker/back/models/worker-time-control-params.json b/modules/worker/back/models/worker-time-control-params.json deleted file mode 100644 index 14cabbfb0..000000000 --- a/modules/worker/back/models/worker-time-control-params.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "name": "WorkerTimeControlParams", - "description": "imap config", - "base": "VnModel", - "options": { - "mysql": { - "table": "workerTimeControlParams" - } - }, - "properties": { - "mailHost": { - "type": "string" - }, - "mailUser": { - "type": "string" - }, - "mailPass": { - "type": "string" - }, - "mailSuccessFolder": { - "type": "string" - }, - "mailErrorFolder": { - "type": "string" - } - }, - "acls": [ - { - "accessType": "READ", - "principalType": "ROLE", - "principalId": "$everyone", - "permission": "ALLOW" - } - ] -} diff --git a/modules/worker/back/models/worker.json b/modules/worker/back/models/worker.json index 5c3b95fe6..705851963 100644 --- a/modules/worker/back/models/worker.json +++ b/modules/worker/back/models/worker.json @@ -132,6 +132,16 @@ "type": "hasMany", "model": "WorkerTimeControlMail", "foreignKey": "workerFk" + }, + "irpf": { + "type": "hasMany", + "model": "WorkerIrpf", + "foreignKey": "workerFk" + }, + "workerRelative": { + "type": "hasMany", + "model": "WorkerRelative", + "foreignKey": "workerFK" } }, "acls": [ @@ -317,4 +327,4 @@ ] } } -} \ No newline at end of file +} diff --git a/modules/zone/back/methods/zone/deleteZone.js b/modules/zone/back/methods/zone/deleteZone.js index ffe23c9b9..7432475b3 100644 --- a/modules/zone/back/methods/zone/deleteZone.js +++ b/modules/zone/back/methods/zone/deleteZone.js @@ -40,8 +40,7 @@ module.exports = Self => { try { const filter = { where: { - zoneFk: id, - shipped: {gte: today} + zoneFk: id }, include: { relation: 'ticketState', diff --git a/myt.config.yml b/myt.config.yml index 25f94f1bd..209686fd4 100755 --- a/myt.config.yml +++ b/myt.config.yml @@ -258,7 +258,6 @@ localFixtures: - itemFamily - itemLog - itemShelving - - itemShelvingLog - itemShelvingSale - itemTag - itemTaxCountry @@ -385,7 +384,6 @@ localFixtures: - workerTimeControl - workerTimeControlConfig - workerTimeControlMail - - workerTimeControlParams - zone - zoneAgencyMode - zoneClosure diff --git a/print/templates/reports/buy-label-barcode/assets/css/style.css b/print/templates/reports/buy-label-barcode/assets/css/style.css index fabecd28e..ce1924878 100644 --- a/print/templates/reports/buy-label-barcode/assets/css/style.css +++ b/print/templates/reports/buy-label-barcode/assets/css/style.css @@ -32,6 +32,11 @@ td { .md-txt { font-size: 26px; } +.lg-txt { + font-size: 40px; + padding: 0px; + line-height: 1; +} .xl-txt { font-size: 50px; } diff --git a/print/templates/reports/buy-label-barcode/buy-label-barcode.html b/print/templates/reports/buy-label-barcode/buy-label-barcode.html index f14f0b70b..ebddb60ec 100644 --- a/print/templates/reports/buy-label-barcode/buy-label-barcode.html +++ b/print/templates/reports/buy-label-barcode/buy-label-barcode.html @@ -36,12 +36,12 @@ - +
- {{buy.itemFk}} + {{formatNumber(buy.itemFk)}}
- +
{{`${(packing || buy.packing)} x ${buy.stems || ''}`}}
@@ -56,7 +56,7 @@ {{'LAID'}}
- {{buy.entryFk}} + {{formatNumber(buy.entryFk)}}
@@ -73,17 +73,17 @@ - +
- {{buy.buyFk}} + {{formatNumber(buy.buyFk)}}
- +
{{date}}
- +
{{`${buy.labelNum}/${buy.quantity / (packing || buy.packing)}`}}
diff --git a/print/templates/reports/buy-label-barcode/buy-label-barcode.js b/print/templates/reports/buy-label-barcode/buy-label-barcode.js index 8c39a7046..37b618f09 100755 --- a/print/templates/reports/buy-label-barcode/buy-label-barcode.js +++ b/print/templates/reports/buy-label-barcode/buy-label-barcode.js @@ -9,7 +9,7 @@ module.exports = { this.date = Date.vnNew(); this.buys = await this.rawSqlFromDef('buy', [this.copies || 1, this.id]); if (!this.buys.length) throw new UserError(`Empty data source`); - this.date = moment(this.date).format('WW/E'); + this.date = moment(this.date).format('WW/DD'); }, methods: { getBarcode(data) { @@ -20,11 +20,14 @@ module.exports = { xmlDocument: document, format: 'code128', displayValue: false, - width: 3.8, - height: 85, + width: 3.5, + height: 75, margin: 0 }); return new XMLSerializer().serializeToString(svgNode); + }, + formatNumber(number) { + return new Intl.NumberFormat('es-ES', {maximumFractionDigits: 0}).format(number); } }, props: { diff --git a/print/templates/reports/buy-label-qr/assets/css/style.css b/print/templates/reports/buy-label-qr/assets/css/style.css index 0e288704b..36db0fdef 100644 --- a/print/templates/reports/buy-label-qr/assets/css/style.css +++ b/print/templates/reports/buy-label-qr/assets/css/style.css @@ -34,6 +34,9 @@ html { background-color: black; color: white; } +.sm-txt { + font-size: 18px; +} .md-txt { font-size: 20px; } diff --git a/print/templates/reports/buy-label-qr/buy-label-qr.html b/print/templates/reports/buy-label-qr/buy-label-qr.html index 00e64b57d..00ede5488 100644 --- a/print/templates/reports/buy-label-qr/buy-label-qr.html +++ b/print/templates/reports/buy-label-qr/buy-label-qr.html @@ -11,8 +11,8 @@ - - {{buy.buyFk}} + + {{formatNumber(buy.buyFk)}} @@ -28,7 +28,7 @@
- {{buy.itemFk}} + {{formatNumber(buy.itemFk)}}
@@ -78,8 +78,7 @@
{{'LAID'}}
-
- {{buy.entryFk}} +
@@ -103,7 +102,7 @@
- Entrada: {{buy.entryFk}} + Entrada: {{formatNumber(buy.entryFk)}}
diff --git a/print/templates/reports/buy-label-qr/buy-label-qr.js b/print/templates/reports/buy-label-qr/buy-label-qr.js index 74470ad6d..614e40816 100755 --- a/print/templates/reports/buy-label-qr/buy-label-qr.js +++ b/print/templates/reports/buy-label-qr/buy-label-qr.js @@ -9,7 +9,7 @@ module.exports = { this.buys = await this.rawSqlFromDef('buy', [this.copies || 1, this.id]); if (!this.buys.length) throw new UserError(`Empty data source`); this.qr = await this.getQr(this.buys[0].buyFk); - this.date = moment(this.date).format('WW/E'); + this.date = moment(this.date).format('WW/DD'); }, methods: { getQr(data) { @@ -24,6 +24,9 @@ module.exports = { margin: 0, errorCorrectionLevel: 'L' }); + }, + formatNumber(number) { + return new Intl.NumberFormat('es-ES', {maximumFractionDigits: 0}).format(number); } }, props: { diff --git a/print/templates/reports/entry-order/entry-order.html b/print/templates/reports/entry-order/entry-order.html index 90a95481f..d3f909d4d 100644 --- a/print/templates/reports/entry-order/entry-order.html +++ b/print/templates/reports/entry-order/entry-order.html @@ -62,7 +62,7 @@ x {{buy.packing}} {{buy.name}} - referencia de prueba + {{buy.comment}}
{{buy.tag5}}→ {{buy.value5}}