diff --git a/db/changes/10440-fallas/00-claimConfig.sql b/db/changes/10440-fallas/00-claimConfig.sql new file mode 100644 index 000000000..905dea484 --- /dev/null +++ b/db/changes/10440-fallas/00-claimConfig.sql @@ -0,0 +1,8 @@ +CREATE TABLE `vn`.`claimConfig` ( + `id` int(11) NOT NULL, + `pickupContact` varchar(250), + PRIMARY KEY (`id`) +); + +INSERT INTO vn.claimConfig (id, pickupContact) + VALUES(1, 'Email: cmorenoa@logista.com Telf: 961594250 Extensión: 206'); \ No newline at end of file diff --git a/db/changes/10440-fallas/00-claimState.sql b/db/changes/10440-fallas/00-claimState.sql new file mode 100644 index 000000000..329a9b977 --- /dev/null +++ b/db/changes/10440-fallas/00-claimState.sql @@ -0,0 +1,2 @@ +ALTER TABLE `vn`.`claimState` ADD `hasToNotify` TINYINT DEFAULT 0 NULL; +UPDATE `vn`.`claimState` SET `hasToNotify` = 1 WHERE `code` IN ('canceled', 'incomplete'); \ No newline at end of file diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 2e5436919..23f625e7f 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -812,25 +812,25 @@ INSERT INTO `vn`.`itemFamily`(`code`, `description`) ('VT', 'Sales'); INSERT INTO `vn`.`item`(`id`, `typeFk`, `size`, `inkFk`, `stems`, `originFk`, `description`, `producerFk`, `intrastatFk`, `expenceFk`, - `comment`, `relevancy`, `image`, `subName`, `minPrice`, `stars`, `family`, `isFloramondo`, `genericFk`, `itemPackingTypeFk`) + `comment`, `relevancy`, `image`, `subName`, `minPrice`, `stars`, `family`, `isFloramondo`, `genericFk`, `itemPackingTypeFk`, `hasMinPrice`) VALUES - (1, 2, 70, 'YEL', 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '1', NULL, 0, 1, 'VT', 0, NULL, 'V'), - (2, 2, 70, 'BLU', 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '2', NULL, 0, 2, 'VT', 0, NULL, 'H'), - (3, 1, 60, 'YEL', 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '3', NULL, 0, 5, 'VT', 0, NULL, NULL), - (4, 1, 60, 'YEL', 1, 1, 'Increases block', 1, 05080000, 4751000000, NULL, 0, '4', NULL, 0, 3, 'VT', 0, NULL, NULL), - (5, 3, 30, 'RED', 1, 2, NULL, 2, 06021010, 4751000000, NULL, 0, '5', NULL, 0, 3, 'VT', 0, NULL, NULL), - (6, 5, 30, 'RED', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '6', NULL, 0, 4, 'VT', 0, NULL, NULL), - (7, 5, 90, 'BLU', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '7', NULL, 0, 4, 'VT', 0, NULL, NULL), - (8, 2, 70, 'YEL', 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '8', NULL, 0, 5, 'VT', 0, NULL, NULL), - (9, 2, 70, 'BLU', 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '9', NULL, 0, 4, 'VT', 1, NULL, NULL), - (10, 1, 60, 'YEL', 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '10', NULL, 0, 4, 'VT', 0, NULL, NULL), - (11, 1, 60, 'YEL', 1, 1, NULL, 1, 05080000, 4751000000, NULL, 0, '11', NULL, 0, 4, 'VT', 0, NULL, NULL), - (12, 3, 30, 'RED', 1, 2, NULL, 2, 06021010, 4751000000, NULL, 0, '12', NULL, 0, 3, 'VT', 0, NULL, NULL), - (13, 5, 30, 'RED', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '13', NULL, 0, 2, 'VT', 1, NULL, NULL), - (14, 5, 90, 'BLU', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 4, 'VT', 1, NULL, NULL), - (15, 4, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 0, 'EMB', 0, NULL, NULL), - (16, 6, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 0, 'EMB', 0, NULL, NULL), - (71, 6, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 0, 'VT', 0, NULL, NULL); + (1, 2, 70, 'YEL', 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '1', NULL, 0, 1, 'VT', 0, NULL, 'V', 0), + (2, 2, 70, 'BLU', 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '2', NULL, 0, 2, 'VT', 0, NULL, 'H', 0), + (3, 1, 60, 'YEL', 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '3', NULL, 0, 5, 'VT', 0, NULL, NULL, 0), + (4, 1, 60, 'YEL', 1, 1, 'Increases block', 1, 05080000, 4751000000, NULL, 0, '4', NULL, 0, 3, 'VT', 0, NULL, NULL, 0), + (5, 3, 30, 'RED', 1, 2, NULL, 2, 06021010, 4751000000, NULL, 0, '5', NULL, 0, 3, 'VT', 0, NULL, NULL, 0), + (6, 5, 30, 'RED', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '6', NULL, 0, 4, 'VT', 0, NULL, NULL, 0), + (7, 5, 90, 'BLU', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '7', NULL, 0, 4, 'VT', 0, NULL, NULL, 0), + (8, 2, 70, 'YEL', 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '8', NULL, 0, 5, 'VT', 0, NULL, NULL, 0), + (9, 2, 70, 'BLU', 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '9', NULL, 0, 4, 'VT', 1, NULL, NULL, 0), + (10, 1, 60, 'YEL', 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '10', NULL, 0, 4, 'VT', 0, NULL, NULL, 0), + (11, 1, 60, 'YEL', 1, 1, NULL, 1, 05080000, 4751000000, NULL, 0, '11', NULL, 0, 4, 'VT', 0, NULL, NULL, 0), + (12, 3, 30, 'RED', 1, 2, NULL, 2, 06021010, 4751000000, NULL, 0, '12', NULL, 0, 3, 'VT', 0, NULL, NULL, 0), + (13, 5, 30, 'RED', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '13', NULL, 1, 2, 'VT', 1, NULL, NULL, 1), + (14, 5, 90, 'BLU', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 4, 'VT', 1, NULL, NULL, 0), + (15, 4, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 0, 'EMB', 0, NULL, NULL, 0), + (16, 6, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 0, 'EMB', 0, NULL, NULL, 0), + (71, 6, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 0, 'VT', 0, NULL, NULL, 0); -- Update the taxClass after insert of the items UPDATE `vn`.`itemTaxCountry` SET `taxClassFk` = 2 @@ -840,7 +840,7 @@ INSERT INTO `vn`.`priceFixed`(`id`, `itemFk`, `rate0`, `rate1`, `rate2`, `rate3` VALUES (1, 1, 0, 0, 2.5, 2, CURDATE(), DATE_ADD(CURDATE(), INTERVAL +1 MONTH), 0, 1, CURDATE()), (2, 3, 10, 10, 10, 10, CURDATE(), DATE_ADD(CURDATE(), INTERVAL +1 MONTH), 0, 1, CURDATE()), - (3, 5, 8.5, 10, 7.5, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL +1 MONTH), 1, 2, CURDATE()); + (3, 13, 8.5, 10, 7.5, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL +1 MONTH), 1, 2, CURDATE()); INSERT INTO `vn`.`expeditionBoxVol`(`boxFk`, `m3`, `ratio`) VALUES @@ -1700,15 +1700,15 @@ INSERT INTO `vn`.`clientSample`(`id`, `clientFk`, `typeFk`, `created`, `workerFk (4, 1102, 2, CURDATE(), 18, 18, 567), (5, 1102, 3, CURDATE(), 19, 19, 567); -INSERT INTO `vn`.`claimState`(`id`, `code`, `description`, `roleFk`, `priority`) +INSERT INTO `vn`.`claimState`(`id`, `code`, `description`, `roleFk`, `priority`, `hasToNotify`) VALUES - ( 1, 'pending', 'Pendiente', 1, 1), - ( 2, 'managed', 'Gestionado', 1, 5), - ( 3, 'resolved', 'Resuelto', 72, 7), - ( 4, 'canceled', 'Anulado', 72, 6), - ( 5, 'incomplete', 'Incompleta', 72, 3), - ( 6, 'mana', 'Mana', 1, 4), - ( 7, 'lack', 'Faltas', 1, 2); + ( 1, 'pending', 'Pendiente', 1, 1, 0), + ( 2, 'managed', 'Gestionado', 1, 5, 0), + ( 3, 'resolved', 'Resuelto', 72, 7, 0), + ( 4, 'canceled', 'Anulado', 72, 6, 1), + ( 5, 'incomplete', 'Incompleta', 72, 3, 1), + ( 6, 'mana', 'Mana', 1, 4, 0), + ( 7, 'lack', 'Faltas', 1, 2, 0); INSERT INTO `vn`.`claim`(`id`, `ticketCreated`, `claimStateFk`, `observation`, `clientFk`, `workerFk`, `responsibility`, `isChargedToMana`, `created`, `packages`) VALUES diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 0fefa6c51..21ed27158 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -346,16 +346,17 @@ export default { saveFieldsButton: '.vn-popover.shown vn-button[label="Save"] > button' }, itemFixedPrice: { - add: 'vn-fixed-price vn-icon[icon="add_circle"]', - fourthFixedPrice: 'vn-fixed-price vn-tr:nth-child(4)', - fourthItemID: 'vn-fixed-price vn-tr:nth-child(4) vn-autocomplete[ng-model="price.itemFk"]', - fourthWarehouse: 'vn-fixed-price vn-tr:nth-child(4) vn-autocomplete[ng-model="price.warehouseFk"]', - fourthPPU: 'vn-fixed-price vn-tr:nth-child(4) > vn-td-editable:nth-child(4)', - fourthPPP: 'vn-fixed-price vn-tr:nth-child(4) > vn-td-editable:nth-child(5)', - fourthMinPrice: 'vn-fixed-price vn-tr:nth-child(4) > vn-td-editable:nth-child(6)', - fourthStarted: 'vn-fixed-price vn-tr:nth-child(4) vn-date-picker[ng-model="price.started"]', - fourthEnded: 'vn-fixed-price vn-tr:nth-child(4) vn-date-picker[ng-model="price.ended"]', - fourthDeleteIcon: 'vn-fixed-price vn-tr:nth-child(4) > vn-td:nth-child(9) > vn-icon-button[icon="delete"]' + add: 'vn-fixed-price vn-icon-button[icon="add_circle"]', + fourthFixedPrice: 'vn-fixed-price tr:nth-child(5)', + fourthItemID: 'vn-fixed-price tr:nth-child(5) vn-autocomplete[ng-model="price.itemFk"]', + fourthWarehouse: 'vn-fixed-price tr:nth-child(5) vn-autocomplete[ng-model="price.warehouseFk"]', + fourthPPU: 'vn-fixed-price tr:nth-child(5) > td:nth-child(4)', + fourthPPP: 'vn-fixed-price tr:nth-child(5) > td:nth-child(5)', + fourthHasMinPrice: 'vn-fixed-price tr:nth-child(5) > td:nth-child(6) > vn-check[ng-model="price.hasMinPrice"]', + fourthMinPrice: 'vn-fixed-price tr:nth-child(5) > td:nth-child(6) > vn-input-number[ng-model="price.minPrice"]', + fourthStarted: 'vn-fixed-price tr:nth-child(5) vn-date-picker[ng-model="price.started"]', + fourthEnded: 'vn-fixed-price tr:nth-child(5) vn-date-picker[ng-model="price.ended"]', + fourthDeleteIcon: 'vn-fixed-price tr:nth-child(5) > td:nth-child(9) > vn-icon-button[icon="delete"]' }, itemCreateView: { temporalName: 'vn-item-create vn-textfield[ng-model="$ctrl.item.provisionalName"]', diff --git a/e2e/paths/04-item/13_fixedPrice.spec.js b/e2e/paths/04-item/13_fixedPrice.spec.js index d68092904..fc7aac3d0 100644 --- a/e2e/paths/04-item/13_fixedPrice.spec.js +++ b/e2e/paths/04-item/13_fixedPrice.spec.js @@ -16,33 +16,17 @@ describe('Item fixed prices path', () => { }); it('should click on the add new foxed price button', async() => { + await page.doSearch(); await page.waitToClick(selectors.itemFixedPrice.add); await page.waitForSelector(selectors.itemFixedPrice.fourthFixedPrice); }); it('should fill the fixed price data', async() => { const now = new Date(); - const searchValue = 'Chest ammo box'; - await page.waitToClick(selectors.itemFixedPrice.fourthItemID); - await page.write('body > div > div > div.content > div.filter.ng-scope > vn-textfield', searchValue); - try { - await page.waitForFunction(searchValue => { - const element = document.querySelector('li.active'); - if (element) - return element.innerText.toLowerCase().includes(searchValue.toLowerCase()); - }, {}, searchValue); - } catch (error) { - const builtSelector = await page.selectorFormater(selectors.ticketSales.moreMenuState); - const inputValue = await page.evaluate(() => { - return document.querySelector('.vn-drop-down.shown vn-textfield input').value; - }); - throw new Error(`${builtSelector} value is ${inputValue}! ${error}`); - } - await page.keyboard.press('Enter'); await page.autocompleteSearch(selectors.itemFixedPrice.fourthWarehouse, 'Warehouse one'); - await page.writeOnEditableTD(selectors.itemFixedPrice.fourthPPU, '20'); - await page.writeOnEditableTD(selectors.itemFixedPrice.fourthPPP, '10'); - await page.writeOnEditableTD(selectors.itemFixedPrice.fourthMinPrice, '5'); + await page.write(selectors.itemFixedPrice.fourthPPU, '1'); + await page.write(selectors.itemFixedPrice.fourthPPP, '1'); + await page.write(selectors.itemFixedPrice.fourthMinPrice, '1'); await page.pickDate(selectors.itemFixedPrice.fourthStarted, now); await page.pickDate(selectors.itemFixedPrice.fourthEnded, now); const message = await page.waitForSnackbar(); @@ -53,7 +37,9 @@ describe('Item fixed prices path', () => { it('should reload the section and check the created price has the expected ID', async() => { await page.accessToSection('item.index'); await page.accessToSection('item.fixedPrice'); - const result = await page.getProperty('vn-fixed-price > div > vn-card > vn-table > div > vn-tbody > vn-tr:nth-child(4) > vn-td:nth-child(1) > span', 'innerText'); + await page.doSearch(); + + const result = await page.waitToGetProperty(selectors.itemFixedPrice.fourthItemID, 'value'); expect(result).toContain('13'); }); diff --git a/front/core/components/smart-table/index.js b/front/core/components/smart-table/index.js index b0b4d90dc..84c963e8e 100644 --- a/front/core/components/smart-table/index.js +++ b/front/core/components/smart-table/index.js @@ -32,6 +32,9 @@ export default class SmartTable extends Component { this._options = options; if (!options) return; + if (options.defaultSearch) + this.displaySearch(); + const activeButtons = options.activeButtons; const missingId = activeButtons && activeButtons.shownColumns && !this.viewConfigId; if (missingId) diff --git a/loopback/locale/en.json b/loopback/locale/en.json index 447288077..b7242befb 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -70,6 +70,7 @@ "Sent units from ticket": "I sent *{{quantity}}* units of [{{concept}} ({{itemId}})]({{{itemUrl}}}) to *\"{{nickname}}\"* coming from ticket id [{{ticketId}}]({{{ticketUrl}}})", "Claim will be picked": "The product from the claim [({{claimId}})]({{{claimUrl}}}) from the client *{{clientName}}* will be picked", "Claim state has changed to incomplete": "The state of the claim [({{claimId}})]({{{claimUrl}}}) from client *{{clientName}}* has changed to *incomplete*", + "Claim state has changed to canceled": "The state of the claim [({{claimId}})]({{{claimUrl}}}) from client *{{clientName}}* has changed to *canceled*", "This ticket is not an stowaway anymore": "The ticket id [{{ticketId}}]({{{ticketUrl}}}) is not an stowaway anymore", "Customs agent is required for a non UEE member": "Customs agent is required for a non UEE member", "Incoterms is required for a non UEE member": "Incoterms is required for a non UEE member", diff --git a/loopback/locale/es.json b/loopback/locale/es.json index b71d9ec74..21abc6e9e 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -137,6 +137,7 @@ "Sent units from ticket": "Envio *{{quantity}}* unidades de [{{concept}} ({{itemId}})]({{{itemUrl}}}) a *\"{{nickname}}\"* provenientes del ticket id [{{ticketId}}]({{{ticketUrl}}})", "Claim will be picked": "Se recogerá el género de la reclamación [({{claimId}})]({{{claimUrl}}}) del cliente *{{clientName}}*", "Claim state has changed to incomplete": "Se ha cambiado el estado de la reclamación [({{claimId}})]({{{claimUrl}}}) del cliente *{{clientName}}* a *incompleta*", + "Claim state has changed to canceled": "Se ha cambiado el estado de la reclamación [({{claimId}})]({{{claimUrl}}}) del cliente *{{clientName}}* a *anulado*", "This ticket is not an stowaway anymore": "El ticket id [{{ticketId}}]({{{ticketUrl}}}) ha dejado de ser un polizón", "Client checked as validated despite of duplication": "Cliente comprobado a pesar de que existe el cliente id {{clientId}}", "ORDER_ROW_UNAVAILABLE": "No hay disponibilidad de este producto", diff --git a/modules/claim/back/methods/claim/specs/updateClaim.spec.js b/modules/claim/back/methods/claim/specs/updateClaim.spec.js index de7209c18..8d888eb40 100644 --- a/modules/claim/back/methods/claim/specs/updateClaim.spec.js +++ b/modules/claim/back/methods/claim/specs/updateClaim.spec.js @@ -47,7 +47,7 @@ describe('Update Claim', () => { expect(error.message).toEqual(`You don't have enough privileges to change that field`); }); - it(`should success to update the claim within privileges `, async() => { + it(`should success to update the claimState to 'canceled' and send a rocket message`, async() => { const tx = await app.models.Claim.beginTransaction({}); try { @@ -55,13 +55,15 @@ describe('Update Claim', () => { const newClaim = await app.models.Claim.create(originalData, options); + const chatModel = app.models.Chat; + spyOn(chatModel, 'sendCheckingPresence').and.callThrough(); + const canceledState = 4; const claimManagerId = 72; const ctx = { req: { - accessToken: { - userId: claimManagerId - } + accessToken: {userId: claimManagerId}, + headers: {origin: 'http://localhost'} }, args: { observation: 'valid observation', @@ -69,11 +71,56 @@ describe('Update Claim', () => { hasToPickUp: false } }; + ctx.req.__ = (value, params) => { + return params.nickname; + }; await app.models.Claim.updateClaim(ctx, newClaim.id, options); let updatedClaim = await app.models.Claim.findById(newClaim.id, null, options); expect(updatedClaim.observation).toEqual(ctx.args.observation); + expect(chatModel.sendCheckingPresence).toHaveBeenCalled(); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it(`should success to update the claimState to 'incomplete' and send a rocket message`, async() => { + const tx = await app.models.Claim.beginTransaction({}); + + try { + const options = {transaction: tx}; + + const newClaim = await app.models.Claim.create(originalData, options); + + const chatModel = app.models.Chat; + spyOn(chatModel, 'sendCheckingPresence').and.callThrough(); + + const incompleteState = 5; + const claimManagerId = 72; + const ctx = { + req: { + accessToken: {userId: claimManagerId}, + headers: {origin: 'http://localhost'} + }, + args: { + observation: 'valid observation', + claimStateFk: incompleteState, + hasToPickUp: false + } + }; + ctx.req.__ = (value, params) => { + return params.nickname; + }; + await app.models.Claim.updateClaim(ctx, newClaim.id, options); + + let updatedClaim = await app.models.Claim.findById(newClaim.id, null, options); + + expect(updatedClaim.observation).toEqual(ctx.args.observation); + expect(chatModel.sendCheckingPresence).toHaveBeenCalled(); await tx.rollback(); } catch (e) { diff --git a/modules/claim/back/methods/claim/updateClaim.js b/modules/claim/back/methods/claim/updateClaim.js index 50ad52a6e..cc9937c19 100644 --- a/modules/claim/back/methods/claim/updateClaim.js +++ b/modules/claim/back/methods/claim/updateClaim.js @@ -96,9 +96,12 @@ module.exports = Self => { // When claimState has been changed if (args.claimStateFk) { const newState = await models.ClaimState.findById(args.claimStateFk, null, options); - - if (newState.code == 'incomplete') - notifyStateChange(ctx, salesPerson.id, claim); + if (newState.hasToNotify) { + if (newState.code == 'incomplete') + notifyStateChange(ctx, salesPerson.id, claim, newState.code); + if (newState.code == 'canceled') + notifyStateChange(ctx, claim.workerFk, claim, newState.code); + } } if (tx) await tx.commit(); @@ -125,11 +128,12 @@ module.exports = Self => { return canUpdate; } - async function notifyStateChange(ctx, workerId, claim) { - const origin = ctx.req.headers.origin; + async function notifyStateChange(ctx, workerId, claim, state) { const models = Self.app.models; + const origin = ctx.req.headers.origin; const $t = ctx.req.__; // $translate - const message = $t('Claim state has changed to incomplete', { + + const message = $t(`Claim state has changed to ${state}`, { claimId: claim.id, clientName: claim.client().name, claimUrl: `${origin}/#!/claim/${claim.id}/summary` diff --git a/modules/claim/back/models/claim-state.json b/modules/claim/back/models/claim-state.json index e0a536e11..2fd6d4845 100644 --- a/modules/claim/back/models/claim-state.json +++ b/modules/claim/back/models/claim-state.json @@ -13,20 +13,24 @@ }, "properties": { "id": { - "type": "Number", + "type": "number", "id": true, "description": "Identifier" }, "code": { - "type": "String", + "type": "string", "required": true }, "description": { - "type": "String", + "type": "string", "required": true }, "priority": { - "type": "Number", + "type": "number", + "required": true + }, + "hasToNotify": { + "type": "boolean", "required": true } }, diff --git a/modules/invoiceIn/front/descriptor/index.js b/modules/invoiceIn/front/descriptor/index.js index 952692496..cde324296 100644 --- a/modules/invoiceIn/front/descriptor/index.js +++ b/modules/invoiceIn/front/descriptor/index.js @@ -39,17 +39,25 @@ class Controller extends Descriptor { loadData() { const filter = { include: [ - { - relation: 'company', + {relation: 'supplier'}, + {relation: 'invoiceInDueDay'}, + {relation: 'company', scope: { fields: ['id', 'code'] } } + ] }; return this.getData(`InvoiceIns/${this.id}`, {filter}) - .then(res => this.entity = res.data); + .then(res => { + this.entity = res.data; + this.invoiceIn.amount = res.data.invoiceInDueDay.reduce( + (accumulator, currentValue) => { + return accumulator + (currentValue['amount'] || 0); + }, 0); + }); } checkToBook() { diff --git a/modules/invoiceIn/front/descriptor/index.spec.js b/modules/invoiceIn/front/descriptor/index.spec.js index 46815c155..7e061007f 100644 --- a/modules/invoiceIn/front/descriptor/index.spec.js +++ b/modules/invoiceIn/front/descriptor/index.spec.js @@ -12,12 +12,25 @@ describe('vnInvoiceInDescriptor', () => { controller = $componentController('vnInvoiceInDescriptor', {$element}); controller.invoiceIn = {id: 1}; - $httpBackend.when('GET', `InvoiceIns/${controller.invoiceIn.id}`).respond({id: 1}); })); describe('loadData()', () => { it(`should perform a get query to store the invoice in data into the controller`, () => { - expect(controller.invoiceIn).toEqual({id: 1}); + const invoiceIn = { + id: 1, + invoiceInDueDay: [ + {amount: 1}, + {amount: 2} + ] + }; + const expectedAmount = invoiceIn.invoiceInDueDay[0].amount + invoiceIn.invoiceInDueDay[1].amount; + + $httpBackend.when('GET', `InvoiceIns/${controller.invoiceIn.id}`).respond(invoiceIn); + controller.loadData(); + $httpBackend.flush(); + + expect(controller.invoiceIn.id).toEqual(invoiceIn.id); + expect(controller.invoiceIn.amount).toEqual(expectedAmount); }); }); diff --git a/modules/item/back/methods/fixed-price/specs/filter.spec.js b/modules/item/back/methods/fixed-price/specs/filter.spec.js index bdb28efd9..b51184de5 100644 --- a/modules/item/back/methods/fixed-price/specs/filter.spec.js +++ b/modules/item/back/methods/fixed-price/specs/filter.spec.js @@ -90,7 +90,7 @@ describe('fixed price filter()', () => { } }); - it('should return no results filtering by hasMinPrice', async() => { + it('should return 1 result filtering by hasMinPrice', async() => { const tx = await models.FixedPrice.beginTransaction({}); try { @@ -103,7 +103,7 @@ describe('fixed price filter()', () => { }; const result = await models.FixedPrice.filter(ctx, null, options); - expect(result.length).toEqual(0); + expect(result.length).toEqual(1); await tx.rollback(); } catch (e) { diff --git a/modules/item/front/fixed-price/index.html b/modules/item/front/fixed-price/index.html index 6f98ba65b..a62542c4c 100644 --- a/modules/item/front/fixed-price/index.html +++ b/modules/item/front/fixed-price/index.html @@ -3,8 +3,8 @@ url="FixedPrices/filter" limit="20" data="prices" - auto-load="true" - order="itemFk"> + order="itemFk" + auto-load="false"> -
+
- - - - Item ID - Description - Warehouse - P.P.U. - P.P.P. - Min price - Started - Ended - - - - - - - - {{price.itemFk}} - - - - {{::id}} - {{::name}} - - - - -
- {{price.name}} - -

{{price.subName}}

-
-
- - -
- - - - - - {{price.rate2 | currency: 'EUR':2}} - - - - - - - {{price.rate3 | currency: 'EUR':2}} - - - - - - - {{(price.hasMinPrice ? (price.minPrice | currency: 'EUR':2) : "-")}} - - - - - - - - - - - - - - - - - -
-
-
-
- - -
- - + options="$ctrl.smartTableOptions" + expr-builder="$ctrl.exprBuilder(param, value)"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Item ID + + Description + + Warehouse + + P.P.U. + + P.P.P. + + Min price + + Started + + Ended +
+ + +
{{id}}
+
+ {{name}} +
+
+
+
+
+ + {{price.name}} + + +

{{price.subName}}

+
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ + +
+
{ jest.spyOn(controller.vnApp, 'showSuccess'); jest.spyOn(controller.$.model, 'remove'); + $httpBackend.expectGET('Warehouses').respond(); + controller.removePrice($index); expect(controller.vnApp.showSuccess).not.toHaveBeenCalled(); diff --git a/modules/item/front/fixed-price/locale/es.yml b/modules/item/front/fixed-price/locale/es.yml index f52aef02c..3f400336d 100644 --- a/modules/item/front/fixed-price/locale/es.yml +++ b/modules/item/front/fixed-price/locale/es.yml @@ -2,4 +2,6 @@ Fixed prices: Precios fijados Search prices by item ID or code: Buscar por ID de artículo o código Search fixed prices: Buscar precios fijados Add fixed price: Añadir precio fijado -This row will be removed: Esta linea se eliminará \ No newline at end of file +This row will be removed: Esta linea se eliminará +Price By Unit: Precio Por Unidad +Price By Package: Precio Por Paquete \ No newline at end of file diff --git a/modules/item/front/fixed-price/style.scss b/modules/item/front/fixed-price/style.scss index 74df1800a..ba3878dba 100644 --- a/modules/item/front/fixed-price/style.scss +++ b/modules/item/front/fixed-price/style.scss @@ -1,5 +1,20 @@ @import "variables"; +smart-table table{ + [shrink-field]{ + width: 80px; + max-width: 80px; + } + [shrink-field-expand]{ + width: 150px; + max-width: 150px; + } +} -vn-table vn-date-picker { - max-width: 90px; +.minPrice { + align-items: center; + text-align: center; + vn-input-number { + width: 90px; + max-width: 90px; + } } \ No newline at end of file diff --git a/modules/monitor/back/methods/sales-monitor/clientsFilter.js b/modules/monitor/back/methods/sales-monitor/clientsFilter.js index 8235d5092..3d8edf608 100644 --- a/modules/monitor/back/methods/sales-monitor/clientsFilter.js +++ b/modules/monitor/back/methods/sales-monitor/clientsFilter.js @@ -40,7 +40,8 @@ module.exports = Self => { IFNULL(sc.workerSubstitute, c.salesPersonFk) AS salesPersonFk, c.id AS clientFk, c.name AS clientName, - s.lastUpdate AS dated, + TIME(v.stamp) AS hour, + DATE(v.stamp) AS dated, wtc.workerFk FROM hedera.userSession s JOIN hedera.visitUser v ON v.id = s.userVisitFk diff --git a/modules/monitor/front/index/clients/index.html b/modules/monitor/front/index/clients/index.html index 9786404fd..35b52fa09 100644 --- a/modules/monitor/front/index/clients/index.html +++ b/modules/monitor/front/index/clients/index.html @@ -2,7 +2,8 @@ vn-id="model" url="SalesMonitors/clientsFilter" limit="6" - order="dated DESC" + filter="$ctrl.filter" + order="dated DESC, hour DESC" auto-load="true"> @@ -15,87 +16,85 @@ vn-tooltip="Minimize/Maximize" ng-click="$ctrl.main.toggle()"> - - - - - - Hour - Salesperson - Client - - - - - - - {{::visit.dated | date: 'HH:mm'}} - - - - - {{::visit.salesPerson | dashIfEmpty}} - - - - - {{::visit.clientName}} - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Date + + Hour + + Salesperson + + Client +
+ + {{::visit.dated | date:'dd/MM/yy'}} + + + + {{::visit.hour | date: 'HH:mm'}} + + + + {{::visit.salesPerson | dashIfEmpty}} + + + + {{::visit.clientName}} + +
+ + - - - - - Filter by selection - - - Exclude selection - - - Remove filter - - - Remove all filters - - - Copy value - - - \ No newline at end of file + \ No newline at end of file diff --git a/modules/monitor/front/index/clients/index.js b/modules/monitor/front/index/clients/index.js index 3a69c597b..58613f09d 100644 --- a/modules/monitor/front/index/clients/index.js +++ b/modules/monitor/front/index/clients/index.js @@ -2,26 +2,89 @@ import ngModule from '../../module'; import Section from 'salix/components/section'; export default class Controller extends Section { + constructor($element, $) { + super($element, $); + + const date = new Date(); + this.dateFrom = date; + this.dateTo = date; + this.filter = { + where: { + 'v.stamp': { + between: this.dateRange() + } + } + }; + + this.smartTableOptions = { + activeButtons: { + search: true + }, + columns: [ + { + field: 'clientFk', + autocomplete: { + url: 'Clients', + showField: 'name', + valueField: 'id' + } + }, + { + field: 'salesPersonFk', + autocomplete: { + url: 'Workers/activeWithInheritedRole', + where: `{role: 'salesPerson'}`, + searchFunction: '{firstName: $search}', + showField: 'nickname', + valueField: 'id', + } + }, + { + field: 'dated', + searchable: false + }, + { + field: 'hour', + searchable: false + } + ] + }; + } + exprBuilder(param, value) { switch (param) { - case 'dated': - return {'s.lastUpdate': { - between: this.dateRange(value)} - }; case 'clientFk': + return {[`c.id`]: value}; case 'salesPersonFk': return {[`c.${param}`]: value}; } } - dateRange(value) { - const minHour = new Date(value); + dateRange() { + let from = this.dateFrom; + let to = this.dateTo; + if (!from) + from = new Date(); + if (!to) + to = new Date(); + const minHour = new Date(from); minHour.setHours(0, 0, 0, 0); - const maxHour = new Date(value); + const maxHour = new Date(to); maxHour.setHours(23, 59, 59, 59); return [minHour, maxHour]; } + + addFilterDate() { + this.$.model.filter = { + where: { + 'v.stamp': { + between: this.dateRange() + } + } + }; + this.$.model.refresh(); + } } ngModule.vnComponent('vnMonitorSalesClients', { diff --git a/modules/ticket/front/descriptor-menu/index.html b/modules/ticket/front/descriptor-menu/index.html index d613fb5de..88ed4b46b 100644 --- a/modules/ticket/front/descriptor-menu/index.html +++ b/modules/ticket/front/descriptor-menu/index.html @@ -21,7 +21,7 @@ as PDF @@ -32,6 +32,12 @@ translate> as PDF + + as PDF without prices + @@ -44,7 +50,6 @@ vn-click-stop="sendDeliveryNoteMenu.show($event, 'left')" translate> Send Delivery Note... - + + Show Proforma + { describe('showPdfDeliveryNote()', () => { it('should open a new window showing a delivery note PDF document', () => { jest.spyOn(window, 'open').mockReturnThis(); - + const type = 'deliveryNote'; const expectedParams = { ticketId: ticket.id, - recipientId: ticket.client.id + recipientId: ticket.client.id, + type: type }; const serializedParams = $httpParamSerializer(expectedParams); const expectedPath = `api/report/delivery-note?${serializedParams}`; - controller.showPdfDeliveryNote(); + controller.showPdfDeliveryNote(type); expect(window.open).toHaveBeenCalledWith(expectedPath); }); diff --git a/modules/ticket/front/descriptor-menu/locale/es.yml b/modules/ticket/front/descriptor-menu/locale/es.yml index 4a61556db..761687e74 100644 --- a/modules/ticket/front/descriptor-menu/locale/es.yml +++ b/modules/ticket/front/descriptor-menu/locale/es.yml @@ -2,7 +2,9 @@ Show Delivery Note...: Ver albarán... Send Delivery Note...: Enviar albarán... as PDF: como PDF as CSV: como CSV +as PDF without prices: como PDF sin precios Send PDF: Enviar PDF Send CSV: Enviar CSV Send CSV Delivery Note: Enviar albarán en CSV -Send PDF Delivery Note: Enviar albarán en PDF \ No newline at end of file +Send PDF Delivery Note: Enviar albarán en PDF +Show Proforma: Ver proforma \ No newline at end of file diff --git a/print/templates/reports/claim-pickup-order/claim-pickup-order.html b/print/templates/reports/claim-pickup-order/claim-pickup-order.html index 7a843c830..1f6db4966 100644 --- a/print/templates/reports/claim-pickup-order/claim-pickup-order.html +++ b/print/templates/reports/claim-pickup-order/claim-pickup-order.html @@ -78,8 +78,9 @@

{{client.name}}

- +

+

{{claimConfig.pickupContact}}

diff --git a/print/templates/reports/claim-pickup-order/claim-pickup-order.js b/print/templates/reports/claim-pickup-order/claim-pickup-order.js index fa2124057..bf975e9f2 100755 --- a/print/templates/reports/claim-pickup-order/claim-pickup-order.js +++ b/print/templates/reports/claim-pickup-order/claim-pickup-order.js @@ -7,6 +7,7 @@ module.exports = { async serverPrefetch() { this.client = await this.fetchClient(this.claimId); this.sales = await this.fetchSales(this.claimId); + this.claimConfig = await this.fetchClaimConfig(); if (!this.client) throw new Error('Something went wrong'); @@ -25,6 +26,9 @@ module.exports = { fetchSales(claimId) { return this.rawSqlFromDef('sales', [claimId]); }, + fetchClaimConfig() { + return this.findOneFromDef('claimConfig'); + }, }, components: { 'report-header': reportHeader.build(), diff --git a/print/templates/reports/claim-pickup-order/locale/es.yml b/print/templates/reports/claim-pickup-order/locale/es.yml index faa6eac33..388c1f1a6 100644 --- a/print/templates/reports/claim-pickup-order/locale/es.yml +++ b/print/templates/reports/claim-pickup-order/locale/es.yml @@ -14,4 +14,4 @@ phone: Teléfono sections: agency: description: 'Para agilizar su recogida, por favor, póngase en contacto con la oficina - de Logista Parcel.
Tlf: 96 166 77 88 - Ana Gómez (Ext. 2113) (atcsalidas.i2valencia@integra2.es)' + de Logista Parcel.' diff --git a/print/templates/reports/claim-pickup-order/sql/claimConfig.sql b/print/templates/reports/claim-pickup-order/sql/claimConfig.sql new file mode 100644 index 000000000..9d744ca6d --- /dev/null +++ b/print/templates/reports/claim-pickup-order/sql/claimConfig.sql @@ -0,0 +1,2 @@ +SELECT pickupContact + FROM claimConfig; \ No newline at end of file diff --git a/print/templates/reports/delivery-note/delivery-note.html b/print/templates/reports/delivery-note/delivery-note.html index 36d9abde1..35f9a2960 100644 --- a/print/templates/reports/delivery-note/delivery-note.html +++ b/print/templates/reports/delivery-note/delivery-note.html @@ -15,7 +15,7 @@
-

{{$t('title')}}

+

{{$t(type)}}

@@ -23,7 +23,7 @@ - + @@ -77,10 +77,10 @@ - - - - + + + + @@ -88,10 +88,10 @@ - - - - + + + + - +
{{client.id}}
{{$t('ticketId')}}{{$t(type)}} {{ticket.id}}
{{$t('reference')}} {{$t('quantity')}} {{$t('concept')}}{{$t('price')}}{{$t('discount')}}{{$t('vat')}}{{$t('amount')}}{{$t('price')}}{{$t('discount')}}{{$t('vat')}}{{$t('amount')}}
{{sale.itemFk | zerofill('000000')}} {{sale.quantity}} {{sale.concept}}{{sale.price | currency('EUR', $i18n.locale)}}{{(sale.discount / 100) | percentage}}{{sale.vatType}}{{sale.price * sale.quantity * (1 - sale.discount / 100) | currency('EUR', $i18n.locale)}}{{sale.price | currency('EUR', $i18n.locale)}}{{(sale.discount / 100) | percentage}}{{sale.vatType}}{{sale.price * sale.quantity * (1 - sale.discount / 100) | currency('EUR', $i18n.locale)}}
@@ -107,7 +107,7 @@
{{$t('subtotal')}} @@ -181,7 +181,7 @@ -
+
@@ -281,7 +281,7 @@ diff --git a/print/templates/reports/delivery-note/delivery-note.js b/print/templates/reports/delivery-note/delivery-note.js index 0ee7c8c91..adda6e756 100755 --- a/print/templates/reports/delivery-note/delivery-note.js +++ b/print/templates/reports/delivery-note/delivery-note.js @@ -44,6 +44,13 @@ module.exports = { }); return total; + }, + showPrices() { + return this.type != 'withoutPrices'; + }, + footerType() { + const translatedType = this.$t(this.type); + return `${translatedType} ${this.ticketId}`; } }, methods: { @@ -119,6 +126,10 @@ module.exports = { ticketId: { type: [Number, String], required: true + }, + type: { + type: String, + required: true } } }; diff --git a/print/templates/reports/delivery-note/locale/en.yml b/print/templates/reports/delivery-note/locale/en.yml index 16d0954e2..c74b87520 100644 --- a/print/templates/reports/delivery-note/locale/en.yml +++ b/print/templates/reports/delivery-note/locale/en.yml @@ -1,6 +1,7 @@ reportName: delivery-note -title: Delivery note -ticketId: Delivery note +deliveryNote: Delivery note +proforma: Proforma +withoutPrices: Delivery note clientId: Client deliveryAddress: Delivery address fiscalData: Fiscal data @@ -17,7 +18,6 @@ total: Total subtotal: Subtotal vatType: VAT Type digitalSignature: Digital signature -ticket: Delivery note {0} plantPassport: Plant passport packages: Packages services: diff --git a/print/templates/reports/delivery-note/locale/es.yml b/print/templates/reports/delivery-note/locale/es.yml index ca670ad59..5c5a6af4d 100644 --- a/print/templates/reports/delivery-note/locale/es.yml +++ b/print/templates/reports/delivery-note/locale/es.yml @@ -1,6 +1,7 @@ reportName: albaran -title: Albarán -ticketId: Albarán +deliveryNote: Albarán +proforma: Proforma +withoutPrices: Albarán clientId: Cliente deliveryAddress: Dirección de entrega fiscalData: Datos fiscales diff --git a/print/templates/reports/delivery-note/locale/fr.yml b/print/templates/reports/delivery-note/locale/fr.yml index 6b3779a5b..df7ca053b 100644 --- a/print/templates/reports/delivery-note/locale/fr.yml +++ b/print/templates/reports/delivery-note/locale/fr.yml @@ -1,6 +1,7 @@ reportName: bon-de-livraison -title: Bon de livraison -ticketId: BL +deliveryNote: Bon de livraison +proforma: Proforma +withoutPrices: Bon de livraison clientId: Client deliveryAddress: Adresse de livraison fiscalData: Coordonnées diff --git a/print/templates/reports/delivery-note/locale/pt.yml b/print/templates/reports/delivery-note/locale/pt.yml index 1a9c1fbd1..1f418b31f 100644 --- a/print/templates/reports/delivery-note/locale/pt.yml +++ b/print/templates/reports/delivery-note/locale/pt.yml @@ -1,6 +1,7 @@ reportName: nota-de-entrega -title: Nota de Entrega -ticketId: Nota de Entrega +deliveryNote: Nota de Entrega +proforma: Proforma +withoutPrices: Nota de Entrega clientId: Cliente deliveryAddress: Morada de Entrega fiscalData: Dados Fiscais