diff --git a/db/changes/10180-holyWeek/00-claim.sql b/db/changes/10180-holyWeek/00-claim.sql new file mode 100644 index 0000000000..e3b979efe4 --- /dev/null +++ b/db/changes/10180-holyWeek/00-claim.sql @@ -0,0 +1,2 @@ +ALTER TABLE `vn`.`claim` +ADD COLUMN `hasToPickUp` TINYINT(1) NOT NULL AFTER `ticketFk`; diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 6ec1d8ebe8..bb6dbfd15d 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -613,7 +613,8 @@ export default { firstLineDestination: 'vn-claim-action vn-tr:nth-child(1) vn-autocomplete[ng-model="saleClaimed.claimDestinationFk"]', secondLineDestination: 'vn-claim-action vn-tr:nth-child(2) vn-autocomplete[ng-model="saleClaimed.claimDestinationFk"]', firstDeleteLine: 'vn-claim-action vn-tr:nth-child(1) vn-icon-button[icon="delete"]', - isPaidWithManaCheckbox: 'vn-check[ng-model="$ctrl.claim.isChargedToMana"]' + isPaidWithManaCheckbox: 'vn-claim-action vn-check[ng-model="$ctrl.claim.isChargedToMana"]', + hasToPickUpCheckbox: 'vn-claim-action vn-check[ng-model="$ctrl.claim.hasToPickUp"]' }, ordersIndex: { searchResult: 'vn-order-index vn-card > vn-table > div > vn-tbody > a.vn-tr', diff --git a/e2e/paths/06-claim/04_claim_action.spec.js b/e2e/paths/06-claim/04_claim_action.spec.js index 9897a3ef39..67c936898b 100644 --- a/e2e/paths/06-claim/04_claim_action.spec.js +++ b/e2e/paths/06-claim/04_claim_action.spec.js @@ -66,17 +66,25 @@ describe('Claim action path', () => { }); it('should check the "is paid with mana" checkbox', async() => { - page.waitFor(3000); // can't use waitForNavigation here and needs more time than a single second to get the section ready... await page.waitToClick(selectors.claimAction.isPaidWithManaCheckbox); const message = await page.waitForSnackbar(); expect(message.type).toBe('success'); }); - it('should confirm the "is paid with mana" checkbox is checked', async() => { - await page.reloadSection('claim.card.action'); - const result = await page.checkboxState(selectors.claimAction.isPaidWithManaCheckbox); + it('should check the "Pick up" checkbox', async() => { + await page.waitToClick(selectors.claimAction.hasToPickUpCheckbox); + const message = await page.waitForSnackbar(); - expect(result).toBe('checked'); + expect(message.type).toBe('success'); + }); + + it('should confirm the "is paid with mana" and "Pick up" checkbox are checked', async() => { + await page.reloadSection('claim.card.action'); + const isPaidWithManaCheckbox = await page.checkboxState(selectors.claimAction.isPaidWithManaCheckbox); + const hasToPickUpCheckbox = await page.checkboxState(selectors.claimAction.hasToPickUpCheckbox); + + expect(isPaidWithManaCheckbox).toBe('checked'); + expect(hasToPickUpCheckbox).toBe('checked'); }); }); diff --git a/front/core/components/range/index.js b/front/core/components/range/index.js index 88463e7cf0..b2525d00d2 100644 --- a/front/core/components/range/index.js +++ b/front/core/components/range/index.js @@ -47,7 +47,7 @@ export default class Range extends FormInput { } onValueUpdate() { - this.change(this.input.value); + this.change(parseInt(this.input.value)); this.$.$applyAsync(); } } diff --git a/loopback/locale/en.json b/loopback/locale/en.json index dc62e35f43..6f20b947b1 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -62,6 +62,7 @@ "MESSAGE_INSURANCE_CHANGE": "I have changed the insurence credit of client [{{clientName}} (#{{clientId}})]({{{url}}}) to *{{credit}} €*", "MESSAGE_CHANGED_PAYMETHOD": "I have changed the pay method for client [{{clientName}} (#{{clientId}})]({{{url}}})", "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", "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 da62a6a7d9..8003c31dd6 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -125,6 +125,7 @@ "MESSAGE_INSURANCE_CHANGE": "He cambiado el crédito asegurado del cliente [{{clientName}} (#{{clientId}})]({{{url}}}) a *{{credit}} €*", "MESSAGE_CHANGED_PAYMETHOD": "He cambiado la forma de pago del cliente [{{clientName}} (#{{clientId}})]({{{url}}})", "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}}*", "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/regularizeClaim.js b/modules/claim/back/methods/claim/regularizeClaim.js index adf1623c66..77e5f6504d 100644 --- a/modules/claim/back/methods/claim/regularizeClaim.js +++ b/modules/claim/back/methods/claim/regularizeClaim.js @@ -3,21 +3,22 @@ module.exports = Self => { description: 'Imports lines from claimBeginning to a new ticket with specific shipped, landed dates, agency and company', accessType: 'WRITE', accepts: [{ - arg: 'params', - type: 'object', - http: {source: 'body'} + arg: 'id', + type: 'number', + description: 'The claim id', + http: {source: 'path'} }], returns: { type: ['Object'], root: true }, http: { - path: `/regularizeClaim`, + path: `/:id/regularizeClaim`, verb: 'POST' } }); - Self.regularizeClaim = async(ctx, params) => { + Self.regularizeClaim = async(ctx, claimFk) => { const models = Self.app.models; const $t = ctx.req.__; // $translate const resolvedState = 3; @@ -31,7 +32,7 @@ module.exports = Self => { relation: 'claimDestination', fields: ['addressFk'] }, - where: {claimFk: params.claimFk} + where: {claimFk: claimFk} }, options); for (let i = 0; i < claimEnds.length; i++) { @@ -87,11 +88,32 @@ module.exports = Self => { }, options); } - let claim = await Self.findById(params.claimFk, null, options); + let claim = await Self.findById(claimFk, { + include: { + relation: 'client', + scope: { + include: { + relation: 'salesPerson' + } + } + } + }, options); claim = await claim.updateAttributes({ claimStateFk: resolvedState }, options); + // Get sales person from claim client + const salesPerson = claim.client().salesPerson(); + if (salesPerson && claim.hasToPickUp) { + const origin = ctx.req.headers.origin; + const message = $t('Claim will be picked', { + claimId: claim.id, + clientName: claim.client().name, + claimUrl: `${origin}/#!/claim/${claim.id}/summary` + }); + await models.Chat.sendCheckingPresence(ctx, salesPerson.id, message); + } + await tx.commit(); return claim; diff --git a/modules/claim/back/methods/claim/specs/regularizeClaim.spec.js b/modules/claim/back/methods/claim/specs/regularizeClaim.spec.js index c7aa1cf0a9..db8a898026 100644 --- a/modules/claim/back/methods/claim/specs/regularizeClaim.spec.js +++ b/modules/claim/back/methods/claim/specs/regularizeClaim.spec.js @@ -33,7 +33,6 @@ describe('regularizeClaim()', () => { return params.nickname; }; - let params = {claimFk: claimFk}; const chatModel = app.models.Chat; spyOn(chatModel, 'sendCheckingPresence').and.callThrough(); @@ -46,9 +45,9 @@ describe('regularizeClaim()', () => { claimEnd.updateAttributes({claimDestinationFk: trashDestination}); }); - let claimBefore = await app.models.Claim.findById(params.claimFk); - await app.models.Claim.regularizeClaim(ctx, params); - let claimAfter = await app.models.Claim.findById(params.claimFk); + let claimBefore = await app.models.Claim.findById(claimFk); + await app.models.Claim.regularizeClaim(ctx, claimFk); + let claimAfter = await app.models.Claim.findById(claimFk); trashTicket = await app.models.Ticket.findOne({where: {addressFk: 12}}); @@ -70,7 +69,6 @@ describe('regularizeClaim()', () => { return params.nickname; }; - let params = {claimFk: claimFk}; const chatModel = app.models.Chat; spyOn(chatModel, 'sendCheckingPresence').and.callThrough(); @@ -78,9 +76,35 @@ describe('regularizeClaim()', () => { claimEnd.updateAttributes({claimDestinationFk: okDestination}); }); - await app.models.Claim.regularizeClaim(ctx, params); + await app.models.Claim.regularizeClaim(ctx, claimFk); expect(chatModel.sendCheckingPresence).toHaveBeenCalledWith(ctx, 18, 'Bueno'); expect(chatModel.sendCheckingPresence).toHaveBeenCalledTimes(4); }); + + it('should send a chat message to the salesPerson when claim isPickUp is enabled', async() => { + const ctx = { + req: { + accessToken: {userId: 18}, + headers: {origin: 'http://localhost'} + } + }; + ctx.req.__ = (value, params) => { + return params.nickname; + }; + + const chatModel = app.models.Chat; + spyOn(chatModel, 'sendCheckingPresence').and.callThrough(); + + claimEnds.forEach(async claimEnd => { + claimEnd.updateAttributes({claimDestinationFk: okDestination}); + }); + + const claim = await app.models.Claim.findById(claimFk); + await claim.updateAttribute('hasToPickUp', true); + await app.models.Claim.regularizeClaim(ctx, claimFk); + + expect(chatModel.sendCheckingPresence).toHaveBeenCalledWith(ctx, 18, 'Bueno'); + expect(chatModel.sendCheckingPresence).toHaveBeenCalledTimes(5); + }); }); diff --git a/modules/claim/back/methods/claim/specs/updateClaimAction.spec.js b/modules/claim/back/methods/claim/specs/updateClaimAction.spec.js index 3d3404ac54..4848974fef 100644 --- a/modules/claim/back/methods/claim/specs/updateClaimAction.spec.js +++ b/modules/claim/back/methods/claim/specs/updateClaimAction.spec.js @@ -26,16 +26,16 @@ describe('Update Claim', () => { }); it('should update the claim isChargedToMana attribute', async() => { - const data = {isChargedToMana: false}; - const result = await app.models.Claim.updateClaimAction(newInstance.id, data); + const ctx = {args: {isChargedToMana: false}}; + const result = await app.models.Claim.updateClaimAction(ctx, newInstance.id); expect(result.id).toEqual(newInstance.id); expect(result.isChargedToMana).toBeFalsy(); }); it('should update the claim responsibility attribute', async() => { - const data = {responsibility: 2}; - const result = await app.models.Claim.updateClaimAction(newInstance.id, data); + const ctx = {args: {responsibility: 2}}; + const result = await app.models.Claim.updateClaimAction(ctx, newInstance.id); expect(result.id).toEqual(newInstance.id); expect(result.responsibility).toEqual(2); diff --git a/modules/claim/back/methods/claim/updateClaimAction.js b/modules/claim/back/methods/claim/updateClaimAction.js index c9c4f10435..69691897c6 100644 --- a/modules/claim/back/methods/claim/updateClaimAction.js +++ b/modules/claim/back/methods/claim/updateClaimAction.js @@ -1,6 +1,6 @@ module.exports = Self => { - Self.remoteMethod('updateClaimAction', { + Self.remoteMethodCtx('updateClaimAction', { description: 'Update a claim with privileges', accessType: 'WRITE', accepts: [{ @@ -10,11 +10,17 @@ module.exports = Self => { description: 'Claim id', http: {source: 'path'} }, { - arg: 'data', - type: 'object', - required: true, - description: 'Data to update on the model', - http: {source: 'body'} + arg: 'responsibility', + type: 'number', + required: false + }, { + arg: 'isChargedToMana', + type: 'boolean', + required: false + }, { + arg: 'hasToPickUp', + type: 'boolean', + required: false }], returns: { type: 'object', @@ -22,22 +28,16 @@ module.exports = Self => { }, http: { path: `/:id/updateClaimAction`, - verb: 'post' + verb: 'patch' } }); - Self.updateClaimAction = async(id, data) => { - let models = Self.app.models; + Self.updateClaimAction = async(ctx, id) => { + const models = Self.app.models; + const claim = await models.Claim.findById(id); + const args = ctx.args; + delete args.ctx; - let claim = await models.Claim.findById(id); - let updatedData = {}; - - if (data.hasOwnProperty('responsibility')) - updatedData.responsibility = data.responsibility; - - if (data.hasOwnProperty('isChargedToMana')) - updatedData.isChargedToMana = data.isChargedToMana; - - return await claim.updateAttributes(updatedData); + return await claim.updateAttributes(args); }; }; diff --git a/modules/claim/back/models/claim.json b/modules/claim/back/models/claim.json index 1462c42223..3cb64e31d5 100644 --- a/modules/claim/back/models/claim.json +++ b/modules/claim/back/models/claim.json @@ -13,7 +13,7 @@ "description": "Identifier" }, "observation": { - "type": "String" + "type": "string" }, "ticketCreated": { "type": "date", @@ -26,16 +26,19 @@ "type": "date" }, "responsibility": { - "type": "Number" + "type": "number" + }, + "hasToPickUp": { + "type": "boolean" }, "ticketFk": { - "type": "Number" + "type": "number" }, "claimStateFk": { - "type": "Number" + "type": "number" }, "workerFk": { - "type": "Number" + "type": "number" } }, "relations": { diff --git a/modules/claim/front/action/index.html b/modules/claim/front/action/index.html index 31db6dabd7..a9c1791346 100644 --- a/modules/claim/front/action/index.html +++ b/modules/claim/front/action/index.html @@ -42,15 +42,18 @@ max="$ctrl.maxResponsibility" min="1" step="1" - vn-acl="salesAssistant" - on-change="$ctrl.saveResponsibility(value)"> + on-change="$ctrl.save({responsibility: value})"> + + + on-change="$ctrl.save({isChargedToMana: value})"> diff --git a/modules/claim/front/action/index.js b/modules/claim/front/action/index.js index a847ef0093..65607e0306 100644 --- a/modules/claim/front/action/index.js +++ b/modules/claim/front/action/index.js @@ -116,9 +116,8 @@ export default class Controller extends Section { } regularize() { - let data = {claimFk: this.$params.id}; - let query = `Claims/regularizeClaim`; - return this.$http.post(query, data).then(() => { + const query = `Claims/${this.$params.id}/regularizeClaim`; + return this.$http.post(query).then(() => { if (this.claim.responsibility >= Math.ceil(this.maxResponsibility) / 2) this.$.updateGreuge.show(); else @@ -172,25 +171,15 @@ export default class Controller extends Section { this.vnApp.showSuccess(this.$translate.instant('Data saved!')); } - // Item Descriptor showDescriptor(event, itemFk) { this.$.descriptor.itemFk = itemFk; this.$.descriptor.parent = event.target; this.$.descriptor.show(); } - saveResponsibility(value) { - let query = `Claims/${this.$params.id}/updateClaimAction`; - - this.$http.post(query, {responsibility: value}).then(() => { - this.vnApp.showSuccess(this.$translate.instant('Data saved!')); - }); - } - - saveMana(value) { - let query = `Claims/${this.$params.id}/updateClaimAction`; - - this.$http.post(query, {isChargedToMana: value}).then(() => { + save(data) { + const query = `Claims/${this.$params.id}/updateClaimAction`; + this.$http.patch(query, data).then(() => { this.vnApp.showSuccess(this.$translate.instant('Data saved!')); }); } diff --git a/modules/claim/front/action/index.spec.js b/modules/claim/front/action/index.spec.js index 639e908271..8302f0ac96 100644 --- a/modules/claim/front/action/index.spec.js +++ b/modules/claim/front/action/index.spec.js @@ -143,8 +143,7 @@ describe('claim', () => { jest.spyOn(controller.card, 'reload'); jest.spyOn(controller.vnApp, 'showSuccess'); - let data = {claimFk: $state.params.id}; - $httpBackend.expect('POST', `Claims/regularizeClaim`, data).respond({}); + $httpBackend.expect('POST', `Claims/1/regularizeClaim`).respond({}); controller.regularize(); $httpBackend.flush(); @@ -153,6 +152,19 @@ describe('claim', () => { }); }); + describe('save()', () => { + it('should perform a patch query and show a success message', () => { + jest.spyOn(controller.vnApp, 'showSuccess'); + + const data = {hasToPickUp: true}; + $httpBackend.expect('PATCH', `Claims/1/updateClaimAction`, data).respond({}); + controller.save(data); + $httpBackend.flush(); + + expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!'); + }); + }); + describe('onUpdateGreugeResponse()', () => { const greugeTypeId = 7; const freightPickUpPrice = 11; diff --git a/modules/claim/front/action/locale/es.yml b/modules/claim/front/action/locale/es.yml index db1a257554..bdf4bf8e9a 100644 --- a/modules/claim/front/action/locale/es.yml +++ b/modules/claim/front/action/locale/es.yml @@ -9,4 +9,5 @@ Regularize: Regularizar Do you want to insert greuges?: Desea insertar greuges? Insert greuges on client card: Insertar greuges en la ficha del cliente Greuge inserted: Greuge insertado -ClaimGreugeDescription: Reclamación id {{claimId}} \ No newline at end of file +ClaimGreugeDescription: Reclamación id {{claimId}} +Pick up: Recoger \ No newline at end of file