diff --git a/CHANGELOG.md b/CHANGELOG.md index 73ebecabc..67ffe9f12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,134 @@ +# Version 25.00 - 2025-01-14 + +### Added 🆕 + +- feat: refs #7235 add serialType parameter to getInvoiceDate and implement corresponding tests by:jgallego +- feat: refs #7301 update lastEntriesFilter to include landedDate and enhance test cases (origin/7301-removeRedundantInventories) by:pablone +- feat: refs #7880 error code and translations by:ivanm +- feat: refs #7924 add isCustomInspectionRequired field to item and update related logic by:jgallego +- feat: refs #8167 update canBeInvoiced method to include active status check and improve test cases by:jgallego +- feat: refs #8167 update locale and improve invoicing logic with error handling by:jgallego +- feat: refs #8246 added relation for the front's new field by:Jon +- feat: refs #8266 added itemFk and needed fixtures by:jtubau +- feat: refs #8324 country unique by:Carlos Andrés + +### Changed 📦 + + +### Fixed 🛠️ + +- feat: refs #8266 added itemFk and needed fixtures by:jtubau +- fix: add isCustomInspectionRequired column to item table for customs inspection indication by:jgallego +- fix: canBeInvoiced only in makeInvoice by:alexm +- fix: hotFix getMondayWeekYear by:alexm +- fix: refs #6598 update ACL property assignment by:jorgep +- fix: refs #6861 refs#6861 addPrevOK by:sergiodt +- fix: refs #7301 remove debug console log and update test cases in lastEntriesFilter by:pablone +- fix: refs #7301 update SQL fixtures and improve lastEntriesFilter logic by:pablone + +# Version 24.52 - 2024-01-07 + +### Added 🆕 + +- chore: pullinfo by:alexm +- chore: refs #8002 drop comments by:jorgep +- chore: refs #8002 drop useless code by:jorgep +- feat: added translations and show error in item-type by:Jon +- feat: modified data to be equal as the updated back by:Jon +- feat: refs #4460 invoiceIn refund by:Carlos Andrés +- feat: refs #4466 invoiceIn refund by:Carlos Andrés +- feat: refs #6583 add new opt in where builder by:jorgep +- feat: refs #6583 add tests by:jorgep +- feat: refs #6583 retrieve cloned sale by:jorgep +- feat: refs #6583 rollback by:jorgep +- feat: refs #7301 add inventory-config and acl by:pablone +- feat: refs #7301 update SQL fixtures and enhance lastEntriesFilter logic by:pablone +- feat: refs #7882 Added locationiq service by:guillermo +- feat: refs #7882 Added osrm service by:guillermo +- feat: refs #7882 Added tests by:guillermo +- feat: refs #7882 Fixed problems osrm service by:guillermo +- feat: refs #7882 Osrm service by:guillermo +- feat: refs #7882 Reequested changes by:guillermo +- feat: refs #7882 Requested changes by:guillermo +- feat: refs #7936 add back test for updateInvoiceIn by:jorgep +- feat: refs #7936 add company filter by:jorgep +- feat: refs #7936 add currency check to updateInvoiceIn by:jorgep +- feat: refs #7936 add currency handling in invoiceIn trigger by:jorgep +- feat: refs #7936 add locale by:jorgep +- feat: refs #7936 add minimum due date by:jorgep +- feat: refs #7936 add reference rates for currency in fixtures by:jorgep +- feat: refs #7936 add save validation by:jorgep +- feat: refs #7936 add SiiTypeInvoiceIn model and update invoice correction logic by:jorgep +- feat: refs #7936 add tests for invoiceIn by:jorgep +- feat: refs #7936 add tests for invoiceIn filter by:jorgep +- feat: refs #7936 add validation to InvoiceIn & InvoiceInTax by:jorgep +- feat: refs #7936 return country code & is vies fields by:jorgep +- feat: refs #8002 adjust to lilium by:jorgep +- feat: refs #8002 drop support btn by:jorgep +- feat: refs #8174 Changed datatype incompatibility access by:guillermo +- feat: refs #8174 Created table sim by:guillermo +- feat: refs #8174 create table simsupplier by:Jbreso +- feat: refs #8174 fix by:Jbreso +- feat: refs#8174 simSupplier by:Jbreso +- feat: refs #8190 entry_getCommission by:robert +- feat: refs #8190 entry_getCommission change request by:robert +- feat: refs #8218 Added time and code in mistakeType by:guillermo +- feat: refs #8293 include zone data by:Jtubau +- refactor: refs #6583 entry report table style by:jorgep + +### Changed 📦 + +- refactor: refs #6583 entry report table style by:jorgep +- refactor: refs #6583 use warehouseId var by:jorgep +- refactor: refs #7301 update entry and item filter tests to validate results against specific criteria by:pablone +- refactor: refs #7882 Added ACL's by:guillermo +- refactor: refs #7882 Deleted quadminds files by:guillermo +- refactor: refs #7936 add transaction & tests by:jorgep +- refactor: refs #7936 remove old trigger and add isRaid column to travel table by:jorgep +- refactor: refs #7936 remove schema by:jorgep +- refactor: refs #8002 use loop wip by:jorgep +- refactor: refs #8004 simplify SQL query by removing redundant aliases by:pablone +- refactor: refs #8262 Deprecated inventoryFailure by:guillermo +- refactor: refs #8266 changed expedition item name by:Jtubau +- refactor: refs #8272 delete bi.rotacion by:ivanm + +### Fixed 🛠️ + +- feat: refs #7301 update SQL fixtures and enhance lastEntriesFilter logic by:pablone +- feat: refs #7936 add reference rates for currency in fixtures by:jorgep +- feat: refs #8174 fix by:Jbreso +- fix: 8174 pasar PIN a CHAR by:Jbreso +- fix: monitorPayMethodFilter by:carlossa +- fix: refs #6389 back by:carlossa +- fix: refs #6389 filter by:carlossa +- fix: refs #6389 packing by:carlossa +- fix: refs #6389 saleMonitor filter by:carlossa +- fix: refs #6389 salesFilter by:carlossa +- fix: refs #6583 drop focus by:jorgep +- fix: refs #6583 update onlyWithDestination logic to handle null values correctly by:jorgep +- fix: refs #7028 fix confirm deny by:carlossa +- fix: refs #7028 fix pr by:carlossa +- fix: refs #7028 fix tback findById by:carlossa +- fix: refs #7028 fix userError by:carlossa +- fix: refs #7028 remove ifs by:carlossa +- fix: refs #7028 requesterId fix by:carlossa +- fix: refs #7028 requesterId fix salesPerson by:carlossa +- fix: refs #7031 fix vnPrice by:carlossa +- fix: refs #7031 remove check by:carlossa +- fix: refs #7301 update ACL insertion to use INSERT IGNORE and refine property value by:pablone +- fix: refs #7936 add IF NOT EXISTS to isRaid column in travel table by:jorgep +- fix: refs #7936 change type by:jorgep +- fix: refs #7936 check if insert in hook & change test description by:jorgep +- fix: refs #7936 conflicts by:jorgep +- fix: refs #7936 locale by:jorgep +- fix: refs #7936 update Spanish locale for SII terms by:jorgep +- fix: refs #8174 fix by:Jbreso +- fix: refs#8174 fix by:Jbreso +- fix: refs8174 pasar a char el PIN by:Jbreso +- fix: refs #8174 Version by:guillermo +- fix: refs #8251 add eng template by:carlossa +- fix: refs #8315 fixture claimDevelopment by:alexm + # Version 24.48 - 2024-11-25 ### Added 🆕 diff --git a/back/methods/chat/sendCheckingPresence.js b/back/methods/chat/sendCheckingPresence.js index 7ab5d63fe..955ed0240 100644 --- a/back/methods/chat/sendCheckingPresence.js +++ b/back/methods/chat/sendCheckingPresence.js @@ -27,38 +27,46 @@ module.exports = Self => { }); Self.sendCheckingPresence = async(ctx, recipientId, message) => { - if (!recipientId) return false; - const models = Self.app.models; - const userId = ctx.req.accessToken.userId; - const sender = await models.VnUser.findById(userId, {fields: ['id']}); - const recipient = await models.VnUser.findById(recipientId, null); - - // Prevent sending messages to yourself - if (recipientId == userId) return false; - if (!recipient) - throw new Error(`Could not send message "${message}" to worker id ${recipientId} from user ${userId}`); - - if (!isProduction()) - message = `[Test:Environment to user ${userId}] ` + message; - - const chat = await models.Chat.create({ - senderFk: sender.id, - recipient: `@${recipient.name}`, - dated: Date.vnNew(), - checkUserStatus: 1, - message: message, - status: 'sending', - attempts: 0 - }); - try { - await Self.sendCheckingUserStatus(chat); - await Self.updateChat(chat, 'sent'); - } catch (error) { - await Self.updateChat(chat, 'error', error); - } + const models = Self.app.models; + const sender = await models.VnUser.findById(userId, {fields: ['id']}); + const error = `Could not send message from user ${userId}`; - return true; + if (!recipientId) throw new Error(error); + const recipient = await models.VnUser.findById(recipientId, null); + if (!recipient) + throw new Error(error); + + // Prevent sending messages to yourself + if (recipientId == userId) return false; + + if (!isProduction()) + message = `[Test:Environment to user ${userId}] ` + message; + + const chat = await models.Chat.create({ + senderFk: sender.id, + recipient: `@${recipient.name}`, + dated: Date.vnNew(), + checkUserStatus: 1, + message: message, + status: 'sending', + attempts: 0 + }); + + try { + await Self.sendCheckingUserStatus(chat); + await Self.updateChat(chat, 'sent'); + } catch (error) { + await Self.updateChat(chat, 'error', error); + } + + return true; + } catch (e) { + await Self.rawSql(` + INSERT INTO util.debug (variable, value) + VALUES ('sendCheckingPresence_error', ?) + `, [`User: ${userId}, recipient: ${recipientId}, message: ${message}, error: ${e}`]); + } }; }; diff --git a/back/methods/collection/getTickets.js b/back/methods/collection/getTickets.js index 677c9e444..85d1111df 100644 --- a/back/methods/collection/getTickets.js +++ b/back/methods/collection/getTickets.js @@ -40,6 +40,7 @@ module.exports = Self => { const sales = await Self.rawSql(` SELECT s.ticketFk, + NULL ticketOrder, sgd.saleGroupFk, s.id saleFk, s.itemFk, @@ -83,6 +84,7 @@ module.exports = Self => { GROUP BY s.id, ish.id, p.code, p2.code UNION ALL SELECT s.ticketFk, + DENSE_RANK() OVER (ORDER BY ss.id), sgd.saleGroupFk, s.id saleFk, s.itemFk, diff --git a/back/methods/osrm-config/optimize.js b/back/methods/osrm-config/optimize.js new file mode 100644 index 000000000..e0412c74c --- /dev/null +++ b/back/methods/osrm-config/optimize.js @@ -0,0 +1,112 @@ +const UserError = require('vn-loopback/util/user-error'); +const axios = require('axios'); + +module.exports = Self => { + Self.remoteMethod('optimize', { + description: 'Return optimized coords', + accessType: 'READ', + accepts: [{ + arg: 'addressIds', + type: 'array', + required: true + }, { + arg: 'firstAddressId', + type: 'number', + required: false + }, { + arg: 'lastAddressId', + type: 'number', + required: false + }], + returns: { + type: 'object', + root: true + }, + http: { + path: `/optimize`, + verb: 'GET' + } + }); + + Self.optimize = async(addressIds, firstAddressId, lastAddressId) => { + const models = Self.app.models; + try { + const osrmConfig = await models.OsrmConfig.findOne(); + if (!osrmConfig) throw new UserError(`OSRM service is not configured`); + + let coords = []; + if (firstAddressId) { + const address = await models.Address.findById(firstAddressId); + if (address.latitude && address.longitude) { + coords.push({ + addressId: address.id, + latitude: address.latitude.toFixed(6), + longitude: address.longitude.toFixed(6) + }); + } + } + + for (const addressId of addressIds) { + const address = await models.Address.findById(addressId); + if (address.latitude && address.longitude) { + coords.push({ + addressId, + latitude: address.latitude.toFixed(6), + longitude: address.longitude.toFixed(6) + }); + } + } + + if (lastAddressId) { + const firstAddress = await models.Address.findById(lastAddressId); + if (firstAddress.latitude && firstAddress.longitude) { + coords.push({ + addressId: firstAddress.id, + latitude: firstAddress.latitude.toFixed(6), + longitude: firstAddress.longitude.toFixed(6) + }); + } + } + + if (!coords.length) throw new UserError('No address has coordinates'); + + const concatCoords = coords + .map(coord => `${coord.longitude},${coord.latitude}`) + .join(';'); + const response = await axios.post(` + ${osrmConfig.url}/trip/v1/driving/${concatCoords}?source=first&destination=last&roundtrip=true + `); + const tolerance = osrmConfig.tolerance; + for (const waypoint of response.data.waypoints) { + const longitude = waypoint.location[0]; + const latitude = waypoint.location[1]; + + const matchedAddress = coords.find(coord => + coord.position === undefined && + Math.abs(coord.latitude - latitude) <= tolerance && + Math.abs(coord.longitude - longitude) <= tolerance + ); + if (matchedAddress) + matchedAddress.position = waypoint.waypoint_index; + } + coords.sort((a, b) => { + const posA = a.position !== undefined ? a.position : Infinity; + const posB = b.position !== undefined ? b.position : Infinity; + return posA - posB; + }); + + return coords; + } catch (err) { + switch (err.response?.data?.code) { + case 'NoTrips': + throw new UserError('No trips found because input coordinates are not connected'); + case 'NotImplemented': + throw new UserError('This request is not supported'); + case 'InvalidOptions': + throw new UserError('Invalid options or too many coordinates'); + default: + throw err; + } + } + }; +}; diff --git a/back/methods/osrm-config/specs/optimize.spec.js b/back/methods/osrm-config/specs/optimize.spec.js new file mode 100644 index 000000000..9f2adccc6 --- /dev/null +++ b/back/methods/osrm-config/specs/optimize.spec.js @@ -0,0 +1,33 @@ +const models = require('vn-loopback/server/server').models; + +describe('osrmConfig optimize()', function() { + it('should send coords, receive OSRM response, and return a correctly ordered result', async function() { + const result = await models.OsrmConfig.optimize([4, 3], 1, 2); + + // Verifications + expect(Array.isArray(result)).toBe(true); + expect(result.length).toBe(4); + + // Check the order + expect(result[0].addressId).toBe(1); + expect(result[1].addressId).toBe(4); + expect(result[2].addressId).toBe(3); + expect(result[3].addressId).toBe(2); + + // Check the coordinates format + expect(result[0].latitude).toBe('10.111111'); + expect(result[0].longitude).toBe('-74.111111'); + }); + + it('should throw an error if no addresses are provided', async function() { + let error; + try { + await models.OsrmConfig.optimize([], null); + } catch (e) { + error = e; + } + + expect(error).toBeDefined(); + expect(error.message).toBe('No address has coordinates'); + }); +}); diff --git a/back/methods/vn-user/acls.js b/back/methods/vn-user/acls.js index 7da75ed2c..347cfa426 100644 --- a/back/methods/vn-user/acls.js +++ b/back/methods/vn-user/acls.js @@ -19,7 +19,7 @@ module.exports = Self => { if (acl.principalType == 'ROLE' && acl.permission == 'ALLOW') { const staticAcl = { model: model.name, - property: '*', + property: acl.property, accessType: acl.accessType, permission: acl.permission, principalType: acl.principalType, diff --git a/back/methods/vn-user/update-user.js b/back/methods/vn-user/update-user.js index 2bb390cf9..32bad0f17 100644 --- a/back/methods/vn-user/update-user.js +++ b/back/methods/vn-user/update-user.js @@ -22,7 +22,7 @@ module.exports = Self => { description: 'The user email' }, { arg: 'lang', - type: 'string', + type: 'any', description: 'The user lang' }, { arg: 'twoFactor', diff --git a/back/model-config.json b/back/model-config.json index c1682f29a..2ced867f7 100644 --- a/back/model-config.json +++ b/back/model-config.json @@ -88,6 +88,9 @@ "Language": { "dataSource": "vn" }, + "OsrmConfig": { + "dataSource": "vn" + }, "Machine": { "dataSource": "vn" }, diff --git a/back/models/osrm-config.js b/back/models/osrm-config.js new file mode 100644 index 000000000..f738f305c --- /dev/null +++ b/back/models/osrm-config.js @@ -0,0 +1,4 @@ +module.exports = Self => { + require('../methods/osrm-config/optimize')(Self); +}; + diff --git a/back/models/osrm-config.json b/back/models/osrm-config.json new file mode 100644 index 000000000..ae712ba05 --- /dev/null +++ b/back/models/osrm-config.json @@ -0,0 +1,24 @@ +{ + "name": "OsrmConfig", + "base": "VnModel", + "options": { + "mysql": { + "table": "osrmConfig" + } + }, + "properties": { + "id": { + "type": "number", + "id": true, + "required": true + }, + "url": { + "type": "string", + "required": true + }, + "tolerance": { + "type": "number", + "required": false + } + } +} diff --git a/db/dump/.dump/data.sql b/db/dump/.dump/data.sql index cd978e4a8..b95890b0d 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','11377','d3fe5098277c3935c434838b53facb271f84ebec','2024-12-10 07:22:33','11379'); +INSERT INTO `version` VALUES ('vn-database','11391','43edb1f82e88dcc44eedc8501b93c1fac66d71e9','2025-01-14 07:32:09','11407'); 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); @@ -1078,11 +1078,13 @@ INSERT INTO `versionLog` VALUES ('vn-database','11315','00-firstScript.sql','jen 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','11320','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2025-01-14 07:32:07',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','11322','00-entryAcl.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-12-10 07:20:04',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','11327','00-firstScript.sql','jenkins@db-proxy1.servers.dc.verdnatura.es','2025-01-07 07:46:24',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','11332','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-12-10 07:20:04',NULL,NULL); @@ -1110,6 +1112,7 @@ INSERT INTO `versionLog` VALUES ('vn-database','11348','00-firstScript.sql','jen 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','11351','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-12-10 07:20:04',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11352','00-firstScript.sql','jenkins@db-proxy1.servers.dc.verdnatura.es','2025-01-07 07:46:24',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','11354','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-12-10 07:20:04',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); @@ -1120,6 +1123,8 @@ INSERT INTO `versionLog` VALUES ('vn-database','11362','00-firstScript.sql','jen INSERT INTO `versionLog` VALUES ('vn-database','11363','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-12-10 07:20:04',NULL,NULL); INSERT INTO `versionLog` VALUES ('vn-database','11366','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-12-10 07:20:04',NULL,NULL); INSERT INTO `versionLog` VALUES ('vn-database','11367','00-deprecate.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-12-10 07:20:04',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11368','00-firstScript.sql','jenkins@db-proxy1.servers.dc.verdnatura.es','2025-01-07 07:46:32',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11368','01-acls.sql','jenkins@db-proxy1.servers.dc.verdnatura.es','2025-01-07 07:46:32',NULL,NULL); INSERT INTO `versionLog` VALUES ('vn-database','11369','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-12-10 07:20:05',NULL,NULL); INSERT INTO `versionLog` VALUES ('vn-database','11371','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-12-10 07:20:05',NULL,NULL); INSERT INTO `versionLog` VALUES ('vn-database','11371','01-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-12-10 07:20:47',NULL,NULL); @@ -1128,7 +1133,16 @@ INSERT INTO `versionLog` VALUES ('vn-database','11371','03-firstScript.sql','jen INSERT INTO `versionLog` VALUES ('vn-database','11372','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-12-09 13:30:30',NULL,NULL); INSERT INTO `versionLog` VALUES ('vn-database','11373','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-12-02 16:09:01',NULL,NULL); INSERT INTO `versionLog` VALUES ('vn-database','11375','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-12-03 08:58:20',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11376','00-firstScript.sql','jenkins@db-proxy1.servers.dc.verdnatura.es','2025-01-07 07:46:32',NULL,NULL); INSERT INTO `versionLog` VALUES ('vn-database','11377','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-12-10 07:22:31',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11378','00-firstScript.sql','jenkins@db-proxy1.servers.dc.verdnatura.es','2025-01-07 07:46:32',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11379','00-firstScript.sql','jenkins@db-proxy1.servers.dc.verdnatura.es','2025-01-07 07:46:32',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11379','01-secScript.sql','jenkins@db-proxy1.servers.dc.verdnatura.es','2025-01-07 07:46:32',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11384','00-firstScript.sql','jenkins@db-proxy1.servers.dc.verdnatura.es','2025-01-07 07:46:32',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11385','00-firstScript.sql','jenkins@db-proxy1.servers.dc.verdnatura.es','2025-01-07 07:46:33',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11390','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2025-01-14 07:32:08',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11391','00-itemAlter.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2025-01-14 07:32:08',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11400','00-firstScript.sql','jenkins@db-proxy1.servers.dc.verdnatura.es','2025-01-09 09:55:24',NULL,NULL); /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; @@ -1505,6 +1519,7 @@ INSERT INTO `roleInherit` VALUES (378,101,15,19294); INSERT INTO `roleInherit` VALUES (379,103,121,19294); INSERT INTO `roleInherit` VALUES (381,119,123,19295); INSERT INTO `roleInherit` VALUES (382,48,72,783); +INSERT INTO `roleInherit` VALUES (383,114,111,19295); INSERT INTO `userPassword` VALUES (1,7,1,0,2,1); @@ -2128,7 +2143,7 @@ INSERT INTO `ACL` VALUES (746,'Claim','getSummary','READ','ALLOW','ROLE','claimV INSERT INTO `ACL` VALUES (747,'CplusRectificationType','*','READ','ALLOW','ROLE','administrative',NULL); INSERT INTO `ACL` VALUES (748,'SiiTypeInvoiceOut','*','READ','ALLOW','ROLE','salesPerson',NULL); INSERT INTO `ACL` VALUES (749,'InvoiceCorrectionType','*','READ','ALLOW','ROLE','salesPerson',NULL); -INSERT INTO `ACL` VALUES (750,'InvoiceOut','transfer','WRITE','ALLOW','ROLE','administrative',NULL); +INSERT INTO `ACL` VALUES (750,'InvoiceOut','transfer','WRITE','ALLOW','ROLE','administrative',13657); INSERT INTO `ACL` VALUES (751,'Application','executeProc','*','ALLOW','ROLE','employee',NULL); INSERT INTO `ACL` VALUES (752,'Application','executeFunc','*','ALLOW','ROLE','employee',NULL); INSERT INTO `ACL` VALUES (753,'NotificationSubscription','getList','READ','ALLOW','ROLE','employee',NULL); @@ -2301,9 +2316,9 @@ INSERT INTO `ACL` VALUES (938,'Worker','__get__mail','READ','ALLOW','ROLE','hr', 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 (942,'Cmr','filter','READ','ALLOW','ROLE','employee',19295); +INSERT INTO `ACL` VALUES (943,'Cmr','downloadZip','READ','ALLOW','ROLE','employee',19295); +INSERT INTO `ACL` VALUES (944,'Cmr','print','READ','ALLOW','ROLE','employee',19295); 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); @@ -2317,7 +2332,6 @@ INSERT INTO `ACL` VALUES (954,'RouteComplement','find','READ','ALLOW','ROLE','de 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 `ACL` VALUES (957,'SaleGroup','find','READ','ALLOW','ROLE','production',10578); -INSERT INTO `ACL` VALUES (958,'Worker','canCreateAbsenceInPast','WRITE','ALLOW','ROLE','hr',10578); INSERT INTO `ACL` VALUES (959,'WorkerRelative','updateAttributes','*','ALLOW','ROLE','hr',10578); INSERT INTO `ACL` VALUES (960,'WorkerRelative','crud','WRITE','ALLOW','ROLE','hr',10578); INSERT INTO `ACL` VALUES (961,'WorkerRelative','findById','*','ALLOW','ROLE','hr',10578); @@ -2369,6 +2383,12 @@ INSERT INTO `ACL` VALUES (1006,'Entry','latestBuysFilter','READ','ALLOW','ROLE', INSERT INTO `ACL` VALUES (1007,'ItemShelving','getItemsByReviewOrder','READ','ALLOW','ROLE','production',19294); INSERT INTO `ACL` VALUES (1008,'Entry','buyLabelSupplier','READ','ALLOW','ROLE','employee',19295); INSERT INTO `ACL` VALUES (1009,'Entry','buyLabel','READ','ALLOW','ROLE','supplier',19295); +INSERT INTO `ACL` VALUES (1010,'InventoryConfig','find','READ','ALLOW','ROLE','buyer',10578); +INSERT INTO `ACL` VALUES (1011,'SiiTypeInvoiceIn','find','READ','ALLOW','ROLE','salesPerson',10578); +INSERT INTO `ACL` VALUES (1012,'OsrmConfig','optimize','READ','ALLOW','ROLE','employee',10578); +INSERT INTO `ACL` VALUES (1013,'Route','optimizePriority','*','ALLOW','ROLE','employee',10578); +INSERT INTO `ACL` VALUES (1014,'Worker','canModifyAbsenceInPast','WRITE','ALLOW','ROLE','hr',10578); +INSERT INTO `ACL` VALUES (1015,'Worker','__get__sip','READ','ALLOW','ROLE','employee',19294); INSERT INTO `fieldAcl` VALUES (1,'Client','name','update','employee'); INSERT INTO `fieldAcl` VALUES (2,'Client','contact','update','employee'); @@ -2525,9 +2545,8 @@ INSERT INTO `companyI18n` VALUES (442,'en','In compliance with the provisions of INSERT INTO `companyI18n` VALUES (442,'fr','Conformément aux dispositions de la loi organique 15/1999 sur la protection des données personnelles, nous vous informons que les données personnelles que vous fournissez seront incluses dans des dossiers. VERDNATURA LEVANTE S.L., vous pouvez à tout moment, exercer les droits d``accès, de rectification, d``annulation et d``opposition, en communiquant par écrit au siège social de la société. Le dossier a pour objet la gestion administrative, la comptabilité et la facturation.'); INSERT INTO `companyI18n` VALUES (442,'pt','Em cumprimento do disposto na lei Orgânica 15/1999, de Protecção de Dados de Carácter Pessoal, comunicamos que os dados pessoais que facilite se incluirão nos ficheiros automatizados de VERDNATURA LEVANTE S.L., podendo em todo momento exercer os direitos de acesso, rectificação, cancelação e oposição, comunicando por escrito ao domicílio social da entidade. A finalidade do ficheiro é a gestão administrativa, contabilidade e facturação.'); -INSERT INTO `cplusRectificationType` VALUES (1,'Campo vacio'); +INSERT INTO `cplusRectificationType` VALUES (1,'S – Por sustitución'); INSERT INTO `cplusRectificationType` VALUES (2,'I – Por diferencias'); -INSERT INTO `cplusRectificationType` VALUES (3,'S – Por sustitución'); INSERT INTO `cplusSubjectOp` VALUES (1,'Campo vacio'); INSERT INTO `cplusSubjectOp` VALUES (2,'S1 – Sujeta – No exenta'); @@ -2619,6 +2638,8 @@ INSERT INTO `claimResult` VALUES (26,'Decepcion/Esperaba mas'); INSERT INTO `claimResult` VALUES (27,'Otros'); INSERT INTO `claimResult` VALUES (28,'Baboso/Cocido'); INSERT INTO `claimResult` VALUES (29,'Videocámaras'); +INSERT INTO `claimResult` VALUES (30,'Manipulado'); +INSERT INTO `claimResult` VALUES (31,'ReclamReclamado PR/AG'); INSERT INTO `component` VALUES (10,'Precios Especiales',4,NULL,NULL,1,'specialPrices',0); INSERT INTO `component` VALUES (14,'porte extra por dia semana',6,NULL,NULL,1,'extraCostPerWeekDay',0); @@ -2710,7 +2731,7 @@ INSERT INTO `department` VALUES (124,NULL,'CONTROL INTERNO',122,123,NULL,72,0,0, INSERT INTO `department` VALUES (125,'spainTeam3','EQUIPO ESPAÑA 3',59,60,1118,0,0,0,2,0,43,'/1/43/',NULL,1,NULL,0,0,0,0,NULL,NULL,NULL,NULL); INSERT INTO `department` VALUES (126,NULL,'PRESERVADO',29,30,NULL,0,0,0,2,0,37,'/1/37/',NULL,0,NULL,0,1,1,0,NULL,NULL,NULL,NULL); INSERT INTO `department` VALUES (128,NULL,'PALETIZADO',31,32,NULL,0,1,0,2,0,37,'/1/37/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,'PALLETIZING'); -INSERT INTO `department` VALUES (130,NULL,'REVISION',33,34,NULL,0,1,0,2,0,37,'/1/37/',NULL,0,NULL,0,0,0,1,NULL,NULL,NULL,'ON_CHECKING'); +INSERT INTO `department` VALUES (130,'reviewers','REVISION',33,34,NULL,0,1,0,2,0,37,'/1/37/',NULL,0,NULL,0,0,0,1,NULL,NULL,NULL,'ON_CHECKING'); INSERT INTO `department` VALUES (131,'greenhouse','INVERNADERO',105,106,NULL,0,0,0,2,0,58,'/1/58/',NULL,0,NULL,0,1,0,0,NULL,NULL,NULL,NULL); INSERT INTO `department` VALUES (132,NULL,'EQUIPO DC',61,62,1731,0,0,0,2,0,43,'/1/43/','dc_equipo',1,'gestioncomercial@verdnatura.es',0,0,0,0,NULL,NULL,NULL,NULL); INSERT INTO `department` VALUES (133,'franceTeamManagement','EQUIPO GESTIÓN FRANCIA',63,64,9751,72,0,0,2,0,43,'/1/43/','fr_equipo',1,'gestionfrancia@verdnatura.es',0,0,0,0,NULL,NULL,'3300',NULL); @@ -2725,12 +2746,12 @@ INSERT INTO `department` VALUES (146,NULL,'VERDNACOLOMBIA',3,4,NULL,72,0,0,2,0,2 INSERT INTO `department` VALUES (147,'spainTeamAsia','EQUIPO ESPAÑA ASIA',71,72,40214,0,0,0,2,0,43,'/1/43/','esA_equipo',1,'esA@verdnatura.es',0,0,0,0,NULL,NULL,'5500',NULL); INSERT INTO `department` VALUES (148,'franceTeamCatchment','EQUIPO CAPTACIÓN FRANCIA',73,74,25178,0,0,0,2,0,43,'/1/43/',NULL,1,NULL,0,0,0,0,NULL,NULL,'6000',NULL); INSERT INTO `department` VALUES (149,'spainTeamCatchment','EQUIPO ESPAÑA CAPTACIÓN',75,76,1203,0,0,0,2,0,43,'/1/43/','es_captacion_equipo',1,'es_captacion@verdnatura.es',0,0,0,0,NULL,NULL,'5700',NULL); -INSERT INTO `department` VALUES (150,'spainTeamLevanteIslands','EQUIPO ESPAÑA LEVANTE/ISLAS',77,78,1118,0,0,0,2,0,43,'/1/43/','es_levanteislas_equipo',1,'levanteislas.verdnatura@gmail.com',0,0,0,0,NULL,NULL,'5000',NULL); -INSERT INTO `department` VALUES (151,'spainTeamNorthwest','EQUIPO ESPAÑA NOROESTE',79,80,7102,0,0,0,2,0,43,'/1/43/','es_noroeste_equipo',1,'noroeste.verdnatura@gmail.com',0,0,0,0,NULL,NULL,'5300',NULL); -INSERT INTO `department` VALUES (152,'spainTeamNortheast','EQUIPO ESPAÑA NORESTE',81,82,1118,0,0,0,2,0,43,'/1/43/','es_noreste_equipo',1,'noreste.verdnatura@gmail.com',0,0,0,0,NULL,NULL,'5200',NULL); -INSERT INTO `department` VALUES (153,'spainTeamSouth','EQUIPO ESPAÑA SUR',83,84,36578,0,0,0,2,0,43,'/1/43/','es_sur_equipo',1,'sur.verdnatura@gmail.com',0,0,0,0,NULL,NULL,'5400',NULL); -INSERT INTO `department` VALUES (154,'spainTeamCenter','EQUIPO ESPAÑA CENTRO',85,86,4661,0,0,0,2,0,43,'/1/43/','es_centro_equipo',1,'centro.verdnatura@gmail.com',0,0,0,0,NULL,NULL,'5100',NULL); -INSERT INTO `department` VALUES (155,'spainTeamVip','EQUIPO ESPAÑA VIP',87,88,5432,0,0,0,2,0,43,'/1/43/','es_vip_equipo',1,'vip.verdnatura@gmail.com',0,0,0,0,NULL,NULL,'5600',NULL); +INSERT INTO `department` VALUES (150,'spainTeamLevanteIslands','EQUIPO ESPAÑA LEVANTE',77,78,1118,0,0,0,2,0,43,'/1/43/','es_levante_equipo',1,'es_levante@verdnatura.es',0,0,0,0,NULL,NULL,'5000',NULL); +INSERT INTO `department` VALUES (151,'spainTeamNorthwest','EQUIPO ESPAÑA NOROESTE',79,80,7102,0,0,0,2,0,43,'/1/43/','es_noroeste_equipo',1,'es_noroeste@verdnatura.es',0,0,0,0,NULL,NULL,'5300',NULL); +INSERT INTO `department` VALUES (152,'spainTeamNortheast','EQUIPO ESPAÑA NORESTE',81,82,1118,0,0,0,2,0,43,'/1/43/','es_noreste_equipo',1,'es_noreste@verdnatura.es',0,0,0,0,NULL,NULL,'5200',NULL); +INSERT INTO `department` VALUES (153,'spainTeamSouth','EQUIPO ESPAÑA SUR',83,84,36578,0,0,0,2,0,43,'/1/43/','es_sur_equipo',1,'es_sur@verdnatura.es',0,0,0,0,NULL,NULL,'5400',NULL); +INSERT INTO `department` VALUES (154,'spainTeamCenter','EQUIPO ESPAÑA CENTRO',85,86,4661,0,0,0,2,0,43,'/1/43/','es_centro_equipo',1,'es_centro@verdnatura.es',0,0,0,0,NULL,NULL,'5100',NULL); +INSERT INTO `department` VALUES (155,'spainTeamVip','EQUIPO ESPAÑA VIP',87,88,5432,0,0,0,2,0,43,'/1/43/','es_vip_equipo',1,'es_vip@verdnatura.es',0,0,0,0,NULL,NULL,'5600',NULL); INSERT INTO `docuware` VALUES (1,'deliveryNote','Albaranes cliente','find','find','N__ALBAR_N',NULL); INSERT INTO `docuware` VALUES (2,'deliveryNote','Albaranes cliente','store','Archivar','N__ALBAR_N',NULL); @@ -3031,6 +3052,7 @@ INSERT INTO `message` VALUES (20,'clientNotVerified','Incomplete tax data, pleas INSERT INTO `message` VALUES (21,'quantityLessThanMin','The quantity cannot be less than the minimum'); INSERT INTO `message` VALUES (22,'ORDER_ROW_UNAVAILABLE','The ordered quantity exceeds the available'); INSERT INTO `message` VALUES (23,'AMOUNT_NOT_MATCH_GROUPING','The quantity ordered does not match the grouping'); +INSERT INTO `message` VALUES (24,'orderLinesWithZero','There are empty lines. Please delete them'); INSERT INTO `metatag` VALUES (2,'title','Verdnatura Levante SL, mayorista de flores, plantas y complementos para floristería y decoración'); INSERT INTO `metatag` VALUES (3,'description','Verdnatura Levante SL, mayorista de flores, plantas y complementos para floristería y decoración. Envío a toda España, pedidos por internet o por teléfono.'); diff --git a/db/dump/.dump/privileges.sql b/db/dump/.dump/privileges.sql index f608d0e8a..598bfdf75 100644 --- a/db/dump/.dump/privileges.sql +++ b/db/dump/.dump/privileges.sql @@ -979,7 +979,7 @@ INSERT IGNORE INTO `tables_priv` VALUES ('','bi','officeBoss','Greuge_Evolution' INSERT IGNORE INTO `tables_priv` VALUES ('','bi','claimManager','rotacion','alexm@%','0000-00-00 00:00:00','Select',''); INSERT IGNORE INTO `tables_priv` VALUES ('','bs','grafana','sale','juan@db-proxy2.static.verdnatura.es','0000-00-00 00:00:00','Select',''); INSERT IGNORE INTO `tables_priv` VALUES ('','vn','employee','zonePromo__','alexm@%','0000-00-00 00:00:00','Select,Insert,Update,Delete',''); -INSERT IGNORE INTO `tables_priv` VALUES ('','vn','administrative','accountingConfig','alexm@%','0000-00-00 00:00:00','Select',''); +INSERT IGNORE INTO `tables_priv` VALUES ('','vn','administrative','accountingConfig','carlosap@db-proxy2.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select,Update',''); INSERT IGNORE INTO `tables_priv` VALUES ('','vn','administrative','accountingType','alexm@%','0000-00-00 00:00:00','Select',''); INSERT IGNORE INTO `tables_priv` VALUES ('','vn','logistic','agencyMode','alexm@%','0000-00-00 00:00:00','Insert,Update',''); INSERT IGNORE INTO `tables_priv` VALUES ('','cache','employee','visible','juan@10.5.1.2','0000-00-00 00:00:00','Select',''); @@ -1417,9 +1417,11 @@ INSERT IGNORE INTO `tables_priv` VALUES ('','vn','adminOfficer','accountDetail', 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 ('','vn','employee','workerActivityType','guillermo@db-proxy2.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','delivery','zoneConfig','guillermo@db-proxy2.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','Insert,Update,Delete',''); 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','marketingBoss','specialPrice','alexm@db-proxy2.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); 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',''); @@ -1488,6 +1490,14 @@ INSERT IGNORE INTO `tables_priv` VALUES ('','vn','logisticAssist','itemBaseTag', 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',''); +INSERT IGNORE INTO `tables_priv` VALUES ('','vn','grafana','travelThermograph','guillermo@db-proxy1.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); +INSERT IGNORE INTO `tables_priv` VALUES ('','vn','grafana','thermograph','guillermo@db-proxy1.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); +INSERT IGNORE INTO `tables_priv` VALUES ('','vn2008','buyerSalesAssistant','Tickets','guillermo@db-proxy1.servers.dc.verdnatura.es','0000-00-00 00:00:00','Update',''); +INSERT IGNORE INTO `tables_priv` VALUES ('','vn','hr','sim','jenkins@db-proxy1.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select,Insert,Update,Delete',''); +INSERT IGNORE INTO `tables_priv` VALUES ('','vn','employee','zoneGeo','guillermo@db-proxy2.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); +INSERT IGNORE INTO `tables_priv` VALUES ('','vn','buyer','itemCampaign','guillermo@db-proxy1.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); +INSERT IGNORE INTO `tables_priv` VALUES ('','vn','grafana','itemCampaign','guillermo@db-proxy1.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); +INSERT IGNORE INTO `tables_priv` VALUES ('','vn','buyer','campaign','guillermo@db-proxy1.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); /*!40000 ALTER TABLE `tables_priv` ENABLE KEYS */; /*!40000 ALTER TABLE `columns_priv` DISABLE KEYS */; @@ -1873,6 +1883,7 @@ INSERT IGNORE INTO `procs_priv` VALUES ('','vn','salesAssistant','subordinateget INSERT IGNORE INTO `procs_priv` VALUES ('','vn','buyer','buy_afterUpsert','PROCEDURE','alexm@%','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','util','grafana','dayend','FUNCTION','juan@db-proxy2.static.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','srt','production','buffer_settypebyname','PROCEDURE','alexm@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); +INSERT IGNORE INTO `procs_priv` VALUES ('','vn','grafana','clientGetMana','FUNCTION','guillermo@db-proxy2.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','employee','barcodeToItem','FUNCTION','alexm@%','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','employee','ticket_splititempackingtype','PROCEDURE','alexm@%','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','employee','entry_getCommission','FUNCTION','alexm@%','Execute','0000-00-00 00:00:00'); diff --git a/db/dump/.dump/structure.sql b/db/dump/.dump/structure.sql index a4ae460b1..58f1e7591 100644 --- a/db/dump/.dump/structure.sql +++ b/db/dump/.dump/structure.sql @@ -2569,28 +2569,6 @@ SET character_set_client = utf8; 1 AS `Consumo` */; SET character_set_client = @saved_cs_client; --- --- Temporary table structure for view `rotacion` --- - -DROP TABLE IF EXISTS `rotacion`; -/*!50001 DROP VIEW IF EXISTS `rotacion`*/; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; -/*!50001 CREATE VIEW `rotacion` AS SELECT - 1 AS `Id_Article`, - 1 AS `warehouse_id`, - 1 AS `total`, - 1 AS `rotacion`, - 1 AS `cm3`, - 1 AS `almacenaje`, - 1 AS `manipulacion`, - 1 AS `auxiliar`, - 1 AS `mermas`, - 1 AS `cm3reparto`, - 1 AS `grams` */; -SET character_set_client = @saved_cs_client; - -- -- Table structure for table `rutasBoard` -- @@ -6271,19 +6249,27 @@ BEGIN * @param vDateFrom Fecha desde * @param vDateTo Fecha hasta */ - IF vDateFrom IS NULL THEN - SET vDateFrom = util.VN_CURDATE() - INTERVAL WEEKDAY(util.VN_CURDATE()) DAY; + DECLARE vDaysInYear INT; + SET vDaysInYear = DATEDIFF(util.lastDayOfYear(CURDATE()), util.firstDayOfYear(CURDATE())); + + SET vDateFrom = COALESCE(vDateFrom, util.VN_CURDATE()); + SET vDateTo = COALESCE(vDateTo, util.VN_CURDATE()); + + IF DATEDIFF(vDateTo, vDateFrom) > vDaysInYear THEN + CALL util.throw('The period cannot be longer than one year'); END IF; - IF vDateTo IS NULL THEN - SET vDateTo = vDateFrom + INTERVAL 6 DAY; - END IF; + -- Obtiene el primer día de la semana de esa fecha + SET vDateFrom = DATE_SUB(vDateFrom, INTERVAL ((WEEKDAY(vDateFrom) + 1) % 7) DAY); + + -- Obtiene el último día de la semana de esa fecha + SET vDateTo = DATE_ADD(vDateTo, INTERVAL (6 - ((WEEKDAY(vDateTo) + 1) % 7)) DAY); CALL cache.last_buy_refresh(FALSE); REPLACE bs.waste - SELECT YEAR(t.shipped), - WEEK(t.shipped, 4), + SELECT YEARWEEK(t.shipped, 6) DIV 100, + WEEK(t.shipped, 6), it.workerFk, it.id, s.itemFk, @@ -6329,9 +6315,9 @@ BEGIN JOIN cache.last_buy lb ON lb.item_id = i.id AND lb.warehouse_id = w.id JOIN vn.buy b ON b.id = lb.buy_id - WHERE t.shipped BETWEEN vDateFrom AND vDateTo + WHERE t.shipped BETWEEN vDateFrom AND util.dayEnd(vDateTo) AND w.isManaged - GROUP BY YEAR(t.shipped), WEEK(t.shipped, 4), i.id; + GROUP BY YEARWEEK(t.shipped, 6) DIV 100, WEEK(t.shipped, 6), i.id; END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -13829,7 +13815,7 @@ BEGIN ) INTO vHas0Amount; IF vHas0Amount THEN - CALL util.throw('Hay líneas vacías. Por favor, elimínelas'); + CALL util.throw('orderLinesWithZero'); END IF; START TRANSACTION; @@ -17481,10 +17467,10 @@ BEGIN /** * Traslada la info de contabilidad relacionada con las facturas recibidas * - * @vInvoiceInFk Factura recibida - * @vXDiarioFk Id tabla XDiario + * @param vInvoiceInFk Factura recibida + * @param vXDiarioFk Id tabla XDiario */ - DECLARE vInvoiceInOriginalFk INT; + DECLARE vInvoiceInOriginalFk INT; DECLARE vDone BOOL DEFAULT FALSE; DECLARE vBase DOUBLE; DECLARE vVat DOUBLE; @@ -17502,7 +17488,7 @@ BEGIN DECLARE vIsInformativeExportation BOOL DEFAULT FALSE; DECLARE vCursor CURSOR FOR - SELECT it.taxableBase, + SELECT SUM(it.taxableBase), CAST(SUM((( it.taxableBase / 100) * t.PorcentajeIva)) AS DECIMAL (10,2)), t.PorcentajeIva, it.transactionTypeSageFk, @@ -17681,32 +17667,31 @@ BEGIN FROM vn.invoiceInCorrection WHERE correctingFk = vInvoiceInFk; - IF vInvoiceInOriginalFk THEN - + IF vInvoiceInOriginalFk THEN UPDATE movContaIVA mci - JOIN vn.invoiceInRefund iir ON iir.invoiceInRefundFk = vInvoiceInFk + JOIN vn.invoiceInCorrection iic ON iic.correctingFk = vInvoiceInFk + JOIN vn.siiTypeInvoiceIn st ON st.id = iic.siiTypeInvoiceInFk JOIN (SELECT issued, - SUM(sub.taxableBase) taxableBase, + SUM(sub.taxableBase) taxableBase, SUM(ROUND((sub.taxableBase * sub.PorcentajeIva) / 100 , 2)) vat FROM(SELECT issued, - SUM(iit.taxableBase) taxableBase, + SUM(iit.taxableBase) taxableBase, ti.PorcentajeIva - FROM vn.invoiceIn i + FROM vn.invoiceIn i JOIN vn.invoiceInTax iit ON iit.invoiceInFk = i.id - JOIN sage.TiposIva ti ON ti.CodigoIva = iit.taxTypeSageFk + JOIN TiposIva ti ON ti.CodigoIva = iit.taxTypeSageFk WHERE i.id = vInvoiceInOriginalFk GROUP BY ti.CodigoIva)sub )invoiceInOriginal JOIN ClavesOperacion co ON co.Descripcion = 'Factura rectificativa' SET mci.TipoRectificativa = iir.refundCategoryFk, - mci.ClaseAbonoRectificativas = iir.refundType, + mci.ClaseAbonoRectificativas = iir.refundType, mci.FechaFacturaOriginal = invoiceInOriginal.issued, mci.FechaOperacion = invoiceInOriginal.issued, mci.BaseImponibleOriginal = invoiceInOriginal.taxableBase, mci.CuotaIvaOriginal = invoiceInOriginal.vat, mci.ClaveOperacionFactura = co.ClaveOperacionFactura_ WHERE mci.id = vXDiarioFk; - END IF; END ;; DELIMITER ; @@ -18178,6 +18163,7 @@ BEGIN UPDATE movContaIVA mci JOIN vn.invoiceOut i ON i.id = vInvoiceOutCorrectedFk JOIN vn.invoiceCorrection ic ON ic.correctedFk = vInvoiceOutCorrectedFk + JOIN vn.siiTypeInvoiceOut st ON st.id = ic.siiTypeInvoiceOutFk JOIN (SELECT SUM(IF(IFNULL(e.vatFk, TRUE), iot.taxableBase, 0)) taxableBase, SUM(IF(IFNULL(e.vatFk, TRUE), iot.vat, 0)) vat, SUM(IF(IFNULL(e.vatFk, TRUE), 0, iot.vat)) equ @@ -18186,8 +18172,8 @@ BEGIN WHERE iot.invoiceOutFk = vInvoiceOutCorrectedFk ) tax JOIN ClavesOperacion co ON co.Descripcion = 'Factura rectificativa' - SET mci.TipoRectificativa = 2, - mci.ClaseAbonoRectificativas = 1, + SET mci.TipoRectificativa = ic.cplusRectificationTypeFk, + mci.ClaseAbonoRectificativas = REGEXP_REPLACE(st.`code`, '[^0-9]', ''), mci.FechaFacturaOriginal = i.issued, mci.FechaOperacion = i.issued, mci.BaseImponibleOriginal = tax.taxableBase, @@ -28944,6 +28930,7 @@ CREATE TABLE `country` ( `isSocialNameUnique` tinyint(1) NOT NULL DEFAULT 1, PRIMARY KEY (`id`), UNIQUE KEY `country_unique` (`code`), + UNIQUE KEY `country_unique_name` (`name`), KEY `currency_id_fk_idx` (`currencyFk`), KEY `country_Ix4` (`name`), KEY `continent_id_fk_idx` (`continentFk`), @@ -29528,14 +29515,16 @@ CREATE TABLE `deviceProductionUser` ( `userFk` int(10) unsigned NOT NULL, `created` timestamp NULL DEFAULT current_timestamp(), `editorFk` int(10) unsigned DEFAULT NULL, - `simSerialNumber` text DEFAULT NULL, + `simFk` varchar(25) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `deviceProductionUser_unique` (`deviceProductionFk`), KEY `userFgn_idx` (`userFk`), KEY `deviceProductionUser_fk_editor` (`editorFk`), + KEY `deviceProductionUser_sim_FK` (`simFk`), CONSTRAINT `deviceProductionUser_PK` FOREIGN KEY (`userFk`) REFERENCES `account`.`user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `deviceProductionUser_deviceProduction_FK` FOREIGN KEY (`deviceProductionFk`) REFERENCES `deviceProduction` (`id`), - CONSTRAINT `deviceProductionUser_fk_editor` FOREIGN KEY (`editorFk`) REFERENCES `account`.`user` (`id`) + CONSTRAINT `deviceProductionUser_fk_editor` FOREIGN KEY (`editorFk`) REFERENCES `account`.`user` (`id`), + CONSTRAINT `deviceProductionUser_sim_FK` FOREIGN KEY (`simFk`) REFERENCES `sim` (`code`) ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; /*!40101 SET character_set_client = @saved_cs_client */; @@ -31354,13 +31343,27 @@ CREATE TABLE `inventoryConfig` ( /*!40101 SET character_set_client = @saved_cs_client */; -- --- Table structure for table `inventoryFailure` +-- Table structure for table `inventoryFailureCause__` -- -DROP TABLE IF EXISTS `inventoryFailure`; +DROP TABLE IF EXISTS `inventoryFailureCause__`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; -CREATE TABLE `inventoryFailure` ( +CREATE TABLE `inventoryFailureCause__` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `description` varchar(100) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci COMMENT='@deprecated 2024-12-16'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `inventoryFailure__` +-- + +DROP TABLE IF EXISTS `inventoryFailure__`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `inventoryFailure__` ( `id` int(11) NOT NULL AUTO_INCREMENT, `dated` date NOT NULL, `itemFk` int(11) NOT NULL, @@ -31381,22 +31384,8 @@ CREATE TABLE `inventoryFailure` ( CONSTRAINT `inventoryFailure_fk2` FOREIGN KEY (`throwerFk`) REFERENCES `worker` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `inventoryFailure_fk3` FOREIGN KEY (`guiltyFk`) REFERENCES `worker` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `inventoryFailure_fk4` FOREIGN KEY (`warehouseFk`) REFERENCES `warehouse` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT `inventoryFailure_fk5` FOREIGN KEY (`causeFk`) REFERENCES `inventoryFailureCause` (`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 `inventoryFailureCause` --- - -DROP TABLE IF EXISTS `inventoryFailureCause`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `inventoryFailureCause` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `description` varchar(100) NOT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; + CONSTRAINT `inventoryFailure_fk5` FOREIGN KEY (`causeFk`) REFERENCES `inventoryFailureCause__` (`id`) ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci COMMENT='@deprecated 2024-12-16'; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -31554,18 +31543,18 @@ CREATE TABLE `invoiceInCorrection` ( `correctingFk` mediumint(8) unsigned NOT NULL COMMENT 'Factura rectificativa', `correctedFk` mediumint(8) unsigned NOT NULL COMMENT 'Factura rectificada', `cplusRectificationTypeFk` int(10) unsigned NOT NULL, - `siiTypeInvoiceOutFk` int(10) unsigned NOT NULL, + `siiTypeInvoiceInFk` int(10) unsigned NOT NULL, `invoiceCorrectionTypeFk` int(11) NOT NULL DEFAULT 3, PRIMARY KEY (`correctingFk`), KEY `invoiceInCorrection_correctedFk` (`correctedFk`), KEY `invoiceInCorrection_cplusRectificationTypeFk` (`cplusRectificationTypeFk`), - KEY `invoiceInCorrection_siiTypeInvoiceOut` (`siiTypeInvoiceOutFk`), + KEY `invoiceInCorrection_siiTypeInvoiceIn` (`siiTypeInvoiceInFk`), KEY `invoiceInCorrection_invoiceCorrectionTypeFk` (`invoiceCorrectionTypeFk`), CONSTRAINT `invoiceInCorrection_correctedFk` FOREIGN KEY (`correctedFk`) REFERENCES `invoiceIn` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `invoiceInCorrection_correctingFk` FOREIGN KEY (`correctingFk`) REFERENCES `invoiceIn` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `invoiceInCorrection_cplusRectificationTypeFk` FOREIGN KEY (`cplusRectificationTypeFk`) REFERENCES `cplusRectificationType` (`id`) ON UPDATE CASCADE, CONSTRAINT `invoiceInCorrection_invoiceCorrectionTypeFk` FOREIGN KEY (`invoiceCorrectionTypeFk`) REFERENCES `invoiceCorrectionType` (`id`) ON UPDATE CASCADE, - CONSTRAINT `invoiceInCorrection_siiTypeInvoiceOut` FOREIGN KEY (`siiTypeInvoiceOutFk`) REFERENCES `siiTypeInvoiceOut` (`id`) ON UPDATE CASCADE + CONSTRAINT `invoiceInCorrection_siiTypeInvoiceIn` FOREIGN KEY (`siiTypeInvoiceInFk`) REFERENCES `siiTypeInvoiceIn` (`id`) ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; /*!40101 SET character_set_client = @saved_cs_client */; @@ -31991,6 +31980,7 @@ CREATE TABLE `item` ( `value12` varchar(50) DEFAULT NULL, `tag13` varchar(20) DEFAULT NULL, `value13` varchar(50) DEFAULT NULL, + `isCustomInspectionRequired` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'Indicates if the item requires physical inspection at customs', PRIMARY KEY (`id`), UNIQUE KEY `item_supplyResponseFk_idx` (`supplyResponseFk`), KEY `Color` (`inkFk`), @@ -33837,7 +33827,9 @@ DROP TABLE IF EXISTS `mistakeType`; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `mistakeType` ( `id` int(11) NOT NULL AUTO_INCREMENT, + `code` varchar(50) DEFAULT NULL, `description` varchar(45) NOT NULL, + `time` int(10) DEFAULT NULL COMMENT 'Segundos que se suelen tardar en arreglar el fallo', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; /*!40101 SET character_set_client = @saved_cs_client */; @@ -34204,6 +34196,22 @@ CREATE TABLE `osTicketConfig` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; /*!40101 SET character_set_client = @saved_cs_client */; +-- +-- Table structure for table `osrmConfig` +-- + +DROP TABLE IF EXISTS `osrmConfig`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `osrmConfig` ( + `id` int(10) unsigned NOT NULL, + `url` varchar(100) NOT NULL COMMENT 'Dirección base de la API', + `tolerance` decimal(6,6) NOT NULL DEFAULT 0.000000 COMMENT 'Tolerancia entre las coordenadas enviadas y las retornadas', + PRIMARY KEY (`id`), + CONSTRAINT `osrmConfig_check` CHECK (`id` = 1) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + -- -- Table structure for table `outgoingInvoiceVat` -- @@ -35763,26 +35771,6 @@ CREATE TABLE `punchState` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci COMMENT='Table for storing punches that have cars with errors'; /*!40101 SET character_set_client = @saved_cs_client */; --- --- Table structure for table `quadmindsApiConfig` --- - -DROP TABLE IF EXISTS `quadmindsApiConfig`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `quadmindsApiConfig` ( - `id` int(10) unsigned NOT NULL, - `url` varchar(255) DEFAULT NULL, - `key` varchar(255) DEFAULT NULL, - `maxObjects` int(11) DEFAULT NULL COMMENT 'Número máximo de objetos en el array por petición', - `limit` int(11) DEFAULT NULL COMMENT 'Limite de objetos solicitados por petición', - `orderTimeFrom` varchar(5) DEFAULT NULL COMMENT 'Inicio de ventana horaria de pedido', - `orderTimeTo` varchar(5) DEFAULT NULL COMMENT 'Fin de ventana horaria de pedido', - PRIMARY KEY (`id`), - CONSTRAINT `quadMindsConfig_check` CHECK (`id` = 1) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; -/*!40101 SET character_set_client = @saved_cs_client */; - -- -- Table structure for table `quality` -- @@ -37542,6 +37530,23 @@ CREATE TABLE `siiTypeInvoiceOut` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci COMMENT='Tipo de Factura Emitidas en el suministro de inmediato'; /*!40101 SET character_set_client = @saved_cs_client */; +-- +-- Table structure for table `sim` +-- + +DROP TABLE IF EXISTS `sim`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `sim` ( + `code` varchar(25) NOT NULL COMMENT 'No se ha puesto BIGINT por incompatibilidad con Access', + `line` varchar(15) NOT NULL CHECK (`line` regexp '^[0-9]+$'), + `ext` int(4) NOT NULL, + `pin` varchar(4) NOT NULL CHECK (`pin` regexp '^[0-9]+$'), + `puk` varchar(15) NOT NULL CHECK (`pin` regexp '^[0-9]+$'), + PRIMARY KEY (`code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + -- -- Table structure for table `sinister` -- @@ -41255,7 +41260,7 @@ CREATE TABLE `zone` ( `hour` datetime NOT NULL, `agencyModeFk` int(11) NOT NULL, `travelingDays` int(11) NOT NULL DEFAULT 1, - `price` double NOT NULL DEFAULT 0 CHECK (`price` > 0), + `price` decimal(10,2) DEFAULT NULL, `bonus` double NOT NULL DEFAULT 0, `isVolumetric` tinyint(1) NOT NULL DEFAULT 0, `inflation` decimal(5,2) NOT NULL DEFAULT 1.00, @@ -41264,11 +41269,14 @@ CREATE TABLE `zone` ( `code` varchar(45) DEFAULT NULL, `editorFk` int(10) unsigned DEFAULT NULL, `itemMaxLength` int(11) DEFAULT NULL COMMENT 'Longitud maxima para articulos acostados que esa agencia puede transportar', + `addressFk` int(11) DEFAULT NULL COMMENT 'Punto de distribución de donde salen para repartir', PRIMARY KEY (`id`), KEY `fk_zone_2_idx` (`agencyModeFk`), KEY `zone_name_idx` (`name`), KEY `zone_fk_editor` (`editorFk`), + KEY `zone_address_FK` (`addressFk`), CONSTRAINT `fk_zone_2` FOREIGN KEY (`agencyModeFk`) REFERENCES `agencyMode` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION, + CONSTRAINT `zone_address_FK` FOREIGN KEY (`addressFk`) REFERENCES `address` (`id`) ON UPDATE CASCADE, CONSTRAINT `zone_fk_editor` FOREIGN KEY (`editorFk`) REFERENCES `account`.`user` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci; /*!40101 SET character_set_client = @saved_cs_client */; @@ -41318,7 +41326,10 @@ CREATE TABLE `zoneConfig` ( `id` int(10) unsigned NOT NULL, `scope` int(10) unsigned NOT NULL, `forwardDays` int(10) NOT NULL DEFAULT 7 COMMENT 'days forward to show zone_upcomingDeliveries', + `defaultAddressFk` int(11) DEFAULT NULL COMMENT 'Punto de distribución por defecto', PRIMARY KEY (`id`), + KEY `zoneConfig_address_FK` (`defaultAddressFk`), + CONSTRAINT `zoneConfig_address_FK` FOREIGN KEY (`defaultAddressFk`) REFERENCES `address` (`id`) ON UPDATE CASCADE, CONSTRAINT `zoneConfig_check` CHECK (`id` = 1) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; /*!40101 SET character_set_client = @saved_cs_client */; @@ -43244,6 +43255,7 @@ BEGIN DECLARE vCurrentCommission INT; DECLARE vIsNotEUR INT; DECLARE vLastEntryFk INT; + DECLARE vLanded INT; SELECT count(*) INTO vIsNotEUR FROM currency c @@ -43259,23 +43271,25 @@ BEGIN RETURN IFNULL(vCommission, 0); ELSE + SELECT landed INTO vLanded + FROM travel + WHERE id = vTravelFk; + 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; + WHERE e.supplierFk = vSupplierFk + ORDER BY (vLanded <= tr.landed), 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; @@ -49455,7 +49469,7 @@ BEGIN JOIN claimDestination cd ON cd.id = ce.claimDestinationFk JOIN claim c ON c.id = ce.claimFk JOIN claimState cs ON cs.id = c.claimStateFk - WHERE cd.description NOT IN ('Bueno', 'Corregido') + WHERE cd.code NOT IN ('good', 'corrected', 'supplierClaim') AND NOT ce.isGreuge AND cs.code = 'resolved'; @@ -49480,7 +49494,7 @@ BEGIN JOIN claimDestination cd ON cd.id = ce.claimDestinationFk JOIN claim c ON c.id = ce.claimFk JOIN claimState cs ON cs.id = c.claimStateFk - WHERE cd.description NOT IN ('Bueno', 'Corregido') + WHERE cd.code NOT IN ('good', 'corrected', 'supplierClaim') AND NOT ce.isGreuge AND cs.code = 'resolved' AND c.isChargedToMana; @@ -49491,7 +49505,7 @@ BEGIN JOIN claim c ON c.id = ce.claimFk JOIN claimState cs ON cs.id = c.claimStateFk SET ce.isGreuge = TRUE - WHERE cd.description NOT IN ('Bueno', 'Corregido') + WHERE cd.code NOT IN ('good', 'corrected', 'supplierClaim') AND NOT ce.isGreuge AND cs.code = 'resolved'; @@ -49570,7 +49584,7 @@ BEGIN JOIN claimDestination cd ON cd.id = ce.claimDestinationFk JOIN claim c ON c.id = ce.claimFk JOIN claimState cs ON cs.id = c.claimStateFk - WHERE cd.description NOT IN ('Bueno', 'Corregido') + WHERE cd.code NOT IN ('good', 'corrected', 'supplierClaim') AND cs.code = 'resolved' AND c.ticketCreated >= util.VN_CURDATE() - INTERVAL 1 YEAR GROUP BY c.clientFk @@ -56857,67 +56871,6 @@ BEGIN UPDATE greugeConfig SET lastNotifyCheck = vTimeEnd; -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 `inventoryFailureAdd` */; -/*!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 `inventoryFailureAdd`() -BEGIN - -DECLARE done BOOL DEFAULT FALSE; -DECLARE vTicketFk INT; - -DECLARE rs CURSOR FOR - SELECT id FROM vn.ticket - WHERE shipped = util.yesterday() - AND clientFk = 400 - AND warehouseFk IN (1,44); - -DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; - -OPEN rs; - -FETCH rs INTO vTicketFk; - -WHILE NOT done DO - - INSERT INTO vn.inventoryFailure(dated, itemFk, quantity, value, warehouseFk, throwerFk) - SELECT t.shipped, - s.itemFk, - s.quantity, - b.buyingValue + b.freightValue + b.packageValue + b.comissionValue, - t.warehouseFk, - w.id - FROM vn.ticket t - JOIN vn.sale s ON s.ticketFk = t.id - LEFT JOIN cache.last_buy lb ON lb.warehouse_id = t.warehouseFk AND item_id = s.itemFk - LEFT JOIN vn.buy b ON b.id = lb.buy_id - LEFT JOIN vn.worker w ON w.code = LEFT(s.concept, 3) - WHERE t.id = vTicketFk - AND s.quantity > 0; - - FETCH rs INTO vTicketFk; - -END WHILE; - - -CLOSE rs; - - - - END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -57927,7 +57880,7 @@ BEGIN ii.cplusTaxBreakFk, ii.cplusSubjectOpFk, ii.siiTypeInvoiceInFk, - ii.cplusRectificationTypeFk, + ic.cplusRectificationTypeFk, ii.booked, IFNULL(a.isUeeMember, c.isUeeMember) isUeeMember, (c.id = cc.id) isSameCountry, @@ -57950,6 +57903,7 @@ BEGIN e.name expenseName FROM invoiceIn ii JOIN supplier s ON s.id = ii.supplierFk + LEFT JOIN invoiceInCorrection ic ON ic.correctingFk = ii.id LEFT JOIN province p ON p.id = s.provinceFk LEFT JOIN autonomy a ON a.id = p.autonomyFk JOIN country c ON c.id = s.countryFk @@ -62647,10 +62601,6 @@ BEGIN SET itemFk = vItemNew WHERE itemFk = vItemOld; - UPDATE inventoryFailure - SET itemFk = vItemNew - WHERE itemFk = vItemOld; - UPDATE genericAllocation SET itemFk = vItemNew WHERE itemFk = vItemOld; @@ -68721,10 +68671,11 @@ BEGIN TRUE, sc.userFk, s.id - FROM vn.sectorCollection sc - JOIN vn.sectorCollectionSaleGroup scsg ON scsg.sectorCollectionFk = sc.id - JOIN vn.saleGroupDetail sgd ON sgd.saleGroupFk = scsg.saleGroupFk - JOIN vn.state s ON s.code = 'OK PREVIOUS' + FROM sectorCollection sc + JOIN sectorCollectionSaleGroup scsg ON scsg.sectorCollectionFk = sc.id + JOIN saleGroupDetail sgd ON sgd.saleGroupFk = scsg.saleGroupFk + JOIN state s ON s.code = 'OK PREVIOUS' + JOIN itemShelvingSale iss ON iss.saleFk = sgd.saleFk WHERE sc.id = vSectorCollectionFk; END ;; DELIMITER ; @@ -73325,7 +73276,8 @@ BEGIN IFNULL(dest.nickname, origin.nickname) nickname, dest.landed, dest.preparation, - origin.departmentFk + origin.departmentFk, + origin.saleClonedFk FROM ( SELECT s.ticketFk, c.salesPersonFk workerFk, @@ -73346,11 +73298,13 @@ BEGIN t.warehouseFk, t.companyFk, t.agencyModeFk, - wd.departmentFk + wd.departmentFk, + sc.saleClonedFk FROM ticket t JOIN client c ON c.id = t.clientFk JOIN workerDepartment wd ON wd.workerFk = c.salesPersonFk JOIN sale s ON s.ticketFk = t.id + LEFT JOIN saleCloned sc ON sc.saleClonedFk = s.id JOIN saleVolume sv ON sv.saleFk = s.id JOIN item i ON i.id = s.itemFk JOIN ticketState ts ON ts.ticketFk = t.id @@ -77747,8 +77701,8 @@ BEGIN * @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'); + IF NOT vIsRaid AND vDaysInForward THEN + CALL util.throw('If daysInForward has a value, the raid cannot be unchecked'); END IF; END ;; DELIMITER ; @@ -78115,22 +78069,15 @@ BEGIN DECLARE vDone BOOL DEFAULT FALSE; DECLARE vBuyerEmail VARCHAR(40); DECLARE vTravelLink TEXT; - DECLARE vMailBody TEXT DEFAULT ''; + DECLARE vMailBody TEXT; + DECLARE vDaysBetweenDates INT; + DECLARE vSubject VARCHAR(30); - DECLARE vCur CURSOR FOR - 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 vTravels CURSOR FOR + SELECT GROUP_CONCAT(DISTINCT travelLink ORDER BY id SEPARATOR '\n\r'), + buyerEmail + FROM tTravelToMove + GROUP BY buyerEmail; DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE; @@ -78141,35 +78088,50 @@ BEGIN END; CREATE OR REPLACE TEMPORARY TABLE tTravelToMove - SELECT id travelFk, - util.VN_CURDATE() + INTERVAL daysInForward DAY newLanded - FROM travel + WITH travels AS ( + SELECT id, + CONCAT('https://salix.verdnatura.es/#!/travel/', id,'/summary') travelLink, + util.VN_CURDATE() + INTERVAL daysInForward DAY newLanded, + util.VN_CURDATE() - INTERVAL DATEDIFF(landed, shipped) + daysInForward DAY newShipped + FROM vn.travel WHERE isRaid - AND daysInForward; + AND daysInForward + )SELECT t.id, + t.travelLink, + t.newLanded, + t.newShipped, + CONCAT(u.name, '@verdnatura.es') buyerEmail + FROM travels t + STRAIGHT_JOIN vn.entry e ON e.travelFk = t.id + JOIN vn.buy b ON b.entryFk = e.id + JOIN vn.item i ON i.id = b.itemFk + JOIN vn.itemType it ON it.id = i.typeFk + JOIN account.user u ON u.id = it.workerFk + GROUP BY t.id; START TRANSACTION; UPDATE travel tr - JOIN tTravelToMove ttm ON ttm.travelFk = tr.id - SET tr.landed = ttm.newLanded; + JOIN tTravelToMove ttm ON ttm.id = tr.id + SET tr.landed = ttm.newLanded, + tr.shipped = ttm.newShipped; - OPEN vCur; + OPEN vTravels; l: LOOP SET vDone = FALSE; - FETCH vCur INTO vTravelLink, vBuyerEmail; + FETCH vTravels INTO vTravelLink, vBuyerEmail; IF vDone THEN LEAVE l; END IF; - CALL `vn`.`mail_insert`( - vBuyerEmail, - 'noreply@verdnatura.es', - 'Cambio de fecha en Redadas', - CONCAT('Se ha movido los siguientes travels: \n\r ', vTravelLink)); + SET vSubject = 'Cambio de fecha en Redadas', + vMailBody = CONCAT('Se ha movido los siguientes travels: \n\r ', vTravelLink); + + CALL mail_insert(vBuyerEmail, 'noreply@verdnatura.es', vSubject, vMailBody); END LOOP; - CLOSE vCur; + CLOSE vTravels; COMMIT; DROP TEMPORARY TABLE tTravelToMove; END ;; @@ -85618,24 +85580,6 @@ USE `bi`; /*!50001 SET character_set_results = @saved_cs_results */; /*!50001 SET collation_connection = @saved_col_connection */; --- --- Final view structure for view `rotacion` --- - -/*!50001 DROP VIEW IF EXISTS `rotacion`*/; -/*!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 `rotacion` AS select `ic`.`itemFk` AS `Id_Article`,`ic`.`warehouseFk` AS `warehouse_id`,`ic`.`quantity` AS `total`,`ic`.`rotation` AS `rotacion`,`ic`.`cm3` AS `cm3`,`ic`.`storage` AS `almacenaje`,`ic`.`handling` AS `manipulacion`,`ic`.`extraCharge` AS `auxiliar`,`ic`.`wasted` AS `mermas`,`ic`.`cm3delivery` AS `cm3reparto`,`ic`.`grams` AS `grams` from `vn`.`itemCost` `ic` */; -/*!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 `tarifa_componentes` -- @@ -90949,4 +90893,4 @@ USE `vn2008`; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2024-12-10 8:17:51 +-- Dump completed on 2025-01-14 6:39:04 diff --git a/db/dump/.dump/triggers.sql b/db/dump/.dump/triggers.sql index 3299aea37..fb72e9899 100644 --- a/db/dump/.dump/triggers.sql +++ b/db/dump/.dump/triggers.sql @@ -5701,7 +5701,7 @@ BEGIN SET NEW.editorFk = account.myUser_getId(); - IF (SELECT COUNT(*) FROM vn.invoiceIn + IF (SELECT COUNT(*) FROM invoiceIn WHERE supplierRef = NEW.supplierRef AND supplierFk = NEW.supplierFk AND YEAR(issued) = YEAR(NEW.issued) @@ -5713,7 +5713,7 @@ BEGIN IF NEW.supplierFk != OLD.supplierFk THEN CALL supplier_checkIsActive(NEW.supplierFk); SELECT withholdingSageFk INTO vWithholdingSageFk - FROM vn.supplier + FROM supplier WHERE id = NEW.supplierFk; SET NEW.withholdingSageFk = vWithholdingSageFk; END IF; @@ -5737,25 +5737,31 @@ DELIMITER ;; AFTER UPDATE ON `invoiceIn` FOR EACH ROW BEGIN - IF NEW.issued != OLD.issued - OR NEW.currencyFk != OLD.currencyFk THEN + DECLARE vIsEuro BOOL; + + SELECT `code` = 'EUR' INTO vIsEuro + FROM currency + WHERE id = NEW.currencyFk; + + IF (NOT NEW.issued <=> OLD.issued + OR NEW.currencyFk <> OLD.currencyFk) THEN UPDATE invoiceInTax iit JOIN invoiceIn ii ON ii.id = iit.invoiceInFk LEFT JOIN referenceRate rr ON rr.dated = ii.issued AND rr.currencyFk = ii.currencyFk - SET iit.taxableBase = IF(iit.foreignValue IS NULL, iit.taxableBase, iit.foreignValue / rr.value) + SET iit.taxableBase = IF(vIsEuro, iit.taxableBase, iit.foreignValue / rr.value), + iit.foreignValue = IF(vIsEuro, NULL, iit.foreignValue) WHERE ii.id = NEW.id; UPDATE invoiceInDueDay iidd JOIN invoiceIn ii ON ii.id = iidd.invoiceInFk LEFT JOIN referenceRate rr ON rr.dated = ii.issued AND rr.currencyFk = ii.currencyFk - SET iidd.amount = IF(iidd.foreignValue IS NULL, iidd.amount, iidd.foreignValue / rr.value) + SET iidd.amount = IF(vIsEuro, iidd.amount, iidd.foreignValue / rr.value), + iidd.foreignValue = IF(vIsEuro, NULL, iidd.foreignValue) WHERE ii.id = NEW.id; - END IF; - END */;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -8161,6 +8167,7 @@ BEGIN OR !(NEW.workerFk <=> OLD.workerFk) OR !(NEW.m3 <=> OLD.m3) OR !(NEW.agencyModeFk <=> OLD.agencyModeFk) + OR !(NEW.dated <=> OLD.dated) OR !(NEW.vehicleFk <=> OLD.vehicleFk)THEN CALL route_calcCommission(NEW.id); END IF; @@ -10582,6 +10589,10 @@ 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 @@ -11488,4 +11499,4 @@ USE `vn2008`; /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2024-12-10 8:18:11 +-- Dump completed on 2025-01-14 6:39:25 diff --git a/db/dump/fixtures.before.sql b/db/dump/fixtures.before.sql index afb10094b..590fe34b6 100644 --- a/db/dump/fixtures.before.sql +++ b/db/dump/fixtures.before.sql @@ -158,13 +158,13 @@ INSERT INTO `account`.`mailForward`(`account`, `forwardTo`) -INSERT INTO `vn`.`currency`(`id`, `code`, `name`, `ratio`) +INSERT INTO `vn`.`currency`(`id`, `code`, `name`, `ratio`, `hasToDownloadRate`) VALUES - (1, 'EUR', 'Euro', 1), - (2, 'USD', 'Dollar USA', 1.4), - (3, 'GBP', 'Libra', 1), - (4, 'JPY', 'Yen Japones', 1), - (5, 'CNY', 'Yuan Chino', 1.2); + (1, 'EUR', 'Euro', 1, FALSE), + (2, 'USD', 'Dollar USA', 1.4, TRUE), + (3, 'GBP', 'Libra', 1, TRUE), + (4, 'JPY', 'Yen Japones', 1, FALSE), + (5, 'CNY', 'Yuan Chino', 1.2, TRUE); INSERT INTO `vn`.`country`(`id`, `name`, `isUeeMember`, `code`, `currencyFk`, `ibanLength`, `continentFk`, `hasDailyInvoice`, `CEE`) VALUES @@ -426,50 +426,50 @@ INSERT INTO `vn`.`clientConfig`(`id`, `riskTolerance`, `maxCreditRows`, `maxPric (1, 200, 10, 0.25, 2, 4, 5, 300.00, 1, 1, 2); -INSERT INTO `vn`.`address`(`id`, `nickname`, `street`, `city`, `postalCode`, `provinceFk`, `phone`, `mobile`, `isActive`, `clientFk`, `agencyModeFk`, `longitude`, `latitude`, `isEqualizated`, `isDefaultAddress`) +INSERT INTO `vn`.`address`(`id`, `nickname`, `street`, `city`, `postalCode`, `provinceFk`, `phone`, `mobile`, `isActive`, `clientFk`, `agencyModeFk`, `longitude`, `latitude`, `isEqualizated`, `isDefaultAddress`, `customsAgentFk`) VALUES - (1, 'Bruce Wayne', '1007 Mountain Drive, Gotham', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1101, 2, NULL, NULL, 0, 1), - (2, 'Petter Parker', '20 Ingram Street', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1102, 2, NULL, NULL, 0, 1), - (3, 'Clark Kent', '344 Clinton Street', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1103, 2, NULL, NULL, 0, 1), - (4, 'Tony Stark', '10880 Malibu Point', 'Gotham', 46460, 1, 1111111111, 222222222, 1 , 1104, 2, NULL, NULL, 0, 1), - (5, 'Max Eisenhardt', 'Unknown Whereabouts', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1105, 2, NULL, NULL, 0, 1), - (6, 'DavidCharlesHaller', 'Evil hideout', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1106, 2, NULL, NULL, 0, 1), - (7, 'Hank Pym', 'Anthill', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1107, 2, NULL, NULL, 0, 1), - (8, 'Charles Xavier', '3800 Victory Pkwy, Cincinnati, OH 45207, USA', 'Gotham', 46460, 5, 1111111111, 222222222, 1, 1108, 2, NULL, NULL, 0, 1), - (9, 'Bruce Banner', 'Somewhere in New York', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 1), - (10, 'Jessica Jones', 'NYCC 2015 Poster', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1110, 2, NULL, NULL, 0, 1), - (11, 'Missing', 'The space', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1111, 10, NULL, NULL, 0, 1), - (12, 'Trash', 'New York city', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1112, 10, NULL, NULL, 0, 1), - (101, 'Somewhere in Thailand', 'address 01', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0), - (102, 'Somewhere in Poland', 'address 02', 'Gotham', 46460, 1, 3333333333, 444444444, 1, 1109, 2, NULL, NULL, 0, 0), - (103, 'Somewhere in Japan', 'address 03', 'Gotham', 46460, 1, 3333333333, 444444444, 1, 1109, 2, NULL, NULL, 0, 0), - (104, 'Somewhere in Spain', 'address 04', 'Gotham', 46460, 1, 3333333333, 444444444, 1, 1109, 2, NULL, NULL, 0, 0), - (105, 'Somewhere in Potugal', 'address 05', 'Gotham', 46460, 1, 5555555555, 666666666, 1, 1109, 2, NULL, NULL, 0, 0), - (106, 'Somewhere in UK', 'address 06', 'Gotham', 46460, 1, 5555555555, 666666666, 1, 1109, 2, NULL, NULL, 0, 0), - (107, 'Somewhere in Valencia', 'address 07', 'Gotham', 46460, 1, 5555555555, 666666666, 1, 1109, 2, NULL, NULL, 0, 0), - (108, 'Somewhere in Gotham', 'address 08', 'Gotham', 46460, 1, 5555555555, 666666666, 1, 1109, 2, NULL, NULL, 0, 0), - (109, 'Somewhere in London', 'address 09', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0), - (110, 'Somewhere in Algemesi', 'address 10', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0), - (111, 'Somewhere in Carlet', 'address 11', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0), - (112, 'Somewhere in Campanar', 'address 12', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0), - (113, 'Somewhere in Malilla', 'address 13', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0), - (114, 'Somewhere in France', 'address 14', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0), - (115, 'Somewhere in Birmingham', 'address 15', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0), - (116, 'Somewhere in Scotland', 'address 16', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0), - (117, 'Somewhere in nowhere', 'address 17', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0), - (118, 'Somewhere over the rainbow', 'address 18', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0), - (119, 'Somewhere in Alberic', 'address 19', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0), - (120, 'Somewhere in Montortal', 'address 20', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0), - (121, 'the bat cave', 'address 21', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1101, 2, NULL, NULL, 0, 0), - (122, 'NY roofs', 'address 22', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1102, 2, NULL, NULL, 0, 0), - (123, 'The phone box', 'address 23', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1103, 2, NULL, NULL, 0, 0), - (124, 'Stark tower Gotham', 'address 24', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1104, 2, NULL, NULL, 0, 0), - (125, 'The plastic cell', 'address 25', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1105, 2, NULL, NULL, 0, 0), - (126, 'Many places', 'address 26', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1106, 2, NULL, NULL, 0, 0), - (127, 'Your pocket', 'address 27', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1107, 2, NULL, NULL, 0, 0), - (128, 'Cerebro', 'address 28', 'Gotham', 46460, 5, 1111111111, 222222222, 1, 1108, 2, NULL, NULL, 0, 0), - (129, 'Luke Cages Bar', 'address 29', 'Gotham', 'EC170150', 1, 1111111111, 222222222, 1, 1110, 2, NULL, NULL, 0, 0), - (130, 'Non valid address', 'address 30', 'Gotham', 46460, 1, 1111111111, 222222222, 0, 1101, 2, NULL, NULL, 0, 0); + (1, 'Bruce Wayne', '1007 Mountain Drive, Gotham', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1101, 2, -74.1111111, 10.1111111, 0, 1, 1), + (2, 'Petter Parker', '20 Ingram Street', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1102, 2, -74.2222222, 10.2222222, 0, 1, NULL), + (3, 'Clark Kent', '344 Clinton Street', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1103, 2, -74.3333333, 10.3333333, 0, 1, NULL), + (4, 'Tony Stark', '10880 Malibu Point', 'Gotham', 46460, 1, 1111111111, 222222222, 1 , 1104, 2, -74.4444444, 10.4444444, 0, 1, NULL), + (5, 'Max Eisenhardt', 'Unknown Whereabouts', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1105, 2, NULL, NULL, 0, 1, NULL), + (6, 'DavidCharlesHaller', 'Evil hideout', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1106, 2, NULL, NULL, 0, 1, NULL), + (7, 'Hank Pym', 'Anthill', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1107, 2, NULL, NULL, 0, 1, NULL), + (8, 'Charles Xavier', '3800 Victory Pkwy, Cincinnati, OH 45207, USA', 'Gotham', 46460, 5, 1111111111, 222222222, 1, 1108, 2, NULL, NULL, 0, 1, NULL), + (9, 'Bruce Banner', 'Somewhere in New York', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 1, NULL), + (10, 'Jessica Jones', 'NYCC 2015 Poster', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1110, 2, NULL, NULL, 0, 1, NULL), + (11, 'Missing', 'The space', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1111, 10, NULL, NULL, 0, 1, NULL), + (12, 'Trash', 'New York city', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1112, 10, NULL, NULL, 0, 1, NULL), + (101, 'Somewhere in Thailand', 'address 01', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (102, 'Somewhere in Poland', 'address 02', 'Gotham', 46460, 1, 3333333333, 444444444, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (103, 'Somewhere in Japan', 'address 03', 'Gotham', 46460, 1, 3333333333, 444444444, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (104, 'Somewhere in Spain', 'address 04', 'Gotham', 46460, 1, 3333333333, 444444444, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (105, 'Somewhere in Potugal', 'address 05', 'Gotham', 46460, 1, 5555555555, 666666666, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (106, 'Somewhere in UK', 'address 06', 'Gotham', 46460, 1, 5555555555, 666666666, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (107, 'Somewhere in Valencia', 'address 07', 'Gotham', 46460, 1, 5555555555, 666666666, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (108, 'Somewhere in Gotham', 'address 08', 'Gotham', 46460, 1, 5555555555, 666666666, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (109, 'Somewhere in London', 'address 09', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (110, 'Somewhere in Algemesi', 'address 10', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (111, 'Somewhere in Carlet', 'address 11', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (112, 'Somewhere in Campanar', 'address 12', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (113, 'Somewhere in Malilla', 'address 13', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (114, 'Somewhere in France', 'address 14', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (115, 'Somewhere in Birmingham', 'address 15', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (116, 'Somewhere in Scotland', 'address 16', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (117, 'Somewhere in nowhere', 'address 17', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (118, 'Somewhere over the rainbow', 'address 18', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (119, 'Somewhere in Alberic', 'address 19', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (120, 'Somewhere in Montortal', 'address 20', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (121, 'the bat cave', 'address 21', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1101, 2, NULL, NULL, 0, 0, NULL), + (122, 'NY roofs', 'address 22', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1102, 2, NULL, NULL, 0, 0, NULL), + (123, 'The phone box', 'address 23', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1103, 2, -74.555555, 10.555555, 0, 0, NULL), + (124, 'Stark tower Gotham', 'address 24', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1104, 2, NULL, NULL, 0, 0, NULL), + (125, 'The plastic cell', 'address 25', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1105, 2, NULL, NULL, 0, 0, NULL), + (126, 'Many places', 'address 26', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1106, 2, NULL, NULL, 0, 0, NULL), + (127, 'Your pocket', 'address 27', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1107, 2, NULL, NULL, 0, 0, NULL), + (128, 'Cerebro', 'address 28', 'Gotham', 46460, 5, 1111111111, 222222222, 1, 1108, 2, NULL, NULL, 0, 0, NULL), + (129, 'Luke Cages Bar', 'address 29', 'Gotham', 'EC170150', 1, 1111111111, 222222222, 1, 1110, 2, NULL, NULL, 0, 0, NULL), + (130, 'Non valid address', 'address 30', 'Gotham', 46460, 1, 1111111111, 222222222, 0, 1101, 2, NULL, NULL, 0, 0, NULL); INSERT INTO `vn`.`address`( `nickname`, `street`, `city`, `postalCode`, `provinceFk`, `isActive`, `clientFk`, `agencyModeFk`, `isDefaultAddress`) SELECT name, CONCAT(name, 'Street'), 'GOTHAM', 46460, 1, 1, id, 2, 1 @@ -648,13 +648,13 @@ INSERT INTO `vn`.`invoiceOutSerial` ('X', 'Exportación global', 0, 'WORLD', 0, 'global'), ('N', 'Múltiple Intracomunitaria', 0, 'CEE', 1, 'multiple'); -INSERT INTO `vn`.`invoiceOut`(`id`, `serial`, `amount`, `issued`,`clientFk`, `created`, `companyFk`, `dued`, `booked`, `bankFk`, `hasPdf`) +INSERT INTO `vn`.`invoiceOut`(`id`, `serial`, `amount`, `issued`,`clientFk`, `created`, `companyFk`, `dued`, `booked`, `bankFk`, `hasPdf`, `customsAgentFk`, `incotermsFk`) VALUES - (1, 'T', 1026.24, util.VN_CURDATE(), 1101, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0), - (2, 'T', 121.36, util.VN_CURDATE(), 1102, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0), - (3, 'T', 8.88, util.VN_CURDATE(), 1103, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0), - (4, 'T', 8.88, util.VN_CURDATE(), 1104, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0), - (5, 'A', 8.88, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1103, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 442, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 0); + (1, 'E', 1026.24, util.VN_CURDATE(), 1101, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0, 1, 'FAS'), + (2, 'T', 121.36, util.VN_CURDATE(), 1102, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0, NULL, NULL), + (3, 'T', 8.88, util.VN_CURDATE(), 1103, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0, NULL, NULL), + (4, 'T', 8.88, util.VN_CURDATE(), 1104, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0, NULL, NULL), + (5, 'A', 8.88, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1103, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 442, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 0, NULL, NULL); UPDATE `vn`.`invoiceOut` SET ref = 'T1111111' WHERE id = 1; UPDATE `vn`.`invoiceOut` SET ref = 'T2222222' WHERE id = 2; @@ -694,22 +694,22 @@ INSERT INTO `vn`.`invoiceOutExpense`(`id`, `invoiceOutFk`, `amount`, `expenseFk` (6, 4, 8.07, 2000000000, util.VN_CURDATE()), (7, 5, 8.07, 2000000000, util.VN_CURDATE()); -INSERT INTO `vn`.`zone` (`id`, `name`, `hour`, `agencyModeFk`, `travelingDays`, `price`, `bonus`, `itemMaxSize`) - VALUES - (1, 'Zone pickup A', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 1, 0, 1, 0, 100), - (2, 'Zone pickup B', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 1, 0, 1, 0, 100), - (3, 'Zone 247 A', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 7, 1, 2, 0, 100), - (4, 'Zone 247 B', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 7, 1, 2, 0, 100), - (5, 'Zone expensive A', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 8, 1, 1000, 0, 100), - (6, 'Zone expensive B', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 8, 1, 1000, 0, 100), - (7, 'Zone refund', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 23, 0, 1, 0, 100), - (8, 'Zone others', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 10, 0, 1, 0, 100), - (9, 'Zone superMan', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 2, 0, 1, 0, 100), - (10, 'Zone teleportation', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 3, 0, 1, 0, 100), - (11, 'Zone pickup C', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 1, 0, 1, 0, 100), - (12, 'Zone entanglement', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 4, 0, 1, 0, 100), - (13, 'Zone quantum break', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 5, 0, 1, 0, 100); - +INSERT INTO `vn`.`zone` + (`id`, `name`, `hour`, `agencyModeFk`, `travelingDays`, `price`, `bonus`, `itemMaxSize`, `priceOptimum`) +VALUES + (1, 'Zone pickup A', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 1, 0, 1, 0, 100, 1), + (2, 'Zone pickup B', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 1, 0, 1, 0, 100, 1), + (3, 'Zone 247 A', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 7, 1, 2, 0, 100, 1), + (4, 'Zone 247 B', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 7, 1, 2, 0, 100, 1), + (5, 'Zone expensive A', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 8, 1, 1000, 0, 100, 500), + (6, 'Zone expensive B', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 8, 1, 1000, 0, 100, 500), + (7, 'Zone refund', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 23, 0, 1, 0, 100, 0.5), + (8, 'Zone others', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 10, 0, 1, 0, 100, 0.5), + (9, 'Zone superMan', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 2, 0, 1, 0, 100, 0.5), + (10, 'Zone teleportation', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 3, 0, 1, 0, 100, 0.5), + (11, 'Zone pickup C', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 1, 0, 1, 0, 100, 0.5), + (12, 'Zone entanglement', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 4, 0, 1, 0, 100, 0.5), + (13, 'Zone quantum break', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 5, 0, 1, 0, 100, 0.5); INSERT INTO `vn`.`zoneWarehouse` (`id`, `zoneFk`, `warehouseFk`) VALUES @@ -974,26 +974,30 @@ INSERT INTO `vn`.`itemFamily`(`code`, `description`) ('SER', 'Services'), ('VT', 'Sales'); -INSERT INTO `vn`.`item`(`id`, `typeFk`, `stems`, `originFk`, `description`, `producerFk`, `intrastatFk`, `expenseFk`, - `comment`, `relevancy`, `image`, `subName`, `minPrice`, `family`, `isFloramondo`, `genericFk`, `itemPackingTypeFk`, `hasMinPrice`, `weightByPiece`) - VALUES - (1, 2, 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '1', NULL, 0, 'EMB', 0, NULL, 'V', 0, 3), - (2, 2, 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '2', NULL, 0, 'VT', 0, NULL, 'H', 0, 2), - (3, 1, 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '3', NULL, 0, 'VT', 0, NULL, NULL, 0, 5), - (4, 1, 1, 1, 'Increases block', 1, 05080000, 4751000000, NULL, 0, '4', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL), - (5, 3, 1, 2, NULL, 2, 06021010, 4751000000, NULL, 0, '5', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL), - (6, 5, 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '6', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL), - (7, 5, 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '7', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL), - (8, 2, 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '8', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL), - (9, 2, 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '9', NULL, 0, 'VT', 1, NULL, NULL, 0, NULL), - (10, 1, 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '10', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL), - (11, 1, 1, 1, NULL, 1, 05080000, 4751000000, NULL, 0, '11', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL), - (12, 3, 1, 2, NULL, 2, 06021010, 4751000000, NULL, 0, '12', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL), - (13, 5, 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '13', NULL, 1, 'VT', 1, NULL, NULL, 1, NULL), - (14, 5, 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 'VT', 1, NULL, NULL, 0, NULL), - (15, 4, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 'EMB', 0, NULL, NULL, 0, NULL), - (16, 6, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 'EMB', 0, NULL, NULL, 0, NULL), - (71, 6, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL); +INSERT INTO `vn`.`item`( + `id`, `typeFk`, `stems`, `originFk`, `description`, `producerFk`, `intrastatFk`, `expenseFk`, + `comment`, `relevancy`, `image`, `subName`, `minPrice`, `family`, `isFloramondo`, `genericFk`, + `itemPackingTypeFk`, `hasMinPrice`, `weightByPiece`, `isCustomInspectionRequired` +) +VALUES + (1, 2, 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '1', NULL, 0, 'EMB', 0, NULL, 'V', 0, 3, 1), + (2, 2, 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '2', NULL, 0, 'VT', 0, NULL, 'H', 0, 2, 1), + (3, 1, 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '3', NULL, 0, 'VT', 0, NULL, NULL, 0, 5, 0), + (4, 1, 1, 1, 'Increases block', 1, 05080000, 4751000000, NULL, 0, '4', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL, 0), + (5, 3, 1, 2, NULL, 2, 06021010, 4751000000, NULL, 0, '5', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL, 0), + (6, 5, 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '6', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL, 0), + (7, 5, 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '7', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL, 0), + (8, 2, 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '8', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL, 0), + (9, 2, 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '9', NULL, 0, 'VT', 1, NULL, NULL, 0, NULL, 0), + (10, 1, 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '10', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL, 0), + (11, 1, 1, 1, NULL, 1, 05080000, 4751000000, NULL, 0, '11', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL, 0), + (12, 3, 1, 2, NULL, 2, 06021010, 4751000000, NULL, 0, '12', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL, 0), + (13, 5, 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '13', NULL, 1, 'VT', 1, NULL, NULL, 1, NULL, 0), + (14, 5, 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 'VT', 1, NULL, NULL, 0, NULL, 0), + (15, 4, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 'EMB', 0, NULL, NULL, 0, NULL, 0), + (16, 6, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 'EMB', 0, NULL, NULL, 0, NULL, 0), + (71, 6, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL, 0); + -- Update the taxClass after insert of the items UPDATE `vn`.`itemTaxCountry` SET `taxClassFk` = 2 @@ -1516,7 +1520,8 @@ INSERT INTO `vn`.`travel`(`id`,`shipped`, `landed`, `warehouseInFk`, `warehouseO (8, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 5, 1, 1, 50.00, 500, 'eight travel', 1, 2, 10, FALSE, NULL), (10, DATE_ADD(util.VN_CURDATE(), INTERVAL +5 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL +5 DAY), 5, 1, 1, 50.00, 500, 'nineth travel', 1, 2, 10, TRUE, 2), (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); + (12, util.VN_CURDATE() , util.VN_CURDATE() + INTERVAL 1 DAY, 6, 3, 0, 50.00, 500, 'eleventh travel', 1, 2, 4, FALSE, NULL), + (13, util.VN_CURDATE() - INTERVAL 1 MONTH - INTERVAL 1 DAY, util.VN_CURDATE() - INTERVAL 1 MONTH, 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`, `typeFk`) VALUES @@ -1529,8 +1534,9 @@ INSERT INTO `vn`.`entry`(`id`, `supplierFk`, `created`, `travelFk`, `isConfirmed (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'), - (11, 4, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 1, 442, 'IN2001', 'Movement 11',0, '', 'product'), + (10, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL +2 DAY), 10, 0, 442, 'IN2010', 'Movement 10',1, '', 'product'), + (11, 4, DATE_ADD(util.VN_CURDATE(), INTERVAL -2 MONTH), 1, 1, 442, 'IN2011', 'Movement 11',0, '', 'product'), + (12, 4, util.VN_CURDATE() - INTERVAL 1 MONTH, 13, 1, 442, 'IN2012', 'Movement 12',0, '', 'product'), (99, 69, util.VN_CURDATE() - INTERVAL 1 MONTH, 11, 0, 442, 'IN2009', 'Movement 99',0, '', 'product'); INSERT INTO `vn`.`entryConfig` (`defaultEntry`, `inventorySupplierFk`, `defaultSupplierFk`) @@ -1572,7 +1578,8 @@ INSERT INTO `bs`.`waste`(`buyerFk`, `year`, `week`, `itemFk`, `itemTypeFk`, `sal (14, 7, 2, 5, 0, 3, 1, 2.000, 2.000, 0.000, 10, 10, 'grouping', NULL, 0.00, 7.30, 7.00, 0, 1, 0, 4, util.VN_CURDATE()), (15, 7, 4, 1.25, 0, 3, 1, 2.000, 2.000, 0.000, 10, 10, 'grouping', NULL, 0.00, 1.75, 1.67, 0, 1, 0, 4, util.VN_CURDATE()), (16, 99,1,50.0000, 5000, 4, 1, 1.500, 1.500, 0.000, 1, 1, 'packing', NULL, 0.00, 99.60, 99.40, 0, 1, 0, 1.00, '2024-07-30 08:13:51.000'), - (17, 11, 1, 50, 5000, 4, 1, 1.500, 1.500, 0.000, 1, 1, 'packing', NULL, 0.00, 99.6, 99.4, 0, 1, 0, 1, util.VN_CURDATE() - INTERVAL 2 MONTH); + (17, 11, 1, 50, 5000, 4, 1, 1.500, 1.500, 0.000, 1, 1, 'packing', NULL, 0.00, 99.6, 99.4, 0, 1, 0, 1, util.VN_CURDATE() - INTERVAL 2 MONTH), + (18, 12, 1, 50, 5000, 4, 1, 1.500, 1.500, 0.000, 1, 1, 'grouping', NULL, 0.00, 99.6, 99.4, 0, 1, 0, 1, util.VN_CURDATE() - INTERVAL 2 MONTH); INSERT INTO `hedera`.`order`(`id`, `date_send`, `customer_id`, `delivery_method_id`, `agency_id`, `address_id`, `company_id`, `note`, `source_app`, `confirmed`,`total`, `date_make`, `first_row_stamp`, `confirm_date`) VALUES @@ -1922,7 +1929,7 @@ INSERT INTO `vn`.`claimDestination`(`id`, `description`, `addressFk`) INSERT INTO `vn`.`claimDevelopment`(`id`, `claimFk`, `claimResponsibleFk`, `workerFk`, `claimReasonFk`, `claimResultFk`, `claimRedeliveryFk`, `claimDestinationFk`) VALUES - (1, 1, 1, 21, 1, 1, 2, 5), + (1, 1, 1, 21, 7, 1, 2, 5), (2, 1, 2, 21, 7, 2, 2, 5), (3, 2, 7, 21, 9, 3, 2, 5), (4, 3, 7, 21, 15, 8, 2, 5), @@ -3965,7 +3972,7 @@ VALUES(1, ''); INSERT INTO dipole.expedition_PrintOut (expeditionFk, ticketFk, addressFk, street, postalCode, city, shopName, isPrinted, created, printerFk, routeFk, parkingCode, truckName, clientFk, phone, province, agency, m3, workerCode, itemFk, quantity, longName, shelvingFk, comments) -VALUES(1, 1, 0, ' ', ' ', ' ', ' ', 0, '2001-01-01 00:00:00', 1, 0, ' ', ' ', 0, NULL, '', NULL, 0.000, NULL, 10, NULL, NULL, 'NCC', NULL); +VALUES(1, 1, 0, ' ', ' ', ' ', ' ', 0, '2001-01-01 00:00:00', 1, 0, ' ', ' ', 0, NULL, '', NULL, 0.000, NULL, 10, NULL, 'Ranged Reinforced weapon sniper rifle 700mm' , 'NCC', NULL); INSERT INTO vn.accountDetail (id, value, accountDetailTypeFk, supplierAccountFk) @@ -4038,7 +4045,14 @@ INSERT IGNORE INTO vn.saySimpleConfig (url, defaultChannel) INSERT INTO vn.workerIrpf (workerFk,spouseNif, geographicMobilityDate) VALUES (1106,'26493101E','2019-09-20'); +INSERT INTO vn.referenceRate (currencyFk, dated, value) + VALUES (2, '2000-12-01', 1.0495), + (2, '2001-01-01', 1.0531), + (2, '2001-02-01', 7.6347); + +INSERT IGNORE INTO vn.osrmConfig (id,url,tolerance) + VALUES (1,'https://router.project-osrm.org', 0.002); INSERT IGNORE INTO vn.inventoryConfig SET id = 1, - supplierFk = 4; \ No newline at end of file + supplierFk = 4; diff --git a/db/routines/bs/procedures/waste_addSales.sql b/db/routines/bs/procedures/waste_addSales.sql index ea4adbc27..4a34d74b3 100644 --- a/db/routines/bs/procedures/waste_addSales.sql +++ b/db/routines/bs/procedures/waste_addSales.sql @@ -10,19 +10,27 @@ BEGIN * @param vDateFrom Fecha desde * @param vDateTo Fecha hasta */ - IF vDateFrom IS NULL THEN - SET vDateFrom = util.VN_CURDATE() - INTERVAL WEEKDAY(util.VN_CURDATE()) DAY; + DECLARE vDaysInYear INT; + SET vDaysInYear = DATEDIFF(util.lastDayOfYear(CURDATE()), util.firstDayOfYear(CURDATE())); + + SET vDateFrom = COALESCE(vDateFrom, util.VN_CURDATE()); + SET vDateTo = COALESCE(vDateTo, util.VN_CURDATE()); + + IF DATEDIFF(vDateTo, vDateFrom) > vDaysInYear THEN + CALL util.throw('The period cannot be longer than one year'); END IF; - IF vDateTo IS NULL THEN - SET vDateTo = vDateFrom + INTERVAL 6 DAY; - END IF; + -- Obtiene el primer día de la semana de esa fecha + SET vDateFrom = DATE_SUB(vDateFrom, INTERVAL ((WEEKDAY(vDateFrom) + 1) % 7) DAY); + + -- Obtiene el último día de la semana de esa fecha + SET vDateTo = DATE_ADD(vDateTo, INTERVAL (6 - ((WEEKDAY(vDateTo) + 1) % 7)) DAY); CALL cache.last_buy_refresh(FALSE); REPLACE bs.waste - SELECT YEAR(t.shipped), - WEEK(t.shipped, 4), + SELECT YEARWEEK(t.shipped, 6) DIV 100, + WEEK(t.shipped, 6), it.workerFk, it.id, s.itemFk, @@ -68,8 +76,8 @@ BEGIN JOIN cache.last_buy lb ON lb.item_id = i.id AND lb.warehouse_id = w.id JOIN vn.buy b ON b.id = lb.buy_id - WHERE t.shipped BETWEEN vDateFrom AND vDateTo + WHERE t.shipped BETWEEN vDateFrom AND util.dayEnd(vDateTo) AND w.isManaged - GROUP BY YEAR(t.shipped), WEEK(t.shipped, 4), i.id; + GROUP BY YEARWEEK(t.shipped, 6) DIV 100, WEEK(t.shipped, 6), i.id; END$$ DELIMITER ; diff --git a/db/routines/hedera/procedures/order_confirmWithUser.sql b/db/routines/hedera/procedures/order_confirmWithUser.sql index 644d68a87..db83cba5c 100644 --- a/db/routines/hedera/procedures/order_confirmWithUser.sql +++ b/db/routines/hedera/procedures/order_confirmWithUser.sql @@ -107,7 +107,7 @@ BEGIN ) INTO vHas0Amount; IF vHas0Amount THEN - CALL util.throw('Hay líneas vacías. Por favor, elimínelas'); + CALL util.throw('orderLinesWithZero'); END IF; START TRANSACTION; diff --git a/db/routines/sage/procedures/invoiceIn_add.sql b/db/routines/sage/procedures/invoiceIn_add.sql index 76618ce50..8fdbb9ce3 100644 --- a/db/routines/sage/procedures/invoiceIn_add.sql +++ b/db/routines/sage/procedures/invoiceIn_add.sql @@ -4,10 +4,10 @@ BEGIN /** * Traslada la info de contabilidad relacionada con las facturas recibidas * - * @vInvoiceInFk Factura recibida - * @vXDiarioFk Id tabla XDiario + * @param vInvoiceInFk Factura recibida + * @param vXDiarioFk Id tabla XDiario */ - DECLARE vInvoiceInOriginalFk INT; + DECLARE vInvoiceInOriginalFk INT; DECLARE vDone BOOL DEFAULT FALSE; DECLARE vBase DOUBLE; DECLARE vVat DOUBLE; @@ -205,9 +205,9 @@ BEGIN WHERE correctingFk = vInvoiceInFk; IF vInvoiceInOriginalFk THEN - UPDATE movContaIVA mci - JOIN vn.invoiceInRefund iir ON iir.invoiceInRefundFk = vInvoiceInFk + JOIN vn.invoiceInCorrection iic ON iic.correctingFk = vInvoiceInFk + JOIN vn.siiTypeInvoiceIn st ON st.id = iic.siiTypeInvoiceInFk JOIN (SELECT issued, SUM(sub.taxableBase) taxableBase, SUM(ROUND((sub.taxableBase * sub.PorcentajeIva) / 100 , 2)) vat @@ -216,7 +216,7 @@ BEGIN ti.PorcentajeIva FROM vn.invoiceIn i JOIN vn.invoiceInTax iit ON iit.invoiceInFk = i.id - JOIN sage.TiposIva ti ON ti.CodigoIva = iit.taxTypeSageFk + JOIN TiposIva ti ON ti.CodigoIva = iit.taxTypeSageFk WHERE i.id = vInvoiceInOriginalFk GROUP BY ti.CodigoIva)sub )invoiceInOriginal @@ -229,7 +229,6 @@ BEGIN mci.CuotaIvaOriginal = invoiceInOriginal.vat, mci.ClaveOperacionFactura = co.ClaveOperacionFactura_ WHERE mci.id = vXDiarioFk; - END IF; END$$ DELIMITER ; diff --git a/db/routines/sage/procedures/invoiceOut_add.sql b/db/routines/sage/procedures/invoiceOut_add.sql index 95d6a56dd..f9c6f6b87 100644 --- a/db/routines/sage/procedures/invoiceOut_add.sql +++ b/db/routines/sage/procedures/invoiceOut_add.sql @@ -169,6 +169,7 @@ BEGIN UPDATE movContaIVA mci JOIN vn.invoiceOut i ON i.id = vInvoiceOutCorrectedFk JOIN vn.invoiceCorrection ic ON ic.correctedFk = vInvoiceOutCorrectedFk + JOIN vn.siiTypeInvoiceOut st ON st.id = ic.siiTypeInvoiceOutFk JOIN (SELECT SUM(IF(IFNULL(e.vatFk, TRUE), iot.taxableBase, 0)) taxableBase, SUM(IF(IFNULL(e.vatFk, TRUE), iot.vat, 0)) vat, SUM(IF(IFNULL(e.vatFk, TRUE), 0, iot.vat)) equ @@ -177,8 +178,8 @@ BEGIN WHERE iot.invoiceOutFk = vInvoiceOutCorrectedFk ) tax JOIN ClavesOperacion co ON co.Descripcion = 'Factura rectificativa' - SET mci.TipoRectificativa = 2, - mci.ClaseAbonoRectificativas = 1, + SET mci.TipoRectificativa = ic.cplusRectificationTypeFk, + mci.ClaseAbonoRectificativas = REGEXP_REPLACE(st.`code`, '[^0-9]', ''), mci.FechaFacturaOriginal = i.issued, mci.FechaOperacion = i.issued, mci.BaseImponibleOriginal = tax.taxableBase, diff --git a/db/routines/vn/events/client_setPackagesDiscountFactor.sql b/db/routines/vn/events/client_setPackagesDiscountFactor.sql new file mode 100644 index 000000000..a0dc33cac --- /dev/null +++ b/db/routines/vn/events/client_setPackagesDiscountFactor.sql @@ -0,0 +1,8 @@ +DELIMITER $$ +CREATE OR REPLACE DEFINER=`vn`@`localhost` EVENT `vn`.`client_setPackagesDiscountFactor` + ON SCHEDULE EVERY 1 DAY + STARTS '2024-10-18 03:00:00.000' + ON COMPLETION PRESERVE + ENABLE +DO CALL client_setPackagesDiscountFactor()$$ +DELIMITER ; diff --git a/db/routines/vn/functions/entry_getCommission.sql b/db/routines/vn/functions/entry_getCommission.sql index a4afdabd4..f8c1ce3b4 100644 --- a/db/routines/vn/functions/entry_getCommission.sql +++ b/db/routines/vn/functions/entry_getCommission.sql @@ -11,6 +11,7 @@ BEGIN DECLARE vCurrentCommission INT; DECLARE vIsNotEUR INT; DECLARE vLastEntryFk INT; + DECLARE vLanded INT; SELECT count(*) INTO vIsNotEUR FROM currency c @@ -26,23 +27,25 @@ BEGIN RETURN IFNULL(vCommission, 0); ELSE + SELECT landed INTO vLanded + FROM travel + WHERE id = vTravelFk; + 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; + WHERE e.supplierFk = vSupplierFk + ORDER BY (vLanded <= tr.landed), 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; diff --git a/db/routines/vn/procedures/catalog_componentCalculate.sql b/db/routines/vn/procedures/catalog_componentCalculate.sql index e29e13a8c..aaf2db408 100644 --- a/db/routines/vn/procedures/catalog_componentCalculate.sql +++ b/db/routines/vn/procedures/catalog_componentCalculate.sql @@ -231,7 +231,19 @@ BEGIN SELECT tcc.warehouseFK, tcc.itemFk, c2.id, - z.inflation * ROUND(ic.cm3delivery * (IFNULL(zo.price,5000) - IFNULL(zo.bonus,0)) / (1000 * vc.standardFlowerBox) , 4) cost + z.inflation + * ROUND( + ic.cm3delivery + * ( + ( + zo.priceOptimum + (( zo.price - zo.priceOptimum) * 2 * ( 1 - c.packagesDiscountFactor)) + ) + - IFNULL(zo.bonus, 0) + ) + / (1000 * vc.standardFlowerBox), + 4 + ) cost + FROM tmp.ticketComponentCalculate tcc JOIN item i ON i.id = tcc.itemFk JOIN tmp.zoneOption zo ON zo.zoneFk = vZoneFk @@ -239,6 +251,7 @@ BEGIN JOIN agencyMode am ON am.id = z.agencyModeFk JOIN vn.volumeConfig vc JOIN vn.component c2 ON c2.code = 'delivery' + JOIN `client` c on c.id = vClientFk LEFT JOIN itemCost ic ON ic.warehouseFk = tcc.warehouseFk AND ic.itemFk = tcc.itemFk HAVING cost <> 0; diff --git a/db/routines/vn/procedures/client_setPackagesDiscountFactor.sql b/db/routines/vn/procedures/client_setPackagesDiscountFactor.sql new file mode 100644 index 000000000..f6068ca37 --- /dev/null +++ b/db/routines/vn/procedures/client_setPackagesDiscountFactor.sql @@ -0,0 +1,25 @@ +DELIMITER $$ + +CREATE OR REPLACE DEFINER=`vn`@`localhost` +PROCEDURE `vn`.`client_setPackagesDiscountFactor`() +BEGIN + /** + * Set the discount factor for the packages of the clients. + */ + UPDATE client c + JOIN ( + SELECT t.clientFk, + LEAST(( + SUM(t.packages) / COUNT(DISTINCT DATE(t.shipped)) + ) / cc.packagesOptimum, 1) discountFactor + FROM ticket t + JOIN clientConfig cc ON TRUE + WHERE t.shipped > util.VN_CURDATE() - INTERVAL cc.monthsToCalcOptimumPrice MONTH + AND t.packages + GROUP BY t.clientFk + ) ca ON c.id = ca.clientFk + SET c.packagesDiscountFactor = ca.discountFactor; + +END$$ + +DELIMITER ; diff --git a/db/routines/vn/procedures/inventoryFailureAdd.sql b/db/routines/vn/procedures/inventoryFailureAdd.sql deleted file mode 100644 index e2b5fa4a0..000000000 --- a/db/routines/vn/procedures/inventoryFailureAdd.sql +++ /dev/null @@ -1,48 +0,0 @@ -DELIMITER $$ -CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`inventoryFailureAdd`() -BEGIN - -DECLARE done BOOL DEFAULT FALSE; -DECLARE vTicketFk INT; - -DECLARE rs CURSOR FOR - SELECT id FROM vn.ticket - WHERE shipped = util.yesterday() - AND clientFk = 400 - AND warehouseFk IN (1,44); - -DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; - -OPEN rs; - -FETCH rs INTO vTicketFk; - -WHILE NOT done DO - - INSERT INTO vn.inventoryFailure(dated, itemFk, quantity, value, warehouseFk, throwerFk) - SELECT t.shipped, - s.itemFk, - s.quantity, - b.buyingValue + b.freightValue + b.packageValue + b.comissionValue, - t.warehouseFk, - w.id - FROM vn.ticket t - JOIN vn.sale s ON s.ticketFk = t.id - LEFT JOIN cache.last_buy lb ON lb.warehouse_id = t.warehouseFk AND item_id = s.itemFk - LEFT JOIN vn.buy b ON b.id = lb.buy_id - LEFT JOIN vn.worker w ON w.code = LEFT(s.concept, 3) - WHERE t.id = vTicketFk - AND s.quantity > 0; - - FETCH rs INTO vTicketFk; - -END WHILE; - - -CLOSE rs; - - - - -END$$ -DELIMITER ; diff --git a/db/routines/vn/procedures/invoiceIn_booking.sql b/db/routines/vn/procedures/invoiceIn_booking.sql index cfe3adb0b..ef68e4804 100644 --- a/db/routines/vn/procedures/invoiceIn_booking.sql +++ b/db/routines/vn/procedures/invoiceIn_booking.sql @@ -43,7 +43,7 @@ BEGIN ii.cplusTaxBreakFk, ii.cplusSubjectOpFk, ii.siiTypeInvoiceInFk, - ii.cplusRectificationTypeFk, + ic.cplusRectificationTypeFk, ii.booked, IFNULL(a.isUeeMember, c.isUeeMember) isUeeMember, (c.id = cc.id) isSameCountry, @@ -66,6 +66,7 @@ BEGIN e.name expenseName FROM invoiceIn ii JOIN supplier s ON s.id = ii.supplierFk + LEFT JOIN invoiceInCorrection ic ON ic.correctingFk = ii.id LEFT JOIN province p ON p.id = s.provinceFk LEFT JOIN autonomy a ON a.id = p.autonomyFk JOIN country c ON c.id = s.countryFk diff --git a/db/routines/vn/procedures/invoiceOut_new.sql b/db/routines/vn/procedures/invoiceOut_new.sql index 723f33df5..1f20fb5fc 100644 --- a/db/routines/vn/procedures/invoiceOut_new.sql +++ b/db/routines/vn/procedures/invoiceOut_new.sql @@ -34,6 +34,7 @@ BEGIN DECLARE vMaxShipped DATE; DECLARE vDone BOOL; DECLARE vTicketFk INT; + DECLARE vAddressFk INT; DECLARE vCursor CURSOR FOR SELECT id FROM tmp.ticketToInvoice; @@ -48,11 +49,13 @@ BEGIN DATE(vInvoiceDate) >= invoiceOut_getMaxIssued( vSerial, t.companyFk, - YEAR(vInvoiceDate)) + YEAR(vInvoiceDate)), + t.addressFk INTO vClientFk, vCompanyFk, vMaxShipped, - vIsCorrectInvoiceDate + vIsCorrectInvoiceDate, + vAddressFk FROM tmp.ticketToInvoice tt JOIN ticket t ON t.id = tt.id; @@ -105,7 +108,9 @@ BEGIN clientFk, dued, companyFk, - siiTypeInvoiceOutFk + siiTypeInvoiceOutFk, + customsAgentFk, + incotermsFk ) SELECT 1, @@ -118,9 +123,12 @@ BEGIN vCplusCorrectingInvoiceTypeFk, IF(vSerial = vSimplifiedSerial, vCplusSimplifiedInvoiceTypeFk, - vCplusStandardInvoiceTypeFk)) - FROM client - WHERE id = vClientFk; + vCplusStandardInvoiceTypeFk)), + a.customsAgentFk, + a.incotermsFk + FROM client c + JOIN address a ON a.id = vAddressFk + WHERE c.id = vClientFk; SET vNewInvoiceId = LAST_INSERT_ID(); diff --git a/db/routines/vn/procedures/item_cleanFloramondo.sql b/db/routines/vn/procedures/item_cleanFloramondo.sql index 849cfe93d..21d8ebe3c 100644 --- a/db/routines/vn/procedures/item_cleanFloramondo.sql +++ b/db/routines/vn/procedures/item_cleanFloramondo.sql @@ -164,10 +164,6 @@ BEGIN SET itemFk = vItemNew WHERE itemFk = vItemOld; - UPDATE inventoryFailure - SET itemFk = vItemNew - WHERE itemFk = vItemOld; - UPDATE genericAllocation SET itemFk = vItemNew WHERE itemFk = vItemOld; diff --git a/db/routines/vn/procedures/saleTracking_addPrevOK.sql b/db/routines/vn/procedures/saleTracking_addPrevOK.sql index 34d1cfac8..9f823e9a0 100644 --- a/db/routines/vn/procedures/saleTracking_addPrevOK.sql +++ b/db/routines/vn/procedures/saleTracking_addPrevOK.sql @@ -16,10 +16,11 @@ BEGIN TRUE, sc.userFk, s.id - FROM vn.sectorCollection sc - JOIN vn.sectorCollectionSaleGroup scsg ON scsg.sectorCollectionFk = sc.id - JOIN vn.saleGroupDetail sgd ON sgd.saleGroupFk = scsg.saleGroupFk - JOIN vn.state s ON s.code = 'OK PREVIOUS' + FROM sectorCollection sc + JOIN sectorCollectionSaleGroup scsg ON scsg.sectorCollectionFk = sc.id + JOIN saleGroupDetail sgd ON sgd.saleGroupFk = scsg.saleGroupFk + JOIN state s ON s.code = 'OK PREVIOUS' + JOIN itemShelvingSale iss ON iss.saleFk = sgd.saleFk WHERE sc.id = vSectorCollectionFk; END$$ DELIMITER ; diff --git a/db/routines/vn/procedures/ticket_canAdvance.sql b/db/routines/vn/procedures/ticket_canAdvance.sql index e8fc70bba..cee706e08 100644 --- a/db/routines/vn/procedures/ticket_canAdvance.sql +++ b/db/routines/vn/procedures/ticket_canAdvance.sql @@ -52,7 +52,8 @@ BEGIN IFNULL(dest.nickname, origin.nickname) nickname, dest.landed, dest.preparation, - origin.departmentFk + origin.departmentFk, + origin.saleClonedFk FROM ( SELECT s.ticketFk, c.salesPersonFk workerFk, @@ -73,11 +74,13 @@ BEGIN t.warehouseFk, t.companyFk, t.agencyModeFk, - wd.departmentFk + wd.departmentFk, + sc.saleClonedFk FROM ticket t JOIN client c ON c.id = t.clientFk JOIN workerDepartment wd ON wd.workerFk = c.salesPersonFk JOIN sale s ON s.ticketFk = t.id + LEFT JOIN saleCloned sc ON sc.saleClonedFk = s.id JOIN saleVolume sv ON sv.saleFk = s.id JOIN item i ON i.id = s.itemFk JOIN ticketState ts ON ts.ticketFk = t.id diff --git a/db/routines/vn/procedures/ticket_canbePostponed.sql b/db/routines/vn/procedures/ticket_canbePostponed.sql index 1f3c43057..a21e171cf 100644 --- a/db/routines/vn/procedures/ticket_canbePostponed.sql +++ b/db/routines/vn/procedures/ticket_canbePostponed.sql @@ -19,6 +19,7 @@ BEGIN sub2.iptd futureIpt, sub2.state futureState, t.clientFk, + cl.salespersonFk, t.warehouseFk, ts.alertLevel, sub2.alertLevel futureAlertLevel, @@ -38,6 +39,7 @@ BEGIN JOIN vn.province p ON p.id = a.provinceFk JOIN vn.country c ON c.id = p.countryFk JOIN vn.ticketState ts ON ts.ticketFk = t.id + JOIN vn.client cl ON cl.id = t.clientFk JOIN vn.state st ON st.id = ts.stateFk JOIN vn.alertLevel al ON al.id = ts.alertLevel LEFT JOIN vn.ticketParking tp ON tp.ticketFk = t.id diff --git a/db/routines/vn/procedures/zone_getAddresses.sql b/db/routines/vn/procedures/zone_getAddresses.sql index 2e5982c82..9946b0b73 100644 --- a/db/routines/vn/procedures/zone_getAddresses.sql +++ b/db/routines/vn/procedures/zone_getAddresses.sql @@ -1,26 +1,27 @@ DELIMITER $$ CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`zone_getAddresses`( vSelf INT, - vShipped DATE, + vLanded DATE, vDepartmentFk INT ) BEGIN /** * Devuelve un listado de todos los clientes activos * con consignatarios a los que se les puede - * vender producto para esa zona. + * entregar producto para esa zona. * * @param vSelf Id de zona - * @param vShipped Fecha de envio - * @param vDepartmentFk Id de departamento + * @param vLanded Fecha de entrega + * @param vDepartmentFk Id de departamento | NULL para mostrar todos * @return Un select */ CALL zone_getPostalCode(vSelf); WITH clientWithTicket AS ( - SELECT clientFk + SELECT DISTINCT clientFk FROM vn.ticket - WHERE shipped BETWEEN vShipped AND util.dayEnd(vShipped) + WHERE landed BETWEEN vLanded AND util.dayEnd(vLanded) + AND NOT isDeleted ) SELECT c.id, c.name, @@ -30,7 +31,7 @@ BEGIN u.name username, aai.invoiced, cnb.lastShipped, - cwt.clientFk + IF(cwt.clientFk, TRUE, FALSE) hasTicket FROM vn.client c JOIN vn.worker w ON w.id = c.salesPersonFk JOIN vn.workerDepartment wd ON wd.workerFk = w.id @@ -50,7 +51,7 @@ BEGIN AND c.isActive AND ct.code = 'normal' AND bt.code <> 'worker' - AND (d.id = vDepartmentFk OR NOT vDepartmentFk) + AND (d.id = vDepartmentFk OR vDepartmentFk IS NULL) GROUP BY c.id; DROP TEMPORARY TABLE tmp.zoneNodes; diff --git a/db/routines/vn/procedures/zone_getOptionsForShipment.sql b/db/routines/vn/procedures/zone_getOptionsForShipment.sql index fa48b0b0f..17d1b3d11 100644 --- a/db/routines/vn/procedures/zone_getOptionsForShipment.sql +++ b/db/routines/vn/procedures/zone_getOptionsForShipment.sql @@ -9,7 +9,7 @@ BEGIN * @return tmp.zoneOption(zoneFk, hour, travelingDays, price, bonus, specificity) The computed options */ DECLARE vHour TIME DEFAULT TIME(util.VN_NOW()); - + DROP TEMPORARY TABLE IF EXISTS tLandings; CREATE TEMPORARY TABLE tLandings (INDEX (eventFk)) @@ -30,6 +30,7 @@ BEGIN TIME(IFNULL(e.`hour`, z.`hour`)) `hour`, l.travelingDays, IFNULL(e.price, z.price) price, + IFNULL(e.priceOptimum, z.priceOptimum) priceOptimum, IFNULL(e.bonus, z.bonus) bonus, l.landed, vShipped shipped diff --git a/db/routines/vn/triggers/invoiceIn_afterUpdate.sql b/db/routines/vn/triggers/invoiceIn_afterUpdate.sql index 95b1d98a9..8c2785e38 100644 --- a/db/routines/vn/triggers/invoiceIn_afterUpdate.sql +++ b/db/routines/vn/triggers/invoiceIn_afterUpdate.sql @@ -3,24 +3,30 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`invoiceIn_afterUpdate` AFTER UPDATE ON `invoiceIn` FOR EACH ROW BEGIN - IF NEW.issued != OLD.issued - OR NEW.currencyFk != OLD.currencyFk THEN + DECLARE vIsEuro BOOL; + + SELECT `code` = 'EUR' INTO vIsEuro + FROM currency + WHERE id = NEW.currencyFk; + + IF (NOT NEW.issued <=> OLD.issued + OR NEW.currencyFk <> OLD.currencyFk) THEN UPDATE invoiceInTax iit JOIN invoiceIn ii ON ii.id = iit.invoiceInFk LEFT JOIN referenceRate rr ON rr.dated = ii.issued AND rr.currencyFk = ii.currencyFk - SET iit.taxableBase = IF(iit.foreignValue IS NULL, iit.taxableBase, iit.foreignValue / rr.value) + SET iit.taxableBase = IF(vIsEuro, iit.taxableBase, iit.foreignValue / rr.value), + iit.foreignValue = IF(vIsEuro, NULL, iit.foreignValue) WHERE ii.id = NEW.id; UPDATE invoiceInDueDay iidd JOIN invoiceIn ii ON ii.id = iidd.invoiceInFk LEFT JOIN referenceRate rr ON rr.dated = ii.issued AND rr.currencyFk = ii.currencyFk - SET iidd.amount = IF(iidd.foreignValue IS NULL, iidd.amount, iidd.foreignValue / rr.value) + SET iidd.amount = IF(vIsEuro, iidd.amount, iidd.foreignValue / rr.value), + iidd.foreignValue = IF(vIsEuro, NULL, iidd.foreignValue) WHERE ii.id = NEW.id; - END IF; - END$$ DELIMITER ; diff --git a/db/routines/vn/triggers/itemTaxCountry_beforeDelete.sql b/db/routines/vn/triggers/itemTaxCountry_beforeDelete.sql new file mode 100644 index 000000000..461b861f2 --- /dev/null +++ b/db/routines/vn/triggers/itemTaxCountry_beforeDelete.sql @@ -0,0 +1,8 @@ +DELIMITER $$ +CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`itemTaxCountry_beforeDelete` + BEFORE DELETE ON `itemTaxCountry` + FOR EACH ROW +BEGIN + CALL util.throw('Records in this table cannot be deleted'); +END$$ +DELIMITER ; diff --git a/db/routines/vn/triggers/itemTaxCountry_beforeUpdate.sql b/db/routines/vn/triggers/itemTaxCountry_beforeUpdate.sql index ad7d6327b..5220028e8 100644 --- a/db/routines/vn/triggers/itemTaxCountry_beforeUpdate.sql +++ b/db/routines/vn/triggers/itemTaxCountry_beforeUpdate.sql @@ -4,5 +4,9 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`itemTaxCountry_beforeUp FOR EACH ROW BEGIN SET NEW.editorFk = account.myUser_getId(); + + IF NOT(NEW.`countryFk` <=> OLD.`countryFk`) OR NOT(NEW.`itemFk` <=> OLD.`itemFk`) THEN + CALL util.throw('Only the VAT can be modified'); + END IF; END$$ DELIMITER ; diff --git a/db/routines/vn/triggers/route_afterUpdate.sql b/db/routines/vn/triggers/route_afterUpdate.sql index 447608acc..a15c1a4b7 100644 --- a/db/routines/vn/triggers/route_afterUpdate.sql +++ b/db/routines/vn/triggers/route_afterUpdate.sql @@ -22,6 +22,7 @@ BEGIN OR !(NEW.workerFk <=> OLD.workerFk) OR !(NEW.m3 <=> OLD.m3) OR !(NEW.agencyModeFk <=> OLD.agencyModeFk) + OR !(NEW.dated <=> OLD.dated) OR !(NEW.vehicleFk <=> OLD.vehicleFk)THEN CALL route_calcCommission(NEW.id); END IF; diff --git a/db/routines/vn/triggers/workerManaExcluded_beforeInsert.sql b/db/routines/vn/triggers/workerManaExcluded_beforeInsert.sql new file mode 100644 index 000000000..824f0982b --- /dev/null +++ b/db/routines/vn/triggers/workerManaExcluded_beforeInsert.sql @@ -0,0 +1,9 @@ +DELIMITER $$ +CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`workerManaExcluded_beforeInsert` + BEFORE INSERT ON `workerManaExcluded` + FOR EACH ROW +BEGIN + DELETE FROM workerMana + WHERE workerFk = NEW.workerFk; +END$$ +DELIMITER ; diff --git a/db/routines/vn/triggers/workerManaExcluded_beforeUpdate.sql b/db/routines/vn/triggers/workerManaExcluded_beforeUpdate.sql new file mode 100644 index 000000000..83d73e131 --- /dev/null +++ b/db/routines/vn/triggers/workerManaExcluded_beforeUpdate.sql @@ -0,0 +1,9 @@ +DELIMITER $$ +CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`workerManaExcluded_beforeUpdate` + BEFORE UPDATE ON `workerManaExcluded` + FOR EACH ROW +BEGIN + DELETE FROM workerMana + WHERE workerFk = NEW.workerFk; +END$$ +DELIMITER ; diff --git a/db/routines/vn/triggers/workerMana_beforeInsert.sql b/db/routines/vn/triggers/workerMana_beforeInsert.sql new file mode 100644 index 000000000..2d27004e3 --- /dev/null +++ b/db/routines/vn/triggers/workerMana_beforeInsert.sql @@ -0,0 +1,10 @@ +DELIMITER $$ +CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`workerMana_beforeInsert` + BEFORE INSERT ON `workerMana` + FOR EACH ROW +BEGIN + IF (SELECT EXISTS(SELECT TRUE FROM workerManaExcluded WHERE workerFk = NEW.workerFk)) THEN + CALL util.throw('Worker is excluded from mana'); + END IF; +END$$ +DELIMITER ; diff --git a/db/routines/vn/triggers/workerMana_beforeUpdate.sql b/db/routines/vn/triggers/workerMana_beforeUpdate.sql new file mode 100644 index 000000000..6916733cb --- /dev/null +++ b/db/routines/vn/triggers/workerMana_beforeUpdate.sql @@ -0,0 +1,10 @@ +DELIMITER $$ +CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`workerMana_beforeUpdate` + BEFORE UPDATE ON `workerMana` + FOR EACH ROW +BEGIN + IF (SELECT EXISTS(SELECT TRUE FROM workerManaExcluded WHERE workerFk = NEW.workerFk)) THEN + CALL util.throw('Worker is excluded from mana'); + END IF; +END$$ +DELIMITER ; diff --git a/db/routines/vn/triggers/workerTimeControl_afterDelete.sql b/db/routines/vn/triggers/workerTimeControl_afterDelete.sql index 27432fccb..96db381b5 100644 --- a/db/routines/vn/triggers/workerTimeControl_afterDelete.sql +++ b/db/routines/vn/triggers/workerTimeControl_afterDelete.sql @@ -3,10 +3,12 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`workerTimeControl_after AFTER DELETE ON `workerTimeControl` FOR EACH ROW BEGIN - INSERT INTO workerLog - SET `action` = 'delete', - `changedModel` = 'WorkerTimeControl', - `changedModelId` = OLD.id, - `userFk` = account.myUser_getId(); + IF account.myUser_getId() IS NOT NULL THEN + INSERT INTO workerLog + SET `action` = 'delete', + `changedModel` = 'WorkerTimeControl', + `changedModelId` = OLD.id, + `userFk` = account.myUser_getId(); + END IF; END$$ DELIMITER ; diff --git a/db/routines/vn2008/views/Split_lines.sql b/db/routines/vn2008/views/Split_lines.sql deleted file mode 100644 index 0b7897be7..000000000 --- a/db/routines/vn2008/views/Split_lines.sql +++ /dev/null @@ -1,8 +0,0 @@ -CREATE OR REPLACE DEFINER=`root`@`localhost` - SQL SECURITY DEFINER - VIEW `vn2008`.`Split_lines` -AS SELECT `sl`.`id` AS `Id_Split_lines`, - `sl`.`splitFk` AS `Id_Split`, - `sl`.`itemFk` AS `Id_Article`, - `sl`.`buyFk` AS `Id_Compra` -FROM `vn`.`splitLine` `sl` \ No newline at end of file diff --git a/db/versions/11269-wheatBirch/00-firstScript.sql b/db/versions/11269-wheatBirch/00-firstScript.sql new file mode 100644 index 000000000..9432d131b --- /dev/null +++ b/db/versions/11269-wheatBirch/00-firstScript.sql @@ -0,0 +1,15 @@ +ALTER TABLE vn.invoiceOut ADD COLUMN IF NOT EXISTS customsAgentFk INT(11) DEFAULT NULL AFTER siiTrascendencyInvoiceOutFk; +ALTER TABLE vn.invoiceOut ADD COLUMN IF NOT EXISTS incotermsFk varchar(3) DEFAULT NULL AFTER customsAgentFk; + +ALTER TABLE vn.invoiceOut ADD CONSTRAINT invoiceOut_customsAgentFk FOREIGN KEY (customsAgentFk) + REFERENCES vn.customsAgent (id) ON DELETE RESTRICT ON UPDATE CASCADE; + +ALTER TABLE vn.invoiceOut ADD CONSTRAINT invoiceOut_incotermsFk FOREIGN KEY (incotermsFk) + REFERENCES vn.incoterms (`code`) ON DELETE RESTRICT ON UPDATE CASCADE; + +UPDATE vn.invoiceOut io + JOIN vn.client c ON c.id = io.clientFk + JOIN vn.ticket t ON t.clientFk = c.id + JOIN vn.address a ON a.id = t.addressFk + SET io.customsAgentFk = a.customsAgentFk, + io.incotermsFk = a.incotermsFk; \ No newline at end of file diff --git a/db/versions/11320-salmonRose/00-firstScript.sql b/db/versions/11320-salmonRose/00-firstScript.sql new file mode 100644 index 000000000..cd3431fee --- /dev/null +++ b/db/versions/11320-salmonRose/00-firstScript.sql @@ -0,0 +1,11 @@ +INSERT INTO hedera.message (code, description) + VALUES ('orderLinesWithZero','There are empty lines. Please delete them'); + +INSERT INTO hedera.messageI18n (code, lang, description) + VALUES ('orderLinesWithZero','es','Hay líneas vacías. Por favor, elimínelas'); + +INSERT INTO hedera.messageI18n (code, lang, description) + VALUES ('orderLinesWithZero','fr','Il y a des lignes vides. Veuillez les supprimer'); + +INSERT INTO hedera.messageI18n (code, lang, description) + VALUES ('orderLinesWithZero','pt','Existem linhas vazias. Por favor, apague-os'); \ No newline at end of file diff --git a/db/versions/11327-maroonOak/00-firstScript.sql b/db/versions/11327-maroonOak/00-firstScript.sql new file mode 100644 index 000000000..a51ee3fff --- /dev/null +++ b/db/versions/11327-maroonOak/00-firstScript.sql @@ -0,0 +1,185 @@ +CREATE TABLE IF NOT EXISTS `vn`.`sim` ( + `code` VARCHAR(25) COMMENT 'No se ha puesto BIGINT por incompatibilidad con Access', + `line` VARCHAR(15) NOT NULL CHECK (`line` REGEXP '^[0-9]+$'), + `ext` INT(4) NOT NULL, + `pin` VARCHAR(4) NOT NULL CHECK (`pin` REGEXP '^[0-9]+$'), + `puk` VARCHAR(15) NOT NULL CHECK (`pin` REGEXP '^[0-9]+$'), + PRIMARY KEY (`code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; + +ALTER TABLE vn.deviceProductionUser CHANGE simSerialNumber simFk VARCHAR(25) DEFAULT NULL NULL; +ALTER TABLE vn.deviceProductionUser MODIFY COLUMN simFk VARCHAR(25) DEFAULT NULL NULL; + +INSERT IGNORE INTO `vn`.`sim` (`line`, `ext`, `pin`, `code`, `puk`) VALUES + ('621188151', 2209, '1486', '3456985220092508','14213470'), + ('621188152', 2210, '8765', '3456985220092509','99473093'), + ('621188153', 2211, '3064', '3456985220092510','52967210'), + ('621188759', 2081, '3700', '3456985220123637','56600999'), + ('621188760', 2082, '3259', '345698522023638','87492404'), + ('621188761', 2083, '2790', '3456985220123639','94009456'), + ('621188762', 2084, '2480', '3456985220123644','1484999'), + ('621188763', 2085, '6876', '3456985220123641','36577064'), + ('621188766', 2086, '7775', '3456985220123642','80761698'), + ('621188769', 2088, '4027', '3456985220123643','37921712'), + ('621188771', 2089, '8797', '3456985220123640','63092540'), + ('621188772', 2090, '8404', '3456985220123645','21014997'), + ('621188773', 2091, '5481', '3456985220123646','16317277'), + ('621188774', 2092, '9632', '3456985220123647','22235994'), + ('621188775', 2093, '4654', '3456985220123648','28506486'), + ('621188838', 2094, '1392', '3456985220123649','29498627'), + ('621188839', 2095, '7774', '3456985220123650','46263490'), + ('621188840', 2096, '7304', '3456985220123658','8212044'), + ('621188841', 2097, '5569', '3456985220123652','81597658'), + ('621188842', 2098, '4944', '3456985220123653','24961501'), + ('621188843', 2099, '5142', '3456985220123654','17035634'), + ('621188844', 2111, '7245', '3456985220123655','90231951'), + ('621188846', 2110, '6590', '3456985220123656','72201537'), + ('667680207', 2564, '4042', '34569832200759166','48401979'), + ('667680315', 2565, '7143', '34569832200759372','32143252'), + ('667680318', 2566, '6342', '34569832200759364','39597112'), + ('667680413', 2567, '5580', '34569832200759356','32786992'), + ('667680463', 2568, '0171', '34569832200759349','34240853'), + ('667688217', 2569, '2500', '34569832200759331','5687589'), + ('633603945', 2212, '7129', '34569832200759323','51554019'), + ('622130186', 2213, '4826', '34569832200759307','19623551'), + ('633973424', 2214, '8535', '34569832200759299','94619307'), + ('633703828', 2215, '8628', '34569832200759281','22468012'), + ('622025110', 2216, '2399', '34569832200759273','34602918'), + ('622924867', 2217, '5665', '34569832200759265','26920216'), + ('722409630', 2218, '5211', '34569832200759240','93750137'), + ('623590529', 2219, '0493', '34569832200759208','47077088'), + ('633243462', 2220, '6902', '34569832200759174','6421962'), + ('633047286', 2221, '5592', '34569832200759182','32069439'), + ('744716801', 2112, '9184', '34569832200759190','57049814'), + ('655995021', 2131, '8896', '34569852202049093','19497356'), + ('685522718', 2132, '1955', '34569852202049101','28519879'), + ('674587213', 2994, '2006', '34569332200223743','62360135'), + ('674587227', 2993, '9271', '34569332200223750','81628192'), + ('674587229', 2993, '0900', '34569332200223768','91119071'), + ('674587231', 2992, '5007', '34569332200223776','45826232'), + ('674587234', 2991, '1378', '34569332200223784','91245744'), + ('674587240', 2990, '0905', '34569332200223792','13083224'), + ('674587245', 2989, '9059', '34569332200223800','15291807'), + ('674587250', 2988, '8188', '34569332200223818','83017918'), + ('674587254', 2987, '2962', '34569332200223826','92809271'), + ('674587256', 2986, '0358', '34569332200223834','81067040'), + ('674592713', 2570, '2537', '34569332200230672','82325850'), + ('697832478', 2579, '0936', '34568732200494825','49658372'), + ('697832176', 2571, '5944', '34568732200494742','19039461'), + ('697832477', 2572, '5138', '34568732200494759','25712504'), + ('697832178', 2573, '4597', '34568732200494767','66241760'), + ('697832182', 2574, '9241', '34568732200494775','07342562'), + ('697832196', 2575, '2995', '34568732200494783','53929026'), + ('697832214', 2576, '7434', '34568732200494791','49698432'), + ('697832230', 2577, '7004', '34568732200494809','21578612'), + ('697832235', 2578, '9674', '34568732200494817','93090700'), + ('673420375', 2599, '5430', '34562052300117259','35911412'), + ('673420367', 2598, '8402', '34562052300117242','924654'), + ('673420361', 2597, '5125', '34562052300117234','12027970'), + ('673420355', 2596, '5069', '34562052300117226','34978149'), + ('673420348', 2595, '8911', '34562052300117218','4228121'), + ('673420346', 2594, '2461', '34562052300117200','67670772'), + ('673420345', 2593, '2226', '34562052300117192','90586404'), + ('673420306', 2592, '3355', '34562052300117184','97850017'), + ('673420257', 2591, '9395', '34562052300117176','50713786'), + ('673420231', 2590, '1378', '34562052300117168','50151763'), + ('673420223', 2589, '9580', '34562052300117150','99534550'), + ('673420216', 2588, '4955', '34562052300117143','317554'), + ('673420203', 2587, '6742', '34562052300117135','69321531'), + ('673420201', 2586, '1659', '34562052300117127','54720480'), + ('673420199', 2585, '7823', '34562052300117119','22923796'), + ('673420198', 2584, '1787', '34562052300117101','54414630'), + ('673420168', 2583, '6334', '34562052300117093','50694894'), + ('673420147', 2582, '8951', '34562052300117085','1402535'), + ('673420125', 2581, '3068', '34562052300117077','86216200'), + ('673420124', 2580, '9517', '34562052300117069','42504099'), + ('600294609', 2715, '7474', '34569832304894588','55923317'), + ('600084713', 2703, '8342', '34569832304894570','8392636'), + ('600084732', 2704, '1625', '34569832304894513','75477452'), + ('600084850', 2705, '9896', '34569832304894653','28589813'), + ('600084951', 2706, '5520', '34569832304894661','75353012'), + ('600084978', 2707, '2698', '34569832304894679','9005523'), + ('600085403', 2708, '0837', '34569832304894646','77051152'), + ('600085513', 2709, '3106', '34569832304894687','41571002'), + ('600293916', 2712, '8990', '34569832304894620','95188676'), + ('600294160', 2714, '6376', '34569832304894703','79879896'), + ('671919529', 2975, '9184', '34569832304806236','7535392'), + ('671919942', 2981, '0328', '34569832304806269','31052894'), + ('671919530', 2976, '0344', '34569832304806251','89860304'), + ('671919533', 2977, '0668', '34569832304806244','42921771'), + ('671919535', 2978, '0105', '34569832304806277','31009417'), + ('671919537', 2979, '0881', '34569832304806285','33479769'), + ('671919540', 2980, '9874', '34569832304806293','14103929'), + ('671919525', 2972, '2089', '34569832304806301','45903729'), + ('671919527', 2973, '8206', '34569832304806368','1586035'), + ('671919528', 2974, '2532', '34569832304806327','62310124'), + ('673668717', 2836, '7973', '34562032301044223','15635496'), + ('673668734', 2837, '4457', '34562032301044231','18313118'), + ('673668738', 2824, '2911', '34562032301044249','30875583'), + ('673668745', 2838, '7253', '34562032301044256','62754222'), + ('673668796', 2839, '0068', '34562032301044264','15556829'), + ('673668803', 2840, '2386', '34562032301044272','17572287'), + ('673669591', 2850, '3833', '34562032301044280','34828896'), + ('673668808', 2841, '3584', '34562032301044298','16234497'), + ('673670102', 2851, '3554', '34562032301044306','23652625'), + ('673670131', 2852, '4412', '34562032301044314','88611709'), + ('673670135', 2827, '6058', '34562032301044322','53918579'), + ('673670201', 2828, '8066', '34562032301044330','92369343'), + ('673670225', 2829, '4592', '34562032301044348','24126635'), + ('673670236', 2830, '2974', '34562032301044355','88608465'), + ('673671485', 2849, '0349', '34562032301044363','44944874'), + ('673461977', 2871, '1728', '34562032400157090','46975780'), + ('673461975', 2870, '4734', '34562032400157082','69628432'), + ('673461972', 2867, '6276', '34562032400157058','53338365'), + ('673461979', 2872, '6043', '34562032400157108','36525197'), + ('673461958', 2859, '3164', '34562032400156977','58947831'), + ('673461957', 2857, '8685', '34562032400156969','15826386'), + ('673461944', 2853, '1073', '34562032400156910','20452195'), + ('673461974', 2869, '7121', '34562032400157074','32044645'), + ('673461973', 2868, '8022', '34562032400157066','29282044'), + ('673461971', 2866, '3089', '34562032400157041','66149978'), + ('673461969', 2865, '7555', '34562032400157033','78391293'), + ('673461960', 2860, '5203', '34562032400156985','37138232'), + ('673461952', 2855, '6915', '34562032400156936','62724661'), + ('673461949', 2854, '8706', '34562032400156928','5594345'), + ('673461966', 2863, '2496', '34562032400157017','93450666'), + ('673461968', 2864, '3703', '34562032400157025','23208841'), + ('673461963', 2862, '9364', '34562032400157009','29712130'), + ('673462719', 2873, '9387', '34562032400156951','50434348'), + ('673461962', 2861, '8441', '34562032400156993','39686909'), + ('673461956', 2826, '5392', '34562032400156944','5496107'), + ('673465284', 2694, '1523', '34562032400171349','14554994'), + ('673465282', 2692, '4645', '34562032400171323','24871187'), + ('673465283', 2693, '5253', '34562032400171331','28303238'), + ('673465841', 2696, '0849', '34562032400171257','21673222'), + ('673465258', 2679, '4140', '34562032400171174','39793881'), + ('673465263', 2680, '6922', '34562032400171182','12253261'), + ('673465265', 2681, '9112', '34562032400171190','93894366'), + ('673465267', 2682, '3259', '34562032400171208','2342189'), + ('673465268', 2683, '8540', '34562032400171216','63886925'), + ('673465285', 2695, '4167', '34562032400171356','79227618'), + ('673465270', 2684, '4292', '34562032400171224','19216349'), + ('673465272', 2685, '4007', '34562032400171232','14396903'), + ('673465273', 2686, '6894', '34562032400171240','13569394'), + ('673465274', 2687, '5268', '34562032400171265','59453667'), + ('673465275', 2688, '0232', '34562032400171273','62324713'), + ('673465276', 2689, '2720', '34562032400171281','65977200'), + ('673465843', 2698, '4773', '34562032400171364','78387158'), + ('673465842', 2697, '3729', '34562032400171315','94201789'), + ('673465280', 2691, '0503', '34562032400171307','12298533'), + ('673465279', 2690, '8239', '34562032400171299','76183877'); + +UPDATE vn.deviceProductionUser + SET simFk = NULL + WHERE id IN ( + SELECT dpu.id + FROM vn.deviceProductionUser dpu + LEFT JOIN vn.sim s ON s.code = dpu.simFk + WHERE s.code IS NULL + AND dpu.simFk IS NOT NULL + ); + +ALTER TABLE vn.deviceProductionUser ADD CONSTRAINT deviceProductionUser_sim_FK + FOREIGN KEY (simFk) REFERENCES vn.sim(code) ON DELETE RESTRICT ON UPDATE CASCADE; + +GRANT SELECT, INSERT, DELETE, UPDATE ON TABLE vn.sim TO hr; diff --git a/db/versions/11368-whiteAspidistra/00-firstScript.sql b/db/versions/11368-whiteAspidistra/00-firstScript.sql new file mode 100644 index 000000000..f36832805 --- /dev/null +++ b/db/versions/11368-whiteAspidistra/00-firstScript.sql @@ -0,0 +1,48 @@ + USE vn; + + DROP TRIGGER IF EXISTS invoiceIn_beforeUpdate; + + UPDATE invoiceIn + SET cplusRectificationTypeFk = NULL + WHERE cplusRectificationTypeFk = 1; + + DELETE IGNORE FROM cplusRectificationType WHERE id = 1; + + UPDATE cplusRectificationType + SET id = 1 + WHERE id = 3; + +DELIMITER $$ +CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`invoiceIn_beforeUpdate` + BEFORE UPDATE ON `invoiceIn` + FOR EACH ROW +BEGIN + DECLARE vWithholdingSageFk INT; + + IF NOT (NEW.supplierRef <=> OLD.supplierRef) AND NOT util.checkPrintableChars(NEW.supplierRef) THEN + CALL util.throw('The invoiceIn reference contains invalid characters'); + END IF; + + SET NEW.editorFk = account.myUser_getId(); + + IF (SELECT COUNT(*) FROM invoiceIn + WHERE supplierRef = NEW.supplierRef + AND supplierFk = NEW.supplierFk + AND YEAR(issued) = YEAR(NEW.issued) + AND id <> NEW.id + ) THEN + CALL util.throw('reference duplicated'); + END IF; + + IF NEW.supplierFk != OLD.supplierFk THEN + CALL supplier_checkIsActive(NEW.supplierFk); + SELECT withholdingSageFk INTO vWithholdingSageFk + FROM supplier + WHERE id = NEW.supplierFk; + SET NEW.withholdingSageFk = vWithholdingSageFk; + END IF; + +END$$ +DELIMITER ; + + diff --git a/db/versions/11368-whiteAspidistra/01-acls.sql b/db/versions/11368-whiteAspidistra/01-acls.sql new file mode 100644 index 000000000..6ac98db43 --- /dev/null +++ b/db/versions/11368-whiteAspidistra/01-acls.sql @@ -0,0 +1,23 @@ +INSERT INTO salix.ACL (model, property, accessType, permission, principalType, principalId) + VALUES('SiiTypeInvoiceIn', 'find', 'READ', 'ALLOW', 'ROLE', 'salesPerson'); + +DROP TABLE IF EXISTS vn.invoiceInCorrection; + +CREATE TABLE `invoiceInCorrection` ( + `correctingFk` mediumint(8) unsigned NOT NULL COMMENT 'Factura rectificativa', + `correctedFk` mediumint(8) unsigned NOT NULL COMMENT 'Factura rectificada', + `cplusRectificationTypeFk` int(10) unsigned NOT NULL, + `siiTypeInvoiceInFk` int(10) unsigned NOT NULL, + `invoiceCorrectionTypeFk` int(11) NOT NULL DEFAULT 3, + PRIMARY KEY (`correctingFk`), + KEY `invoiceInCorrection_correctedFk` (`correctedFk`), + KEY `invoiceInCorrection_cplusRectificationTypeFk` (`cplusRectificationTypeFk`), + KEY `invoiceInCorrection_siiTypeInvoiceIn` (`siiTypeInvoiceInFk`), + KEY `invoiceInCorrection_invoiceCorrectionTypeFk` (`invoiceCorrectionTypeFk`), + CONSTRAINT `invoiceInCorrection_correctedFk` FOREIGN KEY (`correctedFk`) REFERENCES `invoiceIn` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `invoiceInCorrection_correctingFk` FOREIGN KEY (`correctingFk`) REFERENCES `invoiceIn` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `invoiceInCorrection_cplusRectificationTypeFk` FOREIGN KEY (`cplusRectificationTypeFk`) REFERENCES `cplusRectificationType` (`id`) ON UPDATE CASCADE, + CONSTRAINT `invoiceInCorrection_invoiceCorrectionTypeFk` FOREIGN KEY (`invoiceCorrectionTypeFk`) REFERENCES `invoiceCorrectionType` (`id`) ON UPDATE CASCADE, + CONSTRAINT `invoiceInCorrection_siiTypeInvoiceIn` FOREIGN KEY (`siiTypeInvoiceInFk`) REFERENCES `siiTypeInvoiceIn` (`id`) ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; + diff --git a/db/versions/11379-yellowCordyline/00-firstScript.sql b/db/versions/11379-yellowCordyline/00-firstScript.sql new file mode 100644 index 000000000..8d90ee90c --- /dev/null +++ b/db/versions/11379-yellowCordyline/00-firstScript.sql @@ -0,0 +1,20 @@ +CREATE TABLE `vn`.`osrmConfig` ( + `id` int(10) unsigned NOT NULL, + `url` varchar(100) NOT NULL COMMENT 'Dirección base de la API', + `tolerance` decimal(6,6) NOT NULL DEFAULT 0 COMMENT 'Tolerancia entre las coordenadas enviadas y las retornadas', + PRIMARY KEY (`id`), + CONSTRAINT `osrmConfig_check` CHECK (`id` = 1) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; + +-- Para que no de error al añadir la FK de zone +UPDATE vn.zone + SET price = 0.1 + WHERE price = 0; + +ALTER TABLE vn.`zone` + ADD addressFk int(11) DEFAULT NULL COMMENT 'Punto de distribución de donde salen para repartir', + ADD CONSTRAINT zone_address_FK FOREIGN KEY (addressFk) REFERENCES vn.address(id) ON DELETE RESTRICT ON UPDATE CASCADE; + +ALTER TABLE vn.zoneConfig + ADD defaultAddressFk int(11) DEFAULT NULL NULL COMMENT 'Punto de distribución por defecto', + ADD CONSTRAINT zoneConfig_address_FK FOREIGN KEY (defaultAddressFk) REFERENCES vn.address(id) ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/db/versions/11379-yellowCordyline/01-secScript.sql b/db/versions/11379-yellowCordyline/01-secScript.sql new file mode 100644 index 000000000..30479229e --- /dev/null +++ b/db/versions/11379-yellowCordyline/01-secScript.sql @@ -0,0 +1,5 @@ +INSERT IGNORE INTO salix.ACL (model,property,accessType,permission,principalType,principalId) + VALUES ('OsrmConfig','optimize','READ','ALLOW','ROLE','employee'), + ('Route', 'optimizePriority','*','ALLOW','ROLE','employee'); +INSERT IGNORE INTO vn.osrmConfig (id,url,tolerance) + VALUES (1,'https://router.project-osrm.org', 0.002); diff --git a/db/versions/11384-grayAnthurium/00-firstScript.sql b/db/versions/11384-grayAnthurium/00-firstScript.sql new file mode 100644 index 000000000..b3a7f3da2 --- /dev/null +++ b/db/versions/11384-grayAnthurium/00-firstScript.sql @@ -0,0 +1,3 @@ +ALTER TABLE vn.mistakeType + ADD `time` int(10) NULL COMMENT 'Segundos que se suelen tardar en arreglar el fallo', + ADD code varchar(50) DEFAULT NULL NULL AFTER id; diff --git a/db/versions/11385-yellowOrchid/00-firstScript.sql b/db/versions/11385-yellowOrchid/00-firstScript.sql new file mode 100644 index 000000000..287e9fcab --- /dev/null +++ b/db/versions/11385-yellowOrchid/00-firstScript.sql @@ -0,0 +1,5 @@ +RENAME TABLE vn.inventoryFailure TO vn.inventoryFailure__; +ALTER TABLE vn.inventoryFailure__ COMMENT='@deprecated 2024-12-16'; + +RENAME TABLE vn.inventoryFailureCause TO vn.inventoryFailureCause__; +ALTER TABLE vn.inventoryFailureCause__ COMMENT='@deprecated 2024-12-16'; diff --git a/db/versions/11387-whiteDendro/00-firstScript.sql b/db/versions/11387-whiteDendro/00-firstScript.sql new file mode 100644 index 000000000..4e9f1d217 --- /dev/null +++ b/db/versions/11387-whiteDendro/00-firstScript.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS vn.productionCountry( + countryFk MEDIUMINT(8) UNSIGNED NOT NULL, + volumeGrowthEstimatePercent DECIMAL(6, 2) COMMENT 'Porcentaje estimado de crecimiento del volumen', + PRIMARY KEY (countryFk), + CONSTRAINT productionCountryVolume_countryFK + FOREIGN KEY (countryFk) REFERENCES vn.country (id) + ON DELETE RESTRICT ON UPDATE CASCADE +) COMMENT = 'Datos de producción por país' \ No newline at end of file diff --git a/db/versions/11390-goldenPalmetto/00-firstScript.sql b/db/versions/11390-goldenPalmetto/00-firstScript.sql new file mode 100644 index 000000000..adcc76e4f --- /dev/null +++ b/db/versions/11390-goldenPalmetto/00-firstScript.sql @@ -0,0 +1,3 @@ + +ALTER TABLE vn.country + ADD CONSTRAINT country_unique_name UNIQUE KEY (name); diff --git a/db/versions/11391-redPalmetto/00-itemAlter.sql b/db/versions/11391-redPalmetto/00-itemAlter.sql new file mode 100644 index 000000000..fc47d5fc0 --- /dev/null +++ b/db/versions/11391-redPalmetto/00-itemAlter.sql @@ -0,0 +1,2 @@ +ALTER TABLE `vn`.`item` +ADD COLUMN `isCustomInspectionRequired` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Indicates if the item requires physical inspection at customs'; diff --git a/db/versions/11396-blueErica/00-firstScript.sql b/db/versions/11396-blueErica/00-firstScript.sql new file mode 100644 index 000000000..b21965fe8 --- /dev/null +++ b/db/versions/11396-blueErica/00-firstScript.sql @@ -0,0 +1,5 @@ +DELETE FROM vn.workerMana + WHERE workerFk IN ( + SELECT workerFk + FROM vn.workerManaExcluded + ); diff --git a/db/versions/11398-orangeRose/00-zoneEventPriceOptimum.sql b/db/versions/11398-orangeRose/00-zoneEventPriceOptimum.sql new file mode 100644 index 000000000..0440714e4 --- /dev/null +++ b/db/versions/11398-orangeRose/00-zoneEventPriceOptimum.sql @@ -0,0 +1,5 @@ +ALTER TABLE `vn`.`zoneEvent` + ADD COLUMN `priceOptimum` DECIMAL(10,2) NULL COMMENT 'Precio mínimo que puede pagar un bulto' + AFTER `price`, + ADD CONSTRAINT `ck_zoneEvent_priceOptimum` + CHECK (priceOptimum <= price) diff --git a/db/versions/11398-orangeRose/00-zonePriceOptimum.sql b/db/versions/11398-orangeRose/00-zonePriceOptimum.sql new file mode 100644 index 000000000..82b2001cd --- /dev/null +++ b/db/versions/11398-orangeRose/00-zonePriceOptimum.sql @@ -0,0 +1,5 @@ +ALTER TABLE `vn`.`zone` + ADD COLUMN `priceOptimum` DECIMAL(10,2) NOT NULL COMMENT 'Precio mínimo que puede pagar un bulto' + AFTER `price`, + ADD CONSTRAINT `ck_zone_priceOptimum` + CHECK (priceOptimum <= price) diff --git a/db/versions/11398-orangeRose/01-zoneUpdate.sql b/db/versions/11398-orangeRose/01-zoneUpdate.sql new file mode 100644 index 000000000..042f2a92b --- /dev/null +++ b/db/versions/11398-orangeRose/01-zoneUpdate.sql @@ -0,0 +1,2 @@ +UPDATE `vn`.`zone` + SET `priceOptimum` = `price`; diff --git a/db/versions/11398-orangeRose/02-clientAlter.sql b/db/versions/11398-orangeRose/02-clientAlter.sql new file mode 100644 index 000000000..b5275a301 --- /dev/null +++ b/db/versions/11398-orangeRose/02-clientAlter.sql @@ -0,0 +1,3 @@ +ALTER TABLE `vn`.`client` + ADD COLUMN `packagesDiscountFactor` DECIMAL(4,3) NOT NULL DEFAULT 1.000 + COMMENT 'Porcentaje de ajuste entre el numero de bultos medio del cliente, y el número medio óptimo para las zonas en las que compra'; diff --git a/db/versions/11398-orangeRose/03-clientConfig.sql b/db/versions/11398-orangeRose/03-clientConfig.sql new file mode 100644 index 000000000..2869f26a2 --- /dev/null +++ b/db/versions/11398-orangeRose/03-clientConfig.sql @@ -0,0 +1,3 @@ +ALTER TABLE `vn`.`clientConfig` + ADD COLUMN `packagesOptimum` INT UNSIGNED NOT NULL DEFAULT 20 COMMENT 'Numero de bultos por cliente/dia para conseguir el precio optimo', + ADD COLUMN `monthsToCalcOptimumPrice` TINYINT UNSIGNED NOT NULL DEFAULT 3 COMMENT 'Número de meses a usar para el cálculo de client.packagesDiscountFactor'; diff --git a/db/versions/11400-turquoiseChrysanthemum/00-firstScript.sql b/db/versions/11400-turquoiseChrysanthemum/00-firstScript.sql new file mode 100644 index 000000000..f3e0355a8 --- /dev/null +++ b/db/versions/11400-turquoiseChrysanthemum/00-firstScript.sql @@ -0,0 +1,4 @@ +DELETE FROM salix.ACL WHERE property = 'canCreateAbsenceInPast'; + +INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId) + VALUES ('Worker','canModifyAbsenceInPast','WRITE','ALLOW','ROLE','hr'); diff --git a/db/versions/11405-blackMoss/00-entryAlter.sql b/db/versions/11405-blackMoss/00-entryAlter.sql new file mode 100644 index 000000000..3320b9dd3 --- /dev/null +++ b/db/versions/11405-blackMoss/00-entryAlter.sql @@ -0,0 +1,3 @@ +ALTER TABLE `vn`.`entry` + ADD COLUMN `initialTemperature` decimal(10,2) DEFAULT NULL COMMENT 'Temperatura de como lo recibimos del proveedor ej. en colombia', + ADD COLUMN `finalTemperature` decimal(10,2) DEFAULT NULL COMMENT 'Temperatura final de como llega a nuestras instalaciones'; diff --git a/db/versions/11406-bronzeMoss/00-currrencyAlter.sql b/db/versions/11406-bronzeMoss/00-currrencyAlter.sql new file mode 100644 index 000000000..86465545e --- /dev/null +++ b/db/versions/11406-bronzeMoss/00-currrencyAlter.sql @@ -0,0 +1,2 @@ +ALTER TABLE `vn`.`currency` +ADD COLUMN `hasToDownloadRate` TINYINT(1) NOT NULL DEFAULT 0 comment 'Si se guarda el tipo de cambio diariamente en referenceRate'; diff --git a/db/versions/11406-bronzeMoss/01-currrencyUpdate.sql b/db/versions/11406-bronzeMoss/01-currrencyUpdate.sql new file mode 100644 index 000000000..5e0882de2 --- /dev/null +++ b/db/versions/11406-bronzeMoss/01-currrencyUpdate.sql @@ -0,0 +1,3 @@ +UPDATE `vn`.`currency` + SET `hasToDownloadRate` = TRUE + WHERE `code` IN ('USD', 'CNY', 'GBP'); diff --git a/db/versions/11407-turquoiseTulip/00-firstScript.sql b/db/versions/11407-turquoiseTulip/00-firstScript.sql new file mode 100644 index 000000000..72d29061d --- /dev/null +++ b/db/versions/11407-turquoiseTulip/00-firstScript.sql @@ -0,0 +1,2 @@ +INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId) + VALUES ('VnUser','adminUser','WRITE','ALLOW','ROLE','sysadmin'); \ No newline at end of file diff --git a/db/versions/11410-blackTulip/00-firstScript.sql b/db/versions/11410-blackTulip/00-firstScript.sql new file mode 100644 index 000000000..e300c4b7c --- /dev/null +++ b/db/versions/11410-blackTulip/00-firstScript.sql @@ -0,0 +1,2 @@ +RENAME TABLE bi.f_tvc TO bi.f_tvc__; +ALTER TABLE bi.f_tvc__ COMMENT='@deprecated 2025-01-15'; \ No newline at end of file diff --git a/db/versions/11415-chocolateTulip/00-firstScript.sql b/db/versions/11415-chocolateTulip/00-firstScript.sql new file mode 100644 index 000000000..2ed7ec9b5 --- /dev/null +++ b/db/versions/11415-chocolateTulip/00-firstScript.sql @@ -0,0 +1 @@ +CREATE INDEX ticket_landed_IDX USING BTREE ON vn.ticket (landed); diff --git a/db/versions/11418-goldenRuscus/00-firstScript.sql b/db/versions/11418-goldenRuscus/00-firstScript.sql new file mode 100644 index 000000000..6c623d7b7 --- /dev/null +++ b/db/versions/11418-goldenRuscus/00-firstScript.sql @@ -0,0 +1,130 @@ +-- Place your SQL code here +CREATE TABLE IF NOT EXISTS `vn`.`itemSoldOutTag` ( + `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `name_UNIQUE` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT + CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; + +INSERT IGNORE INTO `vn`.`itemSoldOutTag` (`name`) VALUES ('Ultimas unidades'); +INSERT IGNORE INTO `vn`.`itemSoldOutTag` (`name`) VALUES ('Temporalmente'); +INSERT IGNORE INTO `vn`.`itemSoldOutTag` (`name`) VALUES ('Descatalogado'); +INSERT IGNORE INTO `vn`.`itemSoldOutTag` (`name`) VALUES ('Hasta mayo'); +INSERT IGNORE INTO `vn`.`itemSoldOutTag` (`name`) VALUES ('Hasta febrero'); +INSERT IGNORE INTO `vn`.`itemSoldOutTag` (`name`) VALUES ('Hasta diciembre'); +INSERT IGNORE INTO `vn`.`itemSoldOutTag` (`name`) VALUES ('Hasta enero'); +INSERT IGNORE INTO `vn`.`itemSoldOutTag` (`name`) VALUES ('Hasta marzo'); +INSERT IGNORE INTO `vn`.`itemSoldOutTag` (`name`) VALUES ('Hasta nueva temporada'); +INSERT IGNORE INTO `vn`.`itemSoldOutTag` (`name`) VALUES ('Hasta septiembre'); + +UPDATE vn.tag + SET isFree=FALSE, + sourceTable='itemSoldOutTag' + WHERE name= 'Agotado'; + + +CREATE TABLE IF NOT EXISTS `vn`.`itemDurationTag` ( + `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `name_UNIQUE` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT + CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; + +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('10 días'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('11 días'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('12 días'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('13 días'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('14 días'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('15 días'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('17 días'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('7 días'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('9 días'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('16-20 días'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('17-21 días'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('19-23 días'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('3-4 semanas'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('13-17 días'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('14-16 días'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('15-19 días'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('18-25 días'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('20 días'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('6 días'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('9 días'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('10-13 días'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('6 meses'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('5 años'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('10 horas'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('20 horas'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('35 horas'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('6 horas'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('11 horas'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('12 horas'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('14 horas'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('15 horas'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('18 horas'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('19 horas'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('24 horas'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('25 horas'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('30 horas'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('32 horas'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('4 horas'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('40 horas'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('45 horas'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('50 horas'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('55 horas'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('70 horas'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('8 horas'); +INSERT IGNORE INTO `vn`.`itemDurationTag` (`name`) VALUES ('9 horas'); + +UPDATE vn.tag + SET isFree=FALSE, + sourceTable='itemDurationTag' + WHERE name= 'Duracion'; + + +CREATE TABLE IF NOT EXISTS `vn`.`itemGrowingTag` ( + `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `name_UNIQUE` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT + CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; + +INSERT IGNORE INTO `vn`.`itemGrowingTag` (`name`) VALUES ('01-05'); +INSERT IGNORE INTO `vn`.`itemGrowingTag` (`name`) VALUES ('01-06'); +INSERT IGNORE INTO `vn`.`itemGrowingTag` (`name`) VALUES ('01-12'); +INSERT IGNORE INTO `vn`.`itemGrowingTag` (`name`) VALUES ('02-06'); +INSERT IGNORE INTO `vn`.`itemGrowingTag` (`name`) VALUES ('03-05'); +INSERT IGNORE INTO `vn`.`itemGrowingTag` (`name`) VALUES ('03-07'); +INSERT IGNORE INTO `vn`.`itemGrowingTag` (`name`) VALUES ('03-08'); +INSERT IGNORE INTO `vn`.`itemGrowingTag` (`name`) VALUES ('03-11'); +INSERT IGNORE INTO `vn`.`itemGrowingTag` (`name`) VALUES ('04-06'); +INSERT IGNORE INTO `vn`.`itemGrowingTag` (`name`) VALUES ('04-09'); +INSERT IGNORE INTO `vn`.`itemGrowingTag` (`name`) VALUES ('04-11'); +INSERT IGNORE INTO `vn`.`itemGrowingTag` (`name`) VALUES ('05-07'); +INSERT IGNORE INTO `vn`.`itemGrowingTag` (`name`) VALUES ('05-08'); +INSERT IGNORE INTO `vn`.`itemGrowingTag` (`name`) VALUES ('05-10'); +INSERT IGNORE INTO `vn`.`itemGrowingTag` (`name`) VALUES ('05-11'); +INSERT IGNORE INTO `vn`.`itemGrowingTag` (`name`) VALUES ('06-09'); +INSERT IGNORE INTO `vn`.`itemGrowingTag` (`name`) VALUES ('06-10'); +INSERT IGNORE INTO `vn`.`itemGrowingTag` (`name`) VALUES ('06-11'); +INSERT IGNORE INTO `vn`.`itemGrowingTag` (`name`) VALUES ('07-09'); +INSERT IGNORE INTO `vn`.`itemGrowingTag` (`name`) VALUES ('07-10'); +INSERT IGNORE INTO `vn`.`itemGrowingTag` (`name`) VALUES ('07-11'); +INSERT IGNORE INTO `vn`.`itemGrowingTag` (`name`) VALUES ('07-12'); +INSERT IGNORE INTO `vn`.`itemGrowingTag` (`name`) VALUES ('09-12'); +INSERT IGNORE INTO `vn`.`itemGrowingTag` (`name`) VALUES ('01-04 / 10-12'); +INSERT IGNORE INTO `vn`.`itemGrowingTag` (`name`) VALUES ('01-04 / 9-12'); +INSERT IGNORE INTO `vn`.`itemGrowingTag` (`name`) VALUES ('01-05 / 10-12'); +INSERT IGNORE INTO `vn`.`itemGrowingTag` (`name`) VALUES ('01-05 / 11-12'); + +UPDATE vn.tag + SET isFree=FALSE, + sourceTable='itemGrowingTag' + WHERE name= 'Recolecta'; + +GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE vn.itemSoldOutTag TO logisticAssist; +GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE vn.itemDurationTag TO logisticAssist; +GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE vn.itemGrowingTag TO logisticAssist; diff --git a/db/versions/11422-blackAsparagus/00-firstScript.sql b/db/versions/11422-blackAsparagus/00-firstScript.sql new file mode 100644 index 000000000..bb0e7c3e9 --- /dev/null +++ b/db/versions/11422-blackAsparagus/00-firstScript.sql @@ -0,0 +1,5 @@ +RENAME TABLE vn.sorter TO vn.sorter__; +ALTER TABLE vn.sorter__ COMMENT='@deprecated 2025-01-22'; + +RENAME TABLE vn.splitLine TO vn.splitLine__; +ALTER TABLE vn.splitLine__ COMMENT='@deprecated 2025-01-22'; \ No newline at end of file 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 index d9689e31a..af1dc56bc 100644 --- a/e2e/paths/05-ticket/01-sale/02_edit_sale.spec.js +++ b/e2e/paths/05-ticket/01-sale/02_edit_sale.spec.js @@ -238,25 +238,11 @@ describe('Ticket Edit sale path', () => { 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(); + it('should select the third sale and delete it', async() => { 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); diff --git a/e2e/paths/05-ticket/06_basic_data_steps.spec.js b/e2e/paths/05-ticket/06_basic_data_steps.spec.js index 77f0e0459..0a3ae4edc 100644 --- a/e2e/paths/05-ticket/06_basic_data_steps.spec.js +++ b/e2e/paths/05-ticket/06_basic_data_steps.spec.js @@ -75,7 +75,7 @@ describe('Ticket Edit basic data path', () => { const result = await page .waitToGetProperty(selectors.ticketBasicData.stepTwoTotalPriceDif, 'innerText'); - expect(result).toContain('-€228.25'); + expect(result).toContain('-€111.75'); }); it(`should select a new reason for the changes made then click on finalize`, async() => { diff --git a/loopback/locale/en.json b/loopback/locale/en.json index 002a3307e..06428475f 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -211,6 +211,7 @@ "Name should be uppercase": "Name should be uppercase", "You cannot update these fields": "You cannot update these fields", "CountryFK cannot be empty": "Country cannot be empty", + "No tickets to invoice": "There are no tickets to invoice that meet the invoicing requirements", "You are not allowed to modify the alias": "You are not allowed to modify the alias", "You already have the mailAlias": "You already have the mailAlias", "This machine is already in use.": "This machine is already in use.", @@ -246,8 +247,11 @@ "ticketLostExpedition": "The ticket [{{ticketId}}]({{{ticketUrl}}}) has the following lost expedition:{{ expeditionId }}", "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", - "Holidays to past days not available": "Holidays to past days not available", - "There are tickets to be invoiced": "There are tickets to be invoiced for this zone, please delete them first", - "Price cannot be blank": "Price cannot be blank" -} + "Price cannot be blank": "Price cannot be blank", + "There are tickets to be invoiced": "There are tickets to be invoiced", + "The address of the customer must have information about Incoterms and Customs Agent": "The address of the customer must have information about Incoterms and Customs Agent", + "Sales already moved": "Sales already moved", + "Holidays to past days not available": "Holidays to past days not available", + "Incorrect delivery order alert on route": "Incorrect delivery order alert on route: {{ route }} zone: {{ zone }}", + "Ticket has been delivered out of order": "The ticket {{ticket}} {{{fullUrl}}} has been delivered out of order." +} \ No newline at end of file diff --git a/loopback/locale/es.json b/loopback/locale/es.json index a81f2574f..abd2f79a0 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -339,7 +339,7 @@ "Incorrect pin": "Pin incorrecto.", "You already have the mailAlias": "Ya tienes este alias de correo", "The alias cant be modified": "Este alias de correo no puede ser modificado", - "No tickets to invoice": "No hay tickets para facturar", + "No tickets to invoice": "No hay tickets para facturar que cumplan los requisitos de facturación", "this warehouse has not dms": "El Almacén no acepta documentos", "This ticket already has a cmr saved": "Este ticket ya tiene un cmr guardado", "Name should be uppercase": "El nombre debe ir en mayúscula", @@ -390,8 +390,11 @@ "The web user's email already exists": "El correo del usuario web ya existe", "Sales already moved": "Ya han sido transferidas", "The raid information is not correct": "La información de la redada no es correcta", - "There are tickets to be invoiced": "Hay tickets para esta zona, borralos primero", - "Price cannot be blank": "Price cannot be blank", "An item type with the same code already exists": "Un tipo con el mismo código ya existe", - "Holidays to past days not available": "Las vacaciones a días pasados no están disponibles" -} + "Holidays to past days not available": "Las vacaciones a días pasados no están disponibles", + "All tickets have a route order": "Todos los tickets tienen orden de ruta", + "There are tickets to be invoiced": "La zona tiene tickets por facturar", + "Incorrect delivery order alert on route": "Alerta de orden de entrega incorrecta en ruta: {{ route }} zona: {{ zone }}", + "Ticket has been delivered out of order": "El ticket {{ticket}} {{{fullUrl}}} no ha sigo entregado en su orden.", + "Price cannot be blank": "El precio no puede estar en blanco" +} \ No newline at end of file diff --git a/loopback/locale/fr.json b/loopback/locale/fr.json index 9941358be..d7d5b7710 100644 --- a/loopback/locale/fr.json +++ b/loopback/locale/fr.json @@ -339,7 +339,7 @@ "Incorrect pin": "Pin incorrect.", "You already have the mailAlias": "Vous avez déjà cet alias de courrier", "The alias cant be modified": "Cet alias de courrier ne peut pas être modifié", - "No tickets to invoice": "Pas de tickets à facturer", + "No tickets to invoice": "Il n'y a pas de tickets à facturer qui répondent aux exigences de facturation", "this warehouse has not dms": "L'entrepôt n'accepte pas les documents", "This ticket already has a cmr saved": "Ce ticket a déjà un cmr enregistré", "Name should be uppercase": "Le nom doit être en majuscules", @@ -362,9 +362,11 @@ "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", - "You do not have permission to modify the booked field": "Vous n'avez pas la permission de modifier le champ comptabilisé", + "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à" -} + "The web user's email already exists": "L'email de l'internaute existe déjà", + "Incorrect delivery order alert on route": "Alerte de bon de livraison incorrect sur l'itinéraire: {{ route }} zone : {{ zone }}", + "Ticket has been delivered out of order": "Le ticket {{ticket}} {{{fullUrl}}} a été livré hors ordre." +} \ No newline at end of file diff --git a/loopback/locale/pt.json b/loopback/locale/pt.json index e84b30f3d..d1ac2ef23 100644 --- a/loopback/locale/pt.json +++ b/loopback/locale/pt.json @@ -339,7 +339,7 @@ "Incorrect pin": "PIN incorreto.", "You already have the mailAlias": "Você já tem o alias de e-mail", "The alias cant be modified": "O alias não pode ser modificado", - "No tickets to invoice": "Não há tickets para faturar", + "No tickets to invoice": "Não há bilhetes para faturar que atendam aos requisitos de faturamento", "this warehouse has not dms": "Este armazém não tem DMS", "This ticket already has a cmr saved": "Este ticket já tem um CMR salvo", "Name should be uppercase": "O nome deve estar em maiúsculas", @@ -365,5 +365,7 @@ "Cannot send mail": "Não é possível enviar o email", "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." -} + "The web user's email already exists": "O e-mail do utilizador da web já existe.", + "Incorrect delivery order alert on route": "Alerta de ordem de entrega incorreta na rota: {{ route }} zona: {{ zone }}", + "Ticket has been delivered out of order": "O ticket {{ticket}} {{{fullUrl}}} foi entregue fora de ordem." +} \ No newline at end of file diff --git a/modules/account/back/methods/account/sync.js b/modules/account/back/methods/account/sync.js index 1026c5020..b38e4dd37 100644 --- a/modules/account/back/methods/account/sync.js +++ b/modules/account/back/methods/account/sync.js @@ -29,14 +29,14 @@ module.exports = Self => { const models = Self.app.models; const myOptions = {}; let tx; - + if (typeof options == 'object') Object.assign(myOptions, options); if (!myOptions.transaction) { tx = await Self.beginTransaction({}); myOptions.transaction = tx; - }; + } try { const user = await models.VnUser.findOne({ diff --git a/modules/claim/back/methods/claim/filter.js b/modules/claim/back/methods/claim/filter.js index f60b6572e..bf9cd9441 100644 --- a/modules/claim/back/methods/claim/filter.js +++ b/modules/claim/back/methods/claim/filter.js @@ -80,6 +80,12 @@ module.exports = Self => { description: 'The claimResponsible id', http: {source: 'query'} }, + { + arg: 'zoneFk', + type: 'string', + description: 'The zone name', + http: {source: 'query'} + }, { arg: 'myTeam', type: 'boolean', @@ -103,6 +109,7 @@ module.exports = Self => { const args = ctx.args; const myOptions = {}; let to; + let myTeamIds = []; if (typeof options == 'object') Object.assign(myOptions, options); @@ -127,21 +134,8 @@ module.exports = Self => { claimIdsByClaimResponsibleFk = claims.map(claim => claim.claimFk); } - // Apply filter by team - const teamMembersId = []; - if (args.myTeam != null) { - const worker = await models.Worker.findById(userId, { - include: { - relation: 'collegues' - } - }, myOptions); - const collegues = worker.collegues() || []; - for (let collegue of collegues) - teamMembersId.push(collegue.collegueFk); - - if (teamMembersId.length == 0) - teamMembersId.push(userId); - } + if (args.myTeam != null) + myTeamIds = await models.Worker.myTeam(userId); const where = buildFilter(ctx.args, (param, value) => { switch (param) { @@ -174,11 +168,13 @@ module.exports = Self => { to.setHours(23, 59, 59, 999); return {'cl.created': {between: [value, to]}}; + case 'zoneFk': + return {'t.zoneFk': value}; case 'myTeam': if (value) - return {'cl.workerFk': {inq: teamMembersId}}; + return {'cl.workerFk': {inq: myTeamIds}}; else - return {'cl.workerFk': {nin: teamMembersId}}; + return {'cl.workerFk': {nin: myTeamIds}}; } }); @@ -195,11 +191,15 @@ module.exports = Self => { u.name AS workerName, cs.code stateCode, cs.description stateDescription, - cl.created + cl.created, + z.name zoneName, + z.id zoneId FROM claim cl LEFT JOIN client c ON c.id = cl.clientFk LEFT JOIN account.user u ON u.id = cl.workerFk - LEFT JOIN claimState cs ON cs.id = cl.claimStateFk` + LEFT JOIN claimState cs ON cs.id = cl.claimStateFk + LEFT JOIN ticket t ON t.id = cl.ticketFk + LEFT JOIN zone z ON z.id = t.zoneFk` ); stmt.merge(conn.makeSuffix(filter)); diff --git a/modules/client/back/methods/client/canBeInvoiced.js b/modules/client/back/methods/client/canBeInvoiced.js index cdb865500..536606b0b 100644 --- a/modules/client/back/methods/client/canBeInvoiced.js +++ b/modules/client/back/methods/client/canBeInvoiced.js @@ -2,7 +2,7 @@ const UserError = require('vn-loopback/util/user-error'); module.exports = function(Self) { Self.remoteMethod('canBeInvoiced', { - description: 'Change property isEqualizated in all client addresses', + description: 'Check if a client can be invoiced', accessType: 'READ', accepts: [ { @@ -38,7 +38,7 @@ module.exports = function(Self) { Object.assign(myOptions, options); const client = await models.Client.findById(id, { - fields: ['id', 'isTaxDataChecked', 'hasToInvoice', 'payMethodFk'], + fields: ['id', 'isTaxDataChecked', 'hasToInvoice', 'payMethodFk', 'isActive'], include: { relation: 'payMethod', @@ -53,9 +53,6 @@ module.exports = function(Self) { if (client.payMethod().code === 'wireTransfer' && !company.supplierAccountFk) throw new UserError('The company has not informed the supplier account for bank transfers'); - if (client.isTaxDataChecked && client.hasToInvoice) - return true; - - return false; + return client.isTaxDataChecked && client.hasToInvoice && client.isActive; }; }; diff --git a/modules/client/back/methods/client/createAddress.js b/modules/client/back/methods/client/createAddress.js index 2709632cb..6bd4a26c1 100644 --- a/modules/client/back/methods/client/createAddress.js +++ b/modules/client/back/methods/client/createAddress.js @@ -52,6 +52,14 @@ module.exports = function(Self) { arg: 'customsAgentFk', type: 'number' }, + { + arg: 'longitude', + type: 'number' + }, + { + arg: 'latitude', + type: 'number' + }, { arg: 'isActive', type: 'boolean' diff --git a/modules/client/back/methods/client/specs/canBeInvoiced.spec.js b/modules/client/back/methods/client/specs/canBeInvoiced.spec.js index 397be3c92..4012b7409 100644 --- a/modules/client/back/methods/client/specs/canBeInvoiced.spec.js +++ b/modules/client/back/methods/client/specs/canBeInvoiced.spec.js @@ -8,6 +8,8 @@ describe('client canBeInvoiced()', () => { const activeCtx = { accessToken: {userId: userId} }; + let tx; + let options; beforeAll(async() => { spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ @@ -15,60 +17,45 @@ describe('client canBeInvoiced()', () => { }); }); + beforeEach(async() => { + tx = await models.Client.beginTransaction({}); + options = {transaction: tx}; + }); + + afterEach(async() => { + await tx.rollback(); + }); + it('should return falsy for a client without the data checked', async() => { - const tx = await models.Client.beginTransaction({}); + const client = await models.Client.findById(clientId, null, options); + await client.updateAttribute('isTaxDataChecked', false, options); - try { - const options = {transaction: tx}; + const canBeInvoiced = await models.Client.canBeInvoiced(clientId, companyId, options); - const client = await models.Client.findById(clientId, null, options); - await client.updateAttribute('isTaxDataChecked', false, options); + expect(canBeInvoiced).toEqual(false); + }); - const canBeInvoiced = await models.Client.canBeInvoiced(clientId, companyId, options); + it('should return falsy for a client not active', async() => { + const client = await models.Client.findById(clientId, null, options); + await client.updateAttribute('isActive', false, options); - expect(canBeInvoiced).toEqual(false); + const canBeInvoiced = await models.Client.canBeInvoiced(clientId, companyId, options); - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } + expect(canBeInvoiced).toEqual(false); }); it('should return falsy for a client with invoicing disabled', async() => { - const tx = await models.Client.beginTransaction({}); + const client = await models.Client.findById(clientId, null, options); + await client.updateAttribute('hasToInvoice', false, options); - try { - const options = {transaction: tx}; + const canBeInvoiced = await models.Client.canBeInvoiced(clientId, companyId, options); - const client = await models.Client.findById(clientId, null, options); - await client.updateAttribute('hasToInvoice', false, options); - - const canBeInvoiced = await models.Client.canBeInvoiced(clientId, companyId, options); - - expect(canBeInvoiced).toEqual(false); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } + expect(canBeInvoiced).toEqual(false); }); it('should return truthy for an invoiceable client', async() => { - const tx = await models.Client.beginTransaction({}); + const canBeInvoiced = await models.Client.canBeInvoiced(clientId, companyId, options); - try { - const options = {transaction: tx}; - - const canBeInvoiced = await models.Client.canBeInvoiced(clientId, companyId, options); - - expect(canBeInvoiced).toEqual(true); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } + expect(canBeInvoiced).toEqual(true); }); }); diff --git a/modules/client/back/methods/client/specs/updateAddress.spec.js b/modules/client/back/methods/client/specs/updateAddress.spec.js index 68981f8b7..0453332d7 100644 --- a/modules/client/back/methods/client/specs/updateAddress.spec.js +++ b/modules/client/back/methods/client/specs/updateAddress.spec.js @@ -1,7 +1,7 @@ const models = require('vn-loopback/server/server').models; describe('Address updateAddress', () => { - const clientId = 1101; - const addressId = 1; + const clientId = 1102; + const addressId = 2; const provinceId = 5; const incotermsId = 'FAS'; const customAgentOneId = 1; diff --git a/modules/client/back/methods/client/updateAddress.js b/modules/client/back/methods/client/updateAddress.js index 7342b28f1..efef83d6b 100644 --- a/modules/client/back/methods/client/updateAddress.js +++ b/modules/client/back/methods/client/updateAddress.js @@ -72,6 +72,14 @@ module.exports = function(Self) { { arg: 'isLogifloraAllowed', type: 'boolean' + }, + { + arg: 'longitude', + type: 'any', + }, + { + arg: 'latitude', + type: 'any', } ], returns: { diff --git a/modules/client/back/methods/defaulter/filter.js b/modules/client/back/methods/defaulter/filter.js index 5359ce4a7..cf8bd855a 100644 --- a/modules/client/back/methods/defaulter/filter.js +++ b/modules/client/back/methods/defaulter/filter.js @@ -94,7 +94,7 @@ module.exports = Self => { AND r1.started = r2.maxStarted ) r ON r.clientFk = c.id LEFT JOIN workerDepartment wd ON wd.workerFk = u.id - JOIN department dp ON dp.id = wd.departmentFk + LEFT JOIN department dp ON dp.id = wd.departmentFk WHERE d.created = ? AND d.amount > 0 diff --git a/modules/client/back/models/address.json b/modules/client/back/models/address.json index e8bf8d8a0..2d11b7745 100644 --- a/modules/client/back/models/address.json +++ b/modules/client/back/models/address.json @@ -84,6 +84,11 @@ "type": "belongsTo", "model": "CustomsAgent", "foreignKey": "customsAgentFk" + }, + "postcode": { + "type": "belongsTo", + "model": "Postcode", + "foreignKey": "postalCode" } } } diff --git a/modules/client/back/models/client-credit.json b/modules/client/back/models/client-credit.json index b92639b80..b57374dc3 100644 --- a/modules/client/back/models/client-credit.json +++ b/modules/client/back/models/client-credit.json @@ -19,6 +19,9 @@ }, "created": { "type": "date" + }, + "workerFk": { + "type": "number" } }, "relations": { @@ -33,4 +36,4 @@ "foreignKey": "workerFk" } } -} \ No newline at end of file +} diff --git a/modules/entry/back/methods/entry/filter.js b/modules/entry/back/methods/entry/filter.js index d7740dd4e..e5eae85fd 100644 --- a/modules/entry/back/methods/entry/filter.js +++ b/modules/entry/back/methods/entry/filter.js @@ -119,6 +119,16 @@ module.exports = Self => { arg: 'invoiceAmount', type: 'number', description: `The invoice amount` + }, + { + arg: 'initialTemperature', + type: 'number', + description: 'Initial temperature value' + }, + { + arg: 'finalTemperature', + type: 'number', + description: 'Final temperature value' } ], returns: { @@ -170,6 +180,10 @@ module.exports = Self => { case 'invoiceInFk': param = `e.${param}`; return {[param]: value}; + case 'initialTemperature': + return {'e.initialTemperature': {lte: value}}; + case 'finalTemperature': + return {'e.finalTemperature': {gte: value}}; } }); filter = mergeFilters(ctx.args.filter, {where}); @@ -204,6 +218,8 @@ module.exports = Self => { e.gestDocFk, e.invoiceInFk, e.invoiceAmount, + e.initialTemperature, + e.finalTemperature, t.landed, s.name supplierName, s.nickname supplierAlias, diff --git a/modules/entry/back/models/entry.json b/modules/entry/back/models/entry.json index 4a09c7d6a..1ff062119 100644 --- a/modules/entry/back/models/entry.json +++ b/modules/entry/back/models/entry.json @@ -68,6 +68,12 @@ }, "invoiceAmount": { "type": "number" + }, + "initialTemperature": { + "type": "number" + }, + "finalTemperature": { + "type": "number" } }, "relations": { diff --git a/modules/invoiceIn/back/locale/invoiceIn/en.yml b/modules/invoiceIn/back/locale/invoiceIn/en.yml index 9e94eba0d..f590f9656 100644 --- a/modules/invoiceIn/back/locale/invoiceIn/en.yml +++ b/modules/invoiceIn/back/locale/invoiceIn/en.yml @@ -17,4 +17,6 @@ columns: isVatDeductible: is VAT deductible withholdingSageFk: withholding expenseFkDeductible: expense deductible - editorFk: editor \ No newline at end of file + editorFk: editor + siiTrasCendencyInvoiceInFk: SII tax regime + siiTypeInvoiceInFk: SII Type \ No newline at end of file diff --git a/modules/invoiceIn/back/locale/invoiceIn/es.yml b/modules/invoiceIn/back/locale/invoiceIn/es.yml index bd64c4327..64ded6aca 100644 --- a/modules/invoiceIn/back/locale/invoiceIn/es.yml +++ b/modules/invoiceIn/back/locale/invoiceIn/es.yml @@ -5,7 +5,7 @@ columns: serial: serie supplierFk: proveedor issued: fecha emisión - supplierRef: referéncia proveedor + supplierRef: referencia proveedor isBooked: facturado currencyFk: moneda created: creado @@ -17,4 +17,6 @@ columns: isVatDeductible: impuesto deducible withholdingSageFk: código de retención expenseFkDeductible: gasto deducible - editorFk: editor \ No newline at end of file + editorFk: editor + siiTrasCendencyInvoiceInFk: régimen fiscal SII + siiTypeInvoiceInFk: tipo SII \ No newline at end of file diff --git a/modules/invoiceIn/back/methods/invoice-in/corrective.js b/modules/invoiceIn/back/methods/invoice-in/corrective.js index 05f632bcd..e7088d201 100644 --- a/modules/invoiceIn/back/methods/invoice-in/corrective.js +++ b/modules/invoiceIn/back/methods/invoice-in/corrective.js @@ -44,7 +44,7 @@ module.exports = Self => { correctingFk: clone.id, correctedFk: id, cplusRectificationTypeFk: invoiceType, - siiTypeInvoiceOutFk: invoiceClass, + siiTypeInvoiceInFk: invoiceClass, invoiceCorrectionTypeFk: invoiceReason }, myOptions); diff --git a/modules/invoiceIn/back/methods/invoice-in/exchangeRateUpdate.js b/modules/invoiceIn/back/methods/invoice-in/exchangeRateUpdate.js index 989b1d4a2..99ff4cd79 100644 --- a/modules/invoiceIn/back/methods/invoice-in/exchangeRateUpdate.js +++ b/modules/invoiceIn/back/methods/invoice-in/exchangeRateUpdate.js @@ -13,66 +13,114 @@ module.exports = Self => { } }); - Self.exchangeRateUpdate = async() => { - const response = await axios.get('http://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist-90d.xml'); - const xmlData = response.data; - - const doc = new DOMParser({errorHandler: {warning: () => {}}})?.parseFromString(xmlData, 'text/xml'); - const cubes = doc?.getElementsByTagName('Cube'); - if (!cubes || cubes.length === 0) - throw new UserError('No cubes found. Exiting the method.'); - + Self.exchangeRateUpdate = async(options = {}) => { const models = Self.app.models; + const myOptions = {}; + let tx; - const maxDateRecord = await models.ReferenceRate.findOne({order: 'dated DESC'}); + if (typeof options == 'object') + Object.assign(myOptions, options); - const maxDate = maxDateRecord?.dated ? new Date(maxDateRecord.dated) : null; + if (!myOptions.transaction) { + tx = await Self.beginTransaction({}); + myOptions.transaction = tx; + } + + try { + const response = await axios.get('http://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist-90d.xml'); + const xmlData = response.data; + + const doc = new DOMParser({errorHandler: {warning: () => {}}}) + .parseFromString(xmlData, 'text/xml'); + const cubes = doc?.getElementsByTagName('Cube'); + if (!cubes || cubes.length === 0) + throw new UserError('No cubes found. Exiting the method.'); + + const currencies = await models.Currency.find({where: {hasToDownloadRate: true}}, myOptions); + const maxDateRecord = await models.ReferenceRate.findOne({order: 'dated DESC'}, myOptions); + const maxDate = maxDateRecord?.dated ? new Date(maxDateRecord.dated) : null; + let lastProcessedDate = maxDate; + + for (const cube of Array.from(cubes)) { + if (cube.nodeType === doc.ELEMENT_NODE && cube.attributes.getNamedItem('time')) { + const xmlDate = new Date(cube.getAttribute('time')); + const xmlDateWithoutTime = new Date( + xmlDate.getFullYear(), + xmlDate.getMonth(), + xmlDate.getDate() + ); + + if (!maxDate || xmlDateWithoutTime > maxDate) { + if (lastProcessedDate && xmlDateWithoutTime > lastProcessedDate) { + for (const currency of currencies) { + await fillMissingDates( + models, currency, lastProcessedDate, xmlDateWithoutTime, myOptions + ); + } + } + } - for (const cube of Array.from(cubes)) { - if (cube.nodeType === doc.ELEMENT_NODE && cube.attributes.getNamedItem('time')) { - const xmlDate = new Date(cube.getAttribute('time')); - const xmlDateWithoutTime = new Date(xmlDate.getFullYear(), xmlDate.getMonth(), xmlDate.getDate()); - if (!maxDate || maxDate < xmlDateWithoutTime) { for (const rateCube of Array.from(cube.childNodes)) { if (rateCube.nodeType === doc.ELEMENT_NODE) { const currencyCode = rateCube.getAttribute('currency'); const rate = rateCube.getAttribute('rate'); - if (['USD', 'CNY', 'GBP'].includes(currencyCode)) { - const currency = await models.Currency.findOne({where: {code: currencyCode}}); - if (!currency) throw new UserError(`Currency not found for code: ${currencyCode}`); + const currency = currencies.find(c => c.code === currencyCode); + if (currency) { const existingRate = await models.ReferenceRate.findOne({ - where: {currencyFk: currency.id, dated: xmlDate} - }); + where: {currencyFk: currency.id, dated: xmlDateWithoutTime} + }, myOptions); if (existingRate) { if (existingRate.value !== rate) - await existingRate.updateAttributes({value: rate}); + await existingRate.updateAttributes({value: rate}, myOptions); } else { await models.ReferenceRate.create({ currencyFk: currency.id, - dated: xmlDate, + dated: xmlDateWithoutTime, value: rate - }); - } - const monday = 1; - if (xmlDateWithoutTime.getDay() === monday) { - const saturday = new Date(xmlDateWithoutTime); - saturday.setDate(xmlDateWithoutTime.getDate() - 2); - const sunday = new Date(xmlDateWithoutTime); - sunday.setDate(xmlDateWithoutTime.getDate() - 1); - - for (const date of [saturday, sunday]) { - await models.ReferenceRate.upsertWithWhere( - {currencyFk: currency.id, dated: date}, - {currencyFk: currency.id, dated: date, value: rate} - ); - } + }, myOptions); } } } } + + lastProcessedDate = xmlDateWithoutTime; } } + + if (tx) await tx.commit(); + } catch (error) { + if (tx) await tx.rollback(); + throw error; } }; + + async function getLastValidRate(models, currencyId, date, myOptions) { + return models.ReferenceRate.findOne({ + where: {currencyFk: currencyId, dated: {lt: date}}, + order: 'dated DESC' + }, myOptions); + } + + async function fillMissingDates(models, currency, startDate, endDate, myOptions) { + const cursor = new Date(startDate); + cursor.setDate(cursor.getDate() + 1); + while (cursor < endDate) { + const existingRate = await models.ReferenceRate.findOne({ + where: {currencyFk: currency.id, dated: cursor} + }, myOptions); + + if (!existingRate) { + const lastValid = await getLastValidRate(models, currency.id, cursor, myOptions); + if (lastValid) { + await models.ReferenceRate.create({ + currencyFk: currency.id, + dated: new Date(cursor), + value: lastValid.value + }, myOptions); + } + } + cursor.setDate(cursor.getDate() + 1); + } + } }; diff --git a/modules/invoiceIn/back/methods/invoice-in/filter.js b/modules/invoiceIn/back/methods/invoice-in/filter.js index 936f7bb6c..f081368e4 100644 --- a/modules/invoiceIn/back/methods/invoice-in/filter.js +++ b/modules/invoiceIn/back/methods/invoice-in/filter.js @@ -91,6 +91,10 @@ module.exports = Self => { { arg: 'supplierActivityFk', type: 'string', + }, + { + arg: 'companyFk', + type: 'number', } ], returns: { @@ -161,8 +165,8 @@ module.exports = Self => { : {'ii.id': {nin: correcteds.map(x => x.correctingFk)}}; case 'correctedFk': return {'ii.id': {inq: correctings.map(x => x.correctingFk)}}; - case 'supplierActivityFk': - return {'s.supplierActivityFk': value}; + case 'companyFk': + return {'ii.companyFk': value}; } }); @@ -184,7 +188,9 @@ module.exports = Self => { s.name supplierName, s.account, SUM(iid.amount) amount, - sub.code awbCode + sub.code awbCode, + c.code, + MIN(iid.dueDated) dueDated FROM invoiceIn ii JOIN supplier s ON s.id = ii.supplierFk LEFT JOIN invoiceInDueDay iid ON iid.invoiceInFk = ii.id @@ -199,7 +205,8 @@ module.exports = Self => { GROUP BY de.duaFk ) sub ON sub.duaFk = d.id LEFT JOIN company co ON co.id = ii.companyFk - LEFT JOIN dms dm ON dm.id = ii.docFk` + LEFT JOIN dms dm ON dm.id = ii.docFk + JOIN company c ON c.id = ii.companyFk`, ); const sqlWhere = conn.makeWhere(filter.where); diff --git a/modules/invoiceIn/back/methods/invoice-in/specs/corrective.spec.js b/modules/invoiceIn/back/methods/invoice-in/specs/corrective.spec.js index c63f02439..aee8d3f2c 100644 --- a/modules/invoiceIn/back/methods/invoice-in/specs/corrective.spec.js +++ b/modules/invoiceIn/back/methods/invoice-in/specs/corrective.spec.js @@ -15,11 +15,11 @@ describe('invoiceIn corrective()', () => { await tx.rollback(); }); - it('La función corrective debería devolver un id cuando se ejecuta correctamente', async() => { + it('should return an id when executed correctly', async() => { const originalId = 1; const invoiceReason = 3; const invoiceType = 2; - const invoiceClass = 1; + const invoiceClass = 8; const cloneId = await models.InvoiceIn.corrective(ctx, originalId, invoiceReason, invoiceType, invoiceClass, options); @@ -30,7 +30,7 @@ describe('invoiceIn corrective()', () => { }, options); expect(correction.cplusRectificationTypeFk).toEqual(invoiceType); - expect(correction.siiTypeInvoiceOutFk).toEqual(invoiceClass); + expect(correction.siiTypeInvoiceInFk).toEqual(invoiceClass); expect(correction.invoiceCorrectionTypeFk).toEqual(invoiceReason); }); }); diff --git a/modules/invoiceIn/back/methods/invoice-in/specs/exchangeRateUpdate.spec.js b/modules/invoiceIn/back/methods/invoice-in/specs/exchangeRateUpdate.spec.js index 0fd7ea165..c3dcca5ae 100644 --- a/modules/invoiceIn/back/methods/invoice-in/specs/exchangeRateUpdate.spec.js +++ b/modules/invoiceIn/back/methods/invoice-in/specs/exchangeRateUpdate.spec.js @@ -1,52 +1,190 @@ describe('exchangeRateUpdate functionality', function() { const axios = require('axios'); const models = require('vn-loopback/server/server').models; + let tx; let options; - beforeEach(function() { - spyOn(axios, 'get').and.returnValue(Promise.resolve({ - data: ` - - - - - ` - })); + function formatYmd(d) { + const mm = (d.getMonth() + 1).toString().padStart(2, '0'); + const dd = d.getDate().toString().padStart(2, '0'); + return `${d.getFullYear()}-${mm}-${dd}`; + } + + afterEach(async() => { + await tx.rollback(); }); - it('should process XML data and update or create rates in the database', async function() { + beforeEach(async() => { + tx = await models.Sale.beginTransaction({}); + options = {transaction: tx}; + spyOn(axios, 'get').and.returnValue(Promise.resolve({data: ''})); + }); + + it('should process XML data and create rates', async function() { + const d1 = Date.vnNew(); + const d4 = Date.vnNew(); + d4.setDate(d4.getDate() + 1); + const xml = ` + + + + + + + + `; + axios.get.and.returnValue(Promise.resolve({data: xml})); spyOn(models.ReferenceRate, 'findOne').and.returnValue(Promise.resolve(null)); spyOn(models.ReferenceRate, 'create').and.returnValue(Promise.resolve()); + await models.InvoiceIn.exchangeRateUpdate(options); - await models.InvoiceIn.exchangeRateUpdate(); - - expect(models.ReferenceRate.create).toHaveBeenCalledTimes(2); + expect(models.ReferenceRate.create).toHaveBeenCalledTimes(3); }); - it('should not create or update rates when no XML data is available', async function() { + it('should handle no data', async function() { axios.get.and.returnValue(Promise.resolve({})); spyOn(models.ReferenceRate, 'create'); - - let thrownError = null; + let e; try { - await models.InvoiceIn.exchangeRateUpdate(); - } catch (error) { - thrownError = error; + await models.InvoiceIn.exchangeRateUpdate(options); + } catch (err) { + e = err; } - expect(thrownError.message).toBe('No cubes found. Exiting the method.'); + expect(e.message).toBe('No cubes found. Exiting the method.'); + expect(models.ReferenceRate.create).not.toHaveBeenCalled(); }); - it('should handle errors gracefully', async function() { + it('should handle errors', async function() { axios.get.and.returnValue(Promise.reject(new Error('Network error'))); - let error; - + let e; try { - await models.InvoiceIn.exchangeRateUpdate(); - } catch (e) { - error = e; + await models.InvoiceIn.exchangeRateUpdate(options); + } catch (err) { + e = err; } - expect(error).toBeDefined(); - expect(error.message).toBe('Network error'); + expect(e).toBeDefined(); + expect(e.message).toBe('Network error'); + }); + + it('should update existing rate', async function() { + const existingRate = await models.ReferenceRate.findOne({ + order: 'id DESC' + }, options); + + if (!existingRate) return fail('No ReferenceRate records in DB'); + + const currency = await models.Currency.findById(existingRate.currencyFk, null, options); + + const xml = ` + + + + `; + + axios.get.and.returnValue(Promise.resolve({data: xml})); + + await models.InvoiceIn.exchangeRateUpdate(options); + + const updatedRate = await models.ReferenceRate.findById(existingRate.id, null, options); + + expect(updatedRate.value).toBeCloseTo('2.22'); + }); + + it('should not update if same rate', async function() { + const existingRate = await models.ReferenceRate.findOne({order: 'id DESC'}, options); + if (!existingRate) return fail('No existing ReferenceRate in DB'); + + const currency = await models.Currency.findById(existingRate.currencyFk, null, options); + + const oldValue = existingRate.value; + const xml = ` + + + + `; + + axios.get.and.returnValue(Promise.resolve({data: xml})); + + await models.InvoiceIn.exchangeRateUpdate(options); + + const updatedRate = await models.ReferenceRate.findById(existingRate.id, null, options); + + expect(updatedRate.value).toBe(oldValue); + }); + + it('should backfill missing dates', async function() { + const lastRate = await models.ReferenceRate.findOne({order: 'dated DESC'}, options); + if (!lastRate) return fail('No existing ReferenceRate data in DB'); + + const currency = await models.Currency.findById(lastRate.currencyFk, null, options); + + const d1 = new Date(lastRate.dated); + d1.setDate(d1.getDate() + 1); + const d4 = new Date(lastRate.dated); + d4.setDate(d4.getDate() + 4); + + const xml = ` + + + + + + + `; + + axios.get.and.returnValue(Promise.resolve({data: xml})); + + const beforeCount = await models.ReferenceRate.count({}, options); + await models.InvoiceIn.exchangeRateUpdate(options); + const afterCount = await models.ReferenceRate.count({}, options); + + expect(afterCount - beforeCount).toBe(4); + }); + + it('should create entries for day1 and day2 from the feed, and not backfill day3', async function() { + const lastRate = await models.ReferenceRate.findOne({order: 'dated DESC'}, options); + if (!lastRate) return fail('No existing ReferenceRate data in DB'); + + const currency = await models.Currency.findById(lastRate.currencyFk, null, options); + if (!currency) return fail(`No currency for ID ${lastRate.currencyFk}`); + + const day1 = new Date(lastRate.dated); + day1.setDate(day1.getDate() + 1); + + const day2 = new Date(lastRate.dated); + day2.setDate(day2.getDate() + 2); + + const day3 = new Date(lastRate.dated); + day3.setDate(day3.getDate() + 3); + + const xml = ` + + + + + + + `; + + axios.get.and.returnValue(Promise.resolve({data: xml})); + + await models.InvoiceIn.exchangeRateUpdate(options); + + const day3Record = await models.ReferenceRate.findOne({ + where: {currencyFk: currency.id, dated: day3} + }, options); + + expect(day3Record).toBeNull(); + + const day1Record = await models.ReferenceRate.findOne({ + where: {currencyFk: currency.id, dated: day1} + }, options); + const day2Record = await models.ReferenceRate.findOne({ + where: {currencyFk: currency.id, dated: day2} + }, options); + + expect(day1Record.value).toBeCloseTo('1.1'); + expect(day2Record.value).toBeCloseTo('2.2'); }); }); diff --git a/modules/invoiceIn/back/methods/invoice-in/specs/filter.spec.js b/modules/invoiceIn/back/methods/invoice-in/specs/filter.spec.js index 48310b32a..beaa608e6 100644 --- a/modules/invoiceIn/back/methods/invoice-in/specs/filter.spec.js +++ b/modules/invoiceIn/back/methods/invoice-in/specs/filter.spec.js @@ -166,4 +166,21 @@ describe('InvoiceIn filter()', () => { throw e; } }); + + it('should return the invoice in matching companyFk', async() => { + const tx = await models.InvoiceIn.beginTransaction({}); + const options = {transaction: tx}; + + try { + const company = await models.Company.findOne({}, options); + const invoicesByCompany = await models.InvoiceIn.find({where: {companyFk: company.id}}, options); + const filteredInvoices = await models.InvoiceIn.filter({args: {companyFk: company.id}}, {}, options); + + expect(filteredInvoices.length).toEqual(invoicesByCompany.length); + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); }); diff --git a/modules/invoiceIn/back/methods/invoice-in/specs/invoiceIn.spec.js b/modules/invoiceIn/back/methods/invoice-in/specs/invoiceIn.spec.js new file mode 100644 index 000000000..a83aad3b2 --- /dev/null +++ b/modules/invoiceIn/back/methods/invoice-in/specs/invoiceIn.spec.js @@ -0,0 +1,63 @@ +const models = require('vn-loopback/server/server').models; + +describe('invoiceIn', () => { + let options; + let tx; + const invoiceId = 1; + const supplierId = 791; + const currencyId = 1; + const companyId = 442; + + beforeEach(async() => { + tx = await models.InvoiceIn.beginTransaction({}); + options = {transaction: tx}; + }); + + afterEach(async() => { + await tx.rollback(); + }); + + it('should allow insert for new instance', async() => { + const newInvoice = { + supplierFk: supplierId, + issued: Date.vnNew(), + operated: Date.vnNew(), + currencyFk: currencyId, + companyFk: companyId, + isBooked: false + }; + + const createdInvoice = await models.InvoiceIn.create(newInvoice, options); + + expect(createdInvoice).toBeDefined(); + expect(createdInvoice.id).toBeDefined(); + }); + + it('should throw an error if trying to update a booked invoice', async() => { + const invoice = await models.InvoiceIn.findById(invoiceId, null, options); + await invoice.updateAttribute('isBooked', true, options); + + let error; + try { + await invoice.updateAttribute('supplierFk', supplierId, options); + } catch (err) { + error = err; + } + + expect(error.message).toBe('InvoiceIn is already booked'); + }); + + it('should throw an error if trying to delete a booked invoice', async() => { + const invoice = await models.InvoiceIn.findById(invoiceId, null, options); + await invoice.updateAttribute('isBooked', true, options); + + let error; + try { + await models.InvoiceIn.deleteById(invoiceId, options); + } catch (err) { + error = err; + } + + expect(error.message).toBe('InvoiceIn is already booked'); + }); +}); diff --git a/modules/invoiceIn/back/methods/invoice-in/specs/invoiceInTax.spec.js b/modules/invoiceIn/back/methods/invoice-in/specs/invoiceInTax.spec.js new file mode 100644 index 000000000..e822189bd --- /dev/null +++ b/modules/invoiceIn/back/methods/invoice-in/specs/invoiceInTax.spec.js @@ -0,0 +1,74 @@ +const models = require('vn-loopback/server/server').models; + +describe('invoiceInTax', () => { + let options; + let tx; + const invoiceInId = 1; + const invoiceInTaxId = 1; + beforeEach(async() => { + tx = await models.InvoiceInTax.beginTransaction({}); + options = {transaction: tx}; + }); + + afterEach(async() => { + await tx.rollback(); + }); + + it('should throw an error if trying to save a tax from a booked invoice', async() => { + const invoiceIn = await models.InvoiceIn.findById(invoiceInId, null, options); + await invoiceIn.updateAttributes({isBooked: true}, options); + const invoiceInTax = await models.InvoiceInTax.findById(invoiceInTaxId, null, options); + let error; + try { + await invoiceInTax.updateAttribute('taxableBase', 100, options); + } catch (err) { + error = err; + } + + expect(error.message).toBe('InvoiceIn is already booked'); + }); + + it('should allow save if the invoice is not booked', async() => { + const invoiceIn = await models.InvoiceIn.findById(invoiceInId, null, options); + await invoiceIn.updateAttribute('isBooked', false, options); + + const invoiceInTax = await models.InvoiceInTax.findById(invoiceInTaxId, null, options); + await invoiceInTax.updateAttribute('taxableBase', 100, options); + + const updatedInvoiceInTax = await models.InvoiceInTax.findById(invoiceInTaxId, null, options); + + expect(updatedInvoiceInTax.taxableBase).toBe(100); + }); + + it('should throw an error if trying to delete a tax from a booked invoice', async() => { + const invoiceIn = await models.InvoiceIn.findById(invoiceInId, null, options); + await invoiceIn.updateAttribute('isBooked', true, options); + + let error; + try { + await models.InvoiceInTax.destroyById(invoiceInTaxId, options); + } catch (err) { + error = err; + } + + expect(error).toBeDefined(); + expect(error.message).toBe('InvoiceIn is already booked'); + }); + + it('should allow delete if the invoice is not booked', async() => { + const invoiceIn = await models.InvoiceIn.findById(invoiceInId, null, options); + await invoiceIn.updateAttribute('isBooked', false, options); + + let error; + try { + await models.InvoiceInTax.destroyById(invoiceInTaxId, options); + } catch (err) { + error = err; + } + + const deletedInvoiceInTax = await models.InvoiceInTax.findById(invoiceInTaxId, null, options); + + expect(error).toBeUndefined(); + expect(deletedInvoiceInTax).toBeNull(); + }); +}); diff --git a/modules/invoiceIn/back/methods/invoice-in/specs/updateInvoiceIn.spec.js b/modules/invoiceIn/back/methods/invoice-in/specs/updateInvoiceIn.spec.js new file mode 100644 index 000000000..773e2ac2f --- /dev/null +++ b/modules/invoiceIn/back/methods/invoice-in/specs/updateInvoiceIn.spec.js @@ -0,0 +1,59 @@ +const models = require('vn-loopback/server/server').models; + +const invoiceInId = 1; +const supplierId = 791; +describe('invoiceIn updateInvoiceIn()', () => { + const ctx = beforeAll.getCtx(); + let options; + let tx; + + beforeEach(async() => { + options = {transaction: tx}; + tx = await models.Sale.beginTransaction({}); + options.transaction = tx; + }); + + afterEach(async() => { + await tx.rollback(); + }); + + it('should update the invoice', async() => { + const invoiceBefore = await models.InvoiceIn.findById(invoiceInId, null, options); + await update(ctx, options); + const invoiceAfter = await models.InvoiceIn.findById(invoiceInId, null, options); + + expect(invoiceAfter.supplierFk).not.toBe(invoiceBefore.supplierFk); + expect(invoiceAfter.supplierFk).toBe(supplierId); + }); + + it('should not update the invoice if is booked', async() => { + let error; + try { + await models.InvoiceIn.toBook(ctx, invoiceInId, options); + await update(ctx, options); + } catch (e) { + error = e; + } + + expect(error.message).toBe('InvoiceIn is already booked'); + }); +}); + +async function update(ctx, opts) { + const supplierRef = 'mockRef'; + const currencyId = 1; + await models.InvoiceIn.updateInvoiceIn(ctx, + invoiceInId, + supplierId, + supplierRef, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + currencyId, + undefined, + undefined, + opts); +} diff --git a/modules/invoiceIn/back/methods/invoice-in/summary.js b/modules/invoiceIn/back/methods/invoice-in/summary.js index fe198b2b4..b3fd9ee97 100644 --- a/modules/invoiceIn/back/methods/invoice-in/summary.js +++ b/modules/invoiceIn/back/methods/invoice-in/summary.js @@ -37,7 +37,13 @@ module.exports = Self => { { relation: 'supplier', scope: { - fields: ['id', 'name'] + fields: ['id', 'name', 'isVies', 'countryFk'], + include: [{ + relation: 'country', + scope: { + fields: ['id', 'code'] + } + }] } }, { diff --git a/modules/invoiceIn/back/methods/invoice-in/toUnbook.js b/modules/invoiceIn/back/methods/invoice-in/toUnbook.js index a697e9ddc..c27354d73 100644 --- a/modules/invoiceIn/back/methods/invoice-in/toUnbook.js +++ b/modules/invoiceIn/back/methods/invoice-in/toUnbook.js @@ -52,7 +52,8 @@ module.exports = Self => { accountingEntries = await models.Xdiario.count({ASIEN: asien}, myOptions); await models.Xdiario.destroyAll({ASIEN: asien}, myOptions); - await Self.updateAll({id: invoiceInId}, {isBooked: false}, myOptions); + const invoiceIn = await Self.findById(invoiceInId, myOptions); + await invoiceIn.updateAttribute('isBooked', false, myOptions); } else { const linkedBookEntry = await models.Xdiario.findOne({ fields: ['ASIEN'], diff --git a/modules/invoiceIn/back/methods/invoice-in/updateInvoiceIn.js b/modules/invoiceIn/back/methods/invoice-in/updateInvoiceIn.js index 92a1ba8ee..2f1b4caca 100644 --- a/modules/invoiceIn/back/methods/invoice-in/updateInvoiceIn.js +++ b/modules/invoiceIn/back/methods/invoice-in/updateInvoiceIn.js @@ -82,7 +82,7 @@ module.exports = Self => { try { const invoiceIn = await Self.findById(id, null, myOptions); - invoiceIn.updateAttributes({supplierFk, + await invoiceIn.updateAttributes({supplierFk, supplierRef, issued, operated, @@ -94,6 +94,7 @@ module.exports = Self => { companyFk, withholdingSageFk }, myOptions); + if (tx) await tx.commit(); return invoiceIn; } catch (e) { diff --git a/modules/invoiceIn/back/models/invoice-in-correction.json b/modules/invoiceIn/back/models/invoice-in-correction.json index 52e16d420..d353f9e98 100644 --- a/modules/invoiceIn/back/models/invoice-in-correction.json +++ b/modules/invoiceIn/back/models/invoice-in-correction.json @@ -28,11 +28,10 @@ "model": "InvoiceCorrectionType", "foreignKey": "invoiceCorrectionTypeFk" }, - "siiTypeInvoiceOut": { + "siiTypeInvoiceIn": { "type": "belongsTo", - "model": "SiiTypeInvoiceOut", - "foreignKey": "siiTypeInvoiceOutFk" + "model": "SiiTypeInvoiceIn", + "foreignKey": "siiTypeInvoiceInFk" } - } } \ No newline at end of file diff --git a/modules/invoiceIn/back/models/invoice-in-tax.js b/modules/invoiceIn/back/models/invoice-in-tax.js new file mode 100644 index 000000000..ce33fe18f --- /dev/null +++ b/modules/invoiceIn/back/models/invoice-in-tax.js @@ -0,0 +1,18 @@ +const UserError = require('vn-loopback/util/user-error'); + +module.exports = Self => { + Self.observe('before save', async function(ctx) { + if (ctx.isNewInstance) return; + + const models = Self.app.models; + const invoiceIn = await models.InvoiceIn.findById(ctx.currentInstance.invoiceInFk, null, ctx.options); + if (invoiceIn.isBooked) throw new UserError('InvoiceIn is already booked'); + }); + + Self.observe('before delete', async function(ctx) { + const models = Self.app.models; + const invoiceInTax = await Self.findById(ctx.where.id, null, ctx.options); + const invoiceIn = await models.InvoiceIn.findById(invoiceInTax.invoiceInFk, null, ctx.options); + if (invoiceIn.isBooked) throw new UserError('InvoiceIn is already booked'); + }); +}; diff --git a/modules/invoiceIn/back/models/invoice-in-tax.json b/modules/invoiceIn/back/models/invoice-in-tax.json index 53b5548b6..256ee0553 100644 --- a/modules/invoiceIn/back/models/invoice-in-tax.json +++ b/modules/invoiceIn/back/models/invoice-in-tax.json @@ -22,12 +22,11 @@ "type": "number" }, "expenseFk": { - "type": "number" + "type": "string" }, "created": { "type": "date" } - }, "relations": { "invoiceIn": { @@ -51,4 +50,4 @@ "foreignKey": "transactionTypeSageFk" } } -} +} \ No newline at end of file diff --git a/modules/invoiceIn/back/models/invoice-in.js b/modules/invoiceIn/back/models/invoice-in.js index 1e69c0ef8..ca506b54d 100644 --- a/modules/invoiceIn/back/models/invoice-in.js +++ b/modules/invoiceIn/back/models/invoice-in.js @@ -19,4 +19,25 @@ module.exports = Self => { return new UserError(`This invoice has a linked vehicle.`); return err; }); + + Self.observe('before save', async function(ctx) { + if (ctx.isNewInstance) return; + + const changes = ctx.data || ctx.instance; + const orgData = ctx.currentInstance; + let isNotEditable = orgData.isBooked || (!orgData.isBooked && changes.isBooked); + + if (isNotEditable) { + for (const [key, value] of Object.entries(changes)) { + if (key !== 'isBooked' && value !== orgData[key]) + throw new UserError('InvoiceIn is already booked'); + } + } + }); + + Self.observe('before delete', async function(ctx) { + const invoiceIn = await Self.findById(ctx.where.id, null, ctx.options); + if (invoiceIn.isBooked) throw new UserError('InvoiceIn is already booked'); + }); }; + diff --git a/modules/invoiceOut/back/methods/invoiceOut/clientsToInvoice.js b/modules/invoiceOut/back/methods/invoiceOut/clientsToInvoice.js index 5526d214a..78fce348e 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/clientsToInvoice.js +++ b/modules/invoiceOut/back/methods/invoiceOut/clientsToInvoice.js @@ -1,3 +1,5 @@ +const UserError = require('vn-loopback/util/user-error'); + module.exports = Self => { Self.remoteMethodCtx('clientsToInvoice', { description: 'Get the clients to make global invoicing', @@ -47,7 +49,6 @@ module.exports = Self => { } try { - // Packaging liquidation const vIsAllInvoiceable = false; await Self.rawSql('CALL ticketPackaging_add(?, ?, ?, ?)', [ clientId, @@ -71,12 +72,10 @@ module.exports = Self => { AND t.shipped BETWEEN ? AND util.dayEnd(?) AND (t.clientFk = ? OR ? IS NULL ) AND t.companyFk = ? - AND c.hasToInvoice - AND c.isTaxDataChecked - AND c.isActive AND NOT t.isDeleted GROUP BY IF(c.hasToInvoiceByAddress, a.id, c.id) - HAVING SUM(t.totalWithVat) > 0;`; + HAVING SUM(t.totalWithVat) > 0 + ORDER BY c.id`; const addresses = await Self.rawSql(query, [ minShipped, diff --git a/modules/invoiceOut/back/methods/invoiceOut/filter.js b/modules/invoiceOut/back/methods/invoiceOut/filter.js index 764fdbb78..ab6782140 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/filter.js +++ b/modules/invoiceOut/back/methods/invoiceOut/filter.js @@ -79,6 +79,12 @@ module.exports = Self => { type: 'date', description: 'The due date filter', http: {source: 'query'} + }, + { + arg: 'customsAgentFk', + type: 'integer', + description: 'The customsAgent id', + http: {source: 'query'} } ], returns: { @@ -120,6 +126,7 @@ module.exports = Self => { case 'companyFk': case 'issued': case 'dued': + case 'customsAgentFk': param = `i.${param}`; return {[param]: value}; } @@ -139,11 +146,14 @@ module.exports = Self => { i.dued, i.clientFk, i.hasPdf, + i.customsAgentFk, c.socialName AS clientSocialName, - co.code AS companyCode + co.code AS companyCode, + ca.fiscalName AS customsAgentName FROM invoiceOut i LEFT JOIN client c ON c.id = i.clientFk - LEFT JOIN company co ON co.id = i.companyFk` + LEFT JOIN company co ON co.id = i.companyFk + LEFT JOIN customsAgent ca ON ca.id = i.customsAgentFk` ); stmt.merge(conn.makeSuffix(filter)); diff --git a/modules/invoiceOut/back/methods/invoiceOut/getInvoiceDate.js b/modules/invoiceOut/back/methods/invoiceOut/getInvoiceDate.js index dcc1fa6e8..493f19aa7 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/getInvoiceDate.js +++ b/modules/invoiceOut/back/methods/invoiceOut/getInvoiceDate.js @@ -7,7 +7,12 @@ module.exports = Self => { arg: 'companyFk', type: 'number', required: true - } + }, + { + arg: 'serialType', + type: 'string', + required: true + }, ], returns: { type: ['object'], @@ -19,16 +24,16 @@ module.exports = Self => { } }); - Self.getInvoiceDate = async companyFk => { + Self.getInvoiceDate = async(companyFk, serialType) => { const models = Self.app.models; const [invoiceDate] = await models.InvoiceOut.rawSql( `SELECT MAX(io.issued) issued FROM invoiceOut io JOIN invoiceOutSerial ios ON ios.code = io.serial - WHERE ios.type = 'global' - AND io.issued + WHERE ios.type = ? + AND io.issued AND io.companyFk = ?`, - [companyFk] + [serialType, companyFk] ); return invoiceDate; }; diff --git a/modules/invoiceOut/back/methods/invoiceOut/specs/clientsToInvoice.spec.js b/modules/invoiceOut/back/methods/invoiceOut/specs/clientsToInvoice.spec.js index 470690c5a..6e536f433 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/specs/clientsToInvoice.spec.js +++ b/modules/invoiceOut/back/methods/invoiceOut/specs/clientsToInvoice.spec.js @@ -1,14 +1,15 @@ const models = require('vn-loopback/server/server').models; +const LoopBackContext = require('loopback-context'); describe('InvoiceOut clientsToInvoice()', () => { const userId = 1; const clientId = 1101; const companyFk = 442; - const maxShipped = new Date(); + const maxShipped = Date.vnNew(); maxShipped.setMonth(11); maxShipped.setDate(31); maxShipped.setHours(23, 59, 59, 999); - const invoiceDate = new Date(); + const invoiceDate = Date.vnNew(); const activeCtx = { getLocale: () => { return 'en'; @@ -20,6 +21,21 @@ describe('InvoiceOut clientsToInvoice()', () => { headers: {origin: 'http://localhost'} }; const ctx = {req: activeCtx}; + let tx; + let options; + + beforeEach(async() => { + LoopBackContext.getCurrentContext = () => ({ + active: activeCtx, + }); + + tx = await models.InvoiceOut.beginTransaction({}); + options = {transaction: tx}; + }); + + afterEach(async() => { + await tx.rollback(); + }); it('should return a list of clients to invoice', async() => { spyOn(models.InvoiceOut, 'rawSql').and.callFake(query => { @@ -37,24 +53,14 @@ describe('InvoiceOut clientsToInvoice()', () => { } }); - const tx = await models.InvoiceOut.beginTransaction({}); - const options = {transaction: tx}; + const addresses = await models.InvoiceOut.clientsToInvoice( + ctx, clientId, invoiceDate, maxShipped, companyFk, options); - try { - const addresses = await models.InvoiceOut.clientsToInvoice( - ctx, clientId, invoiceDate, maxShipped, companyFk, options); - - expect(addresses.length).toBeGreaterThan(0); - expect(addresses[0].clientId).toBe(clientId); - expect(addresses[0].clientName).toBe('Test Client'); - expect(addresses[0].id).toBe(1); - expect(addresses[0].nickname).toBe('Address 1'); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } + expect(addresses.length).toBeGreaterThan(0); + expect(addresses[0].clientId).toBe(clientId); + expect(addresses[0].clientName).toBe('Test Client'); + expect(addresses[0].id).toBe(1); + expect(addresses[0].nickname).toBe('Address 1'); }); it('should handle errors and rollback transaction', async() => { @@ -62,14 +68,20 @@ describe('InvoiceOut clientsToInvoice()', () => { return Promise.reject(new Error('Test Error')); }); - const tx = await models.InvoiceOut.beginTransaction({}); - const options = {transaction: tx}; - try { await models.InvoiceOut.clientsToInvoice(ctx, clientId, invoiceDate, maxShipped, companyFk, options); } catch (e) { expect(e.message).toBe('Test Error'); - await tx.rollback(); } }); + + it('should return all list', async() => { + const minShipped = Date.vnNew(); + minShipped.setFullYear(maxShipped.getFullYear() - 1); + + const toInvoice = await models.InvoiceOut.clientsToInvoice( + ctx, null, invoiceDate, maxShipped, companyFk, options); + + expect(toInvoice).toBeDefined(); + }); }); diff --git a/modules/invoiceOut/back/methods/invoiceOut/specs/getInvoiceDate.spec.js b/modules/invoiceOut/back/methods/invoiceOut/specs/getInvoiceDate.spec.js new file mode 100644 index 000000000..830402250 --- /dev/null +++ b/modules/invoiceOut/back/methods/invoiceOut/specs/getInvoiceDate.spec.js @@ -0,0 +1,39 @@ +const models = require('vn-loopback/server/server').models; +const moment = require('moment'); + +describe('getInvoiceDate()', () => { + const companyFk = 442; + let tx; + let options; + + beforeEach(async() => { + tx = await models.InvoiceOut.beginTransaction({}); + options = {transaction: tx}; + }); + + afterEach(async() => { + await tx.rollback(); + }); + + it('should return a correct date for serialType "global"', async() => { + const serialType = 'global'; + const result = await models.InvoiceOut.getInvoiceDate(companyFk, serialType, options); + + expect(moment(result.issued).format('YYYY-MM-DD')).toEqual('2000-12-01'); + }); + + it('should return null for serialType "multiple"', async() => { + const serialType = 'multiple'; + const result = await models.InvoiceOut.getInvoiceDate(companyFk, serialType, options); + + expect(result.issued).toBeNull(); + }); + + it('should return correct date for serialType "quick"', async() => { + const serialType = 'quick'; + const result = await models.InvoiceOut.getInvoiceDate(companyFk, serialType, options); + + expect(moment(result.issued).format('YYYY-MM-DD')).toEqual('2001-01-01'); + }); +}); + diff --git a/modules/invoiceOut/back/model-config.json b/modules/invoiceOut/back/model-config.json index 9c7512429..710d824c3 100644 --- a/modules/invoiceOut/back/model-config.json +++ b/modules/invoiceOut/back/model-config.json @@ -43,5 +43,8 @@ }, "SiiTypeInvoiceOut": { "dataSource": "vn" + }, + "SiiTypeInvoiceIn": { + "dataSource": "vn" } -} +} \ No newline at end of file diff --git a/modules/invoiceOut/back/models/invoice-out.json b/modules/invoiceOut/back/models/invoice-out.json index 1ee36accb..2ad13fe3f 100644 --- a/modules/invoiceOut/back/models/invoice-out.json +++ b/modules/invoiceOut/back/models/invoice-out.json @@ -66,6 +66,11 @@ "model": "Ticket", "foreignKey": "refFk", "primaryKey": "ref" + }, + "customsAgentFk": { + "type": "belongsTo", + "model": "CustomsAgent", + "foreignKey": "customsAgentFk" } } } diff --git a/modules/invoiceOut/back/models/sii-type-invoice-in.json b/modules/invoiceOut/back/models/sii-type-invoice-in.json new file mode 100644 index 000000000..a191febb9 --- /dev/null +++ b/modules/invoiceOut/back/models/sii-type-invoice-in.json @@ -0,0 +1,22 @@ +{ + "name": "SiiTypeInvoiceIn", + "base": "VnModel", + "options": { + "mysql": { + "table": "siiTypeInvoiceIn" + } + }, + "properties": { + "id": { + "id": true, + "type": "number", + "description": "Identifier" + }, + "code": { + "type": "string" + }, + "description": { + "type": "string" + } + } +} \ No newline at end of file diff --git a/modules/invoiceOut/back/models/sii-type-invoice-out.json b/modules/invoiceOut/back/models/sii-type-invoice-out.json index 37fd39c38..89f01bd74 100644 --- a/modules/invoiceOut/back/models/sii-type-invoice-out.json +++ b/modules/invoiceOut/back/models/sii-type-invoice-out.json @@ -17,9 +17,6 @@ }, "description": { "type": "string" - }, - "code": { - "type": "string" } } -} +} \ No newline at end of file diff --git a/modules/item/back/methods/item/lastEntriesFilter.js b/modules/item/back/methods/item/lastEntriesFilter.js index 06c60162f..b038bb155 100644 --- a/modules/item/back/methods/item/lastEntriesFilter.js +++ b/modules/item/back/methods/item/lastEntriesFilter.js @@ -29,10 +29,12 @@ module.exports = Self => { Object.assign(myOptions, options); const stmt = new ParameterizedSQL( - `SELECT w.id AS warehouseFk, - w.name AS warehouse, - tr.landed, - b.id AS buyFk, + `SELECT i.id itemFk, + w.id warehouseFk, + w.name warehouse, + CAST(tr.landed AS CHAR) landed, + tr.landed landedDate, + b.id buyFk, b.entryFk, b.isIgnored, b.price2, @@ -47,15 +49,18 @@ module.exports = Self => { b.buyingValue + b.freightValue + b.comissionValue + - b.packageValue AS cost, + b.packageValue cost, b.buyingValue, b.freightValue, b.comissionValue, b.packageValue, b.packagingFk , - s.id AS supplierFk, - s.name AS supplier, - b.printedStickers + s.id supplierFk, + s.name supplier, + b.printedStickers, + c.inventoried, + ic.supplierFk inventorySupplierFk, + s.id = ic.supplierFk isInventorySupplier FROM itemType it RIGHT JOIN (entry e LEFT JOIN supplier s ON s.id = e.supplierFk @@ -66,9 +71,14 @@ module.exports = Self => { LEFT JOIN warehouse w ON w.id = tr.warehouseInFk LEFT JOIN origin o ON o.id = i.originFk ) ON it.id = i.typeFk - LEFT JOIN edi.ekt ek ON b.ektFk = ek.id` + LEFT JOIN edi.ekt ek ON b.ektFk = ek.id + JOIN config c + JOIN inventoryConfig ic` ); - stmt.merge(conn.makeSuffix(filter)); + + stmt.merge(conn.makeWhere(filter.where)); + stmt.merge('AND IF(s.id = ic.supplierFk, tr.landed = DATE(c.inventoried), TRUE)'); + stmt.merge(conn.makePagination(filter)); return conn.executeStmt(stmt, myOptions); }; diff --git a/modules/item/back/methods/item/specs/lastEntriesFilter.spec.js b/modules/item/back/methods/item/specs/lastEntriesFilter.spec.js index d4429e158..b2bfdf59c 100644 --- a/modules/item/back/methods/item/specs/lastEntriesFilter.spec.js +++ b/modules/item/back/methods/item/specs/lastEntriesFilter.spec.js @@ -1,16 +1,22 @@ const {models} = require('vn-loopback/server/server'); +const itemFk = 1; + +const today = Date.vnNew(); +today.setHours(23, 59, 59, 999); + +const twoMonthsAgo = Date.vnNew(); +twoMonthsAgo.setHours(0, 0, 0, 0); +twoMonthsAgo.setMonth(twoMonthsAgo.getMonth() - 2, 1); describe('item lastEntriesFilter()', () => { it('should return two entry for the given item', async() => { const minDate = Date.vnNew(); minDate.setHours(0, 0, 0, 0); - const maxDate = Date.vnNew(); - maxDate.setHours(23, 59, 59, 59); const tx = await models.Item.beginTransaction({}); const options = {transaction: tx}; try { - const filter = {where: {itemFk: 1, landed: {between: [minDate, maxDate]}}}; + const filter = {where: {itemFk, landed: {between: [minDate, today]}}}; const result = await models.Item.lastEntriesFilter(filter, options); expect(result.length).toEqual(2); @@ -23,22 +29,14 @@ describe('item lastEntriesFilter()', () => { }); it('should return six entries for the given item', async() => { - const minDate = Date.vnNew(); - minDate.setHours(0, 0, 0, 0); - minDate.setMonth(minDate.getMonth() - 2, 1); - - const maxDate = Date.vnNew(); - maxDate.setHours(23, 59, 59, 59); - const tx = await models.Item.beginTransaction({}); const options = {transaction: tx}; try { - const itemFk = 1; - const filter = {where: {itemFk, landed: {between: [minDate, maxDate]}}}; + const filter = {where: {itemFk, landed: {between: [twoMonthsAgo, today]}}}; const result = await models.Item.lastEntriesFilter(filter, options); - const minDateUtc = new Date(minDate).getTime(); - const maxDateUtc = new Date(maxDate).getTime(); + const twoMonthsAgoUtc = twoMonthsAgo.getTime(); + const todayUtc = today.getTime(); const resultMatch = ( await Promise.all( @@ -50,8 +48,8 @@ describe('item lastEntriesFilter()', () => { }); const isItemFkValid = itemRecord?.id === itemFk; - const landedDate = new Date(item.landed).getTime(); - const isLandedValid = landedDate >= minDateUtc && landedDate <= maxDateUtc; + const landedDate = Date.vnNew(item.landed).getTime(); + const isLandedValid = landedDate >= twoMonthsAgoUtc && landedDate <= todayUtc; return isItemFkValid && isLandedValid; }) @@ -66,4 +64,31 @@ describe('item lastEntriesFilter()', () => { throw e; } }); + + it('should return just the inventoried inventory', async() => { + const tx = await models.Item.beginTransaction({}); + const options = {transaction: tx}; + + try { + const filter = {where: {itemFk, landed: {between: [twoMonthsAgo, today]}}}; + const result = await models.Item.lastEntriesFilter(filter, options); + + const {supplierFk} = await models.InventoryConfig.findOne(options); + const {inventoried} = await models.Config.findOne(options); + + let hasInventoriedDate = false; + result.forEach(entry => { + if (entry.supplierFk === supplierFk && + entry.landedDate.getTime() === inventoried.getTime() + )hasInventoriedDate = true; + }); + + expect(hasInventoriedDate).toEqual(true); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); }); diff --git a/modules/item/back/models/item.json b/modules/item/back/models/item.json index eda56e938..159883455 100644 --- a/modules/item/back/models/item.json +++ b/modules/item/back/models/item.json @@ -154,6 +154,9 @@ }, "photoMotivation": { "type": "string" + }, + "isCustomInspectionRequired": { + "type": "boolean" } }, "relations": { @@ -222,4 +225,4 @@ } } } -} \ 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 95713f9fb..4947edeaf 100644 --- a/modules/monitor/back/methods/sales-monitor/salesFilter.js +++ b/modules/monitor/back/methods/sales-monitor/salesFilter.js @@ -98,6 +98,11 @@ module.exports = Self => { arg: 'countryFk', type: 'number', description: 'The country id filter' + }, + { + arg: 'payMethod', + type: 'string', + description: 'The payment method filter' } ], returns: { @@ -118,25 +123,13 @@ module.exports = Self => { date.setHours(0, 0, 0, 0); const args = ctx.args; const myOptions = {}; + let myTeamIds = []; if (typeof options == 'object') Object.assign(myOptions, options); - // Apply filter by team - const teamMembersId = []; - if (args.myTeam != null) { - const worker = await models.Worker.findById(userId, { - include: { - relation: 'collegues' - } - }, myOptions); - const collegues = worker.collegues() || []; - for (let collegue of collegues) - teamMembersId.push(collegue.collegueFk); - - if (teamMembersId.length == 0) - teamMembersId.push(userId); - } + if (args.myTeam != null) + myTeamIds = await models.Worker.myTeam(userId); if (ctx.args && args.to) { const dateTo = args.to; @@ -158,13 +151,15 @@ module.exports = Self => { case 'mine': case 'myTeam': if (value) - return {'c.salesPersonFk': {inq: teamMembersId}}; + return {'c.salesPersonFk': {inq: myTeamIds}}; else - return {'c.salesPersonFk': {nin: teamMembersId}}; + return {'c.salesPersonFk': {nin: myTeamIds}}; case 'id': case 'clientFk': param = `t.${param}`; return {[param]: value}; + case 'payMethod': + return {'c.payMethodFk': value}; } }); @@ -205,6 +200,8 @@ module.exports = Self => { u.name userName, c.salesPersonFk, c.credit, + c.payMethodFk payMethodFk, + pm.id payMethodId, pm.name payMethod, z.hour zoneLanding, z.name zoneName, diff --git a/modules/order/back/methods/order/filter.js b/modules/order/back/methods/order/filter.js index 2aeb1aac5..f24d9b225 100644 --- a/modules/order/back/methods/order/filter.js +++ b/modules/order/back/methods/order/filter.js @@ -80,29 +80,15 @@ module.exports = Self => { const conn = Self.dataSource.connector; const myOptions = {}; const userId = ctx.req.accessToken.userId; + let myTeamIds = []; if (typeof options == 'object') Object.assign(myOptions, options); const args = ctx.args; - // Apply filter by team - const teamMembersId = []; - if (args.myTeam != null) { - const worker = await models.Worker.findById(userId, { - include: { - relation: 'collegues' - } - }, myOptions); - const collegues = worker.collegues() || []; - for (let collegue of collegues) - teamMembersId.push(collegue.collegueFk); - if (teamMembersId.length == 0) - teamMembersId.push(userId); - } - - if (args?.myTeam) - args.teamIds = teamIds; + if (args.myTeam != null) + myTeamIds = await models.Worker.myTeam(userId); if (args?.to) args.to.setHours(23, 59, 0, 0); @@ -133,9 +119,9 @@ module.exports = Self => { return {'o.confirmed': value ? 1 : 0}; case 'myTeam': if (value) - return {'c.salesPersonFk': {inq: teamMembersId}}; + return {'c.salesPersonFk': {inq: myTeamIds}}; else - return {'c.salesPersonFk': {nin: teamMembersId}}; + return {'c.salesPersonFk': {nin: myTeamIds}}; case 'showEmpty': return {'o.total': {neq: value}}; case 'id': diff --git a/modules/route/back/methods/route/driverRouteEmail.js b/modules/route/back/methods/route/driverRouteEmail.js index bbac2b0e8..78069683d 100644 --- a/modules/route/back/methods/route/driverRouteEmail.js +++ b/modules/route/back/methods/route/driverRouteEmail.js @@ -8,7 +8,7 @@ module.exports = Self => { arg: 'id', type: 'number', required: true, - description: 'The client id', + description: 'The route id', http: {source: 'path'} }, { arg: 'replyTo', @@ -31,26 +31,13 @@ module.exports = Self => { }); Self.driverRouteEmail = async(ctx, id) => { - const models = Self.app.models; - const {workerFk, agencyMode} = await Self.findById(id, { - fields: ['workerFk', 'agencyModeFk'], + const {agencyMode} = await Self.findById(id, { + fields: ['agencyModeFk'], include: {relation: 'agencyMode'} }); const {reportMail} = agencyMode(); - let user; - let account; - - if (workerFk) { - user = await models.VnUser.findById(workerFk, { - fields: ['active', 'id'], - include: {relation: 'emailUser'} - }); - account = await models.Account.findById(workerFk); - } - - if (user?.active && account) ctx.args.recipient = user.emailUser().email; - else ctx.args.recipient = reportMail; + ctx.args.recipient = reportMail; if (!ctx.args.recipient) throw new UserError('An email is necessary'); return Self.sendTemplate(ctx, 'driver-route'); }; diff --git a/modules/route/back/methods/route/optimizePriority.js b/modules/route/back/methods/route/optimizePriority.js new file mode 100644 index 000000000..56db4ffb5 --- /dev/null +++ b/modules/route/back/methods/route/optimizePriority.js @@ -0,0 +1,122 @@ +const UserError = require('vn-loopback/util/user-error'); + +module.exports = Self => { + Self.remoteMethod('optimizePriority', { + description: 'Updates the ticket priority of tickets without priority', + accepts: { + arg: 'id', + type: 'number', + required: true, + description: 'Route id', + http: {source: 'path'} + }, + returns: { + type: 'object', + root: true + }, + http: { + path: '/:id/optimizePriority', + verb: 'POST' + } + }); + + Self.optimizePriority = async(id, options) => { + const models = Self.app.models; + const myOptions = {}; + let tx; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + const tickets = await models.Ticket.find({ + where: {routeFk: id} + }, myOptions); + + let ticketAddress = []; + for (const ticket of tickets) { + ticketAddress.push({ + ticketId: ticket.id, + addressId: ticket.addressFk, + zoneId: ticket.zoneFk, + priority: ticket.priority + }); + } + + // Igualamos los priority del mismo addressId + const addressPriorityMap = ticketAddress.reduce((acc, {addressId, priority}) => { + if (priority !== null) { + acc[addressId] = acc[addressId] === undefined + ? priority + : Math.max(acc[addressId], priority); + } + return acc; + }); + ticketAddress.forEach(item => { + const maxPriority = addressPriorityMap[item.addressId]; + if (maxPriority) item.priority = maxPriority; + }); + + // Añadimos las direcciones a optimizar + let addressIds = []; + ticketAddress.forEach(h => { + if (!addressIds.includes(h.addressId) && !h.priority) + addressIds.push(h.addressId); + }); + if (!addressIds.length) throw new UserError('All tickets have a route order'); + + // Obtenemos el zoneId más frecuente + const zoneFrequency = ticketAddress.reduce((acc, {zoneId}) => { + if (zoneId != null) acc[zoneId] = (acc[zoneId] || 0) + 1; + return acc; + }, {}); + const [mostFrequentZoneId] = Object.entries(zoneFrequency) + .reduce((maxEntry, entry) => entry[1] > maxEntry[1] ? entry : maxEntry, [null, 0]); + + // Obtenemos los address inicio y fin + const maxPosition = Math.max(...ticketAddress.map(g => g.priority)); + let firstAddress = (await models.Zone.findById(mostFrequentZoneId, myOptions))?.addressFk + || (await models.ZoneConfig.findOne())?.defaultAddressFk; + const lastAddress = firstAddress; + if (maxPosition) firstAddress = ticketAddress.find(g => g.priority === maxPosition)?.addressId; + + // Revisamos las coincidencias y actualizamos la prioridad en el array + const addressPositions = await models.OsrmConfig.optimize(addressIds, firstAddress, lastAddress, myOptions); + await Promise.all(ticketAddress.map(async i => { + const foundPosition = addressPositions.find(item => item.addressId === i.addressId); + if (foundPosition) i.priority = foundPosition.position + (maxPosition + 1); + })); + + // Suavizado de prioridad para que no hayan escalones + const allPriorities = ticketAddress + .map(item => item.priority) + .filter(p => p !== null); + const uniquePriorities = [...new Set(allPriorities)].sort((a, b) => a - b); + const priorityMap = {}; + uniquePriorities.forEach((p, index) => { + priorityMap[p] = index + 1; + }); + ticketAddress.forEach(item => { + if (item.priority !== null) item.priority = priorityMap[item.priority]; + }); + + if (!myOptions.transaction) { + tx = await Self.beginTransaction({}); + myOptions.transaction = tx; + } + + // Realizamos el update en la base de datos + try { + await Promise.all(ticketAddress.map(async y => { + if (y.priority) { + const ticket = await models.Ticket.findById(y.ticketId); + await ticket.updateAttribute('priority', y.priority, myOptions); + } + })); + if (tx) await tx.commit(); + return; + } catch (err) { + if (tx) await tx.rollback(); + throw err; + } + }; +}; diff --git a/modules/route/back/methods/route/specs/optimizePriority.spec.js b/modules/route/back/methods/route/specs/optimizePriority.spec.js new file mode 100644 index 000000000..c1c2dc45e --- /dev/null +++ b/modules/route/back/methods/route/specs/optimizePriority.spec.js @@ -0,0 +1,36 @@ +const models = require('vn-loopback/server/server').models; +const routeId = 1; + +describe('route optimizePriority())', function() { + it('should execute without throwing errors', async function() { + const tx = await models.Route.beginTransaction({}); + let error; + try { + const options = {transaction: tx}; + await models.Ticket.updateAll( + {routeFk: routeId}, + {priority: null}, + options + ); + await models.Route.optimizePriority(routeId, options); + await tx.rollback(); + } catch (e) { + error = e; + await tx.rollback(); + } + + expect(error).toBeUndefined(); + }); + + it('should execute with error', async function() { + let error; + try { + await models.Route.optimizePriority(routeId); + } catch (e) { + error = e; + } + + expect(error).toBeDefined(); + expect(error.message).toBe('All tickets have a route order'); + }); +}); diff --git a/modules/route/back/models/route.js b/modules/route/back/models/route.js index cd8685cec..f73ff3e51 100644 --- a/modules/route/back/models/route.js +++ b/modules/route/back/models/route.js @@ -16,4 +16,5 @@ module.exports = Self => { require('../methods/route/downloadZip')(Self); require('../methods/route/getExpeditionSummary')(Self); require('../methods/route/getByWorker')(Self); + require('../methods/route/optimizePriority')(Self); }; diff --git a/modules/supplier/back/methods/supplier/newSupplier.js b/modules/supplier/back/methods/supplier/newSupplier.js index 3cca4195f..eb941ed69 100644 --- a/modules/supplier/back/methods/supplier/newSupplier.js +++ b/modules/supplier/back/methods/supplier/newSupplier.js @@ -28,6 +28,7 @@ module.exports = Self => { delete args.ctx; if (!args.name) throw new UserError('The social name cannot be empty'); + if (args.name !== args.name.toUpperCase()) throw new UserError('Social name should be uppercase'); const data = {...args, ...{nickname: args.name}}; const supplier = await models.Supplier.create(data, myOptions); diff --git a/modules/ticket/back/methods/expedition/filter.js b/modules/ticket/back/methods/expedition/filter.js index bd2012668..801d00a9b 100644 --- a/modules/ticket/back/methods/expedition/filter.js +++ b/modules/ticket/back/methods/expedition/filter.js @@ -50,7 +50,8 @@ module.exports = Self => { su.name scannerUserName, es.scanned, est.description state, - de.longName + de.longName, + de.itemFk FROM vn.expedition e LEFT JOIN vn.expeditionStateType est ON est.id = e.stateTypeFk INNER JOIN vn.item i1 ON i1.id = e.freightItemFk diff --git a/modules/ticket/back/methods/ticket-request/confirm.js b/modules/ticket/back/methods/ticket-request/confirm.js index 7c17d0010..45ee287de 100644 --- a/modules/ticket/back/methods/ticket-request/confirm.js +++ b/modules/ticket/back/methods/ticket-request/confirm.js @@ -54,9 +54,17 @@ module.exports = Self => { throw new UserError(`That item doesn't exists`); const request = await models.TicketRequest.findById(ctx.args.id, { - include: {relation: 'ticket'} + include: { + relation: 'ticket', + scope: { + include: { + relation: 'client', + scope: { + fields: ['id', 'name', 'salesPersonFk'] + } + } + }} }, myOptions); - const itemStock = await models.Item.getVisibleAvailable( ctx.args.itemFk, request.ticket().warehouseFk, @@ -89,19 +97,19 @@ module.exports = Self => { const query = `CALL vn.sale_calculateComponent(?, NULL)`; await Self.rawSql(query, [sale.id], myOptions); - const url = await Self.app.models.Url.getUrl(); - const requesterId = request.requesterFk; - - const message = $t('Bought units from buy request', { - quantity: sale.quantity, - concept: sale.concept, - itemId: sale.itemFk, - ticketId: sale.ticketFk, - url: `${url}ticket/${sale.ticketFk}/summary`, - urlItem: `${url}item/${sale.itemFk}/summary` - }); - await models.Chat.sendCheckingPresence(ctx, requesterId, message, myOptions); - + const salesPerson = request.ticket().client().salesPersonFk; + if (salesPerson) { + const url = await Self.app.models.Url.getUrl(); + const message = $t('Bought units from buy request', { + quantity: sale.quantity, + concept: sale.concept, + itemId: sale.itemFk, + ticketId: sale.ticketFk, + url: `${url}ticket/${sale.ticketFk}/summary`, + urlItem: `${url}item/${sale.itemFk}/summary` + }); + await models.Chat.sendCheckingPresence(ctx, salesPerson, message, myOptions); + } if (tx) await tx.commit(); return sale; diff --git a/modules/ticket/back/methods/ticket-request/deny.js b/modules/ticket/back/methods/ticket-request/deny.js index 44f1e48a1..26e6f63ff 100644 --- a/modules/ticket/back/methods/ticket-request/deny.js +++ b/modules/ticket/back/methods/ticket-request/deny.js @@ -1,18 +1,22 @@ +const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { Self.remoteMethodCtx('deny', { - description: 'sets a ticket request to denied and returns the changes', + description: 'Sets a ticket request to denied and returns the changes', accessType: 'WRITE', - accepts: [{ - arg: 'id', - type: 'number', - required: true, - description: 'The request ID', - }, { - arg: 'observation', - type: 'String', - required: true, - description: 'The request observation', - }], + accepts: [ + { + arg: 'id', + type: 'number', + required: true, + description: 'The request ID', + }, + { + arg: 'observation', + type: 'string', + required: true, + description: 'The request observation', + } + ], returns: { type: 'number', root: true @@ -29,7 +33,7 @@ module.exports = Self => { const myOptions = {}; let tx; - if (typeof options == 'object') + if (typeof options === 'object') Object.assign(myOptions, options); if (!myOptions.transaction) { @@ -39,7 +43,7 @@ module.exports = Self => { try { const userId = ctx.req.accessToken.userId; - const worker = await Self.app.models.Worker.findOne({where: {id: userId}}, myOptions); + const worker = await models.Worker.findById(userId, {fields: ['id']}, myOptions); const params = { isOk: false, @@ -47,19 +51,32 @@ module.exports = Self => { response: ctx.args.observation, }; - const request = await Self.app.models.TicketRequest.findById(ctx.args.id, null, myOptions); - await request.updateAttributes(params, myOptions); + const request = await models.TicketRequest.findById(ctx.args.id, { + include: { + relation: 'ticket', + scope: { + include: { + relation: 'client', + scope: { + fields: ['id', 'name', 'salesPersonFk'] + } + } + } + } + }, myOptions); - const url = await Self.app.models.Url.getUrl(); - const requesterId = request.requesterFk; + const salesPerson = request.ticket().client().salesPersonFk; + if (salesPerson) { + const url = await models.Url.getUrl(); + const message = $t('Deny buy request', { + ticketId: request.ticketFk, + url: `${url}ticket/${request.ticketFk}/request/index`, + observation: params.response + }); - const message = $t('Deny buy request', { - ticketId: request.ticketFk, - url: `${url}ticket/${request.ticketFk}/request/index`, - observation: params.response - }); - - await models.Chat.sendCheckingPresence(ctx, requesterId, message, myOptions); + await models.Chat.sendCheckingPresence(ctx, salesPerson, message, myOptions); + await request.updateAttributes(params, myOptions); + } if (tx) await tx.commit(); diff --git a/modules/ticket/back/methods/ticket-request/filter.js b/modules/ticket/back/methods/ticket-request/filter.js index c2edcae81..1318c1ab3 100644 --- a/modules/ticket/back/methods/ticket-request/filter.js +++ b/modules/ticket/back/methods/ticket-request/filter.js @@ -87,6 +87,7 @@ module.exports = Self => { const myOptions = {}; const models = Self.app.models; const args = ctx.args; + let myTeamIds = []; if (typeof options == 'object') Object.assign(myOptions, options); @@ -94,20 +95,8 @@ module.exports = Self => { if (ctx.args.mine) ctx.args.attenderFk = userId; - const teamMembersId = []; - if (args.myTeam != null) { - const worker = await models.Worker.findById(userId, { - include: { - relation: 'collegues' - } - }, myOptions); - const collegues = worker.collegues() || []; - for (let collegue of collegues) - teamMembersId.push(collegue.collegueFk); - - if (teamMembersId.length == 0) - teamMembersId.push(userId); - } + if (args.myTeam != null) + myTeamIds = await models.Worker.myTeam(userId); const today = Date.vnNew(); const future = Date.vnNew(); @@ -145,9 +134,9 @@ module.exports = Self => { return {'c.salesPersonFk': value}; case 'myTeam': if (value) - return {'tr.requesterFk': {inq: teamMembersId}}; + return {'tr.requesterFk': {inq: myTeamIds}}; else - return {'tr.requesterFk': {nin: teamMembersId}}; + return {'tr.requesterFk': {nin: myTeamIds}}; case 'daysOnward': today.setHours(0, 0, 0, 0); future.setDate(today.getDate() + value); diff --git a/modules/ticket/back/methods/ticket-request/getItemTypeWorker.js b/modules/ticket/back/methods/ticket-request/getItemTypeWorker.js index f160cfaac..2f2a85abb 100644 --- a/modules/ticket/back/methods/ticket-request/getItemTypeWorker.js +++ b/modules/ticket/back/methods/ticket-request/getItemTypeWorker.js @@ -30,7 +30,7 @@ module.exports = Self => { Object.assign(myOptions, options); const query = - `SELECT DISTINCT u.id, u.nickname + `SELECT DISTINCT u.id, u.nickname, w.firstName, w.lastName FROM itemType it JOIN worker w ON w.id = it.workerFk JOIN account.user u ON u.id = w.id`; diff --git a/modules/ticket/back/methods/ticket/filter.js b/modules/ticket/back/methods/ticket/filter.js index c61223470..f125ac586 100644 --- a/modules/ticket/back/methods/ticket/filter.js +++ b/modules/ticket/back/methods/ticket/filter.js @@ -142,28 +142,14 @@ module.exports = Self => { date.setHours(0, 0, 0, 0); const models = Self.app.models; const args = ctx.args; - + let myTeamIds = []; const myOptions = {}; if (typeof options == 'object') Object.assign(myOptions, options); - // Apply filter by team - const teamMembersId = []; - if (args.myTeam != null) { - const worker = await models.Worker.findById(userId, { - include: { - relation: 'collegues' - } - }, myOptions); - - const collegues = worker.collegues() || []; - for (let collegue of collegues) - teamMembersId.push(collegue.collegueFk); - - if (teamMembersId.length == 0) - teamMembersId.push(userId); - } + if (args.myTeam != null) + myTeamIds = await models.Worker.myTeam(userId); if (ctx.args && args.to) { const dateTo = args.to; @@ -195,9 +181,9 @@ module.exports = Self => { case 'mine': case 'myTeam': if (value) - return {'c.salesPersonFk': {inq: teamMembersId}}; + return {'c.salesPersonFk': {inq: myTeamIds}}; else - return {'c.salesPersonFk': {nin: teamMembersId}}; + return {'c.salesPersonFk': {nin: myTeamIds}}; case 'alertLevel': return {'ts.alertLevel': value}; diff --git a/modules/ticket/back/methods/ticket/getTicketsAdvance.js b/modules/ticket/back/methods/ticket/getTicketsAdvance.js index 41f3ee79a..58d46173c 100644 --- a/modules/ticket/back/methods/ticket/getTicketsAdvance.js +++ b/modules/ticket/back/methods/ticket/getTicketsAdvance.js @@ -55,6 +55,11 @@ module.exports = Self => { type: 'number', description: 'Department identifier' }, + { + arg: 'onlyWithDestination', + type: 'Boolean', + description: 'True when only tickets with destination are returned' + }, { arg: 'filter', type: 'object', @@ -103,6 +108,8 @@ module.exports = Self => { return {'f.isFullMovable': value}; case 'departmentFk': return {'f.departmentFk': value}; + case 'onlyWithDestination': + return {'f.id': value ? {neq: null} : null}; } }); diff --git a/modules/ticket/back/methods/ticket/merge.js b/modules/ticket/back/methods/ticket/merge.js index 1106cef06..6922ad170 100644 --- a/modules/ticket/back/methods/ticket/merge.js +++ b/modules/ticket/back/methods/ticket/merge.js @@ -40,21 +40,23 @@ module.exports = Self => { try { for (let ticket of tickets) { - const originFullPath = `${url}ticket/${ticket.originId}/summary`; - const destinationFullPath = `${url}ticket/${ticket.destinationId}/summary`; - const message = $t('Ticket merged', { - originDated: dateUtil.toString(new Date(ticket.originShipped)), - destinationDated: dateUtil.toString(new Date(ticket.destinationShipped)), - originId: ticket.originId, - destinationId: ticket.destinationId, - originFullPath, - destinationFullPath - }); if (!ticket.originId || !ticket.destinationId) continue; await models.Sale.updateAll({ticketFk: ticket.originId}, {ticketFk: ticket.destinationId}, myOptions); - if (await models.Ticket.setDeleted(ctx, ticket.originId, myOptions)) - await models.Chat.sendCheckingPresence(ctx, ticket.workerFk, message); + if (await models.Ticket.setDeleted(ctx, ticket.originId, myOptions)) { + if (!ticket.salesPersonFk) continue; + const originFullPath = `${url}ticket/${ticket.originId}/summary`; + const destinationFullPath = `${url}ticket/${ticket.destinationId}/summary`; + const message = $t('Ticket merged', { + originDated: dateUtil.toString(new Date(ticket.originShipped)), + destinationDated: dateUtil.toString(new Date(ticket.destinationShipped)), + originId: ticket.originId, + destinationId: ticket.destinationId, + originFullPath, + destinationFullPath + }); + await models.Chat.sendCheckingPresence(ctx, ticket.salesPersonFk, message); + } } if (tx) await tx.commit(); diff --git a/modules/ticket/back/methods/ticket/priceDifference.js b/modules/ticket/back/methods/ticket/priceDifference.js index 7db03e268..7e4fe8283 100644 --- a/modules/ticket/back/methods/ticket/priceDifference.js +++ b/modules/ticket/back/methods/ticket/priceDifference.js @@ -108,7 +108,10 @@ module.exports = Self => { // Get items movable const ticketOrigin = await models.Ticket.findById(args.id, null, myOptions); - const differenceShipped = ticketOrigin.shipped.getTime() > args.shipped.getTime(); + let shipped = ticketOrigin.shipped ?? ticketOrigin.updated; + + const differenceShipped = shipped.getTime() > args.shipped.getTime(); + const differenceWarehouse = ticketOrigin.warehouseFk != args.warehouseId; salesObj.haveDifferences = differenceShipped || differenceWarehouse; diff --git a/modules/ticket/back/methods/ticket/saveSign.js b/modules/ticket/back/methods/ticket/saveSign.js index ac2a7bc66..f99311c39 100644 --- a/modules/ticket/back/methods/ticket/saveSign.js +++ b/modules/ticket/back/methods/ticket/saveSign.js @@ -28,7 +28,6 @@ module.exports = Self => { verb: 'POST' } }); - Self.saveSign = async(ctx, tickets, location, signedTime, options) => { const models = Self.app.models; const myOptions = {userId: ctx.req.accessToken.userId}; @@ -111,6 +110,12 @@ module.exports = Self => { scope: { fields: ['id'] } + }, + { + relation: 'zone', + scope: { + fields: ['id', 'zoneFk,', 'name'] + } }] }, myOptions); @@ -151,6 +156,28 @@ module.exports = Self => { await Self.rawSql(`CALL vn.ticket_setState(?, ?)`, [ticketId, stateCode], myOptions); + if (stateCode == 'DELIVERED' && ticket.priority) { + const orderState = await models.State.findOne({ + where: {code: 'DELIVERED'}, + fields: ['id'] + }, myOptions); + + const ticketIncorrect = await Self.rawSql(` + SELECT t.id + FROM ticket t + JOIN ticketState ts ON ts.ticketFk = t.id + JOIN state s ON s.code = ts.code + WHERE t.routeFk = ? + AND s.\`order\` < ? + AND priority <(SELECT t.priority + FROM ticket t + WHERE t.id = ?)` + , [ticket.routeFk, orderState.id, ticket.id], myOptions); + + if (ticketIncorrect?.length > 0) + await sendMail(ctx, ticket.routeFk, ticket.id, ticket.zone().name); + } + if (ticket?.address()?.province()?.country()?.code != 'ES' && ticket.$cmrFk) { await models.Ticket.saveCmr(ctx, [ticketId], myOptions); externalTickets.push(ticketId); @@ -163,4 +190,25 @@ module.exports = Self => { } await models.Ticket.sendCmrEmail(ctx, externalTickets); }; + + async function sendMail(ctx, route, ticket, zoneName) { + const $t = ctx.req.__; + const url = await Self.app.models.Url.getUrl(); + const sendTo = 'repartos@verdnatura.es'; + const fullUrl = `${url}route/${route}/summary`; + const emailSubject = $t('Incorrect delivery order alert on route', { + route, + zone: zoneName + }); + const emailBody = $t('Ticket has been delivered out of order', { + ticket, + fullUrl + }); + + await Self.app.models.Mail.create({ + receiver: sendTo, + subject: emailSubject, + body: emailBody + }); + } }; diff --git a/modules/ticket/back/methods/ticket/specs/getTicketsAdvance.spec.js b/modules/ticket/back/methods/ticket/specs/getTicketsAdvance.spec.js index a941013cd..157cdb1ff 100644 --- a/modules/ticket/back/methods/ticket/specs/getTicketsAdvance.spec.js +++ b/modules/ticket/back/methods/ticket/specs/getTicketsAdvance.spec.js @@ -8,6 +8,7 @@ describe('TicketFuture getTicketsAdvance()', () => { tomorrow.setDate(today.getDate() + 1); const salesDeptId = 43; const spain1DeptId = 95; + const warehouseId = 1; beforeAll.mockLoopBackContext(); it('should return the tickets passing the required data', async() => { @@ -19,7 +20,7 @@ describe('TicketFuture getTicketsAdvance()', () => { const args = { dateFuture: tomorrow, dateToAdvance: today, - warehouseFk: 1, + warehouseFk: warehouseId, }; ctx.args = args; @@ -42,7 +43,7 @@ describe('TicketFuture getTicketsAdvance()', () => { const args = { dateFuture: tomorrow, dateToAdvance: today, - warehouseFk: 1, + warehouseFk: warehouseId, isFullMovable: true }; @@ -67,7 +68,7 @@ describe('TicketFuture getTicketsAdvance()', () => { const args = { dateFuture: tomorrow, dateToAdvance: today, - warehouseFk: 1, + warehouseFk: warehouseId, isFullMovable: false }; @@ -92,7 +93,7 @@ describe('TicketFuture getTicketsAdvance()', () => { const args = { dateFuture: tomorrow, dateToAdvance: today, - warehouseFk: 1, + warehouseFk: warehouseId, ipt: 'V' }; @@ -117,7 +118,7 @@ describe('TicketFuture getTicketsAdvance()', () => { const args = { dateFuture: tomorrow, dateToAdvance: today, - warehouseFk: 1, + warehouseFk: warehouseId, tfIpt: 'V' }; @@ -141,7 +142,7 @@ describe('TicketFuture getTicketsAdvance()', () => { ctx.args = { dateFuture: tomorrow, dateToAdvance: today, - warehouseFk: 1, + warehouseFk: warehouseId, }; await models.Ticket.updateAll({id: {inq: [12, 31]}}, {clientFk: 1}, options); @@ -167,4 +168,56 @@ describe('TicketFuture getTicketsAdvance()', () => { throw e; } }); + + it('should return the tickets with only destination', async() => { + const tx = await models.Ticket.beginTransaction({}); + + try { + const options = {transaction: tx}; + + const args = { + dateFuture: today, + dateToAdvance: today.setHours(23, 59, 59, 999), + warehouseFk: warehouseId, + }; + ctx.args = args; + + const allTickets = await models.Ticket.getTicketsAdvance(ctx, options); + ctx.args.onlyWithDestination = true; + const withDestinationTickets = await models.Ticket.getTicketsAdvance(ctx, options); + + expect(allTickets.filter(ticket => ticket.id).length).toBe(withDestinationTickets.length); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it('should return the tickets without only destination', async() => { + const tx = await models.Ticket.beginTransaction({}); + + try { + const options = {transaction: tx}; + + const args = { + dateFuture: today, + dateToAdvance: today.setHours(23, 59, 59, 999), + warehouseFk: warehouseId, + }; + ctx.args = args; + + const allTickets = await models.Ticket.getTicketsAdvance(ctx, options); + ctx.args.onlyWithDestination = false; + const withoutDestinationTickets = await models.Ticket.getTicketsAdvance(ctx, options); + + expect(allTickets.filter(ticket => !ticket.id).length).toBe(withoutDestinationTickets.length); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); }); diff --git a/modules/ticket/back/methods/ticket/specs/makeInvoice.spec.js b/modules/ticket/back/methods/ticket/specs/makeInvoice.spec.js index 88812dc92..f9e4bcac0 100644 --- a/modules/ticket/back/methods/ticket/specs/makeInvoice.spec.js +++ b/modules/ticket/back/methods/ticket/specs/makeInvoice.spec.js @@ -77,6 +77,8 @@ describe('ticket makeInvoice()', () => { await tx.rollback(); } - expect(error.message).toEqual(`The address of the customer must have information about Incoterms and Customs Agent`); + expect(error.message).toEqual( + `The address of the customer must have information about Incoterms and Customs Agent` + ); }); }); diff --git a/modules/ticket/back/methods/ticket/specs/merge.spec.js b/modules/ticket/back/methods/ticket/specs/merge.spec.js index 68f9d3393..99e0c6e81 100644 --- a/modules/ticket/back/methods/ticket/specs/merge.spec.js +++ b/modules/ticket/back/methods/ticket/specs/merge.spec.js @@ -7,7 +7,7 @@ describe('ticket merge()', () => { destinationId: 12, originShipped: Date.vnNew(), destinationShipped: Date.vnNew(), - workerFk: 1 + salesPersonFk: 1 }; it('should merge two tickets', async() => { diff --git a/modules/ticket/back/methods/ticket/specs/saveSign.spec.js b/modules/ticket/back/methods/ticket/specs/saveSign.spec.js index e93408973..3b426c2cf 100644 --- a/modules/ticket/back/methods/ticket/specs/saveSign.spec.js +++ b/modules/ticket/back/methods/ticket/specs/saveSign.spec.js @@ -1,12 +1,20 @@ const models = require('vn-loopback/server/server').models; +const LoopBackContext = require('loopback-context'); describe('Ticket saveSign()', () => { let ctx = {req: { getLocale: () => { return 'en'; }, + __: () => {}, accessToken: {userId: 9} - }}; + } + }; + beforeEach(() => { + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: ctx + }); + }); it(`should throw error if the ticket's alert level is lower than 2`, async() => { const tx = await models.TicketDms.beginTransaction({}); @@ -51,4 +59,46 @@ describe('Ticket saveSign()', () => { expect(ticketTrackingAfter.name).toBe('Entregado en parte'); }); + + it('should send an email to notify that the delivery order is not correct', async() => { + const tx = await models.Ticket.beginTransaction({}); + const ticketFk = 8; + const priority = 5; + const stateFk = 10; + const stateTicketFk = 2; + const expeditionFk = 11; + const expeditionStateFK = 2; + + let mailCountBefore; + let mailCountAfter; + spyOn(models.Dms, 'uploadFile').and.returnValue([{id: 1}]); + + const options = {transaction: tx}; + const tickets = [ticketFk]; + + const expedition = await models.Expedition.findById(expeditionFk, null, options); + expedition.updateAttribute('stateTypeFk', expeditionStateFK, options); + + const ticket = await models.Ticket.findById(ticketFk, null, options); + ticket.updateAttribute('priority', priority, options); + + const filter = {where: { + ticketFk: ticketFk, + stateFk: stateTicketFk} + }; + try { + const ticketTracking = await models.TicketTracking.findOne(filter, options); + ticketTracking.updateAttribute('stateFk', stateFk, options); + mailCountBefore = await models.Mail.count(options); + await models.Ticket.saveSign(ctx, tickets, null, null, options); + mailCountAfter = await models.Mail.count(options); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + + expect(mailCountAfter).toBeGreaterThan(mailCountBefore); + }); }); diff --git a/modules/ticket/back/models/specs/ticket-service.spec.js b/modules/ticket/back/models/specs/ticket-service.spec.js new file mode 100644 index 000000000..2691123eb --- /dev/null +++ b/modules/ticket/back/models/specs/ticket-service.spec.js @@ -0,0 +1,64 @@ +const {models} = require('vn-loopback/server/server'); + +describe('ticketService model ', () => { + const originalTicketFk = 1; + const refundTicketFk = 11; + + let tx; + let opts; + let ticketService; + + beforeEach(async() => { + tx = await models.Sale.beginTransaction({}); + opts = {transaction: tx}; + + ticketService = await models.TicketService.create({ + ticketFk: refundTicketFk, + description: 'test', + quantity: 1, + price: 100, + taxClassFk: 1, + ticketServiceTypeFk: 1 + }, opts); + }); + + afterEach(async() => { + await tx.rollback(); + }); + + describe('TicketService', () => { + it('should allow updating description and quantity for non-refund tickets', async() => { + await ticketService.updateAttributes({ + ticketServiceTypeFk: 2, + quantity: 5 + }, opts); + + const updated = await models.TicketService.findById(ticketService.id, null, opts); + + expect(updated.description).not.toBe('test'); + expect(updated.quantity).toBe(5); + }); + + it('should only allow updating description for refund tickets', async() => { + await models.TicketRefund.create({ + refundTicketFk, + originalTicketFk + }, opts); + + await ticketService.updateAttributes({ + ticketServiceTypeFk: 2 + }, opts); + + try { + await ticketService.updateAttributes({ + ticketServiceTypeFk: 3, + quantity: 5 + }, opts); + + fail('Should have thrown error'); + } catch (e) { + expect(e.message).toBe('Only description can be modified in refund tickets'); + } + }); + }); +}); diff --git a/modules/ticket/back/models/ticket-service.js b/modules/ticket/back/models/ticket-service.js index 209727ee4..77479498a 100644 --- a/modules/ticket/back/models/ticket-service.js +++ b/modules/ticket/back/models/ticket-service.js @@ -10,9 +10,18 @@ module.exports = Self => { const isLocked = await models.Ticket.isLocked(ticketId); if (isLocked) throw new UserError(`The current ticket can't be modified`); + + const isRefund = await models.TicketRefund.findOne({ + where: {refundTicketFk: ticketId} + }, { + transaction: ctx.options.transaction + }); + + if (isRefund && ctx.data && Object.keys(ctx.data).some(field => field !== 'ticketServiceTypeFk')) + throw new UserError('Only description can be modified in refund tickets'); } - if (changes && changes.ticketServiceTypeFk) { + if (changes?.ticketServiceTypeFk) { const ticketServiceType = await models.TicketServiceType.findById(changes.ticketServiceTypeFk); changes.description = ticketServiceType.name; } diff --git a/modules/travel/back/methods/travel/extraCommunityFilter.js b/modules/travel/back/methods/travel/extraCommunityFilter.js index f1586f804..2f3f998d6 100644 --- a/modules/travel/back/methods/travel/extraCommunityFilter.js +++ b/modules/travel/back/methods/travel/extraCommunityFilter.js @@ -132,18 +132,18 @@ module.exports = Self => { CAST(SUM(b.weight * b.stickers) AS DECIMAL(10,0)) loadedKg, CAST( SUM( - vc.aerealVolumetricDensity * - b.stickers * + vc.aerealVolumetricDensity * + b.stickers * IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000 ) AS DECIMAL(10,0) ) volumeKg, CAST( GREATEST( SUM(b.weight * b.stickers) , - SUM(vc.aerealVolumetricDensity * - b.stickers * - IF(pkg.volume, - pkg.volume, + SUM(vc.aerealVolumetricDensity * + b.stickers * + IF(pkg.volume, + pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000) ) / t.kg * 100 AS INT ) percentageKg @@ -185,11 +185,12 @@ module.exports = Self => { CAST(SUM(b.weight * b.stickers) AS DECIMAL(10,0)) as loadedkg, CAST( SUM( - vc.aerealVolumetricDensity * - b.stickers * + vc.aerealVolumetricDensity * + b.stickers * IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000 ) AS DECIMAL(10,0) - ) as volumeKg + ) as volumeKg, + MAX(i.isCustomInspectionRequired) isCustomInspectionRequired FROM tmp.travel tr JOIN entry e ON e.travelFk = tr.id JOIN buy b ON b.entryFk = e.id diff --git a/modules/travel/back/methods/travel/filter.js b/modules/travel/back/methods/travel/filter.js index b96873925..837e30b30 100644 --- a/modules/travel/back/methods/travel/filter.js +++ b/modules/travel/back/methods/travel/filter.js @@ -1,4 +1,3 @@ - const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; const buildFilter = require('vn-loopback/util/filter').buildFilter; const mergeFilters = require('vn-loopback/util/filter').mergeFilters; @@ -83,6 +82,19 @@ module.exports = Self => { arg: 'daysOnward', type: 'number', description: 'The days onward' + }, { + arg: 'shipped', + type: 'date', + description: 'The shipped date' + }, { + arg: 'landed', + type: 'date', + description: 'The landed date' + }, + { + arg: 'awbFk', + type: 'number', + description: 'The awbFk id' } ], returns: { @@ -108,6 +120,10 @@ module.exports = Self => { : {'t.ref': {like: `%${value}%`}}; case 'ref': return {'t.ref': {like: `%${value}%`}}; + case 'shipped': + return {'t.shipped': value}; + case 'landed': + return {'t.landed': value}; case 'shippedFrom': return {'t.shipped': {gte: value}}; case 'shippedTo': @@ -156,14 +172,17 @@ module.exports = Self => { t.totalEntries, t.isRaid, t.daysInForward, + t.awbFk, am.name agencyModeName, + a.code awbCode, win.name warehouseInName, wout.name warehouseOutName, cnt.code continent - FROM vn.travel t - JOIN vn.agencyMode am ON am.id = t.agencyModeFk - JOIN vn.warehouse win ON win.id = t.warehouseInFk - JOIN vn.warehouse wout ON wout.id = t.warehouseOutFk + FROM travel t + JOIN agencyMode am ON am.id = t.agencyModeFk + JOIN warehouse win ON win.id = t.warehouseInFk + JOIN warehouse wout ON wout.id = t.warehouseOutFk + LEFT JOIN awb a ON a.id = t.awbFk JOIN warehouse wo ON wo.id = t.warehouseOutFk JOIN country c ON c.id = wo.countryFk LEFT JOIN continent cnt ON cnt.id = c.continentFk) AS t` diff --git a/modules/travel/back/methods/travel/getEntries.js b/modules/travel/back/methods/travel/getEntries.js index 50088ccfa..2399f8bc4 100644 --- a/modules/travel/back/methods/travel/getEntries.js +++ b/modules/travel/back/methods/travel/getEntries.js @@ -41,7 +41,9 @@ module.exports = Self => { * b.stickers)/1000000) AS DECIMAL(10,2)) m3, TRUNCATE(SUM(b.stickers)/(COUNT( b.id) / COUNT( DISTINCT b.id)),0) hb, CAST(SUM(b.freightValue*b.quantity) AS DECIMAL(10,2)) freightValue, - CAST(SUM(b.packageValue*b.quantity) AS DECIMAL(10,2)) packageValue + CAST(SUM(b.packageValue*b.quantity) AS DECIMAL(10,2)) packageValue, + e.initialTemperature, + e.finalTemperature FROM vn.travel t LEFT JOIN vn.entry e ON t.id = e.travelFk LEFT JOIN vn.buy b ON b.entryFk = e.id diff --git a/modules/travel/back/methods/travel/specs/extraCommunityFilter.spec.js b/modules/travel/back/methods/travel/specs/extraCommunityFilter.spec.js index 7e90c7681..8fa013fe4 100644 --- a/modules/travel/back/methods/travel/specs/extraCommunityFilter.spec.js +++ b/modules/travel/back/methods/travel/specs/extraCommunityFilter.spec.js @@ -112,4 +112,17 @@ describe('Travel extraCommunityFilter()', () => { expect(result.length).toEqual(2); }); + + it('should return field isCustomInspectionRequired true', async() => { + const ctx = { + args: { + id: 2 + } + }; + + const result = await app.models.Travel.extraCommunityFilter(ctx, filter); + + expect(result[0].entries[0].isCustomInspectionRequired).toBeTruthy(); + expect(result[0].entries[1].isCustomInspectionRequired).toBeFalsy(); + }); }); diff --git a/modules/travel/back/models/currency.json b/modules/travel/back/models/currency.json index f3241fad1..427a18e31 100644 --- a/modules/travel/back/models/currency.json +++ b/modules/travel/back/models/currency.json @@ -20,6 +20,9 @@ }, "ratio": { "type": "number" + }, + "hasToDownloadRate": { + "type": "boolean" } }, "acls": [ diff --git a/modules/worker/back/methods/worker-time-control/sendMail.js b/modules/worker/back/methods/worker-time-control/sendMail.js index 2e1e00d83..5fd5f65ff 100644 --- a/modules/worker/back/methods/worker-time-control/sendMail.js +++ b/modules/worker/back/methods/worker-time-control/sendMail.js @@ -41,22 +41,10 @@ module.exports = Self => { const stmts = []; let stmt; - if (!args.week || !args.year) { - const from = Date.vnNew(); - const to = Date.vnNew(); + const {date: started, week, year} = Self.getMondayWeekYear(args.week, args.year); + args.week = week; + args.year = year; - const time = await models.Time.findOne({ - where: { - dated: {between: [from.setDate(from.getDate() - 10), to.setDate(to.getDate() - 4)]} - }, - order: 'week ASC' - }, myOptions); - - args.week = time.week; - args.year = time.year; - } - - const started = getStartDateOfWeekNumber(args.week, args.year); started.setHours(0, 0, 0, 0); const ended = new Date(started); @@ -388,17 +376,6 @@ module.exports = Self => { return true; }; - function getStartDateOfWeekNumber(week, year) { - const simple = new Date(year, 0, 1 + (week - 1) * 7); - const dow = simple.getDay(); - const weekStart = simple; - if (dow <= 4) - weekStart.setDate(simple.getDate() - simple.getDay() + 1); - else - weekStart.setDate(simple.getDate() + 8 - simple.getDay()); - return weekStart; - } - function getTime(timeString) { const [hours, minutes, seconds] = timeString.split(':'); return [parseInt(hours), parseInt(minutes), parseInt(seconds)]; diff --git a/modules/worker/back/methods/worker-time-control/weeklyHourRecordEmail.js b/modules/worker/back/methods/worker-time-control/weeklyHourRecordEmail.js index e352eb3cb..eadbecb00 100644 --- a/modules/worker/back/methods/worker-time-control/weeklyHourRecordEmail.js +++ b/modules/worker/back/methods/worker-time-control/weeklyHourRecordEmail.js @@ -55,8 +55,8 @@ module.exports = Self => { } }, myOptions); - const dated = getMondayDateFromYearWeek(args.year, args.week); - const timestamp = dated.getTime() / 1000; + const {date} = Self.getMondayWeekYear(args.week, args.year); + const timestamp = date.getTime() / 1000; const url = `${salix.url}worker/${args.workerId}/time-control?timestamp=${timestamp}`; ctx.args.url = url; @@ -64,23 +64,4 @@ module.exports = Self => { await models.WorkerTimeControl.updateMailState(ctx, ctx.args.workerId, myOptions); return Self.sendTemplate(ctx, 'weekly-hour-record'); }; - - function getMondayDateFromYearWeek(yearNumber, weekNumber) { - const yearStart = new Date(yearNumber, 0, 1); - const firstMonday = new Date(yearStart.getTime() + ((7 - yearStart.getDay() + 1) % 7) * 86400000); - const firstMondayWeekNumber = getWeekNumber(firstMonday); - - if (firstMondayWeekNumber > 1) - firstMonday.setDate(firstMonday.getDate() + 7); - - firstMonday.setDate(firstMonday.getDate() + (weekNumber - 1) * 7); - - return firstMonday; - } - - function getWeekNumber(date) { - const firstDayOfYear = new Date(date.getFullYear(), 0, 1); - const daysPassed = (date - firstDayOfYear) / 86400000; - return Math.ceil((daysPassed + firstDayOfYear.getDay() + 1) / 7); - } }; diff --git a/modules/worker/back/methods/worker/createAbsence.js b/modules/worker/back/methods/worker/createAbsence.js index e46ce9577..dc716c95d 100644 --- a/modules/worker/back/methods/worker/createAbsence.js +++ b/modules/worker/back/methods/worker/createAbsence.js @@ -58,12 +58,10 @@ module.exports = Self => { if (!isSubordinate || (isSubordinate && userId == id && !isTeamBoss)) throw new UserError(`You don't have enough privileges`); - const canCreateAbsenceInPast = - await models.ACL.checkAccessAcl(ctx, 'Worker', 'canCreateAbsenceInPast', 'WRITE'); const now = Date.vnNew(); const newDate = new Date(args.dated).getTime(); - if ((now.getTime() > newDate) && !canCreateAbsenceInPast) + if (!await Self.canModifyAbsenceInPast(ctx, newDate)) throw new UserError(`Holidays to past days not available`); const labour = await models.WorkerLabour.findById(args.businessFk, @@ -128,7 +126,10 @@ module.exports = Self => { 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 receiver = await models.EmailUser.findOne({ + fields: ['email'], + where: {userFk: worker.bossFk} + }, myOptions); const url = await Self.app.models.Url.getUrl(); const body = $t('Created absence', { author: account.nickname, @@ -140,7 +141,7 @@ module.exports = Self => { await models.Mail.create({ subject: $t('Absence change notification on the labour calendar'), body: body, - receiver: departmentBoss.email + receiver: receiver.email }, myOptions); if (tx) await tx.commit(); diff --git a/modules/worker/back/methods/worker/deleteAbsence.js b/modules/worker/back/methods/worker/deleteAbsence.js index b71d077a4..596f8f28d 100644 --- a/modules/worker/back/methods/worker/deleteAbsence.js +++ b/modules/worker/back/methods/worker/deleteAbsence.js @@ -53,6 +53,10 @@ module.exports = Self => { } } }, myOptions); + + if (!await Self.canModifyAbsenceInPast(ctx, absence.dated.getTime())) + throw new UserError(`Holidays to past days not available`); + const result = await absence.destroy(myOptions); const labour = absence.labour(); const department = labour && labour.department(); diff --git a/modules/worker/back/methods/worker/filter.js b/modules/worker/back/methods/worker/filter.js index 52c60572a..087f080bd 100644 --- a/modules/worker/back/methods/worker/filter.js +++ b/modules/worker/back/methods/worker/filter.js @@ -73,6 +73,11 @@ module.exports = Self => { type: 'String', description: 'The user email', http: {source: 'query'} + }, + { + arg: 'myTeam', + type: 'boolean', + description: 'Whether to show only tickets for the current logged user team (currently user tickets)' } ], returns: { @@ -85,10 +90,21 @@ module.exports = Self => { } }); - Self.filter = async(ctx, filter) => { - let conn = Self.dataSource.connector; + Self.filter = async(ctx, filter, options) => { + const userId = ctx.req.accessToken.userId; + const conn = Self.dataSource.connector; + const models = Self.app.models; + const args = ctx.args; + let myTeamIds = []; + const myOptions = {}; - let where = buildFilter(ctx.args, (param, value) => { + if (typeof options == 'object') + Object.assign(myOptions, options); + + if (args.myTeam != null) + myTeamIds = await models.Worker.myTeam(userId); + + const where = buildFilter(ctx.args, (param, value) => { switch (param) { case 'search': return /^\d+$/.test(value) @@ -117,12 +133,17 @@ module.exports = Self => { return {'u.name': {like: `%${value}%`}}; case 'email': return {'eu.email': {like: `%${value}%`}}; + case 'myTeam': + if (value) + return {'c.salesPersonFk': {inq: myTeamIds}}; + else + return {'c.salesPersonFk': {nin: myTeamIds}}; } }); - filter = mergeFilters(ctx.args.filter, {where}); + filter = mergeFilters(filter, {where}); - let stmts = []; + const stmts = []; let stmt; stmt = new ParameterizedSQL( @@ -145,11 +166,12 @@ module.exports = Self => { LEFT JOIN account.emailUser eu ON eu.userFk = u.id` ); - stmt.merge(conn.makeSuffix(filter)); - let itemsIndex = stmts.push(stmt) - 1; + stmt.merge(conn.makeWhere(filter.where)); + stmts.push(stmt); - let sql = ParameterizedSQL.join(stmts, ';'); - let result = await conn.executeStmt(sql); - return itemsIndex === 0 ? result : result[itemsIndex]; + const itemsIndex = stmts.push(stmt) - 1; + const sql = ParameterizedSQL.join(stmts, ';'); + const result = await conn.executeStmt(sql, myOptions); + return result[itemsIndex]; }; }; diff --git a/modules/worker/back/methods/worker/myTeam.js b/modules/worker/back/methods/worker/myTeam.js new file mode 100644 index 000000000..25c5916fb --- /dev/null +++ b/modules/worker/back/methods/worker/myTeam.js @@ -0,0 +1,43 @@ +module.exports = Self => { + Self.remoteMethod('myTeam', { + description: 'Return the members of the user team', + accessType: 'READ', + accepts: [{ + arg: 'userId', + type: 'string', + required: true + }], + returns: { + type: 'string', + root: true + }, + http: { + path: `/myTeam`, + verb: 'GET' + } + }); + + Self.myTeam = async(userId, options) => { + const models = Self.app.models; + const myOptions = {}; + const teamMembersId = []; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + const worker = await models.Worker.findById(userId, { + include: { + relation: 'collegues' + } + }, myOptions); + const collegues = worker.collegues() || []; + for (let collegue of collegues) + teamMembersId.push(collegue.collegueFk); + + if (teamMembersId.length == 0) + teamMembersId.push(userId); + + return teamMembersId; + }; +}; + diff --git a/modules/worker/back/methods/worker/specs/deleteAbsence.spec.js b/modules/worker/back/methods/worker/specs/deleteAbsence.spec.js index 0f3f913dc..c0d05e4a2 100644 --- a/modules/worker/back/methods/worker/specs/deleteAbsence.spec.js +++ b/modules/worker/back/methods/worker/specs/deleteAbsence.spec.js @@ -4,6 +4,8 @@ const LoopBackContext = require('loopback-context'); describe('Worker deleteAbsence()', () => { const businessId = 18; const workerId = 18; + const hrId = 37; + const salesBossId = 19; const activeCtx = { accessToken: {userId: 1106}, headers: {origin: 'http://localhost'} @@ -50,16 +52,16 @@ describe('Worker deleteAbsence()', () => { }); it('should successfully delete an absence', async() => { - activeCtx.accessToken.userId = 19; + activeCtx.accessToken.userId = salesBossId; const tx = await app.models.Calendar.beginTransaction({}); - + const pastDate = new Date(Date.vnNow() + 24 * 60 * 60 * 1000); try { const options = {transaction: tx}; const createdAbsence = await app.models.Calendar.create({ businessFk: businessId, dayOffTypeFk: 1, - dated: Date.vnNew() + dated: pastDate }, options); ctx.args = {absenceId: createdAbsence.id}; @@ -76,4 +78,61 @@ describe('Worker deleteAbsence()', () => { throw e; } }); + + it('should successfully delete an absence if the user is HR even if the date is in the past', async() => { + activeCtx.accessToken.userId = hrId; + const tx = await app.models.Calendar.beginTransaction({}); + + try { + const options = {transaction: tx}; + const pastDate = new Date(Date.vnNow() - 24 * 60 * 60 * 1000); // Restar un día + const createdAbsence = await app.models.Calendar.create({ + businessFk: businessId, + dayOffTypeFk: 1, + dated: pastDate + }, options); + + ctx.args = {absenceId: createdAbsence.id}; + await app.models.Worker.deleteAbsence(ctx, workerId, options); + + const deletedAbsence = await app.models.Calendar.findById(createdAbsence.id, null, options); + + expect(deletedAbsence).toBeNull(); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it('should throw an error if the date is in the past', async() => { + activeCtx.accessToken.userId = salesBossId; + const tx = await app.models.Calendar.beginTransaction({}); + + let error; + try { + const options = {transaction: tx}; + const pastDate = new Date(Date.vnNow() - 24 * 60 * 60 * 1000); + const createdAbsence = await app.models.Calendar.create({ + businessFk: businessId, + dayOffTypeFk: 1, + dated: pastDate + }, options); + + ctx.args = {absenceId: createdAbsence.id}; + await app.models.Worker.deleteAbsence(ctx, workerId, options); + + const deletedAbsence = await app.models.Calendar.findById(createdAbsence.id, null, options); + + expect(deletedAbsence).toBeNull(); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } + + expect(error.message).toBe('Holidays to past days not available'); + }); }); diff --git a/modules/worker/back/methods/worker/specs/filter.spec.js b/modules/worker/back/methods/worker/specs/filter.spec.js index 2eb353576..27eb79cdb 100644 --- a/modules/worker/back/methods/worker/specs/filter.spec.js +++ b/modules/worker/back/methods/worker/specs/filter.spec.js @@ -1,25 +1,69 @@ +const models = require('vn-loopback/server/server').models; const app = require('vn-loopback/server/server'); describe('worker filter()', () => { - it('should return 1 result filtering by id', async() => { - let result = await app.models.Worker.filter({args: {filter: {}, search: 1}}); + const ctx = beforeAll.getCtx(); - expect(result.length).toEqual(1); - expect(result[0].id).toEqual(1); + it('should return 1 result filtering by id', async() => { + const tx = await models.Worker.beginTransaction({}); + + try { + const options = {transaction: tx}; + const filter = {}; + const args = {search: 1}; + ctx.args = args; + + let result = await app.models.Worker.filter(ctx, filter, options); + + expect(result.length).toEqual(1); + expect(result[0].id).toEqual(1); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } }); it('should return 1 result filtering by string', async() => { - let result = await app.models.Worker.filter({args: {filter: {}, search: 'administrativeNick'}}); + const tx = await models.Worker.beginTransaction({}); - expect(result.length).toEqual(1); - expect(result[0].id).toEqual(5); + try { + const options = {transaction: tx}; + const filter = {}; + const args = {search: 'administrativeNick'}; + ctx.args = args; + + let result = await app.models.Worker.filter(ctx, filter, options); + + expect(result.length).toEqual(1); + expect(result[0].id).toEqual(5); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } }); - it('should return 2 results filtering by name', async() => { - let result = await app.models.Worker.filter({args: {filter: {}, firstName: 'agency'}}); + it('should return 2 result filtering by name', async() => { + const tx = await models.Worker.beginTransaction({}); - expect(result.length).toEqual(2); - expect(result[0].nickname).toEqual('agencyNick'); - expect(result[1].nickname).toEqual('agencyBossNick'); + try { + const options = {transaction: tx}; + const filter = {}; + const args = {firstName: 'agency'}; + ctx.args = args; + + let result = await app.models.Worker.filter(ctx, filter, options); + + expect(result[0].nickname).toEqual('agencyNick'); + expect(result[1].nickname).toEqual('agencyBossNick'); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } }); }); diff --git a/modules/worker/back/models/device-production-user.json b/modules/worker/back/models/device-production-user.json index a024cc94c..31aaf92d4 100644 --- a/modules/worker/back/models/device-production-user.json +++ b/modules/worker/back/models/device-production-user.json @@ -25,7 +25,7 @@ "userFk": { "type": "number" }, - "simSerialNumber": { + "simFk": { "type": "string" }, "created": { diff --git a/modules/worker/back/models/worker-time-control.js b/modules/worker/back/models/worker-time-control.js index 92f1bacf0..cdf51b712 100644 --- a/modules/worker/back/models/worker-time-control.js +++ b/modules/worker/back/models/worker-time-control.js @@ -1,4 +1,5 @@ const UserError = require('vn-loopback/util/user-error'); +const moment = require('moment'); module.exports = Self => { require('../methods/worker-time-control/filter')(Self); @@ -19,4 +20,15 @@ module.exports = Self => { return new UserError(`The introduced hour already exists`); return err; }); + + Self.getMondayWeekYear = (week, year) => { + if (!week || !year) { + const today = Date.vnNew(); + today.setDate(today.getDate() - 7); + week = moment(today).isoWeek(); + year = moment(today).isoWeekYear(); + } + const date = moment(year, 'YYYY').week(week).startOf('isoweek').toDate(); + return {date, year, week}; + }; }; diff --git a/modules/worker/back/models/worker.js b/modules/worker/back/models/worker.js index 3351c348c..97e6a283c 100644 --- a/modules/worker/back/models/worker.js +++ b/modules/worker/back/models/worker.js @@ -21,11 +21,19 @@ module.exports = Self => { require('../methods/worker/isAuthorized')(Self); require('../methods/worker/setPassword')(Self); require('../methods/worker/getAvailablePda')(Self); + require('../methods/worker/myTeam')(Self); Self.validateAsync('fi', tinIsValid, { message: 'Invalid TIN' }); + Self.canModifyAbsenceInPast = async(ctx, time) => { + const hasPrivs = await Self.app.models.ACL.checkAccessAcl(ctx, 'Worker', 'canModifyAbsenceInPast', 'WRITE'); + const today = Date.vnNew(); + today.setHours(0, 0, 0, 0); + return hasPrivs || today.getTime() < time; + }; + async function tinIsValid(err, done) { const country = await Self.app.models.Country.findOne({ fields: ['code'], diff --git a/modules/zone/back/methods/zone/deleteZone.js b/modules/zone/back/methods/zone/deleteZone.js index e2e01a949..a147ee588 100644 --- a/modules/zone/back/methods/zone/deleteZone.js +++ b/modules/zone/back/methods/zone/deleteZone.js @@ -51,7 +51,7 @@ module.exports = Self => { }; const ticketList = await models.Ticket.find(filter, myOptions); - const hasRefFk = ticketList.some(ticket => ticket.refFk); + const hasRefFk = ticketList.some(ticket => !ticket.refFk); if (hasRefFk) throw new UserError('There are tickets to be invoiced'); diff --git a/modules/zone/back/model-config.json b/modules/zone/back/model-config.json index 3bbbe0d1b..2cd3f9d01 100644 --- a/modules/zone/back/model-config.json +++ b/modules/zone/back/model-config.json @@ -17,6 +17,9 @@ "ZoneClosure": { "dataSource": "vn" }, + "ZoneConfig": { + "dataSource": "vn" + }, "ZoneEvent": { "dataSource": "vn" }, diff --git a/modules/zone/back/models/zone-config.json b/modules/zone/back/models/zone-config.json new file mode 100644 index 000000000..a5da7fe55 --- /dev/null +++ b/modules/zone/back/models/zone-config.json @@ -0,0 +1,28 @@ +{ + "name": "ZoneConfig", + "options": { + "mysql": { + "table": "zoneConfig" + } + }, + "properties": { + "id": { + "type": "number", + "id": true, + "description": "Identifier" + }, + "scope": { + "type": "number" + }, + "forwardDays": { + "type": "number" + } + }, + "relations": { + "address": { + "type": "belongsTo", + "model": "Address", + "foreignKey": "defaultAddressFk" + } + } +} diff --git a/modules/zone/back/models/zone-event.json b/modules/zone/back/models/zone-event.json index 366bdec9d..cf5045a8c 100644 --- a/modules/zone/back/models/zone-event.json +++ b/modules/zone/back/models/zone-event.json @@ -42,6 +42,9 @@ "price": { "type": "number" }, + "priceOptimum": { + "type": "number" + }, "bonus": { "type": "number" }, diff --git a/modules/zone/back/models/zone.json b/modules/zone/back/models/zone.json index 5b25e40d1..4f963568f 100644 --- a/modules/zone/back/models/zone.json +++ b/modules/zone/back/models/zone.json @@ -1,9 +1,9 @@ { "name": "Zone", "base": "VnModel", - "mixins": { - "Loggable": true - }, + "mixins": { + "Loggable": true + }, "options": { "mysql": { "table": "zone" @@ -28,6 +28,9 @@ "price": { "type": "number" }, + "priceOptimum": { + "type": "number" + }, "bonus": { "type": "number" }, @@ -48,30 +51,35 @@ } }, "relations": { - "agencyMode": { - "type": "belongsTo", - "model": "AgencyMode", - "foreignKey": "agencyModeFk" + "agencyMode": { + "type": "belongsTo", + "model": "AgencyMode", + "foreignKey": "agencyModeFk" }, "events": { - "type": "hasMany", - "model": "ZoneEvent", - "foreignKey": "zoneFk" - }, + "type": "hasMany", + "model": "ZoneEvent", + "foreignKey": "zoneFk" + }, "exclusions": { - "type": "hasMany", - "model": "ZoneExclusion", + "type": "hasMany", + "model": "ZoneExclusion", "foreignKey": "zoneFk" }, "warehouses": { "type": "hasMany", "model": "ZoneWarehouse", "foreignKey": "zoneFk" - }, + }, "closures": { "type": "hasMany", "model": "ZoneClosure", "foreignKey": "zoneFk" - } - } + }, + "address": { + "type": "belongsTo", + "model": "Address", + "foreignKey": "addressFk" + } + } } diff --git a/package.json b/package.json index 4e823eaad..72f8e2d1b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "salix-back", - "version": "24.52.0", + "version": "25.06.0", "author": "Verdnatura Levante SL", "description": "Salix backend", "license": "GPL-3.0", diff --git a/print/templates/reports/buy-label-supplier/assets/css/style.css b/print/templates/reports/buy-label-supplier/assets/css/style.css index 3b1f2f91e..f64e01688 100644 --- a/print/templates/reports/buy-label-supplier/assets/css/style.css +++ b/print/templates/reports/buy-label-supplier/assets/css/style.css @@ -1,7 +1,7 @@ html { font-family: "Roboto", "Helvetica", "Arial", sans-serif; margin-top: -7px; - font-size: 28px; + font-size: 20px; } table { border: 1px solid; @@ -10,22 +10,22 @@ table { } td { border: 1px solid; - padding: 5px; + padding: 2px; width: 100%; } span { - font-size: 48px; + font-size: 34px; font-weight: bold; } .lbl { color: gray; font-weight: lighter; - font-size: 18px; + font-size: 12px; display: block; } .cell { width: 157px; - height: 50px; + height: 35px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; diff --git a/print/templates/reports/buy-label-supplier/buy-label-supplier.js b/print/templates/reports/buy-label-supplier/buy-label-supplier.js index 5e59472eb..c8af17a5d 100755 --- a/print/templates/reports/buy-label-supplier/buy-label-supplier.js +++ b/print/templates/reports/buy-label-supplier/buy-label-supplier.js @@ -10,7 +10,7 @@ module.exports = { async serverPrefetch() { const buy = await models.Buy.findById(this.id, null); this.buys = await this.rawSqlFromDef('buy', [buy.entryFk, buy.entryFk, buy.entryFk, this.id, this.id]); - const date = new Date(); + const date = Date.vnNew(); this.weekNum = moment(date).isoWeek(); this.dayNum = moment(date).day(); }, @@ -24,7 +24,8 @@ module.exports = { format: 'code128', displayValue: false, width: 3.8, - height: 115, + height: 60, + margin: 3, }); return new XMLSerializer().serializeToString(svgNode); }, diff --git a/print/templates/reports/buy-label-supplier/options.json b/print/templates/reports/buy-label-supplier/options.json index 4ed0461b3..a2a781cbf 100644 --- a/print/templates/reports/buy-label-supplier/options.json +++ b/print/templates/reports/buy-label-supplier/options.json @@ -1,6 +1,6 @@ { "width": "10cm", - "height": "10cm", + "height": "6.5cm", "margin": { "top": "0.17cm", "right": "0.2cm", diff --git a/print/templates/reports/invoice-incoterms/sql/incoterms.sql b/print/templates/reports/invoice-incoterms/sql/incoterms.sql index 016a8342e..535451674 100644 --- a/print/templates/reports/invoice-incoterms/sql/incoterms.sql +++ b/print/templates/reports/invoice-incoterms/sql/incoterms.sql @@ -1,9 +1,9 @@ WITH tickets AS( -SELECT id, packages, addressFk, weight - FROM ticket - WHERE refFk= ? +SELECT id, addressFk, packages, refFk + FROM vn.ticket + WHERE refFk = ? ), volume AS( -SELECT SUM(volume) volume +SELECT SUM(volume) volume, MAX(weight)weight FROM tickets t JOIN vn.saleVolume sv ON sv.ticketFk = t.id ), intrastat AS( @@ -12,10 +12,14 @@ SELECT GROUP_CONCAT(DISTINCT ir.description ORDER BY ir.description SEPARATOR ' JOIN vn.sale s ON t.id = s.ticketFk JOIN vn.item i ON i.id = s.itemFk JOIN vn.intrastat ir ON ir.id = i.intrastatFk -)SELECT SUM(t.packages) packages, - a.incotermsFk, +), totalPackages AS( +SELECT SUM(packages)packages + FROM tickets s +) +SELECT tp.packages, + io.incotermsFk, ic.name incotermsName, - MAX(t.weight) weight, + v.weight weight, ca.fiscalName customsAgentName, ca.street customsAgentStreet, ca.nif customsAgentNif, @@ -23,9 +27,10 @@ SELECT GROUP_CONCAT(DISTINCT ir.description ORDER BY ir.description SEPARATOR ' ca.email customsAgentEmail, CAST(v.volume AS DECIMAL (10,2)) volume, i.intrastat - FROM tickets t - JOIN vn.address a ON a.id = t.addressFk - JOIN vn.incoterms ic ON ic.code = a.incotermsFk - LEFT JOIN vn.customsAgent ca ON ca.id = a.customsAgentFk + FROM vn.invoiceOut io + JOIN vn.incoterms ic ON ic.code = io.incotermsFk + LEFT JOIN vn.customsAgent ca ON ca.id = io.customsAgentFk JOIN volume v JOIN intrastat i + JOIN totalPackages tp + WHERE `ref` = (SELECT DISTINCT refFk FROM tickets) \ No newline at end of file