diff --git a/db/dump/fixtures.before.sql b/db/dump/fixtures.before.sql index 97ed0ae47..672250b60 100644 --- a/db/dump/fixtures.before.sql +++ b/db/dump/fixtures.before.sql @@ -974,26 +974,30 @@ INSERT INTO `vn`.`itemFamily`(`code`, `description`) ('SER', 'Services'), ('VT', 'Sales'); -INSERT INTO `vn`.`item`(`id`, `typeFk`, `stems`, `originFk`, `description`, `producerFk`, `intrastatFk`, `expenseFk`, - `comment`, `relevancy`, `image`, `subName`, `minPrice`, `family`, `isFloramondo`, `genericFk`, `itemPackingTypeFk`, `hasMinPrice`, `weightByPiece`) - VALUES - (1, 2, 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '1', NULL, 0, 'EMB', 0, NULL, 'V', 0, 3), - (2, 2, 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '2', NULL, 0, 'VT', 0, NULL, 'H', 0, 2), - (3, 1, 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '3', NULL, 0, 'VT', 0, NULL, NULL, 0, 5), - (4, 1, 1, 1, 'Increases block', 1, 05080000, 4751000000, NULL, 0, '4', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL), - (5, 3, 1, 2, NULL, 2, 06021010, 4751000000, NULL, 0, '5', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL), - (6, 5, 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '6', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL), - (7, 5, 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '7', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL), - (8, 2, 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '8', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL), - (9, 2, 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '9', NULL, 0, 'VT', 1, NULL, NULL, 0, NULL), - (10, 1, 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '10', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL), - (11, 1, 1, 1, NULL, 1, 05080000, 4751000000, NULL, 0, '11', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL), - (12, 3, 1, 2, NULL, 2, 06021010, 4751000000, NULL, 0, '12', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL), - (13, 5, 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '13', NULL, 1, 'VT', 1, NULL, NULL, 1, NULL), - (14, 5, 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 'VT', 1, NULL, NULL, 0, NULL), - (15, 4, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 'EMB', 0, NULL, NULL, 0, NULL), - (16, 6, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 'EMB', 0, NULL, NULL, 0, NULL), - (71, 6, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL); +INSERT INTO `vn`.`item`( + `id`, `typeFk`, `stems`, `originFk`, `description`, `producerFk`, `intrastatFk`, `expenseFk`, + `comment`, `relevancy`, `image`, `subName`, `minPrice`, `family`, `isFloramondo`, `genericFk`, + `itemPackingTypeFk`, `hasMinPrice`, `weightByPiece`, `isCustomInspectionRequired` +) +VALUES + (1, 2, 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '1', NULL, 0, 'EMB', 0, NULL, 'V', 0, 3, 1), + (2, 2, 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '2', NULL, 0, 'VT', 0, NULL, 'H', 0, 2, 1), + (3, 1, 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '3', NULL, 0, 'VT', 0, NULL, NULL, 0, 5, 0), + (4, 1, 1, 1, 'Increases block', 1, 05080000, 4751000000, NULL, 0, '4', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL, 0), + (5, 3, 1, 2, NULL, 2, 06021010, 4751000000, NULL, 0, '5', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL, 0), + (6, 5, 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '6', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL, 0), + (7, 5, 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '7', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL, 0), + (8, 2, 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '8', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL, 0), + (9, 2, 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '9', NULL, 0, 'VT', 1, NULL, NULL, 0, NULL, 0), + (10, 1, 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '10', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL, 0), + (11, 1, 1, 1, NULL, 1, 05080000, 4751000000, NULL, 0, '11', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL, 0), + (12, 3, 1, 2, NULL, 2, 06021010, 4751000000, NULL, 0, '12', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL, 0), + (13, 5, 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '13', NULL, 1, 'VT', 1, NULL, NULL, 1, NULL, 0), + (14, 5, 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 'VT', 1, NULL, NULL, 0, NULL, 0), + (15, 4, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 'EMB', 0, NULL, NULL, 0, NULL, 0), + (16, 6, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 'EMB', 0, NULL, NULL, 0, NULL, 0), + (71, 6, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL, 0); + -- Update the taxClass after insert of the items UPDATE `vn`.`itemTaxCountry` SET `taxClassFk` = 2 @@ -3965,7 +3969,7 @@ VALUES(1, ''); INSERT INTO dipole.expedition_PrintOut (expeditionFk, ticketFk, addressFk, street, postalCode, city, shopName, isPrinted, created, printerFk, routeFk, parkingCode, truckName, clientFk, phone, province, agency, m3, workerCode, itemFk, quantity, longName, shelvingFk, comments) -VALUES(1, 1, 0, ' ', ' ', ' ', ' ', 0, '2001-01-01 00:00:00', 1, 0, ' ', ' ', 0, NULL, '', NULL, 0.000, NULL, 10, NULL, NULL, 'NCC', NULL); +VALUES(1, 1, 0, ' ', ' ', ' ', ' ', 0, '2001-01-01 00:00:00', 1, 0, ' ', ' ', 0, NULL, '', NULL, 0.000, NULL, 10, NULL, 'Ranged Reinforced weapon sniper rifle 700mm' , 'NCC', NULL); INSERT INTO vn.accountDetail (id, value, accountDetailTypeFk, supplierAccountFk) @@ -4038,7 +4042,7 @@ 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) +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); diff --git a/db/versions/11391-redPalmetto/00-itemAlter.sql b/db/versions/11391-redPalmetto/00-itemAlter.sql new file mode 100644 index 000000000..fc47d5fc0 --- /dev/null +++ b/db/versions/11391-redPalmetto/00-itemAlter.sql @@ -0,0 +1,2 @@ +ALTER TABLE `vn`.`item` +ADD COLUMN `isCustomInspectionRequired` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'Indicates if the item requires physical inspection at customs'; diff --git a/loopback/locale/en.json b/loopback/locale/en.json index e6ec52d63..80da13ae5 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -246,8 +246,9 @@ "ticketLostExpedition": "The ticket [{{ticketId}}]({{{ticketUrl}}}) has the following lost expedition:{{ expeditionId }}", "The raid information is not correct": "The raid information is not correct", "Payment method is required": "Payment method is required", - "Sales already moved": "Sales already moved", - "Holidays to past days not available": "Holidays to past days not available", + "Sales already moved": "Sales already moved", + "Holidays to past days not available": "Holidays to past days not available", "Price cannot be blank": "Price cannot be blank", - "There are tickets to be invoiced": "There are tickets to be invoiced" -} + "There are tickets to be invoiced": "There are tickets to be invoiced", + "The address of the customer must have information about Incoterms and Customs Agent": "The address of the customer must have information about Incoterms and Customs Agent" +} \ No newline at end of file diff --git a/modules/client/back/methods/client/canBeInvoiced.js b/modules/client/back/methods/client/canBeInvoiced.js index cdb865500..536606b0b 100644 --- a/modules/client/back/methods/client/canBeInvoiced.js +++ b/modules/client/back/methods/client/canBeInvoiced.js @@ -2,7 +2,7 @@ const UserError = require('vn-loopback/util/user-error'); module.exports = function(Self) { Self.remoteMethod('canBeInvoiced', { - description: 'Change property isEqualizated in all client addresses', + description: 'Check if a client can be invoiced', accessType: 'READ', accepts: [ { @@ -38,7 +38,7 @@ module.exports = function(Self) { Object.assign(myOptions, options); const client = await models.Client.findById(id, { - fields: ['id', 'isTaxDataChecked', 'hasToInvoice', 'payMethodFk'], + fields: ['id', 'isTaxDataChecked', 'hasToInvoice', 'payMethodFk', 'isActive'], include: { relation: 'payMethod', @@ -53,9 +53,6 @@ module.exports = function(Self) { if (client.payMethod().code === 'wireTransfer' && !company.supplierAccountFk) throw new UserError('The company has not informed the supplier account for bank transfers'); - if (client.isTaxDataChecked && client.hasToInvoice) - return true; - - return false; + return client.isTaxDataChecked && client.hasToInvoice && client.isActive; }; }; diff --git a/modules/client/back/methods/client/specs/canBeInvoiced.spec.js b/modules/client/back/methods/client/specs/canBeInvoiced.spec.js index 397be3c92..4012b7409 100644 --- a/modules/client/back/methods/client/specs/canBeInvoiced.spec.js +++ b/modules/client/back/methods/client/specs/canBeInvoiced.spec.js @@ -8,6 +8,8 @@ describe('client canBeInvoiced()', () => { const activeCtx = { accessToken: {userId: userId} }; + let tx; + let options; beforeAll(async() => { spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ @@ -15,60 +17,45 @@ describe('client canBeInvoiced()', () => { }); }); + beforeEach(async() => { + tx = await models.Client.beginTransaction({}); + options = {transaction: tx}; + }); + + afterEach(async() => { + await tx.rollback(); + }); + it('should return falsy for a client without the data checked', async() => { - const tx = await models.Client.beginTransaction({}); + const client = await models.Client.findById(clientId, null, options); + await client.updateAttribute('isTaxDataChecked', false, options); - try { - const options = {transaction: tx}; + const canBeInvoiced = await models.Client.canBeInvoiced(clientId, companyId, options); - const client = await models.Client.findById(clientId, null, options); - await client.updateAttribute('isTaxDataChecked', false, options); + expect(canBeInvoiced).toEqual(false); + }); - const canBeInvoiced = await models.Client.canBeInvoiced(clientId, companyId, options); + it('should return falsy for a client not active', async() => { + const client = await models.Client.findById(clientId, null, options); + await client.updateAttribute('isActive', false, options); - expect(canBeInvoiced).toEqual(false); + const canBeInvoiced = await models.Client.canBeInvoiced(clientId, companyId, options); - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } + expect(canBeInvoiced).toEqual(false); }); it('should return falsy for a client with invoicing disabled', async() => { - const tx = await models.Client.beginTransaction({}); + const client = await models.Client.findById(clientId, null, options); + await client.updateAttribute('hasToInvoice', false, options); - try { - const options = {transaction: tx}; + const canBeInvoiced = await models.Client.canBeInvoiced(clientId, companyId, options); - const client = await models.Client.findById(clientId, null, options); - await client.updateAttribute('hasToInvoice', false, options); - - const canBeInvoiced = await models.Client.canBeInvoiced(clientId, companyId, options); - - expect(canBeInvoiced).toEqual(false); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } + expect(canBeInvoiced).toEqual(false); }); it('should return truthy for an invoiceable client', async() => { - const tx = await models.Client.beginTransaction({}); + const canBeInvoiced = await models.Client.canBeInvoiced(clientId, companyId, options); - try { - const options = {transaction: tx}; - - const canBeInvoiced = await models.Client.canBeInvoiced(clientId, companyId, options); - - expect(canBeInvoiced).toEqual(true); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } + expect(canBeInvoiced).toEqual(true); }); }); diff --git a/modules/invoiceIn/back/locale/invoiceIn/en.yml b/modules/invoiceIn/back/locale/invoiceIn/en.yml index 9e94eba0d..f590f9656 100644 --- a/modules/invoiceIn/back/locale/invoiceIn/en.yml +++ b/modules/invoiceIn/back/locale/invoiceIn/en.yml @@ -17,4 +17,6 @@ columns: isVatDeductible: is VAT deductible withholdingSageFk: withholding expenseFkDeductible: expense deductible - editorFk: editor \ No newline at end of file + editorFk: editor + siiTrasCendencyInvoiceInFk: SII tax regime + siiTypeInvoiceInFk: SII Type \ No newline at end of file diff --git a/modules/invoiceIn/back/locale/invoiceIn/es.yml b/modules/invoiceIn/back/locale/invoiceIn/es.yml index bd64c4327..64ded6aca 100644 --- a/modules/invoiceIn/back/locale/invoiceIn/es.yml +++ b/modules/invoiceIn/back/locale/invoiceIn/es.yml @@ -5,7 +5,7 @@ columns: serial: serie supplierFk: proveedor issued: fecha emisión - supplierRef: referéncia proveedor + supplierRef: referencia proveedor isBooked: facturado currencyFk: moneda created: creado @@ -17,4 +17,6 @@ columns: isVatDeductible: impuesto deducible withholdingSageFk: código de retención expenseFkDeductible: gasto deducible - editorFk: editor \ No newline at end of file + editorFk: editor + siiTrasCendencyInvoiceInFk: régimen fiscal SII + siiTypeInvoiceInFk: tipo SII \ 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 5526d214a..7befdcbeb 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/clientsToInvoice.js +++ b/modules/invoiceOut/back/methods/invoiceOut/clientsToInvoice.js @@ -1,3 +1,5 @@ +const UserError = require('vn-loopback/util/user-error'); + module.exports = Self => { Self.remoteMethodCtx('clientsToInvoice', { description: 'Get the clients to make global invoicing', @@ -47,7 +49,12 @@ module.exports = Self => { } try { - // Packaging liquidation + const clientCanBeInvoiced = + await Self.app.models.Client.canBeInvoiced(clientId, companyFk, myOptions); + + if (!clientCanBeInvoiced) + throw new UserError(`This client can't be invoiced`); + const vIsAllInvoiceable = false; await Self.rawSql('CALL ticketPackaging_add(?, ?, ?, ?)', [ clientId, @@ -71,9 +78,6 @@ module.exports = Self => { 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 IF(c.hasToInvoiceByAddress, a.id, c.id) HAVING SUM(t.totalWithVat) > 0;`; diff --git a/modules/invoiceOut/back/methods/invoiceOut/specs/clientsToInvoice.spec.js b/modules/invoiceOut/back/methods/invoiceOut/specs/clientsToInvoice.spec.js index 470690c5a..df0566c54 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/specs/clientsToInvoice.spec.js +++ b/modules/invoiceOut/back/methods/invoiceOut/specs/clientsToInvoice.spec.js @@ -4,11 +4,11 @@ describe('InvoiceOut clientsToInvoice()', () => { const userId = 1; const clientId = 1101; const companyFk = 442; - const maxShipped = new Date(); + const maxShipped = Date.vnNew(); maxShipped.setMonth(11); maxShipped.setDate(31); maxShipped.setHours(23, 59, 59, 999); - const invoiceDate = new Date(); + const invoiceDate = Date.vnNew(); const activeCtx = { getLocale: () => { return 'en'; diff --git a/modules/item/back/models/item.json b/modules/item/back/models/item.json index eda56e938..159883455 100644 --- a/modules/item/back/models/item.json +++ b/modules/item/back/models/item.json @@ -154,6 +154,9 @@ }, "photoMotivation": { "type": "string" + }, + "isCustomInspectionRequired": { + "type": "boolean" } }, "relations": { @@ -222,4 +225,4 @@ } } } -} \ No newline at end of file +} diff --git a/modules/ticket/back/methods/expedition/filter.js b/modules/ticket/back/methods/expedition/filter.js index bd2012668..801d00a9b 100644 --- a/modules/ticket/back/methods/expedition/filter.js +++ b/modules/ticket/back/methods/expedition/filter.js @@ -50,7 +50,8 @@ module.exports = Self => { su.name scannerUserName, es.scanned, est.description state, - de.longName + de.longName, + de.itemFk FROM vn.expedition e LEFT JOIN vn.expeditionStateType est ON est.id = e.stateTypeFk INNER JOIN vn.item i1 ON i1.id = e.freightItemFk diff --git a/modules/ticket/back/methods/ticket/specs/makeInvoice.spec.js b/modules/ticket/back/methods/ticket/specs/makeInvoice.spec.js index 88812dc92..f9e4bcac0 100644 --- a/modules/ticket/back/methods/ticket/specs/makeInvoice.spec.js +++ b/modules/ticket/back/methods/ticket/specs/makeInvoice.spec.js @@ -77,6 +77,8 @@ describe('ticket makeInvoice()', () => { await tx.rollback(); } - expect(error.message).toEqual(`The address of the customer must have information about Incoterms and Customs Agent`); + expect(error.message).toEqual( + `The address of the customer must have information about Incoterms and Customs Agent` + ); }); }); diff --git a/modules/travel/back/methods/travel/extraCommunityFilter.js b/modules/travel/back/methods/travel/extraCommunityFilter.js index f1586f804..2f3f998d6 100644 --- a/modules/travel/back/methods/travel/extraCommunityFilter.js +++ b/modules/travel/back/methods/travel/extraCommunityFilter.js @@ -132,18 +132,18 @@ module.exports = Self => { CAST(SUM(b.weight * b.stickers) AS DECIMAL(10,0)) loadedKg, CAST( SUM( - vc.aerealVolumetricDensity * - b.stickers * + vc.aerealVolumetricDensity * + b.stickers * IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000 ) AS DECIMAL(10,0) ) volumeKg, CAST( GREATEST( SUM(b.weight * b.stickers) , - SUM(vc.aerealVolumetricDensity * - b.stickers * - IF(pkg.volume, - pkg.volume, + SUM(vc.aerealVolumetricDensity * + b.stickers * + IF(pkg.volume, + pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000) ) / t.kg * 100 AS INT ) percentageKg @@ -185,11 +185,12 @@ module.exports = Self => { CAST(SUM(b.weight * b.stickers) AS DECIMAL(10,0)) as loadedkg, CAST( SUM( - vc.aerealVolumetricDensity * - b.stickers * + vc.aerealVolumetricDensity * + b.stickers * IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000 ) AS DECIMAL(10,0) - ) as volumeKg + ) as volumeKg, + MAX(i.isCustomInspectionRequired) isCustomInspectionRequired FROM tmp.travel tr JOIN entry e ON e.travelFk = tr.id JOIN buy b ON b.entryFk = e.id diff --git a/modules/travel/back/methods/travel/specs/extraCommunityFilter.spec.js b/modules/travel/back/methods/travel/specs/extraCommunityFilter.spec.js index 7e90c7681..8fa013fe4 100644 --- a/modules/travel/back/methods/travel/specs/extraCommunityFilter.spec.js +++ b/modules/travel/back/methods/travel/specs/extraCommunityFilter.spec.js @@ -112,4 +112,17 @@ describe('Travel extraCommunityFilter()', () => { expect(result.length).toEqual(2); }); + + it('should return field isCustomInspectionRequired true', async() => { + const ctx = { + args: { + id: 2 + } + }; + + const result = await app.models.Travel.extraCommunityFilter(ctx, filter); + + expect(result[0].entries[0].isCustomInspectionRequired).toBeTruthy(); + expect(result[0].entries[1].isCustomInspectionRequired).toBeFalsy(); + }); });