diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 914fa6158..beeb83584 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -2780,11 +2780,13 @@ INSERT INTO `util`.`notification` (`id`, `name`, `description`) (2, 'invoice-electronic', 'A electronic invoice has been generated'), (3, 'not-main-printer-configured', 'A printer distinct than main has been configured'), (4, 'supplier-pay-method-update', 'A supplier pay method has been updated'), - (5, 'modified-entry', 'An entry has been modified'); + (5, 'modified-entry', 'An entry has been modified'), + (6, 'book-entry-deleted', 'accounting entries deleted'); INSERT INTO `util`.`notificationAcl` (`notificationFk`, `roleFk`) VALUES - (1, 9); + (1, 9), + (6, 9); INSERT INTO `util`.`notificationQueue` (`id`, `notificationFk`, `params`, `authorFk`, `status`, `created`) VALUES @@ -2797,8 +2799,9 @@ INSERT INTO `util`.`notificationSubscription` (`notificationFk`, `userFk`) (1, 1109), (1, 1110), (2, 1109), - (1,9), - (1,3); + (1, 9), + (1, 3), + (6, 9); INSERT INTO `vn`.`routeConfig` (`id`, `defaultWorkCenterFk`) @@ -2962,3 +2965,12 @@ INSERT INTO `vn`.`invoiceInSerial` (`code`, `description`, `cplusTerIdNifFk`, `t INSERT INTO `hedera`.`imageConfig` (`id`, `maxSize`, `useXsendfile`, `url`) VALUES (1, 0, 0, 'marvel.com'); + +INSERT INTO vn.XDiario (id, ASIEN, FECHA, SUBCTA, CONTRA, CONCEPTO, EURODEBE, EUROHABER, BASEEURO, SERIE, FACTURA, IVA, RECEQUIV, CLAVE, CAMBIO, DEBEME, HABERME, AUXILIAR, MONEDAUSO, TIPOOPE, NFACTICK, TERIDNIF, TERNIF, TERNOM, OPBIENES, L340, enlazado, FECHA_EX, LRECT349, empresa_id, LDIFADUAN, METAL, METALIMP, CLIENTE, METALEJE, FECHA_OP, FACTURAEX, TIPOCLAVE, TIPOEXENCI, TIPONOSUJE, TIPOFACT, TIPORECTIF, SERIE_RT, FACTU_RT, BASEIMP_RT, BASEIMP_RF, RECTIFICA, FECHA_RT, FECREGCON, enlazadoSage) + VALUES + (1, 1.0, util.VN_CURDATE(), '4300001104', NULL, 'n/fra T3333333', 8.88, NULL, NULL, NULL, '0', NULL, 0.00, NULL, NULL, NULL, NULL, NULL, '2', NULL, 1, 2, 'I.F.', 'Nombre Importador', 1, 0, 0, util.VN_CURDATE(), 0, 442, 0, 0, 0.00, NULL, NULL, util.VN_CURDATE(), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, 1), + (2, 1.0, util.VN_CURDATE(), '2000000000', '4300001104', 'n/fra T3333333 Tony Stark', NULL, 8.07, NULL, NULL, '0', NULL, 0.00, NULL, NULL, NULL, NULL, NULL, '2', NULL, 1, 2, 'I.F.', 'Nombre Importador', 1, 0, 0, util.VN_CURDATE(), 0, 442, 0, 0, 0.00, NULL, NULL, util.VN_CURDATE(), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, 1), + (3, 1.0, util.VN_CURDATE(), '4770000010', '4300001104', 'Inmovilizado pendiente : n/fra T3333333 Tony Stark', NULL, 0.81, 8.07, 'T', '3333333', 10.00, NULL, NULL, NULL, NULL, NULL, '', '2', '', 1, 1, '06089160W', 'IRON MAN', 1, 1, 0, util.VN_CURDATE(), 0, 442, 0, 0, 0.00, NULL, NULL, util.VN_CURDATE(), NULL, 1, 1, 1, 1, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, 1), + (4, 2.0, util.VN_CURDATE(), '4300001104', NULL, 'n/fra T4444444', 8.88, NULL, NULL, NULL, '0', NULL, 0.00, NULL, NULL, NULL, NULL, NULL, '2', NULL, 1, 2, 'I.F.', 'Nombre Importador', 1, 0, 0, util.VN_CURDATE(), 0, 442, 0, 0, 0.00, NULL, NULL, util.VN_CURDATE(), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, 0), + (5, 2.0, util.VN_CURDATE(), '2000000000', '4300001104', 'n/fra T4444444 Tony Stark', NULL, 8.07, NULL, NULL, '0', NULL, 0.00, NULL, NULL, NULL, NULL, NULL, '2', NULL, 1, 2, 'I.F.', 'Nombre Importador', 1, 0, 0, util.VN_CURDATE(), 0, 442, 0, 0, 0.00, NULL, NULL, util.VN_CURDATE(), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, 0), + (6, 2.0, util.VN_CURDATE(), '4770000010', '4300001104', 'Inmovilizado pendiente : n/fra T4444444 Tony Stark', NULL, 0.81, 8.07, 'T', '4444444', 10.00, NULL, NULL, NULL, NULL, NULL, '', '2', '', 1, 1, '06089160W', 'IRON MAN', 1, 1, 0, util.VN_CURDATE(), 0, 442, 0, 0, 0.00, NULL, NULL, util.VN_CURDATE(), NULL, 1, 1, 1, 1, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, 0); \ No newline at end of file diff --git a/modules/client/back/model-config.json b/modules/client/back/model-config.json index bc48ec360..296b5e6a7 100644 --- a/modules/client/back/model-config.json +++ b/modules/client/back/model-config.json @@ -136,5 +136,8 @@ }, "Incoterms": { "dataSource": "vn" + }, + "Xdiario": { + "dataSource": "vn" } } diff --git a/modules/client/back/models/XDiario.json b/modules/client/back/models/XDiario.json index be2d258f9..be543393d 100644 --- a/modules/client/back/models/XDiario.json +++ b/modules/client/back/models/XDiario.json @@ -1,5 +1,5 @@ { - "name": "XDiario", + "name": "Xdiario", "base": "VnModel", "options": { "mysql": { @@ -7,10 +7,12 @@ } }, "properties": { - "ASIEN": { + "id": { "type": "number", - "id": true, - "description": "Identifier" + "id": true + }, + "ASIEN": { + "type": "number" }, "FECHA": { "type": "date" @@ -71,6 +73,9 @@ }, "MONEDAUSO": { "type": "string" + }, + "enlazadoSage": { + "type": "boolean" } }, "relations": { diff --git a/modules/entry/back/locale/entry/es.yml b/modules/entry/back/locale/entry/es.yml index 3a0c3d9c1..a892b05d2 100644 --- a/modules/entry/back/locale/entry/es.yml +++ b/modules/entry/back/locale/entry/es.yml @@ -4,14 +4,14 @@ columns: dated: fecha reference: referencia invoiceNumber: número factura - isBooked: reservado + isBooked: contabilizado isExcludedFromAvailable: excluido del disponible notes: notas isConfirmed: confirmado isVirtual: virtual - isRaid: incursión + isRaid: redada commission: comisión - isOrdered: precio3 + isOrdered: pedida created: creado observation: observación isBlocked: bloqueado diff --git a/modules/invoiceIn/front/basic-data/index.js b/modules/invoiceIn/front/basic-data/index.js index 8747fc4f2..246f1b16f 100644 --- a/modules/invoiceIn/front/basic-data/index.js +++ b/modules/invoiceIn/front/basic-data/index.js @@ -67,17 +67,22 @@ class Controller extends Section { } openCreateDialog() { - this.dms = { - reference: null, - warehouseId: null, - companyId: null, - dmsTypeId: null, - description: null, - hasFile: true, - hasFileAttached: true, - files: null - }; - this.$.dmsCreateDialog.show(); + const params = {filter: { + where: {code: 'invoiceIn'} + }}; + this.$http.get('DmsTypes/findOne', {params}).then(res => { + this.dms = { + reference: this.invoiceIn.supplierRef, + warehouseId: this.vnConfig.warehouseFk, + companyId: this.vnConfig.companyFk, + dmsTypeId: res.data.id, + description: this.invoiceIn.supplier.name, + hasFile: true, + hasFileAttached: true, + files: null + }; + this.$.dmsCreateDialog.show(); + }); } downloadFile(dmsId) { diff --git a/modules/invoiceIn/front/create/index.js b/modules/invoiceIn/front/create/index.js index 186f5d478..885d55359 100644 --- a/modules/invoiceIn/front/create/index.js +++ b/modules/invoiceIn/front/create/index.js @@ -6,6 +6,7 @@ class Controller extends Section { this.invoiceIn = {}; if (this.$params && this.$params.supplierFk) this.invoiceIn.supplierFk = this.$params.supplierFk; + this.invoiceIn.issued = Date.vnNew(); } get companyFk() { diff --git a/modules/invoiceIn/front/create/index.spec.js b/modules/invoiceIn/front/create/index.spec.js deleted file mode 100644 index 93109346c..000000000 --- a/modules/invoiceIn/front/create/index.spec.js +++ /dev/null @@ -1,52 +0,0 @@ -import './index.js'; -import watcher from 'core/mocks/watcher'; - -describe('InvoiceIn', () => { - describe('Component vnInvoiceInCreate', () => { - let controller; - let $element; - - beforeEach(ngModule('invoiceIn')); - - beforeEach(inject(($componentController, $rootScope) => { - const $scope = $rootScope.$new(); - $scope.watcher = watcher; - $element = angular.element(''); - controller = $componentController('vnInvoiceInCreate', {$element, $scope}); - controller.$params = {}; - })); - - afterEach(() => { - $element.remove(); - }); - - describe('onInit()', () => { - it(`should defined the controller's invoiceIn property`, () => { - expect(controller.invoiceIn).toBeUndefined(); - - controller.$onInit(); - - expect(controller.invoiceIn).toEqual({}); - }); - - it(`should define invoiceIn and it's supplierFk when received via params`, () => { - controller.$params.supplierFk = 'supplierId'; - - controller.$onInit(); - - expect(controller.invoiceIn.supplierFk).toEqual('supplierId'); - }); - }); - - describe('onSubmit()', () => { - it(`should redirect to basic data by calling the $state.go function`, () => { - jest.spyOn(controller.$state, 'go'); - - controller.onSubmit(); - - expect(controller.$state.go).toHaveBeenCalledWith('invoiceIn.card.basicData', {id: 1234}); - }); - }); - }); -}); - diff --git a/modules/invoiceOut/back/methods/invoiceOut/delete.js b/modules/invoiceOut/back/methods/invoiceOut/delete.js index d8b9d309b..d6efd9961 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/delete.js +++ b/modules/invoiceOut/back/methods/invoiceOut/delete.js @@ -1,4 +1,3 @@ - module.exports = Self => { Self.remoteMethod('delete', { description: 'Delete a invoiceOut', @@ -34,19 +33,41 @@ module.exports = Self => { try { const invoiceOut = await Self.findById(id, {}, myOptions); - const tickets = await Self.app.models.Ticket.find({ + const models = Self.app.models; + const tickets = await models.Ticket.find({ where: {refFk: invoiceOut.ref} }, myOptions); - + + const [bookEntry] = await models.Xdiario.find({ + where: { + SERIE: invoiceOut.ref[0], + FACTURA: invoiceOut.ref.slice(1) + } + }, myOptions); const promises = []; for (let ticket of tickets) promises.push(ticket.updateAttribute('refFk', null, myOptions)); await Promise.all(promises); - await invoiceOut.destroy(myOptions); + if (bookEntry) { + if (bookEntry.enlazadoSage) { + const params = { + bookEntry: bookEntry.ASIEN, + invoiceOutRef: invoiceOut.ref + } + await Self.rawSql(`SELECT util.notification_send('book-entry-deleted', ?, NULL)`, + [JSON.stringify(params)], + myOptions); + }; + + await models.Xdiario.destroyAll({ + ASIEN: bookEntry.ASIEN + }); + } + if (tx) await tx.commit(); return tickets; diff --git a/modules/invoiceOut/back/methods/invoiceOut/specs/delete.spec.js b/modules/invoiceOut/back/methods/invoiceOut/specs/delete.spec.js index a662cb318..9d638ecf4 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/specs/delete.spec.js +++ b/modules/invoiceOut/back/methods/invoiceOut/specs/delete.spec.js @@ -2,18 +2,24 @@ const models = require('vn-loopback/server/server').models; const LoopBackContext = require('loopback-context'); describe('invoiceOut delete()', () => { - const invoiceOutId = 2; - const userId = 1106; + const invoiceOutId = 2; + const userId = 106; const activeCtx = { accessToken: {userId: userId}, }; + + beforeEach(() => { + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); + }); it('should check that there is one ticket in the target invoiceOut', async() => { const tx = await models.InvoiceOut.beginTransaction({}); const options = {transaction: tx}; try { - const invoiceOut = await models.InvoiceOut.findById(invoiceOutId, {}, options); + const invoiceOut = await models.InvoiceOut.findById(invoiceOutId , {}, options); const tickets = await models.Ticket.find({where: {refFk: invoiceOut.ref}}, options); expect(tickets.length).toEqual(1); @@ -31,12 +37,7 @@ describe('invoiceOut delete()', () => { const options = {transaction: tx}; try { - spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ - active: activeCtx - }); - await models.InvoiceOut.delete(invoiceOutId, options); - const originalTicket = await models.Ticket.findById(3, {}, options); const deletedInvoiceOut = await models.InvoiceOut.findById(invoiceOutId, {}, options); @@ -50,4 +51,107 @@ describe('invoiceOut delete()', () => { throw e; } }); + + it('should delete the corresponding bookEntry and not notify', async () => { + const tx = await models.InvoiceOut.beginTransaction({}); + const options = {transaction: tx}; + + try { + const filter = { + where: { + ASIEN: 2 + }, + fields: ['id', 'enlazadoSage'] + }; + + const [beforeXdiario] = await models.Xdiario.find(filter, options) + + const [beforeNotification] = await models.NotificationQueue.find({ + where: { + notificationFk: 'book-entry-deleted', + status: 'pending' + } + }, options); + + expect(beforeXdiario).toBeDefined(); + expect(beforeXdiario.enlazadoSage).toBeFalsy; + expect(beforeNotification).not.toBeDefined(); + + await models.InvoiceOut.delete(4, options); + + const [afterXdiario] = await models.Xdiario.find({ + where: { + ASIEN: 2 + } + }, options); + + const [afterNotification] = await models.NotificationQueue.find({ + where: { + notificationFk: 'book-entry-deleted', + params: '{"bookEntry":2,"invoiceOutRef":"T4444444"}', + status: 'pending' + } + }, options); + + expect(afterXdiario).not.toBeDefined(); + expect(afterNotification).not.toBeDefined(); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it('should delete the corresponding bookEntry and notify', async () => { + const tx = await models.InvoiceOut.beginTransaction({}); + const options = {transaction: tx}; + + try { + const filter = { + where: { + ASIEN: 1 + }, + fields: ['id', 'enlazadoSage'] + }; + + const [beforeXdiario] = await models.Xdiario.find(filter, options) + + const [beforeNotification] = await models.NotificationQueue.find({ + where: { + notificationFk: 'book-entry-deleted', + status: 'pending' + } + }, options); + + expect(beforeXdiario).toBeDefined(); + expect(beforeXdiario.enlazadoSage).toBeTruthy(); + expect(beforeNotification).not.toBeDefined(); + + await models.InvoiceOut.delete(3, options); + + const [afterXdiario] = await models.Xdiario.find({ + where: { + ASIEN: 1 + } + }, options); + + const [afterNotification] = await models.NotificationQueue.find({ + where: { + notificationFk: 'book-entry-deleted', + params: '{"bookEntry":1,"invoiceOutRef":"T3333333"}', + status: 'pending' + } + }, options); + + expect(afterXdiario).not.toBeDefined(); + expect(afterNotification).toBeDefined(); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + }); diff --git a/print/templates/email/book-entry-deleted/assets/css/import.js b/print/templates/email/book-entry-deleted/assets/css/import.js new file mode 100644 index 000000000..1582b82c5 --- /dev/null +++ b/print/templates/email/book-entry-deleted/assets/css/import.js @@ -0,0 +1,12 @@ +const Stylesheet = require(`vn-print/core/stylesheet`); + +const path = require('path'); +const vnPrintPath = path.resolve('print'); + +module.exports = new Stylesheet([ + `${vnPrintPath}/common/css/spacing.css`, + `${vnPrintPath}/common/css/misc.css`, + `${vnPrintPath}/common/css/layout.css`, + `${vnPrintPath}/common/css/email.css`]) + .mergeStyles(); + diff --git a/print/templates/email/book-entry-deleted/book-entry-deleted.html b/print/templates/email/book-entry-deleted/book-entry-deleted.html new file mode 100644 index 000000000..9a9f2a93e --- /dev/null +++ b/print/templates/email/book-entry-deleted/book-entry-deleted.html @@ -0,0 +1,8 @@ + +
+
+

{{ $t('title') }}

+

+
+
+
diff --git a/print/templates/email/book-entry-deleted/book-entry-deleted.js b/print/templates/email/book-entry-deleted/book-entry-deleted.js new file mode 100644 index 000000000..cd29f5ddb --- /dev/null +++ b/print/templates/email/book-entry-deleted/book-entry-deleted.js @@ -0,0 +1,19 @@ +const Component = require(`vn-print/core/component`); +const emailBody = new Component(); + +module.exports = { + name: 'book-entry-deleted', + components: { + 'email-body': emailBody.build(), + }, + props: { + bookEntry: { + type: Number, + required: true + }, + invoiceOutRef: { + type: String, + required: true + } + } +}; diff --git a/print/templates/email/book-entry-deleted/locale/en.yml b/print/templates/email/book-entry-deleted/locale/en.yml new file mode 100644 index 000000000..11c18f2c9 --- /dev/null +++ b/print/templates/email/book-entry-deleted/locale/en.yml @@ -0,0 +1,5 @@ +Subject: Linked Accounting Entry Deleted +Title: Linked Accounting Entry Deleted +Description: The linked accounting entry that was associated with SAGE has been deleted.

+Entry No. {0}

+This entry has been deleted because the associated invoice {1} has been removed. diff --git a/print/templates/email/book-entry-deleted/locale/es.yml b/print/templates/email/book-entry-deleted/locale/es.yml new file mode 100644 index 000000000..c40cf25fd --- /dev/null +++ b/print/templates/email/book-entry-deleted/locale/es.yml @@ -0,0 +1,5 @@ +subject: Asiento contable enlazado eliminado +title: Asiento contable enlazado eliminado +description: Se ha borrado el asiento contable que se encuentraba enlazado a SAGE

+ Asientos nº {0}

+ Este asiento se ha borrado porque se ha eliminado la factura asociada {1}