Merge branch 'dev' into 2819-notify_assignment
gitea/salix/pipeline/head This commit looks good Details

This commit is contained in:
Joan Sanchez 2021-03-24 11:47:38 +00:00
commit c65fbef3df
24 changed files with 257 additions and 2426 deletions

View File

@ -1 +0,0 @@
Delete me

View File

@ -0,0 +1 @@
Delete this

View File

@ -564,13 +564,13 @@ INSERT INTO `vn`.`zoneConfig` (`scope`) VALUES ('1');
INSERT INTO `vn`.`route`(`id`, `time`, `workerFk`, `created`, `vehicleFk`, `agencyModeFk`, `description`, `m3`, `cost`, `started`, `finished`, `zoneFk`)
VALUES
(1, '1899-12-30 12:15:00', 56, CURDATE(), 1, 1, 'first route', 1.8, 10, CURDATE(), CURDATE(), 1),
(2, '1899-12-30 13:20:00', 56, CURDATE(), 1, 2, 'second route', 0.2, 20, CURDATE(), CURDATE(), 9),
(3, '1899-12-30 14:30:00', 56, CURDATE(), 2, 3, 'third route', 0.5, 30, CURDATE(), CURDATE(), 10),
(4, '1899-12-30 15:45:00', 56, CURDATE(), 3, 4, 'fourth route', 0, 40, CURDATE(), CURDATE(), 12),
(5, '1899-12-30 16:00:00', 56, CURDATE(), 4, 5, 'fifth route', 0.1, 50, CURDATE(), CURDATE(), 13),
(6, NULL, 57, CURDATE(), 5, 7, 'sixth route', 1.7, 60, CURDATE(), CURDATE(), 3),
(7, NULL, 57, CURDATE(), 6, 8, 'seventh route', 0, 70, CURDATE(), CURDATE(), 5);
(1, '1899-12-30 12:15:00', 56, CURDATE(), 1, 1, 'first route', 1.8, 10, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 1),
(2, '1899-12-30 13:20:00', 56, CURDATE(), 1, 2, 'second route', 0.2, 20, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 9),
(3, '1899-12-30 14:30:00', 56, CURDATE(), 2, 3, 'third route', 0.5, 30, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 10),
(4, '1899-12-30 15:45:00', 56, CURDATE(), 3, 4, 'fourth route', 0, 40, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 12),
(5, '1899-12-30 16:00:00', 56, CURDATE(), 4, 5, 'fifth route', 0.1, 50, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 13),
(6, NULL, 57, CURDATE(), 5, 7, 'sixth route', 1.7, 60, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 3),
(7, NULL, 57, CURDATE(), 6, 8, 'seventh route', 0, 70, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 5);
INSERT INTO `vn`.`ticket`(`id`, `priority`, `agencyModeFk`,`warehouseFk`,`routeFk`, `shipped`, `landed`, `clientFk`,`nickname`, `addressFk`, `refFk`, `isDeleted`, `zoneFk`, `zonePrice`, `zoneBonus`, `created`)
VALUES
@ -2257,3 +2257,10 @@ INSERT INTO `vn`.`ticketRecalc`(`ticketFk`)
SELECT `id` FROM `vn`.`ticket`;
CALL `vn`.`ticket_doRecalc`();
INSERT INTO `vn`.`zoneAgencyMode`(`id`, `agencyModeFk`, `zoneFk`)
VALUES
(1, 1, 1),
(2, 1, 2),
(3, 6, 5),
(4, 7, 1);

View File

