diff --git a/CHANGELOG.md b/CHANGELOG.md index e89f394b07..1be03b7339 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [2316.01] - 2023-05-04 ### Added -- +- (Usuarios -> Histórico) Nueva sección +- (Roles -> Histórico) Nueva sección ### Changed - (Artículo -> Precio fijado) Modificado el buscador superior por uno lateral diff --git a/db/changes/231402/00-negativeBases.sql b/db/changes/231402/00-negativeBases.sql new file mode 100644 index 0000000000..f7d6cdfb0d --- /dev/null +++ b/db/changes/231402/00-negativeBases.sql @@ -0,0 +1,3 @@ +UPDATE `salix`.`ACL` + SET model = 'InvoiceOut' + WHERE property IN ('negativeBases', 'negativeBasesCsv'); diff --git a/db/changes/231601/00-insertI18n.sql b/db/changes/231601/00-insertI18n.sql new file mode 100644 index 0000000000..f86cb6a738 --- /dev/null +++ b/db/changes/231601/00-insertI18n.sql @@ -0,0 +1,5 @@ +INSERT INTO `vn`.`companyI18n` (`companyFk`, `lang`, `footnotes`) +VALUES (442, 'en', 'In compliance with the provisions of Organic Law 15/1999, on the Protection of Personal Data, we inform you that the personal data you provide will be included in automated files of VERDNATURA LEVANTE SL, being able at all times to exercise the rights of access, rectification, cancellation and opposition, communicating it in writing to the registered office of the entity. The purpose of the file is administrative management, accounting, and billing.'), + (442, 'es', 'En cumplimiento de lo dispuesto en la Ley Orgánica 15/1999, de Protección de Datos de Carácter Personal, le comunicamos que los datos personales que facilite se incluirán en ficheros automatizados de VERDNATURA LEVANTE S.L., pudiendo en todo momento ejercitar los derechos de acceso, rectificación, cancelación y oposición, comunicándolo por escrito al domicilio social de la entidad. La finalidad del fichero es la gestión administrativa, contabilidad, y facturación.'), + (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.'), + (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.'); diff --git a/db/changes/231601/00-newCompanyI18n.sql b/db/changes/231601/00-newCompanyI18n.sql new file mode 100644 index 0000000000..948b9cb085 --- /dev/null +++ b/db/changes/231601/00-newCompanyI18n.sql @@ -0,0 +1,9 @@ +-- vn.companyI18n definition +CREATE TABLE `vn`.`companyI18n` ( + `companyFk` smallint(5) unsigned NOT NULL, + `lang` char(2) CHARACTER SET utf8mb3 NOT NULL, + `footnotes` longtext COLLATE utf8mb3_unicode_ci DEFAULT NULL, + PRIMARY KEY (`companyFk`,`lang`), + CONSTRAINT `companyI18n_FK` FOREIGN KEY (`companyFk`) REFERENCES `company` (`id`) ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; + diff --git a/db/changes/231601/00-newTableWeb.sql b/db/changes/231601/00-newTableWeb.sql new file mode 100644 index 0000000000..1a24029569 --- /dev/null +++ b/db/changes/231601/00-newTableWeb.sql @@ -0,0 +1 @@ +ALTER TABLE `vn`.`company` ADD `web` varchar(100) NULL; \ No newline at end of file diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 4dc7dcafc4..15ccece355 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -546,7 +546,8 @@ INSERT INTO `vn`.`supplier`(`id`, `name`, `nickname`,`account`,`countryFk`,`nif` VALUES (1, 'Plants SL', 'Plants nick', 4100000001, 1, '06089160W', 0, util.VN_CURDATE(), 1, 'supplier address 1', 'PONTEVEDRA', 1, 15214, 1, 1, 15, 4, 1, 1, 18, 'flowerPlants', 1, '400664487V'), (2, 'Farmer King', 'The farmer', 4000020002, 1, '87945234L', 0, util.VN_CURDATE(), 1, 'supplier address 2', 'GOTHAM', 2, 43022, 1, 2, 10, 93, 2, 8, 18, 'animals', 1, '400664487V'), - (442, 'Verdnatura Levante SL', 'Verdnatura', 5115000442, 1, '06815934E', 0, util.VN_CURDATE(), 1, 'supplier address 3', 'GOTHAM', 1, 43022, 1, 2, 15, 6, 9, 3, 18, 'complements', 1, '400664487V'); + (442, 'Verdnatura Levante SL', 'Verdnatura', 5115000442, 1, '06815934E', 0, util.VN_CURDATE(), 1, 'supplier address 3', 'GOTHAM', 1, 43022, 1, 2, 15, 6, 9, 3, 18, 'complements', 1, '400664487V'), + (1381, 'Ornamentales', 'Ornamentales', 7185000440, 1, '03815934E', 0, util.VN_CURDATE(), 1, 'supplier address 4', 'GOTHAM', 1, 43022, 1, 2, 15, 6, 9, 3, 18, 'complements', 1, '400664487V'); INSERT INTO `vn`.`supplierContact`(`id`, `supplierFk`, `phone`, `mobile`, `email`, `observation`, `name`) VALUES @@ -2789,7 +2790,7 @@ INSERT INTO `vn`.`profileType` (`id`, `name`) INSERT INTO `salix`.`url` (`appName`, `environment`, `url`) VALUES - ('lilium', 'dev', 'http://localhost:8080/#/'), + ('lilium', 'dev', 'http://localhost:9000/#/'), ('salix', 'dev', 'http://localhost:5000/#!/'); INSERT INTO `vn`.`report` (`id`, `name`, `paperSizeFk`, `method`) diff --git a/e2e/paths/09-invoice-in/05_negative_bases.spec.js b/e2e/paths/09-invoice-out/05_negative_bases.spec.js similarity index 70% rename from e2e/paths/09-invoice-in/05_negative_bases.spec.js rename to e2e/paths/09-invoice-out/05_negative_bases.spec.js index 4c9fe651fc..43ced2115e 100644 --- a/e2e/paths/09-invoice-in/05_negative_bases.spec.js +++ b/e2e/paths/09-invoice-out/05_negative_bases.spec.js @@ -1,6 +1,6 @@ import getBrowser from '../../helpers/puppeteer'; -describe('InvoiceIn negative bases path', () => { +describe('InvoiceOut negative bases path', () => { let browser; let page; const httpRequests = []; @@ -9,11 +9,11 @@ describe('InvoiceIn negative bases path', () => { browser = await getBrowser(); page = browser.page; page.on('request', req => { - if (req.url().includes(`InvoiceIns/negativeBases`)) + if (req.url().includes(`InvoiceOuts/negativeBases`)) httpRequests.push(req.url()); }); - await page.loginAndModule('administrative', 'invoiceIn'); - await page.accessToSection('invoiceIn.negative-bases'); + await page.loginAndModule('administrative', 'invoiceOut'); + await page.accessToSection('invoiceOut.negative-bases'); }); afterAll(async() => { diff --git a/loopback/locale/en.json b/loopback/locale/en.json index ff51452dd3..5767632eee 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -156,6 +156,18 @@ "Component cost not set": "Componente coste no está estabecido", "Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº 2": "Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº 2", "Description cannot be blank": "Description cannot be blank", + "company": "Company", + "country": "Country", + "clientId": "Id client", + "clientSocialName": "Client", + "amount": "Amount", + "taxableBase": "Taxable base", + "ticketFk": "Id ticket", + "isActive": "Active", + "hasToInvoice": "Invoice", + "isTaxDataChecked": "Data checked", + "comercialId": "Id Comercial", + "comercialName": "Comercial", "Added observation": "Added observation", "Comment added to client": "Comment added to client" } diff --git a/loopback/locale/es.json b/loopback/locale/es.json index d52eacff6a..3ef3c4a227 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -275,7 +275,19 @@ "Collection does not exist": "La colección no existe", "Cannot obtain exclusive lock": "No se puede obtener un bloqueo exclusivo", "Insert a date range": "Inserte un rango de fechas", - "Added observation": "{{user}} añadió esta observacion: {{text}}", - "Comment added to client": "Observación añadida al cliente {{clientFk}}", - "Cannot create a new claimBeginning from a different ticket": "No se puede crear una línea de reclamación de un ticket diferente al origen" + "Added observation": "{{user}} añadió esta observacion: {{text}}", + "Comment added to client": "Observación añadida al cliente {{clientFk}}", + "Cannot create a new claimBeginning from a different ticket": "No se puede crear una línea de reclamación de un ticket diferente al origen", + "company": "Compañía", + "country": "País", + "clientId": "Id cliente", + "clientSocialName": "Cliente", + "amount": "Importe", + "taxableBase": "Base", + "ticketFk": "Id ticket", + "isActive": "Activo", + "hasToInvoice": "Facturar", + "isTaxDataChecked": "Datos comprobados", + "comercialId": "Id comercial", + "comercialName": "Comercial" } diff --git a/modules/claim/front/photos/index.html b/modules/claim/front/photos/index.html index 9e00ee02f8..8b13789179 100644 --- a/modules/claim/front/photos/index.html +++ b/modules/claim/front/photos/index.html @@ -1,48 +1 @@ - - - -
-
-
Drag & Drop photos here...
-
-
-
-
- -
- - -
-
-
- - - - + diff --git a/modules/claim/front/photos/index.js b/modules/claim/front/photos/index.js index 62e439a910..c9fada9a47 100644 --- a/modules/claim/front/photos/index.js +++ b/modules/claim/front/photos/index.js @@ -1,105 +1,17 @@ import ngModule from '../module'; import Section from 'salix/components/section'; -import './style.scss'; class Controller extends Section { - constructor($element, $, vnFile) { + constructor($element, $) { super($element, $); - this.vnFile = vnFile; - this.filter = { - include: [ - { - relation: 'dms' - } - ] - }; } - deleteDms(index) { - const dmsFk = this.photos[index].dmsFk; - return this.$http.post(`ClaimDms/${dmsFk}/removeFile`) - .then(() => { - this.$.model.remove(index); - this.vnApp.showSuccess(this.$t('File deleted')); - }); - } - - onDrop($event) { - const files = $event.dataTransfer.files; - this.setDefaultParams().then(() => { - this.dms.files = files; - this.create(); - }); - } - - setDefaultParams() { - const filter = { - where: {code: 'claim'} - }; - return this.$http.get('DmsTypes/findOne', {filter}).then(res => { - const dmsTypeId = res.data && res.data.id; - const companyId = this.vnConfig.companyFk; - const warehouseId = this.vnConfig.warehouseFk; - this.dms = { - hasFile: false, - hasFileAttached: false, - reference: this.claim.id, - warehouseId: warehouseId, - companyId: companyId, - dmsTypeId: dmsTypeId, - description: this.$t('FileDescription', { - claimId: this.claim.id, - clientId: this.claim.client.id, - clientName: this.claim.client.name - }).toUpperCase() - }; - }); - } - - openUploadDialog() { - const element = document.createElement('input'); - element.setAttribute('type', 'file'); - element.setAttribute('multiple', true); - element.click(); - - element.addEventListener('change', () => - this.setDefaultParams().then(() => { - this.dms.files = element.files; - this.create(); - }) - ); - } - - create() { - const query = `claims/${this.claim.id}/uploadFile`; - const options = { - method: 'POST', - url: query, - params: this.dms, - headers: {'Content-Type': undefined}, - transformRequest: files => { - const formData = new FormData(); - - for (let i = 0; i < files.length; i++) - formData.append(files[i].name, files[i]); - - return formData; - }, - data: this.dms.files - }; - this.$http(options).then(() => { - this.vnApp.showSuccess(this.$t('File uploaded!')); - this.$.model.refresh(); - }); - } - - getImagePath(dmsId) { - return this.vnFile.getPath(`/api/Claims/${dmsId}/downloadFile`); + async $onInit() { + const url = await this.vnApp.getUrl(`claim/${this.$params.id}/photos`); + window.location.href = url; } } -Controller.$inject = ['$element', '$scope', 'vnFile']; - ngModule.vnComponent('vnClaimPhotos', { template: require('./index.html'), controller: Controller, diff --git a/modules/claim/front/photos/index.spec.js b/modules/claim/front/photos/index.spec.js deleted file mode 100644 index 84df48b447..0000000000 --- a/modules/claim/front/photos/index.spec.js +++ /dev/null @@ -1,70 +0,0 @@ -import './index'; -import crudModel from 'core/mocks/crud-model'; - -describe('Claim', () => { - describe('Component vnClaimPhotos', () => { - let $scope; - let $httpBackend; - let controller; - - beforeEach(ngModule('claim')); - - beforeEach(inject(($componentController, $rootScope, _$httpBackend_) => { - $httpBackend = _$httpBackend_; - $scope = $rootScope.$new(); - controller = $componentController('vnClaimPhotos', {$element: null, $scope}); - controller.$.model = crudModel; - controller.claim = { - id: 1, - client: {id: 1101, name: 'Bruce Wayne'} - }; - })); - - describe('deleteDms()', () => { - it('should make an HTTP Post query', () => { - jest.spyOn(controller.vnApp, 'showSuccess'); - jest.spyOn(controller.$.model, 'remove'); - - const dmsId = 1; - const dmsIndex = 0; - controller.photos = [{dmsFk: 1}]; - - $httpBackend.expectPOST(`ClaimDms/${dmsId}/removeFile`).respond(); - controller.deleteDms(dmsIndex); - $httpBackend.flush(); - - expect(controller.$.model.remove).toHaveBeenCalledWith(dmsIndex); - expect(controller.vnApp.showSuccess).toHaveBeenCalled(); - }); - }); - - describe('setDefaultParams()', () => { - it('should make an HTTP GET query, then set all dms properties', () => { - $httpBackend.expectRoute('GET', `DmsTypes/findOne`).respond({}); - controller.setDefaultParams(); - $httpBackend.flush(); - - expect(controller.dms).toBeDefined(); - }); - }); - - describe('create()', () => { - it('should make an HTTP Post query, then refresh the model data', () => { - const claimId = 1; - const dmsIndex = 0; - jest.spyOn(controller.vnApp, 'showSuccess'); - jest.spyOn(controller.$.model, 'refresh'); - controller.photos = [{dmsFk: 1}]; - controller.dmsIndex = dmsIndex; - controller.dms = {files: []}; - - $httpBackend.expectPOST(`claims/${claimId}/uploadFile`).respond({}); - controller.create(); - $httpBackend.flush(); - - expect(controller.$.model.refresh).toHaveBeenCalled(); - expect(controller.vnApp.showSuccess).toHaveBeenCalled(); - }); - }); - }); -}); diff --git a/modules/claim/front/photos/locale/es.yml b/modules/claim/front/photos/locale/es.yml deleted file mode 100644 index d2ee9ffbdb..0000000000 --- a/modules/claim/front/photos/locale/es.yml +++ /dev/null @@ -1,5 +0,0 @@ -Are you sure you want to continue?: ¿Seguro que quieres continuar? -Drag & Drop photos here...: Arrastra y suelta fotos aquí... -File deleted: Archivo eliminado -File uploaded!: Archivo subido! -Select file: Seleccionar fichero \ No newline at end of file diff --git a/modules/claim/front/photos/style.scss b/modules/claim/front/photos/style.scss deleted file mode 100644 index 101cb0da21..0000000000 --- a/modules/claim/front/photos/style.scss +++ /dev/null @@ -1,47 +0,0 @@ -@import "./variables"; - -vn-claim-photos { - height: 100%; - - .drop-zone { - color: $color-font-secondary; - box-sizing: border-box; - border-radius: 8px; - text-align: center; - min-height: 100%; - - .empty-rows { - padding: 80px $spacing-md; - font-size: 1.375rem - } - - vn-icon { - font-size: 3rem - } - } - - .photo-list { - padding: $spacing-md; - min-height: 100%; - - .photo { - width: 512px; - height: 288px; - } - } - - .video { - width: 100%; - height: 100%; - object-fit: cover; - cursor: pointer; - box-shadow: 0 2px 2px 0 rgba(0,0,0,.14), - 0 3px 1px -2px rgba(0,0,0,.2), - 0 1px 5px 0 rgba(0,0,0,.12); - border: 2px solid transparent; - - } - .video:hover { - border: 2px solid $color-primary - } -} diff --git a/modules/invoiceIn/back/methods/invoice-in/negativeBasesCsv.js b/modules/invoiceIn/back/methods/invoice-in/negativeBasesCsv.js deleted file mode 100644 index 963151b7da..0000000000 --- a/modules/invoiceIn/back/methods/invoice-in/negativeBasesCsv.js +++ /dev/null @@ -1,53 +0,0 @@ -const {toCSV} = require('vn-loopback/util/csv'); - -module.exports = Self => { - Self.remoteMethodCtx('negativeBasesCsv', { - description: 'Returns the negative bases as .csv', - accessType: 'READ', - accepts: [{ - arg: 'negativeBases', - type: ['object'], - required: true - }, - { - arg: 'from', - type: 'date', - description: 'From date' - }, - { - arg: 'to', - type: 'date', - description: 'To date' - }], - 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: '/negativeBasesCsv', - verb: 'GET' - } - }); - - Self.negativeBasesCsv = async ctx => { - const args = ctx.args; - const content = toCSV(args.negativeBases); - - return [ - content, - 'text/csv', - `attachment; filename="negative-bases-${new Date(args.from).toLocaleDateString()}-${new Date(args.to).toLocaleDateString()}.csv"` - ]; - }; -}; diff --git a/modules/invoiceIn/back/models/invoice-in.js b/modules/invoiceIn/back/models/invoice-in.js index 167f2ac34e..51905ccb8b 100644 --- a/modules/invoiceIn/back/models/invoice-in.js +++ b/modules/invoiceIn/back/models/invoice-in.js @@ -7,6 +7,4 @@ module.exports = Self => { require('../methods/invoice-in/invoiceInPdf')(Self); require('../methods/invoice-in/invoiceInEmail')(Self); require('../methods/invoice-in/getSerial')(Self); - require('../methods/invoice-in/negativeBases')(Self); - require('../methods/invoice-in/negativeBasesCsv')(Self); }; diff --git a/modules/invoiceIn/front/index.js b/modules/invoiceIn/front/index.js index c0374e9966..e257cfee38 100644 --- a/modules/invoiceIn/front/index.js +++ b/modules/invoiceIn/front/index.js @@ -15,4 +15,3 @@ import './create'; import './log'; import './serial'; import './serial-search-panel'; -import './negative-bases'; diff --git a/modules/invoiceIn/front/negative-bases/locale/es.yml b/modules/invoiceIn/front/negative-bases/locale/es.yml deleted file mode 100644 index 9095eee221..0000000000 --- a/modules/invoiceIn/front/negative-bases/locale/es.yml +++ /dev/null @@ -1,14 +0,0 @@ -Has To Invoice: Facturar -Download as CSV: Descargar como CSV -company: Compañía -country: País -clientId: Id Cliente -clientSocialName: Cliente -amount: Importe -taxableBase: Base -ticketFk: Id Ticket -isActive: Activo -hasToInvoice: Facturar -isTaxDataChecked: Datos comprobados -comercialId: Id Comercial -comercialName: Comercial diff --git a/modules/invoiceIn/front/routes.json b/modules/invoiceIn/front/routes.json index 40d061d1b8..6f4d3d1a3b 100644 --- a/modules/invoiceIn/front/routes.json +++ b/modules/invoiceIn/front/routes.json @@ -10,8 +10,7 @@ "menus": { "main": [ { "state": "invoiceIn.index", "icon": "icon-invoice-in"}, - { "state": "invoiceIn.serial", "icon": "icon-invoice-in"}, - { "state": "invoiceIn.negative-bases", "icon": "icon-ticket"} + { "state": "invoiceIn.serial", "icon": "icon-invoice-in"} ], "card": [ { @@ -53,15 +52,6 @@ "administrative" ] }, - { - "url": "/negative-bases", - "state": "invoiceIn.negative-bases", - "component": "vn-negative-bases", - "description": "Negative bases", - "acl": [ - "administrative" - ] - }, { "url": "/serial", "state": "invoiceIn.serial", diff --git a/modules/invoiceIn/back/methods/invoice-in/negativeBases.js b/modules/invoiceOut/back/methods/invoiceOut/negativeBases.js similarity index 93% rename from modules/invoiceIn/back/methods/invoice-in/negativeBases.js rename to modules/invoiceOut/back/methods/invoiceOut/negativeBases.js index 4c9a8984bf..ae9c404afd 100644 --- a/modules/invoiceIn/back/methods/invoice-in/negativeBases.js +++ b/modules/invoiceOut/back/methods/invoiceOut/negativeBases.js @@ -96,16 +96,18 @@ module.exports = Self => { SELECT f.* FROM tmp.filter f`); - stmt.merge(conn.makeWhere(args.filter.where)); - stmt.merge(conn.makeOrderBy(args.filter.order)); - stmt.merge(conn.makeLimit(args.filter)); + if (args.filter) { + stmt.merge(conn.makeWhere(args.filter.where)); + stmt.merge(conn.makeOrderBy(args.filter.order)); + stmt.merge(conn.makeLimit(args.filter)); + } const negativeBasesIndex = stmts.push(stmt) - 1; stmts.push(`DROP TEMPORARY TABLE tmp.filter, tmp.ticket, tmp.ticketTax, tmp.ticketAmount`); const sql = ParameterizedSQL.join(stmts, ';'); - const result = await conn.executeStmt(sql, myOptions); + const result = await conn.executeStmt(sql); return negativeBasesIndex === 0 ? result : result[negativeBasesIndex]; }; diff --git a/modules/invoiceOut/back/methods/invoiceOut/negativeBasesCsv.js b/modules/invoiceOut/back/methods/invoiceOut/negativeBasesCsv.js new file mode 100644 index 0000000000..d70a8fce52 --- /dev/null +++ b/modules/invoiceOut/back/methods/invoiceOut/negativeBasesCsv.js @@ -0,0 +1,68 @@ +const {toCSV} = require('vn-loopback/util/csv'); + +module.exports = Self => { + Self.remoteMethodCtx('negativeBasesCsv', { + description: 'Returns the negative bases as .csv', + accessType: 'READ', + accepts: [ + { + arg: 'from', + type: 'date', + description: 'From date', + required: true + }, + { + arg: 'to', + type: 'date', + description: 'To date', + required: true + }], + 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: '/negativeBasesCsv', + verb: 'GET' + } + }); + + Self.negativeBasesCsv = async(ctx, options) => { + const $t = ctx.req.__; // $translate + const args = ctx.args; + const myOptions = {}; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + const negativeBases = await Self.app.models.InvoiceOut.negativeBases(ctx, myOptions); + const locatedFields = []; + negativeBases.forEach(element => { + locatedFields.push(Object.keys(element).map(key => { + return {newName: $t(key), value: element[key]}; + }).filter(item => item !== null) + .reduce((result, item) => { + result[item.newName] = item.value; + return result; + }, {})); + }); + const content = toCSV(locatedFields); + + return [ + content, + 'text/csv', + `attachment; filename="negative-bases-${new Date(args.from).toLocaleDateString()}-${new Date(args.to).toLocaleDateString()}.csv"` + ]; + }; +}; diff --git a/modules/invoiceIn/back/methods/invoice-in/specs/negativeBases.spec.js b/modules/invoiceOut/back/methods/invoiceOut/specs/negativeBases.spec.js similarity index 71% rename from modules/invoiceIn/back/methods/invoice-in/specs/negativeBases.spec.js rename to modules/invoiceOut/back/methods/invoiceOut/specs/negativeBases.spec.js index a5c6e31027..1164e894b0 100644 --- a/modules/invoiceIn/back/methods/invoice-in/specs/negativeBases.spec.js +++ b/modules/invoiceOut/back/methods/invoiceOut/specs/negativeBases.spec.js @@ -1,19 +1,18 @@ const models = require('vn-loopback/server/server').models; -describe('invoiceIn negativeBases()', () => { +describe('invoiceOut negativeBases()', () => { it('should return all negative bases in a date range', async() => { - const tx = await models.InvoiceIn.beginTransaction({}); + const tx = await models.InvoiceOut.beginTransaction({}); const options = {transaction: tx}; const ctx = { args: { from: new Date().setMonth(new Date().getMonth() - 12), - to: new Date(), - filter: {} + to: new Date() } }; try { - const result = await models.InvoiceIn.negativeBases(ctx, options); + const result = await models.InvoiceOut.negativeBases(ctx, options); expect(result.length).toBeGreaterThan(0); @@ -26,7 +25,7 @@ describe('invoiceIn negativeBases()', () => { it('should throw an error if a date range is not in args', async() => { let error; - const tx = await models.InvoiceIn.beginTransaction({}); + const tx = await models.InvoiceOut.beginTransaction({}); const options = {transaction: tx}; const ctx = { args: { @@ -35,7 +34,7 @@ describe('invoiceIn negativeBases()', () => { }; try { - await models.InvoiceIn.negativeBases(ctx, options); + await models.InvoiceOut.negativeBases(ctx, options); await tx.rollback(); } catch (e) { error = e; diff --git a/modules/invoiceOut/back/models/invoice-out.js b/modules/invoiceOut/back/models/invoice-out.js index 6205abe7b8..5fcef7744a 100644 --- a/modules/invoiceOut/back/models/invoice-out.js +++ b/modules/invoiceOut/back/models/invoice-out.js @@ -17,4 +17,6 @@ module.exports = Self => { require('../methods/invoiceOut/invoiceCsvEmail')(Self); require('../methods/invoiceOut/invoiceOutPdf')(Self); require('../methods/invoiceOut/getInvoiceDate')(Self); + require('../methods/invoiceOut/negativeBases')(Self); + require('../methods/invoiceOut/negativeBasesCsv')(Self); }; diff --git a/modules/invoiceOut/front/index.js b/modules/invoiceOut/front/index.js index f7cebc0d04..723e3be5af 100644 --- a/modules/invoiceOut/front/index.js +++ b/modules/invoiceOut/front/index.js @@ -10,3 +10,4 @@ import './descriptor-popover'; import './descriptor-menu'; import './index/manual'; import './global-invoicing'; +import './negative-bases'; diff --git a/modules/invoiceIn/front/negative-bases/index.html b/modules/invoiceOut/front/negative-bases/index.html similarity index 96% rename from modules/invoiceIn/front/negative-bases/index.html rename to modules/invoiceOut/front/negative-bases/index.html index 5da8e7aad0..26f67c7d49 100644 --- a/modules/invoiceIn/front/negative-bases/index.html +++ b/modules/invoiceOut/front/negative-bases/index.html @@ -1,6 +1,6 @@ @@ -43,7 +43,7 @@ Country - Id Client + Client id Client @@ -55,7 +55,7 @@ Base - Id Ticket + Ticket id Active diff --git a/modules/invoiceIn/front/negative-bases/index.js b/modules/invoiceOut/front/negative-bases/index.js similarity index 79% rename from modules/invoiceIn/front/negative-bases/index.js rename to modules/invoiceOut/front/negative-bases/index.js index 0f6f046927..1a838507ca 100644 --- a/modules/invoiceIn/front/negative-bases/index.js +++ b/modules/invoiceOut/front/negative-bases/index.js @@ -58,18 +58,7 @@ export default class Controller extends Section { } downloadCSV() { - const data = []; - this.$.model._orgData.forEach(element => { - data.push(Object.keys(element).map(key => { - return {newName: this.$t(key), value: element[key]}; - }).filter(item => item !== null) - .reduce((result, item) => { - result[item.newName] = item.value; - return result; - }, {})); - }); - this.vnReport.show('InvoiceIns/negativeBasesCsv', { - negativeBases: data, + this.vnReport.show('InvoiceOuts/negativeBasesCsv', { from: this.params.from, to: this.params.to }); diff --git a/modules/invoiceOut/front/negative-bases/locale/es.yml b/modules/invoiceOut/front/negative-bases/locale/es.yml new file mode 100644 index 0000000000..dd3432592d --- /dev/null +++ b/modules/invoiceOut/front/negative-bases/locale/es.yml @@ -0,0 +1,2 @@ +Has To Invoice: Facturar +Download as CSV: Descargar como CSV diff --git a/modules/invoiceIn/front/negative-bases/style.scss b/modules/invoiceOut/front/negative-bases/style.scss similarity index 100% rename from modules/invoiceIn/front/negative-bases/style.scss rename to modules/invoiceOut/front/negative-bases/style.scss diff --git a/modules/invoiceOut/front/routes.json b/modules/invoiceOut/front/routes.json index c396a5334c..f7f589b01c 100644 --- a/modules/invoiceOut/front/routes.json +++ b/modules/invoiceOut/front/routes.json @@ -7,8 +7,8 @@ "menus": { "main": [ {"state": "invoiceOut.index", "icon": "icon-invoice-out"}, - {"state": "invoiceOut.global-invoicing", "icon": "contact_support"} - + {"state": "invoiceOut.global-invoicing", "icon": "contact_support"}, + { "state": "invoiceOut.negative-bases", "icon": "icon-ticket"} ] }, "routes": [ @@ -46,6 +46,15 @@ "state": "invoiceOut.card", "abstract": true, "component": "vn-invoice-out-card" + }, + { + "url": "/negative-bases", + "state": "invoiceOut.negative-bases", + "component": "vn-negative-bases", + "description": "Negative bases", + "acl": [ + "administrative" + ] } ] } diff --git a/modules/supplier/back/methods/supplier/specs/filter.spec.js b/modules/supplier/back/methods/supplier/specs/filter.spec.js index 2620bb687e..8f8ff13469 100644 --- a/modules/supplier/back/methods/supplier/specs/filter.spec.js +++ b/modules/supplier/back/methods/supplier/specs/filter.spec.js @@ -23,6 +23,6 @@ describe('Supplier filter()', () => { let result = await app.models.Supplier.filter(ctx); - expect(result.length).toEqual(2); + expect(result.length).toEqual(3); }); }); diff --git a/print/core/components/report-footer/assets/css/style.css b/print/core/components/report-footer/assets/css/style.css index 9727e6f8f9..b260c1b9fc 100644 --- a/print/core/components/report-footer/assets/css/style.css +++ b/print/core/components/report-footer/assets/css/style.css @@ -4,6 +4,7 @@ margin-right: 2cm; font-size: 10px; color: #555; + width: 100%; zoom: 0.65 } diff --git a/print/core/components/report-footer/locale/en.yml b/print/core/components/report-footer/locale/en.yml index 3899f8b98a..8ca14b4d76 100644 --- a/print/core/components/report-footer/locale/en.yml +++ b/print/core/components/report-footer/locale/en.yml @@ -1,8 +1 @@ -numPages: Page of -law: - privacy: 'In compliance with the provisions of Organic Law 15/1999, on the - Protection of Personal Data, we inform you that the personal data you provide - will be included in automated files of VERDNATURA LEVANTE SL, being able at all - times to exercise the rights of access, rectification, cancellation and opposition, - communicating it in writing to the registered office of the entity. - The purpose of the file is administrative management, accounting, and billing.' +numPages: Page of \ No newline at end of file diff --git a/print/core/components/report-footer/locale/es.yml b/print/core/components/report-footer/locale/es.yml index 985c1e17a1..5ac6544ad4 100644 --- a/print/core/components/report-footer/locale/es.yml +++ b/print/core/components/report-footer/locale/es.yml @@ -1,8 +1 @@ -numPages: Página de -law: - privacy: En cumplimiento de lo dispuesto en la Ley Orgánica 15/1999, de Protección - de Datos de Carácter Personal, le comunicamos que los datos personales que facilite - se incluirán en ficheros automatizados de VERDNATURA LEVANTE S.L., pudiendo en - todo momento ejercitar los derechos de acceso, rectificación, cancelación y oposición, - comunicándolo por escrito al domicilio social de la entidad. La finalidad del - fichero es la gestión administrativa, contabilidad, y facturación. +numPages: Página de \ No newline at end of file diff --git a/print/core/components/report-footer/locale/fr.yml b/print/core/components/report-footer/locale/fr.yml index 861ee56845..6fb644b2c3 100644 --- a/print/core/components/report-footer/locale/fr.yml +++ b/print/core/components/report-footer/locale/fr.yml @@ -1,8 +1 @@ numPages: Page de -law: - privacy: 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. diff --git a/print/core/components/report-footer/locale/pt.yml b/print/core/components/report-footer/locale/pt.yml index 1c343bb4c2..9354ba3e9f 100644 --- a/print/core/components/report-footer/locale/pt.yml +++ b/print/core/components/report-footer/locale/pt.yml @@ -1,8 +1 @@ numPages: Página de -law: - privacy: 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. diff --git a/print/core/components/report-footer/report-footer.html b/print/core/components/report-footer/report-footer.html index 1af8df4d4d..67b5f3cd05 100644 --- a/print/core/components/report-footer/report-footer.html +++ b/print/core/components/report-footer/report-footer.html @@ -5,6 +5,11 @@
{{centerText}}
-

+

+

+ + diff --git a/print/core/components/report-footer/report-footer.js b/print/core/components/report-footer/report-footer.js index 1ba36b1d74..0eaab8ce42 100755 --- a/print/core/components/report-footer/report-footer.js +++ b/print/core/components/report-footer/report-footer.js @@ -1,4 +1,17 @@ +/* eslint-disable no-tabs */ +const db = require('../../database'); + module.exports = { name: 'report-footer', - props: ['leftText', 'centerText'] + async serverPrefetch() { + this.company = await db.findOne( + `SELECT + ci.footnotes + FROM companyI18n ci + JOIN company c ON c.id = ci.companyFk + WHERE c.code = ? AND ci.lang = (SELECT lang FROM account.user WHERE id = ?)`, + [this.companyCode, this.recipientId]); + }, + + props: ['leftText', 'companyCode', 'recipientId', 'centerText'] }; diff --git a/print/core/components/report-header/report-header.html b/print/core/components/report-header/report-header.html index 0479e5caf6..22f2068e2d 100644 --- a/print/core/components/report-header/report-header.html +++ b/print/core/components/report-header/report-header.html @@ -8,7 +8,7 @@ {{companyName}}. {{company.street}}. {{company.postCode}} {{company.city}}. ☎ {{companyPhone}} - · {{$t('company.contactData')}} + · {{company.web}} - {{company.email}}
CIF: {{fiscalAddress.nif}} {{fiscalAddress.register}}
diff --git a/print/core/components/report-header/report-header.js b/print/core/components/report-header/report-header.js index 50c3a1337a..d85e2c8364 100755 --- a/print/core/components/report-header/report-header.js +++ b/print/core/components/report-header/report-header.js @@ -43,7 +43,9 @@ module.exports = { s.postCode, s.city, s.phone, - cg.code AS groupName + cg.code AS groupName, + c.email, + c.web FROM company c JOIN companyGroup cg ON cg.id = c.companyGroupFk JOIN supplier s ON s.id = c.id diff --git a/print/templates/email/greuge-wrong/assets/css/import.js b/print/templates/email/greuge-wrong/assets/css/import.js new file mode 100644 index 0000000000..89b2afaa5a --- /dev/null +++ b/print/templates/email/greuge-wrong/assets/css/import.js @@ -0,0 +1,11 @@ +const Stylesheet = require(`vn-print/core/stylesheet`); + +const path = require('path'); +const vnPrintPath = path.resolve('print'); + +module.exports = new Stylesheet([ + `${vnPrintPath}/common/css/spacing.css`, + `${vnPrintPath}/common/css/misc.css`, + `${vnPrintPath}/common/css/layout.css`, + `${vnPrintPath}/common/css/email.css`]) + .mergeStyles(); \ No newline at end of file diff --git a/print/templates/email/greuge-wrong/greuge-wrong.html b/print/templates/email/greuge-wrong/greuge-wrong.html new file mode 100644 index 0000000000..3360071220 --- /dev/null +++ b/print/templates/email/greuge-wrong/greuge-wrong.html @@ -0,0 +1,15 @@ + +
+
+

{{ $t('total') }}: {{tickets.length}}

+
+
+
+

{{ $t('ticketId') }}: {{ticket.ticketId}}

+

{{ $t('clientId') }}: {{ticket.clientId}}

+

{{ $t('description') }}: {{ticket.description}}

+

{{ $t('amount') }}: {{ticket.amount}} €

+
+
+
+
\ No newline at end of file diff --git a/print/templates/email/greuge-wrong/greuge-wrong.js b/print/templates/email/greuge-wrong/greuge-wrong.js new file mode 100644 index 0000000000..2aa3d50a7d --- /dev/null +++ b/print/templates/email/greuge-wrong/greuge-wrong.js @@ -0,0 +1,36 @@ +const Component = require(`vn-print/core/component`); +const emailBody = new Component('email-body'); +const models = require('vn-loopback/server/server').models; + +module.exports = { + name: 'greuge-wrong', + async serverPrefetch() { + this.url = await this.salixUrl(); + + if (!this.url) + throw new Error('Something went wrong'); + }, + components: { + 'email-body': emailBody.build(), + }, + methods: { + async salixUrl() { + const salix = await models.Url.findOne({ + where: { + appName: 'salix', + environment: process.env.NODE_ENV || 'dev' + } + }); + return salix.url; + }, + clientGreugeUrl(clientId) { + return `${this.url}client/${clientId}/greuge/index` + }, + }, + props: { + tickets: { + type: Array, + required: true + }, + }, +}; \ No newline at end of file diff --git a/print/templates/email/greuge-wrong/locale/en.yml b/print/templates/email/greuge-wrong/locale/en.yml new file mode 100644 index 0000000000..0ace99c36c --- /dev/null +++ b/print/templates/email/greuge-wrong/locale/en.yml @@ -0,0 +1,6 @@ +subject: Abnormal greuges have been created +total: Total number of abnormal greuges +ticketId: Ticket +clientId: Client +description: Description +amount: Amount \ No newline at end of file diff --git a/print/templates/email/greuge-wrong/locale/es.yml b/print/templates/email/greuge-wrong/locale/es.yml new file mode 100644 index 0000000000..fd23971824 --- /dev/null +++ b/print/templates/email/greuge-wrong/locale/es.yml @@ -0,0 +1,6 @@ +subject: Se han creado greuges anormales +total: Número total de greuges anormales +ticketId: Ticket +clientId: Cliente +description: Descipción +amount: Importe \ No newline at end of file diff --git a/print/templates/reports/invoice/invoice.html b/print/templates/reports/invoice/invoice.html index 8b0220e433..727621b2cf 100644 --- a/print/templates/reports/invoice/invoice.html +++ b/print/templates/reports/invoice/invoice.html @@ -5,7 +5,7 @@ -
+
@@ -242,7 +242,7 @@
-
+
{{$t('observations')}}
@@ -266,7 +266,9 @@ v-bind:company-code="invoice.companyCode" v-bind:left-text="$t('invoiceRef', [invoice.ref])" v-bind:center-text="client.socialName" + v-bind:recipient-id="client.id" v-bind="$props" + > diff --git a/print/templates/reports/invoice/invoice.js b/print/templates/reports/invoice/invoice.js index 42988113fa..1c9965d3b3 100755 --- a/print/templates/reports/invoice/invoice.js +++ b/print/templates/reports/invoice/invoice.js @@ -11,8 +11,12 @@ module.exports = { this.client = await this.findOneFromDef('client', [this.reference]); this.taxes = await this.rawSqlFromDef(`taxes`, [this.reference]); this.hasIntrastat = await this.findValueFromDef(`hasIntrastat`, [this.reference]); - this.intrastat = await this.rawSqlFromDef(`intrastat`, - [this.reference, this.reference, this.reference, this.reference]); + this.intrastat = await this.rawSqlFromDef(`intrastat`, [ + this.reference, + this.reference, + this.reference, + this.reference + ]); this.rectified = await this.rawSqlFromDef(`rectified`, [this.reference]); this.hasIncoterms = await this.findValueFromDef(`hasIncoterms`, [this.reference]); diff --git a/print/templates/reports/invoice/sql/invoice.sql b/print/templates/reports/invoice/sql/invoice.sql index 0f12e4f535..303fa937f8 100644 --- a/print/templates/reports/invoice/sql/invoice.sql +++ b/print/templates/reports/invoice/sql/invoice.sql @@ -11,7 +11,7 @@ FROM invoiceOut io JOIN client c ON c.id = io.clientFk JOIN payMethod pm ON pm.id = c.payMethodFk JOIN company cny ON cny.id = io.companyFk - JOIN supplierAccount sa ON sa.id = cny.supplierAccountFk + LEFT JOIN supplierAccount sa ON sa.id = cny.supplierAccountFk LEFT JOIN invoiceOutSerial ios ON ios.code = io.serial LEFT JOIN ticket t ON t.refFk = io.ref WHERE t.refFk = ? \ No newline at end of file