diff --git a/back/methods/docuware/checkFile.js b/back/methods/docuware/checkFile.js new file mode 100644 index 000000000..c6712bb65 --- /dev/null +++ b/back/methods/docuware/checkFile.js @@ -0,0 +1,93 @@ +const got = require('got'); + +module.exports = Self => { + Self.remoteMethodCtx('checkFile', { + description: 'Check if exist docuware file', + accessType: 'READ', + accepts: [ + { + arg: 'id', + type: 'number', + description: 'The id', + http: {source: 'path'} + }, + { + arg: 'fileCabinet', + type: 'string', + required: true, + description: 'The fileCabinet name' + }, + { + arg: 'dialog', + type: 'string', + required: true, + description: 'The dialog name' + } + ], + returns: { + type: 'boolean', + root: true + }, + http: { + path: `/:id/checkFile`, + verb: 'POST' + } + }); + + Self.checkFile = async function(ctx, id, fileCabinet, dialog) { + const myUserId = ctx.req.accessToken.userId; + if (!myUserId) + return false; + + const models = Self.app.models; + const docuwareConfig = await models.DocuwareConfig.findOne(); + const docuwareInfo = await models.Docuware.findOne({ + where: { + code: fileCabinet, + dialogName: dialog + } + }); + + const docuwareUrl = docuwareConfig.url; + const cookie = docuwareConfig.token; + const fileCabinetName = docuwareInfo.fileCabinetName; + const find = docuwareInfo.find; + const options = { + 'headers': { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'Cookie': cookie + } + }; + const searchFilter = { + condition: [ + { + DBName: find, + Value: [id] + } + ] + }; + + try { + // get fileCabinetId + const fileCabinetResponse = await got.get(`${docuwareUrl}/FileCabinets`, options); + const fileCabinetJson = JSON.parse(fileCabinetResponse.body).FileCabinet; + const fileCabinetId = fileCabinetJson.find(dialogs => dialogs.Name === fileCabinetName).Id; + + // get dialog + const dialogResponse = await got.get(`${docuwareUrl}/FileCabinets/${fileCabinetId}/dialogs`, options); + const dialogJson = JSON.parse(dialogResponse.body).Dialog; + const dialogId = dialogJson.find(dialogs => dialogs.DisplayName === 'find').Id; + + // get docuwareID + Object.assign(options, {'body': JSON.stringify(searchFilter)}); + const response = await got.post( + `${docuwareUrl}/FileCabinets/${fileCabinetId}/Query/DialogExpression?dialogId=${dialogId}`, options); + JSON.parse(response.body).Items[0].Id; + + return true; + } catch (error) { + return false; + } + }; +}; diff --git a/back/methods/docuware/download.js b/back/methods/docuware/download.js new file mode 100644 index 000000000..489a07e34 --- /dev/null +++ b/back/methods/docuware/download.js @@ -0,0 +1,120 @@ +/* eslint max-len: ["error", { "code": 180 }]*/ +const got = require('got'); +const UserError = require('vn-loopback/util/user-error'); + +module.exports = Self => { + Self.remoteMethodCtx('download', { + description: 'Download an docuware PDF', + accessType: 'READ', + accepts: [ + { + arg: 'id', + type: 'number', + description: 'The id', + http: {source: 'path'} + }, + { + arg: 'fileCabinet', + type: 'string', + description: 'The id', + http: {source: 'path'} + }, + { + arg: 'dialog', + type: 'string', + description: 'The id', + http: {source: 'path'} + } + ], + returns: [ + { + arg: 'body', + type: 'file', + root: true + }, { + arg: 'Content-Type', + type: 'string', + http: {target: 'header'} + }, { + arg: 'Content-Disposition', + type: 'string', + http: {target: 'header'} + } + ], + http: { + path: `/:id/download/:fileCabinet/:dialog`, + verb: 'GET' + } + }); + + Self.download = async function(ctx, id, fileCabinet, dialog) { + const myUserId = ctx.req.accessToken.userId; + if (!myUserId) + throw new UserError(`You don't have enough privileges`); + + const models = Self.app.models; + const docuwareConfig = await models.DocuwareConfig.findOne(); + const docuwareInfo = await models.Docuware.findOne({ + where: { + code: fileCabinet, + dialogName: dialog + } + }); + + const docuwareUrl = docuwareConfig.url; + const cookie = docuwareConfig.token; + const fileCabinetName = docuwareInfo.fileCabinetName; + const find = docuwareInfo.find; + const options = { + 'headers': { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'Cookie': cookie + } + }; + const searchFilter = { + condition: [ + { + DBName: find, + Value: [id] + } + ] + }; + + try { + // get fileCabinetId + const fileCabinetResponse = await got.get(`${docuwareUrl}/FileCabinets`, options); + const fileCabinetJson = JSON.parse(fileCabinetResponse.body).FileCabinet; + const fileCabinetId = fileCabinetJson.find(dialogs => dialogs.Name === fileCabinetName).Id; + + // get dialog + const dialogResponse = await got.get(`${docuwareUrl}/FileCabinets/${fileCabinetId}/dialogs`, options); + const dialogJson = JSON.parse(dialogResponse.body).Dialog; + const dialogId = dialogJson.find(dialogs => dialogs.DisplayName === 'find').Id; + + // get docuwareID + Object.assign(options, {'body': JSON.stringify(searchFilter)}); + const response = await got.post(`${docuwareUrl}/FileCabinets/${fileCabinetId}/Query/DialogExpression?dialogId=${dialogId}`, options); + const docuwareId = JSON.parse(response.body).Items[0].Id; + + // download & save file + const fileName = `filename="${id}.pdf"`; + const contentType = 'application/pdf'; + const downloadUri = `${docuwareUrl}/FileCabinets/${fileCabinetId}/Documents/${docuwareId}/FileDownload?targetFileType=Auto&keepAnnotations=false`; + const downloadOptions = { + 'headers': { + 'Cookie': cookie + } + }; + + const stream = got.stream(downloadUri, downloadOptions); + + return [stream, contentType, fileName]; + } catch (error) { + if (error.code === 'ENOENT') + throw new UserError('The DOCUWARE PDF document does not exists'); + + throw error; + } + }; +}; diff --git a/back/methods/docuware/specs/checkFile.spec.js b/back/methods/docuware/specs/checkFile.spec.js new file mode 100644 index 000000000..2ebde0df4 --- /dev/null +++ b/back/methods/docuware/specs/checkFile.spec.js @@ -0,0 +1,64 @@ +const models = require('vn-loopback/server/server').models; +const got = require('got'); + +describe('docuware download()', () => { + const ticketId = 1; + const userId = 9; + const ctx = { + req: { + + accessToken: {userId: userId}, + headers: {origin: 'http://localhost:5000'}, + } + }; + + const fileCabinetName = 'deliveryClientTest'; + const dialogDisplayName = 'find'; + const dialogName = 'findTest'; + + const gotGetResponse = { + body: JSON.stringify( + { + FileCabinet: [ + {Id: 12, Name: fileCabinetName} + ], + Dialog: [ + {Id: 34, DisplayName: dialogDisplayName} + ] + }) + }; + + it('should return exist file in docuware', async() => { + const gotPostResponse = { + body: JSON.stringify( + { + Items: [ + {Id: 56} + ], + }) + }; + + spyOn(got, 'get').and.returnValue(new Promise(resolve => resolve(gotGetResponse))); + spyOn(got, 'post').and.returnValue(new Promise(resolve => resolve(gotPostResponse))); + + const result = await models.Docuware.checkFile(ctx, ticketId, fileCabinetName, dialogName); + + expect(result).toEqual(true); + }); + + it('should return not exist file in docuware', async() => { + const gotPostResponse = { + body: JSON.stringify( + { + Items: [], + }) + }; + + spyOn(got, 'get').and.returnValue(new Promise(resolve => resolve(gotGetResponse))); + spyOn(got, 'post').and.returnValue(new Promise(resolve => resolve(gotPostResponse))); + + const result = await models.Docuware.checkFile(ctx, ticketId, fileCabinetName, dialogName); + + expect(result).toEqual(false); + }); +}); diff --git a/back/methods/docuware/specs/download.spec.js b/back/methods/docuware/specs/download.spec.js new file mode 100644 index 000000000..436063fd8 --- /dev/null +++ b/back/methods/docuware/specs/download.spec.js @@ -0,0 +1,50 @@ +const models = require('vn-loopback/server/server').models; +const got = require('got'); +const stream = require('stream'); + +describe('docuware download()', () => { + const userId = 9; + const ticketId = 1; + const ctx = { + req: { + + accessToken: {userId: userId}, + headers: {origin: 'http://localhost:5000'}, + } + }; + + it('should return the downloaded file name', async() => { + const fileCabinetName = 'deliveryClientTest'; + const dialogDisplayName = 'find'; + const dialogName = 'findTest'; + const gotGetResponse = { + body: JSON.stringify( + { + FileCabinet: [ + {Id: 12, Name: fileCabinetName} + ], + Dialog: [ + {Id: 34, DisplayName: dialogDisplayName} + ] + }) + }; + + const gotPostResponse = { + body: JSON.stringify( + { + Items: [ + {Id: 56} + ], + }) + }; + + spyOn(got, 'get').and.returnValue(new Promise(resolve => resolve(gotGetResponse))); + spyOn(got, 'post').and.returnValue(new Promise(resolve => resolve(gotPostResponse))); + spyOn(got, 'stream').and.returnValue(new stream.PassThrough({objectMode: true})); + + const result = await models.Docuware.download(ctx, ticketId, fileCabinetName, dialogName); + + expect(result[1]).toEqual('application/pdf'); + expect(result[2]).toEqual(`filename="${ticketId}.pdf"`); + }); +}); diff --git a/back/model-config.json b/back/model-config.json index 8ad15a16a..4c79d565b 100644 --- a/back/model-config.json +++ b/back/model-config.json @@ -44,6 +44,12 @@ "DmsType": { "dataSource": "vn" }, + "Docuware": { + "dataSource": "vn" + }, + "DocuwareConfig": { + "dataSource": "vn" + }, "EmailUser": { "dataSource": "vn" }, diff --git a/back/models/docuware-config.json b/back/models/docuware-config.json new file mode 100644 index 000000000..8ca76d8ba --- /dev/null +++ b/back/models/docuware-config.json @@ -0,0 +1,32 @@ +{ + "name": "DocuwareConfig", + "description": "Docuware config", + "base": "VnModel", + "options": { + "mysql": { + "table": "docuwareConfig" + } + }, + "properties": { + "id": { + "type": "number", + "id": true, + "description": "Identifier" + }, + "url": { + "type": "string" + }, + "token": { + "type": "string" + } + }, + "acls": [ + { + "property": "*", + "accessType": "*", + "principalType": "ROLE", + "principalId": "$everyone", + "permission": "ALLOW" + } + ] +} \ No newline at end of file diff --git a/back/models/docuware.js b/back/models/docuware.js new file mode 100644 index 000000000..8fd8065ed --- /dev/null +++ b/back/models/docuware.js @@ -0,0 +1,4 @@ +module.exports = Self => { + require('../methods/docuware/download')(Self); + require('../methods/docuware/checkFile')(Self); +}; diff --git a/back/models/docuware.json b/back/models/docuware.json new file mode 100644 index 000000000..fb2ed919e --- /dev/null +++ b/back/models/docuware.json @@ -0,0 +1,38 @@ +{ + "name": "Docuware", + "description": "Docuware sections", + "base": "VnModel", + "options": { + "mysql": { + "table": "docuware" + } + }, + "properties": { + "id": { + "type": "number", + "id": true, + "description": "Identifier" + }, + "code": { + "type": "string" + }, + "fileCabinetName": { + "type": "string" + }, + "dialogName": { + "type": "string" + }, + "find": { + "type": "string" + } + }, + "acls": [ + { + "property": "*", + "accessType": "*", + "principalType": "ROLE", + "principalId": "$everyone", + "permission": "ALLOW" + } + ] +} \ No newline at end of file diff --git a/db/changes/10420-valentines/00-aclDocuware.sql b/db/changes/10420-valentines/00-aclDocuware.sql new file mode 100644 index 000000000..21ed66c4c --- /dev/null +++ b/db/changes/10420-valentines/00-aclDocuware.sql @@ -0,0 +1,3 @@ +INSERT INTO salix.ACL +(model, property, accessType, permission, principalType, principalId) +VALUES('Docuware', '*', '*', 'ALLOW', 'ROLE', 'employee'); \ No newline at end of file diff --git a/db/changes/10420-valentines/00-docuware.sql b/db/changes/10420-valentines/00-docuware.sql new file mode 100644 index 000000000..7cabd135f --- /dev/null +++ b/db/changes/10420-valentines/00-docuware.sql @@ -0,0 +1,11 @@ +CREATE TABLE `vn`.`docuware` ( + `id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, + `code` varchar(50) NULL, + `fileCabinetName` varchar(50) NULL, + `dialogName` varchar(255) DEFAULT NULL, + `find` varchar(50) DEFAULT NULL +); + +INSERT INTO `vn`.`docuware` (`code`, `fileCabinetName`, `dialogName` , `find`) + VALUES + ('deliveryClient', 'Albaranes cliente', 'findTicket', 'N__ALBAR_N'); \ No newline at end of file diff --git a/db/changes/10420-valentines/00-docuwareConfig.sql b/db/changes/10420-valentines/00-docuwareConfig.sql new file mode 100644 index 000000000..1ba19af6d --- /dev/null +++ b/db/changes/10420-valentines/00-docuwareConfig.sql @@ -0,0 +1,9 @@ +CREATE TABLE `vn`.`docuwareConfig` ( + `id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, + `url` varchar(75) NULL, + `token` varchar(1000) DEFAULT NULL +); + +INSERT INTO `vn`.`docuwareConfig` (`url`) + VALUES + ('https://verdnatura.docuware.cloud/docuware/platform'); \ No newline at end of file diff --git a/db/changes/10411-january/00-ticket_getMovable.sql b/db/changes/10420-valentines/00-ticket_getMovable.sql similarity index 77% rename from db/changes/10411-january/00-ticket_getMovable.sql rename to db/changes/10420-valentines/00-ticket_getMovable.sql index 5f5b0a93a..eb5c722c4 100644 --- a/db/changes/10411-january/00-ticket_getMovable.sql +++ b/db/changes/10420-valentines/00-ticket_getMovable.sql @@ -6,20 +6,23 @@ CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`ticket_getMovable`(vTicketFk INT, vDat BEGIN /** * Cálcula el stock movible para los artículos de un ticket + * vDatedNew debe ser menor que vDatedOld, en los otros casos se + * asume que siempre es posible * * @param vTicketFk -> Ticket * @param vDatedNew -> Nueva fecha * @return Sales con Movible */ DECLARE vDatedOld DATETIME; - + SET vDatedNew = DATE_ADD(vDatedNew, INTERVAL 1 DAY); + SELECT t.shipped INTO vDatedOld FROM ticket t WHERE t.id = vTicketFk; - CALL itemStock(vWarehouseFk, DATE_SUB(vDatedNew, INTERVAL 1 DAY), NULL); - CALL item_getMinacum(vWarehouseFk, vDatedNew, DATEDIFF(vDatedOld, vDatedNew), NULL); - + CALL itemStock(vWarehouseFk, vDatedNew, NULL); + CALL item_getMinacum(vWarehouseFk, vDatedNew, DATEDIFF(DATE_SUB(vDatedOld, INTERVAL 1 DAY), vDatedNew), NULL); + SELECT s.id, s.itemFk, s.quantity, diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 07eaf23fd..20298677a 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -2443,3 +2443,11 @@ INSERT INTO `bs`.`defaulter` (`clientFk`, `amount`, `created`, `defaulterSinced` (1103, 500, CURDATE(), CURDATE()), (1107, 500, CURDATE(), CURDATE()), (1109, 500, CURDATE(), CURDATE()); + +INSERT INTO `vn`.`docuware` (`code`, `fileCabinetName`, `dialogName` , `find`) + VALUES + ('deliveryClientTest', 'deliveryClientTest', 'findTest', 'word'); + +INSERT INTO `vn`.`docuwareConfig` (`url`) + VALUES + ('https://verdnatura.docuware.cloud/docuware/platform'); \ No newline at end of file diff --git a/modules/account/back/models/role-config.js b/modules/account/back/models/role-config.js index c6b32a4c5..6051f2060 100644 --- a/modules/account/back/models/role-config.js +++ b/modules/account/back/models/role-config.js @@ -1,6 +1,10 @@ module.exports = Self => { Self.getSynchronizer = async function() { + let NODE_ENV = process.env.NODE_ENV; + if (!NODE_ENV || NODE_ENV == 'development') + return null; + return await Self.findOne({ fields: ['id', 'rolePrefix', 'userPrefix', 'userHost'] }); diff --git a/modules/client/back/methods/client/specs/sendSms.spec.js b/modules/client/back/methods/client/specs/sendSms.spec.js index 121d427ce..54fe802e3 100644 --- a/modules/client/back/methods/client/specs/sendSms.spec.js +++ b/modules/client/back/methods/client/specs/sendSms.spec.js @@ -1,7 +1,8 @@ const models = require('vn-loopback/server/server').models; const soap = require('soap'); -describe('client sendSms()', () => { +// #3673 sendSms tests excluded +xdescribe('client sendSms()', () => { it('should now send a message and log it', async() => { spyOn(soap, 'createClientAsync').and.returnValue('a so fake client'); const tx = await models.Client.beginTransaction({}); diff --git a/modules/client/back/methods/sms/send.spec.js b/modules/client/back/methods/sms/send.spec.js index 7ca78b214..a81c24e96 100644 --- a/modules/client/back/methods/sms/send.spec.js +++ b/modules/client/back/methods/sms/send.spec.js @@ -1,6 +1,7 @@ const app = require('vn-loopback/server/server'); -describe('sms send()', () => { +// #3673 sendSms tests excluded +xdescribe('sms send()', () => { it('should not return status error', async() => { const ctx = {req: {accessToken: {userId: 1}}}; const result = await app.models.Sms.send(ctx, 1105, '123456789', 'My SMS Body'); diff --git a/modules/invoiceOut/front/descriptor-menu/index.html b/modules/invoiceOut/front/descriptor-menu/index.html index 3b30f891c..859486ab1 100644 --- a/modules/invoiceOut/front/descriptor-menu/index.html +++ b/modules/invoiceOut/front/descriptor-menu/index.html @@ -10,7 +10,6 @@ name="showInvoicePdf" translate> Show invoice... - Send invoice... - - - -
- -
{{detail.buyer}}
-
+
+ +
{{detail.buyer}}
+ + + + +
+ @@ -21,7 +29,7 @@
+ ui-sref="item.waste.detail({buyer: waste.buyer, family: waste.family})"> {{::waste.family}} {{::(waste.percentage / 100) | percentage: 2}} {{::waste.dwindle | currency: 'EUR'}} @@ -29,6 +37,6 @@ -
- - + +
+ \ No newline at end of file diff --git a/modules/item/front/waste/index/index.js b/modules/item/front/waste/index/index.js index 15e6b063f..b11f54b08 100644 --- a/modules/item/front/waste/index/index.js +++ b/modules/item/front/waste/index/index.js @@ -2,7 +2,34 @@ import ngModule from '../../module'; import Section from 'salix/components/section'; import './style.scss'; +export default class Controller extends Section { + constructor($element, $) { + super($element, $); + + this.getWasteConfig(); + } + + getWasteConfig() { + return this.wasteConfig = JSON.parse(localStorage.getItem('wasteConfig')) || {}; + } + + setWasteConfig() { + localStorage.setItem('wasteConfig', JSON.stringify(this.wasteConfig)); + } + + toggleHidePanel(detail) { + if (!this.wasteConfig[detail.buyer]) { + this.wasteConfig[detail.buyer] = { + hidden: true + }; + } else + this.wasteConfig[detail.buyer].hidden = !this.wasteConfig[detail.buyer].hidden; + + this.setWasteConfig(); + } +} + ngModule.vnComponent('vnItemWasteIndex', { template: require('./index.html'), - controller: Section + controller: Controller }); diff --git a/modules/item/front/waste/index/index.spec.js b/modules/item/front/waste/index/index.spec.js new file mode 100644 index 000000000..fd7332f68 --- /dev/null +++ b/modules/item/front/waste/index/index.spec.js @@ -0,0 +1,53 @@ +import './index.js'; +import crudModel from 'core/mocks/crud-model'; + +describe('Item', () => { + describe('Component vnItemWasteIndex', () => { + let $scope; + let controller; + + beforeEach(ngModule('item')); + + beforeEach(inject(($componentController, $rootScope) => { + $scope = $rootScope.$new(); + $scope.model = crudModel; + const $element = angular.element(''); + controller = $componentController('vnItemWasteIndex', {$element, $scope}); + })); + + describe('getWasteConfig / setWasteConfig', () => { + it('should return the local storage wasteConfig', () => { + const result = controller.getWasteConfig(); + + expect(result).toEqual({}); + }); + + it('should set and return the local storage wasteConfig', () => { + controller.wasteConfig = {salesPerson: {hidden: true}}; + controller.setWasteConfig(); + + const result = controller.getWasteConfig(); + + expect(result).toEqual(controller.wasteConfig); + }); + }); + + describe('toggleHidePanel()', () => { + it('should make details hidden by default', () => { + controller.wasteConfig = {}; + + controller.toggleHidePanel({buyer: 'salesPerson'}); + + expect(controller.wasteConfig.salesPerson.hidden).toEqual(true); + }); + + it('should toggle hidden false', () => { + controller.wasteConfig = {salesPerson: {hidden: true}}; + + controller.toggleHidePanel({buyer: 'salesPerson'}); + + expect(controller.wasteConfig.salesPerson.hidden).toEqual(false); + }); + }); + }); +}); diff --git a/modules/item/front/waste/index/style.scss b/modules/item/front/waste/index/style.scss index faac46139..8b44cb6f1 100644 --- a/modules/item/front/waste/index/style.scss +++ b/modules/item/front/waste/index/style.scss @@ -1,21 +1,24 @@ @import "variables"; +@import "effects"; vn-item-waste-index, vn-item-waste-detail { .header { - margin-bottom: 16px; - text-transform: uppercase; - font-size: 1.25rem; - line-height: 1; - padding: 7px; - padding-bottom: 7px; - padding-bottom: 4px; - font-weight: lighter; - background-color: $color-bg; - border-bottom: 1px solid #f7931e; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; + padding: 12px 0 5px 0; + color: gray; + font-size: 1.2rem; + border-bottom: $border; + margin-bottom: 10px; + + & > vn-none > vn-icon { + @extend %clickable-light; + color: $color-button; + font-size: 1.4rem; + } + + vn-none > .arrow { + transition: transform 200ms; + } } vn-table vn-th.waste-family, @@ -23,4 +26,12 @@ vn-item-waste-detail { max-width: 64px; width: 64px } + .hidden { + display: none; + + } + .header > vn-none > .arrow.hidden { + display: block; + transform: rotate(180deg); + } } \ No newline at end of file diff --git a/modules/item/front/waste/locale/es.yml b/modules/item/front/waste/locale/es.yml index 9f08e3a72..b9cd33dec 100644 --- a/modules/item/front/waste/locale/es.yml +++ b/modules/item/front/waste/locale/es.yml @@ -1,3 +1,4 @@ Family: Familia Percentage: Porcentaje -Dwindle: Mermas \ No newline at end of file +Dwindle: Mermas +Minimize/Maximize: Minimizar/Maximizar \ No newline at end of file diff --git a/modules/ticket/back/methods/ticket/specs/priceDifference.spec.js b/modules/ticket/back/methods/ticket/specs/priceDifference.spec.js index e9aa5030a..d8c785baa 100644 --- a/modules/ticket/back/methods/ticket/specs/priceDifference.spec.js +++ b/modules/ticket/back/methods/ticket/specs/priceDifference.spec.js @@ -86,8 +86,8 @@ describe('sale priceDifference()', () => { const firstItem = result.items[0]; const secondtItem = result.items[1]; - expect(firstItem.movable).toEqual(440); - expect(secondtItem.movable).toEqual(1980); + expect(firstItem.movable).toEqual(410); + expect(secondtItem.movable).toEqual(1870); await tx.rollback(); } catch (e) { diff --git a/modules/ticket/back/methods/ticket/specs/sendSms.spec.js b/modules/ticket/back/methods/ticket/specs/sendSms.spec.js index 8ec4ca487..46ae23702 100644 --- a/modules/ticket/back/methods/ticket/specs/sendSms.spec.js +++ b/modules/ticket/back/methods/ticket/specs/sendSms.spec.js @@ -1,7 +1,8 @@ const models = require('vn-loopback/server/server').models; const soap = require('soap'); -describe('ticket sendSms()', () => { +// #3673 sendSms tests excluded +xdescribe('ticket sendSms()', () => { it('should send a message and log it', async() => { const tx = await models.Ticket.beginTransaction({}); diff --git a/modules/ticket/front/basic-data/step-two/index.html b/modules/ticket/front/basic-data/step-two/index.html index 092c9e746..6be455fc9 100644 --- a/modules/ticket/front/basic-data/step-two/index.html +++ b/modules/ticket/front/basic-data/step-two/index.html @@ -18,7 +18,14 @@ - {{("000000"+sale.itemFk).slice(-6)}} + + + {{::sale.itemFk | zeroFill:6}} + +
{{::sale.item.name}} @@ -83,5 +90,9 @@
- + + diff --git a/modules/ticket/front/descriptor-menu/index.html b/modules/ticket/front/descriptor-menu/index.html index ae5642cf3..d613fb5de 100644 --- a/modules/ticket/front/descriptor-menu/index.html +++ b/modules/ticket/front/descriptor-menu/index.html @@ -20,14 +20,22 @@ - Show as PDF + as PDF +
+ as PDF + - Show as CSV + as CSV
diff --git a/modules/ticket/front/descriptor-menu/index.js b/modules/ticket/front/descriptor-menu/index.js index 9d4381f7c..841dfa409 100644 --- a/modules/ticket/front/descriptor-menu/index.js +++ b/modules/ticket/front/descriptor-menu/index.js @@ -84,6 +84,7 @@ class Controller extends Section { .then(() => { this.canStowaway(); this.isTicketEditable(); + this.hasDocuware(); }); } @@ -122,6 +123,15 @@ class Controller extends Section { }); } + hasDocuware() { + const params = { + fileCabinet: 'deliveryClient', + dialog: 'findTicket' + }; + this.$http.post(`Docuwares/${this.id}/checkFile`, params) + .then(res => this.hasDocuwareFile = res.data); + } + showCsvDeliveryNote() { this.vnReport.showCsv('delivery-note', { recipientId: this.ticket.client.id, diff --git a/modules/ticket/front/descriptor-menu/index.spec.js b/modules/ticket/front/descriptor-menu/index.spec.js index 288c7508b..0a80d0884 100644 --- a/modules/ticket/front/descriptor-menu/index.spec.js +++ b/modules/ticket/front/descriptor-menu/index.spec.js @@ -206,7 +206,8 @@ describe('Ticket Component vnTicketDescriptorMenu', () => { it('should make a query and show a success snackbar', () => { jest.spyOn(controller.vnApp, 'showSuccess'); - $httpBackend.whenGET(`Tickets/16`).respond(); + $httpBackend.whenPOST(`Docuwares/${ticket.id}/checkFile`).respond(); + $httpBackend.whenGET(`Tickets/${ticket.id}`).respond(); $httpBackend.expectPOST(`InvoiceOuts/${ticket.invoiceOut.id}/createPdf`).respond(); controller.createPdfInvoice(); $httpBackend.flush(); @@ -275,4 +276,12 @@ describe('Ticket Component vnTicketDescriptorMenu', () => { }); }); }); + + describe('hasDocuware()', () => { + it('should call hasDocuware method', () => { + $httpBackend.whenPOST(`Docuwares/${ticket.id}/checkFile`).respond(); + controller.hasDocuware(); + $httpBackend.flush(); + }); + }); }); diff --git a/modules/ticket/front/descriptor-menu/locale/es.yml b/modules/ticket/front/descriptor-menu/locale/es.yml index 1f4ee710c..4a61556db 100644 --- a/modules/ticket/front/descriptor-menu/locale/es.yml +++ b/modules/ticket/front/descriptor-menu/locale/es.yml @@ -1,7 +1,7 @@ Show Delivery Note...: Ver albarán... Send Delivery Note...: Enviar albarán... -Show as PDF: Ver como PDF -Show as CSV: Ver como CSV +as PDF: como PDF +as CSV: como CSV Send PDF: Enviar PDF Send CSV: Enviar CSV Send CSV Delivery Note: Enviar albarán en CSV diff --git a/print/templates/reports/invoice/sql/intrastat.sql b/print/templates/reports/invoice/sql/intrastat.sql index e391056ec..6bf72c158 100644 --- a/print/templates/reports/invoice/sql/intrastat.sql +++ b/print/templates/reports/invoice/sql/intrastat.sql @@ -2,9 +2,13 @@ SELECT ir.id AS code, ir.description AS description, CAST(SUM(IFNULL(i.stems,1) * s.quantity) AS DECIMAL(10,2)) as stems, - CAST(SUM( weight) AS DECIMAL(10,2)) as netKg, + CAST(SUM(IF(sv.physicalWeight, sv.physicalWeight, i.density * sub.cm3delivery/1000000)) AS DECIMAL(10,2)) netKg, CAST(SUM((s.quantity * s.price * (100 - s.discount) / 100 )) AS DECIMAL(10,2)) AS subtotal - FROM vn.sale s + FROM vn.sale s + LEFT JOIN (SELECT ic.itemFk, ic.cm3, ic.cm3delivery + FROM vn.itemCost ic + WHERE ic.cm3 + GROUP BY ic.itemFk) sub ON s.itemFk = sub.itemFk LEFT JOIN vn.saleVolume sv ON sv.saleFk = s.id LEFT JOIN vn.ticket t ON t.id = s.ticketFk LEFT JOIN vn.invoiceOut io ON io.ref = t.refFk