diff --git a/back/Dockerfile b/back/Dockerfile index 363192a0b..0f75f6949 100644 --- a/back/Dockerfile +++ b/back/Dockerfile @@ -32,8 +32,7 @@ RUN apt-get update \ RUN apt-get update \ && apt-get install -y --no-install-recommends \ samba-common-bin samba-dsdb-modules\ - && rm -rf /var/lib/apt/lists/* \ - && npm -g install pm2 + && rm -rf /var/lib/apt/lists/* # Salix @@ -55,7 +54,4 @@ COPY \ README.md \ ./ -CMD ["pm2-runtime", "./back/process.yml"] - -HEALTHCHECK --interval=15s --timeout=10s \ - CMD curl -f http://localhost:3000/api/Applications/status || exit 1 +CMD ["node", "--tls-min-v1.0", "--openssl-legacy-provider", "./loopback/server/server.js"] \ No newline at end of file diff --git a/back/methods/collection/getTickets.js b/back/methods/collection/getTickets.js index 2a2b67524..48301a366 100644 --- a/back/methods/collection/getTickets.js +++ b/back/methods/collection/getTickets.js @@ -62,7 +62,8 @@ module.exports = Self => { p.code parkingCodePrevia, p.pickingOrder pickingOrderPrevia, iss.id itemShelvingSaleFk, - iss.isPicked + iss.isPicked, + iss.itemShelvingFk FROM ticketCollection tc LEFT JOIN collection c ON c.id = tc.collectionFk JOIN sale s ON s.ticketFk = tc.ticketFk @@ -102,7 +103,8 @@ module.exports = Self => { p.code, p.pickingOrder, iss.id itemShelvingSaleFk, - iss.isPicked + iss.isPicked, + iss.itemShelvingFk FROM sectorCollection sc JOIN sectorCollectionSaleGroup ss ON ss.sectorCollectionFk = sc.id JOIN saleGroup sg ON sg.id = ss.saleGroupFk diff --git a/back/methods/docuware/core.js b/back/methods/docuware/core.js index 74d922236..3de33b786 100644 --- a/back/methods/docuware/core.js +++ b/back/methods/docuware/core.js @@ -4,21 +4,45 @@ module.exports = Self => { /** * Returns basic headers * - * @param {string} cookie - The docuware cookie * @return {object} - The headers */ Self.getOptions = async() => { const docuwareConfig = await Self.app.models.DocuwareConfig.findOne(); + const now = Date.vnNow(); + let {url, username, password, token, expired} = docuwareConfig; + + if (process.env.NODE_ENV && (!expired || expired < now + 60)) { + const {data: {IdentityServiceUrl}} = await axios.get(`${url}/Home/IdentityServiceInfo`); + const {data: {token_endpoint}} = await axios.get(`${IdentityServiceUrl}/.well-known/openid-configuration`); + const {data} = await axios.post(token_endpoint, { + grant_type: 'password', + scope: 'docuware.platform', + client_id: 'docuware.platform.net.client', + username, + password + }, {headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/x-www-form-urlencoded' + }}); + + const newToken = data.access_token; + token = data.token_type + ' ' + newToken; + await docuwareConfig.updateAttributes({ + token, + expired: now + data.expires_in + }); + } + const headers = { headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', - 'Cookie': docuwareConfig.cookie + 'Authorization': token } }; return { - url: docuwareConfig.url, + url, headers }; }; diff --git a/back/methods/docuware/specs/core.spec.js b/back/methods/docuware/specs/core.spec.js index cdf8a3b62..47580483d 100644 --- a/back/methods/docuware/specs/core.spec.js +++ b/back/methods/docuware/specs/core.spec.js @@ -2,87 +2,54 @@ const axios = require('axios'); const models = require('vn-loopback/server/server').models; describe('Docuware core', () => { - beforeAll(() => { + const fileCabinetCode = 'deliveryNote'; + beforeAll(async() => { process.env.NODE_ENV = 'testing'; - }); - afterAll(() => { - delete process.env.NODE_ENV; - }); - - describe('getOptions()', () => { - it('should return url and headers', async() => { - const result = await models.Docuware.getOptions(); - - expect(result.url).toBeDefined(); - expect(result.headers).toBeDefined(); + const docuwareInfo = await models.Docuware.findOne({ + where: { + code: fileCabinetCode + } }); - }); - describe('getDialog()', () => { - it('should return dialogId', async() => { - const dialogs = { - data: { - Dialog: [ - { - DisplayName: 'find', - Id: 'getDialogTest' - } - ] - } - }; - spyOn(axios, 'get').and.returnValue(new Promise(resolve => resolve(dialogs))); - const result = await models.Docuware.getDialog('deliveryNote', 'find', 'randomFileCabinetId'); + spyOn(axios, 'get').and.callFake(url => { + if (url.includes('IdentityServiceInfo')) return {data: {IdentityServiceUrl: 'IdentityServiceUrl'}}; + if (url.includes('IdentityServiceUrl')) return {data: {token_endpoint: 'token_endpoint'}}; + if (url.includes('dialogs')) { + return { + data: { + Dialog: [ + { + DisplayName: 'find', + Id: 'getDialogTest' + } + ] + } + }; + } - expect(result).toEqual('getDialogTest'); - }); - }); - - describe('getFileCabinet()', () => { - it('should return fileCabinetId', async() => { - const code = 'deliveryNote'; - const docuwareInfo = await models.Docuware.findOne({ - where: { - code - } - }); - const dialogs = { - data: { + if (url.includes('FileCabinets')) { + return {data: { FileCabinet: [ { Name: docuwareInfo.fileCabinetName, Id: 'getFileCabinetTest' } ] - } - }; - spyOn(axios, 'get').and.returnValue(new Promise(resolve => resolve(dialogs))); - const result = await models.Docuware.getFileCabinet(code); - - expect(result).toEqual('getFileCabinetTest'); - }); - }); - - describe('get()', () => { - it('should return data without parse', async() => { - spyOn(models.Docuware, 'getFileCabinet').and.returnValue((new Promise(resolve => resolve(Math.random())))); - spyOn(models.Docuware, 'getDialog').and.returnValue((new Promise(resolve => resolve(Math.random())))); - const data = { - data: { - id: 1 - } - }; - spyOn(axios, 'post').and.returnValue(new Promise(resolve => resolve(data))); - const result = await models.Docuware.get('deliveryNote'); - - expect(result.id).toEqual(1); + }}; + } }); - it('should return data with parse', async() => { - spyOn(models.Docuware, 'getFileCabinet').and.returnValue((new Promise(resolve => resolve(Math.random())))); - spyOn(models.Docuware, 'getDialog').and.returnValue((new Promise(resolve => resolve(Math.random())))); - const data = { - data: { + spyOn(axios, 'post').and.callFake(url => { + if (url.includes('token_endpoint')) { + return {data: { + access_token: 'access_token', + token_type: 'bearer', + expires_in: 10000 + }}; + } + if (url.includes('DialogExpression')) { + return {data: { Items: [{ Fields: [ { @@ -103,12 +70,52 @@ describe('Docuware core', () => { ] }] } - }; + }; + } + }); + }); + + afterAll(() => { + delete process.env.NODE_ENV; + }); + + describe('getOptions()', () => { + it('should return url and headers', async() => { + const result = await models.Docuware.getOptions(); + + expect(result.url).toBeDefined(); + expect(result.headers).toBeDefined(); + }); + }); + + describe('Dialog()', () => { + it('should return dialogId', async() => { + const result = await models.Docuware.getDialog('deliveryNote', 'find', 'randomFileCabinetId'); + + expect(result).toEqual('getDialogTest'); + }); + }); + + describe('getFileCabinet()', () => { + it('should return fileCabinetId', async() => { + const result = await models.Docuware.getFileCabinet(fileCabinetCode); + + expect(result).toEqual('getFileCabinetTest'); + }); + }); + + describe('get()', () => { + it('should return data without parse', async() => { + const [result] = await models.Docuware.get('deliveryNote'); + + expect(result.firstRequiredField).toEqual(1); + }); + + it('should return data with parse', async() => { const parse = { 'firstRequiredField': 'id', 'secondRequiredField': 'name', }; - spyOn(axios, 'post').and.returnValue(new Promise(resolve => resolve(data))); const [result] = await models.Docuware.get('deliveryNote', null, parse); expect(result.id).toEqual(1); @@ -119,17 +126,14 @@ describe('Docuware core', () => { describe('getById()', () => { it('should return data', async() => { - spyOn(models.Docuware, 'getFileCabinet').and.returnValue((new Promise(resolve => resolve(Math.random())))); - spyOn(models.Docuware, 'getDialog').and.returnValue((new Promise(resolve => resolve(Math.random())))); - const data = { - data: { - id: 1 - } - }; - spyOn(axios, 'post').and.returnValue(new Promise(resolve => resolve(data))); - const result = await models.Docuware.getById('deliveryNote', 1); + spyOn(models.Docuware, 'get'); + await models.Docuware.getById('deliveryNote', 1); - expect(result.id).toEqual(1); + expect(models.Docuware.get).toHaveBeenCalledWith( + 'deliveryNote', + {condition: [Object({DBName: 'N__ALBAR_N', Value: [1]})]}, + undefined + ); }); }); }); diff --git a/back/methods/docuware/upload.js b/back/methods/docuware/upload.js index 0102911e0..5b35b7598 100644 --- a/back/methods/docuware/upload.js +++ b/back/methods/docuware/upload.js @@ -143,7 +143,7 @@ module.exports = Self => { headers: { 'Content-Type': 'multipart/form-data', 'X-File-ModifiedDate': Date.vnNew(), - 'Cookie': docuwareOptions.headers.headers.Cookie, + 'Authorization': docuwareOptions.headers.headers.Authorization, ...data.getHeaders() }, }; diff --git a/back/models/docuware-config.json b/back/models/docuware-config.json index 9d06c4874..b15cb4c03 100644 --- a/back/models/docuware-config.json +++ b/back/models/docuware-config.json @@ -16,17 +16,17 @@ "url": { "type": "string" }, - "cookie": { + "token": { "type": "string" + }, + "username": { + "type": "string" + }, + "password": { + "type": "string" + }, + "expired":{ + "type": "number" } - }, - "acls": [ - { - "property": "*", - "accessType": "*", - "principalType": "ROLE", - "principalId": "$everyone", - "permission": "ALLOW" - } - ] + } } diff --git a/back/process.yml b/back/process.yml deleted file mode 100644 index 94072b57d..000000000 --- a/back/process.yml +++ /dev/null @@ -1,7 +0,0 @@ -apps: - - script: ./loopback/server/server.js - name: salix-back - instances: 1 - max_restarts: 0 - autorestart: false - node_args: --tls-min-v1.0 --openssl-legacy-provider diff --git a/db/dump/fixtures.before.sql b/db/dump/fixtures.before.sql index 7f7e50dd3..a6852be7e 100644 --- a/db/dump/fixtures.before.sql +++ b/db/dump/fixtures.before.sql @@ -388,23 +388,23 @@ INSERT INTO `vn`.`contactChannel`(`id`, `name`) (4, 'GCN Channel'), (5, 'The Newspaper'); -INSERT INTO `vn`.`client`(`id`,`name`,`fi`,`socialName`,`contact`,`street`,`city`,`postcode`,`phone`,`mobile`,`isRelevant`,`email`,`iban`,`dueDay`,`accountingAccount`,`isEqualizated`,`provinceFk`,`hasToInvoice`,`credit`,`countryFk`,`isActive`,`gestdocFk`,`quality`,`payMethodFk`,`created`,`isToBeMailed`,`contactChannelFk`,`hasSepaVnl`,`hasCoreVnl`,`hasCoreVnh`,`riskCalculated`, `hasToInvoiceByAddress`,`isTaxDataChecked`,`isFreezed`,`creditInsurance`,`isCreatedAsServed`,`hasInvoiceSimplified`,`salesPersonFk`,`isVies`,`businessTypeFk`,`typeFk`) +INSERT INTO `vn`.`client`(`id`,`name`,`fi`,`socialName`,`contact`,`street`,`city`,`postcode`,`phone`,`mobile`,`isRelevant`,`email`,`iban`,`dueDay`,`accountingAccount`,`isEqualizated`,`provinceFk`,`hasToInvoice`,`credit`,`countryFk`,`isActive`,`quality`,`payMethodFk`,`created`,`isToBeMailed`,`contactChannelFk`,`hasSepaVnl`,`hasCoreVnl`,`hasCoreVnh`,`riskCalculated`, `hasToInvoiceByAddress`,`isTaxDataChecked`,`isFreezed`,`creditInsurance`,`isCreatedAsServed`,`hasInvoiceSimplified`,`salesPersonFk`,`isVies`,`businessTypeFk`,`typeFk`) VALUES - (1101, 'Bruce Wayne', '84612325V', 'BATMAN', 'Alfred', '1007 MOUNTAIN DRIVE, GOTHAM', 'Gotham', 46460, 1111111111, 222222222, 1, 'BruceWayne@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, NULL, 0, 0, 18, 0, 'florist','normal'), - (1102, 'Petter Parker', '87945234L', 'SPIDER MAN', 'Aunt May', '20 INGRAM STREET, QUEENS, USA', 'Gotham', 46460, 1111111111, 222222222, 1, 'PetterParker@mydomain.com', NULL, 0, 1234567890, 0, 2, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, NULL, 0, 0, 18, 0, 'florist','normal'), - (1103, 'Clark Kent', '06815934E', 'SUPER MAN', 'lois lane', '344 CLINTON STREET, APARTAMENT 3-D', 'Gotham', 46460, 1111111111, 222222222, 1, 'ClarkKent@mydomain.com', NULL, 0, 1234567890, 0, 3, 1, 0, 19, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, NULL, 0, 0, 18, 0, 'florist','normal'), - (1104, 'Tony Stark', '06089160W', 'IRON MAN', 'Pepper Potts', '10880 MALIBU POINT, 90265', 'Gotham', 46460, 1111111111, 222222222, 1, 'TonyStark@mydomain.com', NULL, 0, 1234567890, 0, 2, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, NULL, 0, 0, 18, 0, 'florist','normal'), - (1105, 'Max Eisenhardt', '251628698', 'MAGNETO', 'Rogue', 'UNKNOWN WHEREABOUTS', 'Gotham', 46460, 1111111111, 222222222, 1, 'MaxEisenhardt@mydomain.com', NULL, 0, 1234567890, 0, 3, 1, 300, 8, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, NULL, 0, 0, 18, 0, 'florist','normal'), - (1106, 'DavidCharlesHaller', '53136686Q', 'LEGION', 'Charles Xavier', 'CITY OF NEW YORK, NEW YORK, USA', 'Gotham', 46460, 1111111111, 222222222, 1, 'DavidCharlesHaller@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 0, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, NULL, 0, 0, 19, 0, 'florist','normal'), - (1107, 'Hank Pym', '09854837G', 'ANT MAN', 'Hawk', 'ANTHILL, SAN FRANCISCO, CALIFORNIA', 'Gotham', 46460, 1111111111, 222222222, 1, 'HankPym@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 0, 0, NULL, 0, 0, 19, 0, 'florist','normal'), - (1108, 'Charles Xavier', '22641921P', 'PROFESSOR X', 'Beast', '3800 VICTORY PKWY, CINCINNATI, OH 45207, USA', 'Gotham', 46460, 1111111111, 222222222, 1, 'CharlesXavier@mydomain.com', NULL, 0, 1234567890, 0, 5, 1, 300, 13, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, NULL, 0, 0, 19, 0, 'florist','normal'), - (1109, 'Bruce Banner', '16104829E', 'HULK', 'Black widow', 'SOMEWHERE IN NEW YORK', 'Gotham', 46460, 1111111111, 222222222, 1, 'BruceBanner@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 0, 0, NULL, 0, 0, 9, 0, 'florist','normal'), - (1110, 'Jessica Jones', '58282869H', 'JESSICA JONES', 'Luke Cage', 'NYCC 2015 POSTER', 'Gotham', 46460, 1111111111, 222222222, 1, 'JessicaJones@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, NULL, 0, 0, NULL, 1, 'florist','normal'), - (1111, 'Missing', NULL, 'MISSING MAN', 'Anton', 'THE SPACE, UNIVERSE FAR AWAY', 'Gotham', 46460, 1111111111, 222222222, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 0, 1, 0, NULL, 1, 0, NULL, 0, 'others','loses'), - (1112, 'Trash', NULL, 'GARBAGE MAN', 'Unknown name', 'NEW YORK CITY, UNDERGROUND', 'Gotham', 46460, 1111111111, 222222222, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 0, 1, 0, NULL, 1, 0, NULL, 0, 'others','loses'); + (1101, 'Bruce Wayne', '84612325V', 'BATMAN', 'Alfred', '1007 MOUNTAIN DRIVE, GOTHAM', 'Gotham', 46460, 1111111111, 222222222, 1, 'BruceWayne@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, NULL, 0, 0, 18, 0, 'florist','normal'), + (1102, 'Petter Parker', '87945234L', 'SPIDER MAN', 'Aunt May', '20 INGRAM STREET, QUEENS, USA', 'Gotham', 46460, 1111111111, 222222222, 1, 'PetterParker@mydomain.com', NULL, 0, 1234567890, 0, 2, 1, 300, 1, 1, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, NULL, 0, 0, 18, 0, 'florist','normal'), + (1103, 'Clark Kent', '06815934E', 'SUPER MAN', 'lois lane', '344 CLINTON STREET, APARTAMENT 3-D', 'Gotham', 46460, 1111111111, 222222222, 1, 'ClarkKent@mydomain.com', NULL, 0, 1234567890, 0, 3, 1, 0, 19, 1, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, NULL, 0, 0, 18, 0, 'florist','normal'), + (1104, 'Tony Stark', '06089160W', 'IRON MAN', 'Pepper Potts', '10880 MALIBU POINT, 90265', 'Gotham', 46460, 1111111111, 222222222, 1, 'TonyStark@mydomain.com', NULL, 0, 1234567890, 0, 2, 1, 300, 1, 1, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, NULL, 0, 0, 18, 0, 'florist','normal'), + (1105, 'Max Eisenhardt', '251628698', 'MAGNETO', 'Rogue', 'UNKNOWN WHEREABOUTS', 'Gotham', 46460, 1111111111, 222222222, 1, 'MaxEisenhardt@mydomain.com', NULL, 0, 1234567890, 0, 3, 1, 300, 8, 1, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, NULL, 0, 0, 18, 0, 'florist','normal'), + (1106, 'DavidCharlesHaller', '53136686Q', 'LEGION', 'Charles Xavier', 'CITY OF NEW YORK, NEW YORK, USA', 'Gotham', 46460, 1111111111, 222222222, 1, 'DavidCharlesHaller@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 0, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, NULL, 0, 0, 19, 0, 'florist','normal'), + (1107, 'Hank Pym', '09854837G', 'ANT MAN', 'Hawk', 'ANTHILL, SAN FRANCISCO, CALIFORNIA', 'Gotham', 46460, 1111111111, 222222222, 1, 'HankPym@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 0, 0, NULL, 0, 0, 19, 0, 'florist','normal'), + (1108, 'Charles Xavier', '22641921P', 'PROFESSOR X', 'Beast', '3800 VICTORY PKWY, CINCINNATI, OH 45207, USA', 'Gotham', 46460, 1111111111, 222222222, 1, 'CharlesXavier@mydomain.com', NULL, 0, 1234567890, 0, 5, 1, 300, 13, 1, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, NULL, 0, 0, 19, 0, 'florist','normal'), + (1109, 'Bruce Banner', '16104829E', 'HULK', 'Black widow', 'SOMEWHERE IN NEW YORK', 'Gotham', 46460, 1111111111, 222222222, 1, 'BruceBanner@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 0, 0, NULL, 0, 0, 9, 0, 'florist','normal'), + (1110, 'Jessica Jones', '58282869H', 'JESSICA JONES', 'Luke Cage', 'NYCC 2015 POSTER', 'Gotham', 46460, 1111111111, 222222222, 1, 'JessicaJones@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, NULL, 0, 0, NULL, 1, 'florist','normal'), + (1111, 'Missing', NULL, 'MISSING MAN', 'Anton', 'THE SPACE, UNIVERSE FAR AWAY', 'Gotham', 46460, 1111111111, 222222222, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 0, 1, 0, NULL, 1, 0, NULL, 0, 'others','loses'), + (1112, 'Trash', NULL, 'GARBAGE MAN', 'Unknown name', 'NEW YORK CITY, UNDERGROUND', 'Gotham', 46460, 1111111111, 222222222, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 0, 1, 0, NULL, 1, 0, NULL, 0, 'others','loses'); -INSERT INTO `vn`.`client`(`id`, `name`, `fi`, `socialName`, `contact`, `street`, `city`, `postcode`, `isRelevant`, `email`, `iban`,`dueDay`,`accountingAccount`, `isEqualizated`, `provinceFk`, `hasToInvoice`, `credit`, `countryFk`, `isActive`, `gestdocFk`, `quality`, `payMethodFk`,`created`, `isTaxDataChecked`) - SELECT id, name, CONCAT(RPAD(CONCAT(id,9),8,id),'A'), UPPER(CONCAT(name, 'Social')), CONCAT(name, 'Contact'), CONCAT(name, 'Street'), 'GOTHAM', 46460, 1, CONCAT(name,'@mydomain.com'), NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5, util.VN_CURDATE(), 1 +INSERT INTO `vn`.`client`(`id`, `name`, `fi`, `socialName`, `contact`, `street`, `city`, `postcode`, `isRelevant`, `email`, `iban`,`dueDay`,`accountingAccount`, `isEqualizated`, `provinceFk`, `hasToInvoice`, `credit`, `countryFk`, `isActive`, `quality`, `payMethodFk`,`created`, `isTaxDataChecked`) + SELECT id, name, CONCAT(RPAD(CONCAT(id,9),8,id),'A'), UPPER(CONCAT(name, 'Social')), CONCAT(name, 'Contact'), CONCAT(name, 'Street'), 'GOTHAM', 46460, 1, CONCAT(name,'@mydomain.com'), NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, 10, 5, util.VN_CURDATE(), 1 FROM `account`.`role` `r` WHERE `r`.`hasLogin` = 1; diff --git a/db/routines/vn/procedures/saleTracking_sectorCollectionAddPrevOK.sql b/db/routines/vn/procedures/saleTracking_sectorCollectionAddPrevOK.sql new file mode 100644 index 000000000..003168ec8 --- /dev/null +++ b/db/routines/vn/procedures/saleTracking_sectorCollectionAddPrevOK.sql @@ -0,0 +1,20 @@ +DELIMITER $$ +CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`saleTracking_sectorCollectionAddPrevOK`( + vSectorCollectionFk INT +) +BEGIN +/** + * Inserta los registros de sectorCollection con el estado PREVIA OK si la reserva está picked + * + * @param vSectorCollectionFk Identificador de vn.sectorCollection + */ + REPLACE saleTracking(saleFk, isChecked, workerFk, stateFk) + SELECT sgd.saleFk, TRUE, sc.userFk, s.id + 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 AND iss.isPicked; +END$$ +DELIMITER ; diff --git a/db/routines/vn/procedures/ticket_getTax.sql b/db/routines/vn/procedures/ticket_getTax.sql index 947c45806..cb9dc09d9 100644 --- a/db/routines/vn/procedures/ticket_getTax.sql +++ b/db/routines/vn/procedures/ticket_getTax.sql @@ -1,5 +1,7 @@ DELIMITER $$ -CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`ticket_getTax`(IN vTaxArea VARCHAR(25)) +CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`ticket_getTax`( + vTaxArea VARCHAR(25) +) BEGIN /** * Calcula la base imponible, el IVA y el recargo de equivalencia para @@ -33,30 +35,39 @@ BEGIN CREATE OR REPLACE TEMPORARY TABLE tmp.ticketTax (PRIMARY KEY (ticketFk, code, rate)) ENGINE = MEMORY - SELECT * FROM ( - SELECT tmpTicket.ticketFk, - bp.pgcFk, - SUM(s.quantity * s.price * (100 - s.discount) / 100 ) taxableBase, - pgc.rate, - tc.code, - bp.priority - FROM tmp.ticket tmpTicket - JOIN sale s ON s.ticketFk = tmpTicket.ticketFk - JOIN item i ON i.id = s.itemFk - JOIN ticket t ON t.id = tmpTicket.ticketFk - JOIN supplier su ON su.id = t.companyFk + WITH sales AS ( + SELECT s.ticketFk, + s.itemFk, + s.quantity * s.price * (100 - s.discount) / 100 total, + t.companyFk, + t.addressFk, + su.countryFk, + ata.areaFk, + itc.taxClassFk + FROM vn.sale s + JOIN tmp.ticket tmp ON tmp.ticketFk = s.ticketFk + JOIN vn.ticket t ON t.id = s.ticketFk + JOIN vn.supplier su ON su.id = t.companyFk JOIN tmp.addressTaxArea ata ON ata.addressFk = t.addressFk AND ata.companyFk = t.companyFk - JOIN itemTaxCountry itc ON itc.itemFk = i.id + JOIN vn.itemTaxCountry itc ON itc.itemFk = s.itemFk AND itc.countryFk = su.countryFk - JOIN bookingPlanner bp ON bp.countryFk = su.countryFk - AND bp.taxAreaFk = ata.areaFk - AND bp.taxClassFk = itc.taxClassFk - JOIN pgc ON pgc.code = bp.pgcFk - JOIN taxClass tc ON tc.id = bp.taxClassFk - GROUP BY tmpTicket.ticketFk, pgc.code, pgc.rate - HAVING taxableBase - ) t3 + HAVING total + ) + SELECT s.ticketFk, + bp.pgcFk, + SUM(s.total) taxableBase, + pgc.rate, + tc.code, + bp.priority + FROM sales s + JOIN vn.bookingPlanner bp ON bp.countryFk = s.countryFk + AND bp.taxAreaFk = s.areaFk + AND bp.taxClassFk = s.taxClassFk + JOIN vn.pgc ON pgc.code = bp.pgcFk + JOIN vn.taxClass tc ON tc.id = bp.taxClassFk + GROUP BY s.ticketFk, pgc.code, pgc.rate + HAVING taxableBase ORDER BY priority; CREATE OR REPLACE TEMPORARY TABLE tmp.ticketServiceTax diff --git a/db/routines/vn/triggers/itemShelvingSale_afterInsert.sql b/db/routines/vn/triggers/itemShelvingSale_afterInsert.sql index 3531b094c..ad4a6f670 100644 --- a/db/routines/vn/triggers/itemShelvingSale_afterInsert.sql +++ b/db/routines/vn/triggers/itemShelvingSale_afterInsert.sql @@ -3,10 +3,10 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`itemShelvingSale_afterI AFTER INSERT ON `itemShelvingSale` FOR EACH ROW BEGIN - UPDATE sale s JOIN operator o ON o.workerFk = account.myUser_getId() - SET s.isPicked = IF(o.isOnReservationMode, s.isPicked, TRUE) - WHERE id = NEW.saleFk; + JOIN sector se ON se.id = o.sectorFk + SET s.isPicked = IF(IFNULL(se.isOnReservationMode, o.isOnReservationMode), s.isPicked, TRUE) + WHERE s.id = NEW.saleFk; END$$ DELIMITER ; \ No newline at end of file diff --git a/db/routines/vn2008/views/Clientes.sql b/db/routines/vn2008/views/Clientes.sql index 153d875bc..9f8ef712e 100644 --- a/db/routines/vn2008/views/Clientes.sql +++ b/db/routines/vn2008/views/Clientes.sql @@ -22,7 +22,6 @@ AS SELECT `c`.`id` AS `id_cliente`, `c`.`credit` AS `credito`, `c`.`countryFk` AS `Id_Pais`, `c`.`isActive` AS `activo`, - `c`.`gestdocFk` AS `gestdoc_id`, `c`.`quality` AS `calidad`, `c`.`payMethodFk` AS `pay_met_id`, `c`.`created` AS `created`, diff --git a/db/versions/11290-blackOrchid/00-firstScript.sql b/db/versions/11290-blackOrchid/00-firstScript.sql new file mode 100644 index 000000000..fe568ed6e --- /dev/null +++ b/db/versions/11290-blackOrchid/00-firstScript.sql @@ -0,0 +1,6 @@ +ALTER TABLE `vn`.`operator` +ADD COLUMN `machineFk` int(11) DEFAULT NULL, +ADD CONSTRAINT `operator_machine_FK` FOREIGN KEY (`machineFk`) REFERENCES `vn`.`machine` (`id`) ON DELETE SET NULL ON UPDATE CASCADE; + +INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId) + VALUES ('Machine','*','*','ALLOW','ROLE','productionBoss'); diff --git a/db/versions/11291-purpleChico/00-firstScript.sql b/db/versions/11291-purpleChico/00-firstScript.sql new file mode 100644 index 000000000..e60b90376 --- /dev/null +++ b/db/versions/11291-purpleChico/00-firstScript.sql @@ -0,0 +1,4 @@ +ALTER TABLE vn.docuwareConfig ADD IF NOT EXISTS username varchar(100) NULL; +ALTER TABLE vn.docuwareConfig ADD IF NOT EXISTS password varchar(100) NULL; +ALTER TABLE vn.docuwareConfig ADD IF NOT EXISTS token text NULL; +ALTER TABLE vn.docuwareConfig ADD IF NOT EXISTS expired int(11) NULL; diff --git a/db/versions/11311-tealFern/00-firstScript.sql b/db/versions/11311-tealFern/00-firstScript.sql new file mode 100644 index 000000000..909747f3c --- /dev/null +++ b/db/versions/11311-tealFern/00-firstScript.sql @@ -0,0 +1 @@ +ALTER TABLE vn.client CHANGE gestdocFk gestdocFk__ int(11) DEFAULT NULL NULL COMMENT '@deprecated 2024-10-17'; \ No newline at end of file diff --git a/loopback/locale/en.json b/loopback/locale/en.json index ea84cb6eb..a7e21960b 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -240,5 +240,6 @@ "There is already a tray with the same height": "There is already a tray with the same height", "The height must be greater than 50cm": "The height must be greater than 50cm", "The maximum height of the wagon is 200cm": "The maximum height of the wagon is 200cm", - "The quantity claimed cannot be greater than the quantity of the line": "The quantity claimed cannot be greater than the quantity of the line" + "The quantity claimed cannot be greater than the quantity of the line": "The quantity claimed cannot be greater than the quantity of the line", + "There are tickets for this area, delete them first": "There are tickets for this area, delete them first" } diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 9308fd4ec..6d50f634e 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -382,5 +382,6 @@ "This buyer has already made a reservation for this date": "Este comprador ya ha hecho una reserva para esta fecha", "No valid travel thermograph found": "No se encontró un termógrafo válido", "The quantity claimed cannot be greater than the quantity of the line": "La cantidad reclamada no puede ser mayor que la cantidad de la línea", - "type cannot be blank": "Se debe rellenar el tipo" -} \ No newline at end of file + "type cannot be blank": "Se debe rellenar el tipo", + "There are tickets for this area, delete them first": "Hay tickets para esta sección, borralos primero" +} diff --git a/modules/invoiceOut/back/methods/invoiceOut/negativeBases.js b/modules/invoiceOut/back/methods/invoiceOut/negativeBases.js index 76ef29604..9e491b35c 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/negativeBases.js +++ b/modules/invoiceOut/back/methods/invoiceOut/negativeBases.js @@ -48,13 +48,13 @@ module.exports = Self => { let stmt; stmts.push(new ParameterizedSQL( `CREATE OR REPLACE TEMPORARY TABLE tmp.ticket - (KEY (ticketFk)) + (INDEX (ticketFk)) ENGINE = MEMORY SELECT id ticketFk - FROM ticket t + FROM ticket WHERE shipped BETWEEN ? AND util.dayEnd(?) AND refFk IS NULL`, [args.from, args.to])); - stmts.push(`CALL vn.ticket_getTax(NULL)`); + stmts.push(`CALL ticket_getTax(NULL)`); stmts.push(new ParameterizedSQL( `CREATE OR REPLACE TEMPORARY TABLE tmp.filter ENGINE = MEMORY @@ -71,12 +71,12 @@ module.exports = Self => { c.isTaxDataChecked, w.id comercialId, u.name workerName - FROM vn.ticket t - JOIN vn.company co ON co.id = t.companyFk - JOIN vn.sale s ON s.ticketFk = t.id - JOIN vn.client c ON c.id = t.clientFk - JOIN vn.country cou ON cou.id = c.countryFk - LEFT JOIN vn.worker w ON w.id = c.salesPersonFk + FROM ticket t + JOIN company co ON co.id = t.companyFk + JOIN sale s ON s.ticketFk = t.id + JOIN client c ON c.id = t.clientFk + JOIN country cou ON cou.id = c.countryFk + LEFT JOIN worker w ON w.id = c.salesPersonFk JOIN account.user u ON u.id = w.id LEFT JOIN ( SELECT ticketFk, taxableBase diff --git a/modules/ticket/back/methods/ticket/filter.js b/modules/ticket/back/methods/ticket/filter.js index 06781c3c8..d3e53c702 100644 --- a/modules/ticket/back/methods/ticket/filter.js +++ b/modules/ticket/back/methods/ticket/filter.js @@ -228,52 +228,57 @@ module.exports = Self => { stmt = new ParameterizedSQL(` CREATE OR REPLACE TEMPORARY TABLE tmp.filter (INDEX (id)) - ENGINE = MEMORY + ENGINE = InnoDB SELECT t.id, - t.shipped, - CAST(DATE(t.shipped) AS CHAR) shippedDate, - HOUR(t.shipped) shippedHour, - t.nickname, - t.refFk, - t.routeFk, - t.warehouseFk, - t.clientFk, - t.totalWithoutVat, - t.totalWithVat, - io.id invoiceOutId, - a.provinceFk, - p.name province, - w.name warehouse, - am.name agencyMode, - am.id agencyModeFk, - st.name state, - st.classColor, - wk.lastName salesPerson, - ts.stateFk stateFk, - ts.alertLevel alertLevel, - ts.code alertLevelCode, - u.name userName, - c.salesPersonFk, - z.hour zoneLanding, - HOUR(z.hour) zoneHour, - MINUTE(z.hour) zoneMinute, - z.name zoneName, - z.id zoneFk, - CAST(z.hour AS CHAR) hour, - a.nickname addressNickname - FROM ticket t - LEFT JOIN invoiceOut io ON t.refFk = io.ref - LEFT JOIN zone z ON z.id = t.zoneFk - LEFT JOIN address a ON a.id = t.addressFk - LEFT JOIN province p ON p.id = a.provinceFk - LEFT JOIN warehouse w ON w.id = t.warehouseFk - LEFT JOIN agencyMode am ON am.id = t.agencyModeFk - LEFT JOIN ticketState ts ON ts.ticketFk = t.id - LEFT JOIN state st ON st.id = ts.stateFk - LEFT JOIN client c ON c.id = t.clientFk - LEFT JOIN worker wk ON wk.id = c.salesPersonFk - LEFT JOIN account.user u ON u.id = wk.id - LEFT JOIN route r ON r.id = t.routeFk + t.shipped, + CAST(DATE(t.shipped) AS CHAR) shippedDate, + HOUR(t.shipped) shippedHour, + t.nickname, + t.refFk, + t.routeFk, + t.warehouseFk, + t.clientFk, + t.totalWithoutVat, + t.totalWithVat, + io.id invoiceOutId, + a.provinceFk, + p.name province, + w.name warehouse, + am.name agencyMode, + am.id agencyModeFk, + st.name state, + st.classColor, + wk.lastName salesPerson, + ts.stateFk stateFk, + ts.alertLevel alertLevel, + ts.code alertLevelCode, + u.name userName, + c.salesPersonFk, + z.hour zoneLanding, + HOUR(z.hour) zoneHour, + MINUTE(z.hour) zoneMinute, + z.name zoneName, + z.id zoneFk, + CAST(z.hour AS CHAR) hour, + a.nickname addressNickname, + (SELECT GROUP_CONCAT(DISTINCT i2.itemPackingTypeFk ORDER BY i2.itemPackingTypeFk SEPARATOR ',') + FROM sale s2 + JOIN item i2 ON i2.id = s2.itemFk + WHERE s2.ticketFk = t.id + ) AS packing + FROM ticket t + LEFT JOIN invoiceOut io ON t.refFk = io.ref + LEFT JOIN zone z ON z.id = t.zoneFk + LEFT JOIN address a ON a.id = t.addressFk + LEFT JOIN province p ON p.id = a.provinceFk + LEFT JOIN warehouse w ON w.id = t.warehouseFk + LEFT JOIN agencyMode am ON am.id = t.agencyModeFk + LEFT JOIN ticketState ts ON ts.ticketFk = t.id + LEFT JOIN state st ON st.id = ts.stateFk + LEFT JOIN client c ON c.id = t.clientFk + LEFT JOIN worker wk ON wk.id = c.salesPersonFk + LEFT JOIN account.user u ON u.id = wk.id + LEFT JOIN route r ON r.id = t.routeFk `); if (args.orderFk) { @@ -292,6 +297,7 @@ module.exports = Self => { } stmt.merge(conn.makeWhere(filter.where)); + stmts.push(stmt); stmt = new ParameterizedSQL(` diff --git a/modules/worker/back/models/operator.json b/modules/worker/back/models/operator.json index d4832bccf..b75bf6732 100644 --- a/modules/worker/back/models/operator.json +++ b/modules/worker/back/models/operator.json @@ -24,13 +24,28 @@ "warehouseFk": { "type": "number" }, + "sectorFk": { + "type": "number" + }, "labelerFk": { "type": "number" }, "isOnReservationMode": { "type": "boolean", "required": true - } + }, + "machineFk": { + "type": "number" + }, + "linesLimit": { + "type": "number" + }, + "volumeLimit": { + "type": "number" + }, + "sizeLimit": { + "type": "number" + } }, "relations": { "sector": { @@ -53,6 +68,11 @@ "model": "ItemPackingType", "foreignKey": "itemPackingTypeFk", "primaryKey": "code" - } + }, + "machine": { + "type": "belongsTo", + "model": "Machine", + "foreignKey": "machineFk" + } } -} \ No newline at end of file +} diff --git a/modules/zone/back/methods/zone/deleteZone.js b/modules/zone/back/methods/zone/deleteZone.js index a75302703..ffe23c9b9 100644 --- a/modules/zone/back/methods/zone/deleteZone.js +++ b/modules/zone/back/methods/zone/deleteZone.js @@ -1,3 +1,4 @@ +const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { Self.remoteMethodCtx('deleteZone', { description: 'Delete a zone', @@ -49,26 +50,12 @@ module.exports = Self => { } } }; - const promises = []; const ticketList = await models.Ticket.find(filter, myOptions); - const fixingState = await models.State.findOne({where: {code: 'FIXING'}}, myOptions); - const worker = await models.Worker.findOne({ - where: {id: userId} - }, myOptions); - await models.Ticket.rawSql('UPDATE ticket SET zoneFk = NULL WHERE zoneFk = ?', [id], myOptions); + if (ticketList.length > 0) + throw new UserError('There are tickets for this area, delete them first'); - for (ticket of ticketList) { - if (ticket.ticketState().alertLevel == 0) { - promises.push(models.Ticket.state(ctx, { - ticketFk: ticket.id, - stateFk: fixingState.id, - userFk: worker.id - }, myOptions)); - } - } - await Promise.all(promises); await models.Zone.destroyById(id, myOptions); if (tx) await tx.commit(); diff --git a/modules/zone/back/methods/zone/specs/deleteZone.spec.js b/modules/zone/back/methods/zone/specs/deleteZone.spec.js index 08dafd181..aef7fd290 100644 --- a/modules/zone/back/methods/zone/specs/deleteZone.spec.js +++ b/modules/zone/back/methods/zone/specs/deleteZone.spec.js @@ -8,9 +8,9 @@ describe('zone deletezone()', () => { __: value => value }; const ctx = {req: activeCtx}; - const zoneId = 9; + const zoneId = 4; + const zoneId2 = 3; let ticketIDs; - let originalTicketStates; beforeAll(async() => { spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ @@ -35,18 +35,8 @@ describe('zone deletezone()', () => { await models.Zone.deleteZone(ctx, zoneId, options); const updatedZone = await models.Zone.findById(zoneId, null, options); - const anUpdatedTicket = await models.Ticket.findById(ticketIDs[0], null, options); - - const updatedTicketStates = await models.TicketState.find({ - where: { - ticketFk: {inq: ticketIDs}, - code: 'FIXING' - } - }, options); expect(updatedZone).toBeNull(); - expect(anUpdatedTicket.zoneFk).toBeNull(); - expect(updatedTicketStates.length).toBeGreaterThan(originalTicketStates.length); await tx.rollback(); } catch (e) { @@ -54,4 +44,20 @@ describe('zone deletezone()', () => { throw e; } }); + + it('should not delete the zone if it has tickets', async() => { + const tx = await models.Zone.beginTransaction({}); + + let error; + try { + const options = {transaction: tx}; + await models.Zone.deleteZone(ctx, zoneId2, options); + await tx.rollback(); + } catch (e) { + error = e.message; + await tx.rollback(); + } + + expect(error).toEqual('There are tickets for this area, delete them first'); + }); }); diff --git a/print/templates/reports/delivery-note/delivery-note.html b/print/templates/reports/delivery-note/delivery-note.html index c1701e084..89bc07488 100644 --- a/print/templates/reports/delivery-note/delivery-note.html +++ b/print/templates/reports/delivery-note/delivery-note.html @@ -58,6 +58,7 @@