From e324716f2fdd5fc9b5849e2dad5708213e89261f Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 27 Dec 2022 12:21:04 +0100 Subject: [PATCH 01/48] feat: add subsection Global invoicing --- .../back/methods/invoiceOut/invoiceClient.js | 135 +++++++----------- .../front/global-invoicing/index.html | 122 ++++++++++++++++ .../{index => }/global-invoicing/index.js | 69 ++++----- .../front/global-invoicing/index.spec.js | 126 ++++++++++++++++ .../front/global-invoicing/locale/es.yml | 7 + .../front/global-invoicing/style.scss | 5 + modules/invoiceOut/front/index.js | 2 +- .../front/index/global-invoicing/index.html | 96 ------------- modules/invoiceOut/front/index/index.html | 8 +- modules/invoiceOut/front/routes.json | 12 +- 10 files changed, 361 insertions(+), 221 deletions(-) create mode 100644 modules/invoiceOut/front/global-invoicing/index.html rename modules/invoiceOut/front/{index => }/global-invoicing/index.js (67%) create mode 100644 modules/invoiceOut/front/global-invoicing/index.spec.js create mode 100644 modules/invoiceOut/front/global-invoicing/locale/es.yml create mode 100644 modules/invoiceOut/front/global-invoicing/style.scss delete mode 100644 modules/invoiceOut/front/index/global-invoicing/index.html diff --git a/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js b/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js index 95c51a96d..72bdb3ec7 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js +++ b/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js @@ -68,63 +68,57 @@ module.exports = Self => { const client = await models.Client.findById(args.clientId, { fields: ['id', 'hasToInvoiceByAddress'] }, myOptions); - try { - if (client.hasToInvoiceByAddress) { - await Self.rawSql('CALL ticketToInvoiceByAddress(?, ?, ?, ?)', [ - args.minShipped, - args.maxShipped, - args.addressId, - args.companyFk - ], myOptions); - } else { - await Self.rawSql('CALL invoiceFromClient(?, ?, ?)', [ - args.maxShipped, - client.id, - args.companyFk - ], myOptions); - } - // Make invoice - const isSpanishCompany = await getIsSpanishCompany(args.companyFk, myOptions); - - // Validates ticket nagative base - const hasAnyNegativeBase = await getNegativeBase(myOptions); - if (hasAnyNegativeBase && isSpanishCompany) - return tx.rollback(); - - query = `SELECT invoiceSerial(?, ?, ?) AS serial`; - const [invoiceSerial] = await Self.rawSql(query, [ + if (client.hasToInvoiceByAddress) { + await Self.rawSql('CALL ticketToInvoiceByAddress(?, ?, ?, ?)', [ + args.minShipped, + args.maxShipped, + args.addressId, + args.companyFk + ], myOptions); + } else { + await Self.rawSql('CALL invoiceFromClient(?, ?, ?)', [ + args.maxShipped, client.id, - args.companyFk, - 'G' + args.companyFk ], myOptions); - const serialLetter = invoiceSerial.serial; - - query = `CALL invoiceOut_new(?, ?, NULL, @invoiceId)`; - await Self.rawSql(query, [ - serialLetter, - args.invoiceDate - ], myOptions); - - const [newInvoice] = await Self.rawSql(`SELECT @invoiceId id`, null, myOptions); - if (newInvoice.id) { - await Self.rawSql('CALL invoiceOutBooking(?)', [newInvoice.id], myOptions); - - invoiceId = newInvoice.id; - } - } catch (e) { - const failedClient = { - id: client.id, - stacktrace: e - }; - await notifyFailures(ctx, failedClient, myOptions); } - invoiceOut = await models.InvoiceOut.findById(invoiceId, { - include: { - relation: 'client' - } - }, myOptions); + // Make invoice + const isSpanishCompany = await getIsSpanishCompany(args.companyFk, myOptions); + + // Validates ticket nagative base + const hasAnyNegativeBase = await getNegativeBase(myOptions); + if (hasAnyNegativeBase && isSpanishCompany) + return tx.rollback(); + + query = `SELECT invoiceSerial(?, ?, ?) AS serial`; + const [invoiceSerial] = await Self.rawSql(query, [ + client.id, + args.companyFk, + 'G' + ], myOptions); + const serialLetter = invoiceSerial.serial; + + query = `CALL invoiceOut_new(?, ?, NULL, @invoiceId)`; + await Self.rawSql(query, [ + serialLetter, + args.invoiceDate + ], myOptions); + if (client.id == 1102) + throw new Error('Error1'); + const [newInvoice] = await Self.rawSql(`SELECT @invoiceId id`, null, myOptions); + if (newInvoice.id) { + await Self.rawSql('CALL invoiceOutBooking(?)', [newInvoice.id], myOptions); + + invoiceOut = await models.InvoiceOut.findById(newInvoice.id, { + include: { + relation: 'client' + } + }, myOptions); + + invoiceId = newInvoice.id; + } if (tx) await tx.commit(); } catch (e) { @@ -132,15 +126,14 @@ module.exports = Self => { throw e; } - ctx.args = { - reference: invoiceOut.ref, - recipientId: invoiceOut.clientFk, - recipient: invoiceOut.client().email - }; - try { + if (invoiceId) { + ctx.args = { + reference: invoiceOut.ref, + recipientId: invoiceOut.clientFk, + recipient: invoiceOut.client().email + }; await models.InvoiceOut.invoiceEmail(ctx, invoiceOut.ref); - } catch (err) {} - + } return invoiceId; }; @@ -165,26 +158,4 @@ module.exports = Self => { return supplierCompany && supplierCompany.total; } - - async function notifyFailures(ctx, failedClient, options) { - const models = Self.app.models; - const userId = ctx.req.accessToken.userId; - const $t = ctx.req.__; // $translate - - const worker = await models.EmailUser.findById(userId, null, options); - const subject = $t('Global invoicing failed'); - let body = $t(`Wasn't able to invoice the following clients`) + ':

'; - - body += `ID: ${failedClient.id} -
${failedClient.stacktrace}

`; - - await Self.rawSql(` - INSERT INTO vn.mail (sender, replyTo, sent, subject, body) - VALUES (?, ?, FALSE, ?, ?)`, [ - worker.email, - worker.email, - subject, - body - ], options); - } }; diff --git a/modules/invoiceOut/front/global-invoicing/index.html b/modules/invoiceOut/front/global-invoicing/index.html new file mode 100644 index 000000000..1b14a72f6 --- /dev/null +++ b/modules/invoiceOut/front/global-invoicing/index.html @@ -0,0 +1,122 @@ +
+ + + + + + Id + Status + + + + + + + {{::client.id}} + + + + + + + + + + + + + + + +
+ + + + + + +
+ + + + + + + + + + + + + + + {{::id}} - {{::name}} + + + {{::id}} - {{::name}} + + + + + + + + +
+
+ + + diff --git a/modules/invoiceOut/front/index/global-invoicing/index.js b/modules/invoiceOut/front/global-invoicing/index.js similarity index 67% rename from modules/invoiceOut/front/index/global-invoicing/index.js rename to modules/invoiceOut/front/global-invoicing/index.js index f772a4936..0750d8d6c 100644 --- a/modules/invoiceOut/front/index/global-invoicing/index.js +++ b/modules/invoiceOut/front/global-invoicing/index.js @@ -1,12 +1,14 @@ -import ngModule from '../../module'; -import Dialog from 'core/components/dialog'; +import ngModule from '../module'; +import Section from 'salix/components/section'; +import UserError from 'core/lib/user-error'; import './style.scss'; -class Controller extends Dialog { +class Controller extends Section { constructor($element, $, $transclude) { super($element, $, $transclude); this.invoice = { - maxShipped: new Date() + maxShipped: new Date(), + companyFk: this.vnConfig.companyFk }; this.clientsNumber = 'allClients'; } @@ -37,14 +39,6 @@ class Controller extends Dialog { return this.$http.get('Clients/findOne', {params}); } - get companyFk() { - return this.invoice.companyFk; - } - - set companyFk(value) { - this.invoice.companyFk = value; - } - restartValues() { this.lastClientId = null; this.$.invoiceButton.disabled = false; @@ -69,45 +63,51 @@ class Controller extends Dialog { }; - const options = this.cancelRequest(); - - return this.$http.post(`InvoiceOuts/invoiceClient`, params, options) + const index = this.$.data.findIndex(element => element.id == clientAndAddress.clientId); + return this.$http.post(`InvoiceOuts/invoiceClient`, params) .then(() => { + this.$.data[index].status = 'ok'; + }).catch(() => { + this.$.data[index].status = 'error'; + }).finally(() => { clientsAndAddresses.shift(); return this.invoiceOut(invoice, clientsAndAddresses); }); } - responseHandler(response) { + makeInvoice() { try { - if (response !== 'accept') - return super.responseHandler(response); - if (!this.invoice.invoiceDate || !this.invoice.maxShipped) throw new Error('Invoice date and the max date should be filled'); if (!this.invoice.fromClientId || !this.invoice.toClientId) throw new Error('Choose a valid clients range'); - this.on('close', () => { - if (this.canceler) this.canceler.resolve(); - this.vnApp.showSuccess(this.$t('Data saved!')); - }); - this.$.invoiceButton.disabled = true; this.packageInvoicing = true; - const options = this.cancelRequest(); - this.$http.post(`InvoiceOuts/clientsToInvoice`, this.invoice, options) + this.$http.post(`InvoiceOuts/clientsToInvoice`, this.invoice) .then(res => { this.packageInvoicing = false; const invoice = res.data.invoice; + + const clientsIds = []; + for (const clientAndAddress of res.data.clientsAndAddresses) + clientsIds.push(clientAndAddress.clientId); + const dataArr = new Set(clientsIds); + const clientsIdsNoRepeat = [...dataArr]; + const clients = clientsIdsNoRepeat.map(clientId => { + return { + id: clientId, + status: 'waiting' + }; + }); + this.$.data = clients; + const clientsAndAddresses = res.data.clientsAndAddresses; - if (!clientsAndAddresses.length) return super.responseHandler(response); - this.lastClientId = clientsAndAddresses[clientsAndAddresses.length - 1].clientId; + if (!clientsAndAddresses.length) throw new UserError(`There aren't clients to invoice`); return this.invoiceOut(invoice, clientsAndAddresses); }) - .then(() => super.responseHandler(response)) .then(() => this.vnApp.showSuccess(this.$t('Data saved!'))) .finally(() => this.restartValues()); } catch (e) { @@ -116,14 +116,15 @@ class Controller extends Dialog { return false; } } + + clean() { + this.$.data = this.$.data.filter(client => client.status == 'error'); + } } Controller.$inject = ['$element', '$scope', '$transclude']; ngModule.vnComponent('vnInvoiceOutGlobalInvoicing', { - slotTemplate: require('./index.html'), - controller: Controller, - bindings: { - companyFk: ' { + let $httpBackend; + let controller; + let $element; + + beforeEach(ngModule('zone')); + + beforeEach(inject(($componentController, _$httpBackend_) => { + $httpBackend = _$httpBackend_; + $element = angular.element(' { + it('should set the deliveryMethodFk property as pickup and then perform a query that sets the filter', () => { + $httpBackend.expect('GET', 'DeliveryMethods').respond([{id: 999}]); + controller.deliveryMethodFk = 'pickUp'; + $httpBackend.flush(); + + expect(controller.agencyFilter).toEqual({deliveryMethodFk: {inq: [999]}}); + }); + }); + + describe('setParams()', () => { + it('should do nothing when no params are received', () => { + controller.setParams(); + + expect(controller.deliveryMethodFk).toBeUndefined(); + expect(controller.geoFk).toBeUndefined(); + expect(controller.agencyModeFk).toBeUndefined(); + }); + + it('should set the controller properties when the params are provided', () => { + controller.$params = { + deliveryMethodFk: 3, + geoFk: 2, + agencyModeFk: 1 + }; + controller.setParams(); + + expect(controller.deliveryMethodFk).toEqual(controller.$params.deliveryMethodFk); + expect(controller.geoFk).toEqual(controller.$params.geoFk); + expect(controller.agencyModeFk).toEqual(controller.$params.agencyModeFk); + }); + }); + + describe('fetchData()', () => { + it('should make an HTTP GET query and then call the showMessage() method', () => { + jest.spyOn(controller.vnApp, 'showMessage'); + jest.spyOn(controller.$state, 'go'); + + controller.agencyModeFk = 1; + controller.deliveryMethodFk = 2; + controller.geoFk = 3; + controller.$state.current.name = 'myState'; + + const expectedData = {events: []}; + + const url = 'Zones/getEvents?agencyModeFk=1&deliveryMethodFk=2&geoFk=3'; + + $httpBackend.when('GET', 'DeliveryMethods').respond([]); + $httpBackend.expect('GET', url).respond({events: []}); + controller.fetchData(); + $httpBackend.flush(); + + expect(controller.$.data).toEqual(expectedData); + expect(controller.vnApp.showMessage).toHaveBeenCalledWith('No service for the specified zone'); + expect(controller.$state.go).toHaveBeenCalledWith( + controller.$state.current.name, + { + agencyModeFk: 1, + deliveryMethodFk: 2, + geoFk: 3 + } + ); + }); + }); + + describe('onSelection()', () => { + it('should not call the show popover method if events array is empty', () => { + jest.spyOn(controller.$.zoneEvents, 'show'); + + const event = new Event('click'); + const target = document.createElement('div'); + target.dispatchEvent(event); + const events = []; + controller.onSelection(event, events); + + expect(controller.$.zoneEvents.show).not.toHaveBeenCalled(); + }); + + it('should call the show() method and call getZoneClosing() with the expected ids', () => { + jest.spyOn(controller.$.zoneEvents, 'show'); + + const event = new Event('click'); + const target = document.createElement('div'); + target.dispatchEvent(event); + + const day = new Date(); + const events = [ + {zoneFk: 1}, + {zoneFk: 2}, + {zoneFk: 8} + ]; + const params = { + zoneIds: [1, 2, 8], + date: [day][0] + }; + const response = [{id: 1, hour: ''}]; + + $httpBackend.when('POST', 'Zones/getZoneClosing', params).respond({response}); + controller.onSelection(event, events, [day]); + $httpBackend.flush(); + + expect(controller.$.zoneEvents.show).toHaveBeenCalledWith(target); + expect(controller.zoneClosing.id).toEqual(response.id); + }); + }); +}); diff --git a/modules/invoiceOut/front/global-invoicing/locale/es.yml b/modules/invoiceOut/front/global-invoicing/locale/es.yml new file mode 100644 index 000000000..5c556fa39 --- /dev/null +++ b/modules/invoiceOut/front/global-invoicing/locale/es.yml @@ -0,0 +1,7 @@ +There aren't clients to invoice: No existen clientes para facturar +Max date: Fecha límite +Invoice date: Fecha de factura +Invoice date and the max date should be filled: La fecha de factura y la fecha límite deben rellenarse +Choose a valid clients range: Selecciona un rango válido de clientes +Clients range: Rango de clientes +Calculating packages to invoice...: Calculando paquetes a factura... diff --git a/modules/invoiceOut/front/global-invoicing/style.scss b/modules/invoiceOut/front/global-invoicing/style.scss new file mode 100644 index 000000000..41dd3fac2 --- /dev/null +++ b/modules/invoiceOut/front/global-invoicing/style.scss @@ -0,0 +1,5 @@ +@import "variables"; + +.error { + color: $color-alert; + } diff --git a/modules/invoiceOut/front/index.js b/modules/invoiceOut/front/index.js index 0307b2b4b..f7cebc0d0 100644 --- a/modules/invoiceOut/front/index.js +++ b/modules/invoiceOut/front/index.js @@ -9,4 +9,4 @@ import './descriptor'; import './descriptor-popover'; import './descriptor-menu'; import './index/manual'; -import './index/global-invoicing'; +import './global-invoicing'; diff --git a/modules/invoiceOut/front/index/global-invoicing/index.html b/modules/invoiceOut/front/index/global-invoicing/index.html deleted file mode 100644 index c2d1c4304..000000000 --- a/modules/invoiceOut/front/index/global-invoicing/index.html +++ /dev/null @@ -1,96 +0,0 @@ - - Create global invoice - - - - - - -
- -
- {{'Calculating packages to invoice...' | translate}} -
-
-
-
- -
- {{'Id Client' | translate}}: {{$ctrl.currentClientId}} - {{'of' | translate}} {{::$ctrl.lastClientId}} -
-
-
- - - - - - - - - - - - - - - {{::id}} - {{::name}} - - - {{::id}} - {{::name}} - - - - - - -
- - - {{$ctrl.isInvoicing}} - \ No newline at end of file diff --git a/modules/invoiceOut/front/index/index.html b/modules/invoiceOut/front/index/index.html index e2cf2120a..e2b0c221f 100644 --- a/modules/invoiceOut/front/index/index.html +++ b/modules/invoiceOut/front/index/index.html @@ -18,7 +18,7 @@ - @@ -37,7 +37,7 @@ class="clickable vn-tr search-result" ui-sref="invoiceOut.card.summary({id: {{::invoiceOut.id}}})"> - @@ -103,7 +103,3 @@ - - \ No newline at end of file diff --git a/modules/invoiceOut/front/routes.json b/modules/invoiceOut/front/routes.json index 09d9f3d33..c396a5334 100644 --- a/modules/invoiceOut/front/routes.json +++ b/modules/invoiceOut/front/routes.json @@ -6,7 +6,9 @@ "dependencies": ["worker", "client", "ticket"], "menus": { "main": [ - {"state": "invoiceOut.index", "icon": "icon-invoice-out"} + {"state": "invoiceOut.index", "icon": "icon-invoice-out"}, + {"state": "invoiceOut.global-invoicing", "icon": "contact_support"} + ] }, "routes": [ @@ -24,6 +26,12 @@ "component": "vn-invoice-out-index", "description": "InvoiceOut" }, + { + "url": "/global-invoicing?q", + "state": "invoiceOut.global-invoicing", + "component": "vn-invoice-out-global-invoicing", + "description": "Global invoicing" + }, { "url": "/summary", "state": "invoiceOut.card.summary", @@ -40,4 +48,4 @@ "component": "vn-invoice-out-card" } ] -} \ No newline at end of file +} From b406551f52f4b2e199a113dd1034c57baf29d678 Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 27 Dec 2022 12:21:12 +0100 Subject: [PATCH 02/48] delete: old section --- .../index/global-invoicing/index.spec.js | 118 ------------------ .../index/global-invoicing/locale/es.yml | 14 --- .../front/index/global-invoicing/style.scss | 17 --- 3 files changed, 149 deletions(-) delete mode 100644 modules/invoiceOut/front/index/global-invoicing/index.spec.js delete mode 100644 modules/invoiceOut/front/index/global-invoicing/locale/es.yml delete mode 100644 modules/invoiceOut/front/index/global-invoicing/style.scss diff --git a/modules/invoiceOut/front/index/global-invoicing/index.spec.js b/modules/invoiceOut/front/index/global-invoicing/index.spec.js deleted file mode 100644 index e88b0b1d4..000000000 --- a/modules/invoiceOut/front/index/global-invoicing/index.spec.js +++ /dev/null @@ -1,118 +0,0 @@ -import './index'; - -describe('InvoiceOut', () => { - describe('Component vnInvoiceOutGlobalInvoicing', () => { - let controller; - let $httpBackend; - let $httpParamSerializer; - - beforeEach(ngModule('invoiceOut')); - - beforeEach(inject(($componentController, $rootScope, _$httpBackend_, _$httpParamSerializer_) => { - $httpBackend = _$httpBackend_; - $httpParamSerializer = _$httpParamSerializer_; - let $scope = $rootScope.$new(); - const $element = angular.element(''); - const $transclude = { - $$boundTransclude: { - $$slots: [] - } - }; - controller = $componentController('vnInvoiceOutGlobalInvoicing', {$element, $scope, $transclude}); - controller.$.invoiceButton = {disabled: false}; - })); - - describe('getMinClientId()', () => { - it('should set the invoice fromClientId property', () => { - const filter = { - order: 'id ASC', - limit: 1 - }; - - const serializedParams = $httpParamSerializer({filter}); - $httpBackend.expectGET(`Clients/findOne?${serializedParams}`).respond(200, {id: 1101}); - - controller.getMinClientId(); - $httpBackend.flush(); - - expect(controller.invoice.fromClientId).toEqual(1101); - }); - }); - - describe('getMaxClientId()', () => { - it('should set the invoice toClientId property', () => { - const filter = { - order: 'id DESC', - limit: 1 - }; - - const serializedParams = $httpParamSerializer({filter}); - $httpBackend.expectGET(`Clients/findOne?${serializedParams}`).respond(200, {id: 1112}); - - controller.getMaxClientId(); - $httpBackend.flush(); - - expect(controller.invoice.toClientId).toEqual(1112); - }); - }); - - describe('responseHandler()', () => { - it('should throw an error when invoiceDate or maxShipped properties are not filled in', () => { - jest.spyOn(controller.vnApp, 'showError'); - - controller.invoice = { - fromClientId: 1101, - toClientId: 1101 - }; - - controller.responseHandler('accept'); - - const expectedError = 'Invoice date and the max date should be filled'; - - expect(controller.vnApp.showError).toHaveBeenCalledWith(expectedError); - }); - - it('should throw an error when fromClientId or toClientId properties are not filled in', () => { - jest.spyOn(controller.vnApp, 'showError'); - - controller.invoice = { - invoiceDate: new Date(), - maxShipped: new Date() - }; - - controller.responseHandler('accept'); - - expect(controller.vnApp.showError).toHaveBeenCalledWith(`Choose a valid clients range`); - }); - - it('should make an http POST query and then call to the showSuccess() method', () => { - jest.spyOn(controller.vnApp, 'showSuccess'); - - const minShipped = new Date(); - minShipped.setFullYear(minShipped.getFullYear() - 1); - minShipped.setMonth(1); - minShipped.setDate(1); - minShipped.setHours(0, 0, 0, 0); - controller.invoice = { - invoiceDate: new Date(), - maxShipped: new Date(), - fromClientId: 1101, - toClientId: 1101, - companyFk: 442, - minShipped: minShipped - }; - const response = { - clientsAndAddresses: [{clientId: 1101, addressId: 121}], - invoice: controller.invoice - }; - - $httpBackend.expect('POST', `InvoiceOuts/clientsToInvoice`).respond(response); - $httpBackend.expect('POST', `InvoiceOuts/invoiceClient`).respond({id: 1}); - controller.responseHandler('accept'); - $httpBackend.flush(); - - expect(controller.vnApp.showSuccess).toHaveBeenCalled(); - }); - }); - }); -}); diff --git a/modules/invoiceOut/front/index/global-invoicing/locale/es.yml b/modules/invoiceOut/front/index/global-invoicing/locale/es.yml deleted file mode 100644 index af151684f..000000000 --- a/modules/invoiceOut/front/index/global-invoicing/locale/es.yml +++ /dev/null @@ -1,14 +0,0 @@ -Create global invoice: Crear factura global -Some fields are required: Algunos campos son obligatorios -Max date: Fecha límite -Adding invoices to queue...: Añadiendo facturas a la cola... -Invoice date: Fecha de factura -From client: Desde el cliente -To client: Hasta el cliente -Invoice date and the max date should be filled: La fecha de factura y la fecha límite deben rellenarse -Choose a valid clients range: Selecciona un rango válido de clientes -of: de -Id Client: Id Cliente -All clients: Todos los clientes -Clients range: Rango de clientes -Calculating packages to invoice...: Calculando paquetes a factura... \ No newline at end of file diff --git a/modules/invoiceOut/front/index/global-invoicing/style.scss b/modules/invoiceOut/front/index/global-invoicing/style.scss deleted file mode 100644 index d0bd9e214..000000000 --- a/modules/invoiceOut/front/index/global-invoicing/style.scss +++ /dev/null @@ -1,17 +0,0 @@ -@import "variables"; - -.vn-invoice-out-global-invoicing { - tpl-body { - width: 500px; - - .progress { - font-weight: bold; - text-align: center; - font-size: 1.5rem; - color: $color-primary; - vn-horizontal { - justify-content: center - } - } - } -} \ No newline at end of file From 7b8a9791b4af49f3b98ef140484fae917905ec30 Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 27 Dec 2022 13:50:10 +0100 Subject: [PATCH 03/48] refactor: code --- .../front/global-invoicing/index.html | 88 +++++++++---------- .../front/global-invoicing/index.js | 26 ++---- .../front/global-invoicing/locale/es.yml | 2 + 3 files changed, 55 insertions(+), 61 deletions(-) diff --git a/modules/invoiceOut/front/global-invoicing/index.html b/modules/invoiceOut/front/global-invoicing/index.html index 1b14a72f6..ed772cf9c 100644 --- a/modules/invoiceOut/front/global-invoicing/index.html +++ b/modules/invoiceOut/front/global-invoicing/index.html @@ -1,46 +1,46 @@ -
- - - - - - Id - Status - - - - - - - {{::client.id}} - - - - - - - - - - - - - - - -
+

{{'Calculating packages to invoice...'}}

+ + + + + Id + Address + Status + + + + + + + {{::client.id}} + + + + {{::client.address}} + + + + + + + + + + + + + + - + diff --git a/modules/invoiceOut/front/global-invoicing/index.js b/modules/invoiceOut/front/global-invoicing/index.js index 0750d8d6c..07d76626d 100644 --- a/modules/invoiceOut/front/global-invoicing/index.js +++ b/modules/invoiceOut/front/global-invoicing/index.js @@ -40,7 +40,6 @@ class Controller extends Section { } restartValues() { - this.lastClientId = null; this.$.invoiceButton.disabled = false; } @@ -52,7 +51,6 @@ class Controller extends Section { invoiceOut(invoice, clientsAndAddresses) { const [clientAndAddress] = clientsAndAddresses; if (!clientAndAddress) return; - this.currentClientId = clientAndAddress.clientId; const params = { clientId: clientAndAddress.clientId, addressId: clientAndAddress.addressId, @@ -63,7 +61,14 @@ class Controller extends Section { }; - const index = this.$.data.findIndex(element => element.id == clientAndAddress.clientId); + this.$.data.push({ + id: clientAndAddress.clientId, + address: clientAndAddress.addressId, + status: 'waiting' + }); + const index = this.$.data.findIndex( + client => client.id == clientAndAddress.clientId && client.address == clientAndAddress.addressId + ); return this.$http.post(`InvoiceOuts/invoiceClient`, params) .then(() => { this.$.data[index].status = 'ok'; @@ -84,26 +89,13 @@ class Controller extends Section { throw new Error('Choose a valid clients range'); this.$.invoiceButton.disabled = true; + this.$.data = []; this.packageInvoicing = true; this.$http.post(`InvoiceOuts/clientsToInvoice`, this.invoice) .then(res => { this.packageInvoicing = false; const invoice = res.data.invoice; - - const clientsIds = []; - for (const clientAndAddress of res.data.clientsAndAddresses) - clientsIds.push(clientAndAddress.clientId); - const dataArr = new Set(clientsIds); - const clientsIdsNoRepeat = [...dataArr]; - const clients = clientsIdsNoRepeat.map(clientId => { - return { - id: clientId, - status: 'waiting' - }; - }); - this.$.data = clients; - const clientsAndAddresses = res.data.clientsAndAddresses; if (!clientsAndAddresses.length) throw new UserError(`There aren't clients to invoice`); return this.invoiceOut(invoice, clientsAndAddresses); diff --git a/modules/invoiceOut/front/global-invoicing/locale/es.yml b/modules/invoiceOut/front/global-invoicing/locale/es.yml index 5c556fa39..3a0176845 100644 --- a/modules/invoiceOut/front/global-invoicing/locale/es.yml +++ b/modules/invoiceOut/front/global-invoicing/locale/es.yml @@ -4,4 +4,6 @@ Invoice date: Fecha de factura Invoice date and the max date should be filled: La fecha de factura y la fecha límite deben rellenarse Choose a valid clients range: Selecciona un rango válido de clientes Clients range: Rango de clientes +All clients: Todos los clientes Calculating packages to invoice...: Calculando paquetes a factura... +Clean: Limpiar From 4295ae010834b6c9745b95c262ecdf4fc6823738 Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 27 Dec 2022 14:17:16 +0100 Subject: [PATCH 04/48] delete --- modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js b/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js index 72bdb3ec7..53e1023ba 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js +++ b/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js @@ -105,8 +105,9 @@ module.exports = Self => { serialLetter, args.invoiceDate ], myOptions); - if (client.id == 1102) + if (client.id == 1101 && args.addressId == 121) throw new Error('Error1'); + const [newInvoice] = await Self.rawSql(`SELECT @invoiceId id`, null, myOptions); if (newInvoice.id) { await Self.rawSql('CALL invoiceOutBooking(?)', [newInvoice.id], myOptions); From 4579758ba6ff8b434de956f4361ab73fce5fe4b3 Mon Sep 17 00:00:00 2001 From: vicent Date: Thu, 29 Dec 2022 07:20:07 +0100 Subject: [PATCH 05/48] refactor: add translation --- modules/invoiceOut/front/global-invoicing/index.html | 4 +--- modules/invoiceOut/front/global-invoicing/locale/es.yml | 2 ++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/invoiceOut/front/global-invoicing/index.html b/modules/invoiceOut/front/global-invoicing/index.html index ed772cf9c..cb720d674 100644 --- a/modules/invoiceOut/front/global-invoicing/index.html +++ b/modules/invoiceOut/front/global-invoicing/index.html @@ -67,8 +67,6 @@ label="Max date" ng-model="$ctrl.invoice.maxShipped"> - - - + Date: Thu, 29 Dec 2022 08:15:04 +0100 Subject: [PATCH 06/48] =?UTF-8?q?feat:=20mostrar=20fallos,=20mostrar=20m?= =?UTF-8?q?=C3=A1s=20datos=20y=20actualizar=20estilo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../back/methods/invoiceOut/invoiceClient.js | 2 +- .../front/global-invoicing/index.html | 24 +++++++---- .../front/global-invoicing/index.js | 40 +++++++++++-------- .../front/global-invoicing/locale/es.yml | 1 + .../front/global-invoicing/style.scss | 9 ++++- 5 files changed, 49 insertions(+), 27 deletions(-) diff --git a/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js b/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js index 53e1023ba..d7674cdd8 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js +++ b/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js @@ -106,7 +106,7 @@ module.exports = Self => { args.invoiceDate ], myOptions); if (client.id == 1101 && args.addressId == 121) - throw new Error('Error1'); + throw new Error('No se ha podido facturar'); const [newInvoice] = await Self.rawSql(`SELECT @invoiceId id`, null, myOptions); if (newInvoice.id) { diff --git a/modules/invoiceOut/front/global-invoicing/index.html b/modules/invoiceOut/front/global-invoicing/index.html index cb720d674..a59475297 100644 --- a/modules/invoiceOut/front/global-invoicing/index.html +++ b/modules/invoiceOut/front/global-invoicing/index.html @@ -3,15 +3,17 @@ - Id - Address - Status + Client id + Nickname + Address id + Street + - + @@ -19,9 +21,15 @@ - {{::client.address}} + {{::client.address.nickname}} - + + {{::client.address.id}} + + + {{::client.address.street}} + + @@ -31,9 +39,9 @@ icon="check"> + icon="clear"> diff --git a/modules/invoiceOut/front/global-invoicing/index.js b/modules/invoiceOut/front/global-invoicing/index.js index 07d76626d..89487d440 100644 --- a/modules/invoiceOut/front/global-invoicing/index.js +++ b/modules/invoiceOut/front/global-invoicing/index.js @@ -61,22 +61,30 @@ class Controller extends Section { }; - this.$.data.push({ - id: clientAndAddress.clientId, - address: clientAndAddress.addressId, - status: 'waiting' - }); - const index = this.$.data.findIndex( - client => client.id == clientAndAddress.clientId && client.address == clientAndAddress.addressId - ); - return this.$http.post(`InvoiceOuts/invoiceClient`, params) - .then(() => { - this.$.data[index].status = 'ok'; - }).catch(() => { - this.$.data[index].status = 'error'; - }).finally(() => { - clientsAndAddresses.shift(); - return this.invoiceOut(invoice, clientsAndAddresses); + this.$http.get(`Addresses/${clientAndAddress.addressId}`) + .then(res => { + this.address = res.data; + + this.$.data.push({ + id: clientAndAddress.clientId, + address: this.address, + status: 'waiting' + }); + + const index = this.$.data.findIndex( + client => client.id == clientAndAddress.clientId && client.address.id == clientAndAddress.addressId + ); + + return this.$http.post(`InvoiceOuts/invoiceClient`, params) + .then(() => { + this.$.data[index].status = 'ok'; + }).catch(res => { + this.$.data[index].status = 'error'; + this.$.data[index].error = res.data.error.message; + }).finally(() => { + clientsAndAddresses.shift(); + return this.invoiceOut(invoice, clientsAndAddresses); + }); }); } diff --git a/modules/invoiceOut/front/global-invoicing/locale/es.yml b/modules/invoiceOut/front/global-invoicing/locale/es.yml index 72826134d..84cfe43ad 100644 --- a/modules/invoiceOut/front/global-invoicing/locale/es.yml +++ b/modules/invoiceOut/front/global-invoicing/locale/es.yml @@ -9,3 +9,4 @@ Calculating packages to invoice...: Calculando paquetes a factura... Clean: Limpiar From client: Desde cliente To client: Hasta cliente +Address id: Id dirección diff --git a/modules/invoiceOut/front/global-invoicing/style.scss b/modules/invoiceOut/front/global-invoicing/style.scss index 41dd3fac2..d67df4479 100644 --- a/modules/invoiceOut/front/global-invoicing/style.scss +++ b/modules/invoiceOut/front/global-invoicing/style.scss @@ -1,5 +1,10 @@ @import "variables"; -.error { - color: $color-alert; +vn-td { + vn-icon[icon=clear] { + color: $color-alert; } + vn-icon[icon=check] { + color: $color-success; + } +} From 2b62e16164d0718c54314be5bda3436f28d54f46 Mon Sep 17 00:00:00 2001 From: vicent Date: Thu, 29 Dec 2022 11:47:12 +0100 Subject: [PATCH 07/48] fix: test --- .../back/methods/invoiceOut/invoiceClient.js | 2 - .../front/global-invoicing/index.spec.js | 227 +++++++++--------- 2 files changed, 111 insertions(+), 118 deletions(-) diff --git a/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js b/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js index d7674cdd8..154546d73 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js +++ b/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js @@ -105,8 +105,6 @@ module.exports = Self => { serialLetter, args.invoiceDate ], myOptions); - if (client.id == 1101 && args.addressId == 121) - throw new Error('No se ha podido facturar'); const [newInvoice] = await Self.rawSql(`SELECT @invoiceId id`, null, myOptions); if (newInvoice.id) { diff --git a/modules/invoiceOut/front/global-invoicing/index.spec.js b/modules/invoiceOut/front/global-invoicing/index.spec.js index 63c87fbea..2a505e6b6 100644 --- a/modules/invoiceOut/front/global-invoicing/index.spec.js +++ b/modules/invoiceOut/front/global-invoicing/index.spec.js @@ -1,126 +1,121 @@ -import './index.js'; -import popover from 'core/mocks/popover'; -import crudModel from 'core/mocks/crud-model'; +import './index'; -describe('Zone Component vnZoneDeliveryDays', () => { - let $httpBackend; - let controller; - let $element; +describe('InvoiceOut', () => { + describe('Component vnInvoiceOutGlobalInvoicing', () => { + let controller; + let $httpBackend; + let $httpParamSerializer; - beforeEach(ngModule('zone')); + beforeEach(ngModule('invoiceOut')); - beforeEach(inject(($componentController, _$httpBackend_) => { - $httpBackend = _$httpBackend_; - $element = angular.element(' { - it('should set the deliveryMethodFk property as pickup and then perform a query that sets the filter', () => { - $httpBackend.expect('GET', 'DeliveryMethods').respond([{id: 999}]); - controller.deliveryMethodFk = 'pickUp'; - $httpBackend.flush(); - - expect(controller.agencyFilter).toEqual({deliveryMethodFk: {inq: [999]}}); - }); - }); - - describe('setParams()', () => { - it('should do nothing when no params are received', () => { - controller.setParams(); - - expect(controller.deliveryMethodFk).toBeUndefined(); - expect(controller.geoFk).toBeUndefined(); - expect(controller.agencyModeFk).toBeUndefined(); - }); - - it('should set the controller properties when the params are provided', () => { - controller.$params = { - deliveryMethodFk: 3, - geoFk: 2, - agencyModeFk: 1 - }; - controller.setParams(); - - expect(controller.deliveryMethodFk).toEqual(controller.$params.deliveryMethodFk); - expect(controller.geoFk).toEqual(controller.$params.geoFk); - expect(controller.agencyModeFk).toEqual(controller.$params.agencyModeFk); - }); - }); - - describe('fetchData()', () => { - it('should make an HTTP GET query and then call the showMessage() method', () => { - jest.spyOn(controller.vnApp, 'showMessage'); - jest.spyOn(controller.$state, 'go'); - - controller.agencyModeFk = 1; - controller.deliveryMethodFk = 2; - controller.geoFk = 3; - controller.$state.current.name = 'myState'; - - const expectedData = {events: []}; - - const url = 'Zones/getEvents?agencyModeFk=1&deliveryMethodFk=2&geoFk=3'; - - $httpBackend.when('GET', 'DeliveryMethods').respond([]); - $httpBackend.expect('GET', url).respond({events: []}); - controller.fetchData(); - $httpBackend.flush(); - - expect(controller.$.data).toEqual(expectedData); - expect(controller.vnApp.showMessage).toHaveBeenCalledWith('No service for the specified zone'); - expect(controller.$state.go).toHaveBeenCalledWith( - controller.$state.current.name, - { - agencyModeFk: 1, - deliveryMethodFk: 2, - geoFk: 3 + beforeEach(inject(($componentController, $rootScope, _$httpBackend_, _$httpParamSerializer_) => { + $httpBackend = _$httpBackend_; + $httpParamSerializer = _$httpParamSerializer_; + let $scope = $rootScope.$new(); + const $element = angular.element(''); + const $transclude = { + $$boundTransclude: { + $$slots: [] } - ); - }); - }); - - describe('onSelection()', () => { - it('should not call the show popover method if events array is empty', () => { - jest.spyOn(controller.$.zoneEvents, 'show'); - - const event = new Event('click'); - const target = document.createElement('div'); - target.dispatchEvent(event); - const events = []; - controller.onSelection(event, events); - - expect(controller.$.zoneEvents.show).not.toHaveBeenCalled(); - }); - - it('should call the show() method and call getZoneClosing() with the expected ids', () => { - jest.spyOn(controller.$.zoneEvents, 'show'); - - const event = new Event('click'); - const target = document.createElement('div'); - target.dispatchEvent(event); - - const day = new Date(); - const events = [ - {zoneFk: 1}, - {zoneFk: 2}, - {zoneFk: 8} - ]; - const params = { - zoneIds: [1, 2, 8], - date: [day][0] }; - const response = [{id: 1, hour: ''}]; + controller = $componentController('vnInvoiceOutGlobalInvoicing', {$element, $scope, $transclude}); + controller.$.invoiceButton = {disabled: false}; + })); - $httpBackend.when('POST', 'Zones/getZoneClosing', params).respond({response}); - controller.onSelection(event, events, [day]); - $httpBackend.flush(); + describe('getMinClientId()', () => { + it('should set the invoice fromClientId property', () => { + const filter = { + order: 'id ASC', + limit: 1 + }; - expect(controller.$.zoneEvents.show).toHaveBeenCalledWith(target); - expect(controller.zoneClosing.id).toEqual(response.id); + const serializedParams = $httpParamSerializer({filter}); + $httpBackend.expectGET(`Clients/findOne?${serializedParams}`).respond(200, {id: 1101}); + + controller.getMinClientId(); + $httpBackend.flush(); + + expect(controller.invoice.fromClientId).toEqual(1101); + }); + }); + + describe('getMaxClientId()', () => { + it('should set the invoice toClientId property', () => { + const filter = { + order: 'id DESC', + limit: 1 + }; + + const serializedParams = $httpParamSerializer({filter}); + $httpBackend.expectGET(`Clients/findOne?${serializedParams}`).respond(200, {id: 1112}); + + controller.getMaxClientId(); + $httpBackend.flush(); + + expect(controller.invoice.toClientId).toEqual(1112); + }); + }); + + describe('makeInvoice()', () => { + it('should throw an error when invoiceDate or maxShipped properties are not filled in', () => { + jest.spyOn(controller.vnApp, 'showError'); + + controller.invoice = { + fromClientId: 1101, + toClientId: 1101 + }; + + controller.makeInvoice(); + + const expectedError = 'Invoice date and the max date should be filled'; + + expect(controller.vnApp.showError).toHaveBeenCalledWith(expectedError); + }); + + it('should throw an error when fromClientId or toClientId properties are not filled in', () => { + jest.spyOn(controller.vnApp, 'showError'); + + controller.invoice = { + invoiceDate: new Date(), + maxShipped: new Date() + }; + + controller.makeInvoice(); + + expect(controller.vnApp.showError).toHaveBeenCalledWith(`Choose a valid clients range`); + }); + + it('should make an http POST query and then call to the showSuccess() method', () => { + jest.spyOn(controller.vnApp, 'showSuccess'); + + const minShipped = new Date(); + minShipped.setFullYear(minShipped.getFullYear() - 1); + minShipped.setMonth(1); + minShipped.setDate(1); + minShipped.setHours(0, 0, 0, 0); + controller.invoice = { + invoiceDate: new Date(), + maxShipped: new Date(), + fromClientId: 1101, + toClientId: 1101, + companyFk: 442, + minShipped: minShipped + }; + const response = { + clientsAndAddresses: [{clientId: 1101, addressId: 121}], + invoice: controller.invoice + }; + + const address = {id: 121}; + + $httpBackend.expect('POST', `InvoiceOuts/clientsToInvoice`).respond(response); + $httpBackend.expect('GET', `Addresses/${response.clientsAndAddresses[0].addressId}`).respond(address); + $httpBackend.expect('POST', `InvoiceOuts/invoiceClient`).respond({id: 1}); + controller.makeInvoice(); + $httpBackend.flush(); + + expect(controller.vnApp.showSuccess).toHaveBeenCalled(); + }); }); }); }); From d16235cba921625dc0b6abcc95715826a01dca6b Mon Sep 17 00:00:00 2001 From: vicent Date: Thu, 5 Jan 2023 10:55:56 +0100 Subject: [PATCH 08/48] fix: show error when is negative base --- loopback/locale/es.json | 5 +++-- modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js | 4 +++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/loopback/locale/es.json b/loopback/locale/es.json index ea83b36c4..2c1a08f46 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -135,7 +135,7 @@ "Changed client paymethod": "He cambiado la forma de pago del cliente [{{clientName}} ({{clientId}})]({{{url}}})", "Sent units from ticket": "Envio *{{quantity}}* unidades de [{{concept}} ({{itemId}})]({{{itemUrl}}}) a *\"{{nickname}}\"* provenientes del ticket id [{{ticketId}}]({{{ticketUrl}}})", "Change quantity": "{{concept}} cambia de {{oldQuantity}} a {{newQuantity}}", - "Claim will be picked": "Se recogerá el género de la reclamación [({{claimId}})]({{{claimUrl}}}) del cliente *{{clientName}}*", + "Claim will be picked": "Se recogerá el género de la reclamación [({{claimId}})]({{{claimUrl}}}) del cliente *{{clientName}}*", "Claim state has changed to incomplete": "Se ha cambiado el estado de la reclamación [({{claimId}})]({{{claimUrl}}}) del cliente *{{clientName}}* a *incompleta*", "Claim state has changed to canceled": "Se ha cambiado el estado de la reclamación [({{claimId}})]({{{claimUrl}}}) del cliente *{{clientName}}* a *anulado*", "Client checked as validated despite of duplication": "Cliente comprobado a pesar de que existe el cliente id {{clientId}}", @@ -252,5 +252,6 @@ "Receipt's bank was not found": "No se encontró el banco del recibo", "This receipt was not compensated": "Este recibo no ha sido compensado", "Client's email was not found": "No se encontró el email del cliente", - "Aplicación bloqueada por el usuario 9": "Aplicación bloqueada por el usuario 9" + "Aplicación bloqueada por el usuario 9": "Aplicación bloqueada por el usuario 9", + "Negative basis": "Negative basis" } \ No newline at end of file diff --git a/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js b/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js index 154546d73..017acf8b5 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js +++ b/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js @@ -1,3 +1,5 @@ +const UserError = require('vn-loopback/util/user-error'); + module.exports = Self => { Self.remoteMethodCtx('invoiceClient', { description: 'Make a invoice of a client', @@ -90,7 +92,7 @@ module.exports = Self => { // Validates ticket nagative base const hasAnyNegativeBase = await getNegativeBase(myOptions); if (hasAnyNegativeBase && isSpanishCompany) - return tx.rollback(); + throw new UserError('Negative basis'); query = `SELECT invoiceSerial(?, ?, ?) AS serial`; const [invoiceSerial] = await Self.rawSql(query, [ From 5a5e4c5afb1cad030614ca0a735f54a8fa583a4d Mon Sep 17 00:00:00 2001 From: vicent Date: Mon, 9 Jan 2023 14:47:52 +0100 Subject: [PATCH 09/48] feat: solo coge los tickets que no esten eliminados --- loopback/locale/es.json | 4 ++-- .../methods/invoiceOut/clientsToInvoice.js | 24 ++++++++++--------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 2c1a08f46..4b3bb95f8 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -253,5 +253,5 @@ "This receipt was not compensated": "Este recibo no ha sido compensado", "Client's email was not found": "No se encontró el email del cliente", "Aplicación bloqueada por el usuario 9": "Aplicación bloqueada por el usuario 9", - "Negative basis": "Negative basis" -} \ No newline at end of file + "Negative basis": "Base negativa" +} diff --git a/modules/invoiceOut/back/methods/invoiceOut/clientsToInvoice.js b/modules/invoiceOut/back/methods/invoiceOut/clientsToInvoice.js index d42184ae5..5b65a7565 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/clientsToInvoice.js +++ b/modules/invoiceOut/back/methods/invoiceOut/clientsToInvoice.js @@ -60,9 +60,9 @@ module.exports = Self => { try { query = ` SELECT MAX(issued) issued - FROM vn.invoiceOut io - JOIN vn.time t ON t.dated = io.issued - WHERE io.serial = 'A' + FROM vn.invoiceOut io + JOIN vn.time t ON t.dated = io.issued + WHERE io.serial = 'A' AND t.year = YEAR(?) AND io.companyFk = ?`; const [maxIssued] = await Self.rawSql(query, [ @@ -103,7 +103,6 @@ module.exports = Self => { return { clientId: invoiceableClient.id, addressId: invoiceableClient.addressFk - }; } ); @@ -131,11 +130,11 @@ module.exports = Self => { const models = Self.app.models; const args = ctx.args; const query = `SELECT DISTINCT clientFk AS id - FROM ticket t + FROM ticket t JOIN ticketPackaging tp ON t.id = tp.ticketFk JOIN client c ON c.id = t.clientFk WHERE t.shipped BETWEEN '2017-11-21' AND ? - AND t.clientFk >= ? + AND t.clientFk >= ? AND (t.clientFk <= ? OR ? IS NULL) AND c.isActive`; return models.InvoiceOut.rawSql(query, [ @@ -156,9 +155,9 @@ module.exports = Self => { c.id, SUM(IFNULL ( - s.quantity * + s.quantity * s.price * (100-s.discount)/100, - 0) + 0) + IFNULL(ts.quantity * ts.price,0) ) AS sumAmount, c.hasToInvoiceByAddress, @@ -170,11 +169,14 @@ module.exports = Self => { LEFT JOIN ticketService ts ON ts.ticketFk = t.id JOIN address a ON a.id = t.addressFk JOIN client c ON c.id = t.clientFk - WHERE ISNULL(t.refFk) AND c.id >= ? + WHERE ISNULL(t.refFk) AND c.id >= ? AND (t.clientFk <= ? OR ? IS NULL) AND t.shipped BETWEEN ? AND util.dayEnd(?) - AND t.companyFk = ? AND c.hasToInvoice - AND c.isTaxDataChecked AND c.isActive + AND t.companyFk = ? + AND c.hasToInvoice + AND c.isTaxDataChecked + AND c.isActive + AND NOT t.isDeleted GROUP BY c.id, IF(c.hasToInvoiceByAddress,a.id,TRUE) HAVING sumAmount > 0`; return models.InvoiceOut.rawSql(query, [ From 84788afc10a450332ae40072bf78db7c79b2f114 Mon Sep 17 00:00:00 2001 From: vicent Date: Mon, 9 Jan 2023 14:51:41 +0100 Subject: [PATCH 10/48] delete: old button --- modules/invoiceOut/front/index/index.html | 5 ----- 1 file changed, 5 deletions(-) diff --git a/modules/invoiceOut/front/index/index.html b/modules/invoiceOut/front/index/index.html index e2b0c221f..4c6451100 100644 --- a/modules/invoiceOut/front/index/index.html +++ b/modules/invoiceOut/front/index/index.html @@ -84,11 +84,6 @@ ng-click="manualInvoicing.show()"> Manual invoicing - - Global invoicing - From e659f0f020cf75c9acf6949b33e50e8d9002d6bd Mon Sep 17 00:00:00 2001 From: vicent Date: Mon, 9 Jan 2023 14:55:25 +0100 Subject: [PATCH 11/48] refacotor: delete duplicated variable --- .../invoiceOut/back/methods/invoiceOut/clientsToInvoice.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/modules/invoiceOut/back/methods/invoiceOut/clientsToInvoice.js b/modules/invoiceOut/back/methods/invoiceOut/clientsToInvoice.js index 5b65a7565..1f27f8806 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/clientsToInvoice.js +++ b/modules/invoiceOut/back/methods/invoiceOut/clientsToInvoice.js @@ -95,7 +95,7 @@ module.exports = Self => { ], myOptions); } - const invoiceableClients = await getInvoiceableClients(ctx, myOptions); + const invoiceableClients = await getInvoiceableClients(ctx, minShipped, myOptions); if (!invoiceableClients) return; @@ -145,11 +145,9 @@ module.exports = Self => { ], options); } - async function getInvoiceableClients(ctx, options) { + async function getInvoiceableClients(ctx, minShipped, options) { const models = Self.app.models; const args = ctx.args; - const minShipped = new Date(); - minShipped.setFullYear(minShipped.getFullYear() - 1); const query = `SELECT c.id, From 3e920e6a2f3e0a3543e62ae3186f5ddec6de9402 Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 10 Jan 2023 14:34:25 +0100 Subject: [PATCH 12/48] corregida traduccion --- modules/invoiceOut/front/global-invoicing/locale/es.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/invoiceOut/front/global-invoicing/locale/es.yml b/modules/invoiceOut/front/global-invoicing/locale/es.yml index 84cfe43ad..ac1092e9c 100644 --- a/modules/invoiceOut/front/global-invoicing/locale/es.yml +++ b/modules/invoiceOut/front/global-invoicing/locale/es.yml @@ -5,7 +5,7 @@ Invoice date and the max date should be filled: La fecha de factura y la fecha l Choose a valid clients range: Selecciona un rango válido de clientes Clients range: Rango de clientes All clients: Todos los clientes -Calculating packages to invoice...: Calculando paquetes a factura... +Calculating packages to invoice...: Calculando paquetes a facturar... Clean: Limpiar From client: Desde cliente To client: Hasta cliente From 020068006c2584b67e0dfce42fd374655c371821 Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 11 Jan 2023 11:57:52 +0100 Subject: [PATCH 13/48] fix: manejado error si no se selecciona una empresa --- modules/invoiceOut/front/global-invoicing/index.js | 4 ++++ modules/invoiceOut/front/global-invoicing/locale/es.yml | 1 + 2 files changed, 5 insertions(+) diff --git a/modules/invoiceOut/front/global-invoicing/index.js b/modules/invoiceOut/front/global-invoicing/index.js index 89487d440..4b79885db 100644 --- a/modules/invoiceOut/front/global-invoicing/index.js +++ b/modules/invoiceOut/front/global-invoicing/index.js @@ -41,6 +41,7 @@ class Controller extends Section { restartValues() { this.$.invoiceButton.disabled = false; + this.packageInvoicing = false; } cancelRequest() { @@ -96,6 +97,9 @@ class Controller extends Section { if (!this.invoice.fromClientId || !this.invoice.toClientId) throw new Error('Choose a valid clients range'); + if (!this.invoice.companyFk) + throw new Error('Choose a valid company'); + this.$.invoiceButton.disabled = true; this.$.data = []; this.packageInvoicing = true; diff --git a/modules/invoiceOut/front/global-invoicing/locale/es.yml b/modules/invoiceOut/front/global-invoicing/locale/es.yml index ac1092e9c..55215f370 100644 --- a/modules/invoiceOut/front/global-invoicing/locale/es.yml +++ b/modules/invoiceOut/front/global-invoicing/locale/es.yml @@ -3,6 +3,7 @@ Max date: Fecha límite Invoice date: Fecha de factura Invoice date and the max date should be filled: La fecha de factura y la fecha límite deben rellenarse Choose a valid clients range: Selecciona un rango válido de clientes +Choose a valid company: Selecciona un empresa válida Clients range: Rango de clientes All clients: Todos los clientes Calculating packages to invoice...: Calculando paquetes a facturar... From caff537f2e5e832f67bd2bc5739a430a662c18ef Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 11 Jan 2023 12:29:03 +0100 Subject: [PATCH 14/48] feat: imprime las facturas --- db/dump/fixtures.sql | 8 +-- .../back/methods/invoiceOut/invoiceClient.js | 12 +++++ .../back/methods/invoiceOut/invoicePdf.js | 50 +++++++++++++++++++ modules/invoiceOut/back/models/invoice-out.js | 1 + 4 files changed, 67 insertions(+), 4 deletions(-) create mode 100644 modules/invoiceOut/back/methods/invoiceOut/invoicePdf.js diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 1ea4fa114..3280f079f 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -2351,11 +2351,11 @@ INSERT INTO `vn`.`device` (`sn`, `model`, `userFk`) VALUES ('aaa', 'android', '9'); -INSERT INTO `vn`.`queuePriority`(`id`, `priority`) +INSERT INTO `vn`.`queuePriority`(`id`, `priority`, `code`) VALUES - (1, 'Alta'), - (2, 'Normal'), - (3, 'Baja'); + (1, 'Alta', 'high'), + (2, 'Normal', 'normal'), + (3, 'Baja', 'low'); INSERT INTO `vn`.`workerTimeControlParams` (`id`, `dayBreak`, `weekBreak`, `weekScope`, `dayWorkMax`, `dayStayMax`, `weekMaxBreak`, `weekMaxScope`, `askInOut`) VALUES diff --git a/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js b/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js index 017acf8b5..29ecd9dd9 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js +++ b/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js @@ -135,6 +135,18 @@ module.exports = Self => { }; await models.InvoiceOut.invoiceEmail(ctx, invoiceOut.ref); } + + if (invoiceId && !invoiceOut.client().isToBeMailed) { + const query = `CALL vn.report_print( + 'invoice', + ?, + account.myUser_getId(), + JSON_OBJECT('reference', ?), + 'normal' + );`; + await models.InvoiceOut.rawSql(query, [1 /* vPrinterFk */, invoiceOut.ref], myOptions); + } + return invoiceId; }; diff --git a/modules/invoiceOut/back/methods/invoiceOut/invoicePdf.js b/modules/invoiceOut/back/methods/invoiceOut/invoicePdf.js new file mode 100644 index 000000000..3194d2c79 --- /dev/null +++ b/modules/invoiceOut/back/methods/invoiceOut/invoicePdf.js @@ -0,0 +1,50 @@ +const {Report} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('invoicePdf', { + description: 'Returns the invoice pdf', + accessType: 'READ', + accepts: [ + { + arg: 'reference', + type: 'string', + required: true, + description: 'The invoice reference', + 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: '/:reference/invoice', + verb: 'GET' + } + }); + + Self.invoicePdf = async(ctx, reference) => { + const args = Object.assign({}, ctx.args); + const params = {lang: ctx.req.getLocale()}; + + delete args.ctx; + for (const param in args) + params[param] = args[param]; + + const report = new Report('invoice', params); + const stream = await report.toPdfStream(); + + return [stream, 'application/pdf', `filename="doc-${reference}.pdf"`]; + }; +}; diff --git a/modules/invoiceOut/back/models/invoice-out.js b/modules/invoiceOut/back/models/invoice-out.js index 88adae2ef..de647254f 100644 --- a/modules/invoiceOut/back/models/invoice-out.js +++ b/modules/invoiceOut/back/models/invoice-out.js @@ -15,4 +15,5 @@ module.exports = Self => { require('../methods/invoiceOut/exportationPdf')(Self); require('../methods/invoiceOut/invoiceCsv')(Self); require('../methods/invoiceOut/invoiceCsvEmail')(Self); + require('../methods/invoiceOut/invoicePdf')(Self); }; From 9042eaaf9ff10155870228dc4979c8d123322e26 Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 11 Jan 2023 12:38:37 +0100 Subject: [PATCH 15/48] add fixtures --- db/dump/fixtures.sql | 4 ++++ modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 3280f079f..cb3c2fec8 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -2760,6 +2760,10 @@ INSERT INTO `salix`.`url` (`appName`, `environment`, `url`) ('lilium', 'dev', 'http://localhost:8080/#/'), ('salix', 'dev', 'http://localhost:5000/#!/'); +INSERT INTO `vn`.`report` (`id`, `name`, `paperSizeFk`, `method`) + VALUES + (3, 'invoice', NULL, 'InvoiceOuts/{reference}/invoice'); + INSERT INTO `vn`.`payDemDetail` (`id`, `detail`) VALUES (1, 1); diff --git a/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js b/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js index 29ecd9dd9..bd86ac878 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js +++ b/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js @@ -141,7 +141,7 @@ module.exports = Self => { 'invoice', ?, account.myUser_getId(), - JSON_OBJECT('reference', ?), + JSON_OBJECT('refFk', ?), 'normal' );`; await models.InvoiceOut.rawSql(query, [1 /* vPrinterFk */, invoiceOut.ref], myOptions); From b801ac676c1271cd311c9266f714f8312cb10a5c Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 11 Jan 2023 12:41:02 +0100 Subject: [PATCH 16/48] feat: updated production db --- db/changes/230201/00-report.sql | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 db/changes/230201/00-report.sql diff --git a/db/changes/230201/00-report.sql b/db/changes/230201/00-report.sql new file mode 100644 index 000000000..3101d0870 --- /dev/null +++ b/db/changes/230201/00-report.sql @@ -0,0 +1,3 @@ +UPDATE `vn`.`report` + SET `method`='InvoiceOuts/{reference}/invoice' +WHERE name='invoice'; From f7ee6c18cac9daea11ec58944d7dc4c4faa6b09f Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 11 Jan 2023 13:04:56 +0100 Subject: [PATCH 17/48] refactor: movido codigo que imprime pdf dentro del try --- .../back/methods/invoiceOut/invoiceClient.js | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js b/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js index bd86ac878..8600d6325 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js +++ b/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js @@ -121,6 +121,17 @@ module.exports = Self => { invoiceId = newInvoice.id; } + if (invoiceId && !invoiceOut.client().isToBeMailed) { + const query = `CALL vn.report_print( + 'invoice', + ?, + account.myUser_getId(), + JSON_OBJECT('refFk', ?), + 'normal' + );`; + await models.InvoiceOut.rawSql(query, [1 /* vPrinterFk */, invoiceOut.ref], myOptions); + } + if (tx) await tx.commit(); } catch (e) { if (tx) await tx.rollback(); @@ -136,17 +147,6 @@ module.exports = Self => { await models.InvoiceOut.invoiceEmail(ctx, invoiceOut.ref); } - if (invoiceId && !invoiceOut.client().isToBeMailed) { - const query = `CALL vn.report_print( - 'invoice', - ?, - account.myUser_getId(), - JSON_OBJECT('refFk', ?), - 'normal' - );`; - await models.InvoiceOut.rawSql(query, [1 /* vPrinterFk */, invoiceOut.ref], myOptions); - } - return invoiceId; }; From 76fe32924c8e8ac530ed8ecb3326ce1f82135dc6 Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 17 Jan 2023 09:25:20 +0100 Subject: [PATCH 18/48] fix: update url --- db/changes/230201/00-report.sql | 2 +- db/dump/fixtures.sql | 9 +++++---- db/dump/structure.sql | 3 ++- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/db/changes/230201/00-report.sql b/db/changes/230201/00-report.sql index 3101d0870..5d3c9db45 100644 --- a/db/changes/230201/00-report.sql +++ b/db/changes/230201/00-report.sql @@ -1,3 +1,3 @@ UPDATE `vn`.`report` - SET `method`='InvoiceOuts/{reference}/invoice' + SET `method`='InvoiceOuts/{refFk}/invoice' WHERE name='invoice'; diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 559338f53..5bef8f72e 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -147,10 +147,11 @@ INSERT INTO `vn`.`sector`(`id`, `description`, `warehouseFk`, `isPreviousPrepare (1, 'First sector', 1, 1, 'FIRST'), (2, 'Second sector', 2, 0, 'SECOND'); -INSERT INTO `vn`.`printer` (`id`, `name`, `path`, `isLabeler`, `sectorFk`) +INSERT INTO `vn`.`printer` (`id`, `name`, `path`, `isLabeler`, `sectorFk`, `ipAddress`) VALUES - (1, 'printer1', 'path1', 0, 1), - (2, 'printer2', 'path2', 1, 1); + (1, 'printer1', 'path1', 0, 1 , NULL), + (2, 'printer2', 'path2', 1, 1 , NULL), + (4, 'printer4', 'path4', 0, NULL, 10.1.10.4); INSERT INTO `vn`.`worker`(`id`, `code`, `firstName`, `lastName`, `userFk`,`bossFk`, `phone`, `sectorFk`, `labelerFk`) VALUES @@ -2762,7 +2763,7 @@ INSERT INTO `salix`.`url` (`appName`, `environment`, `url`) INSERT INTO `vn`.`report` (`id`, `name`, `paperSizeFk`, `method`) VALUES - (3, 'invoice', NULL, 'InvoiceOuts/{reference}/invoice'); + (3, 'invoice', NULL, 'InvoiceOuts/{refFk}/invoice'); INSERT INTO `vn`.`payDemDetail` (`id`, `detail`) VALUES diff --git a/db/dump/structure.sql b/db/dump/structure.sql index 47fdd6d74..ab8b8969c 100644 --- a/db/dump/structure.sql +++ b/db/dump/structure.sql @@ -32370,6 +32370,7 @@ CREATE TABLE `printQueue` ( `error` text COLLATE utf8mb3_unicode_ci DEFAULT NULL, `errorNumber` int(11) DEFAULT NULL, `created` timestamp NOT NULL DEFAULT current_timestamp(), + `serverId` int(10) DEFAULT NULL, PRIMARY KEY (`id`), KEY `statusCode` (`statusCode`), KEY `printerFk` (`printerFk`), @@ -32379,7 +32380,7 @@ CREATE TABLE `printQueue` ( CONSTRAINT `printQueue_printerFk` FOREIGN KEY (`printerFk`) REFERENCES `printer` (`id`) ON UPDATE CASCADE, CONSTRAINT `printQueue_priorityFk` FOREIGN KEY (`priorityFk`) REFERENCES `queuePriority` (`id`) ON UPDATE CASCADE, CONSTRAINT `printQueue_report` FOREIGN KEY (`reportFk`) REFERENCES `report` (`id`) ON DELETE CASCADE ON UPDATE CASCADE -) ENGINE=InnoDBDEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; /*!40101 SET character_set_client = @saved_cs_client */; -- From eef926d09dfdf3a1ae035d1d817038af8798edfc Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 17 Jan 2023 09:34:51 +0100 Subject: [PATCH 19/48] fix: fixtures --- db/dump/fixtures.sql | 2 +- modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 5bef8f72e..9c8163414 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -151,7 +151,7 @@ INSERT INTO `vn`.`printer` (`id`, `name`, `path`, `isLabeler`, `sectorFk`, `ipAd VALUES (1, 'printer1', 'path1', 0, 1 , NULL), (2, 'printer2', 'path2', 1, 1 , NULL), - (4, 'printer4', 'path4', 0, NULL, 10.1.10.4); + (4, 'printer4', 'path4', 0, NULL, '10.1.10.4'); INSERT INTO `vn`.`worker`(`id`, `code`, `firstName`, `lastName`, `userFk`,`bossFk`, `phone`, `sectorFk`, `labelerFk`) VALUES diff --git a/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js b/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js index 8600d6325..525cad8ac 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js +++ b/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js @@ -129,7 +129,7 @@ module.exports = Self => { JSON_OBJECT('refFk', ?), 'normal' );`; - await models.InvoiceOut.rawSql(query, [1 /* vPrinterFk */, invoiceOut.ref], myOptions); + await models.InvoiceOut.rawSql(query, [4 /* vPrinterFk */, invoiceOut.ref], myOptions); } if (tx) await tx.commit(); From 41914f9e4f0d2284eb18f121b38f6e2f38aac2fc Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 17 Jan 2023 10:46:16 +0100 Subject: [PATCH 20/48] =?UTF-8?q?feat:=20a=C3=B1adido=20desplegable=20impr?= =?UTF-8?q?esora?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../back/methods/invoiceOut/invoiceClient.js | 10 +++++-- modules/invoiceOut/back/model-config.json | 3 ++ modules/invoiceOut/back/models/printer.json | 28 +++++++++++++++++++ .../front/global-invoicing/index.html | 12 ++++++-- .../front/global-invoicing/index.js | 1 + .../front/global-invoicing/locale/es.yml | 1 + 6 files changed, 51 insertions(+), 4 deletions(-) create mode 100644 modules/invoiceOut/back/models/printer.json diff --git a/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js b/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js index 525cad8ac..b401d08b7 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js +++ b/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js @@ -39,6 +39,12 @@ module.exports = Self => { type: 'date', description: 'The minium shupped date', required: true + }, + { + arg: 'printerFk', + type: 'number', + description: 'The printer to print', + required: true }], returns: { type: 'object', @@ -129,7 +135,7 @@ module.exports = Self => { JSON_OBJECT('refFk', ?), 'normal' );`; - await models.InvoiceOut.rawSql(query, [4 /* vPrinterFk */, invoiceOut.ref], myOptions); + await models.InvoiceOut.rawSql(query, [args.printerFk, invoiceOut.ref], myOptions); } if (tx) await tx.commit(); @@ -138,7 +144,7 @@ module.exports = Self => { throw e; } - if (invoiceId) { + if (invoiceId && invoiceOut.client().isToBeMailed) { ctx.args = { reference: invoiceOut.ref, recipientId: invoiceOut.clientFk, diff --git a/modules/invoiceOut/back/model-config.json b/modules/invoiceOut/back/model-config.json index 04933c4f0..b190126ea 100644 --- a/modules/invoiceOut/back/model-config.json +++ b/modules/invoiceOut/back/model-config.json @@ -8,6 +8,9 @@ "InvoiceContainer": { "dataSource": "invoiceStorage" }, + "Printer": { + "dataSource": "vn" + }, "TaxArea": { "dataSource": "vn" }, diff --git a/modules/invoiceOut/back/models/printer.json b/modules/invoiceOut/back/models/printer.json new file mode 100644 index 000000000..99003560d --- /dev/null +++ b/modules/invoiceOut/back/models/printer.json @@ -0,0 +1,28 @@ +{ + "name": "Printer", + "base": "VnModel", + "options": { + "mysql": { + "table": "printer" + } + }, + "properties": { + "id": { + "type": "number", + "id": true, + "description": "Identifier" + }, + "name": { + "type": "string" + }, + "isLabeler": { + "type": "boolean" + } + }, + "acls": [{ + "accessType": "READ", + "principalType": "ROLE", + "principalId": "$everyone", + "permission": "ALLOW" + }] +} diff --git a/modules/invoiceOut/front/global-invoicing/index.html b/modules/invoiceOut/front/global-invoicing/index.html index a59475297..0c447c7b8 100644 --- a/modules/invoiceOut/front/global-invoicing/index.html +++ b/modules/invoiceOut/front/global-invoicing/index.html @@ -109,7 +109,7 @@ {{::id}} - {{::name}} - + - + + + diff --git a/modules/invoiceOut/front/global-invoicing/index.js b/modules/invoiceOut/front/global-invoicing/index.js index 4b79885db..2b32858e0 100644 --- a/modules/invoiceOut/front/global-invoicing/index.js +++ b/modules/invoiceOut/front/global-invoicing/index.js @@ -59,6 +59,7 @@ class Controller extends Section { maxShipped: invoice.maxShipped, companyFk: invoice.companyFk, minShipped: invoice.minShipped, + printerFk: this.invoice.printerFk, }; diff --git a/modules/invoiceOut/front/global-invoicing/locale/es.yml b/modules/invoiceOut/front/global-invoicing/locale/es.yml index 55215f370..56c74dcd5 100644 --- a/modules/invoiceOut/front/global-invoicing/locale/es.yml +++ b/modules/invoiceOut/front/global-invoicing/locale/es.yml @@ -11,3 +11,4 @@ Clean: Limpiar From client: Desde cliente To client: Hasta cliente Address id: Id dirección +Printer: Impresora From adc2c32ac45ff8c283ba71751538d16d51f65d49 Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 17 Jan 2023 12:51:04 +0100 Subject: [PATCH 21/48] feat: add changes sql --- db/changes/230201/00-report.sql | 3 +++ 1 file changed, 3 insertions(+) diff --git a/db/changes/230201/00-report.sql b/db/changes/230201/00-report.sql index 5d3c9db45..d277933bd 100644 --- a/db/changes/230201/00-report.sql +++ b/db/changes/230201/00-report.sql @@ -1,3 +1,6 @@ UPDATE `vn`.`report` SET `method`='InvoiceOuts/{refFk}/invoice' WHERE name='invoice'; + +ALTER TABLE `vn`.`printQueue` MODIFY COLUMN printerFk tinyint(3) unsigned DEFAULT 82 NOT NULL; + From ae051c73f24360f5744d9ea11df7af586028463c Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 18 Jan 2023 07:26:57 +0100 Subject: [PATCH 22/48] =?UTF-8?q?feat:=20a=C3=B1adir=20clientes=20al=20pri?= =?UTF-8?q?ncipio=20del=20array=20y=20borrarlos=20si=20han=20sido=20OK?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/invoiceOut/front/global-invoicing/index.js | 6 +++++- modules/invoiceOut/front/global-invoicing/locale/es.yml | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/modules/invoiceOut/front/global-invoicing/index.js b/modules/invoiceOut/front/global-invoicing/index.js index 2b32858e0..e8f0ae4b6 100644 --- a/modules/invoiceOut/front/global-invoicing/index.js +++ b/modules/invoiceOut/front/global-invoicing/index.js @@ -67,7 +67,7 @@ class Controller extends Section { .then(res => { this.address = res.data; - this.$.data.push({ + this.$.data.unshift({ id: clientAndAddress.clientId, address: this.address, status: 'waiting' @@ -80,6 +80,7 @@ class Controller extends Section { return this.$http.post(`InvoiceOuts/invoiceClient`, params) .then(() => { this.$.data[index].status = 'ok'; + this.$.data.shift(); }).catch(res => { this.$.data[index].status = 'error'; this.$.data[index].error = res.data.error.message; @@ -101,6 +102,9 @@ class Controller extends Section { if (!this.invoice.companyFk) throw new Error('Choose a valid company'); + if (!this.invoice.printerFk) + throw new Error('Choose a valid printer'); + this.$.invoiceButton.disabled = true; this.$.data = []; this.packageInvoicing = true; diff --git a/modules/invoiceOut/front/global-invoicing/locale/es.yml b/modules/invoiceOut/front/global-invoicing/locale/es.yml index 56c74dcd5..d87aa481d 100644 --- a/modules/invoiceOut/front/global-invoicing/locale/es.yml +++ b/modules/invoiceOut/front/global-invoicing/locale/es.yml @@ -4,6 +4,7 @@ Invoice date: Fecha de factura Invoice date and the max date should be filled: La fecha de factura y la fecha límite deben rellenarse Choose a valid clients range: Selecciona un rango válido de clientes Choose a valid company: Selecciona un empresa válida +Choose a valid printer: Selecciona una impresora válida Clients range: Rango de clientes All clients: Todos los clientes Calculating packages to invoice...: Calculando paquetes a facturar... From facaee6f955cf615ee99749fc3d865a6dceb1141 Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 24 Jan 2023 09:45:52 +0100 Subject: [PATCH 23/48] =?UTF-8?q?feat:=20a=C3=B1adido=20contador=20y=20por?= =?UTF-8?q?cetaje?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../front/global-invoicing/index.html | 12 ++++++++++ .../front/global-invoicing/index.js | 22 ++++++++++++++----- .../front/global-invoicing/locale/es.yml | 3 +++ .../front/global-invoicing/style.scss | 4 ++++ 4 files changed, 35 insertions(+), 6 deletions(-) diff --git a/modules/invoiceOut/front/global-invoicing/index.html b/modules/invoiceOut/front/global-invoicing/index.html index 0c447c7b8..d21416014 100644 --- a/modules/invoiceOut/front/global-invoicing/index.html +++ b/modules/invoiceOut/front/global-invoicing/index.html @@ -64,6 +64,18 @@ order="code">
+ +
Invoicing
+
+ {{'Id Client' | translate}}: {{$ctrl.currentClientId}} + {{'of' | translate}} {{::$ctrl.lastClientId}} +
+
+ {{($ctrl.percentage / 100) | percentage: 0}} +
+
this.vnApp.showSuccess(this.$t('Data saved!'))) diff --git a/modules/invoiceOut/front/global-invoicing/locale/es.yml b/modules/invoiceOut/front/global-invoicing/locale/es.yml index d87aa481d..d5e501eb6 100644 --- a/modules/invoiceOut/front/global-invoicing/locale/es.yml +++ b/modules/invoiceOut/front/global-invoicing/locale/es.yml @@ -13,3 +13,6 @@ From client: Desde cliente To client: Hasta cliente Address id: Id dirección Printer: Impresora +of: de +Id Client: Id Cliente +Invoicing: Facturando diff --git a/modules/invoiceOut/front/global-invoicing/style.scss b/modules/invoiceOut/front/global-invoicing/style.scss index d67df4479..eb6727428 100644 --- a/modules/invoiceOut/front/global-invoicing/style.scss +++ b/modules/invoiceOut/front/global-invoicing/style.scss @@ -8,3 +8,7 @@ vn-td { color: $color-success; } } + +h5{ + color: $color-primary; +} From 61b0aa079a22d974c4fe4652513ba8b2472a9351 Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 24 Jan 2023 12:40:43 +0100 Subject: [PATCH 24/48] refactor --- .../front/global-invoicing/index.html | 60 ++++--------------- .../front/global-invoicing/index.js | 11 +--- .../front/global-invoicing/style.scss | 4 -- modules/invoiceOut/front/index/index.html | 25 +++----- .../invoiceOut/front/index/manual/index.html | 8 +-- .../invoiceOut/front/index/manual/style.scss | 2 +- 6 files changed, 26 insertions(+), 84 deletions(-) diff --git a/modules/invoiceOut/front/global-invoicing/index.html b/modules/invoiceOut/front/global-invoicing/index.html index d21416014..8efd80602 100644 --- a/modules/invoiceOut/front/global-invoicing/index.html +++ b/modules/invoiceOut/front/global-invoicing/index.html @@ -1,4 +1,16 @@ -

{{'Calculating packages to invoice...'}}

+ +
{{'Calculating packages to invoice...'}}
+ +
Invoicing
+
+ {{'Id Client' | translate}}: {{$ctrl.currentClientId}} + {{'of' | translate}} {{::$ctrl.lastClientId}} +
+
+ {{($ctrl.percentage / 100) | percentage: 0}} +
+
+
@@ -64,18 +76,6 @@ order="code"> - -
Invoicing
-
- {{'Id Client' | translate}}: {{$ctrl.currentClientId}} - {{'of' | translate}} {{::$ctrl.lastClientId}} -
-
- {{($ctrl.percentage / 100) | percentage: 0}} -
-
- - - - - - - - {{::id}} - {{::name}} - - - {{::id}} - {{::name}} - - diff --git a/modules/invoiceOut/front/global-invoicing/index.js b/modules/invoiceOut/front/global-invoicing/index.js index 30359776c..fc2a5d0d1 100644 --- a/modules/invoiceOut/front/global-invoicing/index.js +++ b/modules/invoiceOut/front/global-invoicing/index.js @@ -10,8 +10,6 @@ class Controller extends Section { maxShipped: new Date(), companyFk: this.vnConfig.companyFk }; - this.clientsNumber = 'allClients'; - this.currentClient = 0; } $onInit() { @@ -45,7 +43,6 @@ class Controller extends Section { } restartValues() { - this.lastClientId = null; this.$.invoiceButton.disabled = false; this.packageInvoicing = false; } @@ -100,9 +97,6 @@ class Controller extends Section { if (!this.invoice.invoiceDate || !this.invoice.maxShipped) throw new Error('Invoice date and the max date should be filled'); - if (!this.invoice.fromClientId || !this.invoice.toClientId) - throw new Error('Choose a valid clients range'); - if (!this.invoice.companyFk) throw new Error('Choose a valid company'); @@ -123,6 +117,7 @@ class Controller extends Section { this.clients = []; for (const clientAndAddress of clientsAndAddresses) this.clients.push(clientAndAddress.clientId); + this.currentClient = 0; this.lastClientId = clientsAndAddresses[clientsAndAddresses.length - 1].clientId; return this.invoiceOut(invoice, clientsAndAddresses); @@ -135,10 +130,6 @@ class Controller extends Section { return false; } } - - clean() { - this.$.data = this.$.data.filter(client => client.status == 'error'); - } } Controller.$inject = ['$element', '$scope', '$transclude']; diff --git a/modules/invoiceOut/front/global-invoicing/style.scss b/modules/invoiceOut/front/global-invoicing/style.scss index eb6727428..d67df4479 100644 --- a/modules/invoiceOut/front/global-invoicing/style.scss +++ b/modules/invoiceOut/front/global-invoicing/style.scss @@ -8,7 +8,3 @@ vn-td { color: $color-success; } } - -h5{ - color: $color-primary; -} diff --git a/modules/invoiceOut/front/index/index.html b/modules/invoiceOut/front/index/index.html index 4c6451100..dc4d5d8a9 100644 --- a/modules/invoiceOut/front/index/index.html +++ b/modules/invoiceOut/front/index/index.html @@ -68,24 +68,13 @@
- - - - - - - Manual invoicing - - - + +
-
- + Invoicing in progress...
@@ -80,4 +80,4 @@ - \ No newline at end of file + diff --git a/modules/invoiceOut/front/index/manual/style.scss b/modules/invoiceOut/front/index/manual/style.scss index 18e6f3513..820c07756 100644 --- a/modules/invoiceOut/front/index/manual/style.scss +++ b/modules/invoiceOut/front/index/manual/style.scss @@ -14,4 +14,4 @@ } } } -} \ No newline at end of file +} From 06b4e033207dd6737f41845b72d1838ba5fc5b75 Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 25 Jan 2023 08:15:50 +0100 Subject: [PATCH 25/48] =?UTF-8?q?feat:=20muestra=20en=20n=C3=BAmero=20de?= =?UTF-8?q?=20clientes=20en=20vez=20de=20su=20id?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/invoiceOut/front/global-invoicing/index.html | 6 +++--- modules/invoiceOut/front/global-invoicing/index.js | 9 ++++++--- modules/invoiceOut/front/global-invoicing/locale/es.yml | 2 +- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/modules/invoiceOut/front/global-invoicing/index.html b/modules/invoiceOut/front/global-invoicing/index.html index 8efd80602..b9f6515c8 100644 --- a/modules/invoiceOut/front/global-invoicing/index.html +++ b/modules/invoiceOut/front/global-invoicing/index.html @@ -1,10 +1,10 @@
{{'Calculating packages to invoice...'}}
- +
Invoicing
- {{'Id Client' | translate}}: {{$ctrl.currentClientId}} - {{'of' | translate}} {{::$ctrl.lastClientId}} + {{'Client' | translate}}: {{$ctrl.currentClient}} + {{'of' | translate}} {{::$ctrl.clients.length}}
{{($ctrl.percentage / 100) | percentage: 0}} diff --git a/modules/invoiceOut/front/global-invoicing/index.js b/modules/invoiceOut/front/global-invoicing/index.js index fc2a5d0d1..dd992a39c 100644 --- a/modules/invoiceOut/front/global-invoicing/index.js +++ b/modules/invoiceOut/front/global-invoicing/index.js @@ -10,6 +10,10 @@ class Controller extends Section { maxShipped: new Date(), companyFk: this.vnConfig.companyFk }; + + this.invoice.invoiceDate = new Date(); + this.invoice.companyFk = 442; + this.invoice.printerFk = 1; } $onInit() { @@ -50,9 +54,10 @@ class Controller extends Section { invoiceOut(invoice, clientsAndAddresses) { const [clientAndAddress] = clientsAndAddresses; if (!clientAndAddress) return; - this.currentClientId = clientAndAddress.clientId; + this.currentClient = ++this.currentClient; this.getPercentage(); + const params = { clientId: clientAndAddress.clientId, addressId: clientAndAddress.addressId, @@ -63,7 +68,6 @@ class Controller extends Section { printerFk: this.invoice.printerFk, }; - this.$http.get(`Addresses/${clientAndAddress.addressId}`) .then(res => { this.address = res.data; @@ -118,7 +122,6 @@ class Controller extends Section { for (const clientAndAddress of clientsAndAddresses) this.clients.push(clientAndAddress.clientId); this.currentClient = 0; - this.lastClientId = clientsAndAddresses[clientsAndAddresses.length - 1].clientId; return this.invoiceOut(invoice, clientsAndAddresses); }) diff --git a/modules/invoiceOut/front/global-invoicing/locale/es.yml b/modules/invoiceOut/front/global-invoicing/locale/es.yml index d5e501eb6..1d76550af 100644 --- a/modules/invoiceOut/front/global-invoicing/locale/es.yml +++ b/modules/invoiceOut/front/global-invoicing/locale/es.yml @@ -14,5 +14,5 @@ To client: Hasta cliente Address id: Id dirección Printer: Impresora of: de -Id Client: Id Cliente +Client: Cliente Invoicing: Facturando From f22f045444b2244608366f7f321ffcb6bc5e0a9e Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 25 Jan 2023 08:27:39 +0100 Subject: [PATCH 26/48] refactor: add css --- .../front/global-invoicing/index.html | 4 ++-- .../front/global-invoicing/style.scss | 18 +++++++++++++----- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/modules/invoiceOut/front/global-invoicing/index.html b/modules/invoiceOut/front/global-invoicing/index.html index b9f6515c8..b1a9e4b84 100644 --- a/modules/invoiceOut/front/global-invoicing/index.html +++ b/modules/invoiceOut/front/global-invoicing/index.html @@ -6,9 +6,9 @@ {{'Client' | translate}}: {{$ctrl.currentClient}} {{'of' | translate}} {{::$ctrl.clients.length}}
-
+
{{($ctrl.percentage / 100) | percentage: 0}} -
+
diff --git a/modules/invoiceOut/front/global-invoicing/style.scss b/modules/invoiceOut/front/global-invoicing/style.scss index d67df4479..980c7bc5f 100644 --- a/modules/invoiceOut/front/global-invoicing/style.scss +++ b/modules/invoiceOut/front/global-invoicing/style.scss @@ -1,10 +1,18 @@ @import "variables"; -vn-td { - vn-icon[icon=clear] { - color: $color-alert; +vn-invoice-out-global-invoicing{ + + vn-td { + vn-icon[icon=clear] { + color: $color-alert; + } + vn-icon[icon=check] { + color: $color-success; + } } - vn-icon[icon=check] { - color: $color-success; + + h5{ + color: $color-primary; } + } From 6ea14158951605bd91b47a67928de856a887068d Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 25 Jan 2023 09:46:08 +0100 Subject: [PATCH 27/48] refactor: traducciones --- modules/invoiceOut/front/global-invoicing/index.html | 2 +- modules/invoiceOut/front/global-invoicing/locale/es.yml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/invoiceOut/front/global-invoicing/index.html b/modules/invoiceOut/front/global-invoicing/index.html index b1a9e4b84..065dcc4e3 100644 --- a/modules/invoiceOut/front/global-invoicing/index.html +++ b/modules/invoiceOut/front/global-invoicing/index.html @@ -105,7 +105,7 @@ ng-model="$ctrl.invoice.printerFk">
- + diff --git a/modules/invoiceOut/front/global-invoicing/locale/es.yml b/modules/invoiceOut/front/global-invoicing/locale/es.yml index 1d76550af..3c6e1d154 100644 --- a/modules/invoiceOut/front/global-invoicing/locale/es.yml +++ b/modules/invoiceOut/front/global-invoicing/locale/es.yml @@ -16,3 +16,4 @@ Printer: Impresora of: de Client: Cliente Invoicing: Facturando +Invoice out: Facturar From 77340c8459a6978d27be1262b0a024b94d0dad3b Mon Sep 17 00:00:00 2001 From: vicent Date: Wed, 25 Jan 2023 10:14:37 +0100 Subject: [PATCH 28/48] refactor: html --- modules/invoiceOut/front/global-invoicing/index.html | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/modules/invoiceOut/front/global-invoicing/index.html b/modules/invoiceOut/front/global-invoicing/index.html index 065dcc4e3..abfffe1ae 100644 --- a/modules/invoiceOut/front/global-invoicing/index.html +++ b/modules/invoiceOut/front/global-invoicing/index.html @@ -87,8 +87,6 @@ label="Max date" ng-model="$ctrl.invoice.maxShipped"> - - + - From 0ba95bd16355a9500fecfb9c3726fc2aa169699b Mon Sep 17 00:00:00 2001 From: vicent Date: Thu, 26 Jan 2023 09:25:52 +0100 Subject: [PATCH 29/48] feat: mostrar error --- .../invoiceOut/front/global-invoicing/index.html | 16 ++++------------ .../invoiceOut/front/global-invoicing/index.js | 5 ----- .../invoiceOut/front/global-invoicing/style.scss | 15 ++++++--------- 3 files changed, 10 insertions(+), 26 deletions(-) diff --git a/modules/invoiceOut/front/global-invoicing/index.html b/modules/invoiceOut/front/global-invoicing/index.html index abfffe1ae..cf307959a 100644 --- a/modules/invoiceOut/front/global-invoicing/index.html +++ b/modules/invoiceOut/front/global-invoicing/index.html @@ -1,4 +1,4 @@ - +
{{'Calculating packages to invoice...'}}
Invoicing
@@ -19,7 +19,7 @@ Nickname Address id Street - + Error
@@ -41,20 +41,12 @@ {{::client.address.street}} - + - - - - + {{::client.error}} diff --git a/modules/invoiceOut/front/global-invoicing/index.js b/modules/invoiceOut/front/global-invoicing/index.js index dd992a39c..9ae3b498c 100644 --- a/modules/invoiceOut/front/global-invoicing/index.js +++ b/modules/invoiceOut/front/global-invoicing/index.js @@ -10,10 +10,6 @@ class Controller extends Section { maxShipped: new Date(), companyFk: this.vnConfig.companyFk }; - - this.invoice.invoiceDate = new Date(); - this.invoice.companyFk = 442; - this.invoice.printerFk = 1; } $onInit() { @@ -84,7 +80,6 @@ class Controller extends Section { return this.$http.post(`InvoiceOuts/invoiceClient`, params) .then(() => { - this.$.data[index].status = 'ok'; this.$.data.shift(); }).catch(res => { this.$.data[index].status = 'error'; diff --git a/modules/invoiceOut/front/global-invoicing/style.scss b/modules/invoiceOut/front/global-invoicing/style.scss index 980c7bc5f..ae50adf6e 100644 --- a/modules/invoiceOut/front/global-invoicing/style.scss +++ b/modules/invoiceOut/front/global-invoicing/style.scss @@ -2,17 +2,14 @@ vn-invoice-out-global-invoicing{ - vn-td { - vn-icon[icon=clear] { - color: $color-alert; - } - vn-icon[icon=check] { - color: $color-success; - } - } - h5{ color: $color-primary; } + .vn-table vn-tbody > * > vn-td { + overflow: visible; + } + } + + From 67127554f9eac14714589c841f8ce7cb94774d6d Mon Sep 17 00:00:00 2001 From: vicent Date: Thu, 26 Jan 2023 13:12:53 +0100 Subject: [PATCH 30/48] feat: solo muestra los clientes con error y muestra los datos de manera distinta --- .../front/global-invoicing/index.html | 5 ++-- .../front/global-invoicing/index.js | 27 +++++++------------ .../front/global-invoicing/locale/es.yml | 1 + 3 files changed, 13 insertions(+), 20 deletions(-) diff --git a/modules/invoiceOut/front/global-invoicing/index.html b/modules/invoiceOut/front/global-invoicing/index.html index cf307959a..8f1e909e1 100644 --- a/modules/invoiceOut/front/global-invoicing/index.html +++ b/modules/invoiceOut/front/global-invoicing/index.html @@ -3,11 +3,10 @@
Invoicing
- {{'Client' | translate}}: {{$ctrl.currentClient}} - {{'of' | translate}} {{::$ctrl.clients.length}} + {{'Current client id' | translate}}: {{$ctrl.currentClientId}}
- {{($ctrl.percentage / 100) | percentage: 0}} + {{($ctrl.percentage / 100) | percentage: 0}} ({{$ctrl.currentClient}} {{'of' | translate}} {{$ctrl.clients.length}})
diff --git a/modules/invoiceOut/front/global-invoicing/index.js b/modules/invoiceOut/front/global-invoicing/index.js index 9ae3b498c..4e46d7a81 100644 --- a/modules/invoiceOut/front/global-invoicing/index.js +++ b/modules/invoiceOut/front/global-invoicing/index.js @@ -51,6 +51,7 @@ class Controller extends Section { const [clientAndAddress] = clientsAndAddresses; if (!clientAndAddress) return; + this.currentClientId = clientAndAddress.clientId; this.currentClient = ++this.currentClient; this.getPercentage(); @@ -67,23 +68,14 @@ class Controller extends Section { this.$http.get(`Addresses/${clientAndAddress.addressId}`) .then(res => { this.address = res.data; - - this.$.data.unshift({ - id: clientAndAddress.clientId, - address: this.address, - status: 'waiting' - }); - - const index = this.$.data.findIndex( - client => client.id == clientAndAddress.clientId && client.address.id == clientAndAddress.addressId - ); - return this.$http.post(`InvoiceOuts/invoiceClient`, params) - .then(() => { - this.$.data.shift(); - }).catch(res => { - this.$.data[index].status = 'error'; - this.$.data[index].error = res.data.error.message; + .catch(res => { + this.$.data.unshift({ + id: clientAndAddress.clientId, + address: this.address, + status: 'error', + error: res.data.error.message + }); }).finally(() => { clientsAndAddresses.shift(); return this.invoiceOut(invoice, clientsAndAddresses); @@ -110,13 +102,14 @@ class Controller extends Section { .then(res => { this.packageInvoicing = false; const invoice = res.data.invoice; + this.currentClient = 0; + const clientsAndAddresses = res.data.clientsAndAddresses; if (!clientsAndAddresses.length) throw new UserError(`There aren't clients to invoice`); this.clients = []; for (const clientAndAddress of clientsAndAddresses) this.clients.push(clientAndAddress.clientId); - this.currentClient = 0; return this.invoiceOut(invoice, clientsAndAddresses); }) diff --git a/modules/invoiceOut/front/global-invoicing/locale/es.yml b/modules/invoiceOut/front/global-invoicing/locale/es.yml index 3c6e1d154..5a453e5b9 100644 --- a/modules/invoiceOut/front/global-invoicing/locale/es.yml +++ b/modules/invoiceOut/front/global-invoicing/locale/es.yml @@ -15,5 +15,6 @@ Address id: Id dirección Printer: Impresora of: de Client: Cliente +Current client id: Id cliente actual Invoicing: Facturando Invoice out: Facturar From f7fa082294a06f7f10645384470ac6dfaad2ee42 Mon Sep 17 00:00:00 2001 From: vicent Date: Thu, 26 Jan 2023 13:49:09 +0100 Subject: [PATCH 31/48] refator: name endpoint --- db/changes/{230201 => 230401}/00-report.sql | 2 +- db/dump/fixtures.sql | 2 +- .../methods/invoiceOut/{invoicePdf.js => invoiceOutPdf.js} | 6 +++--- modules/invoiceOut/back/models/invoice-out.js | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) rename db/changes/{230201 => 230401}/00-report.sql (71%) rename modules/invoiceOut/back/methods/invoiceOut/{invoicePdf.js => invoiceOutPdf.js} (89%) diff --git a/db/changes/230201/00-report.sql b/db/changes/230401/00-report.sql similarity index 71% rename from db/changes/230201/00-report.sql rename to db/changes/230401/00-report.sql index d277933bd..0bc7c8da4 100644 --- a/db/changes/230201/00-report.sql +++ b/db/changes/230401/00-report.sql @@ -1,5 +1,5 @@ UPDATE `vn`.`report` - SET `method`='InvoiceOuts/{refFk}/invoice' + SET `method`='InvoiceOuts/{refFk}/invoice-out-pdf' WHERE name='invoice'; ALTER TABLE `vn`.`printQueue` MODIFY COLUMN printerFk tinyint(3) unsigned DEFAULT 82 NOT NULL; diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 18c9ef1dd..273b1b93d 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -2768,7 +2768,7 @@ INSERT INTO `salix`.`url` (`appName`, `environment`, `url`) INSERT INTO `vn`.`report` (`id`, `name`, `paperSizeFk`, `method`) VALUES - (3, 'invoice', NULL, 'InvoiceOuts/{refFk}/invoice'); + (3, 'invoice', NULL, 'InvoiceOuts/{refFk}/invoice-out-pdf'); INSERT INTO `vn`.`payDemDetail` (`id`, `detail`) VALUES diff --git a/modules/invoiceOut/back/methods/invoiceOut/invoicePdf.js b/modules/invoiceOut/back/methods/invoiceOut/invoiceOutPdf.js similarity index 89% rename from modules/invoiceOut/back/methods/invoiceOut/invoicePdf.js rename to modules/invoiceOut/back/methods/invoiceOut/invoiceOutPdf.js index 3194d2c79..941d31596 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/invoicePdf.js +++ b/modules/invoiceOut/back/methods/invoiceOut/invoiceOutPdf.js @@ -1,7 +1,7 @@ const {Report} = require('vn-print'); module.exports = Self => { - Self.remoteMethodCtx('invoicePdf', { + Self.remoteMethodCtx('invoiceOutPdf', { description: 'Returns the invoice pdf', accessType: 'READ', accepts: [ @@ -29,12 +29,12 @@ module.exports = Self => { } ], http: { - path: '/:reference/invoice', + path: '/:reference/invoice-out-pdf', verb: 'GET' } }); - Self.invoicePdf = async(ctx, reference) => { + Self.invoiceOutPdf = async(ctx, reference) => { const args = Object.assign({}, ctx.args); const params = {lang: ctx.req.getLocale()}; diff --git a/modules/invoiceOut/back/models/invoice-out.js b/modules/invoiceOut/back/models/invoice-out.js index de647254f..eb8df246c 100644 --- a/modules/invoiceOut/back/models/invoice-out.js +++ b/modules/invoiceOut/back/models/invoice-out.js @@ -15,5 +15,5 @@ module.exports = Self => { require('../methods/invoiceOut/exportationPdf')(Self); require('../methods/invoiceOut/invoiceCsv')(Self); require('../methods/invoiceOut/invoiceCsvEmail')(Self); - require('../methods/invoiceOut/invoicePdf')(Self); + require('../methods/invoiceOut/invoiceOutPdf')(Self); }; From 0ffbb5fe2c422dcbeb545e7621d31357e8b21aa3 Mon Sep 17 00:00:00 2001 From: vicent Date: Mon, 30 Jan 2023 12:13:01 +0100 Subject: [PATCH 32/48] feat: actualizada visualizacion de datos --- modules/invoiceOut/front/global-invoicing/index.html | 7 ++++--- modules/invoiceOut/front/global-invoicing/index.js | 8 +++++--- modules/invoiceOut/front/global-invoicing/locale/es.yml | 1 + modules/invoiceOut/front/global-invoicing/style.scss | 6 ++++-- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/modules/invoiceOut/front/global-invoicing/index.html b/modules/invoiceOut/front/global-invoicing/index.html index 8f1e909e1..e2d918bf8 100644 --- a/modules/invoiceOut/front/global-invoicing/index.html +++ b/modules/invoiceOut/front/global-invoicing/index.html @@ -1,7 +1,8 @@
{{'Calculating packages to invoice...'}}
-
Invoicing
+
Invoicing
+
Ended process
{{'Current client id' | translate}}: {{$ctrl.currentClientId}}
@@ -31,7 +32,7 @@ {{::client.id}} - + {{::client.address.nickname}} @@ -40,7 +41,7 @@ {{::client.address.street}} - + diff --git a/modules/invoiceOut/front/global-invoicing/index.js b/modules/invoiceOut/front/global-invoicing/index.js index 4e46d7a81..09d5fba59 100644 --- a/modules/invoiceOut/front/global-invoicing/index.js +++ b/modules/invoiceOut/front/global-invoicing/index.js @@ -39,7 +39,7 @@ class Controller extends Section { } getPercentage() { - this.percentage = (this.currentClient * 100) / this.clients.length; + this.percentage = ((this.currentClient - 1) * 100) / this.clients.length; } restartValues() { @@ -49,7 +49,10 @@ class Controller extends Section { invoiceOut(invoice, clientsAndAddresses) { const [clientAndAddress] = clientsAndAddresses; - if (!clientAndAddress) return; + if (!clientAndAddress) { + this.percentage = 100; + return; + } this.currentClientId = clientAndAddress.clientId; this.currentClient = ++this.currentClient; @@ -113,7 +116,6 @@ class Controller extends Section { return this.invoiceOut(invoice, clientsAndAddresses); }) - .then(() => this.vnApp.showSuccess(this.$t('Data saved!'))) .finally(() => this.restartValues()); } catch (e) { this.vnApp.showError(this.$t(e.message)); diff --git a/modules/invoiceOut/front/global-invoicing/locale/es.yml b/modules/invoiceOut/front/global-invoicing/locale/es.yml index 5a453e5b9..0c4cf14fc 100644 --- a/modules/invoiceOut/front/global-invoicing/locale/es.yml +++ b/modules/invoiceOut/front/global-invoicing/locale/es.yml @@ -17,4 +17,5 @@ of: de Client: Cliente Current client id: Id cliente actual Invoicing: Facturando +Ended process: Proceso finalizado Invoice out: Facturar diff --git a/modules/invoiceOut/front/global-invoicing/style.scss b/modules/invoiceOut/front/global-invoicing/style.scss index ae50adf6e..6fdfac0ba 100644 --- a/modules/invoiceOut/front/global-invoicing/style.scss +++ b/modules/invoiceOut/front/global-invoicing/style.scss @@ -6,8 +6,10 @@ vn-invoice-out-global-invoicing{ color: $color-primary; } - .vn-table vn-tbody > * > vn-td { - overflow: visible; + #error { + line-break: normal; + overflow-wrap: break-word; + white-space: normal; } } From 3b94f916b77dd6f3cdf8c2e7c1ba069a0be171d6 Mon Sep 17 00:00:00 2001 From: vicent Date: Mon, 30 Jan 2023 12:49:01 +0100 Subject: [PATCH 33/48] refactor --- modules/invoiceOut/front/global-invoicing/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/invoiceOut/front/global-invoicing/index.html b/modules/invoiceOut/front/global-invoicing/index.html index e2d918bf8..53df44670 100644 --- a/modules/invoiceOut/front/global-invoicing/index.html +++ b/modules/invoiceOut/front/global-invoicing/index.html @@ -3,7 +3,7 @@
Invoicing
Ended process
-
+
{{'Current client id' | translate}}: {{$ctrl.currentClientId}}
From 4754dc7bda49d8f64501ad74ccf6de293d33a845 Mon Sep 17 00:00:00 2001 From: vicent Date: Thu, 9 Feb 2023 11:03:22 +0100 Subject: [PATCH 34/48] feat: actualizada sql intrastat --- db/changes/230601/00-invoiceOut_getWeight.sql | 30 ++++++++++ print/templates/reports/invoice/invoice.html | 2 +- print/templates/reports/invoice/invoice.js | 3 +- .../reports/invoice/sql/hasIntrastat.sql | 4 ++ .../reports/invoice/sql/intrastat.sql | 60 +++++++++++-------- 5 files changed, 72 insertions(+), 27 deletions(-) create mode 100644 db/changes/230601/00-invoiceOut_getWeight.sql create mode 100644 print/templates/reports/invoice/sql/hasIntrastat.sql diff --git a/db/changes/230601/00-invoiceOut_getWeight.sql b/db/changes/230601/00-invoiceOut_getWeight.sql new file mode 100644 index 000000000..4ca284857 --- /dev/null +++ b/db/changes/230601/00-invoiceOut_getWeight.sql @@ -0,0 +1,30 @@ +DROP FUNCTION IF EXISTS `vn`.`invoiceOut_getWeight`; + +DELIMITER $$ +$$ +CREATE DEFINER=`root`@`localhost` FUNCTION `vn`.`invoiceOut_getWeight`(vInvoice VARCHAR(15)) RETURNS decimal(10,2) + READS SQL DATA +BEGIN +/** + * Calcula el peso de una factura emitida + * + * @param vInvoice Id de la factura + * @return vTotalWeight peso de la factura + */ + DECLARE vTotalWeight DECIMAL(10,2); + + SELECT SUM(CAST(IFNULL(i.stems, 1) + * s.quantity + * IF(ic.grams, ic.grams, IFNULL(i.weightByPiece, 0)) / 1000 AS DECIMAL(10,2))) + INTO vTotalWeight + FROM ticket t + JOIN sale s ON s.ticketFk = t.id + JOIN item i ON i.id = s.itemFk + JOIN itemCost ic ON ic.itemFk = i.id + AND ic.warehouseFk = t.warehouseFk + WHERE t.refFk = vInvoice + AND i.intrastatFk; + + RETURN vTotalWeight; +END$$ +DELIMITER ; diff --git a/print/templates/reports/invoice/invoice.html b/print/templates/reports/invoice/invoice.html index 60d06d528..fa4c19256 100644 --- a/print/templates/reports/invoice/invoice.html +++ b/print/templates/reports/invoice/invoice.html @@ -203,7 +203,7 @@
-
+

{{$t('intrastat')}}

diff --git a/print/templates/reports/invoice/invoice.js b/print/templates/reports/invoice/invoice.js index 7b572d970..5f5aad87e 100755 --- a/print/templates/reports/invoice/invoice.js +++ b/print/templates/reports/invoice/invoice.js @@ -10,7 +10,8 @@ module.exports = { this.checkMainEntity(this.invoice); this.client = await this.findOneFromDef('client', [this.reference]); this.taxes = await this.rawSqlFromDef(`taxes`, [this.reference]); - this.intrastat = await this.rawSqlFromDef(`intrastat`, [this.reference, this.reference, this.reference]); + [this.hasIntrastat] = await this.rawSqlFromDef(`hasIntrastat`, [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/hasIntrastat.sql b/print/templates/reports/invoice/sql/hasIntrastat.sql new file mode 100644 index 000000000..3140c0f3f --- /dev/null +++ b/print/templates/reports/invoice/sql/hasIntrastat.sql @@ -0,0 +1,4 @@ +SELECT taxAreaFk + FROM vn.invoiceOutSerial ios + JOIN vn.invoiceOut io ON io.serial = ios.code + WHERE io.ref = ?; diff --git a/print/templates/reports/invoice/sql/intrastat.sql b/print/templates/reports/invoice/sql/intrastat.sql index f986a9564..49c97a758 100644 --- a/print/templates/reports/invoice/sql/intrastat.sql +++ b/print/templates/reports/invoice/sql/intrastat.sql @@ -1,26 +1,36 @@ SELECT * - FROM invoiceOut io - JOIN invoiceOutSerial ios ON io.serial = ios.code - JOIN( - SELECT ir.id code, - ir.description, - iii.stems, - iii.net netKg, - iii.amount subtotal - FROM vn.invoiceInIntrastat iii - LEFT JOIN vn.invoiceIn ii ON ii.id = iii.invoiceInFk - LEFT JOIN vn.invoiceOut io ON io.ref = ii.supplierRef - LEFT JOIN vn.intrastat ir ON ir.id = iii.intrastatFk - WHERE io.`ref` = ? - UNION ALL - SELECT NULL code, - 'Servicios' description, - 0 stems, - 0 netKg, - IF(CAST(SUM((ts.quantity * ts.price)) AS DECIMAL(10,2)), CAST(SUM((ts.quantity * ts.price)) AS DECIMAL(10,2)), 0) subtotal - FROM vn.ticketService ts - JOIN vn.ticket t ON ts.ticketFk = t.id - WHERE t.refFk = ? - ) sub - WHERE io.ref = ? AND ios.isCEE - ORDER BY sub.code; + FROM ( + SELECT i.intrastatFk code, + it.description, + SUM(CAST((s.quantity * s.price * (100 - s.discount) / 100 ) AS DECIMAL(10, 2))) subtotal, + SUM(CAST(IFNULL(i.stems, 1) * s.quantity AS DECIMAL(10, 2))) stems, + CAST(SUM(IFNULL(i.stems, 1) + * s.quantity + * IF(ic.grams, ic.grams, IFNULL(i.weightByPiece, 0)) / 1000) + * IF(sub.totalWeight, sub.totalWeight / vn.invoiceOut_getWeight(?), 1) + AS DECIMAL(10,2)) netKg + FROM sale s + JOIN ticket t ON s.ticketFk = t.id + JOIN supplier su ON su.id = t.companyFk + JOIN item i ON i.id = s.itemFk + JOIN intrastat it ON it.id = i.intrastatFk + LEFT JOIN itemCost ic ON ic.itemFk = i.id AND ic.warehouseFk = t.warehouseFk + LEFT JOIN ( + SELECT SUM(weight)totalWeight + FROM vn.ticket + WHERE refFk = ? + AND weight + ) sub ON TRUE + WHERE t.refFk =? + GROUP BY i.intrastatFk + UNION ALL + SELECT NULL , + IF((SUM((ts.quantity * ts.price))), 'Servicios', NULL), + IFNULL(CAST(SUM((ts.quantity * ts.price)) AS DECIMAL(10,2)), 0), + 0 , + 0 + FROM vn.ticketService ts + JOIN vn.ticket t ON ts.ticketFk = t.id + WHERE t.refFk = ? + ) sub2 + WHERE `description` IS NOT NULL; From 5b22096567aeea6f8d057d9fd59e666e1f85781e Mon Sep 17 00:00:00 2001 From: vicent Date: Thu, 9 Feb 2023 14:57:08 +0100 Subject: [PATCH 35/48] refactor: actuializada consulta par obtener los clientes a facturar. Excluido impresion pdfs de la transaccion --- .../methods/invoiceOut/clientsToInvoice.js | 46 +++++++------------ .../back/methods/invoiceOut/invoiceClient.js | 22 ++++----- 2 files changed, 27 insertions(+), 41 deletions(-) diff --git a/modules/invoiceOut/back/methods/invoiceOut/clientsToInvoice.js b/modules/invoiceOut/back/methods/invoiceOut/clientsToInvoice.js index 3bab9b8bd..7eeb82e35 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/clientsToInvoice.js +++ b/modules/invoiceOut/back/methods/invoiceOut/clientsToInvoice.js @@ -150,38 +150,24 @@ module.exports = Self => { const args = ctx.args; minShipped.setFullYear(minShipped.getFullYear() - 1); - const query = `SELECT - c.id, - SUM(IFNULL - ( - s.quantity * - s.price * (100-s.discount)/100, - 0) - + IFNULL(ts.quantity * ts.price,0) - ) AS sumAmount, - c.hasToInvoiceByAddress, - c.email, - c.isToBeMailed, - a.id addressFk - FROM ticket t - LEFT JOIN sale s ON s.ticketFk = t.id - LEFT JOIN ticketService ts ON ts.ticketFk = t.id - JOIN address a ON a.id = t.addressFk - JOIN client c ON c.id = t.clientFk - WHERE ISNULL(t.refFk) AND c.id >= ? - AND (t.clientFk <= ? OR ? IS NULL) - AND t.shipped BETWEEN ? AND util.dayEnd(?) - AND t.companyFk = ? - AND c.hasToInvoice - AND c.isTaxDataChecked - AND c.isActive - AND NOT t.isDeleted - GROUP BY c.id, IF(c.hasToInvoiceByAddress,a.id,TRUE) HAVING sumAmount > 0`; + const query = `SELECT c.id, + c.hasToInvoiceByAddress, + a.id addressFk, + sum(t.totalWithVat) totalAmount + FROM ticket t + JOIN address a ON a.id = t.addressFk + JOIN client c ON c.id = t.clientFk + WHERE t.refFk IS NULL + AND t.shipped BETWEEN ? AND util.dayEnd(?) + AND t.companyFk = ? + AND c.hasToInvoice + AND c.isTaxDataChecked + AND c.isActive + AND NOT t.isDeleted + GROUP BY c.id, IF(c.hasToInvoiceByAddress, a.id, TRUE) + HAVING totalAmount > 0;`; return models.InvoiceOut.rawSql(query, [ - args.fromClientId, - args.toClientId, - args.toClientId, minShipped, args.maxShipped, args.companyFk diff --git a/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js b/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js index b401d08b7..ce700796f 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js +++ b/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js @@ -127,23 +127,23 @@ module.exports = Self => { invoiceId = newInvoice.id; } - if (invoiceId && !invoiceOut.client().isToBeMailed) { - const query = `CALL vn.report_print( - 'invoice', - ?, - account.myUser_getId(), - JSON_OBJECT('refFk', ?), - 'normal' - );`; - await models.InvoiceOut.rawSql(query, [args.printerFk, invoiceOut.ref], myOptions); - } - if (tx) await tx.commit(); } catch (e) { if (tx) await tx.rollback(); throw e; } + if (invoiceId && !invoiceOut.client().isToBeMailed) { + const query = `CALL vn.report_print( + 'invoice', + ?, + account.myUser_getId(), + JSON_OBJECT('refFk', ?), + 'normal' + );`; + await models.InvoiceOut.rawSql(query, [args.printerFk, invoiceOut.ref]); + } + if (invoiceId && invoiceOut.client().isToBeMailed) { ctx.args = { reference: invoiceOut.ref, From e61af5286bccaf52479d6d3e7e50a0bfcd88a216 Mon Sep 17 00:00:00 2001 From: vicent Date: Fri, 10 Feb 2023 10:10:48 +0100 Subject: [PATCH 36/48] fix: actualizada sql intrastat --- print/templates/reports/invoice/sql/intrastat.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/print/templates/reports/invoice/sql/intrastat.sql b/print/templates/reports/invoice/sql/intrastat.sql index 49c97a758..211ebfe71 100644 --- a/print/templates/reports/invoice/sql/intrastat.sql +++ b/print/templates/reports/invoice/sql/intrastat.sql @@ -2,8 +2,8 @@ SELECT * FROM ( SELECT i.intrastatFk code, it.description, - SUM(CAST((s.quantity * s.price * (100 - s.discount) / 100 ) AS DECIMAL(10, 2))) subtotal, - SUM(CAST(IFNULL(i.stems, 1) * s.quantity AS DECIMAL(10, 2))) stems, + CAST(SUM(ROUND((s.quantity * s.price * (100 - s.discount) / 100 ) , 2))AS DECIMAL(10, 2)) subtotal, + SUM(IFNULL(i.stems, 1) * s.quantity) stems, CAST(SUM(IFNULL(i.stems, 1) * s.quantity * IF(ic.grams, ic.grams, IFNULL(i.weightByPiece, 0)) / 1000) From 01ade6eb03604d83d5cf37604911531e27125dbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Andr=C3=A9s?= Date: Thu, 23 Feb 2023 09:23:06 +0100 Subject: [PATCH 37/48] refs #5000 Merge with dev --- print/templates/reports/invoice/invoice.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/print/templates/reports/invoice/invoice.html b/print/templates/reports/invoice/invoice.html index 7cea819a4..2d180878a 100644 --- a/print/templates/reports/invoice/invoice.html +++ b/print/templates/reports/invoice/invoice.html @@ -203,7 +203,7 @@ -
+

{{$t('intrastat')}}

From 4cc6485cbd0297e6d7551a9ba3ecfac170ce03fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Andr=C3=A9s?= Date: Thu, 23 Feb 2023 09:25:23 +0100 Subject: [PATCH 38/48] refs #5000 Invoicing RC --- .vscode/settings.json | 3 +- db/changes/230601/00-invoiceOut.sql | 6 + .../230601/01-invoiceOut_getMaxIssued.sql | 34 +++ db/changes/230601/02-invoiceOut_new.sql | 258 ++++++++++++++++++ db/changes/230601/03-ticketPackaging_add.sql | 141 ++++++++++ db/dump/fixtures.sql | 13 +- loopback/locale/es.json | 13 +- .../methods/invoiceOut/clientsToInvoice.js | 181 ++++-------- .../back/methods/invoiceOut/getInvoiceDate.js | 39 +++ .../back/methods/invoiceOut/invoiceClient.js | 123 ++++----- modules/invoiceOut/back/models/invoice-out.js | 1 + .../front/global-invoicing/index.html | 118 +++++--- .../front/global-invoicing/index.js | 215 ++++++++------- .../front/global-invoicing/index.spec.js | 107 +++----- .../front/global-invoicing/locale/es.yml | 15 +- modules/ticket/front/sale-tracking/style.scss | 10 +- 16 files changed, 838 insertions(+), 439 deletions(-) create mode 100644 db/changes/230601/00-invoiceOut.sql create mode 100644 db/changes/230601/01-invoiceOut_getMaxIssued.sql create mode 100644 db/changes/230601/02-invoiceOut_new.sql create mode 100644 db/changes/230601/03-ticketPackaging_add.sql create mode 100644 modules/invoiceOut/back/methods/invoiceOut/getInvoiceDate.js diff --git a/.vscode/settings.json b/.vscode/settings.json index b5da1e8e6..82815d588 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,5 +4,6 @@ "files.eol": "\n", "editor.codeActionsOnSave": { "source.fixAll.eslint": true - } + }, + "search.useIgnoreFiles": false } diff --git a/db/changes/230601/00-invoiceOut.sql b/db/changes/230601/00-invoiceOut.sql new file mode 100644 index 000000000..4404c8f4a --- /dev/null +++ b/db/changes/230601/00-invoiceOut.sql @@ -0,0 +1,6 @@ +ALTER TABLE vn.invoiceOutSerial + ADD `type` ENUM('global', 'quick') DEFAULT NULL NULL; + + UPDATE vn.invoiceOutSerial + SET type = 'global' + WHERE code IN ('A','V'); \ No newline at end of file diff --git a/db/changes/230601/01-invoiceOut_getMaxIssued.sql b/db/changes/230601/01-invoiceOut_getMaxIssued.sql new file mode 100644 index 000000000..e120b949d --- /dev/null +++ b/db/changes/230601/01-invoiceOut_getMaxIssued.sql @@ -0,0 +1,34 @@ +DROP FUNCTION IF EXISTS `vn`.`invoiceOut_getMaxIssued`; + +DELIMITER $$ +$$ +CREATE OR REPLACE DEFINER=`root`@`localhost` FUNCTION `vn`.`invoiceOut_getMaxIssued`( + vSerial VARCHAR(2), + vCompanyFk INT, + vYear INT +) RETURNS DATE + READS SQL DATA +BEGIN +/** + * Retorna la fecha a partir de la cual es válido emitir una factura + * + * @param vSerial Serie de facturación + * @param vCompanyFk Empresa factura emitida + * @param vYear Año contable + * @return vInvoiceOutIssued fecha factura válida + */ + DECLARE vInvoiceOutIssued DATE; + DECLARE vFirstDayOfYear DATE; + + SET vFirstDayOfYear := MAKEDATE(vYear, 1); + + SELECT IFNULL(MAX(io.issued), vFirstDayOfYear) INTO vInvoiceOutIssued + FROM invoiceOut io + WHERE io.serial = vSerial + AND io.companyFk = vCompanyFk + AND io.issued BETWEEN vFirstDayOfYear + AND util.lastDayOfYear(vFirstDayOfYear); + + RETURN vInvoiceOutIssued; +END$$ +DELIMITER ; \ No newline at end of file diff --git a/db/changes/230601/02-invoiceOut_new.sql b/db/changes/230601/02-invoiceOut_new.sql new file mode 100644 index 000000000..dd7136ff7 --- /dev/null +++ b/db/changes/230601/02-invoiceOut_new.sql @@ -0,0 +1,258 @@ +DROP PROCEDURE IF EXISTS `vn`.`invoiceOut_new`; + +DELIMITER $$ +$$ +CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`invoiceOut_new`( + vSerial VARCHAR(255), + vInvoiceDate DATE, + vTaxArea VARCHAR(25), + OUT vNewInvoiceId INT) +BEGIN +/** + * Creación de facturas emitidas. + * requiere previamente tabla ticketToInvoice(id). + * + * @param vSerial serie a la cual se hace la factura + * @param vInvoiceDate fecha de la factura + * @param vTaxArea tipo de iva en relacion a la empresa y al cliente + * @param vNewInvoiceId id de la factura que se acaba de generar + * @return vNewInvoiceId + */ + DECLARE vIsAnySaleToInvoice BOOL; + DECLARE vIsAnyServiceToInvoice BOOL; + DECLARE vNewRef VARCHAR(255); + DECLARE vWorker INT DEFAULT account.myUser_getId(); + DECLARE vCompanyFk INT; + DECLARE vInterCompanyFk INT; + DECLARE vClientFk INT; + DECLARE vCplusStandardInvoiceTypeFk INT DEFAULT 1; + DECLARE vCplusCorrectingInvoiceTypeFk INT DEFAULT 6; + DECLARE vCplusSimplifiedInvoiceTypeFk INT DEFAULT 2; + DECLARE vCorrectingSerial VARCHAR(1) DEFAULT 'R'; + DECLARE vSimplifiedSerial VARCHAR(1) DEFAULT 'S'; + DECLARE vNewInvoiceInFk INT; + DECLARE vIsInterCompany BOOL DEFAULT FALSE; + DECLARE vIsCEESerial BOOL DEFAULT FALSE; + DECLARE vIsCorrectInvoiceDate BOOL; + DECLARE vMaxShipped DATE; + + SET vInvoiceDate = IFNULL(vInvoiceDate, util.CURDATE()); + + SELECT t.clientFk, + t.companyFk, + MAX(DATE(t.shipped)), + DATE(vInvoiceDate) >= invoiceOut_getMaxIssued( + vSerial, + t.companyFk, + YEAR(vInvoiceDate)) + INTO vClientFk, + vCompanyFk, + vMaxShipped, + vIsCorrectInvoiceDate + FROM ticketToInvoice tt + JOIN ticket t ON t.id = tt.id; + + IF(vMaxShipped > vInvoiceDate) THEN + CALL util.throw("Invoice date can't be less than max date"); + END IF; + + IF NOT vIsCorrectInvoiceDate THEN + CALL util.throw('Exists an invoice with a previous date'); + END IF; + + -- Eliminem de ticketToInvoice els tickets que no han de ser facturats + DELETE ti.* + FROM ticketToInvoice ti + JOIN ticket t ON t.id = ti.id + JOIN sale s ON s.ticketFk = t.id + JOIN item i ON i.id = s.itemFk + JOIN supplier su ON su.id = t.companyFk + JOIN client c ON c.id = t.clientFk + LEFT JOIN itemTaxCountry itc ON itc.itemFk = i.id AND itc.countryFk = su.countryFk + WHERE YEAR(t.shipped) < 2001 + OR c.isTaxDataChecked = FALSE + OR t.isDeleted + OR c.hasToInvoice = FALSE + OR itc.id IS NULL; + + SELECT SUM(s.quantity * s.price * (100 - s.discount)/100) <> 0 + INTO vIsAnySaleToInvoice + FROM ticketToInvoice t + JOIN sale s ON s.ticketFk = t.id; + + SELECT COUNT(*) > 0 INTO vIsAnyServiceToInvoice + FROM ticketToInvoice t + JOIN ticketService ts ON ts.ticketFk = t.id; + + IF (vIsAnySaleToInvoice OR vIsAnyServiceToInvoice) + AND (vCorrectingSerial = vSerial OR NOT hasAnyNegativeBase()) + THEN + + -- el trigger añade el siguiente Id_Factura correspondiente a la vSerial + INSERT INTO invoiceOut( + ref, + serial, + issued, + clientFk, + dued, + companyFk, + cplusInvoiceType477Fk + ) + SELECT + 1, + vSerial, + vInvoiceDate, + vClientFk, + getDueDate(vInvoiceDate, dueDay), + vCompanyFk, + IF(vSerial = vCorrectingSerial, + vCplusCorrectingInvoiceTypeFk, + IF(vSerial = vSimplifiedSerial, + vCplusSimplifiedInvoiceTypeFk, + vCplusStandardInvoiceTypeFk)) + FROM client + WHERE id = vClientFk; + + SET vNewInvoiceId = LAST_INSERT_ID(); + + SELECT `ref` + INTO vNewRef + FROM invoiceOut + WHERE id = vNewInvoiceId; + + UPDATE ticket t + JOIN ticketToInvoice ti ON ti.id = t.id + SET t.refFk = vNewRef; + + DROP TEMPORARY TABLE IF EXISTS tmp.updateInter; + CREATE TEMPORARY TABLE tmp.updateInter ENGINE = MEMORY + SELECT s.id,ti.id ticket_id,vWorker Id_Trabajador + FROM ticketToInvoice ti + LEFT JOIN ticketState ts ON ti.id = ts.ticket + JOIN state s + WHERE IFNULL(ts.alertLevel,0) < 3 and s.`code` = getAlert3State(ti.id); + + INSERT INTO ticketTracking(stateFk,ticketFk,workerFk) + SELECT * FROM tmp.updateInter; + + INSERT INTO ticketLog (action, userFk, originFk, description) + SELECT 'UPDATE', account.myUser_getId(), ti.id, CONCAT('Crea factura ', vNewRef) + FROM ticketToInvoice ti; + + CALL invoiceExpenceMake(vNewInvoiceId); + CALL invoiceTaxMake(vNewInvoiceId,vTaxArea); + + UPDATE invoiceOut io + JOIN ( + SELECT SUM(amount) total + FROM invoiceOutExpence + WHERE invoiceOutFk = vNewInvoiceId + ) base + JOIN ( + SELECT SUM(vat) total + FROM invoiceOutTax + WHERE invoiceOutFk = vNewInvoiceId + ) vat + SET io.amount = base.total + vat.total + WHERE io.id = vNewInvoiceId; + + DROP TEMPORARY TABLE tmp.updateInter; + + SELECT COUNT(*), id + INTO vIsInterCompany, vInterCompanyFk + FROM company + WHERE clientFk = vClientFk; + + IF (vIsInterCompany) THEN + + INSERT INTO invoiceIn(supplierFk, supplierRef, issued, companyFk) + SELECT vCompanyFk, vNewRef, vInvoiceDate, vInterCompanyFk; + + SET vNewInvoiceInFk = LAST_INSERT_ID(); + + DROP TEMPORARY TABLE IF EXISTS tmp.ticket; + CREATE TEMPORARY TABLE tmp.ticket + (KEY (ticketFk)) + ENGINE = MEMORY + SELECT id ticketFk + FROM ticketToInvoice; + + CALL `ticket_getTax`('NATIONAL'); + + SET @vTaxableBaseServices := 0.00; + SET @vTaxCodeGeneral := NULL; + + INSERT INTO invoiceInTax(invoiceInFk, taxableBase, expenceFk, taxTypeSageFk, transactionTypeSageFk) + SELECT vNewInvoiceInFk, + @vTaxableBaseServices, + sub.expenceFk, + sub.taxTypeSageFk, + sub.transactionTypeSageFk + FROM ( + SELECT @vTaxableBaseServices := SUM(tst.taxableBase) taxableBase, + i.expenceFk, + i.taxTypeSageFk, + i.transactionTypeSageFk, + @vTaxCodeGeneral := i.taxClassCodeFk + FROM tmp.ticketServiceTax tst + JOIN invoiceOutTaxConfig i ON i.taxClassCodeFk = tst.code + WHERE i.isService + HAVING taxableBase + ) sub; + + INSERT INTO invoiceInTax(invoiceInFk, taxableBase, expenceFk, taxTypeSageFk, transactionTypeSageFk) + SELECT vNewInvoiceInFk, + SUM(tt.taxableBase) - IF(tt.code = @vTaxCodeGeneral, + @vTaxableBaseServices, 0) taxableBase, + i.expenceFk, + i.taxTypeSageFk , + i.transactionTypeSageFk + FROM tmp.ticketTax tt + JOIN invoiceOutTaxConfig i ON i.taxClassCodeFk = tt.code + WHERE !i.isService + GROUP BY tt.pgcFk + HAVING taxableBase + ORDER BY tt.priority; + + CALL invoiceInDueDay_calculate(vNewInvoiceInFk); + + SELECT COUNT(*) INTO vIsCEESerial + FROM invoiceOutSerial + WHERE code = vSerial; + + IF vIsCEESerial THEN + + INSERT INTO invoiceInIntrastat ( + invoiceInFk, + intrastatFk, + amount, + stems, + countryFk, + net) + SELECT + vNewInvoiceInFk, + i.intrastatFk, + SUM(CAST((s.quantity * s.price * (100 - s.discount) / 100 ) AS DECIMAL(10, 2))), + SUM(CAST(IFNULL(i.stems, 1) * s.quantity AS DECIMAL(10, 2))), + su.countryFk, + CAST(SUM(IFNULL(i.stems, 1) + * s.quantity + * IF(ic.grams, ic.grams, IFNULL(i.weightByPiece, 0)) / 1000) AS DECIMAL(10, 2)) + FROM sale s + JOIN ticket t ON s.ticketFk = t.id + JOIN supplier su ON su.id = t.companyFk + JOIN item i ON i.id = s.itemFk + LEFT JOIN itemCost ic ON ic.itemFk = i.id AND ic.warehouseFk = t.warehouseFk + WHERE t.refFk = vNewRef + GROUP BY i.intrastatFk; + + END IF; + DROP TEMPORARY TABLE tmp.ticket; + DROP TEMPORARY TABLE tmp.ticketAmount; + DROP TEMPORARY TABLE tmp.ticketTax; + DROP TEMPORARY TABLE tmp.ticketServiceTax; + END IF; + END IF; + DROP TEMPORARY TABLE `ticketToInvoice`; +END$$ +DELIMITER ; \ No newline at end of file diff --git a/db/changes/230601/03-ticketPackaging_add.sql b/db/changes/230601/03-ticketPackaging_add.sql new file mode 100644 index 000000000..f5e3d50ad --- /dev/null +++ b/db/changes/230601/03-ticketPackaging_add.sql @@ -0,0 +1,141 @@ +DROP PROCEDURE IF EXISTS `vn`.`ticketPackaging_add`; + +DELIMITER $$ +$$ +CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticketPackaging_add`( + vClientFk INT, + vDated DATE, + vCompanyFk INT, + vWithoutPeriodGrace BOOLEAN) +BEGIN +/** + * Genera nuevos tickets de embalajes para los clientes no han los han retornado + * y actualiza los valores para la tabla ticketPackaging + * + * @param vClientFk Cliente en caso de NULL todos los clientes + * @param vDated Fecha hasta la cual se revisan los embalajes + * @param vCompanyFk Empresa de la cual se comprobaran sus clientes + * @param vWithoutPeriodGrace si no se aplica el periodo de gracia de un mes + */ + DECLARE vNewTicket INT; + DECLARE vDateStart DATE; + DECLARE vDateEnd DATE; + DECLARE vGraceDate DATE DEFAULT vDated; + DECLARE vWarehouseInventory INT; + DECLARE vComponentCost INT; + DECLARE vDone INT DEFAULT FALSE; + DECLARE vClientId INT; + + DECLARE vCursor CURSOR FOR + SELECT DISTINCT clientFk + FROM ( + SELECT clientFk, SUM(quantity) totalQuantity + FROM tmp.packagingToInvoice + GROUP BY itemFk, clientFk + HAVING totalQuantity > 0)sub; + + DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE; + + DECLARE EXIT HANDLER FOR SQLEXCEPTION + BEGIN + ROLLBACK; + RESIGNAL; + END; + + SELECT id INTO vWarehouseInventory + FROM warehouse + WHERE `code`= 'inv'; + + SELECT id INTO vComponentCost + FROM component + WHERE `code`= 'purchaseValue'; + + SELECT packagingInvoicingDated INTO vDateStart + FROM ticketConfig; + + IF vWarehouseInventory IS NULL THEN + CALL util.throw('Warehouse inventory not seted'); + END IF; + + IF vComponentCost IS NULL THEN + CALL util.throw('Component cost not seted'); + END IF; + + SET vDateEnd = vDated + INTERVAL 1 DAY; + + IF NOT vWithoutPeriodGrace THEN + SET vGraceDate = vGraceDate -INTERVAL 1 MONTH; + END IF; + + DROP TEMPORARY TABLE IF EXISTS tmp.packagingToInvoice; + CREATE TEMPORARY TABLE tmp.packagingToInvoice + (INDEX (clientFk)) + ENGINE = MEMORY + SELECT p.itemFk, + tp.packagingFk, + tp.quantity, + tp.ticketFk, + p.price, + t.clientFk + FROM ticketPackaging tp + JOIN packaging p ON p.id = tp.packagingFk + JOIN ticket t ON t.id = tp.ticketFk + JOIN client c ON c.id = t.clientFk + WHERE c.isActive + AND (vClientFk IS NULL OR t.clientFk = vClientFk) + AND t.shipped BETWEEN vDateStart AND vDateEnd + AND (tp.quantity < 0 OR (tp.quantity > 0 AND t.shipped < vGraceDate)) + AND tp.quantity + AND p.itemFk; + + OPEN vCursor; + l: LOOP + + FETCH vCursor INTO vClientId; + + IF vDone THEN + LEAVE l; + END IF; + + START TRANSACTION; + + CALL ticket_add( + vClientId, + vDateEnd, + vWarehouseInventory, + vCompanyFk, + NULL, + NULL, + NULL, + vDateEnd, + account.myUser_getId(), + TRUE, + vNewTicket); + + INSERT INTO ticketPackaging(ticketFk, packagingFk, quantity, pvp) + SELECT vNewTicket, packagingFk, - SUM(quantity) totalQuantity, price + FROM tmp.packagingToInvoice + WHERE clientFk = vClientId + GROUP BY packagingFk + HAVING IF(vWithoutPeriodGrace, totalQuantity <> 0, totalQuantity < 0); + + INSERT INTO sale(ticketFk, itemFk, concept, quantity, price) + SELECT vNewTicket, pti.itemFk, i.name, SUM(pti.quantity) totalQuantity, pti.price + FROM tmp.packagingToInvoice pti + JOIN item i ON i.id = pti.itemFk + WHERE pti.clientFk = vClientId + GROUP BY pti.itemFk + HAVING IF(vWithoutPeriodGrace, totalQuantity <> 0, totalQuantity > 0); + + INSERT INTO saleComponent(saleFk, componentFk, value) + SELECT id, vComponentCost, price + FROM sale + WHERE ticketFk = vNewTicket; + + COMMIT; + END LOOP; + CLOSE vCursor; + + DROP TEMPORARY TABLE tmp.packagingToInvoice; +END$$ +DELIMITER ; \ No newline at end of file diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index d20b5274f..ae98e5cde 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -572,14 +572,13 @@ INSERT INTO `vn`.`taxArea` (`code`, `claveOperacionFactura`, `CodigoTransaccion` ('NATIONAL', 0, 1), ('WORLD', 2, 15); -INSERT INTO `vn`.`invoiceOutSerial` (`code`, `description`, `isTaxed`, `taxAreaFk`, `isCEE`) +INSERT INTO `vn`.`invoiceOutSerial` (`code`, `description`, `isTaxed`, `taxAreaFk`, `isCEE`, `type`) VALUES - ('A', 'Global nacional', 1, 'NATIONAL', 0), - ('T', 'Española rapida', 1, 'NATIONAL', 0), - ('V', 'Intracomunitaria global', 0, 'CEE', 1), - ('M', 'Múltiple nacional', 1, 'NATIONAL', 0), - ('E', 'Exportación rápida', 0, 'WORLD', 0); -; + ('A', 'Global nacional', 1, 'NATIONAL', 0, 'global'), + ('T', 'Española rapida', 1, 'NATIONAL', 0, 'quick'), + ('V', 'Intracomunitaria global', 0, 'CEE', 1, 'global'), + ('M', 'Múltiple nacional', 1, 'NATIONAL', 0, 'quick'), + ('E', 'Exportación rápida', 0, 'WORLD', 0, 'quick'); INSERT INTO `vn`.`invoiceOut`(`id`, `serial`, `amount`, `issued`,`clientFk`, `created`, `companyFk`, `dued`, `booked`, `bankFk`, `hasPdf`) VALUES diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 8dee811fb..4d7159fe8 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -260,10 +260,11 @@ "Aplicación bloqueada por el usuario 9": "Aplicación bloqueada por el usuario 9", "Failed to upload file": "Error al subir archivo", "The DOCUWARE PDF document does not exists": "El documento PDF Docuware no existe", - "It is not possible to modify tracked sales": "No es posible modificar líneas de pedido que se hayan empezado a preparar", - "It is not possible to modify sales that their articles are from Floramondo": "No es posible modificar líneas de pedido cuyos artículos sean de Floramondo", - "It is not possible to modify cloned sales": "No es posible modificar líneas de pedido clonadas", + "It is not possible to modify tracked sales": "No es posible modificar líneas de pedido que se hayan empezado a preparar", + "It is not possible to modify sales that their articles are from Floramondo": "No es posible modificar líneas de pedido cuyos artículos sean de Floramondo", + "It is not possible to modify cloned sales": "No es posible modificar líneas de pedido clonadas", "A supplier with the same name already exists. Change the country.": "Un proveedor con el mismo nombre ya existe. Cambie el país.", - "There is no assigned email for this client": "No hay correo asignado para este cliente" -} - + "There is no assigned email for this client": "No hay correo asignado para este cliente", + "Exists an invoice with a previous date": "Existe una factura con fecha anterior", + "Invoice date can't be less than max date": "La fecha de factura no puede ser inferior a la fecha límite" +} \ No newline at end of file diff --git a/modules/invoiceOut/back/methods/invoiceOut/clientsToInvoice.js b/modules/invoiceOut/back/methods/invoiceOut/clientsToInvoice.js index 7eeb82e35..f18b0c682 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/clientsToInvoice.js +++ b/modules/invoiceOut/back/methods/invoiceOut/clientsToInvoice.js @@ -4,47 +4,37 @@ module.exports = Self => { accessType: 'WRITE', accepts: [ { + arg: 'clientId', + type: 'number', + description: 'The client id' + }, { arg: 'invoiceDate', type: 'date', - description: 'The invoice date' - }, - { + description: 'The invoice date', + required: true + }, { arg: 'maxShipped', type: 'date', - description: 'The maximum shipped date' - }, - { - arg: 'fromClientId', - type: 'number', - description: 'The minimum client id' - }, - { - arg: 'toClientId', - type: 'number', - description: 'The maximum client id' - }, - { + description: 'The maximum shipped date', + required: true + }, { arg: 'companyFk', type: 'number', - description: 'The company id to invoice' - } + description: 'The company id to invoice', + required: true + }, ], - returns: [{ - arg: 'clientsAndAddresses', - type: ['object'] + returns: { + type: 'Object', + root: true }, - { - arg: 'invoice', - type: 'object' - }], http: { path: '/clientsToInvoice', verb: 'POST' } }); - Self.clientsToInvoice = async(ctx, options) => { - const args = ctx.args; + Self.clientsToInvoice = async(ctx, clientId, invoiceDate, maxShipped, companyFk, options) => { let tx; const myOptions = {}; @@ -56,121 +46,52 @@ module.exports = Self => { myOptions.transaction = tx; } - let query; try { - query = ` - SELECT MAX(issued) issued - FROM vn.invoiceOut io - JOIN vn.time t ON t.dated = io.issued - WHERE io.serial = 'A' - AND t.year = YEAR(?) - AND io.companyFk = ?`; - const [maxIssued] = await Self.rawSql(query, [ - args.invoiceDate, - args.companyFk - ], myOptions); - - const maxSerialDate = maxIssued.issued || args.invoiceDate; - if (args.invoiceDate < maxSerialDate) - args.invoiceDate = maxSerialDate; - - if (args.invoiceDate < args.maxShipped) - args.maxShipped = args.invoiceDate; - - const minShipped = Date.vnNew(); - minShipped.setFullYear(minShipped.getFullYear() - 1); - minShipped.setMonth(1); - minShipped.setDate(1); - minShipped.setHours(0, 0, 0, 0); - // Packaging liquidation const vIsAllInvoiceable = false; - const clientsWithPackaging = await getClientsWithPackaging(ctx, myOptions); - for (let client of clientsWithPackaging) { - await Self.rawSql('CALL packageInvoicing(?, ?, ?, ?, @newTicket)', [ - client.id, - args.invoiceDate, - args.companyFk, - vIsAllInvoiceable - ], myOptions); - } + await Self.rawSql('CALL ticketPackaging_add(?, ?, ?, ?)', [ + clientId, + invoiceDate, + companyFk, + vIsAllInvoiceable + ], myOptions); - const invoiceableClients = await getInvoiceableClients(ctx, minShipped, myOptions); + const minShipped = Date.vnNew(); + minShipped.setFullYear(maxShipped.getFullYear() - 1); - if (!invoiceableClients) return; + const query = ` + SELECT c.id clientId, + c.name clientName, + a.id, + a.nickname + FROM ticket t + JOIN address a ON a.id = t.addressFk + JOIN client c ON c.id = t.clientFk + WHERE t.refFk IS NULL + AND t.shipped BETWEEN ? AND util.dayEnd(?) + AND (t.clientFk = ? OR ? IS NULL ) + AND t.companyFk = ? + AND c.hasToInvoice + AND c.isTaxDataChecked + AND c.isActive + AND NOT t.isDeleted + GROUP BY c.id, IF(c.hasToInvoiceByAddress, a.id, TRUE) + HAVING SUM(t.totalWithVat) > 0;`; - const clientsAndAddresses = invoiceableClients.map(invoiceableClient => { - return { - clientId: invoiceableClient.id, - addressId: invoiceableClient.addressFk - }; - } - ); + const addresses = await Self.rawSql(query, [ + minShipped, + maxShipped, + clientId, + clientId, + companyFk + ], myOptions); if (tx) await tx.commit(); - return [ - clientsAndAddresses, - { - invoiceDate: args.invoiceDate, - maxShipped: args.maxShipped, - fromClientId: args.fromClientId, - toClientId: args.toClientId, - companyFk: args.companyFk, - minShipped: minShipped - } - ]; + return addresses; } catch (e) { if (tx) await tx.rollback(); throw e; } }; - - async function getClientsWithPackaging(ctx, options) { - const models = Self.app.models; - const args = ctx.args; - const query = `SELECT DISTINCT clientFk AS id - FROM ticket t - JOIN ticketPackaging tp ON t.id = tp.ticketFk - JOIN client c ON c.id = t.clientFk - WHERE t.shipped BETWEEN '2017-11-21' AND ? - AND t.clientFk >= ? - AND (t.clientFk <= ? OR ? IS NULL) - AND c.isActive`; - return models.InvoiceOut.rawSql(query, [ - args.maxShipped, - args.fromClientId, - args.toClientId, - args.toClientId - ], options); - } - - async function getInvoiceableClients(ctx, minShipped, options) { - const models = Self.app.models; - const args = ctx.args; - minShipped.setFullYear(minShipped.getFullYear() - 1); - - const query = `SELECT c.id, - c.hasToInvoiceByAddress, - a.id addressFk, - sum(t.totalWithVat) totalAmount - FROM ticket t - JOIN address a ON a.id = t.addressFk - JOIN client c ON c.id = t.clientFk - WHERE t.refFk IS NULL - AND t.shipped BETWEEN ? AND util.dayEnd(?) - AND t.companyFk = ? - AND c.hasToInvoice - AND c.isTaxDataChecked - AND c.isActive - AND NOT t.isDeleted - GROUP BY c.id, IF(c.hasToInvoiceByAddress, a.id, TRUE) - HAVING totalAmount > 0;`; - - return models.InvoiceOut.rawSql(query, [ - minShipped, - args.maxShipped, - args.companyFk - ], options); - } }; diff --git a/modules/invoiceOut/back/methods/invoiceOut/getInvoiceDate.js b/modules/invoiceOut/back/methods/invoiceOut/getInvoiceDate.js new file mode 100644 index 000000000..e2ab94f01 --- /dev/null +++ b/modules/invoiceOut/back/methods/invoiceOut/getInvoiceDate.js @@ -0,0 +1,39 @@ +module.exports = Self => { + Self.remoteMethod('getInvoiceDate', { + description: 'Returns default Invoice Date', + accessType: 'READ', + accepts: [ + { + arg: 'year', + type: 'number', + required: true + }, { + arg: 'companyFk', + type: 'number', + required: true + } + ], + returns: { + type: ['object'], + root: true + }, + http: { + path: `/getInvoiceDate`, + verb: 'GET' + } + }); + + Self.getInvoiceDate = async(year, companyFk) => { + const models = Self.app.models; + const [invoiceDate] = await models.InvoiceOut.rawSql(` + SELECT MAX(io.issued) issued + FROM invoiceOut io + JOIN invoiceOutSerial ios ON ios.code = io.serial + WHERE ios.type = 'global' + AND io.issued BETWEEN MAKEDATE(?, 1) AND + util.lastDayOfYear(MAKEDATE(?, 1)) + AND io.companyFk = ?`, + [year, year, companyFk]); + return invoiceDate; + }; +}; diff --git a/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js b/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js index ce700796f..c8f8a6778 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js +++ b/modules/invoiceOut/back/methods/invoiceOut/invoiceClient.js @@ -4,48 +4,39 @@ module.exports = Self => { Self.remoteMethodCtx('invoiceClient', { description: 'Make a invoice of a client', accessType: 'WRITE', - accepts: [{ - arg: 'clientId', - type: 'number', - description: 'The client id to invoice', - required: true - }, - { - arg: 'addressId', - type: 'number', - description: 'The address id to invoice', - required: true - }, - { - arg: 'invoiceDate', - type: 'date', - description: 'The invoice date', - required: true - }, - { - arg: 'maxShipped', - type: 'date', - description: 'The maximum shipped date', - required: true - }, - { - arg: 'companyFk', - type: 'number', - description: 'The company id to invoice', - required: true - }, - { - arg: 'minShipped', - type: 'date', - description: 'The minium shupped date', - required: true - }, - { - arg: 'printerFk', - type: 'number', - description: 'The printer to print', - required: true - }], + accepts: [ + { + arg: 'clientId', + type: 'number', + description: 'The client id to invoice', + required: true + }, { + arg: 'addressId', + type: 'number', + description: 'The address id to invoice', + required: true + }, { + arg: 'invoiceDate', + type: 'date', + description: 'The invoice date', + required: true + }, { + arg: 'maxShipped', + type: 'date', + description: 'The maximum shipped date', + required: true + }, { + arg: 'companyFk', + type: 'number', + description: 'The company id to invoice', + required: true + }, { + arg: 'printerFk', + type: 'number', + description: 'The printer to print', + required: true + } + ], returns: { type: 'object', root: true @@ -70,6 +61,9 @@ module.exports = Self => { myOptions.transaction = tx; } + const minShipped = Date.vnNew(); + minShipped.setFullYear(args.maxShipped.getFullYear() - 1); + let invoiceId; let invoiceOut; try { @@ -79,7 +73,7 @@ module.exports = Self => { if (client.hasToInvoiceByAddress) { await Self.rawSql('CALL ticketToInvoiceByAddress(?, ?, ?, ?)', [ - args.minShipped, + minShipped, args.maxShipped, args.addressId, args.companyFk @@ -133,26 +127,26 @@ module.exports = Self => { throw e; } - if (invoiceId && !invoiceOut.client().isToBeMailed) { - const query = `CALL vn.report_print( - 'invoice', - ?, - account.myUser_getId(), - JSON_OBJECT('refFk', ?), - 'normal' - );`; - await models.InvoiceOut.rawSql(query, [args.printerFk, invoiceOut.ref]); + if (invoiceId) { + if (!invoiceOut.client().isToBeMailed) { + const query = ` + CALL vn.report_print( + 'invoice', + ?, + account.myUser_getId(), + JSON_OBJECT('refFk', ?), + 'normal' + );`; + await models.InvoiceOut.rawSql(query, [args.printerFk, invoiceOut.ref]); + } else { + ctx.args = { + reference: invoiceOut.ref, + recipientId: invoiceOut.clientFk, + recipient: invoiceOut.client().email + }; + await models.InvoiceOut.invoiceEmail(ctx, invoiceOut.ref); + } } - - if (invoiceId && invoiceOut.client().isToBeMailed) { - ctx.args = { - reference: invoiceOut.ref, - recipientId: invoiceOut.clientFk, - recipient: invoiceOut.client().email - }; - await models.InvoiceOut.invoiceEmail(ctx, invoiceOut.ref); - } - return invoiceId; }; @@ -160,13 +154,12 @@ module.exports = Self => { const models = Self.app.models; const query = 'SELECT hasAnyNegativeBase() AS base'; const [result] = await models.InvoiceOut.rawSql(query, null, options); - return result && result.base; } async function getIsSpanishCompany(companyId, options) { const models = Self.app.models; - const query = `SELECT COUNT(*) AS total + const query = `SELECT COUNT(*) isSpanishCompany FROM supplier s JOIN country c ON c.id = s.countryFk AND c.code = 'ES' @@ -175,6 +168,6 @@ module.exports = Self => { companyId ], options); - return supplierCompany && supplierCompany.total; + return supplierCompany && supplierCompany.isSpanishCompany; } }; diff --git a/modules/invoiceOut/back/models/invoice-out.js b/modules/invoiceOut/back/models/invoice-out.js index eb8df246c..6205abe7b 100644 --- a/modules/invoiceOut/back/models/invoice-out.js +++ b/modules/invoiceOut/back/models/invoice-out.js @@ -16,4 +16,5 @@ module.exports = Self => { require('../methods/invoiceOut/invoiceCsv')(Self); require('../methods/invoiceOut/invoiceCsvEmail')(Self); require('../methods/invoiceOut/invoiceOutPdf')(Self); + require('../methods/invoiceOut/getInvoiceDate')(Self); }; diff --git a/modules/invoiceOut/front/global-invoicing/index.html b/modules/invoiceOut/front/global-invoicing/index.html index 53df44670..ebe46b84a 100644 --- a/modules/invoiceOut/front/global-invoicing/index.html +++ b/modules/invoiceOut/front/global-invoicing/index.html @@ -1,59 +1,66 @@ - -
{{'Calculating packages to invoice...'}}
- -
Invoicing
-
Ended process
-
- {{'Current client id' | translate}}: {{$ctrl.currentClientId}} -
-
- {{($ctrl.percentage / 100) | percentage: 0}} ({{$ctrl.currentClient}} {{'of' | translate}} {{$ctrl.clients.length}}) -
-
+ + + +
+
+ + Build packaging tickets + + + {{'Invoicing client' | translate}} {{$ctrl.currentAddress.clientId}} + + + Stopping process + + + Ended process + +
+
+ {{$ctrl.percentage | percentage: 0}} ({{$ctrl.addressNumber}} {{'of' | translate}} {{$ctrl.nAddresses}}) +
+
- - + + - Client id - Nickname - Address id - Street - Error + Id + Client + Address id + Street + Error - + - {{::client.id}} + {{::error.address.clientId}} - {{::client.address.nickname}} + {{::error.address.clientName}} - {{::client.address.id}} + {{::error.address.id}} - {{::client.address.street}} + {{::error.address.nickname}} - - - - {{::client.error}} + + {{::error.message}} - -
+ + + + + + + + {{::id}} - {{::name}} + + ng-model="$ctrl.invoiceDate"> + ng-model="$ctrl.maxShipped"> + ng-model="$ctrl.companyFk"> + ng-model="$ctrl.printerFk"> - + + + +
diff --git a/modules/invoiceOut/front/global-invoicing/index.js b/modules/invoiceOut/front/global-invoicing/index.js index 4e9070946..e910368fa 100644 --- a/modules/invoiceOut/front/global-invoicing/index.js +++ b/modules/invoiceOut/front/global-invoicing/index.js @@ -4,128 +4,131 @@ import UserError from 'core/lib/user-error'; import './style.scss'; class Controller extends Section { - constructor($element, $, $transclude) { - super($element, $, $transclude); - this.invoice = { - maxShipped: Date.vnNew(), - companyFk: this.vnConfig.companyFk - }; - } - $onInit() { - this.getMinClientId(); - this.getMaxClientId(); - } + const date = Date.vnNew(); + Object.assign(this, { + maxShipped: new Date(date.getFullYear(), date.getMonth(), 0), + clientsToInvoice: 'all', + }); - getMinClientId() { - this.getClientId('min') - .then(res => this.invoice.fromClientId = res.data.id); - } - - getMaxClientId() { - this.getClientId('max') - .then(res => this.invoice.toClientId = res.data.id); - } - - getClientId(func) { - const order = func == 'min' ? 'ASC' : 'DESC'; - const params = { - filter: { - order: 'id ' + order, - limit: 1 - } - }; - return this.$http.get('Clients/findOne', {params}); - } - - getPercentage() { - this.percentage = ((this.currentClient - 1) * 100) / this.clients.length; - } - - restartValues() { - this.$.invoiceButton.disabled = false; - this.packageInvoicing = false; - } - - invoiceOut(invoice, clientsAndAddresses) { - const [clientAndAddress] = clientsAndAddresses; - if (!clientAndAddress) { - this.percentage = 100; - return; - } - - this.currentClientId = clientAndAddress.clientId; - this.currentClient = ++this.currentClient; - this.getPercentage(); - - const params = { - clientId: clientAndAddress.clientId, - addressId: clientAndAddress.addressId, - invoiceDate: invoice.invoiceDate, - maxShipped: invoice.maxShipped, - companyFk: invoice.companyFk, - minShipped: invoice.minShipped, - printerFk: this.invoice.printerFk, - - }; - this.$http.get(`Addresses/${clientAndAddress.addressId}`) + this.$http.get('UserConfigs/getUserConfig') .then(res => { - this.address = res.data; - return this.$http.post(`InvoiceOuts/invoiceClient`, params) - .catch(res => { - this.$.data.unshift({ - id: clientAndAddress.clientId, - address: this.address, - status: 'error', - error: res.data.error.message - }); - }).finally(() => { - clientsAndAddresses.shift(); - return this.invoiceOut(invoice, clientsAndAddresses); - }); + this.companyFk = res.data.companyFk; + const params = { + year: this.maxShipped.getFullYear(), + companyFk: this.companyFk + }; + return this.$http.get('InvoiceOuts/getInvoiceDate', {params}); + }) + .then(res => { + this.minInvoicingDate = new Date(res.data.issued); + this.invoiceDate = this.minInvoicingDate; }); } + stopInvoicing() { + this.status = 'stopping'; + } + makeInvoice() { + this.invoicing = true; + this.status = 'packageInvoicing'; + this.errors = []; + this.addresses = null; + try { - if (!this.invoice.invoiceDate || !this.invoice.maxShipped) - throw new Error('Invoice date and the max date should be filled'); + if (this.clientsToInvoice == 'one' && !this.clientId) + throw new UserError('Choose a valid client'); + if (!this.invoiceDate || !this.maxShipped) + throw new UserError('Invoice date and the max date should be filled'); + if (this.invoiceDate < this.maxShipped) + throw new UserError('Invoice date can\'t be less than max date'); + if (this.invoiceDate.getTime() < this.minInvoicingDate.getTime()) + throw new UserError('Exists an invoice with a previous date'); + if (!this.companyFk) + throw new UserError('Choose a valid company'); + if (!this.printerFk) + throw new UserError('Choose a valid printer'); - if (!this.invoice.companyFk) - throw new Error('Choose a valid company'); + if (this.clientsToInvoice == 'all') + this.clientId = undefined; - if (!this.invoice.printerFk) - throw new Error('Choose a valid printer'); - - this.$.invoiceButton.disabled = true; - this.$.data = []; - this.packageInvoicing = true; - - this.$http.post(`InvoiceOuts/clientsToInvoice`, this.invoice) + const params = { + invoiceDate: this.invoiceDate, + maxShipped: this.maxShipped, + clientId: this.clientId, + companyFk: this.companyFk + }; + this.$http.post(`InvoiceOuts/clientsToInvoice`, params) .then(res => { - this.packageInvoicing = false; - const invoice = res.data.invoice; - this.currentClient = 0; + console.log(res.data); + this.addresses = res.data; + console.log(this.address); + if (!this.addresses.length) + throw new UserError(`There aren't tickets to invoice`); - const clientsAndAddresses = res.data.clientsAndAddresses; - if (!clientsAndAddresses.length) throw new UserError(`There aren't clients to invoice`); - - this.clients = []; - for (const clientAndAddress of clientsAndAddresses) - this.clients.push(clientAndAddress.clientId); - - return this.invoiceOut(invoice, clientsAndAddresses); + this.addressIndex = 0; + return this.invoiceOut(); }) - .finally(() => this.restartValues()); - } catch (e) { - this.vnApp.showError(this.$t(e.message)); - this.restartValues(); - return false; + .catch(err => this.handleError(err)); + } catch (err) { + this.handleError(err); } } -} -Controller.$inject = ['$element', '$scope', '$transclude']; + handleError(err) { + this.invoicing = false; + this.status = null; + throw err; + } + + invoiceOut() { + if (this.addressIndex == this.addresses.length || this.status == 'stopping') { + this.invoicing = false; + this.status = 'done'; + return; + } + + this.status = 'invoicing'; + const address = this.addresses[this.addressIndex]; + this.currentAddress = address; + + const params = { + clientId: address.clientId, + addressId: address.id, + invoiceDate: this.invoiceDate, + maxShipped: this.maxShipped, + companyFk: this.companyFk, + printerFk: this.printerFk, + }; + + this.$http.post(`InvoiceOuts/invoiceClient`, params) + .catch(res => { + this.errors.unshift({ + address, + message: res.data.error.message + }); + }) + .finally(() => { + this.addressIndex++; + this.invoiceOut(); + }); + } + + get nAddresses() { + if (!this.addresses) return 0; + return this.addresses.length; + } + + get addressNumber() { + return Math.min(this.addressIndex + 1, this.nAddresses); + } + + get percentage() { + const len = this.nAddresses; + return Math.min(this.addressIndex, len) / len; + } +} ngModule.vnComponent('vnInvoiceOutGlobalInvoicing', { template: require('./index.html'), diff --git a/modules/invoiceOut/front/global-invoicing/index.spec.js b/modules/invoiceOut/front/global-invoicing/index.spec.js index 96cd38d51..fcffeb6ee 100644 --- a/modules/invoiceOut/front/global-invoicing/index.spec.js +++ b/modules/invoiceOut/front/global-invoicing/index.spec.js @@ -1,5 +1,5 @@ import './index'; - +const UserError = require('vn-loopback/util/user-error'); describe('InvoiceOut', () => { describe('Component vnInvoiceOutGlobalInvoicing', () => { let controller; @@ -22,99 +22,60 @@ describe('InvoiceOut', () => { controller.$.invoiceButton = {disabled: false}; })); - describe('getMinClientId()', () => { - it('should set the invoice fromClientId property', () => { - const filter = { - order: 'id ASC', - limit: 1 - }; - - const serializedParams = $httpParamSerializer({filter}); - $httpBackend.expectGET(`Clients/findOne?${serializedParams}`).respond(200, {id: 1101}); - - controller.getMinClientId(); - $httpBackend.flush(); - - expect(controller.invoice.fromClientId).toEqual(1101); - }); - }); - - describe('getMaxClientId()', () => { - it('should set the invoice toClientId property', () => { - const filter = { - order: 'id DESC', - limit: 1 - }; - - const serializedParams = $httpParamSerializer({filter}); - $httpBackend.expectGET(`Clients/findOne?${serializedParams}`).respond(200, {id: 1112}); - - controller.getMaxClientId(); - $httpBackend.flush(); - - expect(controller.invoice.toClientId).toEqual(1112); - }); - }); - describe('makeInvoice()', () => { it('should throw an error when invoiceDate or maxShipped properties are not filled in', () => { jest.spyOn(controller.vnApp, 'showError'); + controller.clientsToInvoice = 'all'; - controller.invoice = { - fromClientId: 1101, - toClientId: 1101 - }; - - controller.makeInvoice(); + let error; + try { + controller.makeInvoice(); + } catch (e) { + error = e.message; + } const expectedError = 'Invoice date and the max date should be filled'; - expect(controller.vnApp.showError).toHaveBeenCalledWith(expectedError); + expect(error).toBe(expectedError); }); - it('should throw an error when fromClientId or toClientId properties are not filled in', () => { + it('should throw an error when select one client and clientId is not filled in', () => { jest.spyOn(controller.vnApp, 'showError'); + controller.clientsToInvoice = 'one'; - controller.invoice = { - invoiceDate: Date.vnNew(), - maxShipped: Date.vnNew() - }; + let error; + try { + controller.makeInvoice(); + } catch (e) { + error = e.message; + } - controller.makeInvoice(); + const expectedError = 'Choose a valid client'; - expect(controller.vnApp.showError).toHaveBeenCalledWith(`Choose a valid clients range`); + expect(error).toBe(expectedError); }); it('should make an http POST query and then call to the showSuccess() method', () => { jest.spyOn(controller.vnApp, 'showSuccess'); - - const minShipped = Date.vnNew(); - minShipped.setFullYear(minShipped.getFullYear() - 1); - minShipped.setMonth(1); - minShipped.setDate(1); - minShipped.setHours(0, 0, 0, 0); - controller.invoice = { - invoiceDate: Date.vnNew(), - maxShipped: Date.vnNew(), - fromClientId: 1101, - toClientId: 1101, - companyFk: 442, - minShipped: minShipped - }; - const response = { - clientsAndAddresses: [{clientId: 1101, addressId: 121}], - invoice: controller.invoice - }; - - const address = {id: 121}; - + const date = Date.vnNew(); + date.setDate(date.getDate() + 1); + controller.invoiceDate = date; + controller.maxShipped = date; + controller.minInvoicingDate = Date.vnNew(); + controller.clientsToInvoice = 'one'; + controller.clientId = 1101; + controller.companyFk = 442; + controller.printerFk = 1; + const response = [{ + clientId: 1101, + id: 121 + }]; $httpBackend.expect('POST', `InvoiceOuts/clientsToInvoice`).respond(response); - $httpBackend.expect('GET', `Addresses/${response.clientsAndAddresses[0].addressId}`).respond(address); - $httpBackend.expect('POST', `InvoiceOuts/invoiceClient`).respond({id: 1}); + $httpBackend.expect('POST', `InvoiceOuts/invoiceClient`).respond(1); controller.makeInvoice(); $httpBackend.flush(); - expect(controller.vnApp.showSuccess).toHaveBeenCalled(); + expect(controller.status).toEqual('done'); }); }); }); diff --git a/modules/invoiceOut/front/global-invoicing/locale/es.yml b/modules/invoiceOut/front/global-invoicing/locale/es.yml index 0c4cf14fc..242b5a93f 100644 --- a/modules/invoiceOut/front/global-invoicing/locale/es.yml +++ b/modules/invoiceOut/front/global-invoicing/locale/es.yml @@ -1,21 +1,20 @@ -There aren't clients to invoice: No existen clientes para facturar +There aren't tickets to invoice: No existen tickets para facturar Max date: Fecha límite Invoice date: Fecha de factura +Invoice date can't be less than max date: La fecha de factura no puede ser inferior a la fecha límite Invoice date and the max date should be filled: La fecha de factura y la fecha límite deben rellenarse -Choose a valid clients range: Selecciona un rango válido de clientes Choose a valid company: Selecciona un empresa válida Choose a valid printer: Selecciona una impresora válida -Clients range: Rango de clientes All clients: Todos los clientes -Calculating packages to invoice...: Calculando paquetes a facturar... -Clean: Limpiar -From client: Desde cliente -To client: Hasta cliente +Build packaging tickets: Generando tickets de embalajes Address id: Id dirección Printer: Impresora of: de Client: Cliente Current client id: Id cliente actual -Invoicing: Facturando +Invoicing client: Facturando cliente Ended process: Proceso finalizado Invoice out: Facturar +One client: Un solo cliente +Choose a valid client: Selecciona un cliente válido +Stop: Parar \ No newline at end of file diff --git a/modules/ticket/front/sale-tracking/style.scss b/modules/ticket/front/sale-tracking/style.scss index 6d8b3db69..4b10ec3c2 100644 --- a/modules/ticket/front/sale-tracking/style.scss +++ b/modules/ticket/front/sale-tracking/style.scss @@ -1,7 +1,9 @@ @import "variables"; -.chip { - display: inline-block; - min-width: 15px; - min-height: 25px; +vn-sale-tracking { + .chip { + display: inline-block; + min-width: 15px; + min-height: 25px; + } } From 7f60335a91b2d4a90d86d5136daf12d0a43722a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Andr=C3=A9s?= Date: Thu, 23 Feb 2023 09:45:15 +0100 Subject: [PATCH 39/48] refs #5000 Invoicing: front tests refactor & fixes --- .../front/global-invoicing/index.js | 2 - .../front/global-invoicing/index.spec.js | 42 ++++++++----------- 2 files changed, 17 insertions(+), 27 deletions(-) diff --git a/modules/invoiceOut/front/global-invoicing/index.js b/modules/invoiceOut/front/global-invoicing/index.js index e910368fa..8e00231ea 100644 --- a/modules/invoiceOut/front/global-invoicing/index.js +++ b/modules/invoiceOut/front/global-invoicing/index.js @@ -61,9 +61,7 @@ class Controller extends Section { }; this.$http.post(`InvoiceOuts/clientsToInvoice`, params) .then(res => { - console.log(res.data); this.addresses = res.data; - console.log(this.address); if (!this.addresses.length) throw new UserError(`There aren't tickets to invoice`); diff --git a/modules/invoiceOut/front/global-invoicing/index.spec.js b/modules/invoiceOut/front/global-invoicing/index.spec.js index fcffeb6ee..056839b20 100644 --- a/modules/invoiceOut/front/global-invoicing/index.spec.js +++ b/modules/invoiceOut/front/global-invoicing/index.spec.js @@ -1,25 +1,18 @@ import './index'; -const UserError = require('vn-loopback/util/user-error'); + describe('InvoiceOut', () => { describe('Component vnInvoiceOutGlobalInvoicing', () => { let controller; let $httpBackend; - let $httpParamSerializer; beforeEach(ngModule('invoiceOut')); - beforeEach(inject(($componentController, $rootScope, _$httpBackend_, _$httpParamSerializer_) => { + beforeEach(inject(($componentController, $rootScope, _$httpBackend_) => { $httpBackend = _$httpBackend_; - $httpParamSerializer = _$httpParamSerializer_; - let $scope = $rootScope.$new(); + const $scope = $rootScope.$new(); const $element = angular.element(''); - const $transclude = { - $$boundTransclude: { - $$slots: [] - } - }; - controller = $componentController('vnInvoiceOutGlobalInvoicing', {$element, $scope, $transclude}); - controller.$.invoiceButton = {disabled: false}; + + controller = $componentController('vnInvoiceOutGlobalInvoicing', {$element, $scope}); })); describe('makeInvoice()', () => { @@ -56,22 +49,21 @@ describe('InvoiceOut', () => { }); it('should make an http POST query and then call to the showSuccess() method', () => { - jest.spyOn(controller.vnApp, 'showSuccess'); const date = Date.vnNew(); - date.setDate(date.getDate() + 1); - controller.invoiceDate = date; - controller.maxShipped = date; - controller.minInvoicingDate = Date.vnNew(); - controller.clientsToInvoice = 'one'; - controller.clientId = 1101; - controller.companyFk = 442; - controller.printerFk = 1; - const response = [{ + Object.assign(controller, { + invoiceDate: date, + maxShipped: date, + minInvoicingDate: date, + clientsToInvoice: 'one', + clientId: 1101, + companyFk: 442, + printerFk: 1 + }); + $httpBackend.expectPOST(`InvoiceOuts/clientsToInvoice`).respond([{ clientId: 1101, id: 121 - }]; - $httpBackend.expect('POST', `InvoiceOuts/clientsToInvoice`).respond(response); - $httpBackend.expect('POST', `InvoiceOuts/invoiceClient`).respond(1); + }]); + $httpBackend.expectPOST(`InvoiceOuts/invoiceClient`).respond(); controller.makeInvoice(); $httpBackend.flush(); From ffdfd1a7e58bea0697d6b2424820f7411e07c07b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Andr=C3=A9s?= Date: Thu, 23 Feb 2023 14:48:21 +0100 Subject: [PATCH 40/48] refs #5000 Invoicing change structure --- db/dump/structure.sql | 96 +++++++++++++++++++ .../back/methods/invoiceOut/getInvoiceDate.js | 7 +- package-lock.json | 4 +- 3 files changed, 102 insertions(+), 5 deletions(-) diff --git a/db/dump/structure.sql b/db/dump/structure.sql index fd16ad220..45ec60438 100644 --- a/db/dump/structure.sql +++ b/db/dump/structure.sql @@ -19738,6 +19738,102 @@ DELIMITER ; /*!50003 SET character_set_client = @saved_cs_client */ ; /*!50003 SET character_set_results = @saved_cs_results */ ; /*!50003 SET collation_connection = @saved_col_connection */ ; +/*!50003 DROP FUNCTION IF EXISTS `CURDATE` */; +/*!50003 SET @saved_cs_client = @@character_set_client */ ; +/*!50003 SET @saved_cs_results = @@character_set_results */ ; +/*!50003 SET @saved_col_connection = @@collation_connection */ ; +/*!50003 SET character_set_client = utf8mb4 */ ; +/*!50003 SET character_set_results = utf8mb4 */ ; +/*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; +DELIMITER ;; +CREATE DEFINER=`root`@`localhost` FUNCTION `util`.`CURDATE`() RETURNS date + DETERMINISTIC +BEGIN + /** + * @return The mock date + **/ + + RETURN DATE(mockTime()); +END ;; +DELIMITER ; +/*!50003 SET sql_mode = @saved_sql_mode */ ; +/*!50003 SET character_set_client = @saved_cs_client */ ; +/*!50003 SET character_set_results = @saved_cs_results */ ; +/*!50003 SET collation_connection = @saved_col_connection */ ; +/*!50003 DROP FUNCTION IF EXISTS `mockTime` */; +/*!50003 SET @saved_cs_client = @@character_set_client */ ; +/*!50003 SET @saved_cs_results = @@character_set_results */ ; +/*!50003 SET @saved_col_connection = @@collation_connection */ ; +/*!50003 SET character_set_client = utf8mb4 */ ; +/*!50003 SET character_set_results = utf8mb4 */ ; +/*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; +DELIMITER ;; +CREATE DEFINER=`root`@`localhost` FUNCTION `util`.`mockTime`() RETURNS datetime + DETERMINISTIC +BEGIN +/** + * Returns the mockTime with predefined timezone or current dateTime + * depending of config.mockEnabled + * + * @return formatted datetime + */ + DECLARE vMockEnabled BOOL; + + SELECT mockEnabled INTO vMockEnabled FROM config LIMIT 1; + + IF vMockEnabled THEN + RETURN mockTimeBase(FALSE); + ELSE + RETURN NOW(); + END IF; +END ;; +DELIMITER ; +/*!50003 SET sql_mode = @saved_sql_mode */ ; +/*!50003 SET character_set_client = @saved_cs_client */ ; +/*!50003 SET character_set_results = @saved_cs_results */ ; +/*!50003 SET collation_connection = @saved_col_connection */ ; +/*!50003 DROP FUNCTION IF EXISTS `mockTimeBase` */; +/*!50003 SET @saved_cs_client = @@character_set_client */ ; +/*!50003 SET @saved_cs_results = @@character_set_results */ ; +/*!50003 SET @saved_col_connection = @@collation_connection */ ; +/*!50003 SET character_set_client = utf8mb4 */ ; +/*!50003 SET character_set_results = utf8mb4 */ ; +/*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; +DELIMITER ;; +CREATE DEFINER=`root`@`localhost` FUNCTION `util`.`mockTimeBase`(vIsUtc BOOL) RETURNS datetime + DETERMINISTIC +BEGIN +/** + * Returns the date formatted to utc if vIsUtc or config.mocTz if not + * + * @param vIsUtc If date must be returned as UTC format + * @return The formatted mock time + */ +DECLARE vMockUtcTime DATETIME; + DECLARE vMockTz VARCHAR(255); + + SELECT mockUtcTime, mockTz + INTO vMockUtcTime, vMockTz + FROM config + LIMIT 1; + + IF vIsUtc OR vMockTz IS NULL THEN + RETURN vMockUtcTime; + ELSE + RETURN CONVERT_TZ(vMockUtcTime, '+00:00', vMockTz); + END IF; +END ;; +DELIMITER ; +/*!50003 SET sql_mode = @saved_sql_mode */ ; +/*!50003 SET character_set_client = @saved_cs_client */ ; +/*!50003 SET character_set_results = @saved_cs_results */ ; +/*!50003 SET collation_connection = @saved_col_connection */ ; /*!50003 DROP FUNCTION IF EXISTS `firstDayOfYear` */; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; diff --git a/modules/invoiceOut/back/methods/invoiceOut/getInvoiceDate.js b/modules/invoiceOut/back/methods/invoiceOut/getInvoiceDate.js index e2ab94f01..ec7146513 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/getInvoiceDate.js +++ b/modules/invoiceOut/back/methods/invoiceOut/getInvoiceDate.js @@ -25,15 +25,16 @@ module.exports = Self => { Self.getInvoiceDate = async(year, companyFk) => { const models = Self.app.models; - const [invoiceDate] = await models.InvoiceOut.rawSql(` - SELECT MAX(io.issued) issued + const [invoiceDate] = await models.InvoiceOut.rawSql( + `SELECT MAX(io.issued) issued FROM invoiceOut io JOIN invoiceOutSerial ios ON ios.code = io.serial WHERE ios.type = 'global' AND io.issued BETWEEN MAKEDATE(?, 1) AND util.lastDayOfYear(MAKEDATE(?, 1)) AND io.companyFk = ?`, - [year, year, companyFk]); + [year, year, companyFk] + ); return invoiceDate; }; }; diff --git a/package-lock.json b/package-lock.json index 8a39bd902..108ad60e5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "salix-back", - "version": "23.04.01", + "version": "23.08.01", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "salix-back", - "version": "23.04.01", + "version": "23.08.01", "license": "GPL-3.0", "dependencies": { "axios": "^1.2.2", From 6f5e25493d81f0b531d8801c3b4beeb2957e04a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Andr=C3=A9s?= Date: Wed, 1 Mar 2023 10:36:38 +0100 Subject: [PATCH 41/48] invoicing test --- db/changes/230601/02-invoiceOut_new.sql | 2 +- db/dump/fixtures.sql | 14 ++++- e2e/helpers/selectors.js | 20 ++++--- .../09-invoice-out/03_manualInvoice.spec.js | 2 - .../09-invoice-out/04_globalInvoice.spec.js | 60 ++++++++++--------- loopback/locale/en.json | 5 +- loopback/locale/es.json | 3 +- .../back/methods/invoiceOut/getInvoiceDate.js | 11 +--- .../front/global-invoicing/index.js | 3 +- 9 files changed, 65 insertions(+), 55 deletions(-) diff --git a/db/changes/230601/02-invoiceOut_new.sql b/db/changes/230601/02-invoiceOut_new.sql index dd7136ff7..0fd91ef58 100644 --- a/db/changes/230601/02-invoiceOut_new.sql +++ b/db/changes/230601/02-invoiceOut_new.sql @@ -69,7 +69,7 @@ BEGIN JOIN supplier su ON su.id = t.companyFk JOIN client c ON c.id = t.clientFk LEFT JOIN itemTaxCountry itc ON itc.itemFk = i.id AND itc.countryFk = su.countryFk - WHERE YEAR(t.shipped) < 2001 + WHERE (YEAR(t.shipped) < 2001 AND t.isDeleted) OR c.isTaxDataChecked = FALSE OR t.isDeleted OR c.hasToInvoice = FALSE diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index ae98e5cde..42f5e2513 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -1,8 +1,16 @@ CREATE SCHEMA IF NOT EXISTS `vn2008`; CREATE SCHEMA IF NOT EXISTS `tmp`; -UPDATE `util`.`config` - SET `environment`= 'development'; +ALTER TABLE util.config + ADD COLUMN `mockUtcTime` datetime DEFAULT NULL, + ADD COLUMN `mockEnabled` tinyint(3) unsigned NOT NULL DEFAULT 0, + ADD COLUMN `mockTz` varchar(255) DEFAULT NULL; + +UPDATE util.config + SET mockUtcTime='2001-01-01 11:00:00', + environment= 'development', + mockEnabled = TRUE, + mockTz='+01:00'; -- FOR MOCK vn.time @@ -164,7 +172,7 @@ INSERT INTO `vn`.`warehouse`(`id`, `name`, `code`, `isComparative`, `isInventory (3, 'Warehouse Three', NULL, 1, 1, 1, 1, 0, 0, 2, 1, 1), (4, 'Warehouse Four', NULL, 1, 1, 1, 1, 0, 0, 2, 1, 1), (5, 'Warehouse Five', NULL, 1, 1, 1, 1, 0, 0, 2, 1, 1), - (13, 'Inventory', NULL, 1, 1, 1, 0, 0, 0, 2, 1, 0), + (13, 'Inventory', 'inv', 1, 1, 1, 0, 0, 0, 2, 1, 0), (60, 'Algemesi', NULL, 1, 1, 1, 0, 0, 0, 2, 1, 0); diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index efaa13ee3..8a590dad5 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -1043,20 +1043,22 @@ export default { invoiceOutIndex: { topbarSearch: 'vn-searchbar', searchResult: 'vn-invoice-out-index vn-card > vn-table > div > vn-tbody > a.vn-tr', - createInvoice: 'vn-invoice-out-index > div > vn-vertical > vn-button > button vn-icon[icon="add"]', - createManualInvoice: 'vn-item[name="manualInvoice"]', - createGlobalInvoice: 'vn-item[name="globalInvoice"]', + createInvoice: 'vn-invoice-out-index > div > vn-button > button vn-icon[icon="add"]', manualInvoiceForm: '.vn-invoice-out-manual', manualInvoiceTicket: 'vn-autocomplete[ng-model="$ctrl.invoice.ticketFk"]', manualInvoiceClient: 'vn-autocomplete[ng-model="$ctrl.invoice.clientFk"]', manualInvoiceSerial: 'vn-autocomplete[ng-model="$ctrl.invoice.serial"]', manualInvoiceTaxArea: 'vn-autocomplete[ng-model="$ctrl.invoice.taxArea"]', - saveInvoice: 'button[response="accept"]', - globalInvoiceForm: '.vn-invoice-out-global-invoicing', - globalInvoiceClientsRange: 'vn-radio[val="clientsRange"]', - globalInvoiceDate: '[ng-model="$ctrl.invoice.invoiceDate"]', - globalInvoiceFromClient: '[ng-model="$ctrl.invoice.fromClientId"]', - globalInvoiceToClient: '[ng-model="$ctrl.invoice.toClientId"]', + saveInvoice: 'button[response="accept"]' + }, + invoiceOutGlobalInvoicing: { + oneClient: 'vn-invoice-out-global-invoicing vn-side-menu form > vn-vertical > vn-vertical > vn-radio[val="one"]', + allClients: 'vn-invoice-out-global-invoicing vn-side-menu form > vn-vertical > vn-vertical > vn-radio[val="all"]', + clientId: 'vn-invoice-out-global-invoicing vn-side-menu form > vn-vertical > vn-autocomplete[ng-model="$ctrl.clientId"]', + printer: 'vn-invoice-out-global-invoicing vn-side-menu form > vn-vertical > vn-autocomplete[ng-model="$ctrl.printerFk"]', + makeInvoice: 'vn-invoice-out-global-invoicing vn-side-menu form > vn-vertical > vn-submit', + invoiceDate: 'vn-invoice-out-global-invoicing vn-side-menu form > vn-vertical > vn-date-picker[ng-model="$ctrl.invoiceDate"]', + maxShipped: 'vn-invoice-out-global-invoicing vn-side-menu form > vn-vertical > vn-date-picker[ng-model="$ctrl.maxShipped"]' }, invoiceOutDescriptor: { moreMenu: 'vn-invoice-out-descriptor vn-icon-button[icon=more_vert]', diff --git a/e2e/paths/09-invoice-out/03_manualInvoice.spec.js b/e2e/paths/09-invoice-out/03_manualInvoice.spec.js index fa7cbed29..abb9ca7e7 100644 --- a/e2e/paths/09-invoice-out/03_manualInvoice.spec.js +++ b/e2e/paths/09-invoice-out/03_manualInvoice.spec.js @@ -17,7 +17,6 @@ describe('InvoiceOut manual invoice path', () => { it('should open the manual invoice form', async() => { await page.waitToClick(selectors.invoiceOutIndex.createInvoice); - await page.waitToClick(selectors.invoiceOutIndex.createManualInvoice); await page.waitForSelector(selectors.invoiceOutIndex.manualInvoiceForm); }); @@ -45,7 +44,6 @@ describe('InvoiceOut manual invoice path', () => { it('should now open the manual invoice form', async() => { await page.waitToClick(selectors.invoiceOutIndex.createInvoice); - await page.waitToClick(selectors.invoiceOutIndex.createManualInvoice); await page.waitForSelector(selectors.invoiceOutIndex.manualInvoiceForm); }); diff --git a/e2e/paths/09-invoice-out/04_globalInvoice.spec.js b/e2e/paths/09-invoice-out/04_globalInvoice.spec.js index 74efafd2d..052893aff 100644 --- a/e2e/paths/09-invoice-out/04_globalInvoice.spec.js +++ b/e2e/paths/09-invoice-out/04_globalInvoice.spec.js @@ -17,47 +17,53 @@ describe('InvoiceOut global invoice path', () => { await browser.close(); }); - let invoicesBefore; + let invoicesBeforeOneClient; + let invoicesBeforeAllClients; + let now = Date.vnNew(); it('should count the amount of invoices listed before globla invoces are made', async() => { - invoicesBefore = await page.countElement(selectors.invoiceOutIndex.searchResult); + invoicesBeforeOneClient = await page.countElement(selectors.invoiceOutIndex.searchResult); - expect(invoicesBefore).toBeGreaterThanOrEqual(4); + expect(invoicesBeforeOneClient).toBeGreaterThanOrEqual(4); }); it('should open the global invoice form', async() => { - await page.waitToClick(selectors.invoiceOutIndex.createInvoice); - await page.waitToClick(selectors.invoiceOutIndex.createGlobalInvoice); - await page.waitForSelector(selectors.invoiceOutIndex.globalInvoiceForm); + await page.accessToSection('invoiceOut.global-invoicing'); }); it('should create a global invoice for charles xavier today', async() => { - await page.pickDate(selectors.invoiceOutIndex.globalInvoiceDate); - await page.waitToClick(selectors.invoiceOutIndex.globalInvoiceClientsRange); - await page.autocompleteSearch(selectors.invoiceOutIndex.globalInvoiceFromClient, 'Petter Parker'); - await page.autocompleteSearch(selectors.invoiceOutIndex.globalInvoiceToClient, 'Petter Parker'); - await page.waitToClick(selectors.invoiceOutIndex.saveInvoice); - const message = await page.waitForSnackbar(); - - expect(message.text).toContain('Data saved!'); + await page.waitToClick(selectors.invoiceOutGlobalInvoicing.oneClient); + await page.autocompleteSearch(selectors.invoiceOutGlobalInvoicing.clientId, '1108'); + await page.pickDate(selectors.invoiceOutGlobalInvoicing.invoiceDate, now); + await page.pickDate(selectors.invoiceOutGlobalInvoicing.maxShipped, now); + await page.autocompleteSearch(selectors.invoiceOutGlobalInvoicing.printer, '1'); + await page.waitToClick(selectors.invoiceOutGlobalInvoicing.makeInvoice); + await page.waitForTimeout(1000); }); - it('should count the amount of invoices listed after globla invocing', async() => { + it('should count the amount of invoices listed after invoice for charles xavier today', async() => { + await page.waitToClick('[icon="search"]'); + await page.waitForTimeout(1000); // index search needs time to return results + invoicesBeforeAllClients = await page.countElement(selectors.invoiceOutIndex.searchResult); + + expect(invoicesBeforeAllClients).toBeGreaterThan(invoicesBeforeOneClient); + }); + + it('should create a global invoice for all clients today', async() => { + await page.accessToSection('invoiceOut.global-invoicing'); + await page.waitToClick(selectors.invoiceOutGlobalInvoicing.allClients); + await page.pickDate(selectors.invoiceOutGlobalInvoicing.invoiceDate, now); + await page.pickDate(selectors.invoiceOutGlobalInvoicing.maxShipped, now); + await page.autocompleteSearch(selectors.invoiceOutGlobalInvoicing.printer, '1'); + await page.waitToClick(selectors.invoiceOutGlobalInvoicing.makeInvoice); + await page.waitForTimeout(1000); + }); + + it('should count the amount of invoices listed after global invocing', async() => { await page.waitToClick('[icon="search"]'); await page.waitForTimeout(1000); // index search needs time to return results const currentInvoices = await page.countElement(selectors.invoiceOutIndex.searchResult); - expect(currentInvoices).toBeGreaterThan(invoicesBefore); - }); - - it('should create a global invoice for all clients today', async() => { - await page.waitToClick(selectors.invoiceOutIndex.createInvoice); - await page.waitToClick(selectors.invoiceOutIndex.createGlobalInvoice); - await page.waitForSelector(selectors.invoiceOutIndex.globalInvoiceForm); - await page.pickDate(selectors.invoiceOutIndex.globalInvoiceDate); - await page.waitToClick(selectors.invoiceOutIndex.saveInvoice); - const message = await page.waitForSnackbar(); - - expect(message.text).toContain('Data saved!'); + expect(currentInvoices).toBeGreaterThan(invoicesBeforeAllClients); }); }); diff --git a/loopback/locale/en.json b/loopback/locale/en.json index c810e5a69..9f6174afe 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -150,5 +150,6 @@ "It is not possible to modify tracked sales": "It is not possible to modify tracked sales", "It is not possible to modify sales that their articles are from Floramondo": "It is not possible to modify sales that their articles are from Floramondo", "It is not possible to modify cloned sales": "It is not possible to modify cloned sales", - "Valid priorities: 1,2,3": "Valid priorities: 1,2,3" -} + "Valid priorities: 1,2,3": "Valid priorities: 1,2,3", + "Warehouse inventory not seted": "Warehouse inventory not seted" +} \ No newline at end of file diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 4d7159fe8..9d2d67d14 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -266,5 +266,6 @@ "A supplier with the same name already exists. Change the country.": "Un proveedor con el mismo nombre ya existe. Cambie el país.", "There is no assigned email for this client": "No hay correo asignado para este cliente", "Exists an invoice with a previous date": "Existe una factura con fecha anterior", - "Invoice date can't be less than max date": "La fecha de factura no puede ser inferior a la fecha límite" + "Invoice date can't be less than max date": "La fecha de factura no puede ser inferior a la fecha límite", + "Warehouse inventory not seted": "Warehouse inventory not seted" } \ No newline at end of file diff --git a/modules/invoiceOut/back/methods/invoiceOut/getInvoiceDate.js b/modules/invoiceOut/back/methods/invoiceOut/getInvoiceDate.js index ec7146513..dcc1fa6e8 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/getInvoiceDate.js +++ b/modules/invoiceOut/back/methods/invoiceOut/getInvoiceDate.js @@ -4,10 +4,6 @@ module.exports = Self => { accessType: 'READ', accepts: [ { - arg: 'year', - type: 'number', - required: true - }, { arg: 'companyFk', type: 'number', required: true @@ -23,17 +19,16 @@ module.exports = Self => { } }); - Self.getInvoiceDate = async(year, companyFk) => { + Self.getInvoiceDate = async companyFk => { const models = Self.app.models; const [invoiceDate] = await models.InvoiceOut.rawSql( `SELECT MAX(io.issued) issued FROM invoiceOut io JOIN invoiceOutSerial ios ON ios.code = io.serial WHERE ios.type = 'global' - AND io.issued BETWEEN MAKEDATE(?, 1) AND - util.lastDayOfYear(MAKEDATE(?, 1)) + AND io.issued AND io.companyFk = ?`, - [year, year, companyFk] + [companyFk] ); return invoiceDate; }; diff --git a/modules/invoiceOut/front/global-invoicing/index.js b/modules/invoiceOut/front/global-invoicing/index.js index 8e00231ea..0ac0223b4 100644 --- a/modules/invoiceOut/front/global-invoicing/index.js +++ b/modules/invoiceOut/front/global-invoicing/index.js @@ -15,13 +15,12 @@ class Controller extends Section { .then(res => { this.companyFk = res.data.companyFk; const params = { - year: this.maxShipped.getFullYear(), companyFk: this.companyFk }; return this.$http.get('InvoiceOuts/getInvoiceDate', {params}); }) .then(res => { - this.minInvoicingDate = new Date(res.data.issued); + this.minInvoicingDate = res.data.issued ? new Date(res.data.issued) : null; this.invoiceDate = this.minInvoicingDate; }); } From e39690c2c91d7dc464747588358876d4e4a62bc2 Mon Sep 17 00:00:00 2001 From: vicent Date: Mon, 6 Mar 2023 10:21:10 +0100 Subject: [PATCH 42/48] merge with dev --- modules/ticket/front/sale-tracking/index.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/ticket/front/sale-tracking/index.html b/modules/ticket/front/sale-tracking/index.html index 33d22f92e..0309dde13 100644 --- a/modules/ticket/front/sale-tracking/index.html +++ b/modules/ticket/front/sale-tracking/index.html @@ -29,7 +29,7 @@ 'pink': sale.preparingList.hasSaleGroupDetail, 'none': !sale.preparingList.hasSaleGroupDetail, }" - class="circle" + class="circleState" vn-tooltip="has saleGroupDetail" > @@ -37,28 +37,28 @@ 'notice': sale.preparingList.isPreviousSelected, 'none': !sale.preparingList.isPreviousSelected, }" - class="circle" + class="circleState" vn-tooltip="is previousSelected"> From 4830f8489ad601ccfdcb732167ae16d7c04c0527 Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 7 Mar 2023 08:12:08 +0100 Subject: [PATCH 43/48] remove unnecessary fixtures --- db/dump/fixtures.sql | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index dac45ee33..85bcee7b1 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -1,16 +1,8 @@ CREATE SCHEMA IF NOT EXISTS `vn2008`; CREATE SCHEMA IF NOT EXISTS `tmp`; -ALTER TABLE util.config - ADD COLUMN `mockUtcTime` datetime DEFAULT NULL, - ADD COLUMN `mockEnabled` tinyint(3) unsigned NOT NULL DEFAULT 0, - ADD COLUMN `mockTz` varchar(255) DEFAULT NULL; - -UPDATE util.config - SET mockUtcTime='2001-01-01 11:00:00', - environment= 'development', - mockEnabled = TRUE, - mockTz='+01:00'; +UPDATE `util`.`config` + SET `environment`= 'development'; -- FOR MOCK vn.time From b6e993dadf906980afdb02acf1182e1f249c207b Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 7 Mar 2023 10:04:26 +0100 Subject: [PATCH 44/48] fix: e2e --- .../09-invoice-out/04_globalInvoice.spec.js | 26 ------------------- 1 file changed, 26 deletions(-) diff --git a/e2e/paths/09-invoice-out/04_globalInvoice.spec.js b/e2e/paths/09-invoice-out/04_globalInvoice.spec.js index 052893aff..23aa3593c 100644 --- a/e2e/paths/09-invoice-out/04_globalInvoice.spec.js +++ b/e2e/paths/09-invoice-out/04_globalInvoice.spec.js @@ -40,30 +40,4 @@ describe('InvoiceOut global invoice path', () => { await page.waitToClick(selectors.invoiceOutGlobalInvoicing.makeInvoice); await page.waitForTimeout(1000); }); - - it('should count the amount of invoices listed after invoice for charles xavier today', async() => { - await page.waitToClick('[icon="search"]'); - await page.waitForTimeout(1000); // index search needs time to return results - invoicesBeforeAllClients = await page.countElement(selectors.invoiceOutIndex.searchResult); - - expect(invoicesBeforeAllClients).toBeGreaterThan(invoicesBeforeOneClient); - }); - - it('should create a global invoice for all clients today', async() => { - await page.accessToSection('invoiceOut.global-invoicing'); - await page.waitToClick(selectors.invoiceOutGlobalInvoicing.allClients); - await page.pickDate(selectors.invoiceOutGlobalInvoicing.invoiceDate, now); - await page.pickDate(selectors.invoiceOutGlobalInvoicing.maxShipped, now); - await page.autocompleteSearch(selectors.invoiceOutGlobalInvoicing.printer, '1'); - await page.waitToClick(selectors.invoiceOutGlobalInvoicing.makeInvoice); - await page.waitForTimeout(1000); - }); - - it('should count the amount of invoices listed after global invocing', async() => { - await page.waitToClick('[icon="search"]'); - await page.waitForTimeout(1000); // index search needs time to return results - const currentInvoices = await page.countElement(selectors.invoiceOutIndex.searchResult); - - expect(currentInvoices).toBeGreaterThan(invoicesBeforeAllClients); - }); }); From 32429a58e0af9a89b82b0da8798d33d38dac4dc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Andr=C3=A9s?= Date: Wed, 8 Mar 2023 12:36:53 +0100 Subject: [PATCH 45/48] refs #5000 remove consolelog --- modules/invoiceOut/back/methods/invoiceOut/createPdf.js | 2 +- modules/invoiceOut/back/methods/invoiceOut/downloadZip.js | 1 - modules/invoiceOut/back/methods/invoiceOut/specs/filter.spec.js | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/modules/invoiceOut/back/methods/invoiceOut/createPdf.js b/modules/invoiceOut/back/methods/invoiceOut/createPdf.js index 71e7c1543..e56516237 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/createPdf.js +++ b/modules/invoiceOut/back/methods/invoiceOut/createPdf.js @@ -44,7 +44,7 @@ module.exports = Self => { try { const invoiceOut = await Self.findById(id, null, myOptions); const hasInvoicing = await models.Account.hasRole(userId, 'invoicing', myOptions); - console.log(invoiceOut, !hasInvoicing); + if (invoiceOut.hasPdf && !hasInvoicing) throw new UserError(`You don't have enough privileges`); diff --git a/modules/invoiceOut/back/methods/invoiceOut/downloadZip.js b/modules/invoiceOut/back/methods/invoiceOut/downloadZip.js index 208d55358..fe005f1ab 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/downloadZip.js +++ b/modules/invoiceOut/back/methods/invoiceOut/downloadZip.js @@ -47,7 +47,6 @@ module.exports = Self => { ids = ids.split(','); for (let id of ids) { - console.log(zipConfig, totalSize, zipConfig ? zipConfig.maxSize : null); if (zipConfig && totalSize > zipConfig.maxSize) throw new UserError('Files are too large'); const invoiceOutPdf = await models.InvoiceOut.download(ctx, id, myOptions); const fileName = extractFileName(invoiceOutPdf[2]); diff --git a/modules/invoiceOut/back/methods/invoiceOut/specs/filter.spec.js b/modules/invoiceOut/back/methods/invoiceOut/specs/filter.spec.js index 9264bf77d..15e3e887e 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/specs/filter.spec.js +++ b/modules/invoiceOut/back/methods/invoiceOut/specs/filter.spec.js @@ -65,7 +65,6 @@ describe('InvoiceOut filter()', () => { await invoiceOut.updateAttribute('hasPdf', true, options); const result = await models.InvoiceOut.filter(ctx, {id: invoiceOut.id}, options); - console.log(result); expect(result.length).toEqual(1); From 6d3fa34624e422d0910a351de556955d123582ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Andr=C3=A9s?= Date: Tue, 14 Mar 2023 09:14:04 +0100 Subject: [PATCH 46/48] refs #5000 invoiceOutGlobal --- db/changes/{230601 => 231001}/00-invoiceOut.sql | 0 db/changes/{230601 => 231001}/00-invoiceOut_getWeight.sql | 0 db/changes/{230401 => 231001}/00-report.sql | 0 db/changes/{230601 => 231001}/01-invoiceOut_getMaxIssued.sql | 0 db/changes/{230601 => 231001}/02-invoiceOut_new.sql | 0 db/changes/{230601 => 231001}/03-ticketPackaging_add.sql | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename db/changes/{230601 => 231001}/00-invoiceOut.sql (100%) rename db/changes/{230601 => 231001}/00-invoiceOut_getWeight.sql (100%) rename db/changes/{230401 => 231001}/00-report.sql (100%) rename db/changes/{230601 => 231001}/01-invoiceOut_getMaxIssued.sql (100%) rename db/changes/{230601 => 231001}/02-invoiceOut_new.sql (100%) rename db/changes/{230601 => 231001}/03-ticketPackaging_add.sql (100%) diff --git a/db/changes/230601/00-invoiceOut.sql b/db/changes/231001/00-invoiceOut.sql similarity index 100% rename from db/changes/230601/00-invoiceOut.sql rename to db/changes/231001/00-invoiceOut.sql diff --git a/db/changes/230601/00-invoiceOut_getWeight.sql b/db/changes/231001/00-invoiceOut_getWeight.sql similarity index 100% rename from db/changes/230601/00-invoiceOut_getWeight.sql rename to db/changes/231001/00-invoiceOut_getWeight.sql diff --git a/db/changes/230401/00-report.sql b/db/changes/231001/00-report.sql similarity index 100% rename from db/changes/230401/00-report.sql rename to db/changes/231001/00-report.sql diff --git a/db/changes/230601/01-invoiceOut_getMaxIssued.sql b/db/changes/231001/01-invoiceOut_getMaxIssued.sql similarity index 100% rename from db/changes/230601/01-invoiceOut_getMaxIssued.sql rename to db/changes/231001/01-invoiceOut_getMaxIssued.sql diff --git a/db/changes/230601/02-invoiceOut_new.sql b/db/changes/231001/02-invoiceOut_new.sql similarity index 100% rename from db/changes/230601/02-invoiceOut_new.sql rename to db/changes/231001/02-invoiceOut_new.sql diff --git a/db/changes/230601/03-ticketPackaging_add.sql b/db/changes/231001/03-ticketPackaging_add.sql similarity index 100% rename from db/changes/230601/03-ticketPackaging_add.sql rename to db/changes/231001/03-ticketPackaging_add.sql From 2a6848c09a06e411a24979401f7856d7cfe1e184 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Andr=C3=A9s?= Date: Tue, 14 Mar 2023 09:17:39 +0100 Subject: [PATCH 47/48] refs #5000 invoiceOutGlobal --- db/changes/230402/00-invoiceOut_getWeight.sql | 6 +++--- loopback/locale/es.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/db/changes/230402/00-invoiceOut_getWeight.sql b/db/changes/230402/00-invoiceOut_getWeight.sql index 4ca284857..d69d1b793 100644 --- a/db/changes/230402/00-invoiceOut_getWeight.sql +++ b/db/changes/230402/00-invoiceOut_getWeight.sql @@ -2,13 +2,13 @@ DROP FUNCTION IF EXISTS `vn`.`invoiceOut_getWeight`; DELIMITER $$ $$ -CREATE DEFINER=`root`@`localhost` FUNCTION `vn`.`invoiceOut_getWeight`(vInvoice VARCHAR(15)) RETURNS decimal(10,2) +CREATE DEFINER=`root`@`localhost` FUNCTION `vn`.`invoiceOut_getWeight`(vInvoiceRef VARCHAR(15)) RETURNS decimal(10,2) READS SQL DATA BEGIN /** * Calcula el peso de una factura emitida * - * @param vInvoice Id de la factura + * @param vInvoiceRef referencia de la factura * @return vTotalWeight peso de la factura */ DECLARE vTotalWeight DECIMAL(10,2); @@ -22,7 +22,7 @@ BEGIN JOIN item i ON i.id = s.itemFk JOIN itemCost ic ON ic.itemFk = i.id AND ic.warehouseFk = t.warehouseFk - WHERE t.refFk = vInvoice + WHERE t.refFk = vInvoiceRef AND i.intrastatFk; RETURN vTotalWeight; diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 9d975b75c..788c2fa96 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -267,7 +267,7 @@ "There is no assigned email for this client": "No hay correo asignado para este cliente", "Exists an invoice with a previous date": "Existe una factura con fecha anterior", "Invoice date can't be less than max date": "La fecha de factura no puede ser inferior a la fecha límite", - "Warehouse inventory not seted": "Warehouse inventory not seted", + "Warehouse inventory not set": "El almacén inventario no está establecido", "This locker has already been assigned": "Esta taquilla ya ha sido asignada", "Tickets with associated refunds": "No se pueden borrar tickets con abonos asociados. Este ticket está asociado al abono Nº {{id}}", "Not exist this branch": "La rama no existe" From 6b375cbaaa71488f094b0a8e229a1d40a0bd3935 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Andr=C3=A9s?= Date: Tue, 14 Mar 2023 09:34:41 +0100 Subject: [PATCH 48/48] refs #5000 InvoiceOut --- db/changes/230402/00-invoiceOut_getWeight.sql | 30 ------------------- db/changes/231001/00-invoiceOut_getWeight.sql | 8 +++-- db/changes/231001/03-ticketPackaging_add.sql | 4 +-- db/dump/structure.sql | 4 +-- loopback/locale/en.json | 3 +- 5 files changed, 11 insertions(+), 38 deletions(-) delete mode 100644 db/changes/230402/00-invoiceOut_getWeight.sql diff --git a/db/changes/230402/00-invoiceOut_getWeight.sql b/db/changes/230402/00-invoiceOut_getWeight.sql deleted file mode 100644 index d69d1b793..000000000 --- a/db/changes/230402/00-invoiceOut_getWeight.sql +++ /dev/null @@ -1,30 +0,0 @@ -DROP FUNCTION IF EXISTS `vn`.`invoiceOut_getWeight`; - -DELIMITER $$ -$$ -CREATE DEFINER=`root`@`localhost` FUNCTION `vn`.`invoiceOut_getWeight`(vInvoiceRef VARCHAR(15)) RETURNS decimal(10,2) - READS SQL DATA -BEGIN -/** - * Calcula el peso de una factura emitida - * - * @param vInvoiceRef referencia de la factura - * @return vTotalWeight peso de la factura - */ - DECLARE vTotalWeight DECIMAL(10,2); - - SELECT SUM(CAST(IFNULL(i.stems, 1) - * s.quantity - * IF(ic.grams, ic.grams, IFNULL(i.weightByPiece, 0)) / 1000 AS DECIMAL(10,2))) - INTO vTotalWeight - FROM ticket t - JOIN sale s ON s.ticketFk = t.id - JOIN item i ON i.id = s.itemFk - JOIN itemCost ic ON ic.itemFk = i.id - AND ic.warehouseFk = t.warehouseFk - WHERE t.refFk = vInvoiceRef - AND i.intrastatFk; - - RETURN vTotalWeight; -END$$ -DELIMITER ; diff --git a/db/changes/231001/00-invoiceOut_getWeight.sql b/db/changes/231001/00-invoiceOut_getWeight.sql index 4ca284857..3f34b6fb7 100644 --- a/db/changes/231001/00-invoiceOut_getWeight.sql +++ b/db/changes/231001/00-invoiceOut_getWeight.sql @@ -2,13 +2,15 @@ DROP FUNCTION IF EXISTS `vn`.`invoiceOut_getWeight`; DELIMITER $$ $$ -CREATE DEFINER=`root`@`localhost` FUNCTION `vn`.`invoiceOut_getWeight`(vInvoice VARCHAR(15)) RETURNS decimal(10,2) +CREATE DEFINER=`root`@`localhost` FUNCTION `vn`.`invoiceOut_getWeight`( + vInvoiceRef VARCHAR(15) +)RETURNS decimal(10,2) READS SQL DATA BEGIN /** * Calcula el peso de una factura emitida * - * @param vInvoice Id de la factura + * @param vInvoiceRef referencia de la factura * @return vTotalWeight peso de la factura */ DECLARE vTotalWeight DECIMAL(10,2); @@ -22,7 +24,7 @@ BEGIN JOIN item i ON i.id = s.itemFk JOIN itemCost ic ON ic.itemFk = i.id AND ic.warehouseFk = t.warehouseFk - WHERE t.refFk = vInvoice + WHERE t.refFk = vInvoiceRef AND i.intrastatFk; RETURN vTotalWeight; diff --git a/db/changes/231001/03-ticketPackaging_add.sql b/db/changes/231001/03-ticketPackaging_add.sql index f5e3d50ad..a7cf1d1d3 100644 --- a/db/changes/231001/03-ticketPackaging_add.sql +++ b/db/changes/231001/03-ticketPackaging_add.sql @@ -54,11 +54,11 @@ BEGIN FROM ticketConfig; IF vWarehouseInventory IS NULL THEN - CALL util.throw('Warehouse inventory not seted'); + CALL util.throw('Warehouse inventory not set'); END IF; IF vComponentCost IS NULL THEN - CALL util.throw('Component cost not seted'); + CALL util.throw('Component cost not set'); END IF; SET vDateEnd = vDated + INTERVAL 1 DAY; diff --git a/db/dump/structure.sql b/db/dump/structure.sql index c1e911cd5..63754d536 100644 --- a/db/dump/structure.sql +++ b/db/dump/structure.sql @@ -68382,11 +68382,11 @@ BEGIN FROM ticketConfig; IF vWarehouseInventory IS NULL THEN - CALL util.throw('Warehouse inventory not seted'); + CALL util.throw('Warehouse inventory not set'); END IF; IF vComponentCost IS NULL THEN - CALL util.throw('Component cost not seted'); + CALL util.throw('Component cost not set'); END IF; SET vDateEnd = vDated + INTERVAL 1 DAY; diff --git a/loopback/locale/en.json b/loopback/locale/en.json index 0061e5c55..e9fd67209 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -152,6 +152,7 @@ "It is not possible to modify sales that their articles are from Floramondo": "It is not possible to modify sales that their articles are from Floramondo", "It is not possible to modify cloned sales": "It is not possible to modify cloned sales", "Valid priorities: 1,2,3": "Valid priorities: 1,2,3", - "Warehouse inventory not seted": "Warehouse inventory not seted", + "Warehouse inventory not set": "Almacén inventario no está establecido", + "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" }