diff --git a/db/changes/231201/.gitkeep b/db/changes/231201/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/db/changes/231201/00-wagon.sql b/db/changes/231201/00-wagon.sql new file mode 100644 index 000000000..3e4d225d7 --- /dev/null +++ b/db/changes/231201/00-wagon.sql @@ -0,0 +1,72 @@ +CREATE TABLE `vn`.`wagonType` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(30) NOT NULL UNIQUE, + `divisible` tinyint(1) NOT NULL DEFAULT 0, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb3; + +CREATE TABLE `vn`.`wagonTypeColor` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(30) NOT NULL UNIQUE, + `rgb` varchar(30) NOT NULL UNIQUE, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb3; + +CREATE TABLE `vn`.`wagonTypeTray` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `typeFk` int(11) unsigned, + `height` int(11) unsigned NOT NULL, + `colorFk` int(11) unsigned, + PRIMARY KEY (`id`), + UNIQUE KEY (`typeFk`,`height`), + CONSTRAINT `wagonTypeTray_type` FOREIGN KEY (`typeFk`) REFERENCES `wagonType` (`id`) ON UPDATE CASCADE, + CONSTRAINT `wagonTypeTray_color` FOREIGN KEY (`colorFk`) REFERENCES `wagonTypeColor` (`id`) ON UPDATE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb3; + +CREATE TABLE `vn`.`wagonConfig` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `width` int(11) unsigned DEFAULT 1350, + `height` int(11) unsigned DEFAULT 1900, + `maxWagonHeight` int(11) unsigned DEFAULT 200, + `minHeightBetweenTrays` int(11) unsigned DEFAULT 50, + `maxTrays` int(11) unsigned DEFAULT 6, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb3; + +CREATE TABLE `vn`.`collectionWagon` ( + `collectionFk` int(11) NOT NULL, + `wagonFk` int(11) NOT NULL, + `position` int(11) unsigned, + PRIMARY KEY (`collectionFk`,`position`), + UNIQUE KEY `collectionWagon_unique` (`collectionFk`,`wagonFk`), + CONSTRAINT `collectionWagon_collection` FOREIGN KEY (`collectionFk`) REFERENCES `collection` (`id`) ON UPDATE CASCADE, + CONSTRAINT `collectionWagon_wagon` FOREIGN KEY (`wagonFk`) REFERENCES `wagon` (`id`) ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; + +CREATE TABLE `vn`.`collectionWagonTicket` ( + `ticketFk` int(11) NOT NULL, + `wagonFk` int(11) NOT NULL, + `trayFk` int(11) unsigned NOT NULL, + `side` SET('L', 'R') NULL, + PRIMARY KEY (`ticketFk`), + CONSTRAINT `collectionWagonTicket_ticket` FOREIGN KEY (`ticketFk`) REFERENCES `ticket` (`id`) ON UPDATE CASCADE, + CONSTRAINT `collectionWagonTicket_wagon` FOREIGN KEY (`wagonFk`) REFERENCES `wagon` (`id`) ON UPDATE CASCADE, + CONSTRAINT `collectionWagonTicket_tray` FOREIGN KEY (`trayFk`) REFERENCES `wagonTypeTray` (`id`) ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3; + +ALTER TABLE `vn`.`wagon` ADD `typeFk` int(11) unsigned NOT NULL; +ALTER TABLE `vn`.`wagon` ADD `label` int(11) unsigned NOT NULL; +ALTER TABLE `vn`.`wagon` ADD CONSTRAINT `wagon_type` FOREIGN KEY (`typeFk`) REFERENCES `wagonType` (`id`) ON UPDATE CASCADE; + +INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) + VALUES + ('WagonType', '*', '*', 'ALLOW', 'ROLE', 'productionAssi'), + ('WagonTypeColor', '*', '*', 'ALLOW', 'ROLE', 'productionAssi'), + ('WagonTypeTray', '*', '*', 'ALLOW', 'ROLE', 'productionAssi'), + ('WagonConfig', '*', '*', 'ALLOW', 'ROLE', 'productionAssi'), + ('CollectionWagon', '*', '*', 'ALLOW', 'ROLE', 'productionAssi'), + ('CollectionWagonTicket', '*', '*', 'ALLOW', 'ROLE', 'productionAssi'), + ('Wagon', '*', '*', 'ALLOW', 'ROLE', 'productionAssi'), + ('WagonType', 'createWagonType', '*', 'ALLOW', 'ROLE', 'productionAssi'), + ('WagonType', 'deleteWagonType', '*', 'ALLOW', 'ROLE', 'productionAssi'), + ('WagonType', 'editWagonType', '*', 'ALLOW', 'ROLE', 'productionAssi'); diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index e9c70878f..1f240b684 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -2840,4 +2840,27 @@ INSERT INTO `vn`.`workerTimeControlMail` (`id`, `workerFk`, `year`, `week`, `sta (3, 9, 2000, 51, 'CONFIRMED', util.VN_NOW(), 1, NULL), (4, 9, 2001, 1, 'SENDED', util.VN_NOW(), 1, NULL); +INSERT INTO `vn`.`wagonConfig` (`id`, `width`, `height`, `maxWagonHeight`, `minHeightBetweenTrays`, `maxTrays`) + VALUES + (1, 1350, 1900, 200, 50, 6); + +INSERT INTO `vn`.`wagonTypeColor` (`id`, `name`, `rgb`) + VALUES + (1, 'white', '#ffffff'), + (2, 'red', '#ff0000'), + (3, 'green', '#00ff00'), + (4, 'blue', '#0000ff'); + +INSERT INTO `vn`.`wagonType` (`id`, `name`, `divisible`) + VALUES + (1, 'Wagon Type #1', 1); + +INSERT INTO `vn`.`wagonTypeTray` (`id`, `typeFk`, `height`, `colorFk`) + VALUES + (1, 1, 100, 1), + (2, 1, 50, 2), + (3, 1, 0, 3); + + + diff --git a/modules/wagon/back/methods/wagonType/createWagonType.js b/modules/wagon/back/methods/wagonType/createWagonType.js new file mode 100644 index 000000000..fed915b28 --- /dev/null +++ b/modules/wagon/back/methods/wagonType/createWagonType.js @@ -0,0 +1,57 @@ +module.exports = Self => { + Self.remoteMethodCtx('createWagonType', { + description: 'Creates a new wagon type', + accessType: 'WRITE', + accepts: [ + { + arg: 'name', + type: 'String', + required: true + }, + { + arg: 'divisible', + type: 'boolean', + required: true + }, { + arg: 'trays', + type: 'any', + required: true + } + ], + http: { + path: `/createWagonType`, + verb: 'PATCH' + } + }); + + Self.createWagonType = async(ctx, options) => { + const args = ctx.args; + const models = Self.app.models; + const myOptions = {}; + let tx; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + if (!myOptions.transaction) { + tx = await Self.beginTransaction({}); + myOptions.transaction = tx; + } + + try { + const newWagonType = await models.WagonType.create({name: args.name, divisible: args.divisible}, myOptions); + args.trays.forEach(async tray => { + await models.WagonTypeTray.create({ + typeFk: newWagonType.id, + height: tray.position, + colorFk: tray.color.id + }, myOptions); + }); + + if (tx) await tx.commit(); + } catch (e) { + if (tx) await tx.rollback(); + throw e; + } + }; +}; diff --git a/modules/wagon/back/methods/wagonType/deleteWagonType.js b/modules/wagon/back/methods/wagonType/deleteWagonType.js new file mode 100644 index 000000000..46b65e32f --- /dev/null +++ b/modules/wagon/back/methods/wagonType/deleteWagonType.js @@ -0,0 +1,43 @@ +module.exports = Self => { + Self.remoteMethodCtx('deleteWagonType', { + description: 'Deletes a wagon type', + accessType: 'WRITE', + accepts: [ + { + arg: 'id', + type: 'Number', + required: true + } + ], + http: { + path: `/deleteWagonType`, + verb: 'DELETE' + } + }); + + Self.deleteWagonType = async(ctx, options) => { + const args = ctx.args; + const models = Self.app.models; + const myOptions = {}; + let tx; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + if (!myOptions.transaction) { + tx = await Self.beginTransaction({}); + myOptions.transaction = tx; + } + + try { + await models.Wagon.destroyAll({typeFk: args.id}, myOptions); + await models.WagonTypeTray.destroyAll({typeFk: args.id}, myOptions); + await models.WagonType.destroyAll({id: args.id}, myOptions); + + if (tx) await tx.commit(); + } catch (e) { + if (tx) await tx.rollback(); + throw e; + } + }; +}; diff --git a/modules/wagon/back/methods/wagonType/editWagonType.js b/modules/wagon/back/methods/wagonType/editWagonType.js new file mode 100644 index 000000000..bd5ad1f16 --- /dev/null +++ b/modules/wagon/back/methods/wagonType/editWagonType.js @@ -0,0 +1,64 @@ +module.exports = Self => { + Self.remoteMethodCtx('editWagonType', { + description: 'Edits a new wagon type', + accessType: 'WRITE', + accepts: [ + { + arg: 'id', + type: 'String', + required: true + }, + { + arg: 'name', + type: 'String', + required: true + }, + { + arg: 'divisible', + type: 'boolean', + required: true + }, { + arg: 'trays', + type: 'any', + required: true + } + ], + http: { + path: `/editWagonType`, + verb: 'PATCH' + } + }); + + Self.editWagonType = async(ctx, options) => { + const args = ctx.args; + const models = Self.app.models; + const myOptions = {}; + let tx; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + if (!myOptions.transaction) { + tx = await Self.beginTransaction({}); + myOptions.transaction = tx; + } + + try { + const wagonType = await models.WagonType.findById(args.id, null, myOptions); + wagonType.updateAttributes({name: args.name, divisible: args.divisible}, myOptions); + models.WagonTypeTray.destroyAll({typeFk: args.id}, myOptions); + args.trays.forEach(async tray => { + await models.WagonTypeTray.create({ + typeFk: args.id, + height: tray.position, + colorFk: tray.color.id + }, myOptions); + }); + + if (tx) await tx.commit(); + } catch (e) { + if (tx) await tx.rollback(); + throw e; + } + }; +}; diff --git a/modules/wagon/back/methods/wagonType/specs/crudWagonType.spec.js b/modules/wagon/back/methods/wagonType/specs/crudWagonType.spec.js new file mode 100644 index 000000000..92ac61060 --- /dev/null +++ b/modules/wagon/back/methods/wagonType/specs/crudWagonType.spec.js @@ -0,0 +1,63 @@ +const models = require('vn-loopback/server/server').models; + +describe('WagonType crudWagonType()', () => { + const ctx = { + args: { + name: 'Mock wagon type', + divisible: true, + trays: [{position: 0, color: {id: 1}}, + {position: 50, color: {id: 2}}, + {position: 100, color: {id: 3}}] + } + }; + + it(`should create, edit and delete a new wagon type and its trays`, async() => { + const tx = await models.WagonType.beginTransaction({}); + + try { + const options = {transaction: tx}; + + // create + await models.WagonType.createWagonType(ctx, options); + + const newWagonType = await models.WagonType.findOne({where: {name: ctx.args.name}}, options); + const newWagonTrays = await models.WagonTypeTray.find({where: {typeFk: newWagonType.id}}, options); + + expect(newWagonType).not.toEqual(null); + expect(newWagonType.name).toEqual(ctx.args.name); + expect(newWagonType.divisible).toEqual(ctx.args.divisible); + expect(newWagonTrays.length).toEqual(ctx.args.trays.length); + + ctx.args = { + id: newWagonType.id, + name: 'Edited wagon type', + divisible: false, + trays: [{position: 0, color: {id: 1}}] + }; + + // edit + await models.WagonType.editWagonType(ctx, options); + + const editedWagonType = await models.WagonType.findById(newWagonType.id, null, options); + const editedWagonTrays = await models.WagonTypeTray.find({where: {typeFk: newWagonType.id}}, options); + + expect(editedWagonType.name).toEqual(ctx.args.name); + expect(editedWagonType.divisible).toEqual(ctx.args.divisible); + expect(editedWagonTrays.length).toEqual(ctx.args.trays.length); + + // delete + await models.WagonType.deleteWagonType(ctx, options); + + const deletedWagonType = await models.WagonType.findById(newWagonType.id, null, options); + const deletedWagonTrays = await models.WagonTypeTray.find({where: {typeFk: newWagonType.id}}, options); + + expect(deletedWagonType).toEqual(null); + expect(deletedWagonTrays).toEqual([]); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); +}); diff --git a/modules/wagon/back/model-config.json b/modules/wagon/back/model-config.json new file mode 100644 index 000000000..279d55e5c --- /dev/null +++ b/modules/wagon/back/model-config.json @@ -0,0 +1,23 @@ +{ + "Wagon": { + "dataSource": "vn" + }, + "WagonType": { + "dataSource": "vn" + }, + "WagonTypeColor": { + "dataSource": "vn" + }, + "WagonTypeTray": { + "dataSource": "vn" + }, + "WagonConfig": { + "dataSource": "vn" + }, + "CollectionWagon": { + "dataSource": "vn" + }, + "CollectionWagonTicket": { + "dataSource": "vn" + } +} diff --git a/modules/wagon/back/models/collection-wagon-ticket.json b/modules/wagon/back/models/collection-wagon-ticket.json new file mode 100644 index 000000000..04527205c --- /dev/null +++ b/modules/wagon/back/models/collection-wagon-ticket.json @@ -0,0 +1,43 @@ +{ + "name": "CollectionWagonTicket", + "base": "VnModel", + "options": { + "mysql": { + "table": "collectionWagonTicket" + } + }, + "properties": { + "ticketFk": { + "id": true, + "type": "number" + }, + "wagonFk": { + "type": "number", + "required": true + }, + "trayFk": { + "type": "number", + "required": true + }, + "side": { + "type": "string" + } + }, + "relations": { + "ticket": { + "type": "belongsTo", + "model": "Ticket", + "foreignKey": "ticketFk" + }, + "wagon": { + "type": "belongsTo", + "model": "Wagon", + "foreignKey": "wagonFk" + }, + "tray": { + "type": "belongsTo", + "model": "WagonTypeTray", + "foreignKey": "trayFk" + } + } +} diff --git a/modules/wagon/back/models/collection-wagon.json b/modules/wagon/back/models/collection-wagon.json new file mode 100644 index 000000000..f3f237428 --- /dev/null +++ b/modules/wagon/back/models/collection-wagon.json @@ -0,0 +1,34 @@ +{ + "name": "CollectionWagon", + "base": "VnModel", + "options": { + "mysql": { + "table": "collectionWagon" + } + }, + "properties": { + "collectionFk": { + "id": true, + "type": "number" + }, + "wagonFk": { + "type": "number", + "required": true + }, + "position": { + "type": "number" + } + }, + "relations": { + "collection": { + "type": "belongsTo", + "model": "Collection", + "foreignKey": "collectionFk" + }, + "wagon": { + "type": "belongsTo", + "model": "Wagon", + "foreignKey": "wagonFk" + } + } +} diff --git a/modules/wagon/back/models/wagon-config.json b/modules/wagon/back/models/wagon-config.json new file mode 100644 index 000000000..3d96e2864 --- /dev/null +++ b/modules/wagon/back/models/wagon-config.json @@ -0,0 +1,30 @@ +{ + "name": "WagonConfig", + "base": "VnModel", + "options": { + "mysql": { + "table": "wagonConfig" + } + }, + "properties": { + "id": { + "id": true, + "type": "number" + }, + "width": { + "type": "number" + }, + "height": { + "type": "string" + }, + "maxWagonHeight": { + "type": "number" + }, + "minHeightBetweenTrays": { + "type": "number" + }, + "maxTrays": { + "type": "number" + } + } +} diff --git a/modules/wagon/back/models/wagon-type-color.json b/modules/wagon/back/models/wagon-type-color.json new file mode 100644 index 000000000..573fd60f5 --- /dev/null +++ b/modules/wagon/back/models/wagon-type-color.json @@ -0,0 +1,21 @@ +{ + "name": "WagonTypeColor", + "base": "VnModel", + "options": { + "mysql": { + "table": "wagonTypeColor" + } + }, + "properties": { + "id": { + "id": true, + "type": "number" + }, + "name": { + "type": "string" + }, + "rgb": { + "type": "string" + } + } +} diff --git a/modules/wagon/back/models/wagon-type-tray.json b/modules/wagon/back/models/wagon-type-tray.json new file mode 100644 index 000000000..b61510bcf --- /dev/null +++ b/modules/wagon/back/models/wagon-type-tray.json @@ -0,0 +1,36 @@ +{ + "name": "WagonTypeTray", + "base": "VnModel", + "options": { + "mysql": { + "table": "wagonTypeTray" + } + }, + "properties": { + "id": { + "id": true, + "type": "number" + }, + "typeFk": { + "type": "number" + }, + "height": { + "type": "number" + }, + "colorFk": { + "type": "number" + } + }, + "relations": { + "type": { + "type": "belongsTo", + "model": "WagonType", + "foreignKey": "typeFk" + }, + "color": { + "type": "belongsTo", + "model": "WagonTypeColor", + "foreignKey": "colorFk" + } + } +} diff --git a/modules/wagon/back/models/wagon-type.js b/modules/wagon/back/models/wagon-type.js new file mode 100644 index 000000000..bebf7a9d9 --- /dev/null +++ b/modules/wagon/back/models/wagon-type.js @@ -0,0 +1,5 @@ +module.exports = Self => { + require('../methods/wagonType/createWagonType')(Self); + require('../methods/wagonType/editWagonType')(Self); + require('../methods/wagonType/deleteWagonType')(Self); +}; diff --git a/modules/wagon/back/models/wagon-type.json b/modules/wagon/back/models/wagon-type.json new file mode 100644 index 000000000..f57bf957d --- /dev/null +++ b/modules/wagon/back/models/wagon-type.json @@ -0,0 +1,21 @@ +{ + "name": "WagonType", + "base": "VnModel", + "options": { + "mysql": { + "table": "wagonType" + } + }, + "properties": { + "id": { + "id": true, + "type": "number" + }, + "name": { + "type": "string" + }, + "divisible": { + "type": "boolean" + } + } +} diff --git a/modules/wagon/back/models/wagon.json b/modules/wagon/back/models/wagon.json new file mode 100644 index 000000000..61ee61e61 --- /dev/null +++ b/modules/wagon/back/models/wagon.json @@ -0,0 +1,34 @@ +{ + "name": "Wagon", + "base": "VnModel", + "options": { + "mysql": { + "table": "wagon" + } + }, + "properties": { + "id": { + "id": true, + "type": "number" + }, + "label": { + "type": "number" + }, + "volume": { + "type": "number" + }, + "plate": { + "type": "string" + }, + "typeFk": { + "type": "number" + } + }, + "relations": { + "type": { + "type": "belongsTo", + "model": "WagonType", + "foreignKey": "typeFk" + } + } +}