Merge branch 'dev' into 7880-hedera.order_confirmWithUserTranslations
gitea/salix/pipeline/pr-dev This commit looks good
Details
gitea/salix/pipeline/pr-dev This commit looks good
Details
This commit is contained in:
commit
ab5cf0f497
|
@ -1922,7 +1922,7 @@ INSERT INTO `vn`.`claimDestination`(`id`, `description`, `addressFk`)
|
|||
|
||||
INSERT INTO `vn`.`claimDevelopment`(`id`, `claimFk`, `claimResponsibleFk`, `workerFk`, `claimReasonFk`, `claimResultFk`, `claimRedeliveryFk`, `claimDestinationFk`)
|
||||
VALUES
|
||||
(1, 1, 1, 21, 1, 1, 2, 5),
|
||||
(1, 1, 1, 21, 7, 1, 2, 5),
|
||||
(2, 1, 2, 21, 7, 2, 2, 5),
|
||||
(3, 2, 7, 21, 9, 3, 2, 5),
|
||||
(4, 3, 7, 21, 15, 8, 2, 5),
|
||||
|
@ -4038,6 +4038,11 @@ INSERT IGNORE INTO vn.saySimpleConfig (url, defaultChannel)
|
|||
INSERT INTO vn.workerIrpf (workerFk,spouseNif, geographicMobilityDate)
|
||||
VALUES (1106,'26493101E','2019-09-20');
|
||||
|
||||
INSERT INTO vn.referenceRate (currencyFk, dated, value)
|
||||
VALUES (2, '2000-12-01', 1.0495),
|
||||
(2, '2001-01-01', 1.0531),
|
||||
(2, '2001-02-01', 7.6347);
|
||||
|
||||
INSERT IGNORE INTO vn.osrmConfig (id,url,tolerance)
|
||||
VALUES (1,'https://router.project-osrm.org', 0.002);
|
||||
|
||||
|
|
|
@ -4,10 +4,10 @@ BEGIN
|
|||
/**
|
||||
* Traslada la info de contabilidad relacionada con las facturas recibidas
|
||||
*
|
||||
* @vInvoiceInFk Factura recibida
|
||||
* @vXDiarioFk Id tabla XDiario
|
||||
* @param vInvoiceInFk Factura recibida
|
||||
* @param vXDiarioFk Id tabla XDiario
|
||||
*/
|
||||
DECLARE vInvoiceInOriginalFk INT;
|
||||
DECLARE vInvoiceInOriginalFk INT;
|
||||
DECLARE vDone BOOL DEFAULT FALSE;
|
||||
DECLARE vBase DOUBLE;
|
||||
DECLARE vVat DOUBLE;
|
||||
|
@ -205,9 +205,9 @@ BEGIN
|
|||
WHERE correctingFk = vInvoiceInFk;
|
||||
|
||||
IF vInvoiceInOriginalFk THEN
|
||||
|
||||
UPDATE movContaIVA mci
|
||||
JOIN vn.invoiceInRefund iir ON iir.invoiceInRefundFk = vInvoiceInFk
|
||||
JOIN vn.invoiceInCorrection iic ON iic.correctingFk = vInvoiceInFk
|
||||
JOIN vn.siiTypeInvoiceIn st ON st.id = iic.siiTypeInvoiceInFk
|
||||
JOIN (SELECT issued,
|
||||
SUM(sub.taxableBase) taxableBase,
|
||||
SUM(ROUND((sub.taxableBase * sub.PorcentajeIva) / 100 , 2)) vat
|
||||
|
@ -216,7 +216,7 @@ BEGIN
|
|||
ti.PorcentajeIva
|
||||
FROM vn.invoiceIn i
|
||||
JOIN vn.invoiceInTax iit ON iit.invoiceInFk = i.id
|
||||
JOIN sage.TiposIva ti ON ti.CodigoIva = iit.taxTypeSageFk
|
||||
JOIN TiposIva ti ON ti.CodigoIva = iit.taxTypeSageFk
|
||||
WHERE i.id = vInvoiceInOriginalFk
|
||||
GROUP BY ti.CodigoIva)sub
|
||||
)invoiceInOriginal
|
||||
|
@ -229,7 +229,6 @@ BEGIN
|
|||
mci.CuotaIvaOriginal = invoiceInOriginal.vat,
|
||||
mci.ClaveOperacionFactura = co.ClaveOperacionFactura_
|
||||
WHERE mci.id = vXDiarioFk;
|
||||
|
||||
END IF;
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
|
|
@ -169,6 +169,7 @@ BEGIN
|
|||
UPDATE movContaIVA mci
|
||||
JOIN vn.invoiceOut i ON i.id = vInvoiceOutCorrectedFk
|
||||
JOIN vn.invoiceCorrection ic ON ic.correctedFk = vInvoiceOutCorrectedFk
|
||||
JOIN vn.siiTypeInvoiceOut st ON st.id = ic.siiTypeInvoiceOutFk
|
||||
JOIN (SELECT SUM(IF(IFNULL(e.vatFk, TRUE), iot.taxableBase, 0)) taxableBase,
|
||||
SUM(IF(IFNULL(e.vatFk, TRUE), iot.vat, 0)) vat,
|
||||
SUM(IF(IFNULL(e.vatFk, TRUE), 0, iot.vat)) equ
|
||||
|
@ -177,8 +178,8 @@ BEGIN
|
|||
WHERE iot.invoiceOutFk = vInvoiceOutCorrectedFk
|
||||
) tax
|
||||
JOIN ClavesOperacion co ON co.Descripcion = 'Factura rectificativa'
|
||||
SET mci.TipoRectificativa = 2,
|
||||
mci.ClaseAbonoRectificativas = 1,
|
||||
SET mci.TipoRectificativa = ic.cplusRectificationTypeFk,
|
||||
mci.ClaseAbonoRectificativas = REGEXP_REPLACE(st.`code`, '[^0-9]', ''),
|
||||
mci.FechaFacturaOriginal = i.issued,
|
||||
mci.FechaOperacion = i.issued,
|
||||
mci.BaseImponibleOriginal = tax.taxableBase,
|
||||
|
|
|
@ -43,7 +43,7 @@ BEGIN
|
|||
ii.cplusTaxBreakFk,
|
||||
ii.cplusSubjectOpFk,
|
||||
ii.siiTypeInvoiceInFk,
|
||||
ii.cplusRectificationTypeFk,
|
||||
ic.cplusRectificationTypeFk,
|
||||
ii.booked,
|
||||
IFNULL(a.isUeeMember, c.isUeeMember) isUeeMember,
|
||||
(c.id = cc.id) isSameCountry,
|
||||
|
@ -66,6 +66,7 @@ BEGIN
|
|||
e.name expenseName
|
||||
FROM invoiceIn ii
|
||||
JOIN supplier s ON s.id = ii.supplierFk
|
||||
LEFT JOIN invoiceInCorrection ic ON ic.correctingFk = ii.id
|
||||
LEFT JOIN province p ON p.id = s.provinceFk
|
||||
LEFT JOIN autonomy a ON a.id = p.autonomyFk
|
||||
JOIN country c ON c.id = s.countryFk
|
||||
|
|
|
@ -52,7 +52,8 @@ BEGIN
|
|||
IFNULL(dest.nickname, origin.nickname) nickname,
|
||||
dest.landed,
|
||||
dest.preparation,
|
||||
origin.departmentFk
|
||||
origin.departmentFk,
|
||||
origin.saleClonedFk
|
||||
FROM (
|
||||
SELECT s.ticketFk,
|
||||
c.salesPersonFk workerFk,
|
||||
|
@ -73,11 +74,13 @@ BEGIN
|
|||
t.warehouseFk,
|
||||
t.companyFk,
|
||||
t.agencyModeFk,
|
||||
wd.departmentFk
|
||||
wd.departmentFk,
|
||||
sc.saleClonedFk
|
||||
FROM ticket t
|
||||
JOIN client c ON c.id = t.clientFk
|
||||
JOIN workerDepartment wd ON wd.workerFk = c.salesPersonFk
|
||||
JOIN sale s ON s.ticketFk = t.id
|
||||
LEFT JOIN saleCloned sc ON sc.saleClonedFk = s.id
|
||||
JOIN saleVolume sv ON sv.saleFk = s.id
|
||||
JOIN item i ON i.id = s.itemFk
|
||||
JOIN ticketState ts ON ts.ticketFk = t.id
|
||||
|
|
|
@ -3,24 +3,30 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`invoiceIn_afterUpdate`
|
|||
AFTER UPDATE ON `invoiceIn`
|
||||
FOR EACH ROW
|
||||
BEGIN
|
||||
IF NEW.issued != OLD.issued
|
||||
OR NEW.currencyFk != OLD.currencyFk THEN
|
||||
DECLARE vIsEuro BOOL;
|
||||
|
||||
SELECT `code` = 'EUR' INTO vIsEuro
|
||||
FROM currency
|
||||
WHERE id = NEW.currencyFk;
|
||||
|
||||
IF (NOT NEW.issued <=> OLD.issued
|
||||
OR NEW.currencyFk <> OLD.currencyFk) THEN
|
||||
|
||||
UPDATE invoiceInTax iit
|
||||
JOIN invoiceIn ii ON ii.id = iit.invoiceInFk
|
||||
LEFT JOIN referenceRate rr ON rr.dated = ii.issued
|
||||
AND rr.currencyFk = ii.currencyFk
|
||||
SET iit.taxableBase = IF(iit.foreignValue IS NULL, iit.taxableBase, iit.foreignValue / rr.value)
|
||||
SET iit.taxableBase = IF(vIsEuro, iit.taxableBase, iit.foreignValue / rr.value),
|
||||
iit.foreignValue = IF(vIsEuro, NULL, iit.foreignValue)
|
||||
WHERE ii.id = NEW.id;
|
||||
|
||||
UPDATE invoiceInDueDay iidd
|
||||
JOIN invoiceIn ii ON ii.id = iidd.invoiceInFk
|
||||
LEFT JOIN referenceRate rr ON rr.dated = ii.issued
|
||||
AND rr.currencyFk = ii.currencyFk
|
||||
SET iidd.amount = IF(iidd.foreignValue IS NULL, iidd.amount, iidd.foreignValue / rr.value)
|
||||
SET iidd.amount = IF(vIsEuro, iidd.amount, iidd.foreignValue / rr.value),
|
||||
iidd.foreignValue = IF(vIsEuro, NULL, iidd.foreignValue)
|
||||
WHERE ii.id = NEW.id;
|
||||
|
||||
END IF;
|
||||
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
USE vn;
|
||||
|
||||
DROP TRIGGER IF EXISTS invoiceIn_beforeUpdate;
|
||||
|
||||
UPDATE invoiceIn
|
||||
SET cplusRectificationTypeFk = NULL
|
||||
WHERE cplusRectificationTypeFk = 1;
|
||||
|
||||
DELETE IGNORE FROM cplusRectificationType WHERE id = 1;
|
||||
|
||||
UPDATE cplusRectificationType
|
||||
SET id = 1
|
||||
WHERE id = 3;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`invoiceIn_beforeUpdate`
|
||||
BEFORE UPDATE ON `invoiceIn`
|
||||
FOR EACH ROW
|
||||
BEGIN
|
||||
DECLARE vWithholdingSageFk INT;
|
||||
|
||||
IF NOT (NEW.supplierRef <=> OLD.supplierRef) AND NOT util.checkPrintableChars(NEW.supplierRef) THEN
|
||||
CALL util.throw('The invoiceIn reference contains invalid characters');
|
||||
END IF;
|
||||
|
||||
SET NEW.editorFk = account.myUser_getId();
|
||||
|
||||
IF (SELECT COUNT(*) FROM invoiceIn
|
||||
WHERE supplierRef = NEW.supplierRef
|
||||
AND supplierFk = NEW.supplierFk
|
||||
AND YEAR(issued) = YEAR(NEW.issued)
|
||||
AND id <> NEW.id
|
||||
) THEN
|
||||
CALL util.throw('reference duplicated');
|
||||
END IF;
|
||||
|
||||
IF NEW.supplierFk != OLD.supplierFk THEN
|
||||
CALL supplier_checkIsActive(NEW.supplierFk);
|
||||
SELECT withholdingSageFk INTO vWithholdingSageFk
|
||||
FROM supplier
|
||||
WHERE id = NEW.supplierFk;
|
||||
SET NEW.withholdingSageFk = vWithholdingSageFk;
|
||||
END IF;
|
||||
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
INSERT INTO salix.ACL (model, property, accessType, permission, principalType, principalId)
|
||||
VALUES('SiiTypeInvoiceIn', 'find', 'READ', 'ALLOW', 'ROLE', 'salesPerson');
|
||||
|
||||
DROP TABLE IF EXISTS vn.invoiceInCorrection;
|
||||
|
||||
CREATE TABLE `invoiceInCorrection` (
|
||||
`correctingFk` mediumint(8) unsigned NOT NULL COMMENT 'Factura rectificativa',
|
||||
`correctedFk` mediumint(8) unsigned NOT NULL COMMENT 'Factura rectificada',
|
||||
`cplusRectificationTypeFk` int(10) unsigned NOT NULL,
|
||||
`siiTypeInvoiceInFk` int(10) unsigned NOT NULL,
|
||||
`invoiceCorrectionTypeFk` int(11) NOT NULL DEFAULT 3,
|
||||
PRIMARY KEY (`correctingFk`),
|
||||
KEY `invoiceInCorrection_correctedFk` (`correctedFk`),
|
||||
KEY `invoiceInCorrection_cplusRectificationTypeFk` (`cplusRectificationTypeFk`),
|
||||
KEY `invoiceInCorrection_siiTypeInvoiceIn` (`siiTypeInvoiceInFk`),
|
||||
KEY `invoiceInCorrection_invoiceCorrectionTypeFk` (`invoiceCorrectionTypeFk`),
|
||||
CONSTRAINT `invoiceInCorrection_correctedFk` FOREIGN KEY (`correctedFk`) REFERENCES `invoiceIn` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
CONSTRAINT `invoiceInCorrection_correctingFk` FOREIGN KEY (`correctingFk`) REFERENCES `invoiceIn` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
CONSTRAINT `invoiceInCorrection_cplusRectificationTypeFk` FOREIGN KEY (`cplusRectificationTypeFk`) REFERENCES `cplusRectificationType` (`id`) ON UPDATE CASCADE,
|
||||
CONSTRAINT `invoiceInCorrection_invoiceCorrectionTypeFk` FOREIGN KEY (`invoiceCorrectionTypeFk`) REFERENCES `invoiceCorrectionType` (`id`) ON UPDATE CASCADE,
|
||||
CONSTRAINT `invoiceInCorrection_siiTypeInvoiceIn` FOREIGN KEY (`siiTypeInvoiceInFk`) REFERENCES `siiTypeInvoiceIn` (`id`) ON UPDATE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
|
@ -80,6 +80,12 @@ module.exports = Self => {
|
|||
description: 'The claimResponsible id',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'zoneFk',
|
||||
type: 'string',
|
||||
description: 'The zone name',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'myTeam',
|
||||
type: 'boolean',
|
||||
|
@ -174,6 +180,8 @@ module.exports = Self => {
|
|||
to.setHours(23, 59, 59, 999);
|
||||
|
||||
return {'cl.created': {between: [value, to]}};
|
||||
case 'zoneFk':
|
||||
return {'t.zoneFk': value};
|
||||
case 'myTeam':
|
||||
if (value)
|
||||
return {'cl.workerFk': {inq: teamMembersId}};
|
||||
|
@ -195,11 +203,15 @@ module.exports = Self => {
|
|||
u.name AS workerName,
|
||||
cs.code stateCode,
|
||||
cs.description stateDescription,
|
||||
cl.created
|
||||
cl.created,
|
||||
z.name zoneName,
|
||||
z.id zoneId
|
||||
FROM claim cl
|
||||
LEFT JOIN client c ON c.id = cl.clientFk
|
||||
LEFT JOIN account.user u ON u.id = cl.workerFk
|
||||
LEFT JOIN claimState cs ON cs.id = cl.claimStateFk`
|
||||
LEFT JOIN claimState cs ON cs.id = cl.claimStateFk
|
||||
LEFT JOIN ticket t ON t.id = cl.ticketFk
|
||||
LEFT JOIN zone z ON z.id = t.zoneFk`
|
||||
);
|
||||
|
||||
stmt.merge(conn.makeSuffix(filter));
|
||||
|
|
|
@ -44,7 +44,7 @@ module.exports = Self => {
|
|||
correctingFk: clone.id,
|
||||
correctedFk: id,
|
||||
cplusRectificationTypeFk: invoiceType,
|
||||
siiTypeInvoiceOutFk: invoiceClass,
|
||||
siiTypeInvoiceInFk: invoiceClass,
|
||||
invoiceCorrectionTypeFk: invoiceReason
|
||||
}, myOptions);
|
||||
|
||||
|
|
|
@ -91,6 +91,10 @@ module.exports = Self => {
|
|||
{
|
||||
arg: 'supplierActivityFk',
|
||||
type: 'string',
|
||||
},
|
||||
{
|
||||
arg: 'companyFk',
|
||||
type: 'number',
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
|
@ -161,8 +165,8 @@ module.exports = Self => {
|
|||
: {'ii.id': {nin: correcteds.map(x => x.correctingFk)}};
|
||||
case 'correctedFk':
|
||||
return {'ii.id': {inq: correctings.map(x => x.correctingFk)}};
|
||||
case 'supplierActivityFk':
|
||||
return {'s.supplierActivityFk': value};
|
||||
case 'companyFk':
|
||||
return {'ii.companyFk': value};
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -184,7 +188,9 @@ module.exports = Self => {
|
|||
s.name supplierName,
|
||||
s.account,
|
||||
SUM(iid.amount) amount,
|
||||
sub.code awbCode
|
||||
sub.code awbCode,
|
||||
c.code,
|
||||
MIN(iid.dueDated) dueDated
|
||||
FROM invoiceIn ii
|
||||
JOIN supplier s ON s.id = ii.supplierFk
|
||||
LEFT JOIN invoiceInDueDay iid ON iid.invoiceInFk = ii.id
|
||||
|
@ -199,7 +205,8 @@ module.exports = Self => {
|
|||
GROUP BY de.duaFk
|
||||
) sub ON sub.duaFk = d.id
|
||||
LEFT JOIN company co ON co.id = ii.companyFk
|
||||
LEFT JOIN dms dm ON dm.id = ii.docFk`
|
||||
LEFT JOIN dms dm ON dm.id = ii.docFk
|
||||
JOIN company c ON c.id = ii.companyFk`,
|
||||
);
|
||||
|
||||
const sqlWhere = conn.makeWhere(filter.where);
|
||||
|
|
|
@ -15,11 +15,11 @@ describe('invoiceIn corrective()', () => {
|
|||
await tx.rollback();
|
||||
});
|
||||
|
||||
it('La función corrective debería devolver un id cuando se ejecuta correctamente', async() => {
|
||||
it('should return an id when executed correctly', async() => {
|
||||
const originalId = 1;
|
||||
const invoiceReason = 3;
|
||||
const invoiceType = 2;
|
||||
const invoiceClass = 1;
|
||||
const invoiceClass = 8;
|
||||
const cloneId = await models.InvoiceIn.corrective(ctx,
|
||||
originalId, invoiceReason, invoiceType, invoiceClass, options);
|
||||
|
||||
|
@ -30,7 +30,7 @@ describe('invoiceIn corrective()', () => {
|
|||
}, options);
|
||||
|
||||
expect(correction.cplusRectificationTypeFk).toEqual(invoiceType);
|
||||
expect(correction.siiTypeInvoiceOutFk).toEqual(invoiceClass);
|
||||
expect(correction.siiTypeInvoiceInFk).toEqual(invoiceClass);
|
||||
expect(correction.invoiceCorrectionTypeFk).toEqual(invoiceReason);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -166,4 +166,21 @@ describe('InvoiceIn filter()', () => {
|
|||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should return the invoice in matching companyFk', async() => {
|
||||
const tx = await models.InvoiceIn.beginTransaction({});
|
||||
const options = {transaction: tx};
|
||||
|
||||
try {
|
||||
const company = await models.Company.findOne({}, options);
|
||||
const invoicesByCompany = await models.InvoiceIn.find({where: {companyFk: company.id}}, options);
|
||||
const filteredInvoices = await models.InvoiceIn.filter({args: {companyFk: company.id}}, {}, options);
|
||||
|
||||
expect(filteredInvoices.length).toEqual(invoicesByCompany.length);
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
const models = require('vn-loopback/server/server').models;
|
||||
|
||||
describe('invoiceIn', () => {
|
||||
let options;
|
||||
let tx;
|
||||
const invoiceId = 1;
|
||||
const supplierId = 791;
|
||||
const currencyId = 1;
|
||||
const companyId = 442;
|
||||
|
||||
beforeEach(async() => {
|
||||
tx = await models.InvoiceIn.beginTransaction({});
|
||||
options = {transaction: tx};
|
||||
});
|
||||
|
||||
afterEach(async() => {
|
||||
await tx.rollback();
|
||||
});
|
||||
|
||||
it('should allow insert for new instance', async() => {
|
||||
const newInvoice = {
|
||||
supplierFk: supplierId,
|
||||
issued: Date.vnNew(),
|
||||
operated: Date.vnNew(),
|
||||
currencyFk: currencyId,
|
||||
companyFk: companyId,
|
||||
isBooked: false
|
||||
};
|
||||
|
||||
const createdInvoice = await models.InvoiceIn.create(newInvoice, options);
|
||||
|
||||
expect(createdInvoice).toBeDefined();
|
||||
expect(createdInvoice.id).toBeDefined();
|
||||
});
|
||||
|
||||
it('should throw an error if trying to update a booked invoice', async() => {
|
||||
const invoice = await models.InvoiceIn.findById(invoiceId, null, options);
|
||||
await invoice.updateAttribute('isBooked', true, options);
|
||||
|
||||
let error;
|
||||
try {
|
||||
await invoice.updateAttribute('supplierFk', supplierId, options);
|
||||
} catch (err) {
|
||||
error = err;
|
||||
}
|
||||
|
||||
expect(error.message).toBe('InvoiceIn is already booked');
|
||||
});
|
||||
|
||||
it('should throw an error if trying to delete a booked invoice', async() => {
|
||||
const invoice = await models.InvoiceIn.findById(invoiceId, null, options);
|
||||
await invoice.updateAttribute('isBooked', true, options);
|
||||
|
||||
let error;
|
||||
try {
|
||||
await models.InvoiceIn.deleteById(invoiceId, options);
|
||||
} catch (err) {
|
||||
error = err;
|
||||
}
|
||||
|
||||
expect(error.message).toBe('InvoiceIn is already booked');
|
||||
});
|
||||
});
|
|
@ -0,0 +1,74 @@
|
|||
const models = require('vn-loopback/server/server').models;
|
||||
|
||||
describe('invoiceInTax', () => {
|
||||
let options;
|
||||
let tx;
|
||||
const invoiceInId = 1;
|
||||
const invoiceInTaxId = 1;
|
||||
beforeEach(async() => {
|
||||
tx = await models.InvoiceInTax.beginTransaction({});
|
||||
options = {transaction: tx};
|
||||
});
|
||||
|
||||
afterEach(async() => {
|
||||
await tx.rollback();
|
||||
});
|
||||
|
||||
it('should throw an error if trying to save a tax from a booked invoice', async() => {
|
||||
const invoiceIn = await models.InvoiceIn.findById(invoiceInId, null, options);
|
||||
await invoiceIn.updateAttributes({isBooked: true}, options);
|
||||
const invoiceInTax = await models.InvoiceInTax.findById(invoiceInTaxId, null, options);
|
||||
let error;
|
||||
try {
|
||||
await invoiceInTax.updateAttribute('taxableBase', 100, options);
|
||||
} catch (err) {
|
||||
error = err;
|
||||
}
|
||||
|
||||
expect(error.message).toBe('InvoiceIn is already booked');
|
||||
});
|
||||
|
||||
it('should allow save if the invoice is not booked', async() => {
|
||||
const invoiceIn = await models.InvoiceIn.findById(invoiceInId, null, options);
|
||||
await invoiceIn.updateAttribute('isBooked', false, options);
|
||||
|
||||
const invoiceInTax = await models.InvoiceInTax.findById(invoiceInTaxId, null, options);
|
||||
await invoiceInTax.updateAttribute('taxableBase', 100, options);
|
||||
|
||||
const updatedInvoiceInTax = await models.InvoiceInTax.findById(invoiceInTaxId, null, options);
|
||||
|
||||
expect(updatedInvoiceInTax.taxableBase).toBe(100);
|
||||
});
|
||||
|
||||
it('should throw an error if trying to delete a tax from a booked invoice', async() => {
|
||||
const invoiceIn = await models.InvoiceIn.findById(invoiceInId, null, options);
|
||||
await invoiceIn.updateAttribute('isBooked', true, options);
|
||||
|
||||
let error;
|
||||
try {
|
||||
await models.InvoiceInTax.destroyById(invoiceInTaxId, options);
|
||||
} catch (err) {
|
||||
error = err;
|
||||
}
|
||||
|
||||
expect(error).toBeDefined();
|
||||
expect(error.message).toBe('InvoiceIn is already booked');
|
||||
});
|
||||
|
||||
it('should allow delete if the invoice is not booked', async() => {
|
||||
const invoiceIn = await models.InvoiceIn.findById(invoiceInId, null, options);
|
||||
await invoiceIn.updateAttribute('isBooked', false, options);
|
||||
|
||||
let error;
|
||||
try {
|
||||
await models.InvoiceInTax.destroyById(invoiceInTaxId, options);
|
||||
} catch (err) {
|
||||
error = err;
|
||||
}
|
||||
|
||||
const deletedInvoiceInTax = await models.InvoiceInTax.findById(invoiceInTaxId, null, options);
|
||||
|
||||
expect(error).toBeUndefined();
|
||||
expect(deletedInvoiceInTax).toBeNull();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,59 @@
|
|||
const models = require('vn-loopback/server/server').models;
|
||||
|
||||
const invoiceInId = 1;
|
||||
const supplierId = 791;
|
||||
describe('invoiceIn updateInvoiceIn()', () => {
|
||||
const ctx = beforeAll.getCtx();
|
||||
let options;
|
||||
let tx;
|
||||
|
||||
beforeEach(async() => {
|
||||
options = {transaction: tx};
|
||||
tx = await models.Sale.beginTransaction({});
|
||||
options.transaction = tx;
|
||||
});
|
||||
|
||||
afterEach(async() => {
|
||||
await tx.rollback();
|
||||
});
|
||||
|
||||
it('should update the invoice', async() => {
|
||||
const invoiceBefore = await models.InvoiceIn.findById(invoiceInId, null, options);
|
||||
await update(ctx, options);
|
||||
const invoiceAfter = await models.InvoiceIn.findById(invoiceInId, null, options);
|
||||
|
||||
expect(invoiceAfter.supplierFk).not.toBe(invoiceBefore.supplierFk);
|
||||
expect(invoiceAfter.supplierFk).toBe(supplierId);
|
||||
});
|
||||
|
||||
it('should not update the invoice if is booked', async() => {
|
||||
let error;
|
||||
try {
|
||||
await models.InvoiceIn.toBook(ctx, invoiceInId, options);
|
||||
await update(ctx, options);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
|
||||
expect(error.message).toBe('InvoiceIn is already booked');
|
||||
});
|
||||
});
|
||||
|
||||
async function update(ctx, opts) {
|
||||
const supplierRef = 'mockRef';
|
||||
const currencyId = 1;
|
||||
await models.InvoiceIn.updateInvoiceIn(ctx,
|
||||
invoiceInId,
|
||||
supplierId,
|
||||
supplierRef,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
currencyId,
|
||||
undefined,
|
||||
undefined,
|
||||
opts);
|
||||
}
|
|
@ -37,7 +37,13 @@ module.exports = Self => {
|
|||
{
|
||||
relation: 'supplier',
|
||||
scope: {
|
||||
fields: ['id', 'name']
|
||||
fields: ['id', 'name', 'isVies', 'countryFk'],
|
||||
include: [{
|
||||
relation: 'country',
|
||||
scope: {
|
||||
fields: ['id', 'code']
|
||||
}
|
||||
}]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
@ -52,7 +52,8 @@ module.exports = Self => {
|
|||
accountingEntries = await models.Xdiario.count({ASIEN: asien}, myOptions);
|
||||
|
||||
await models.Xdiario.destroyAll({ASIEN: asien}, myOptions);
|
||||
await Self.updateAll({id: invoiceInId}, {isBooked: false}, myOptions);
|
||||
const invoiceIn = await Self.findById(invoiceInId, myOptions);
|
||||
await invoiceIn.updateAttribute('isBooked', false, myOptions);
|
||||
} else {
|
||||
const linkedBookEntry = await models.Xdiario.findOne({
|
||||
fields: ['ASIEN'],
|
||||
|
|
|
@ -82,7 +82,7 @@ module.exports = Self => {
|
|||
|
||||
try {
|
||||
const invoiceIn = await Self.findById(id, null, myOptions);
|
||||
invoiceIn.updateAttributes({supplierFk,
|
||||
await invoiceIn.updateAttributes({supplierFk,
|
||||
supplierRef,
|
||||
issued,
|
||||
operated,
|
||||
|
@ -94,6 +94,7 @@ module.exports = Self => {
|
|||
companyFk,
|
||||
withholdingSageFk
|
||||
}, myOptions);
|
||||
|
||||
if (tx) await tx.commit();
|
||||
return invoiceIn;
|
||||
} catch (e) {
|
||||
|
|
|
@ -28,11 +28,10 @@
|
|||
"model": "InvoiceCorrectionType",
|
||||
"foreignKey": "invoiceCorrectionTypeFk"
|
||||
},
|
||||
"siiTypeInvoiceOut": {
|
||||
"siiTypeInvoiceIn": {
|
||||
"type": "belongsTo",
|
||||
"model": "SiiTypeInvoiceOut",
|
||||
"foreignKey": "siiTypeInvoiceOutFk"
|
||||
"model": "SiiTypeInvoiceIn",
|
||||
"foreignKey": "siiTypeInvoiceInFk"
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
const UserError = require('vn-loopback/util/user-error');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.observe('before save', async function(ctx) {
|
||||
if (ctx.isNewInstance) return;
|
||||
|
||||
const models = Self.app.models;
|
||||
const invoiceIn = await models.InvoiceIn.findById(ctx.currentInstance.invoiceInFk, null, ctx.options);
|
||||
if (invoiceIn.isBooked) throw new UserError('InvoiceIn is already booked');
|
||||
});
|
||||
|
||||
Self.observe('before delete', async function(ctx) {
|
||||
const models = Self.app.models;
|
||||
const invoiceInTax = await Self.findById(ctx.where.id, null, ctx.options);
|
||||
const invoiceIn = await models.InvoiceIn.findById(invoiceInTax.invoiceInFk, null, ctx.options);
|
||||
if (invoiceIn.isBooked) throw new UserError('InvoiceIn is already booked');
|
||||
});
|
||||
};
|
|
@ -22,12 +22,11 @@
|
|||
"type": "number"
|
||||
},
|
||||
"expenseFk": {
|
||||
"type": "number"
|
||||
"type": "string"
|
||||
},
|
||||
"created": {
|
||||
"type": "date"
|
||||
}
|
||||
|
||||
},
|
||||
"relations": {
|
||||
"invoiceIn": {
|
||||
|
@ -51,4 +50,4 @@
|
|||
"foreignKey": "transactionTypeSageFk"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,4 +19,25 @@ module.exports = Self => {
|
|||
return new UserError(`This invoice has a linked vehicle.`);
|
||||
return err;
|
||||
});
|
||||
|
||||
Self.observe('before save', async function(ctx) {
|
||||
if (ctx.isNewInstance) return;
|
||||
|
||||
const changes = ctx.data || ctx.instance;
|
||||
const orgData = ctx.currentInstance;
|
||||
let isNotEditable = orgData.isBooked || (!orgData.isBooked && changes.isBooked);
|
||||
|
||||
if (isNotEditable) {
|
||||
for (const [key, value] of Object.entries(changes)) {
|
||||
if (key !== 'isBooked' && value !== orgData[key])
|
||||
throw new UserError('InvoiceIn is already booked');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Self.observe('before delete', async function(ctx) {
|
||||
const invoiceIn = await Self.findById(ctx.where.id, null, ctx.options);
|
||||
if (invoiceIn.isBooked) throw new UserError('InvoiceIn is already booked');
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -43,5 +43,8 @@
|
|||
},
|
||||
"SiiTypeInvoiceOut": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"SiiTypeInvoiceIn": {
|
||||
"dataSource": "vn"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"name": "SiiTypeInvoiceIn",
|
||||
"base": "VnModel",
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "siiTypeInvoiceIn"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"id": true,
|
||||
"type": "number",
|
||||
"description": "Identifier"
|
||||
},
|
||||
"code": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,9 +17,6 @@
|
|||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"code": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -55,6 +55,11 @@ module.exports = Self => {
|
|||
type: 'number',
|
||||
description: 'Department identifier'
|
||||
},
|
||||
{
|
||||
arg: 'onlyWithDestination',
|
||||
type: 'Boolean',
|
||||
description: 'True when only tickets with destination are returned'
|
||||
},
|
||||
{
|
||||
arg: 'filter',
|
||||
type: 'object',
|
||||
|
@ -103,6 +108,8 @@ module.exports = Self => {
|
|||
return {'f.isFullMovable': value};
|
||||
case 'departmentFk':
|
||||
return {'f.departmentFk': value};
|
||||
case 'onlyWithDestination':
|
||||
return {'f.id': value ? {neq: null} : null};
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ describe('TicketFuture getTicketsAdvance()', () => {
|
|||
tomorrow.setDate(today.getDate() + 1);
|
||||
const salesDeptId = 43;
|
||||
const spain1DeptId = 95;
|
||||
const warehouseId = 1;
|
||||
beforeAll.mockLoopBackContext();
|
||||
|
||||
it('should return the tickets passing the required data', async() => {
|
||||
|
@ -19,7 +20,7 @@ describe('TicketFuture getTicketsAdvance()', () => {
|
|||
const args = {
|
||||
dateFuture: tomorrow,
|
||||
dateToAdvance: today,
|
||||
warehouseFk: 1,
|
||||
warehouseFk: warehouseId,
|
||||
};
|
||||
|
||||
ctx.args = args;
|
||||
|
@ -42,7 +43,7 @@ describe('TicketFuture getTicketsAdvance()', () => {
|
|||
const args = {
|
||||
dateFuture: tomorrow,
|
||||
dateToAdvance: today,
|
||||
warehouseFk: 1,
|
||||
warehouseFk: warehouseId,
|
||||
isFullMovable: true
|
||||
};
|
||||
|
||||
|
@ -67,7 +68,7 @@ describe('TicketFuture getTicketsAdvance()', () => {
|
|||
const args = {
|
||||
dateFuture: tomorrow,
|
||||
dateToAdvance: today,
|
||||
warehouseFk: 1,
|
||||
warehouseFk: warehouseId,
|
||||
isFullMovable: false
|
||||
};
|
||||
|
||||
|
@ -92,7 +93,7 @@ describe('TicketFuture getTicketsAdvance()', () => {
|
|||
const args = {
|
||||
dateFuture: tomorrow,
|
||||
dateToAdvance: today,
|
||||
warehouseFk: 1,
|
||||
warehouseFk: warehouseId,
|
||||
ipt: 'V'
|
||||
};
|
||||
|
||||
|
@ -117,7 +118,7 @@ describe('TicketFuture getTicketsAdvance()', () => {
|
|||
const args = {
|
||||
dateFuture: tomorrow,
|
||||
dateToAdvance: today,
|
||||
warehouseFk: 1,
|
||||
warehouseFk: warehouseId,
|
||||
tfIpt: 'V'
|
||||
};
|
||||
|
||||
|
@ -141,7 +142,7 @@ describe('TicketFuture getTicketsAdvance()', () => {
|
|||
ctx.args = {
|
||||
dateFuture: tomorrow,
|
||||
dateToAdvance: today,
|
||||
warehouseFk: 1,
|
||||
warehouseFk: warehouseId,
|
||||
};
|
||||
|
||||
await models.Ticket.updateAll({id: {inq: [12, 31]}}, {clientFk: 1}, options);
|
||||
|
@ -167,4 +168,56 @@ describe('TicketFuture getTicketsAdvance()', () => {
|
|||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should return the tickets with only destination', async() => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
const args = {
|
||||
dateFuture: today,
|
||||
dateToAdvance: today.setHours(23, 59, 59, 999),
|
||||
warehouseFk: warehouseId,
|
||||
};
|
||||
ctx.args = args;
|
||||
|
||||
const allTickets = await models.Ticket.getTicketsAdvance(ctx, options);
|
||||
ctx.args.onlyWithDestination = true;
|
||||
const withDestinationTickets = await models.Ticket.getTicketsAdvance(ctx, options);
|
||||
|
||||
expect(allTickets.filter(ticket => ticket.id).length).toBe(withDestinationTickets.length);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should return the tickets without only destination', async() => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
const args = {
|
||||
dateFuture: today,
|
||||
dateToAdvance: today.setHours(23, 59, 59, 999),
|
||||
warehouseFk: warehouseId,
|
||||
};
|
||||
ctx.args = args;
|
||||
|
||||
const allTickets = await models.Ticket.getTicketsAdvance(ctx, options);
|
||||
ctx.args.onlyWithDestination = false;
|
||||
const withoutDestinationTickets = await models.Ticket.getTicketsAdvance(ctx, options);
|
||||
|
||||
expect(allTickets.filter(ticket => !ticket.id).length).toBe(withoutDestinationTickets.length);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -83,6 +83,14 @@ module.exports = Self => {
|
|||
arg: 'daysOnward',
|
||||
type: 'number',
|
||||
description: 'The days onward'
|
||||
}, {
|
||||
arg: 'shipped',
|
||||
type: 'date',
|
||||
description: 'The shipped date'
|
||||
}, {
|
||||
arg: 'landed',
|
||||
type: 'date',
|
||||
description: 'The landed date'
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
|
@ -108,6 +116,10 @@ module.exports = Self => {
|
|||
: {'t.ref': {like: `%${value}%`}};
|
||||
case 'ref':
|
||||
return {'t.ref': {like: `%${value}%`}};
|
||||
case 'shipped':
|
||||
return {'t.shipped': value};
|
||||
case 'landed':
|
||||
return {'t.landed': value};
|
||||
case 'shippedFrom':
|
||||
return {'t.shipped': {gte: value}};
|
||||
case 'shippedTo':
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "salix-back",
|
||||
"version": "24.52.0",
|
||||
"version": "25.02.0",
|
||||
"author": "Verdnatura Levante SL",
|
||||
"description": "Salix backend",
|
||||
"license": "GPL-3.0",
|
||||
|
|
Loading…
Reference in New Issue