diff --git a/db/Dockerfile b/db/Dockerfile index 152b953dce..cb3aa741cd 100644 --- a/db/Dockerfile +++ b/db/Dockerfile @@ -1,6 +1,6 @@ -FROM mariadb:10.7.5 +FROM mariadb:10.7.3 -ENV MARIADB_ROOT_PASSWORD root +ENV MYSQL_ROOT_PASSWORD root ENV TZ Europe/Madrid ARG DEBIAN_FRONTEND=noninteractive @@ -22,7 +22,6 @@ COPY \ docker/docker-start.sh \ /usr/local/bin/ -RUN chmod 775 /etc/mysql/conf.d/docker.cnf RUN mkdir /mysql-data \ && chown -R mysql:mysql /mysql-data @@ -36,8 +35,6 @@ COPY \ dump/structure.sql \ dump/dumpedFixtures.sql \ ./ - -RUN chmod 775 config.ini RUN gosu mysql docker-init.sh \ && docker-dump.sh mysqlPlugins \ && docker-dump.sh mockDate \ diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 37f7308a58..0ad9ad7f40 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -1014,9 +1014,9 @@ export default { save: 'vn-travel-create vn-submit > button' }, travelExtraCommunity: { - anySearchResult: 'vn-travel-extra-community > vn-data-viewer div > vn-tbody > vn-tr', - firstTravelReference: 'vn-travel-extra-community vn-tbody:nth-child(2) vn-td-editable[name="reference"]', - firstTravelLockedKg: 'vn-travel-extra-community vn-tbody:nth-child(2) vn-td-editable[name="lockedKg"]', + anySearchResult: 'vn-travel-extra-community > vn-card div > tbody > tr[ng-attr-id="{{::travel.id}}"]', + firstTravelReference: 'vn-travel-extra-community tbody:nth-child(2) vn-textfield[ng-model="travel.ref"]', + firstTravelLockedKg: 'vn-travel-extra-community tbody:nth-child(2) vn-input-number[ng-model="travel.kg"]', removeContinentFilter: 'vn-searchbar > form > vn-textfield > div.container > div.prepend > prepend > div > span:nth-child(3) > vn-icon > i' }, travelBasicData: { diff --git a/e2e/paths/10-travel/04_extra_community.spec.js b/e2e/paths/10-travel/04_extra_community.spec.js index e4a8591924..a1cad6a7d1 100644 --- a/e2e/paths/10-travel/04_extra_community.spec.js +++ b/e2e/paths/10-travel/04_extra_community.spec.js @@ -19,18 +19,22 @@ describe('Travel extra community path', () => { it('should edit the travel reference and the locked kilograms', async() => { await page.waitToClick(selectors.travelExtraCommunity.removeContinentFilter); await page.waitForSpinnerLoad(); - await page.writeOnEditableTD(selectors.travelExtraCommunity.firstTravelReference, 'edited reference'); - await page.waitForSpinnerLoad(); - await page.writeOnEditableTD(selectors.travelExtraCommunity.firstTravelLockedKg, '1500'); + await page.clearInput(selectors.travelExtraCommunity.firstTravelReference); + await page.write(selectors.travelExtraCommunity.firstTravelReference, 'edited reference'); + await page.clearInput(selectors.travelExtraCommunity.firstTravelLockedKg); + await page.write(selectors.travelExtraCommunity.firstTravelLockedKg, '1500'); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Data saved!'); }); it('should reload the index and confirm the reference and locked kg were edited', async() => { await page.accessToSection('travel.index'); await page.accessToSection('travel.extraCommunity'); await page.waitToClick(selectors.travelExtraCommunity.removeContinentFilter); - await page.waitForTextInElement(selectors.travelExtraCommunity.firstTravelReference, 'edited reference'); - const reference = await page.getProperty(selectors.travelExtraCommunity.firstTravelReference, 'innerText'); - const lockedKg = await page.getProperty(selectors.travelExtraCommunity.firstTravelLockedKg, 'innerText'); + + const reference = await page.waitToGetProperty(selectors.travelExtraCommunity.firstTravelReference, 'value'); + const lockedKg = await page.waitToGetProperty(selectors.travelExtraCommunity.firstTravelLockedKg, 'value'); expect(reference).toContain('edited reference'); expect(lockedKg).toContain(1500); diff --git a/modules/item/back/methods/item/getWasteByWorker.js b/modules/item/back/methods/item/getWasteByWorker.js index 2b0b78974f..4c3c64a919 100644 --- a/modules/item/back/methods/item/getWasteByWorker.js +++ b/modules/item/back/methods/item/getWasteByWorker.js @@ -30,11 +30,24 @@ module.exports = Self => { sum(ws.saleWaste) AS dwindle FROM bs.waste ws WHERE year = YEAR(TIMESTAMPADD(WEEK,-1, ?)) - AND week = WEEK(TIMESTAMPADD(WEEK,-1, ?), 1) + AND week = WEEK(TIMESTAMPADD(WEEK,-1, ?), 1) GROUP BY buyer, family ) sub ORDER BY percentage DESC`, [date, date], myOptions); + const wastesTotal = await Self.rawSql(` + SELECT *, 100 * dwindle / total AS percentage + FROM ( + SELECT buyer, + sum(ws.saleTotal) AS total, + sum(ws.saleWaste) AS dwindle + FROM bs.waste ws + WHERE year = YEAR(TIMESTAMPADD(WEEK,-1, ?)) + AND week = WEEK(TIMESTAMPADD(WEEK,-1, ?), 1) + GROUP BY buyer + ) sub + ORDER BY percentage DESC`, [date, date], myOptions); + const details = []; for (let waste of wastes) { @@ -55,6 +68,14 @@ module.exports = Self => { buyerDetail.lines.push(waste); } + for (let waste of details) { + let buyerTotal = wastesTotal.find(totals => { + return waste.buyer == totals.buyer; + }); + + Object.assign(waste, buyerTotal); + } + return details; }; }; diff --git a/modules/item/back/methods/item/specs/getWasteByWorker.spec.js b/modules/item/back/methods/item/specs/getWasteByWorker.spec.js index c8b9d5e156..52f806bd3b 100644 --- a/modules/item/back/methods/item/specs/getWasteByWorker.spec.js +++ b/modules/item/back/methods/item/specs/getWasteByWorker.spec.js @@ -12,6 +12,7 @@ describe('Item getWasteByWorker()', () => { const anyResult = result[Math.floor(Math.random() * Math.floor(length))]; expect(anyResult.buyer).toMatch(/(CharlesXavier|HankPym|DavidCharlesHaller)/); + expect(anyResult.total).toBeGreaterThanOrEqual(1000); expect(anyResult.lines.length).toBeGreaterThanOrEqual(3); await tx.rollback(); diff --git a/modules/item/front/waste/index/index.html b/modules/item/front/waste/index/index.html index c80733e9e0..5da5acbf12 100644 --- a/modules/item/front/waste/index/index.html +++ b/modules/item/front/waste/index/index.html @@ -4,39 +4,46 @@ data="details"> -
- -
{{detail.buyer}}
- - - - -
- - - - - Family - Percentage - Dwindle - Total - - - - - {{::waste.family}} - {{::(waste.percentage / 100) | percentage: 2}} - {{::waste.dwindle | currency: 'EUR'}} - {{::waste.total | currency: 'EUR'}} - - - - -
-
\ No newline at end of file + + + + + Buyer + Family + Percentage + Dwindle + Total + + + + + + {{::detail.buyer}} + {{::detail.family}} + {{::(detail.percentage / 100) | percentage: 2}} + {{::detail.dwindle | currency: 'EUR'}} + {{::detail.total | currency: 'EUR'}} + + + + + + + + {{::waste.family}} + {{::(waste.percentage / 100) | percentage: 2}} + {{::waste.dwindle | currency: 'EUR'}} + {{::waste.total | currency: 'EUR'}} + + + + + + diff --git a/modules/item/front/waste/index/style.scss b/modules/item/front/waste/index/style.scss index 8b44cb6f17..36fac33114 100644 --- a/modules/item/front/waste/index/style.scss +++ b/modules/item/front/waste/index/style.scss @@ -5,20 +5,9 @@ vn-item-waste-index, vn-item-waste-detail { .header { padding: 12px 0 5px 0; - color: gray; + background-color: $color-bg; font-size: 1.2rem; - border-bottom: $border; margin-bottom: 10px; - - & > vn-none > vn-icon { - @extend %clickable-light; - color: $color-button; - font-size: 1.4rem; - } - - vn-none > .arrow { - transition: transform 200ms; - } } vn-table vn-th.waste-family, @@ -26,12 +15,13 @@ vn-item-waste-detail { max-width: 64px; width: 64px } + .hidden { display: none; - } - .header > vn-none > .arrow.hidden { + + .arrow.hidden { display: block; transform: rotate(180deg); } -} \ No newline at end of file +} diff --git a/modules/route/back/models/vehicle.json b/modules/route/back/models/vehicle.json index a35926befd..34a376b897 100644 --- a/modules/route/back/models/vehicle.json +++ b/modules/route/back/models/vehicle.json @@ -50,8 +50,10 @@ }, "scope": { "where": { - "isActive": true - } + "isActive": { + "neq": false + } + } }, "acls": [ { diff --git a/modules/travel/back/methods/travel/extraCommunityFilter.js b/modules/travel/back/methods/travel/extraCommunityFilter.js index 7769b7f21e..feb16d0522 100644 --- a/modules/travel/back/methods/travel/extraCommunityFilter.js +++ b/modules/travel/back/methods/travel/extraCommunityFilter.js @@ -128,7 +128,7 @@ module.exports = Self => { w.name AS warehouseInFk, w.name AS warehouseInName, SUM(b.stickers) AS stickers, - s.id AS supplierFk, + s.id AS cargoSupplierFk, 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 @@ -160,13 +160,14 @@ module.exports = Self => { e.travelFk, e.ref, e.loadPriority, + s.id AS supplierFk, 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 tmp.travel tr + FROM tmp.travel tr JOIN entry e ON e.travelFk = tr.id JOIN buy b ON b.entryFk = e.id JOIN packaging pkg ON pkg.id = b.packageFk diff --git a/modules/travel/front/extra-community-search-panel/index.html b/modules/travel/front/extra-community-search-panel/index.html index ab1e88891b..09fbb89495 100644 --- a/modules/travel/front/extra-community-search-panel/index.html +++ b/modules/travel/front/extra-community-search-panel/index.html @@ -50,15 +50,15 @@ @@ -84,4 +84,4 @@ - \ No newline at end of file + diff --git a/modules/travel/front/extra-community/index.html b/modules/travel/front/extra-community/index.html index 0b94c6c1e6..f19ab592e7 100644 --- a/modules/travel/front/extra-community/index.html +++ b/modules/travel/front/extra-community/index.html @@ -1,6 +1,7 @@ - - -
- - - - - - - - Id - Supplier - Freighter - Reference - Packages - Bl. KG - Phy. KG - Vol. KG - - Wh. Out - - W. Shipped - - Wh. In - - W. Landed - - - - - - + + +
+ + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + +
+ Id + + Supplier + + Agency + + Reference + + Packages + + Bl. KG + + Phy. KG + + Vol. KG + + Wh. Out + + W. Shipped + + Wh. In + + W. Landed +
+ {{::travel.id}} - - {{::travel.agencyModeName}} - {{::travel.cargoSupplierNickname}} - - {{travel.ref}} - - - - - - {{::travel.stickers}} - - {{travel.kg}} - - - - - - {{::travel.loadedKg}} - {{::travel.volumeKg}} - {{::travel.warehouseOutName}} - {{::travel.shipped | date: 'dd/MM/yyyy'}} - {{::travel.warehouseInName}} - {{::travel.landed | date: 'dd/MM/yyyy'}} - - + + + {{::travel.cargoSupplierNickname}} + + {{::travel.agencyModeName}} + + + + {{::travel.stickers}} + + + {{::travel.loadedKg}}{{::travel.volumeKg}}{{::travel.warehouseOutName}}{{::travel.shipped | date: 'dd/MM/yyyy'}}{{::travel.warehouseInName}}{{::travel.landed | date: 'dd/MM/yyyy'}}
{{::entry.id}} - - {{::entry.supplierName}} - - {{::entry.ref}} - {{::entry.stickers}} - - {{::entry.loadedkg}} - {{::entry.volumeKg}} - + + + {{::entry.supplierName}} + + {{::entry.ref}}{{::entry.stickers}}{{::entry.loadedkg}}{{::entry.volumeKg}} {{::entry.notes}} - - + {{::entry.evaNotes}} - - - - - - - - - +
+
+
+ - + + diff --git a/modules/travel/front/extra-community/index.js b/modules/travel/front/extra-community/index.js index a380c1ed85..461712e9c5 100644 --- a/modules/travel/front/extra-community/index.js +++ b/modules/travel/front/extra-community/index.js @@ -14,8 +14,15 @@ class Controller extends Section { draggable.addEventListener('dragend', event => this.dragEnd(event)); - this.draggableElement = 'a[draggable]'; - this.droppableElement = 'vn-tbody[vn-droppable]'; + draggable.addEventListener('dragover', + event => this.dragOver(event)); + draggable.addEventListener('dragenter', + event => this.dragEnter(event)); + draggable.addEventListener('dragleave', + event => this.dragLeave(event)); + + this.draggableElement = 'tr[draggable]'; + this.droppableElement = 'tbody[vn-droppable]'; const twoDays = 2; const shippedFrom = new Date(); @@ -32,6 +39,8 @@ class Controller extends Section { landedTo: landedTo, continent: 'AM' }; + + this.smartTableOptions = {}; } get hasDateRange() { @@ -44,6 +53,15 @@ class Controller extends Section { return hasLanded || hasShipped || hasContinent || hasWarehouseOut; } + onDragInterval() { + if (this.dragClientY > 0 && this.dragClientY < 75) + this.$window.scrollTo(0, this.$window.scrollY - 10); + + const maxHeight = window.screen.availHeight - (window.outerHeight - window.innerHeight); + if (this.dragClientY > maxHeight - 75 && this.dragClientY < maxHeight) + this.$window.scrollTo(0, this.$window.scrollY + 10); + } + findDraggable($event) { const target = $event.target; const draggable = target.closest(this.draggableElement); @@ -65,6 +83,7 @@ class Controller extends Section { const id = parseInt(draggable.id); this.entryId = id; this.entry = draggable; + this.interval = setInterval(() => this.onDragInterval(), 50); } dragEnd($event) { @@ -72,6 +91,8 @@ class Controller extends Section { draggable.classList.remove('dragging'); this.entryId = null; this.entry = null; + + clearInterval(this.interval); } onDrop($event) { @@ -91,6 +112,37 @@ class Controller extends Section { } } + undrop() { + if (!this.dropping) return; + this.dropping.classList.remove('dropping'); + this.dropping = null; + } + + dragOver($event) { + this.dragClientY = $event.clientY; + $event.preventDefault(); + } + + dragEnter($event) { + let element = this.findDroppable($event); + if (element) this.dropCount++; + + if (element != this.dropping) { + this.undrop(); + if (element) element.classList.add('dropping'); + this.dropping = element; + } + } + + dragLeave($event) { + let element = this.findDroppable($event); + + if (element) { + this.dropCount--; + if (this.dropCount == 0) this.undrop(); + } + } + save(id, data) { const endpoint = `Travels/${id}`; this.$http.patch(endpoint, data) diff --git a/modules/travel/front/extra-community/index.spec.js b/modules/travel/front/extra-community/index.spec.js index 59688a46ca..ae48b9ca11 100644 --- a/modules/travel/front/extra-community/index.spec.js +++ b/modules/travel/front/extra-community/index.spec.js @@ -27,7 +27,7 @@ describe('Travel Component vnTravelExtraCommunity', () => { describe('findDraggable()', () => { it('should find the draggable element', () => { - const draggable = document.createElement('a'); + const draggable = document.createElement('tr'); draggable.setAttribute('draggable', true); const $event = new Event('dragstart'); @@ -43,7 +43,7 @@ describe('Travel Component vnTravelExtraCommunity', () => { describe('findDroppable()', () => { it('should find the droppable element', () => { - const droppable = document.createElement('vn-tbody'); + const droppable = document.createElement('tbody'); droppable.setAttribute('vn-droppable', true); const $event = new Event('drop'); @@ -58,9 +58,9 @@ describe('Travel Component vnTravelExtraCommunity', () => { }); describe('dragStart()', () => { - it(`should add the class "dragging" to the draggable element + it(`should add the class "dragging" to the draggable element and then set the entryId controller property`, () => { - const draggable = document.createElement('a'); + const draggable = document.createElement('tr'); draggable.setAttribute('draggable', true); draggable.setAttribute('id', 3); @@ -78,9 +78,9 @@ describe('Travel Component vnTravelExtraCommunity', () => { }); describe('dragEnd()', () => { - it(`should remove the class "dragging" from the draggable element + it(`should remove the class "dragging" from the draggable element and then set the entryId controller property to null`, () => { - const draggable = document.createElement('a'); + const draggable = document.createElement('tr'); draggable.setAttribute('draggable', true); draggable.setAttribute('id', 3); draggable.classList.add('dragging'); @@ -100,13 +100,13 @@ describe('Travel Component vnTravelExtraCommunity', () => { describe('onDrop()', () => { it('should make an HTTP patch query', () => { - const droppable = document.createElement('vn-tbody'); + const droppable = document.createElement('tbody'); droppable.setAttribute('vn-droppable', true); droppable.setAttribute('id', 1); jest.spyOn(controller, 'findDroppable').mockReturnValue(droppable); - const oldDroppable = document.createElement('vn-tbody'); + const oldDroppable = document.createElement('tbody'); oldDroppable.setAttribute('vn-droppable', true); const entry = document.createElement('div'); oldDroppable.appendChild(entry); diff --git a/modules/travel/front/extra-community/style.scss b/modules/travel/front/extra-community/style.scss index f903f94eac..532a3056ab 100644 --- a/modules/travel/front/extra-community/style.scss +++ b/modules/travel/front/extra-community/style.scss @@ -15,41 +15,44 @@ vn-travel-extra-community { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; + cursor: pointer; } - 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:hover text:after { - font-family: 'Material Icons'; - content: 'edit'; - position: absolute; - right: -15px; - color: $color-spacer - } - - vn-table[vn-droppable] { + table[vn-droppable] { border-radius: 0; } - a[draggable] { + tr[draggable] { transition: all .5s; cursor: move; + overflow: auto; outline: 0; + height: 65px; + pointer-events: fill; + user-select:all; } - a[draggable]:hover { - background-color: $color-hover-cd + tr[draggable] *::selection{ + background-color: transparent; } - a[draggable].dragging { - background-color: $color-success-light; - font-weight:bold + tr[draggable]:hover { + background-color: $color-hover-cd; } -} \ No newline at end of file + + tr[draggable].dragging { + background-color: $color-primary-light; + color: $color-font-light; + font-weight:bold; + } + + .td-editable{ + input{ + font-size: 1.25rem!important; + } + } + + .number *{ + text-align: right; + } +} diff --git a/modules/zone/back/models/zone-exclusion.json b/modules/zone/back/models/zone-exclusion.json index 415bce40c5..e8088cd448 100644 --- a/modules/zone/back/models/zone-exclusion.json +++ b/modules/zone/back/models/zone-exclusion.json @@ -1,6 +1,10 @@ { "name": "ZoneExclusion", - "base": "VnModel", + "base": "Loggable", + "log": { + "model":"ZoneLog", + "relation": "zone" + }, "options": { "mysql": { "table": "zoneExclusion"