@ -790,10 +790,11 @@ export default {
saveButton: 'vn-route-basic-data button[type=submit]'
},
routeTickets: {
firstTicketPriority: 'vn-route-tickets vn-tr:nth-child(1) vn-textfield[ng-model="ticket.priority"]',
firstTicketPriority: 'vn-route-tickets vn-tr:nth-child(1) vn-input-number[ng-model="ticket.priority"]',
firstTicketCheckbox: 'vn-route-tickets vn-tr:nth-child(1) vn-check',
buscamanButton: 'vn-route-tickets vn-button[icon="icon-buscaman"]',
firstTicketDeleteButton: 'vn-route-tickets vn-tr:nth-child(1) vn-icon[icon="delete"]',
anyTicket: 'vn-route-tickets vn-tbody > vn-tr',
confirmButton: '.vn-confirm.shown button[response="accept"]'
},
workerSummary: {

View File

@ -1,8 +1,7 @@
import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer';
// #1528 e2e claim/detail
xdescribe('Route basic Data path', () => {
describe('Route tickets path', () => {
let browser;
let page;
@ -10,7 +9,7 @@ xdescribe('Route basic Data path', () => {
browser = await getBrowser();
page = browser.page;
await page.loginAndModule('delivery', 'route');
await page.accessToSearchResult('3');
await page.accessToSearchResult('2');
await page.accessToSection('route.card.tickets');
});
@ -19,40 +18,32 @@ xdescribe('Route basic Data path', () => {
});
it('should modify the first ticket priority', async() => {
await page.write(selectors.routeTickets.firstTicketPriority, '2');
await page.clearInput(selectors.routeTickets.firstTicketPriority);
await page.type(selectors.routeTickets.firstTicketPriority, '9');
await page.keyboard.press('Enter');
const message = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!');
});
it('should confirm the buscamanButton is disabled', async() => {
const result = await page.evaluate(selector => {
return document.querySelector(selector);
}, `${selectors.routeTickets.buscamanButton} :disabled`);
expect(result).toBeTruthy();
it('should confirm the buscaman button is disabled', async() => {
await page.waitForSelector(`${selectors.routeTickets.buscamanButton}.disabled`);
});
it('should check the first ticket checkbox and confirm the buscamanButton button is no longer disabled', async() => {
await page.waitToClick(selectors.routeTickets.firstTicketCheckbox);
const result = await page.evaluate(selector => {
return document.querySelector(selector);
}, `${selectors.routeTickets.buscamanButton} :disabled`);
expect(result).toBeFalsy();
await page.waitForSelector(`${selectors.routeTickets.buscamanButton}.disabled`, {visible: false});
});
it('should check the route volume on the descriptor', async() => {
const result = await page.waitToGetProperty(selectors.routeDescriptor.volume, 'innerText');
expect(result).toEqual('1.1 / 18 m³');
expect(result).toEqual('0.2 / 50 m³');
});
it('should count how many tickets are in route', async() => {
const result = await page.countElement('vn-route-tickets vn-textfield[ng-model="ticket.priority"]');
const result = await page.countElement(selectors.routeTickets.anyTicket);
expect(result).toEqual(11);
expect(result).toEqual(1);
});
it('should delete the first ticket in route', async() => {
@ -63,23 +54,14 @@ xdescribe('Route basic Data path', () => {
expect(message.text).toContain('Ticket removed from route');
});
it('should again delete the first ticket in route', async() => {
await page.waitToClick(selectors.routeTickets.firstTicketDeleteButton);
await page.waitToClick(selectors.routeTickets.confirmButton);
const message = await page.waitForSnackbar();
expect(message.text).toContain('Ticket removed from route');
});
it('should now count how many tickets are in route to find one less', async() => {
const result = await page.countElement('vn-route-tickets vn-textfield[ng-model="ticket.priority"]');
expect(result).toEqual(9);
await page.waitForNumberOfElements(selectors.routeTickets.anyTicket, 0);
});
it('should confirm the route volume on the descriptor has been updated by the changes made', async() => {
// #2862 updateVolume() route descriptor no actualiza volumen
xit('should confirm the route volume on the descriptor has been updated by the changes made', async() => {
const result = await page.waitToGetProperty(selectors.routeDescriptor.volume, 'innerText');
expect(result).toEqual('0.9 / 18 m³');
expect(result).toEqual('0 / 50 m³');
});
});

View File

@ -1,8 +1,7 @@
import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer';
// #2833 Refactor account.basicData
xdescribe('Account create and basic data path', () => {
describe('Account create and basic data path', () => {
let browser;
let page;
@ -37,40 +36,23 @@ xdescribe('Account create and basic data path', () => {
await page.waitForState('account.card.basicData');
});
it('should edit the basic data', async() => {
await page.overwrite(selectors.accountBasicData.name, 'Anna');
await page.overwrite(selectors.accountBasicData.nickname, 'Rogue');
await page.overwrite(selectors.accountBasicData.email, 'AnnaMarieLeBeau@verdnatura.es');
await page.autocompleteSearch(selectors.accountBasicData.language, 'english');
await page.waitToClick(selectors.accountBasicData.save);
const message = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!');
});
it('should reload the section and check the name was edited successfully', async() => {
it('should reload the section and check the name is as expected', async() => {
await page.reloadSection('account.card.basicData');
const result = await page.waitToGetProperty(selectors.accountBasicData.name, 'value');
expect(result).toEqual('Anna');
expect(result).toEqual('Remy');
});
it('should check the nickname was edited successfully', async() => {
it('should check the nickname is as expected', async() => {
const result = await page.waitToGetProperty(selectors.accountBasicData.nickname, 'value');
expect(result).toEqual('Rogue');
expect(result).toEqual('Gambit');
});
it('should check the email was edited successfully', async() => {
it('should check the email is as expected', async() => {
const result = await page.waitToGetProperty(selectors.accountBasicData.email, 'value');
expect(result).toEqual('AnnaMarieLeBeau@verdnatura.es');
});
it('should check the language was edited successfully', async() => {
const result = await page.waitToGetProperty(selectors.accountBasicData.language, 'value');
expect(result).toEqual('English');
expect(result).toEqual('RemyEtienneLeBeau@verdnatura.es');
});
it('should navigate to the roles section to check the roles are correct', async() => {

155
front/package-lock.json generated
View File

@ -1,144 +1,8 @@
{
"name": "salix-front",
"version": "1.0.0",
"lockfileVersion": 2,
"lockfileVersion": 1,
"requires": true,
"packages": {
"": {
"name": "salix-front",
"version": "1.0.0",
"license": "GPL-3.0",
"dependencies": {
"@uirouter/angularjs": "^1.0.20",
"angular": "^1.7.5",
"angular-animate": "^1.7.8",
"angular-translate": "^2.18.1",
"angular-translate-loader-partial": "^2.18.1",
"js-yaml": "^3.13.1",
"mg-crud": "^1.1.2",
"oclazyload": "^0.6.3",
"require-yaml": "0.0.1",
"validator": "^6.3.0"
}
},
"node_modules/@uirouter/angularjs": {
"version": "1.0.29",
"resolved": "https://registry.npmjs.org/@uirouter/angularjs/-/angularjs-1.0.29.tgz",
"integrity": "sha512-RImWnBarNixkMto0o8stEaGwZmvhv5cnuOLXyMU2pY8MP2rgEF74ZNJTLeJCW14LR7XDUxVH8Mk8bPI6lxedmQ==",
"dependencies": {
"@uirouter/core": "6.0.7"
},
"engines": {
"node": ">=4.0.0"
},
"peerDependencies": {
"angular": ">=1.2.0"
}
},
"node_modules/@uirouter/core": {
"version": "6.0.7",
"resolved": "https://registry.npmjs.org/@uirouter/core/-/core-6.0.7.tgz",
"integrity": "sha512-KUTJxL+6q0PiBnFx4/Z+Hsyg0pSGiaW5yZQeJmUxknecjpTbnXkLU8H2EqRn9N2B+qDRa7Jg8RcgeNDPY72O1w==",
"engines": {
"node": ">=4.0.0"
}
},
"node_modules/angular": {
"version": "1.8.2",
"resolved": "https://registry.npmjs.org/angular/-/angular-1.8.2.tgz",
"integrity": "sha512-IauMOej2xEe7/7Ennahkbb5qd/HFADiNuLSESz9Q27inmi32zB0lnAsFeLEWcox3Gd1F6YhNd1CP7/9IukJ0Gw=="
},
"node_modules/angular-animate": {
"version": "1.8.2",
"resolved": "https://registry.npmjs.org/angular-animate/-/angular-animate-1.8.2.tgz",
"integrity": "sha512-Jbr9+grNMs9Kj57xuBU3Ju3NOPAjS1+g2UAwwDv7su1lt0/PLDy+9zEwDiu8C8xJceoTbmBNKiWGPJGBdCQLlA=="
},
"node_modules/angular-translate": {
"version": "2.18.4",
"resolved": "https://registry.npmjs.org/angular-translate/-/angular-translate-2.18.4.tgz",
"integrity": "sha512-KohNrkH6J9PK+VW0L/nsRTcg5Fw70Ajwwe3Jbfm54Pf9u9Fd+wuingoKv+h45mKf38eT+Ouu51FPua8VmZNoCw==",
"dependencies": {
"angular": "^1.8.0"
},
"engines": {
"node": "*"
}
},
"node_modules/angular-translate-loader-partial": {
"version": "2.18.4",
"resolved": "https://registry.npmjs.org/angular-translate-loader-partial/-/angular-translate-loader-partial-2.18.4.tgz",
"integrity": "sha512-bsjR+FbB0sdA2528E/ugwKdlPPQhA1looxLxI3otayBTFXBpED33besfSZhYAISLgNMSL038vSssfRUen9qD8w==",
"dependencies": {
"angular-translate": "~2.18.4"
}
},
"node_modules/argparse": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
"dependencies": {
"sprintf-js": "~1.0.2"
}
},
"node_modules/esprima": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
"bin": {
"esparse": "bin/esparse.js",
"esvalidate": "bin/esvalidate.js"
},
"engines": {
"node": ">=4"
}
},
"node_modules/js-yaml": {
"version": "3.14.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
"dependencies": {
"argparse": "^1.0.7",
"esprima": "^4.0.0"
},
"bin": {
"js-yaml": "bin/js-yaml.js"
}
},
"node_modules/mg-crud": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/mg-crud/-/mg-crud-1.1.2.tgz",
"integrity": "sha1-p6AWGzWSPK7/8ZpIBpS2V1vDggw=",
"dependencies": {
"angular": "^1.6.1"
}
},
"node_modules/oclazyload": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/oclazyload/-/oclazyload-0.6.3.tgz",
"integrity": "sha1-Kjirv/QJDAihEBZxkZRbWfLoJ5w="
},
"node_modules/require-yaml": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/require-yaml/-/require-yaml-0.0.1.tgz",
"integrity": "sha1-LhsY2RPDuqcqWk03O28Tjd0sMr0=",
"dependencies": {
"js-yaml": ""
}
},
"node_modules/sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
},
"node_modules/validator": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/validator/-/validator-6.3.0.tgz",
"integrity": "sha1-R84j7Y1Ord+p1LjvAHG2zxB418g=",
"engines": {
"node": ">= 0.10"
}
}
},
"dependencies": {
"@uirouter/angularjs": {
"version": "1.0.29",
@ -219,7 +83,22 @@
"resolved": "https://registry.npmjs.org/require-yaml/-/require-yaml-0.0.1.tgz",
"integrity": "sha1-LhsY2RPDuqcqWk03O28Tjd0sMr0=",
"requires": {
"js-yaml": ""
"js-yaml": "^4.0.0"
},
"dependencies": {
"argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
},
"js-yaml": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz",
"integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==",
"requires": {
"argparse": "^2.0.1"
}
}
}
},
"sprintf-js": {

View File

@ -32,7 +32,7 @@
<div ng-transclude="before"></div>
<div class="body">
<div class="top">
<h5>{{$ctrl.description}}</h5>
<h5 title="{{$ctrl.description}}">{{$ctrl.description}}</h5>
<div>
{{$ctrl.descriptor.id | id}}
</div>

View File

@ -42,7 +42,7 @@ Travels: Envíos
Workers: Trabajadores
Routes: Rutas
Locator: Localizador
Invoices out: Facturas emitidas
Invoices out: Fact. emitidas
Invoices in: Fact. recibidas
Entries: Entradas
Users: Usuarios

View File

@ -2,4 +2,5 @@ reference: Referencia
Observation: Observación
Box: Embalaje
Import buys: Importar compras
Some of the imported buys doesn't have an item: Algunas de las compras importadas no tienen un artículo
Some of the imported buys doesn't have an item: Algunas de las compras importadas no tienen un artículo
JSON files only: Solo ficheros JSON

View File

@ -165,9 +165,13 @@
<vn-dialog class="edit"
vn-id="edit"
on-accept="$ctrl.onEditAccept()"
on-close="$ctrl.editedColumn = null"
message="Edit buy(s)">
on-close="$ctrl.editedColumn = null">
<tpl-body>
<span translate>Edit</span>
<span class="countLines">
{{::$ctrl.totalChecked}}
</span>
<span translate>buy(s)</span>
<vn-horizontal>
<vn-autocomplete
vn-two

View File

@ -1,5 +1,6 @@
import ngModule from '../module';
import Section from 'salix/components/section';
import './style.scss';
export default class Controller extends Section {
constructor($element, $) {

View File

@ -12,3 +12,5 @@ Weight: Peso
Minimun amount: Cantidad mínima de compra
Field to edit: Campo a editar
PackageName: Cubo
Edit: Editar
buy(s): compra(s)

View File

@ -0,0 +1,7 @@
.countLines {
flex: 0.15;
font-size: 24px;
color: orangered;
font-weight: bold;
max-width: 30px;
}

View File

@ -0,0 +1,72 @@
module.exports = Self => {
Self.remoteMethod('getSuggestedTickets', {
description: 'Returns an array of suggested tickets for the given route',
accessType: 'READ',
accepts: [{
arg: 'id',
type: 'number',
required: true,
description: 'The route id',
http: {source: 'path'}
}],
returns: {
type: ['object'],
root: true
},
http: {
path: `/:id/getSuggestedTickets`,
verb: 'GET'
}
});
Self.getSuggestedTickets = async id => {
const ticketsInRoute = await Self.app.models.Ticket.find({
where: {routeFk: id},
fields: ['id']
});
const idsToExclude = ticketsInRoute.map(ticket => ticket.id);
const route = await Self.app.models.Route.findById(id);
const zoneAgencyModes = await Self.app.models.ZoneAgencyMode.find({
where: {
agencyModeFk: route.agencyModeFk
}
});
const zoneIds = [];
for (let zoneAgencyMode of zoneAgencyModes)
zoneIds.push(zoneAgencyMode.zoneFk);
const minDate = new Date(route.finished);
minDate.setHours(0, 0, 0, 0);
const maxDate = new Date(route.finished);
maxDate.setHours(23, 59, 59, 59);
let tickets = await Self.app.models.Ticket.find({
where: {
agencyModeFk: route.agencyModeFk,
zoneFk: {inq: zoneIds},
id: {nin: idsToExclude},
landed: {between: [minDate, maxDate]}
},
include: [
{
relation: 'warehouse',
scope: {
fields: ['id', 'name']
}
},
{
relation: 'address',
scope: {
fields: ['id', 'street', 'postalCode', 'city'],
}
},
]
});
return tickets;
};
};

View File

@ -0,0 +1,30 @@
const app = require('vn-loopback/server/server');
const LoopBackContext = require('loopback-context');
describe('route getSuggestedTickets()', () => {
it('should return an array of suggested tickets', async() => {
const activeCtx = {
accessToken: {userId: 19},
headers: {origin: 'http://localhost'}
};
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
active: activeCtx
});
const routeID = 1;
const ticketInRoute = await app.models.Ticket.findById(12);
await ticketInRoute.updateAttribute('routeFk', null);
const result = await app.models.Route.getSuggestedTickets(routeID);
const length = result.length;
const anyResult = result[Math.floor(Math.random() * Math.floor(length))];
expect(result.length).toEqual(1);
expect(anyResult.zoneFk).toEqual(1);
expect(anyResult.agencyModeFk).toEqual(1);
await ticketInRoute.updateAttribute('routeFk', routeID);
});
});

View File

@ -4,7 +4,7 @@ const LoopBackContext = require('loopback-context');
describe('route insertTicket()', () => {
const deliveryId = 56;
let originalTicket;
const routeId = 2;
const routeId = 1;
const activeCtx = {
accessToken: {userId: deliveryId},
};
@ -17,26 +17,18 @@ describe('route insertTicket()', () => {
done();
});
afterAll(async done => {
try {
await originalTicket.updateAttribute('routeFk', null);
} catch (error) {
console.error(error);
}
done();
});
it('should add the ticket to a route', async() => {
originalTicket = await app.models.Ticket.findById(14);
const ticketId = 12;
originalTicket = await app.models.Ticket.findById(ticketId);
await originalTicket.updateAttribute('routeFk', null);
const ticketId = 14;
const result = await app.models.Route.insertTicket(routeId, ticketId);
expect(result.routeFk).toEqual(2);
expect(result.routeFk).toEqual(routeId);
});
it('should throw and error if the ticket is not suitable for the route', async() => {
const ticketId = 23;
const ticketId = 2;
let error;
try {

View File

@ -7,6 +7,7 @@ module.exports = Self => {
require('../methods/route/getDeliveryPoint')(Self);
require('../methods/route/insertTicket')(Self);
require('../methods/route/clone')(Self);
require('../methods/route/getSuggestedTickets')(Self);
Self.validate('kmStart', validateDistance, {
message: 'Distance must be lesser than 1000'

View File

@ -80,7 +80,7 @@
<vn-td shrink>
<vn-icon
ng-if="ticket.notes.length"
title="::{{ticket.notes[0].description}}"
title="{{ticket.notes[0].description}}"
icon="insert_drive_file"
class="bright">
</vn-icon>
@ -110,10 +110,9 @@
question="Delete ticket from route?"
on-accept="$ctrl.removeTicketFromRoute()">
</vn-confirm>
<vn-crud-model
<vn-crud-model
vn-id="possibleTicketsModel"
url="Tickets"
filter="$ctrl.possibleTicketsFilter"
url="Routes/{{$ctrl.$params.id}}/getSuggestedTickets"
data="$ctrl.possibleTickets">
</vn-crud-model>
<vn-dialog

View File

@ -9,8 +9,6 @@ class Controller extends Section {
set route(value) {
this._route = value;
if (value)
this.buildPossibleTicketsFilter();
}
get isChecked() {
@ -22,32 +20,6 @@ class Controller extends Section {
return false;
}
buildPossibleTicketsFilter() {
let minDate = new Date(this.route.finished);
minDate.setHours(0, 0, 0, 0);
let maxDate = new Date(this.route.finished);
maxDate.setHours(23, 59, 59, 59);
this.possibleTicketsFilter = {
where: {
zoneFk: this.route.zoneFk,
routeFk: null,
landed: {between: [minDate, maxDate]},
},
include: [
{
relation: 'warehouse',
scope: {
fields: ['name']
},
}, {
relation: 'address'
}
]
};
}
getHighestPriority() {
let highestPriority = Math.max(...this.$.model.data.map(tag => {
return tag.priority;
@ -134,14 +106,26 @@ class Controller extends Section {
setTicketsRoute() {
let tickets = this.getSelectedItems(this.possibleTickets);
if (tickets.length === 0) return;
for (let i = 0; i < tickets.length; i++) {
delete tickets[i].checked;
tickets[i].routeFk = this.route.id;
const updates = [];
for (let ticket of tickets) {
delete ticket.checked;
const update = {
where: {id: ticket.id},
data: {routeFk: this.route.id}
};
updates.push(update);
}
return this.$.possibleTicketsModel.save().then(() => {
this.$.model.data = this.$.model.data.concat(tickets);
});
const data = {creates: [], updates: updates, deletes: []};
return this.$http.post(`Tickets/crud`, data)
.then(() => {
this.$.model.data = this.$.model.data.concat(tickets);
this.vnApp.showSuccess(this.$t('Data saved!'));
});
}
onDrop($event) {

View File

@ -37,42 +37,6 @@ describe('Route', () => {
});
});
describe('buildPossibleTicketsFilter()', () => {
it('should build the possible tickets filter', () => {
let expectedFilter = {
include: [
{
relation: 'warehouse',
scope: {
fields: ['name']
}
}, {
relation: 'address'
}
],
where: {
landed: {
between: [
jasmine.any(Date),
jasmine.any(Date)
]
},
routeFk: null,
zoneFk: 67
}
};
controller.route = {
finished: new Date(),
routeFk: null,
zoneFk: 67
};
controller.buildPossibleTicketsFilter();
expect(controller.possibleTicketsFilter).toEqual(expectedFilter);
});
});
describe('getHighestPriority()', () => {
it('should return the highest value found in priorities plus 1', () => {
controller.$.model = {data: [
@ -228,13 +192,13 @@ describe('Route', () => {
});
describe('setTicketsRoute()', () => {
it('should perform a POST query to add tickets to the route', done => {
controller.$.possibleTicketsModel = {save: () => {}};
jest.spyOn(controller.$.possibleTicketsModel, 'save').mockReturnValue(Promise.resolve());
it('should perform a POST query to add tickets to the route', () => {
controller.$.model = {data: [
{id: 1, checked: false}
]};
const existingTicket = controller.$.model.data[0];
controller.route = {id: 111};
controller.possibleTickets = [
@ -245,15 +209,16 @@ describe('Route', () => {
];
let expectedResult = [
{checked: false, id: 1},
{id: 3, routeFk: 111},
{id: 5, routeFk: 111}
existingTicket,
{id: 3},
{id: 5}
];
controller.setTicketsRoute().then(() => {
expect(controller.$.model.data).toEqual(expectedResult);
done();
}).catch(done.fail);
$httpBackend.expectPOST(`Tickets/crud`).respond();
controller.setTicketsRoute();
$httpBackend.flush();
expect(controller.$.model.data).toEqual(expectedResult);
});
});

View File

@ -11,6 +11,9 @@
"Zone": {
"dataSource": "vn"
},
"ZoneAgencyMode": {
"dataSource": "vn"
},
"ZoneClosure": {
"dataSource": "vn"
},

View File

@ -0,0 +1,29 @@
{
"name": "ZoneAgencyMode",
"base": "VnModel",
"options": {
"mysql": {
"table": "zoneAgencyMode"
}
},
"properties": {
"id": {
"id": true,
"type": "number"
},
"agencyModeFk": {
"type": "number"
},
"zoneFk": {
"type": "number"
}
},
"acls": [
{
"accessType": "READ",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW"
}
]
}

2128
print/package-lock.json generated

File diff suppressed because it is too large Load Diff