From 7693a1c449a0a6a93599a56cda637ce9a81044db Mon Sep 17 00:00:00 2001 From: joan Date: Fri, 20 Nov 2020 15:05:57 +0100 Subject: [PATCH] 2569 - Section changes --- back/model-config.json | 3 + back/models/continent.json | 27 +++ db/changes/10250-curfew/03-continent.sql | 20 +++ db/changes/10250-curfew/04-country.sql | 13 ++ db/config.ini | 1 + db/dump/fixtures.sql | 42 ++--- front/core/components/th/index.html | 4 +- front/core/components/th/index.js | 16 +- front/core/components/th/style.scss | 10 +- front/salix/components/descriptor/index.html | 2 +- loopback/server/connectors/vn-mysql.js | 26 +++ .../back/methods/item/specs/getDiary.spec.js | 6 +- .../methods/travel/extraCommunityFilter.js | 162 ++++++++---------- .../travel/specs/extraCommunityFilter.spec.js | 66 +++++++ modules/travel/front/descriptor/locale/es.yml | 4 +- .../extra-community-search-panel/index.html | 91 ++++++++++ .../extra-community-search-panel/index.js | 7 + .../travel/front/extra-community/index.html | 120 +++++++++---- modules/travel/front/extra-community/index.js | 85 ++++++++- .../front/extra-community/index.spec.js | 47 +++++ .../front/extra-community/locale/es.yml | 9 +- .../travel/front/extra-community/style.scss | 40 ++++- modules/travel/front/index.js | 1 + modules/travel/front/routes.json | 2 +- modules/travel/front/summary/locale/es.yml | 4 +- 25 files changed, 635 insertions(+), 173 deletions(-) create mode 100644 back/models/continent.json create mode 100644 db/changes/10250-curfew/03-continent.sql create mode 100644 db/changes/10250-curfew/04-country.sql create mode 100644 modules/travel/back/methods/travel/specs/extraCommunityFilter.spec.js create mode 100644 modules/travel/front/extra-community-search-panel/index.html create mode 100644 modules/travel/front/extra-community-search-panel/index.js create mode 100644 modules/travel/front/extra-community/index.spec.js diff --git a/back/model-config.json b/back/model-config.json index da9feaa1f..277f933e1 100644 --- a/back/model-config.json +++ b/back/model-config.json @@ -20,6 +20,9 @@ "Container": { "dataSource": "storage" }, + "Continent": { + "dataSource": "vn" + }, "Collection": { "dataSource": "vn" }, diff --git a/back/models/continent.json b/back/models/continent.json new file mode 100644 index 000000000..090bada09 --- /dev/null +++ b/back/models/continent.json @@ -0,0 +1,27 @@ +{ + "name": "Continent", + "base": "VnModel", + "options": { + "mysql": { + "table": "continent" + } + }, + "properties": { + "id": { + "type": "number" + }, + "name": { + "type": "string" + }, + "code": { + "id": true, + "type": "string" + } + }, + "acls": [{ + "accessType": "READ", + "principalType": "ROLE", + "principalId": "$everyone", + "permission": "ALLOW" + }] +} \ No newline at end of file diff --git a/db/changes/10250-curfew/03-continent.sql b/db/changes/10250-curfew/03-continent.sql new file mode 100644 index 000000000..279a73669 --- /dev/null +++ b/db/changes/10250-curfew/03-continent.sql @@ -0,0 +1,20 @@ +CREATE TABLE `vn`.continent +( + id TINYINT(4) AUTO_INCREMENT, + name VARCHAR(50) NOT NULL, + code VARCHAR(2) NOT NULL COLLATE utf8_general_ci, + CONSTRAINT continent_pk + PRIMARY KEY (id) +) + COMMENT 'World continents'; + +CREATE UNIQUE INDEX continent_name_uindex + ON `vn`.continent (name); + +INSERT IGNORE INTO `vn`.continent (`name`, `code`) + VALUES + ('Asia', 'AS'), + ('América', 'AM'), + ('África', 'AF'), + ('Europa', 'EU'), + ('Oceanía', 'OC'); \ No newline at end of file diff --git a/db/changes/10250-curfew/04-country.sql b/db/changes/10250-curfew/04-country.sql new file mode 100644 index 000000000..e7ffbc67f --- /dev/null +++ b/db/changes/10250-curfew/04-country.sql @@ -0,0 +1,13 @@ +ALTER TABLE `vn`.`country` + ADD COLUMN `continentFk` TINYINT(4) NULL AFTER `ibanLength`, + ADD INDEX `continent_id_fk_idx` (`continentFk` ASC); + +ALTER TABLE `vn`.`country` +ADD CONSTRAINT `continent_id_fk` + FOREIGN KEY (`continentFk`) + REFERENCES `vn`.`continent` (`id`) + ON DELETE NO ACTION + ON UPDATE CASCADE; + +UPDATE `vn`.`country` SET `continentFk` = '2' WHERE (`id` = '11'); +UPDATE `vn`.`country` SET `continentFk` = '2' WHERE (`id` = '13'); diff --git a/db/config.ini b/db/config.ini index 7800cadfd..2caf3c2b9 100644 --- a/db/config.ini +++ b/db/config.ini @@ -3,3 +3,4 @@ host = localhost port = 3306 user = root password = root +default-character-set=utf8 diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 2e00878d2..5503a0f7a 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -92,17 +92,17 @@ INSERT INTO `vn`.`worker`(`id`, `code`, `firstName`, `lastName`, `userFk`,`bossF (109, 'HLK', 'Bruce' , 'Banner', 109, 19, 432978109), (110, 'JJJ', 'Jessica' , 'Jones' , 110, 19, 432978110); -INSERT INTO `vn`.`country`(`id`, `country`, `isUeeMember`, `code`, `currencyFk`, `ibanLength`) +INSERT INTO `vn`.`country`(`id`, `country`, `isUeeMember`, `code`, `currencyFk`, `ibanLength`, `continentFk`) VALUES - (1, 'España', 1, 'ES', 1, 24), - (2, 'Italia', 1, 'IT', 1, 27), - (3, 'Alemania', 1, 'DE', 1, 22), - (4, 'Rumania', 1, 'RO', 1, 24), - (5, 'Holanda', 1, 'NL', 1, 18), - (8, 'Portugal', 1, 'PT', 1, 27), - (13,'Ecuador', 0, 'EC', 1, 24), - (19,'Francia', 1, 'FR', 1, 27), - (30,'Canarias', 1, 'IC', 1, 24); + (1, 'España', 1, 'ES', 1, 24, 4), + (2, 'Italia', 1, 'IT', 1, 27, 4), + (3, 'Alemania', 1, 'DE', 1, 22, 4), + (4, 'Rumania', 1, 'RO', 1, 24, 4), + (5, 'Holanda', 1, 'NL', 1, 18, 4), + (8, 'Portugal', 1, 'PT', 1, 27, 4), + (13,'Ecuador', 0, 'EC', 1, 24, 2), + (19,'Francia', 1, 'FR', 1, 27, 4), + (30,'Canarias', 1, 'IC', 1, 24, 4); INSERT INTO `hedera`.`language` (`code`, `name`, `orgName`, `isActive`) VALUES @@ -118,13 +118,13 @@ INSERT INTO `vn`.`warehouseAlias`(`id`, `name`) (1, 'Main Warehouse'), (2, 'Silla'); -INSERT INTO `vn`.`warehouse`(`id`, `name`, `isComparative`, `isInventory`, `hasAvailable`, `isManaged`, `hasStowaway`, `hasDms`, `hasComission`, `aliasFk`) +INSERT INTO `vn`.`warehouse`(`id`, `name`, `isComparative`, `isInventory`, `hasAvailable`, `isManaged`, `hasStowaway`, `hasDms`, `hasComission`, `aliasFk`, `countryFk`) VALUES - (1, 'Warehouse One', 1, 1, 1, 1, 1, 1, 1, 2), - (2, 'Warehouse Two', 1, 1, 1, 1, 0, 0, 1, 2), - (3, 'Warehouse Three', 1, 1, 1, 1, 0, 0, 0, 2), - (4, 'Warehouse Four', 1, 1, 1, 1, 0, 0, 0, 2), - (5, 'Warehouse Five', 1, 1, 1, 1, 0, 0, 0, 2); + (1, 'Warehouse One', 1, 1, 1, 1, 1, 1, 1, 2, 1), + (2, 'Warehouse Two', 1, 1, 1, 1, 0, 0, 1, 2, 13), + (3, 'Warehouse Three', 1, 1, 1, 1, 0, 0, 0, 2, 1), + (4, 'Warehouse Four', 1, 1, 1, 1, 0, 0, 0, 2, 1), + (5, 'Warehouse Five', 1, 1, 1, 1, 0, 0, 0, 2, 1); INSERT INTO `vn`.`sector`(`id`, `description`, `warehouseFk`, `isPreviousPreparedByPacking`, `code`, `pickingPlacement`, `path`) VALUES @@ -1250,11 +1250,11 @@ INSERT INTO `vn`.`travel`(`id`,`shipped`, `landed`, `warehouseInFk`, `warehouseO (1, DATE_ADD(CURDATE(), INTERVAL -2 MONTH), DATE_ADD(CURDATE(), INTERVAL -2 MONTH), 1, 2, 1, 100.00, 1000, 'first travel', 1, 1), (2, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1, 2, 1, 150, 2000, 'second travel', 2, 2), (3, CURDATE(), CURDATE(), 1, 2, 1, 0.00, 0.00, 'third travel', 1, 1), - (4, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1, 2, 1, 50.00, 500, 'fourth travel', 0, 2), - (5, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 3, 2, 1, 50.00, 500, 'fifth travel', 1, 1), - (6, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 4, 2, 1, 50.00, 500, 'sixth travel', 1, 2), - (7, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 5, 2, 1, 50.00, 500, 'seventh travel', 2, 1), - (8, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 5, 2, 1, 50.00, 500, 'eight travel', 1, 2); + (4, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1, 3, 1, 50.00, 500, 'fourth travel', 0, 2), + (5, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 3, 3, 1, 50.00, 500, 'fifth travel', 1, 1), + (6, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 4, 4, 1, 50.00, 500, 'sixth travel', 1, 2), + (7, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 5, 4, 1, 50.00, 500, 'seventh travel', 2, 1), + (8, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 5, 1, 1, 50.00, 500, 'eight travel', 1, 2); INSERT INTO `vn`.`entry`(`id`, `supplierFk`, `created`, `travelFk`, `isConfirmed`, `companyFk`, `ref`,`isInventory`, `isRaid`, `notes`, `evaNotes`) VALUES diff --git a/front/core/components/th/index.html b/front/core/components/th/index.html index 281c6866c..28d80695d 100644 --- a/front/core/components/th/index.html +++ b/front/core/components/th/index.html @@ -1 +1,3 @@ -
\ No newline at end of file +
+ +
\ No newline at end of file diff --git a/front/core/components/th/index.js b/front/core/components/th/index.js index 838431714..f815056f6 100644 --- a/front/core/components/th/index.js +++ b/front/core/components/th/index.js @@ -1,19 +1,10 @@ import ngModule from '../../module'; -import Component from '../../lib/component'; -import './style.scss'; - -export default class Th extends Component { - constructor($element, $, $transclude) { - super($element, $); +export default class Th { + constructor($element) { this._order = 'ASC'; this.column = $element[0]; $element.on('click', () => this.onToggleOrder()); - - $transclude($clone => { - const text = this.$t($clone.text()); // Not updating translations - $element.append(text ? text : $clone); - }); } /** @@ -81,9 +72,10 @@ export default class Th extends Component { } } -Th.$inject = ['$element', '$scope', '$transclude']; +Th.$inject = ['$element']; ngModule.vnComponent('vnTh', { + template: require('./index.html'), transclude: true, controller: Th, bindings: { diff --git a/front/core/components/th/style.scss b/front/core/components/th/style.scss index 6f575a02e..4982f8f89 100644 --- a/front/core/components/th/style.scss +++ b/front/core/components/th/style.scss @@ -6,18 +6,18 @@ vn-th { } vn-th[field] { - &.active:after { + &.active > :after { color: $color-font; opacity: 1; } - &.desc:after { + &.desc > :after { content: 'arrow_drop_down'; } - &.asc:after { + &.asc > :after { content: 'arrow_drop_up'; } - &:after { + & > :after { font-family: 'Material Icons'; content: 'arrow_drop_down'; position: absolute; @@ -27,7 +27,7 @@ vn-th[field] { opacity: 0 } - &:hover:after { + &:hover > :after { opacity: 1; } } \ No newline at end of file diff --git a/front/salix/components/descriptor/index.html b/front/salix/components/descriptor/index.html index 39c93006e..9b11c8b7d 100644 --- a/front/salix/components/descriptor/index.html +++ b/front/salix/components/descriptor/index.html @@ -17,7 +17,7 @@ ui-sref="{{::$ctrl.summaryState}}({id: $ctrl.descriptor.id})"> - diff --git a/loopback/server/connectors/vn-mysql.js b/loopback/server/connectors/vn-mysql.js index 5c625be85..4e1345cd6 100644 --- a/loopback/server/connectors/vn-mysql.js +++ b/loopback/server/connectors/vn-mysql.js @@ -84,6 +84,32 @@ class VnMySQL extends MySQL { return wrappedConnector.buildWhere(null, where); } + /** + * Constructs SQL GROUP BY clause from Loopback filter. + * + * @param {Object} group The group by definition + * @return {String} Built SQL group by + */ + makeGroupBy(group) { + if (!group) + return ''; + if (typeof group === 'string') + group = [group]; + + let clauses = []; + + for (let clause of group) { + let sqlGroup = ''; + let t = clause.split(/[\s,]+/); + + sqlGroup += this.escapeName(t[0]); + + clauses.push(sqlGroup); + } + + return `GROUP BY ${clauses.join(', ')}`; + } + /** * Constructs SQL order clause from Loopback filter. * diff --git a/modules/item/back/methods/item/specs/getDiary.spec.js b/modules/item/back/methods/item/specs/getDiary.spec.js index cf9ed9320..2903fc426 100644 --- a/modules/item/back/methods/item/specs/getDiary.spec.js +++ b/modules/item/back/methods/item/specs/getDiary.spec.js @@ -5,10 +5,8 @@ describe('item getBalance()', () => { let params = {where: {itemFk: 1, warehouseFk: 2}}; let result = await app.models.Item.getBalance(params); - expect(result.length).toBe(4); + expect(result.length).toBe(2); expect(result[0].balance).toBe(-100); - expect(result[1].balance).toBe(-110); - expect(result[2].balance).toBe(-110); - expect(result[3].balance).toBe(-210); + expect(result[1].balance).toBe(-200); }); }); diff --git a/modules/travel/back/methods/travel/extraCommunityFilter.js b/modules/travel/back/methods/travel/extraCommunityFilter.js index 5b095328b..4a49b4401 100644 --- a/modules/travel/back/methods/travel/extraCommunityFilter.js +++ b/modules/travel/back/methods/travel/extraCommunityFilter.js @@ -67,6 +67,10 @@ module.exports = Self => { arg: 'ref', type: 'string', description: 'The reference' + }, { + arg: 'continent', + type: 'string', + description: 'The continent code' } ], returns: { @@ -97,6 +101,8 @@ module.exports = Self => { return {'t.landed': {gte: value}}; case 'landedTo': return {'t.landed': {lte: value}}; + case 'continent': + return {'cnt.code': value}; case 'id': case 'agencyFk': case 'warehouseOutFk': @@ -107,17 +113,21 @@ module.exports = Self => { } }); - filter = mergeFilters(ctx.args.filter, {where}); + filter = mergeFilters(filter, {where}); let stmts = []; let stmt; + stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.travel'); stmt = new ParameterizedSQL( - `SELECT - tr.id, - tr.ref, - tr.shipped, - tr.landed, - tr.kg, + `CREATE TEMPORARY TABLE tmp.travel + (INDEX (id)) + ENGINE = MEMORY + SELECT + t.id, + t.ref, + t.shipped, + t.landed, + t.kg, am.id AS agencyModeFk, am.name AS agencyModeName, wo.id AS warehouseOutFk, @@ -126,102 +136,78 @@ module.exports = Self => { w.name AS warehouseInName, SUM(b.stickers) AS stickers, s.id AS supplierFk, - s.nickname AS supplierNickname - FROM travel tr - LEFT JOIN supplier s ON s.id = tr.cargoSupplierFk - LEFT JOIN entry e ON e.travelFk = tr.id + s.nickname AS cargoSupplierNickname, + CAST(SUM(i.density * b.stickers * IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000 ) as DECIMAL(10,0)) as loadedKg, + CAST(SUM(167.5 * b.stickers * IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000 ) as DECIMAL(10,0)) as volumeKg + FROM travel t + LEFT JOIN supplier s ON s.id = t.cargoSupplierFk + LEFT JOIN entry e ON e.travelFk = t.id LEFT JOIN buy b ON b.entryFk = e.id - LEFT JOIN packaging p ON p.id = b.packageFk + LEFT JOIN packaging pkg ON pkg.id = b.packageFk LEFT JOIN item i ON i.id = b.itemFk LEFT JOIN itemType it ON it.id = i.typeFk - JOIN warehouse w ON w.id = tr.warehouseInFk - JOIN warehouse wo ON wo.id = tr.warehouseOutFk - JOIN agencyMode am ON am.id = tr.agencyFk` + JOIN warehouse w ON w.id = t.warehouseInFk + JOIN warehouse wo ON wo.id = t.warehouseOutFk + JOIN country c ON c.id = wo.countryFk + LEFT JOIN continent cnt ON cnt.id = c.continentFk + JOIN agencyMode am ON am.id = t.agencyFk` ); - /* cast(sum(a.density * c.Etiquetas * IF(cb.Volumen, cb.Volumen, cb.X * cb.Y * cb.Z) / 1000000 ) as DECIMAL(10,0)) as loadedKg, - cast(sum(167.5 * c.Etiquetas * IF(cb.Volumen, cb.Volumen, cb.X * cb.Y * cb.Z) / 1000000 ) as DECIMAL(10,0)) as volumeKg, - pc.Alias as Carguera */ + stmt.merge(conn.makeWhere(filter.where)); + stmt.merge(conn.makeGroupBy('t.id')); + stmt.merge(conn.makeLimit(filter)); + stmts.push(stmt); - // WHERE tr.landing >= @vDateFrom AND (wo.name="Colombia" OR wo.name="Ecuador") + const travelsIndex = stmts.push('SELECT * FROM tmp.travel') - 1; - stmt.merge('GROUP BY tr.id'); - // stmt.merge(conn.makeSuffix(filter)); - const itemsIndex = stmts.push(stmt) - 1; + stmt = new ParameterizedSQL( + `SELECT + e.id, + e.travelFk, + e.ref, + e.loadPriority, + s.name AS supplierName, + SUM(b.stickers) AS stickers, + e.evaNotes, + e.notes, + CAST(SUM(i.density * b.stickers * IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000 ) as DECIMAL(10,0)) as loadedkg, + CAST(SUM(167.5 * b.stickers * IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000 ) as DECIMAL(10,0)) as volumeKg + FROM entry e + JOIN tmp.travel tr ON tr.id = e.travelFk + JOIN buy b ON b.entryFk = e.id + JOIN packaging pkg ON pkg.id = b.packageFk + JOIN item i ON i.id = b.itemFk + JOIN itemType it ON it.id = i.typeFk + JOIN supplier s ON s.id = e.supplierFk` + ); + + stmt.merge(conn.makeGroupBy('e.id')); + stmt.merge(conn.makeOrderBy(filter.order)); + const entriesIndex = stmts.push(stmt) - 1; + + stmts.push(`DROP TEMPORARY TABLE tmp.travel`); const sql = ParameterizedSQL.join(stmts, ';'); const result = await conn.executeStmt(sql); - return itemsIndex === 0 ? result : result[itemsIndex]; - /* - SET @vDateFrom:= TIMESTAMPADD(WEEK,-12,CURDATE()); + const travels = result[travelsIndex]; + const entries = result[entriesIndex]; - SELECT - 1 as IsTravel, - tr.id as travel, - NULL as Entrada, - ag.Agencia, - tr.ref, - tr.shipment, - wo.name as OrigenCajas, - tr.landing, - w.name as Destino, - sum(c.Etiquetas) as Etiquetas, - NULL as Notas_Eva, - kg, - cast(sum(a.density * c.Etiquetas * IF(cb.Volumen, cb.Volumen, cb.X * cb.Y * cb.Z) / 1000000 ) as DECIMAL(10,0)) as loadedKg, - cast(sum(167.5 * c.Etiquetas * IF(cb.Volumen, cb.Volumen, cb.X * cb.Y * cb.Z) / 1000000 ) as DECIMAL(10,0)) as volumeKg, - NULL as loadPriority, - NULL as Notas, - pc.Alias as Carguera - FROM travel tr - LEFT JOIN Proveedores pc ON pc.Id_Proveedor = tr.cargoSupplierFk - LEFT JOIN Entradas e ON e.travel_id = tr.id - LEFT JOIN Compres c ON c.Id_Entrada = e.Id_Entrada - LEFT JOIN Cubos cb ON cb.Id_Cubo = c.Id_Cubo - LEFT JOIN Articles a ON a.Id_Article = c.Id_Article - LEFT JOIN Tipos tp ON tp.tipo_id = a.tipo_id - JOIN warehouse w ON w.id = tr.warehouse_id - JOIN warehouse wo ON wo.id = tr.warehouse_id_out - JOIN Agencias ag ON ag.Id_Agencia = tr.agency_id - WHERE tr.landing >= @vDateFrom AND (wo.name="Colombia" OR wo.name="Ecuador") - GROUP BY tr.id + const travelsMap = new Map(); + for (let travel of travels) + travelsMap.set(travel.id, travel); - UNION ALL + for (let entry of entries) { + const travel = travelsMap.get(entry.travelFk); - SELECT - 0 as IsTravel, - e.travel_id as travel, - e.Id_Entrada, - p.Proveedor, - e.Referencia, - tr.shipment, - wo.name as OrigenCajas, - tr.landing, - w.name as Destino, - sum(Etiquetas) as Etiquetas, - e.Notas_Eva, - NULL as kg, - cast(sum(a.density * c.Etiquetas * IF(cb.Volumen, cb.Volumen, cb.X * cb.Y * cb.Z) / 1000000 ) as DECIMAL(10,0)) as loadedkg, - cast(sum(167.5 * c.Etiquetas * IF(cb.Volumen, cb.Volumen, cb.X * cb.Y * cb.Z) / 1000000 ) as DECIMAL(10,0)) as volumeKg, - loadPriority, - e.Notas, - pc.Alias as carguera + if (travel) { + if (!travel.entries) travel.entries = []; - FROM Entradas e - JOIN Compres c ON c.Id_Entrada = e.Id_Entrada - JOIN Cubos cb ON cb.Id_Cubo = c.Id_Cubo - JOIN Articles a ON a.Id_Article = c.Id_Article - JOIN Tipos tp ON tp.tipo_id = a.tipo_id - JOIN Proveedores p ON p.Id_Proveedor = e.Id_Proveedor - JOIN travel tr ON tr.id = e.travel_id - LEFT JOIN Proveedores pc ON pc.Id_Proveedor = tr.cargoSupplierFk - JOIN warehouse w ON w.id = tr.warehouse_id - JOIN warehouse wo ON wo.id = tr.warehouse_id_out - WHERE tr.landing >= @vDateFrom AND (wo.name="Colombia" OR wo.name="Ecuador") - GROUP BY e.Id_Entrada - ) sub - ORDER BY landing ASC, shipment ASC,travel, IsTravel DESC, (loadPriority > 0) DESC,loadPriority, Agencia, Notas_Eva ; */ + travel.entries.push(entry); + } + } + + return travels; }; }; diff --git a/modules/travel/back/methods/travel/specs/extraCommunityFilter.spec.js b/modules/travel/back/methods/travel/specs/extraCommunityFilter.spec.js new file mode 100644 index 000000000..7f42eb5f0 --- /dev/null +++ b/modules/travel/back/methods/travel/specs/extraCommunityFilter.spec.js @@ -0,0 +1,66 @@ +const app = require('vn-loopback/server/server'); + +describe('Travel extraCommunityFilter()', () => { + const filter = { + order: 'landed ASC, shipped ASC, travelFk, loadPriority, agencyModeFk, evaNotes', + }; + it('should return the travel matching "search"', async() => { + const ctx = { + args: { + search: 2 + } + }; + + const result = await app.models.Travel.extraCommunityFilter(ctx, filter); + const firstRow = result[0]; + const entries = firstRow.entries; + + expect(result.length).toEqual(1); + expect(firstRow.id).toEqual(2); + expect(entries.length).toEqual(2); + }); + + it('should return the travel matching "search" by ref', async() => { + const ctx = { + args: { + search: 'third' + } + }; + + const result = await app.models.Travel.extraCommunityFilter(ctx, filter); + const firstRow = result[0]; + + expect(result.length).toEqual(1); + expect(firstRow.id).toEqual(3); + }); + + it('should return the travel matching "warehouse out"', async() => { + const ctx = { + args: { + warehouseOutFk: 2 + } + }; + + const result = await app.models.Travel.extraCommunityFilter(ctx, filter); + + expect(result.length).toEqual(3); + }); + + it('should return the routes matching "landed from" and "landed to"', async() => { + const from = new Date(); + const to = new Date(); + from.setHours(0, 0, 0, 0); + to.setHours(23, 59, 59, 999); + to.setDate(to.getDate() + 14); + const ctx = { + args: { + landedFrom: from, + landedTo: to + } + }; + + const result = await app.models.Travel.extraCommunityFilter(ctx, filter); + + expect(result.length).toEqual(1); + }); +}); diff --git a/modules/travel/front/descriptor/locale/es.yml b/modules/travel/front/descriptor/locale/es.yml index 0ae18fdbf..3e6d62735 100644 --- a/modules/travel/front/descriptor/locale/es.yml +++ b/modules/travel/front/descriptor/locale/es.yml @@ -1,6 +1,6 @@ Reference: Referencia -Wh. In: Almacén entrada -Wh. Out: Almacén salida +Wh. In: Alm. entrada +Wh. Out: Alm. salida Shipped: F. envío Landed: F. entrega Total entries: Entradas totales \ No newline at end of file diff --git a/modules/travel/front/extra-community-search-panel/index.html b/modules/travel/front/extra-community-search-panel/index.html new file mode 100644 index 000000000..85a30907a --- /dev/null +++ b/modules/travel/front/extra-community-search-panel/index.html @@ -0,0 +1,91 @@ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
\ No newline at end of file diff --git a/modules/travel/front/extra-community-search-panel/index.js b/modules/travel/front/extra-community-search-panel/index.js new file mode 100644 index 000000000..63d404b4b --- /dev/null +++ b/modules/travel/front/extra-community-search-panel/index.js @@ -0,0 +1,7 @@ +import ngModule from '../module'; +import SearchPanel from 'core/components/searchbar/search-panel'; + +ngModule.vnComponent('vnExtraCommunitySearchPanel', { + template: require('./index.html'), + controller: SearchPanel +}); diff --git a/modules/travel/front/extra-community/index.html b/modules/travel/front/extra-community/index.html index 1007f223a..e9f11ba0a 100644 --- a/modules/travel/front/extra-community/index.html +++ b/modules/travel/front/extra-community/index.html @@ -1,49 +1,111 @@ + data="travels" + order="landed ASC, shipped ASC, travelFk, loadPriority, agencyModeFk, evaNotes" + limit="20"> - - -
- - - - - {{travel.id}} - {{travel.supplierNickname}} - - - - - - +
+ + + + + diff --git a/modules/travel/front/extra-community/index.js b/modules/travel/front/extra-community/index.js index 685958909..bd362f34f 100644 --- a/modules/travel/front/extra-community/index.js +++ b/modules/travel/front/extra-community/index.js @@ -2,7 +2,90 @@ import ngModule from '../module'; import Section from 'salix/components/section'; import './style.scss'; +class Controller extends Section { + constructor($element, $) { + super($element, $); + + const draggable = this.element.querySelector('.travel-list'); + draggable.addEventListener('dragstart', + event => this.dragStart(event)); + draggable.addEventListener('dragend', + event => this.dragEnd(event)); + + this.draggableElement = 'a[draggable]'; + this.droppableElement = 'vn-table[vn-droppable]'; + + const scopeDays = 14; + const landedFrom = new Date(); + landedFrom.setHours(0, 0, 0, 0); + + const landedTo = new Date(); + landedTo.setDate(landedTo.getDate() + scopeDays); + landedTo.setHours(23, 59, 59, 59); + + this.defaultFilter = { + landedFrom: landedFrom, + landedTo: landedTo, + continent: 'AM' + }; + } + + findDraggable($event) { + const target = $event.target; + const draggable = target.closest(this.draggableElement); + + return draggable; + } + + findDroppable($event) { + const target = $event.target; + const droppable = target.closest(this.droppableElement); + + return droppable; + } + + dragStart($event) { + const draggable = this.findDraggable($event); + draggable.classList.add('dragging'); + + const id = draggable.getAttribute('id'); + this.entryId = id; + this.entry = draggable; + } + + dragEnd($event) { + const draggable = this.findDraggable($event); + draggable.classList.remove('dragging'); + this.entryId = null; + this.entry = null; + } + + onDrop($event) { + const model = this.$.model; + const droppable = this.findDroppable($event); + const travelId = droppable.getAttribute('id'); + + const currentDroppable = this.entry.closest(this.droppableElement); + + if (currentDroppable == droppable) return; + + if (this.entryId && travelId) { + const path = `Entries/${this.entryId}`; + this.$http.patch(path, {travelFk: travelId}) + .then(() => model.refresh()) + .then(() => this.vnApp.showSuccess(this.$t('Data saved!'))); + } + } + + changeReference(travel) { + const params = {ref: travel.ref}; + const endpoint = `Travels/${travel.id}`; + this.$http.patch(endpoint, params) + .then(() => this.vnApp.showSuccess(this.$t('Data saved!'))); + } +} + ngModule.vnComponent('vnTravelExtraCommunity', { template: require('./index.html'), - controller: Section + controller: Controller }); diff --git a/modules/travel/front/extra-community/index.spec.js b/modules/travel/front/extra-community/index.spec.js new file mode 100644 index 000000000..54f5e505f --- /dev/null +++ b/modules/travel/front/extra-community/index.spec.js @@ -0,0 +1,47 @@ +import './index.js'; + +describe('Travel Component vnTravelExtraCommunity', () => { + let controller; + let $httpBackend; + let travel = { + id: 1, + warehouseInFk: 1, + totalEntries: 3, + isDelivered: false + }; + + beforeEach(ngModule('travel')); + + beforeEach(inject(($componentController, _$httpBackend_) => { + $httpBackend = _$httpBackend_; + const $element = angular.element(''); + controller = $componentController('vnTravelExtraCommunity', {$element}); + controller.$.summary = {show: jasmine.createSpy('show')}; + })); + + describe('changeReference()', () => { + it('should make an HTTP query', () => { + jest.spyOn(controller.vnApp, 'showSuccess'); + + const travel = {id: 1, ref: 'New reference'}; + const expectedData = {ref: 'New reference'}; + $httpBackend.expect('PATCH', `Travels/${travel.id}`, expectedData).respond(200); + controller.changeReference(travel); + $httpBackend.flush(); + + expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!'); + }); + }); + + xdescribe('changeReference()', () => { + it('should make an HTTP query', () => { + let event = new MouseEvent('click', { + bubbles: true, + cancelable: true + }); + controller.preview(event, travel); + + expect(controller.$.summary.show).toHaveBeenCalledWith(); + }); + }); +}); diff --git a/modules/travel/front/extra-community/locale/es.yml b/modules/travel/front/extra-community/locale/es.yml index aa231d3be..e377a1011 100644 --- a/modules/travel/front/extra-community/locale/es.yml +++ b/modules/travel/front/extra-community/locale/es.yml @@ -1 +1,8 @@ -Family: Familia \ No newline at end of file +Family: Familia +Extra community: Extra comunitarios +Freighter: Transitario +Bl. KG: KG Bloq. +Phy. KG: KG físico +Vol. KG: KG Vol. +Search by travel id or reference: Buscar por id travel o referencia +Continent Out: Continente salida \ No newline at end of file diff --git a/modules/travel/front/extra-community/style.scss b/modules/travel/front/extra-community/style.scss index 5a929908c..e7265781d 100644 --- a/modules/travel/front/extra-community/style.scss +++ b/modules/travel/front/extra-community/style.scss @@ -3,7 +3,6 @@ vn-travel-extra-community { .header { margin-bottom: 16px; - text-transform: uppercase; font-size: 1.25rem; line-height: 1; padding: 7px; @@ -11,15 +10,46 @@ vn-travel-extra-community { padding-bottom: 4px; font-weight: lighter; background-color: #fde6ca; + color: $color-font-light; border-bottom: 1px solid #f7931e; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } - vn-table vn-th.waste-family, - vn-table vn-td.waste-family { - max-width: 64px; - width: 64px + vn-td-editable text { + background-color: transparent; + padding: 0; + border: 0; + border-bottom: 1px dashed $color-active; + border-radius: 0; + color: $color-active + } + + vn-td-editable text:after { + font-family: 'Material Icons'; + content: 'edit'; + position: absolute; + margin-left: 5px; + color: $color-spacer + } + + vn-table[vn-droppable] { + border-radius: 0; + } + + a[draggable] { + transition: all .5s; + cursor: move; + outline: 0; + } + + a[draggable]:hover { + background-color: $color-hover-cd + } + + a[draggable].dragging { + background-color: $color-success-light; + font-weight:bold } } \ No newline at end of file diff --git a/modules/travel/front/index.js b/modules/travel/front/index.js index 410cbe219..60953e9a2 100644 --- a/modules/travel/front/index.js +++ b/modules/travel/front/index.js @@ -14,3 +14,4 @@ import './thermograph/create/'; import './thermograph/edit/'; import './descriptor-popover'; import './extra-community'; +import './extra-community-search-panel'; diff --git a/modules/travel/front/routes.json b/modules/travel/front/routes.json index 30792278e..b2e438c6d 100644 --- a/modules/travel/front/routes.json +++ b/modules/travel/front/routes.json @@ -93,7 +93,7 @@ "acl": ["buyer"] }, { - "url": "/extra-community", + "url": "/extra-community?q", "state": "travel.extraCommunity", "component": "vn-travel-extra-community", "description": "Extra community", diff --git a/modules/travel/front/summary/locale/es.yml b/modules/travel/front/summary/locale/es.yml index 8d2e7e78c..74ddfe03e 100644 --- a/modules/travel/front/summary/locale/es.yml +++ b/modules/travel/front/summary/locale/es.yml @@ -1,6 +1,6 @@ Reference: Referencia -Warehouse In: Almacen entrada -Warehouse Out: Almacen salida +Warehouse In: Almacén entrada +Warehouse Out: Almacén salida Shipped: F. envío Landed: F. entrega Total entries: Entradas totales