#7896 - 24.36 Dev To Test #2884
|
@ -632,7 +632,7 @@ INSERT INTO `vn`.`invoiceOutSerial` (`code`, `description`, `isTaxed`, `taxAreaF
|
||||||
('A', 'Global nacional', 1, 'NATIONAL', 0, 'global'),
|
('A', 'Global nacional', 1, 'NATIONAL', 0, 'global'),
|
||||||
('T', 'Española rapida', 1, 'NATIONAL', 0, 'quick'),
|
('T', 'Española rapida', 1, 'NATIONAL', 0, 'quick'),
|
||||||
('V', 'Intracomunitaria global', 0, 'CEE', 1, 'global'),
|
('V', 'Intracomunitaria global', 0, 'CEE', 1, 'global'),
|
||||||
('M', 'Múltiple nacional', 1, 'NATIONAL', 0, 'quick'),
|
('M', 'Múltiple nacional', 1, 'NATIONAL', 0, 'multiple'),
|
||||||
('R', 'Rectificativa', 1, 'NATIONAL', 0, NULL),
|
('R', 'Rectificativa', 1, 'NATIONAL', 0, NULL),
|
||||||
('E', 'Exportación rápida', 0, 'WORLD', 0, 'quick');
|
('E', 'Exportación rápida', 0, 'WORLD', 0, 'quick');
|
||||||
|
|
||||||
|
|
|
@ -1,26 +1,32 @@
|
||||||
DELIMITER $$
|
DELIMITER $$
|
||||||
CREATE OR REPLACE DEFINER=`root`@`localhost` FUNCTION `vn`.`invoiceSerial`(vClientFk INT, vCompanyFk INT, vType CHAR(1))
|
CREATE OR REPLACE DEFINER=`root`@`localhost` FUNCTION `vn`.`invoiceSerial`(vClientFk INT, vCompanyFk INT, vType CHAR(15))
|
||||||
RETURNS char(1) CHARSET utf8mb3 COLLATE utf8mb3_general_ci
|
RETURNS char(2) CHARSET utf8mb3 COLLATE utf8mb3_general_ci
|
||||||
DETERMINISTIC
|
DETERMINISTIC
|
||||||
BEGIN
|
BEGIN
|
||||||
/**
|
/**
|
||||||
* Obtiene la serie de de una factura
|
* Obtiene la serie de una factura
|
||||||
* dependiendo del area del cliente.
|
* dependiendo del area del cliente.
|
||||||
*
|
*
|
||||||
* @param vClientFk Id del cliente
|
* @param vClientFk Id del cliente
|
||||||
* @param vCompanyFk Id de la empresa
|
* @param vCompanyFk Id de la empresa
|
||||||
* @param vType Tipo de factura ["R", "M", "G"]
|
* @param vType Tipo de factura ['global','multiple','quick']
|
||||||
* @return Serie de la factura
|
* @return vSerie de la factura
|
||||||
*/
|
*/
|
||||||
DECLARE vTaxArea VARCHAR(25);
|
DECLARE vTaxArea VARCHAR(25) COLLATE utf8mb3_general_ci;
|
||||||
DECLARE vSerie CHAR(1);
|
DECLARE vSerie CHAR(2);
|
||||||
|
|
||||||
IF (SELECT hasInvoiceSimplified FROM client WHERE id = vClientFk) THEN
|
IF (SELECT hasInvoiceSimplified FROM client WHERE id = vClientFk) THEN
|
||||||
RETURN 'S';
|
RETURN 'S';
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
SELECT clientTaxArea(vClientFk, vCompanyFk) INTO vTaxArea;
|
SELECT addressTaxArea(defaultAddressFk, vCompanyFk) INTO vTaxArea
|
||||||
SELECT invoiceSerialArea(vType,vTaxArea) INTO vSerie;
|
FROM client
|
||||||
|
WHERE id = vClientFk;
|
||||||
|
|
||||||
|
SELECT code INTO vSerie
|
||||||
|
FROM invoiceOutSerial
|
||||||
|
WHERE `type` = vType AND taxAreaFk = vTaxArea;
|
||||||
|
|
||||||
RETURN vSerie;
|
RETURN vSerie;
|
||||||
END$$
|
END$$
|
||||||
DELIMITER ;
|
DELIMITER ;
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
DELIMITER $$
|
|
||||||
CREATE OR REPLACE DEFINER=`root`@`localhost` FUNCTION `vn`.`invoiceSerialArea`(vType CHAR(1), vTaxArea VARCHAR(25))
|
|
||||||
RETURNS char(1) CHARSET utf8mb3 COLLATE utf8mb3_unicode_ci
|
|
||||||
DETERMINISTIC
|
|
||||||
BEGIN
|
|
||||||
DECLARE vSerie CHAR(1);
|
|
||||||
|
|
||||||
IF vType = 'R' THEN
|
|
||||||
SELECT
|
|
||||||
CASE vTaxArea
|
|
||||||
WHEN 'CEE' THEN 'H'
|
|
||||||
WHEN 'WORLD' THEN 'E'
|
|
||||||
ELSE 'T'
|
|
||||||
END INTO vSerie;
|
|
||||||
-- Factura multiple
|
|
||||||
ELSEIF vType = 'M' THEN
|
|
||||||
SELECT
|
|
||||||
CASE vTaxArea
|
|
||||||
WHEN 'CEE' THEN 'H'
|
|
||||||
WHEN 'WORLD' THEN 'E'
|
|
||||||
ELSE 'M'
|
|
||||||
END INTO vSerie;
|
|
||||||
-- Factura global
|
|
||||||
ELSEIF vType = 'G' THEN
|
|
||||||
SELECT
|
|
||||||
CASE vTaxArea
|
|
||||||
WHEN 'CEE' THEN 'V'
|
|
||||||
WHEN 'WORLD' THEN 'X'
|
|
||||||
ELSE 'A'
|
|
||||||
END INTO vSerie;
|
|
||||||
END IF;
|
|
||||||
RETURN vSerie;
|
|
||||||
END$$
|
|
||||||
DELIMITER ;
|
|
|
@ -97,7 +97,7 @@ BEGIN
|
||||||
AND (vCorrectingSerial = vSerial OR NOT hasAnyNegativeBase())
|
AND (vCorrectingSerial = vSerial OR NOT hasAnyNegativeBase())
|
||||||
THEN
|
THEN
|
||||||
|
|
||||||
-- el trigger añade el siguiente Id_Factura correspondiente a la vSerial
|
-- el trigger añade el siguiente ref correspondiente a la vSerial
|
||||||
INSERT INTO invoiceOut(
|
INSERT INTO invoiceOut(
|
||||||
ref,
|
ref,
|
||||||
serial,
|
serial,
|
||||||
|
|
|
@ -90,7 +90,7 @@ BEGIN
|
||||||
IF vIsTaxDataChecked THEN
|
IF vIsTaxDataChecked THEN
|
||||||
CALL invoiceOut_newFromClient(
|
CALL invoiceOut_newFromClient(
|
||||||
vClientFk,
|
vClientFk,
|
||||||
(SELECT invoiceSerial(vClientFk, vCompanyFk, 'M')),
|
(SELECT invoiceSerial(vClientFk, vCompanyFk, 'multiple')),
|
||||||
vShipped,
|
vShipped,
|
||||||
vCompanyFk,
|
vCompanyFk,
|
||||||
NULL,
|
NULL,
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`roadmap_beforeInsert`
|
||||||
|
BEFORE INSERT ON `roadmap`
|
||||||
|
FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
IF NEW.driver1Fk IS NOT NULL THEN
|
||||||
|
SET NEW.driverName = (SELECT firstName FROM worker WHERE id = NEW.driver1Fk);
|
||||||
|
ELSE
|
||||||
|
SET NEW.driverName = NULL;
|
||||||
|
END IF;
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -0,0 +1,12 @@
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`roadmap_beforeUpdate`
|
||||||
|
BEFORE UPDATE ON `roadmap`
|
||||||
|
FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
IF NEW.driver1Fk IS NOT NULL THEN
|
||||||
|
SET NEW.driverName = (SELECT firstName FROM worker WHERE id = NEW.driver1Fk);
|
||||||
|
ELSE
|
||||||
|
SET NEW.driverName = NULL;
|
||||||
|
END IF;
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -0,0 +1,4 @@
|
||||||
|
ALTER TABLE vn.invoiceOutSerial
|
||||||
|
MODIFY COLUMN `type` enum('global','quick','multiple') CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci DEFAULT NULL NULL;
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX invoiceOutSerial_taxAreaFk_IDX USING BTREE ON vn.invoiceOutSerial (taxAreaFk,`type`);
|
|
@ -0,0 +1,3 @@
|
||||||
|
UPDATE vn.invoiceOutSerial
|
||||||
|
SET `type`='multiple'
|
||||||
|
WHERE `description` LIKE '%Múltiple%';
|
|
@ -0,0 +1,6 @@
|
||||||
|
ALTER TABLE vn.roadmap
|
||||||
|
ADD COLUMN m3 INT UNSIGNED NULL,
|
||||||
|
ADD COLUMN driver2Fk INT UNSIGNED NULL,
|
||||||
|
ADD COLUMN driver1Fk INT UNSIGNED NULL,
|
||||||
|
ADD CONSTRAINT roadmap_worker_FK FOREIGN KEY (driver1Fk) REFERENCES vn.worker(id) ON DELETE RESTRICT ON UPDATE CASCADE,
|
||||||
|
ADD CONSTRAINT roadmap_worker_FK_2 FOREIGN KEY (driver2Fk) REFERENCES vn.worker(id) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
@ -46,7 +46,7 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
filter = mergeFilters(args.filter, {where});
|
const filter = mergeFilters(args.filter, {where});
|
||||||
|
|
||||||
const stmt = new ParameterizedSQL(
|
const stmt = new ParameterizedSQL(
|
||||||
`SELECT i.serial, SUM(IF(i.isBooked, 0,1)) pending, COUNT(*) total
|
`SELECT i.serial, SUM(IF(i.isBooked, 0,1)) pending, COUNT(*) total
|
||||||
|
|
|
@ -75,7 +75,7 @@ module.exports = Self => {
|
||||||
AND c.isTaxDataChecked
|
AND c.isTaxDataChecked
|
||||||
AND c.isActive
|
AND c.isActive
|
||||||
AND NOT t.isDeleted
|
AND NOT t.isDeleted
|
||||||
GROUP BY c.id, IF(c.hasToInvoiceByAddress, a.id, TRUE)
|
GROUP BY IF(c.hasToInvoiceByAddress, a.id, c.id)
|
||||||
HAVING SUM(t.totalWithVat) > 0;`;
|
HAVING SUM(t.totalWithVat) > 0;`;
|
||||||
|
|
||||||
const addresses = await Self.rawSql(query, [
|
const addresses = await Self.rawSql(query, [
|
||||||
|
|
|
@ -28,6 +28,11 @@ module.exports = Self => {
|
||||||
type: 'number',
|
type: 'number',
|
||||||
description: 'The company id to invoice',
|
description: 'The company id to invoice',
|
||||||
required: true
|
required: true
|
||||||
|
}, {
|
||||||
|
arg: 'serialType',
|
||||||
|
type: 'string',
|
||||||
|
description: 'Invoice serial number type (see vn.invoiceOutSerial.type enum)',
|
||||||
|
required: true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
returns: {
|
returns: {
|
||||||
|
@ -39,12 +44,10 @@ module.exports = Self => {
|
||||||
verb: 'POST'
|
verb: 'POST'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.invoiceClient = async(ctx, options) => {
|
Self.invoiceClient = async(ctx, options) => {
|
||||||
const args = ctx.args;
|
const args = ctx.args;
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
options = typeof options == 'object'
|
options = typeof options === 'object' ? {...options} : {};
|
||||||
? Object.assign({}, options) : {};
|
|
||||||
options.userId = ctx.req.accessToken.userId;
|
options.userId = ctx.req.accessToken.userId;
|
||||||
|
|
||||||
let tx;
|
let tx;
|
||||||
|
@ -74,10 +77,9 @@ module.exports = Self => {
|
||||||
], options);
|
], options);
|
||||||
}
|
}
|
||||||
|
|
||||||
const invoiceType = 'G';
|
|
||||||
const invoiceId = await models.Ticket.makeInvoice(
|
const invoiceId = await models.Ticket.makeInvoice(
|
||||||
ctx,
|
ctx,
|
||||||
invoiceType,
|
args.serialType,
|
||||||
args.companyFk,
|
args.companyFk,
|
||||||
args.invoiceDate,
|
args.invoiceDate,
|
||||||
null,
|
null,
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
|
||||||
|
describe('InvoiceOut clientsToInvoice()', () => {
|
||||||
|
const userId = 1;
|
||||||
|
const clientId = 1101;
|
||||||
|
const companyFk = 442;
|
||||||
|
const maxShipped = new Date();
|
||||||
|
maxShipped.setMonth(11);
|
||||||
|
maxShipped.setDate(31);
|
||||||
|
maxShipped.setHours(23, 59, 59, 999);
|
||||||
|
const invoiceDate = new Date();
|
||||||
|
const activeCtx = {
|
||||||
|
getLocale: () => {
|
||||||
|
return 'en';
|
||||||
|
},
|
||||||
|
accessToken: {userId: userId},
|
||||||
|
__: value => {
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
headers: {origin: 'http://localhost'}
|
||||||
|
};
|
||||||
|
const ctx = {req: activeCtx};
|
||||||
|
|
||||||
|
it('should return a list of clients to invoice', async() => {
|
||||||
|
spyOn(models.InvoiceOut, 'rawSql').and.callFake(query => {
|
||||||
|
if (query.includes('ticketPackaging_add'))
|
||||||
|
return Promise.resolve(true);
|
||||||
|
else if (query.includes('SELECT c.id clientId')) {
|
||||||
|
return Promise.resolve([
|
||||||
|
{
|
||||||
|
clientId: clientId,
|
||||||
|
clientName: 'Test Client',
|
||||||
|
id: 1,
|
||||||
|
nickname: 'Address 1'
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const tx = await models.InvoiceOut.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const addresses = await models.InvoiceOut.clientsToInvoice(
|
||||||
|
ctx, clientId, invoiceDate, maxShipped, companyFk, options);
|
||||||
|
|
||||||
|
expect(addresses.length).toBeGreaterThan(0);
|
||||||
|
expect(addresses[0].clientId).toBe(clientId);
|
||||||
|
expect(addresses[0].clientName).toBe('Test Client');
|
||||||
|
expect(addresses[0].id).toBe(1);
|
||||||
|
expect(addresses[0].nickname).toBe('Address 1');
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle errors and rollback transaction', async() => {
|
||||||
|
spyOn(models.InvoiceOut, 'rawSql').and.callFake(() => {
|
||||||
|
return Promise.reject(new Error('Test Error'));
|
||||||
|
});
|
||||||
|
|
||||||
|
const tx = await models.InvoiceOut.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
try {
|
||||||
|
await models.InvoiceOut.clientsToInvoice(ctx, clientId, invoiceDate, maxShipped, companyFk, options);
|
||||||
|
} catch (e) {
|
||||||
|
expect(e.message).toBe('Test Error');
|
||||||
|
await tx.rollback();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,16 +1,16 @@
|
||||||
const models = require('vn-loopback/server/server').models;
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
describe('InvoiceOut invoiceClient()', () => {
|
describe('InvoiceOut invoiceClient()', () => {
|
||||||
const userId = 1;
|
const userId = 1;
|
||||||
const clientId = 1101;
|
const clientId = 1101;
|
||||||
const addressId = 121;
|
const addressFk = 121;
|
||||||
const companyFk = 442;
|
const companyFk = 442;
|
||||||
const minShipped = Date.vnNew();
|
const minShipped = Date.vnNew();
|
||||||
minShipped.setFullYear(minShipped.getFullYear() - 1);
|
minShipped.setFullYear(minShipped.getFullYear() - 1);
|
||||||
minShipped.setMonth(1);
|
minShipped.setMonth(1);
|
||||||
minShipped.setDate(1);
|
minShipped.setDate(1);
|
||||||
minShipped.setHours(0, 0, 0, 0);
|
minShipped.setHours(0, 0, 0, 0);
|
||||||
const invoiceSerial = 'A';
|
|
||||||
const activeCtx = {
|
const activeCtx = {
|
||||||
getLocale: () => {
|
getLocale: () => {
|
||||||
return 'en';
|
return 'en';
|
||||||
|
@ -23,9 +23,14 @@ describe('InvoiceOut invoiceClient()', () => {
|
||||||
|
|
||||||
};
|
};
|
||||||
const ctx = {req: activeCtx};
|
const ctx = {req: activeCtx};
|
||||||
|
beforeAll(() => {
|
||||||
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
|
active: activeCtx
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should make a global invoicing', async() => {
|
it('should make a global invoicing by address and verify billing status', async() => {
|
||||||
spyOn(models.InvoiceOut, 'makePdf').and.returnValue(new Promise(resolve => resolve(true)));
|
spyOn(models.InvoiceOut, 'makePdf').and.returnValue(Promise.resolve(true));
|
||||||
spyOn(models.InvoiceOut, 'invoiceEmail');
|
spyOn(models.InvoiceOut, 'invoiceEmail');
|
||||||
|
|
||||||
const tx = await models.InvoiceOut.beginTransaction({});
|
const tx = await models.InvoiceOut.beginTransaction({});
|
||||||
|
@ -34,20 +39,96 @@ describe('InvoiceOut invoiceClient()', () => {
|
||||||
try {
|
try {
|
||||||
ctx.args = {
|
ctx.args = {
|
||||||
clientId: clientId,
|
clientId: clientId,
|
||||||
addressId: addressId,
|
addressId: addressFk,
|
||||||
invoiceDate: Date.vnNew(),
|
invoiceDate: Date.vnNew(),
|
||||||
maxShipped: Date.vnNew(),
|
maxShipped: Date.vnNew(),
|
||||||
companyFk: companyFk,
|
companyFk: companyFk,
|
||||||
minShipped: minShipped
|
serialType: 'global'
|
||||||
};
|
};
|
||||||
|
|
||||||
const invoiceOutId = await models.InvoiceOut.invoiceClient(ctx, options);
|
const invoiceOutId = await models.InvoiceOut.invoiceClient(ctx, options);
|
||||||
|
|
||||||
const invoiceOut = await models.InvoiceOut.findById(invoiceOutId, null, options);
|
const invoiceOut = await models.InvoiceOut.findById(invoiceOutId, null, options);
|
||||||
const [firstTicket] = await models.Ticket.find({
|
|
||||||
|
expect(invoiceOutId).toBeGreaterThan(0);
|
||||||
|
|
||||||
|
const allClientTickets = await models.Ticket.find({
|
||||||
|
where: {
|
||||||
|
clientFk: clientId,
|
||||||
|
or: [
|
||||||
|
{refFk: null},
|
||||||
|
{refFk: invoiceOut.ref}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}, options);
|
||||||
|
|
||||||
|
const billedTickets = await models.Ticket.find({
|
||||||
where: {refFk: invoiceOut.ref}
|
where: {refFk: invoiceOut.ref}
|
||||||
}, options);
|
}, options);
|
||||||
|
|
||||||
|
const allBilledTicketsHaveCorrectAddress = billedTickets.every(ticket => ticket.addressFk === addressFk);
|
||||||
|
|
||||||
|
expect(allBilledTicketsHaveCorrectAddress).toBe(true);
|
||||||
|
|
||||||
|
const addressTickets = allClientTickets.filter(ticket => ticket.addressFk === addressFk);
|
||||||
|
|
||||||
|
const allAddressTicketsBilled = addressTickets.every(ticket => ticket.refFk === invoiceOut.ref);
|
||||||
|
|
||||||
|
expect(allAddressTicketsBilled).toBe(true);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should invoice all tickets regardless of address when hasToInvoiceByAddress is false', async() => {
|
||||||
|
spyOn(models.InvoiceOut, 'makePdf').and.returnValue(Promise.resolve(true));
|
||||||
|
spyOn(models.InvoiceOut, 'invoiceEmail');
|
||||||
|
|
||||||
|
const tx = await models.InvoiceOut.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const client = await models.Client.findById(clientId, null, options);
|
||||||
|
await client.updateAttribute('hasToInvoiceByAddress', false, options);
|
||||||
|
|
||||||
|
ctx.args = {
|
||||||
|
clientId: clientId,
|
||||||
|
invoiceDate: Date.vnNew(),
|
||||||
|
maxShipped: Date.vnNew(),
|
||||||
|
companyFk: companyFk,
|
||||||
|
serialType: 'global'
|
||||||
|
};
|
||||||
|
|
||||||
|
const invoiceOutId = await models.InvoiceOut.invoiceClient(ctx, options);
|
||||||
|
|
||||||
|
const invoiceOut = await models.InvoiceOut.findById(invoiceOutId, null, options);
|
||||||
|
|
||||||
expect(invoiceOutId).toBeGreaterThan(0);
|
expect(invoiceOutId).toBeGreaterThan(0);
|
||||||
expect(firstTicket.refFk).toContain(invoiceSerial);
|
|
||||||
|
const allClientTickets = await models.Ticket.find({
|
||||||
|
where: {
|
||||||
|
clientFk: clientId,
|
||||||
|
or: [
|
||||||
|
{refFk: null},
|
||||||
|
{refFk: invoiceOut.ref}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}, options);
|
||||||
|
|
||||||
|
const billedTickets = await models.Ticket.find({
|
||||||
|
where: {refFk: invoiceOut.ref}
|
||||||
|
}, options);
|
||||||
|
|
||||||
|
const allTicketsBilled = allClientTickets.every(ticket => ticket.refFk === invoiceOut.ref);
|
||||||
|
|
||||||
|
expect(allTicketsBilled).toBe(true);
|
||||||
|
|
||||||
|
const billedAddresses = new Set(billedTickets.map(ticket => ticket.addressFk));
|
||||||
|
|
||||||
|
expect(billedAddresses.size).toBeGreaterThan(1);
|
||||||
|
|
||||||
await tx.rollback();
|
await tx.rollback();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
@ -20,6 +20,9 @@
|
||||||
},
|
},
|
||||||
"isCEE": {
|
"isCEE": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"relations": {
|
"relations": {
|
||||||
|
|
|
@ -114,7 +114,7 @@ module.exports = Self => {
|
||||||
LEFT JOIN itemTaxCountry itc ON itc.itemFk = i.id
|
LEFT JOIN itemTaxCountry itc ON itc.itemFk = i.id
|
||||||
AND itc.countryFk = su.countryFk
|
AND itc.countryFk = su.countryFk
|
||||||
LEFT JOIN vn.invoiceOutSerial ios ON ios.taxAreaFk = 'WORLD'
|
LEFT JOIN vn.invoiceOutSerial ios ON ios.taxAreaFk = 'WORLD'
|
||||||
AND ios.code = invoiceSerial(t.clientFk, t.companyFk, 'M')
|
AND ios.code = invoiceSerial(t.clientFk, t.companyFk, 'multiple')
|
||||||
WHERE (al.code = 'PACKED' OR (am.code = 'refund' AND al.code <> 'delivered'))
|
WHERE (al.code = 'PACKED' OR (am.code = 'refund' AND al.code <> 'delivered'))
|
||||||
AND DATE(t.shipped) BETWEEN ? - INTERVAL 2 DAY AND util.dayEnd(?)
|
AND DATE(t.shipped) BETWEEN ? - INTERVAL 2 DAY AND util.dayEnd(?)
|
||||||
AND t.refFk IS NULL
|
AND t.refFk IS NULL
|
||||||
|
|
|
@ -95,7 +95,7 @@ module.exports = function(Self) {
|
||||||
FROM vn.ticket
|
FROM vn.ticket
|
||||||
WHERE id IN (?)
|
WHERE id IN (?)
|
||||||
`, [ticketsIds], myOptions);
|
`, [ticketsIds], myOptions);
|
||||||
return models.Ticket.makeInvoice(ctx, 'R', companyId, Date.vnNew(), invoiceCorrection, myOptions);
|
return models.Ticket.makeInvoice(ctx, 'quick', companyId, Date.vnNew(), invoiceCorrection, myOptions);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
describe('ticket makeInvoice()', () => {
|
describe('ticket makeInvoice()', () => {
|
||||||
const userId = 19;
|
const userId = 19;
|
||||||
const invoiceType = 'R';
|
const invoiceType = 'quick';
|
||||||
const companyFk = 442;
|
const companyFk = 442;
|
||||||
const invoiceDate = Date.vnNew();
|
const invoiceDate = Date.vnNew();
|
||||||
const activeCtx = {
|
const activeCtx = {
|
||||||
|
|
Loading…
Reference in New Issue