2350-order_index #334

Merged
joan merged 11 commits from 2350-order_index into dev 2020-07-16 12:02:15 +00:00
18 changed files with 296 additions and 35 deletions

View File

@ -0,0 +1,47 @@
USE `vn`;
CREATE
OR REPLACE ALGORITHM = UNDEFINED
DEFINER = `root`@`%`
SQL SECURITY DEFINER
VIEW `vn`.`zoneEstimatedDelivery` AS
SELECT
`t`.`zoneFk` AS `zoneFk`,
CAST((CURDATE() + INTERVAL ((HOUR(`zc`.`hour`) * 60) + MINUTE(`zc`.`hour`)) MINUTE)
AS TIME) AS `hourTheoretical`,
CAST(SUM(`sv`.`volume`) AS DECIMAL (5 , 1 )) AS `totalVolume`,
CAST(SUM(IF((`s`.`alertLevel` < 2),
`sv`.`volume`,
0))
AS DECIMAL (5 , 1 )) AS `remainingVolume`,
GREATEST(IFNULL(`lhp`.`m3`, 0),
IFNULL(`dl`.`minSpeed`, 0)) AS `speed`,
CAST((`zc`.`hour` + INTERVAL ((-(SUM(IF((`s`.`alertLevel` < 2),
`sv`.`volume`,
0))) * 60) / GREATEST(IFNULL(`lhp`.`m3`, 0),
IFNULL(`dl`.`minSpeed`, 0))) MINUTE)
AS TIME) AS `hourEffective`,
FLOOR(((-(SUM(IF((`s`.`alertLevel` < 2),
`sv`.`volume`,
0))) * 60) / GREATEST(IFNULL(`lhp`.`m3`, 0),
IFNULL(`dl`.`minSpeed`, 0)))) AS `minutesLess`,
CAST((`zc`.`hour` + INTERVAL ((-(SUM(IF((`s`.`alertLevel` < 2),
`sv`.`volume`,
0))) * 60) / GREATEST(IFNULL(`lhp`.`m3`, 0),
IFNULL(`dl`.`minSpeed`, 0))) MINUTE)
AS TIME) AS `etc`
FROM
((((((((`ticket` `t`
JOIN `ticketStateToday` `tst` ON ((`tst`.`ticket` = `t`.`id`)))
JOIN `state` `s` ON ((`s`.`id` = `tst`.`state`)))
JOIN `saleVolume` `sv` ON ((`sv`.`ticketFk` = `t`.`id`)))
LEFT JOIN `lastHourProduction` `lhp` ON ((`lhp`.`warehouseFk` = `t`.`warehouseFk`)))
JOIN `warehouse` `w` ON ((`w`.`id` = `t`.`warehouseFk`)))
JOIN `warehouseAlias` `wa` ON ((`wa`.`id` = `w`.`aliasFk`)))
LEFT JOIN `zoneClosure` `zc` ON (((`zc`.`zoneFk` = `t`.`zoneFk`)
AND (`zc`.`dated` = CURDATE()))))
LEFT JOIN `cache`.`departure_limit` `dl` ON (((`dl`.`warehouse_id` = `t`.`warehouseFk`)
AND (`dl`.`fecha` = CURDATE()))))
WHERE
((`wa`.`name` = 'Silla')
AND (CAST(`t`.`shipped` AS DATE) = CURDATE()))
GROUP BY `t`.`zoneFk`;

View File

@ -0,0 +1,16 @@
CREATE
OR REPLACE ALGORITHM = UNDEFINED
DEFINER = `root`@`%`
SQL SECURITY DEFINER
VIEW `vn`.`zone_ETD` AS
SELECT
`zed`.`zoneFk` AS `zoneFk`,
`zed`.`hourTheoretical` AS `HoraTeórica`,
`zed`.`totalVolume` AS `volumenTotal`,
`zed`.`remainingVolume` AS `volumenPendiente`,
`zed`.`speed` AS `velocidad`,
`zed`.`hourEffective` AS `HoraPráctica`,
`zed`.`minutesLess` AS `minutesLess`,
`zed`.`etc` AS `etc`
FROM
`vn`.`zoneEstimatedDelivery` `zed`

