4515-itemWeight #1971

Closed
pablone wants to merge 7 commits from 4515-itemWeight into dev
14 changed files with 234 additions and 86 deletions
Showing only changes of commit fe9cf24905 - Show all commits

View File

@ -2780,11 +2780,13 @@ INSERT INTO `util`.`notification` (`id`, `name`, `description`)
(2, 'invoice-electronic', 'A electronic invoice has been generated'), (2, 'invoice-electronic', 'A electronic invoice has been generated'),
(3, 'not-main-printer-configured', 'A printer distinct than main has been configured'), (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'), (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`) INSERT INTO `util`.`notificationAcl` (`notificationFk`, `roleFk`)
VALUES VALUES
(1, 9); (1, 9),
(6, 9);
INSERT INTO `util`.`notificationQueue` (`id`, `notificationFk`, `params`, `authorFk`, `status`, `created`) INSERT INTO `util`.`notificationQueue` (`id`, `notificationFk`, `params`, `authorFk`, `status`, `created`)
VALUES VALUES
@ -2797,8 +2799,9 @@ INSERT INTO `util`.`notificationSubscription` (`notificationFk`, `userFk`)
(1, 1109), (1, 1109),
(1, 1110), (1, 1110),
(2, 1109), (2, 1109),
(1,9), (1, 9),
(1,3); (1, 3),
(6, 9);
INSERT INTO `vn`.`routeConfig` (`id`, `defaultWorkCenterFk`) 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`) INSERT INTO `hedera`.`imageConfig` (`id`, `maxSize`, `useXsendfile`, `url`)
VALUES VALUES
(1, 0, 0, 'marvel.com'); (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);

View File

@ -136,5 +136,8 @@
}, },
"Incoterms": { "Incoterms": {
"dataSource": "vn" "dataSource": "vn"
},
"Xdiario": {
"dataSource": "vn"
} }
} }

View File

@ -1,5 +1,5 @@
{ {
"name": "XDiario", "name": "Xdiario",
"base": "VnModel", "base": "VnModel",
"options": { "options": {
"mysql": { "mysql": {
@ -7,10 +7,12 @@
} }
}, },
"properties": { "properties": {
"ASIEN": { "id": {
"type": "number", "type": "number",
"id": true, "id": true
"description": "Identifier" },
"ASIEN": {
"type": "number"
}, },
"FECHA": { "FECHA": {
"type": "date" "type": "date"
@ -71,6 +73,9 @@
}, },
"MONEDAUSO": { "MONEDAUSO": {
"type": "string" "type": "string"
},
"enlazadoSage": {
"type": "boolean"
} }
}, },
"relations": { "relations": {

View File

@ -4,14 +4,14 @@ columns:
dated: fecha dated: fecha
reference: referencia reference: referencia
invoiceNumber: número factura invoiceNumber: número factura
isBooked: reservado isBooked: contabilizado
isExcludedFromAvailable: excluido del disponible isExcludedFromAvailable: excluido del disponible
notes: notas notes: notas
isConfirmed: confirmado isConfirmed: confirmado
isVirtual: virtual isVirtual: virtual
isRaid: incursión isRaid: redada
commission: comisión commission: comisión
isOrdered: precio3 isOrdered: pedida
created: creado created: creado
observation: observación observation: observación
isBlocked: bloqueado isBlocked: bloqueado

View File

@ -67,17 +67,22 @@ class Controller extends Section {
} }
openCreateDialog() { openCreateDialog() {
this.dms = { const params = {filter: {
reference: null, where: {code: 'invoiceIn'}
warehouseId: null, }};
companyId: null, this.$http.get('DmsTypes/findOne', {params}).then(res => {
dmsTypeId: null, this.dms = {
description: null, reference: this.invoiceIn.supplierRef,
hasFile: true, warehouseId: this.vnConfig.warehouseFk,
hasFileAttached: true, companyId: this.vnConfig.companyFk,
files: null dmsTypeId: res.data.id,
}; description: this.invoiceIn.supplier.name,
this.$.dmsCreateDialog.show(); hasFile: true,
hasFileAttached: true,
files: null
};
this.$.dmsCreateDialog.show();
});
} }
downloadFile(dmsId) { downloadFile(dmsId) {

View File

@ -6,6 +6,7 @@ class Controller extends Section {
this.invoiceIn = {}; this.invoiceIn = {};
if (this.$params && this.$params.supplierFk) if (this.$params && this.$params.supplierFk)
this.invoiceIn.supplierFk = this.$params.supplierFk; this.invoiceIn.supplierFk = this.$params.supplierFk;
this.invoiceIn.issued = Date.vnNew();
} }
get companyFk() { get companyFk() {

View File

@ -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('<vn-invoice-in-create></vn-invoice-in-create>');
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});
});
});
});
});

View File

@ -1,4 +1,3 @@
module.exports = Self => { module.exports = Self => {
Self.remoteMethod('delete', { Self.remoteMethod('delete', {
description: 'Delete a invoiceOut', description: 'Delete a invoiceOut',
@ -34,19 +33,41 @@ module.exports = Self => {
try { try {
const invoiceOut = await Self.findById(id, {}, myOptions); 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} where: {refFk: invoiceOut.ref}
}, myOptions); }, myOptions);
const [bookEntry] = await models.Xdiario.find({
where: {
SERIE: invoiceOut.ref[0],
FACTURA: invoiceOut.ref.slice(1)
}
}, myOptions);
const promises = []; const promises = [];
for (let ticket of tickets) for (let ticket of tickets)
promises.push(ticket.updateAttribute('refFk', null, myOptions)); promises.push(ticket.updateAttribute('refFk', null, myOptions));
await Promise.all(promises); await Promise.all(promises);
await invoiceOut.destroy(myOptions); 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(); if (tx) await tx.commit();
return tickets; return tickets;

View File

@ -2,18 +2,24 @@ const models = require('vn-loopback/server/server').models;
const LoopBackContext = require('loopback-context'); const LoopBackContext = require('loopback-context');
describe('invoiceOut delete()', () => { describe('invoiceOut delete()', () => {
const invoiceOutId = 2; const invoiceOutId = 2;
const userId = 1106; const userId = 106;
const activeCtx = { const activeCtx = {
accessToken: {userId: userId}, accessToken: {userId: userId},
}; };
beforeEach(() => {
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
active: activeCtx
});
});
it('should check that there is one ticket in the target invoiceOut', async() => { it('should check that there is one ticket in the target invoiceOut', async() => {
const tx = await models.InvoiceOut.beginTransaction({}); const tx = await models.InvoiceOut.beginTransaction({});
const options = {transaction: tx}; const options = {transaction: tx};
try { 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); const tickets = await models.Ticket.find({where: {refFk: invoiceOut.ref}}, options);
expect(tickets.length).toEqual(1); expect(tickets.length).toEqual(1);
@ -31,12 +37,7 @@ describe('invoiceOut delete()', () => {
const options = {transaction: tx}; const options = {transaction: tx};
try { try {
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
active: activeCtx
});
await models.InvoiceOut.delete(invoiceOutId, options); await models.InvoiceOut.delete(invoiceOutId, options);
const originalTicket = await models.Ticket.findById(3, {}, options); const originalTicket = await models.Ticket.findById(3, {}, options);
const deletedInvoiceOut = await models.InvoiceOut.findById(invoiceOutId, {}, options); const deletedInvoiceOut = await models.InvoiceOut.findById(invoiceOutId, {}, options);
@ -50,4 +51,107 @@ describe('invoiceOut delete()', () => {
throw e; 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;
}
});
}); });

View File

@ -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();

View File

@ -0,0 +1,8 @@
<email-body v-bind="$props">
<div class="grid-row">
<div class="grid-block vn-pa-ml">
<h1>{{ $t('title') }}</h1>
<p v-html="$t('description', [bookEntry], [invoiceOutRef])"></p>
</div>
</div>
</email-body>

View File

@ -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
}
}
};

View File

@ -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. <br/><br/>
Entry No. {0} <br/><br/>
This entry has been deleted because the associated invoice {1} has been removed.

View File

@ -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 <br/><br/>
Asientos nº {0} <br/><br/>
Este asiento se ha borrado porque se ha eliminado la factura asociada {1}