diff --git a/e2e/paths/05-ticket/06_basic_data_steps.spec.js b/e2e/paths/05-ticket/06_basic_data_steps.spec.js index 3191673a5..f9ad65a29 100644 --- a/e2e/paths/05-ticket/06_basic_data_steps.spec.js +++ b/e2e/paths/05-ticket/06_basic_data_steps.spec.js @@ -50,7 +50,7 @@ describe('Ticket Edit basic data path', () => { }); it(`should edit the ticket agency then check there are no zones for it`, async() => { - await page.autocompleteSearch(selectors.ticketBasicData.agency, 'Entanglement'); + await page.autocompleteSearch(selectors.ticketBasicData.agency, 'inhouse pickup'); await page.waitFor(1000); let emptyZone = await page .expectPropertyValue(selectors.ticketBasicData.zone, 'value', ''); @@ -59,6 +59,7 @@ describe('Ticket Edit basic data path', () => { }); it(`should edit the ticket zone then check the agency is for the new zone`, async() => { + await page.clearInput(selectors.ticketBasicData.agency); await page.autocompleteSearch(selectors.ticketBasicData.zone, 'Zone expensive A'); let zone = await page .waitToGetProperty(selectors.ticketBasicData.agency, 'value'); diff --git a/front/core/components/autocomplete/index.js b/front/core/components/autocomplete/index.js index 30e984fc6..b335d266f 100755 --- a/front/core/components/autocomplete/index.js +++ b/front/core/components/autocomplete/index.js @@ -248,7 +248,8 @@ export default class Autocomplete extends Field { 'where', 'order', 'limit', - 'searchFunction' + 'searchFunction', + 'whereFunction' ]); } @@ -290,6 +291,7 @@ ngModule.vnComponent('vnAutocomplete', { limit: ' - - - + ng-model="$ctrl.agencyModeId" + where-function="$ctrl.agencyModeWhere()"> + vn-acl="productionBoss" + where-function="$ctrl.zoneWhere()"> {{::name}} - Max. {{::hour | date: 'HH:mm'}} h. @@ -82,16 +92,19 @@ diff --git a/modules/ticket/front/basic-data/step-one/index.js b/modules/ticket/front/basic-data/step-one/index.js index 45fd397dd..e7eb30583 100644 --- a/modules/ticket/front/basic-data/step-one/index.js +++ b/modules/ticket/front/basic-data/step-one/index.js @@ -56,12 +56,8 @@ class Controller extends Component { set warehouseId(value) { if (value != this.ticket.warehouseFk) { this.ticket.warehouseFk = value; - this.getShipped({ - landed: this.ticket.landed, - addressFk: this.ticket.addressFk, - agencyModeFk: this.ticket.agencyModeFk, - warehouseFk: value - }); + this.ticket.agencyModeFk = null; + this.ticket.zoneFk = null; } } @@ -75,8 +71,7 @@ class Controller extends Component { shipped: value, addressFk: this.ticket.addressFk, agencyModeFk: this.ticket.agencyModeFk, - warehouseFk: this.ticket.warehouseFk, - showExpiredZones: false + warehouseFk: this.ticket.warehouseFk }); } @@ -101,12 +96,17 @@ class Controller extends Component { set agencyModeId(value) { if (value != this.ticket.agencyModeFk) { this.ticket.agencyModeFk = value; + + if (!value) return; + + const agencyMode = this.$.agencyMode.selection; + this.ticket.warehouseFk = agencyMode.warehouseFk; + this.getLanded({ shipped: this.ticket.shipped, addressFk: this.ticket.addressFk, agencyModeFk: value, - warehouseFk: this.ticket.warehouseFk, - showExpiredZones: false + warehouseFk: this.ticket.warehouseFk }); } } @@ -241,6 +241,27 @@ class Controller extends Component { || !this.ticket.companyFk || !this.ticket.shipped || !this.ticket.landed || !this.ticket.zoneFk; } + + zoneWhere() { + if (this.ticket.agencyModeFk) { + return { + shipped: this.ticket.shipped, + addressFk: this.ticket.addressFk, + agencyModeFk: this.ticket.agencyModeFk, + warehouseFk: this.ticket.warehouseFk + }; + } + return {}; + } + + agencyModeWhere() { + if (this.warehouseId) { + return { + warehouseFk: this.warehouseId + }; + } + return {}; + } } ngModule.vnComponent('vnTicketBasicDataStepOne', { diff --git a/modules/ticket/front/basic-data/step-one/index.spec.js b/modules/ticket/front/basic-data/step-one/index.spec.js index d9c72b660..bd88b88ac 100644 --- a/modules/ticket/front/basic-data/step-one/index.spec.js +++ b/modules/ticket/front/basic-data/step-one/index.spec.js @@ -94,16 +94,7 @@ describe('Ticket', () => { jest.spyOn(controller, 'getShipped'); controller.ticket.warehouseId = 1; controller.warehouseId = 2; - const landed = new Date(); - const expectedResult = { - landed: landed, - addressFk: 121, - agencyModeFk: 7, - warehouseFk: 2 - }; - controller.landed = landed; - expect(controller.getShipped).toHaveBeenCalledWith(expectedResult); expect(controller.ticket.warehouseFk).toEqual(2); }); }); @@ -125,7 +116,6 @@ describe('Ticket', () => { shipped: shipped, addressFk: 121, agencyModeFk: 7, - showExpiredZones: false, warehouseFk: 1 }; controller.shipped = shipped; @@ -170,14 +160,14 @@ describe('Ticket', () => { describe('agencyModeId() setter', () => { it('should set agencyModeId property and call getLanded() method', () => { jest.spyOn(controller, 'getLanded'); + controller.$.agencyMode = {selection: {warehouseFk: 1}}; const shipped = new Date(); const agencyModeId = 8; const expectedResult = { shipped: shipped, addressFk: 121, agencyModeFk: agencyModeId, - warehouseFk: 1, - showExpiredZones: false, + warehouseFk: 1 }; controller.ticket.shipped = shipped; controller.agencyModeId = 8; @@ -363,5 +353,31 @@ describe('Ticket', () => { expect(controller.landed).toEqual(landed); }); }); + + describe('zoneWhere() getter', () => { + it('should return an object containing filter properties', async() => { + const shipped = new Date(); + controller.ticket.shipped = shipped; + + const expectedResult = { + addressFk: 121, + agencyModeFk: 7, + shipped: shipped, + warehouseFk: 1 + }; + const result = controller.zoneWhere(); + + expect(result).toEqual(expect.objectContaining(expectedResult)); + }); + }); + + describe('agencyModeWhere() getter', () => { + it('should return an object containing the warehouseFk property', async() => { + const expectedResult = {warehouseFk: 1}; + const result = controller.agencyModeWhere(); + + expect(result).toEqual(expect.objectContaining(expectedResult)); + }); + }); }); }); diff --git a/modules/zone/back/methods/agency-mode/byWarehouse.js b/modules/zone/back/methods/agency-mode/byWarehouse.js new file mode 100644 index 000000000..f336f5ed2 --- /dev/null +++ b/modules/zone/back/methods/agency-mode/byWarehouse.js @@ -0,0 +1,38 @@ +const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; +const mergeFilters = require('vn-loopback/util/filter').mergeFilters; + +module.exports = Self => { + Self.remoteMethod('byWarehouse', { + description: 'Returns a list of agencies from a warehouse', + accepts: [{ + arg: 'filter', + type: 'Object', + description: `Filter defining where, order, offset, and limit - must be a JSON-encoded string` + }], + returns: { + type: ['object'], + root: true + }, + http: { + path: `/byWarehouse`, + verb: 'GET' + } + }); + + Self.byWarehouse = async filter => { + const conn = Self.dataSource.connector; + const where = {isActive: true}; + filter = mergeFilters(filter, {where}); + + let stmt = new ParameterizedSQL( + `SELECT id, name, warehouseFk + FROM ( + SELECT DISTINCT am.id, am.name, am.isActive, zw.warehouseFk + FROM zoneWarehouse zw + JOIN zone z ON z.id = zw.zoneFk + JOIN agencyMode am ON am.id = z.agencyModeFk) am`); + stmt.merge(conn.makeSuffix(filter)); + + return conn.executeStmt(stmt); + }; +}; diff --git a/modules/zone/back/methods/agency-mode/specs/byWarehouse.spec.js b/modules/zone/back/methods/agency-mode/specs/byWarehouse.spec.js new file mode 100644 index 000000000..a2c2ca592 --- /dev/null +++ b/modules/zone/back/methods/agency-mode/specs/byWarehouse.spec.js @@ -0,0 +1,21 @@ +const app = require('vn-loopback/server/server'); + +describe('AgencyMode byWarehhouse()', () => { + const warehouseId = 1; + it('should return all the agencies', async() => { + const where = {}; + const agencies = await app.models.AgencyMode.byWarehouse({where}); + + expect(agencies.length).toBeGreaterThan(10); + }); + + it('should return only the agencies for a warehouse', async() => { + const where = {warehouseFk: warehouseId}; + const agencies = await app.models.AgencyMode.byWarehouse({where}); + + const validWarehouse = agencies.every(agency => agency.warehouseFk = warehouseId); + + expect(agencies.length).toEqual(6); + expect(validWarehouse).toBeTruthy(); + }); +}); diff --git a/modules/zone/back/methods/agency/getLanded.js b/modules/zone/back/methods/agency/getLanded.js index ef68331e6..27ac88327 100644 --- a/modules/zone/back/methods/agency/getLanded.js +++ b/modules/zone/back/methods/agency/getLanded.js @@ -1,7 +1,7 @@ const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; module.exports = Self => { - Self.remoteMethod('getLanded', { + Self.remoteMethodCtx('getLanded', { description: 'Returns the first shipped and landed possible for params', accessType: 'READ', accepts: [{ @@ -23,11 +23,6 @@ module.exports = Self => { arg: 'warehouseFk', type: 'number', required: true - }, - { - arg: 'showExpiredZones', - type: 'boolean', - required: true }], returns: { type: 'object', @@ -39,7 +34,13 @@ module.exports = Self => { } }); - Self.getLanded = async(shipped, addressFk, agencyModeFk, warehouseFk, showExpiredZones) => { + Self.getLanded = async(ctx, shipped, addressFk, agencyModeFk, warehouseFk) => { + const userId = ctx.req.accessToken.userId; + const models = Self.app.models; + const isProductionBoss = await models.Account.hasRole(userId, 'productionBoss'); + let showExpired = false; + if (isProductionBoss) showExpired = true; + let stmts = []; stmts.push(new ParameterizedSQL( `CALL vn.zone_getLanded(?, ?, ?, ?, ?)`, [ @@ -47,7 +48,7 @@ module.exports = Self => { addressFk, agencyModeFk, warehouseFk, - showExpiredZones + showExpired ] )); diff --git a/modules/zone/back/methods/agency/specs/getLanded.spec.js b/modules/zone/back/methods/agency/specs/getLanded.spec.js index c24379530..fee3bd608 100644 --- a/modules/zone/back/methods/agency/specs/getLanded.spec.js +++ b/modules/zone/back/methods/agency/specs/getLanded.spec.js @@ -2,13 +2,13 @@ const app = require('vn-loopback/server/server'); describe('agency getLanded()', () => { it('should return a landing date', async() => { + const ctx = {req: {accessToken: {userId: 1}}}; const shipped = new Date(); shipped.setDate(shipped.getDate() + 1); const addressFk = 121; const agencyModeFk = 7; const warehouseFk = 1; - const showExpiredZones = true; - let result = await app.models.Agency.getLanded(shipped, addressFk, agencyModeFk, warehouseFk, showExpiredZones); + let result = await app.models.Agency.getLanded(ctx, shipped, addressFk, agencyModeFk, warehouseFk); expect(result.landed).toBeDefined(); }); diff --git a/modules/zone/back/methods/zone/includingExpired.js b/modules/zone/back/methods/zone/includingExpired.js new file mode 100644 index 000000000..6428d5b88 --- /dev/null +++ b/modules/zone/back/methods/zone/includingExpired.js @@ -0,0 +1,71 @@ +const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; +const mergeFilters = require('vn-loopback/util/filter').mergeFilters; + +module.exports = Self => { + Self.remoteMethodCtx('includingExpired', { + description: 'Returns a list of agencies from a warehouse', + accepts: [{ + arg: 'filter', + type: 'Object', + description: `Filter defining where, order, offset, and limit - must be a JSON-encoded string` + }], + returns: { + type: ['object'], + root: true + }, + http: { + path: `/includingExpired`, + verb: 'GET' + } + }); + + Self.includingExpired = async(ctx, filter) => { + const userId = ctx.req.accessToken.userId; + const conn = Self.dataSource.connector; + const models = Self.app.models; + const where = filter.where; + + const stmts = []; + let stmt; + + const filterByAvailability = where.shipped && where.addressFk + && where.agencyModeFk && where.warehouseFk; + + if (filterByAvailability) { + const isProductionBoss = await models.Account.hasRole(userId, 'productionBoss'); + let showExpired = false; + if (isProductionBoss) showExpired = true; + + stmt = new ParameterizedSQL(`CALL vn.zone_getLanded(?, ?, ?, ?, ?)`, [ + where.shipped, + where.addressFk, + where.agencyModeFk, + where.warehouseFk, + showExpired]); + stmts.push(stmt); + } + + delete where.shipped; + delete where.addressFk; + delete where.warehouseFk; + + stmt = new ParameterizedSQL( + `SELECT id, name, agencyModeFk + FROM vn.zone z`); + + if (filterByAvailability) + stmt.merge(`JOIN tmp.zoneGetLanded zgl ON zgl.zoneFk = z.id`); + + stmt.merge(conn.makeWhere(filter.where)); + + let index; + if (stmts.length) + index = stmts.push(stmt) - 1; + else stmts.push(stmt); + + const sql = ParameterizedSQL.join(stmts, ';'); + const result = await conn.executeStmt(sql); + + return index ? result[index] : result; + }; +}; diff --git a/modules/zone/back/methods/zone/specs/includingExpired.spec.js b/modules/zone/back/methods/zone/specs/includingExpired.spec.js new file mode 100644 index 000000000..ebda57868 --- /dev/null +++ b/modules/zone/back/methods/zone/specs/includingExpired.spec.js @@ -0,0 +1,40 @@ +const app = require('vn-loopback/server/server'); + +describe('zone includingExpired()', () => { + const inhousePickupId = 1; + const addressId = 101; + const warehouseId = 1; + + it('should return an array containing all zones', async() => { + const ctx = {req: {accessToken: {userId: 1}}}; + const where = {}; + const result = await app.models.Zone.includingExpired(ctx, {where}); + + expect(result.length).toBeGreaterThan(2); + }); + + it('should return an array containing zones from the agencyMode "Inhouse pickup"', async() => { + const ctx = {req: {accessToken: {userId: 1}}}; + const where = {agencyModeFk: inhousePickupId}; + const result = await app.models.Zone.includingExpired(ctx, {where}); + + const validAgency = result.every(zone => zone.agencyModeFk = inhousePickupId); + + expect(result.length).toEqual(3); + expect(validAgency).toBeTruthy(); + }); + + it('should return an array containing available zones', async() => { + const ctx = {req: {accessToken: {userId: 1}}}; + const where = { + shipped: new Date(), + addressFk: addressId, + agencyModeFk: inhousePickupId, + warehouseFk: warehouseId + }; + const result = await app.models.Zone.includingExpired(ctx, {where}); + const firstZone = result[0]; + + expect(firstZone.name).toEqual('Zone pickup A'); + }); +}); diff --git a/modules/zone/back/models/agency-mode.js b/modules/zone/back/models/agency-mode.js new file mode 100644 index 000000000..93658f471 --- /dev/null +++ b/modules/zone/back/models/agency-mode.js @@ -0,0 +1,3 @@ +module.exports = Self => { + require('../methods/agency-mode/byWarehouse')(Self); +}; diff --git a/modules/zone/back/models/zone.js b/modules/zone/back/models/zone.js index b0f21c998..0b1b9d106 100644 --- a/modules/zone/back/models/zone.js +++ b/modules/zone/back/models/zone.js @@ -5,6 +5,7 @@ module.exports = Self => { require('../methods/zone/toggleIsIncluded')(Self); require('../methods/zone/getUpcomingDeliveries')(Self); require('../methods/zone/deleteZone')(Self); + require('../methods/zone/includingExpired')(Self); Self.validatesPresenceOf('agencyModeFk', { message: `Agency cannot be blank`