View File

@ -88,13 +88,18 @@ INSERT INTO `vn`.`country`(`id`, `country`, `isUeeMember`, `code`, `currencyFk`,
(19,'Francia', 1, 'FR', 1, 27), (19,'Francia', 1, 'FR', 1, 27),
(30,'Canarias', 1, 'IC', 1, 24); (30,'Canarias', 1, 'IC', 1, 24);
INSERT INTO `vn`.`warehouse`(`id`, `name`, `isComparative`, `isInventory`, `hasAvailable`, `isManaged`, `hasStowaway`, `hasDms`, `hasComission`) INSERT INTO `vn`.`warehouseAlias`(`id`, `name`)
VALUES VALUES
(1, 'Warehouse One', 1, 1, 1, 1, 1, 1, 1), (1, 'Main Warehouse'),
(2, 'Warehouse Two', 1, 1, 1, 1, 0, 0, 1), (2, 'Silla');
(3, 'Warehouse Three', 1, 1, 1, 1, 0, 0, 0),
(4, 'Warehouse Four', 1, 1, 1, 1, 0, 0, 0), INSERT INTO `vn`.`warehouse`(`id`, `name`, `isComparative`, `isInventory`, `hasAvailable`, `isManaged`, `hasStowaway`, `hasDms`, `hasComission`, `aliasFk`)
(5, 'Warehouse Five', 1, 1, 1, 1, 0, 0, 0); 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);
INSERT INTO `vn`.`sector`(`id`, `description`, `warehouseFk`, `isPreviousPreparedByPacking`, `code`, `pickingPlacement`, `path`) INSERT INTO `vn`.`sector`(`id`, `description`, `warehouseFk`, `isPreviousPreparedByPacking`, `code`, `pickingPlacement`, `path`)
VALUES VALUES
@ -111,10 +116,6 @@ INSERT INTO `vn`.`shelving` (`code`, `parkingFk`, `isPrinted`, `priority`, `park
('GVC', '1', '0', '1', '0', '106'), ('GVC', '1', '0', '1', '0', '106'),
('HEJ', '2', '0', '1', '0', '106'); ('HEJ', '2', '0', '1', '0', '106');
INSERT INTO `vn`.`warehouseAlias`(`id`, `name`)
VALUES
(1, 'Main Warehouse');
INSERT INTO `vn`.`accountingType`(`id`, `description`) INSERT INTO `vn`.`accountingType`(`id`, `description`)
VALUES VALUES
(1, 'Digital money'), (1, 'Digital money'),
@ -511,6 +512,22 @@ INSERT INTO `vn`.`zoneWarehouse` (`id`, `zoneFk`, `warehouseFk`)
(12, 12, 4), (12, 12, 4),
(13, 13, 5); (13, 13, 5);
INSERT INTO `vn`.`zoneClosure` (`zoneFk`, `dated`, `hour`)
VALUES
(1, CURDATE(), '23:59'),
(2, CURDATE(), '23:59'),
(3, CURDATE(), '23:59'),
(4, CURDATE(), '23:59'),
(5, CURDATE(), '23:59'),
(6, CURDATE(), '23:59'),
(7, CURDATE(), '23:59'),
(8, CURDATE(), '23:59'),
(9, CURDATE(), '23:59'),
(10, CURDATE(), '23:59'),
(11, CURDATE(), '23:59'),
(12, CURDATE(), '23:59'),
(13, CURDATE(), '23:59');
INSERT INTO `vn`.`zoneConfig` (`scope`) VALUES ('1'); INSERT INTO `vn`.`zoneConfig` (`scope`) VALUES ('1');
INSERT INTO `vn`.`route`(`id`, `time`, `workerFk`, `created`, `vehicleFk`, `agencyModeFk`, `description`, `m3`, `cost`, `started`, `finished`, `zoneFk`) INSERT INTO `vn`.`route`(`id`, `time`, `workerFk`, `created`, `vehicleFk`, `agencyModeFk`, `description`, `m3`, `cost`, `started`, `finished`, `zoneFk`)

View File

@ -631,7 +631,7 @@ export default {
}, },
ordersIndex: { ordersIndex: {
searchResult: 'vn-order-index vn-card > vn-table > div > vn-tbody > a.vn-tr', searchResult: 'vn-order-index vn-card > vn-table > div > vn-tbody > a.vn-tr',
firstSearchResultTotal: 'vn-order-index vn-card > vn-table > div > vn-tbody vn-tr vn-td:nth-child(7)', secondSearchResultTotal: 'vn-order-index vn-card > vn-table > div > vn-tbody vn-tr:nth-child(2) vn-td:nth-child(9)',
searchResultDate: 'vn-order-index vn-table vn-tbody > a:nth-child(1) > vn-td:nth-child(4)', searchResultDate: 'vn-order-index vn-table vn-tbody > a:nth-child(1) > vn-td:nth-child(4)',
searchResultAddress: 'vn-order-index vn-table vn-tbody > a:nth-child(1) > vn-td:nth-child(6)', searchResultAddress: 'vn-order-index vn-table vn-tbody > a:nth-child(1) > vn-td:nth-child(6)',
searchButton: 'vn-searchbar vn-icon[icon="search"]', searchButton: 'vn-searchbar vn-icon[icon="search"]',

View File

@ -8,6 +8,7 @@ describe('Order summary path', () => {
browser = await getBrowser(); browser = await getBrowser();
page = browser.page; page = browser.page;
await page.loginAndModule('employee', 'order'); await page.loginAndModule('employee', 'order');
await page.waitFor(2000);
await page.accessToSearchResult('16'); await page.accessToSearchResult('16');
}); });

View File

@ -15,9 +15,9 @@ describe('Order Index', () => {
await browser.close(); await browser.close();
}); });
it(`should check the first search result doesn't contain a total of 0€`, async() => { it(`should check the second search result doesn't contain a total of 0€`, async() => {
await page.waitToClick(selectors.ordersIndex.searchButton); await page.waitToClick(selectors.ordersIndex.searchButton);
const result = await page.waitToGetProperty(selectors.ordersIndex.firstSearchResultTotal, 'innerText'); const result = await page.waitToGetProperty(selectors.ordersIndex.secondSearchResultTotal, 'innerText');
expect(result).not.toContain('0.00'); expect(result).not.toContain('0.00');
}); });
@ -26,8 +26,8 @@ describe('Order Index', () => {
await page.waitToClick(selectors.ordersIndex.openAdvancedSearch); await page.waitToClick(selectors.ordersIndex.openAdvancedSearch);
await page.waitToClick(selectors.ordersIndex.advancedSearchShowEmptyCheckbox); await page.waitToClick(selectors.ordersIndex.advancedSearchShowEmptyCheckbox);
await page.waitToClick(selectors.ordersIndex.advancedSearchButton); await page.waitToClick(selectors.ordersIndex.advancedSearchButton);
await page.waitForTextInElement(selectors.ordersIndex.firstSearchResultTotal, '0.00'); await page.waitForTextInElement(selectors.ordersIndex.secondSearchResultTotal, '0.00');
const result = await page.waitToGetProperty(selectors.ordersIndex.firstSearchResultTotal, 'innerText'); const result = await page.waitToGetProperty(selectors.ordersIndex.secondSearchResultTotal, 'innerText');
expect(result).toContain('0.00'); expect(result).toContain('0.00');
}); });

View File

@ -133,5 +133,6 @@
"Distance must be lesser than 1000": "La distancia debe ser inferior a 1000", "Distance must be lesser than 1000": "La distancia debe ser inferior a 1000",
"This ticket is deleted": "Este ticket está eliminado", "This ticket is deleted": "Este ticket está eliminado",
"A travel with this data already exists": "Ya existe un travel con estos datos", "A travel with this data already exists": "Ya existe un travel con estos datos",
"This thermograph id already exists": "La id del termógrafo ya existe" "This thermograph id already exists": "La id del termógrafo ya existe",
"ORDER_ALREADY_CONFIRMED": "ORDER_ALREADY_CONFIRMED"
} }

View File

@ -1,7 +1,6 @@
const app = require('vn-loopback/server/server'); const app = require('vn-loopback/server/server');
// #2304 describe('regularizeClaim()', () => {
xdescribe('regularizeClaim()', () => {
const claimFk = 1; const claimFk = 1;
const pendentState = 1; const pendentState = 1;
const resolvedState = 3; const resolvedState = 3;

View File

@ -133,7 +133,6 @@ module.exports = Self => {
}); });
filter = mergeFilters(filter, {where}); filter = mergeFilters(filter, {where});
let stmts = []; let stmts = [];
let stmt; let stmt;
@ -157,14 +156,20 @@ module.exports = Self => {
c.salesPersonFk, c.salesPersonFk,
u.nickname workerNickname, u.nickname workerNickname,
u.name name, u.name name,
co.code companyCode co.code companyCode,
zed.zoneFk,
zed.hourTheoretical,
zed.hourEffective
FROM hedera.order o FROM hedera.order o
LEFT JOIN address a ON a.id = o.address_id LEFT JOIN address a ON a.id = o.address_id
LEFT JOIN agencyMode am ON am.id = o.agency_id LEFT JOIN agencyMode am ON am.id = o.agency_id
LEFT JOIN client c ON c.id = o.customer_id LEFT JOIN client c ON c.id = o.customer_id
LEFT JOIN worker wk ON wk.id = c.salesPersonFk LEFT JOIN worker wk ON wk.id = c.salesPersonFk
LEFT JOIN account.user u ON u.id = wk.userFk LEFT JOIN account.user u ON u.id = wk.userFk
LEFT JOIN company co ON co.id = o.company_id`); LEFT JOIN company co ON co.id = o.company_id
LEFT JOIN orderTicket ot ON ot.orderFk = o.id
LEFT JOIN ticket t ON t.id = ot.ticketFk
LEFT JOIN zoneEstimatedDelivery zed ON zed.zoneFk = t.zoneFk`);
if (args && args.ticketFk) { if (args && args.ticketFk) {
stmt.merge({ stmt.merge({
@ -172,7 +177,11 @@ module.exports = Self => {
}); });
} }
stmt.merge(conn.makeSuffix(filter)); stmt.merge(conn.makeWhere(filter.where));
bernat marked this conversation as resolved
Review

Eliminar linea comentada

Eliminar linea comentada
stmt.merge({
sql: `GROUP BY o.id`
});
stmt.merge(conn.makePagination(filter));
stmts.push(stmt); stmts.push(stmt);
stmts.push(` stmts.push(`

View File

@ -10,11 +10,13 @@
<vn-thead> <vn-thead>
<vn-tr> <vn-tr>
<vn-th field="id" number>Id</vn-th> <vn-th field="id" number>Id</vn-th>
<vn-th field="clientFk">Client</vn-th>
<vn-th field="salesPersonFk">Sales person</vn-th> <vn-th field="salesPersonFk">Sales person</vn-th>
<vn-th field="clientFk">Client</vn-th>
<vn-th field="isConfirmed" center>Confirmed</vn-th> <vn-th field="isConfirmed" center>Confirmed</vn-th>
<vn-th field="created" center>Created</vn-th> <vn-th field="created" center>Created</vn-th>
<vn-th field="landed" default-order="DESC" center>Landed</vn-th> <vn-th field="landed" default-order="DESC" center>Landed</vn-th>
<vn-th field="created" center title ="Theoretical hour" >T. Hour</vn-th>
<vn-th field="created" center>Real hour </vn-th>
<vn-th center>Total</vn-th> <vn-th center>Total</vn-th>
</vn-tr> </vn-tr>
</vn-thead> </vn-thead>
@ -26,16 +28,16 @@
<vn-td number>{{::order.id}}</vn-td> <vn-td number>{{::order.id}}</vn-td>
<vn-td expand> <vn-td expand>
<span <span
vn-click-stop="clientDescriptor.show($event, order.clientFk)" vn-click-stop="workerDescriptor.show($event, order.salesPersonFk)"
class="link" > class="link" >
{{::order.clientName}} {{::order.name | dashIfEmpty}}
</span> </span>
</vn-td> </vn-td>
<vn-td expand> <vn-td expand>
<span <span
vn-click-stop="workerDescriptor.show($event, order.salesPersonFk)" vn-click-stop="clientDescriptor.show($event, order.clientFk)"
class="link"> class="link">
{{::order.name | dashIfEmpty}} {{::order.clientName}}
</span> </span>
</vn-td> </vn-td>
<vn-td center> <vn-td center>
@ -45,7 +47,13 @@
</vn-check> </vn-check>
</vn-td> </vn-td>
<vn-td center>{{::order.created | date: 'dd/MM/yyyy HH:mm'}}</vn-td> <vn-td center>{{::order.created | date: 'dd/MM/yyyy HH:mm'}}</vn-td>
<vn-td center>{{::order.landed | date:'dd/MM/yyyy'}}</vn-td> <vn-td center>
<span class="chip {{$ctrl.compareDate(order.landed)}}">
{{::order.landed | date:'dd/MM/yyyy'}}
</span>
</vn-td>
<vn-td shrink>{{::order.hourTheoretical | date: 'HH:mm'}}</vn-td>
<vn-td shrink>{{::ticket.hourEffective | date: 'HH:mm'}}</vn-td>
<vn-td number>{{::order.total | currency: 'EUR': 2 | dashIfEmpty}}</vn-td> <vn-td number>{{::order.total | currency: 'EUR': 2 | dashIfEmpty}}</vn-td>
<vn-td shrink> <vn-td shrink>
<vn-icon-button <vn-icon-button

View File

@ -6,6 +6,20 @@ export default class Controller extends Section {
this.selectedOrder = order; this.selectedOrder = order;
this.$.summary.show(); this.$.summary.show();
} }
compareDate(date) {
let today = new Date();
today.setHours(0, 0, 0, 0);
let timeTicket = new Date(date);
timeTicket.setHours(0, 0, 0, 0);
let comparation = today - timeTicket;
if (comparation == 0)
return 'warning';
if (comparation < 0)
return 'success';
}
} }
ngModule.component('vnOrderIndex', { ngModule.component('vnOrderIndex', {

View File

@ -0,0 +1,67 @@
import './index.js';
describe('Component vnOrderIndex', () => {
let controller;
let $window;
let orders = [{
id: 1,
clientFk: 1,
isConfirmed: false
}, {
id: 2,
clientFk: 1,
isConfirmed: false
}, {
id: 3,
clientFk: 1,
isConfirmed: true
}];
beforeEach(ngModule('order'));
beforeEach(inject(($componentController, _$window_,) => {
$window = _$window_;
const $element = angular.element('<vn-order-index></vn-order-index>');
controller = $componentController('vnOrderIndex', {$element});
}));
describe('compareDate()', () => {
it('should return warning when the date is the present', () => {
let curDate = new Date();
let result = controller.compareDate(curDate);
expect(result).toEqual('warning');
});
it('should return sucess when the date is in the future', () => {
let futureDate = new Date();
futureDate = futureDate.setDate(futureDate.getDate() + 10);
let result = controller.compareDate(futureDate);
expect(result).toEqual('success');
});
it('should return undefined when the date is in the past', () => {
let pastDate = new Date();
pastDate = pastDate.setDate(pastDate.getDate() - 10);
let result = controller.compareDate(pastDate);
expect(result).toEqual(undefined);
});
});
describe('preview()', () => {
it('should show the dialog summary', () => {
controller.$.summary = {show: () => {}};
jest.spyOn(controller.$.summary, 'show');
let event = new MouseEvent('click', {
view: $window,
bubbles: true,
cancelable: true
});
controller.preview(event, orders[0]);
expect(controller.$.summary.show).toHaveBeenCalledWith();
});
});
});

View File

@ -22,3 +22,5 @@ Descendant: Descendente
Created from: Creado desde Created from: Creado desde
Search order by id: Buscar el pedido por identificador Search order by id: Buscar el pedido por identificador
order: pedido order: pedido
Confirm lines: Confirmar las lineas
Confirm: Confirmar

View File

@ -1,5 +1,14 @@
<vn-card class="summary"> <vn-card class="summary">
<h5>{{$ctrl.summary.id}} - {{$ctrl.summary.client.name}} - {{$ctrl.summary.client.salesPerson.id}}</h5> <h5>{{$ctrl.summary.id}} - {{$ctrl.summary.client.name}} - {{$ctrl.summary.client.salesPerson.id}}
<vn-button
disabled="$ctrl.order.isConfirmed"
class="flat"
style="color: inherit;"
label="Confirm"
ng-click="$ctrl.save()"
vn-tooltip="Confirm lines">
</vn-button>
</h5>
<vn-horizontal class="ticketSummary__data"> <vn-horizontal class="ticketSummary__data">
<vn-one> <vn-one>
<vn-label-value label="Id" <vn-label-value label="Id"

View File

@ -21,6 +21,15 @@ class Controller extends Section {
if (this.order && this.order.id) if (this.order && this.order.id)
this.setSummary(); this.setSummary();
} }
save() {
this.$http.post(`Orders/${this.order.id}/confirm`).then(() => {
this.vnApp.showSuccess(this.$t('Order confirmed'));
this.$state.go(`ticket.index`, {
q: JSON.stringify({clientFk: this.order.clientFk})
});
});
}
} }
ngModule.component('vnOrderSummary', { ngModule.component('vnOrderSummary', {

View File

@ -3,6 +3,21 @@
vn-order-summary .summary{ vn-order-summary .summary{
max-width: $width-lg; max-width: $width-lg;
h5 {
display: flex;
justify-content: space-between;
align-items: center;
align-content: center;
span {
flex: 1;
}
vn-button {
flex: none
}
}
& > div > vn-horizontal > vn-one { & > div > vn-horizontal > vn-one {
min-width: 160px !important; min-width: 160px !important;

View File

@ -28,5 +28,8 @@
}, },
"ZoneWarehouse": { "ZoneWarehouse": {
"dataSource": "vn" "dataSource": "vn"
},
"ZoneEstimatedDelivery": {
"dataSource": "vn"
} }
} }

View File

@ -0,0 +1,44 @@
{
"name": "ZoneEstimatedDelivery",
"base": "VnModel",
"options": {
"mysql": {
"table": "zoneEstimatedDelivery"
}
},
"properties": {
"zoneFk": {
"id": true,
"type": "Number"
},
"hourTheoretical": {
"type": "date"
},
"totalVolume": {
"type": "Number"
},
"remainingVolume": {
"type": "Number"
},
"speed": {
"type": "Number"
},
"hourEffective": {
"type": "Date"
},
"minutesLess": {
"type": "Date"
},
"etc": {
"type": "Date"
}
},
"relations": {
"zone": {
"type": "belongsTo",
"model": "Zone",
"foreignKey": "zoneFk"
}
}
}