diff --git a/db/dump/fixtures.before.sql b/db/dump/fixtures.before.sql index b7197d1db..c409eb692 100644 --- a/db/dump/fixtures.before.sql +++ b/db/dump/fixtures.before.sql @@ -856,14 +856,15 @@ INSERT INTO `vn`.`deliveryPoint` (`id`, `name`, `ubication`) VALUES (1, 'Gotham','1007 Mountain Drive, Gotham'); -INSERT INTO `vn`.`vehicle`(`id`, `numberPlate`, `tradeMark`, `model`, `companyFk`, `warehouseFk`, `description`, `m3`, `isActive`, `deliveryPointFk`) +INSERT INTO `vn`.`vehicle`(`id`, `numberPlate`, `tradeMark`, `model`, `companyFk`, `warehouseFk`, `description`, `m3`, `isActive`, `deliveryPointFk`, `chassis`, `leasing`, `supplierFk`, `fuelTypeFk`, `bankPolicyFk`) VALUES - (1, '3333-BAT', 'WAYNE INDUSTRIES', 'BATMOBILE', 442, 1, 'The ultimate war machine', 50, 1, 1), - (2, '1111-IMK', 'STARK INDUSTRIES', 'MARK-III', 442, 1, 'Iron-Man Heavy Armor MARK-III', 18, 1, 1), - (3, '2222-IMK', 'STARK INDUSTRIES', 'MARK-VI', 442, 1, 'Iron-Man Heavy Armor MARK-VI', 16, 1, 1), - (4, '3333-IMK', 'STARK INDUSTRIES', 'MARK-VII', 442, 1, 'Iron-Man Heavy Armor MARK-VII', 14, 1, 1), - (5, '4444-IMK', 'STARK INDUSTRIES', 'MARK-XLII', 442, 1, 'Iron-Man Heavy Armor MARK-XLII', 13, 1, 1), - (6, '5555-IMK', 'STARK INDUSTRIES', 'MARK-XLV', 442, 1, 'Iron-Man Heavy Armor MARK-XLV', 12, 0, 1); + (1, '3333-BAT', 'WAYNE INDUSTRIES', 'BATMOBILE', 442, 1, 'The ultimate war machine', 50, 1, 1, 'XCSC133C60', 'Wayne leasing', 1, 1, 1), + (2, '1111-IMK', 'STARK INDUSTRIES', 'MARK-III', 442, 1, 'Iron-Man Heavy Armor MARK-III', 18, 1, 1, '', '', 2, 2, 2), + (3, '2222-IMK', 'STARK INDUSTRIES', 'MARK-VI', 442, 1, 'Iron-Man Heavy Armor MARK-VI', 16, 1, 1, '', '', 442, 2, null), + (4, '3333-IMK', 'STARK INDUSTRIES', 'MARK-VII', 442, 1, 'Iron-Man Heavy Armor MARK-VII', 14, 1, 1, '', '', 442, 3, null), + (5, '4444-IMK', 'STARK INDUSTRIES', 'MARK-XLII', 442, 1, 'Iron-Man Heavy Armor MARK-XLII', 13, 1, 1, '', '', 442, 4, null), + (6, '5555-IMK', 'STARK INDUSTRIES', 'MARK-XLV', 442, 1, 'Iron-Man Heavy Armor MARK-XLV', 12, 0, 1, '', '', 442, 5, null), + (7, '5555-SHI', 'SHIELD', 'Quinjet', 442, 1, 'High-speed jet used by the Avengers', 30, 1, 1, 'QJ12345', 'SHIELD leasing', 1, 1, 1); INSERT INTO `vn`.`config`(`id`, `mdbServer`, `fakeEmail`, `defaultersMaxAmount`, `inventoried`) VALUES @@ -4071,3 +4072,43 @@ UPDATE vn.worker SET isFreelance=1 WHERE firstName='deliveryFreelancer'; +INSERT INTO vn.vehicleState (state, hasToNotify) + VALUES + ('Operativo', NULL), + ('Prestado', NULL), + ('Robado', NULL), + ('Taller', NULL), + ('Targeta SOLRED', NULL), + ('Via T SOLRED', NULL), + ('ITV', NULL); + +INSERT INTO vn.vehicleEvent (started, finished, vehicleStateFk, description, vehicleFk, userFk, notified) + VALUES + ('2000-12-01', '2000-12-02', 4, 'cambio de aceite', 5, 103, NULL), + ('2000-12-15', '2000-12-18', 2, 'viaje fin de curso', 5, 103, NULL), + ('2000-12-20', '2001-01-01', 3, 'llaves puestas', 2, 103, NULL); + +INSERT INTO vn.fuelType (id, name, code) + VALUES + (1, 'gasoil', 'gasoil'), + (2, 'gas', 'gas'), + (3, 'adblue', 'adblue'), + (4, 'gasolina', 'gasolina'), + (5, 'gasoil-frigo', 'gasoil-frigo'), + (6, 'electrico', 'electric'); + +INSERT INTO vn.bankPolicy (id, `ref`, amount, committedFee, nonCommittedFee, annualFee, started, ended, accountingFk, companyFk, supplierFk, description, hasGuarantee, dmsFk, notaryFk, currencyFk, amortizationTypeFk, periodicityTypeFk, insuranceExpired) + VALUES + (1, '11112222', 500000.0, 0.028, 0.0, 0.001, '2001-01-01', '2001-02-01', 1, 442, NULL, NULL, 0, NULL, NULL, 1, NULL, NULL, NULL), + (2, '33334444', 100000.0, 0.017, 0.0, 0.0, '2001-01-01', '2001-02-01', 1, 2, NULL, NULL, 0, NULL, NULL, 2, NULL, NULL, NULL); + +INSERT INTO vn.ppe (id, amortization, firstAmortizated, lastAmortizated, finished, value, planFk, groupFk, account, endowment, elementAccount, nature, location, discharged, cause, isInvestmentAsset, workerFk, companyFk, description, isDone) + VALUES + (1, 0.00, '2001-01-01', NULL, NULL, 700.95, 16, 4, '3456000000', '4320000000', '12345', 'INMOVILIZADO', 'V02', NULL, NULL, 0, NULL, 442, 'UTILLAJE LASER ROTATIVO AUTONIVELANTE 500M', NULL), + (2, 0.00, '2001-01-01', NULL, NULL, 400.00, 16, 4, '5678000000', '1230000000', '67891', 'INMOVILIZADO', 'V02', NULL, NULL, 0, NULL, 442, 'UTILLAJE BALANZA Z100 150KILOS', NULL); + +INSERT IGNORE INTO vn.vehicleType (id, name) + VALUES (1,'vehículo empresa'), + (2, 'furgoneta'), + (3, 'cabeza tractora'), + (4, 'remolque'); \ No newline at end of file diff --git a/db/versions/11394-brownAsparagus/00-firstScript.sql b/db/versions/11394-brownAsparagus/00-firstScript.sql new file mode 100644 index 000000000..13b6cfa0d --- /dev/null +++ b/db/versions/11394-brownAsparagus/00-firstScript.sql @@ -0,0 +1,41 @@ +USE vn; + +INSERT INTO salix.ACL (model, property, accessType, permission, principalType, principalId) + VALUES ('Vehicle', 'filter', 'READ', 'ALLOW', 'ROLE', 'administrative'), + ('Vehicle', 'filter', 'READ', 'ALLOW', 'ROLE', 'deliveryAssistant'), + ('Vehicle', 'find', 'READ', 'ALLOW', 'ROLE', 'administrative'), + ('Vehicle', 'find', 'READ', 'ALLOW', 'ROLE', 'deliveryAssistant'), + ('Vehicle', 'findById', 'READ', 'ALLOW', 'ROLE', 'administrative'), + ('Vehicle', 'findById', 'READ', 'ALLOW', 'ROLE', 'deliveryAssistant'), + ('Vehicle', '__get__active', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('Vehicle', 'updateAttributes', 'WRITE', 'ALLOW', 'ROLE', 'administrative'), + ('Vehicle', 'updateAttributes', 'WRITE', 'ALLOW', 'ROLE', 'deliveryAssistant'), + ('Vehicle', 'deleteById', 'WRITE', 'ALLOW', 'ROLE', 'administrative'), + ('Vehicle', 'deleteById', 'WRITE', 'ALLOW', 'ROLE', 'deliveryAssistant'), + ('Vehicle', 'create', 'WRITE', 'ALLOW', 'ROLE', 'administrative'), + ('Vehicle', 'create', 'WRITE', 'ALLOW', 'ROLE', 'deliveryAssistant'), + ('BankPolicy', 'find', 'READ', 'ALLOW', 'ROLE', 'administrative'), + ('BankPolicy', 'find', 'READ', 'ALLOW', 'ROLE', 'deliveryAssistant'), + ('VehicleState', 'find', 'READ', 'ALLOW', 'ROLE', 'administrative'), + ('VehicleState', 'find', 'READ', 'ALLOW', 'ROLE', 'deliveryAssistant'), + ('Ppe', 'find', 'READ', 'ALLOW', 'ROLE', 'administrative' ), + ('Ppe', 'find', 'READ', 'ALLOW', 'ROLE', 'deliveryAssistant' ), + ('VehicleType', 'find', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('DeliveryPoint', 'find', 'READ', 'ALLOW', 'ROLE', 'deliveryAssistant'), + ('DeliveryPoint', 'find', 'READ', 'ALLOW', 'ROLE', 'administrative'); + +CREATE TABLE IF NOT EXISTS vehicleType ( + id INT(11) PRIMARY KEY AUTO_INCREMENT, + name VARCHAR(45) NOT NULL +); + +INSERT IGNORE INTO vehicleType (id, name) + VALUES (1,'vehículo empresa'), + (2, 'furgoneta'), + (3, 'cabeza tractora'), + (4, 'remolque'); + +ALTER TABLE vehicle ADD COLUMN importCooler decimal(10,2) DEFAULT NULL; +ALTER TABLE vehicle ADD COLUMN vehicleTypeFk INT(11) DEFAULT 1; +ALTER TABLE vehicle ADD CONSTRAINT fk_vehicle_vehicleType FOREIGN KEY (vehicleTypeFk) REFERENCES vehicleType(id); + diff --git a/modules/route/back/methods/vehicle/filter.js b/modules/route/back/methods/vehicle/filter.js new file mode 100644 index 000000000..cb55f5f3c --- /dev/null +++ b/modules/route/back/methods/vehicle/filter.js @@ -0,0 +1,128 @@ +const {ParameterizedSQL} = require('loopback-connector'); +const {buildFilter, mergeFilters} = require('vn-loopback/util/filter'); + +module.exports = Self => { + Self.remoteMethodCtx('filter', { + description: 'Find all instances of the model matched by filter from the data source.', + accessType: 'READ', + accepts: [{ + arg: 'filter', + type: 'object', + description: 'Filter defining where, order, skip and limit - must be a JSON-encoded string', + http: {source: 'query'} + }, { + arg: 'search', + type: 'string', + description: 'Searchs the vehicle by id or numberPlate', + http: {source: 'query'} + }, { + arg: 'id', + type: 'number' + }, { + arg: 'description', + type: 'string' + }, { + arg: 'companyFk', + type: 'number' + }, { + arg: 'tradeMark', + type: 'string' + }, { + arg: 'numberPlate', + type: 'string' + }, { + arg: 'warehouseFk', + type: 'number' + }, { + arg: 'chassis', + type: 'string' + }, { + arg: 'leasing', + type: 'string' + }, { + arg: 'countryCodeFk', + type: 'string' + }, { + arg: 'vehicleTypeFk', + type: 'number' + }, { + arg: 'vehicleStateFk', + type: 'number' + }], + returns: { + type: ['object'], + root: true + }, + http: { + path: `/filter`, + verb: `GET` + } + }); + + Self.filter = async(ctx, filter, options) => { + const conn = Self.dataSource.connector; + const myOptions = {}; + + if (typeof options == 'object') Object.assign(myOptions, options); + + const where = buildFilter(ctx.args, (param, value) => { + switch (param) { + case 'search': + return {or: [{'v.id': value}, {numberPlate: {like: `%${value}%`}}]}; + case 'id': + return {'v.id': value}; + case 'description': + case 'tradeMark': + case 'numberPlate': + case 'chassis': + case 'leasing': + return {[param]: {like: `%${value}%`}}; + case 'companyFk': + case 'warehouseFk': + case 'countryCodeFk': + case 'vehicleStateFk': + case 'vehicleTypeFk': + return {[param]: value}; + } + }); + + filter = mergeFilters(filter, {where}); + + const stmt = new ParameterizedSQL(` + SELECT v.id, + v.numberPlate, + v.tradeMark, + v.model, + v.m3, + v.description, + v.isActive, + v.countryCodeFk, + v.chassis, + v.leasing, + vt.name type, + w.name warehouse, + c.code company, + sub.state + FROM vehicle v + JOIN vehicleType vt ON vt.id = v.vehicleTypeFk + LEFT JOIN warehouse w ON w.id = v.warehouseFk + LEFT JOIN company c ON c.id = v.companyFk + LEFT JOIN ( + SELECT e.vehicleFk, + e.vehicleStateFk, + s.state, + ROW_NUMBER() OVER (PARTITION BY e.vehicleFk ORDER BY e.started DESC) rn + FROM vehicleEvent e + LEFT JOIN vehicleState s ON e.vehicleStateFk = s.id + ) sub ON sub.vehicleFk = v.id AND sub.rn = 1 + `); + + const sqlWhere = conn.makeWhere(filter.where); + stmt.merge(sqlWhere); + stmt.merge(conn.makePagination(filter)); + + const sql = ParameterizedSQL.join([stmt], ';'); + + return conn.executeStmt(sql, myOptions); + }; +}; diff --git a/modules/route/back/methods/vehicle/specs/filter.spec.js b/modules/route/back/methods/vehicle/specs/filter.spec.js new file mode 100644 index 000000000..52e0b8a39 --- /dev/null +++ b/modules/route/back/methods/vehicle/specs/filter.spec.js @@ -0,0 +1,127 @@ +const {models} = require('vn-loopback/server/server'); + +describe('Vehicle filter()', () => { + const deliveryAssiId = 123; + const ctx = beforeAll.getCtx(deliveryAssiId); + let options; + let tx; + + beforeEach(async() => { + ctx.args = {}; + options = {}; + tx = await models.Sale.beginTransaction({}); + options.transaction = tx; + }); + + afterEach(async() => { + await tx.rollback(); + }); + + it('should return the vehicles matching "search"', async() => { + const {id} = await models.Vehicle.findById(1, null, options); + const {numberPlate} = await models.Vehicle.findById(2, null, options); + + ctx.args = {search: id}; + const [searchResult] = await models.Vehicle.filter(ctx); + ctx.args = {search: numberPlate}; + const [searchResult2] = await models.Vehicle.filter(ctx); + + expect(searchResult.id).toEqual(id); + expect(searchResult2.numberPlate).toEqual(numberPlate); + }); + + it('should return the vehicles matching "companyFk"', async() => { + const company = await models.Company.findOne({where: {code: 'VNL'}}, options); + ctx.args = {companyFk: company.id}; + const searchResult = await models.Vehicle.filter(ctx, null, options); + searchResult.forEach(record => { + expect(record.company).toEqual(company.code); + }); + }); + + it('should return the vehicles matching "tradeMark"', async() => { + const tradeMark = 'WAYNE INDUSTRIES'; + ctx.args = {tradeMark}; + const searchResult = await models.Vehicle.filter(ctx); + searchResult.forEach(record => { + expect(record.tradeMark).toEqual(tradeMark); + }); + }); + + it('should return the vehicles matching "numberPlate"', async() => { + const {numberPlate} = await models.Vehicle.findById(1, null, options); + ctx.args = {numberPlate}; + + const searchResult = await models.Vehicle.filter(ctx); + + searchResult.forEach(record => { + expect(record.numberPlate).toEqual(numberPlate); + }); + }); + + it('should return the vehicles matching "warehouseFk"', async() => { + const warehouse = await models.Warehouse.findById(1, null, options); + ctx.args = {warehouseFk: warehouse.id}; + const searchResult = await models.Vehicle.filter(ctx); + searchResult.forEach(record => { + expect(record.warehouse).toEqual(warehouse.name); + }); + }); + + it('should return the vehicles matching "chassis"', async() => { + const {chassis} = await models.Vehicle.findById(1, null, options); + ctx.args = {chassis}; + const [searchResult] = await models.Vehicle.filter(ctx); + + expect(searchResult.chassis).toEqual(chassis); + }); + + it('should return the vehicles matching "leasing"', async() => { + const leasing = 'Wayne leasing'; + ctx.args = {leasing}; + const searchResult = await models.Vehicle.filter(ctx); + searchResult.forEach(record => { + expect(record.leasing).toEqual(leasing); + }); + }); + + it('should return the vehicles matching "countryCodeFk"', async() => { + const countryCodeFk = 'ES'; + ctx.args = {countryCodeFk}; + + const searchResult = await models.Vehicle.filter(ctx); + searchResult.forEach(record => { + expect(record.countryCodeFk).toEqual(countryCodeFk); + }); + }); + + it('should return the vehicles matching "vehicleTypeFk"', async() => { + const {name, id} = await models.VehicleType.findById(1, null, options); + ctx.args = {vehicleTypeFk: id}; + + const searchResult = await models.Vehicle.filter(ctx); + searchResult.forEach(record => { + expect(record.type).toEqual(name); + }); + }); + + it('should return the vehicles matching "vehicleStateFk"', async() => { + const {state, id} = await models.VehicleState.findById(3); + ctx.args = {vehicleStateFk: id}; + + const searchResult = await models.Vehicle.filter(ctx); + searchResult.forEach(record => { + expect(record.state).toEqual(state); + }); + }); + + it('should return the vehicles matching "description"', async() => { + const {description} = await models.Vehicle.findById(2); + ctx.args = {description}; + + const searchResult = await models.Vehicle.filter(ctx); + searchResult.forEach(record => { + expect(record.description).toEqual(description); + }); + }); +}); diff --git a/modules/route/back/model-config.json b/modules/route/back/model-config.json index fb1c5d7fd..3a7c9e06b 100644 --- a/modules/route/back/model-config.json +++ b/modules/route/back/model-config.json @@ -5,12 +5,21 @@ "AgencyTermConfig": { "dataSource": "vn" }, + "BankPolicy": { + "dataSource": "vn" + }, "Cmr": { "dataSource": "vn" }, "DeliveryPoint": { "dataSource": "vn" }, + "FuelType": { + "dataSource": "vn" + }, + "Ppe": { + "dataSource": "vn" + }, "RoadmapAddress": { "dataSource": "vn" }, @@ -35,6 +44,12 @@ "Vehicle": { "dataSource": "vn" }, + "VehicleState": { + "dataSource": "vn" + }, + "VehicleType": { + "dataSource": "vn" + }, "RoutesMonitor": { "dataSource": "vn" } diff --git a/modules/route/back/models/bank-policy.json b/modules/route/back/models/bank-policy.json new file mode 100644 index 000000000..55a409a67 --- /dev/null +++ b/modules/route/back/models/bank-policy.json @@ -0,0 +1,21 @@ +{ + "name": "BankPolicy", + "base": "VnModel", + "options": { + "mysql": { + "table": "bankPolicy" + } + }, + "properties": { + "id": { + "type": "number", + "id": true + }, + "ref": { + "type": "string" + }, + "dmsFk": { + "type": "number" + } + } +} \ No newline at end of file diff --git a/modules/route/back/models/fuel-type.json b/modules/route/back/models/fuel-type.json new file mode 100644 index 000000000..d42614837 --- /dev/null +++ b/modules/route/back/models/fuel-type.json @@ -0,0 +1,30 @@ +{ + "name": "FuelType", + "base": "VnModel", + "options": { + "mysql": { + "table": "fuelType" + } + }, + "properties": { + "id": { + "type": "number", + "id": true, + "description": "Identifier" + }, + "name": { + "type": "string" + }, + "code": { + "type": "string" + } + }, + "acls": [ + { + "accessType": "READ", + "principalType": "ROLE", + "principalId": "$everyone", + "permission": "ALLOW" + } + ] +} \ No newline at end of file diff --git a/modules/route/back/models/ppe.json b/modules/route/back/models/ppe.json new file mode 100644 index 000000000..0825d348c --- /dev/null +++ b/modules/route/back/models/ppe.json @@ -0,0 +1,15 @@ +{ + "name": "Ppe", + "base": "VnModel", + "options": { + "mysql": { + "table": "ppe" + } + }, + "properties": { + "id": { + "type": "number", + "id": true + } + } +} \ No newline at end of file diff --git a/modules/route/back/models/vehicle-state.json b/modules/route/back/models/vehicle-state.json new file mode 100644 index 000000000..b53719f63 --- /dev/null +++ b/modules/route/back/models/vehicle-state.json @@ -0,0 +1,21 @@ +{ + "name": "VehicleState", + "base": "VnModel", + "options": { + "mysql": { + "table": "vehicleState" + } + }, + "properties": { + "id": { + "type": "number", + "id": true + }, + "state": { + "type": "string" + }, + "hasToNotify": { + "type": "number" + } + } +} \ No newline at end of file diff --git a/modules/route/back/models/vehicle-type.json b/modules/route/back/models/vehicle-type.json new file mode 100644 index 000000000..34beb6dfb --- /dev/null +++ b/modules/route/back/models/vehicle-type.json @@ -0,0 +1,19 @@ +{ + "name": "VehicleType", + "base": "VnModel", + "options": { + "mysql": { + "table": "vehicleType" + } + }, + "properties": { + "id": { + "type": "number", + "id": true, + "description": "Identifier" + }, + "name": { + "type": "string" + } + } +} \ No newline at end of file diff --git a/modules/route/back/models/vehicle.js b/modules/route/back/models/vehicle.js index 73e321443..59aa7cb8b 100644 --- a/modules/route/back/models/vehicle.js +++ b/modules/route/back/models/vehicle.js @@ -1,3 +1,4 @@ module.exports = Self => { require('../methods/vehicle/sorted')(Self); + require('../methods/vehicle/filter')(Self); }; diff --git a/modules/route/back/models/vehicle.json b/modules/route/back/models/vehicle.json index 34a376b89..d64f3df79 100644 --- a/modules/route/back/models/vehicle.json +++ b/modules/route/back/models/vehicle.json @@ -3,7 +3,7 @@ "base": "VnModel", "options": { "mysql": { - "table": "vehicle" + "table": "vehicle" } }, "properties": { @@ -29,6 +29,39 @@ }, "isActive": { "type": "number" + }, + "countryCodeFk": { + "type": "string" + }, + "chassis": { + "type": "string" + }, + "leasing": { + "type": "string" + }, + "isKmTruckRate": { + "type": "number" + }, + "fuelTypeFk": { + "type": "number" + }, + "import": { + "type": "number" + }, + "importCooler": { + "type": "number" + }, + "vin": { + "type": "string" + }, + "ppeFk": { + "type": "number" + }, + "vehicleTypeFk": { + "type": "number" + }, + "deliveryPointFk": { + "type": "number" } }, "relations": { @@ -46,21 +79,57 @@ "type": "belongsTo", "model": "DeliveryPoint", "foreignKey": "deliveryPointFk" + }, + "event": { + "type": "hasMany", + "model": "VehicleEvent", + "foreignKey": "vehicleFk", + "property": "id" + }, + "supplier": { + "type": "belongsTo", + "model": "Supplier", + "foreignKey": "supplierFk" + }, + "supplierCooler": { + "type": "belongsTo", + "model": "Supplier", + "foreignKey": "supplierCoolerFk" + }, + "bankPolicy": { + "type": "belongsTo", + "model": "BankPolicy", + "foreignKey": "bankPolicyFk" + }, + "fuelType": { + "type": "belongsTo", + "model": "FuelType", + "foreignKey": "fuelTypeFk" + }, + "ppe": { + "type": "hasOne", + "model": "Ppe", + "foreignKey": "id", + "property": "ppeFk" + }, + "type": { + "type": "hasOne", + "model": "VehicleType", + "foreignKey": "id", + "property": "vehicleTypeFk" } }, - "scope": { - "where": { - "isActive": { + "scopes": { + "active": { + "fields": [ + "id", + "numberPlate" + ], + "where": { + "isActive": { "neq": false } } - }, - "acls": [ - { - "accessType": "READ", - "principalType": "ROLE", - "principalId": "$everyone", - "permission": "ALLOW" } - ] -} + } +} \ No newline at end of file