1361 - Añadir filtro por año #348

Merged
joan merged 16 commits from 1361-calendar_date_filter into dev 2020-08-18 12:18:41 +00:00
25 changed files with 1941 additions and 909 deletions
Showing only changes of commit 55b3e962a4 - Show all commits

View File

@ -560,7 +560,7 @@ INSERT INTO `vn`.`ticket`(`id`, `priority`, `agencyModeFk`,`warehouseFk`,`routeF
(16, 1, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 106, 'Many Places', 126, NULL, 0, 3, CURDATE()),
(17, 1, 7, 2, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 106, 'Many Places', 126, NULL, 0, 3, CURDATE()),
(18, 1, 4, 4, 4, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 108, 'Cerebro', 128, NULL, 0, 12, CURDATE()),
(19, 1, 5, 5, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 109, 'Somewhere in Thailand', 129, NULL, 1, 13, CURDATE()),
(19, 1, 5, 5, NULL, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 109, 'Somewhere in Thailand', 129, NULL, 1, 13, CURDATE()),
(20, 1, 5, 5, 3, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 109, 'Somewhere in Thailand', 129, NULL, 0, 13, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)),
(21, NULL, 5, 5, 5, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 109, 'Somewhere in Holland', 102, NULL, 0, 13, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)),
(22, NULL, 5, 5, 5, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 109, 'Somewhere in Japan', 103, NULL, 0, 13, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)),

View File

@ -544,6 +544,7 @@ export default {
logButton: 'vn-left-menu a[ui-sref="ticket.card.log"]',
changedBy: 'vn-ticket-log > vn-log vn-tr:nth-child(1) > vn-td:nth-child(2) > span',
actionTaken: 'vn-ticket-log > vn-log vn-td:nth-child(1) > div > div:nth-child(3) > span.value',
changes: 'vn-ticket-log vn-data-viewer vn-tbody > vn-tr > vn-td:nth-child(7)',
id: 'vn-ticket-log > vn-log vn-td.before > vn-one:nth-child(1) > div > span.value'
},
ticketService: {
@ -868,6 +869,13 @@ export default {
createdThermograph: 'vn-travel-thermograph-index vn-tbody > vn-tr',
upload: 'vn-travel-thermograph-create button[type=submit]'
},
zoneIndex: {
searchResult: 'vn-zone-index a.vn-tr',
},
zoneDescriptor: {
menu: 'vn-zone-descriptor vn-icon-button[vn-popover="menu"]',
deleteZone: 'slot-menu vn-item[ng-click="$ctrl.onDelete()"]'
},
zoneBasicData: {
name: 'vn-zone-basic-data vn-textfield[ng-model="$ctrl.zone.name"]',
agency: 'vn-zone-basic-data vn-autocomplete[ng-model="$ctrl.zone.agencyModeFk"]',

View File

@ -0,0 +1,42 @@
import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer';
describe('Zone descriptor path', () => {
let browser;
let page;
beforeAll(async() => {
browser = await getBrowser();
page = browser.page;
await page.loginAndModule('deliveryBoss', 'zone');
await page.accessToSearchResult('13');
});
afterAll(async() => {
await browser.close();
});
it('should eliminate the zone using the descriptor option', async() => {
await page.waitToClick(selectors.zoneDescriptor.menu);
await page.waitToClick(selectors.zoneDescriptor.deleteZone);
await page.respondToDialog('accept');
await page.waitForState('zone.index');
});
it('should search for the deleted zone to find no results', async() => {
await page.doSearch('13');
const count = await page.countElement(selectors.zoneIndex.searchResult);
expect(count).toEqual(0);
});
it('should check the ticket whom lost the zone and see evidence on the logs', async() => {
await page.waitToClick(selectors.globalItems.homeButton);
await page.selectModule('ticket');
await page.accessToSearchResult('20');
await page.accessToSection('ticket.card.log');
const lastChanges = await page.waitToGetProperty(selectors.ticketLog.changes, 'innerText');
expect(lastChanges).toContain('Arreglar');
});
});

View File

@ -70,7 +70,8 @@ module.exports = {
`front`,
`modules`,
`front/node_modules`,
`node_modules`
`node_modules`,
`print`
],
// An array of file extensions your modules use
@ -153,6 +154,7 @@ module.exports = {
// The glob patterns Jest uses to detect test files
testMatch: [
'**/front/**/*.spec.js',
'**/print/**/*.spec.js',
// 'loopback/**/*.spec.js',
// 'modules/*/back/**/*.spec.js'
// "**/__tests__/**/*.[jt]s?(x)",

View File

@ -134,5 +134,5 @@
"This ticket is deleted": "Este ticket está eliminado",
"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",
"ORDER_ALREADY_CONFIRMED": "ORDER_ALREADY_CONFIRMED"
"Choose a date range or days forward": "Selecciona un rango de fechas o días en adelante"
}

View File

@ -36,7 +36,7 @@ module.exports = Self => {
relation: 'client',
scope: {
include: {
relation: 'salesPerson'
relation: 'salesPersonUser'
}
}
}
@ -53,7 +53,7 @@ module.exports = Self => {
const updatedClaim = await claim.updateAttributes(data);
// Get sales person from claim client
const salesPerson = claim.client().salesPerson();
const salesPerson = claim.client().salesPersonUser();
if (salesPerson && changedHasToPickUp && updatedClaim.hasToPickUp) {
const origin = ctx.req.headers.origin;
const message = $t('Claim will be picked', {

View File

@ -34,17 +34,7 @@ class Controller extends ModuleCard {
scope: {
fields: ['salesPersonFk', 'name', 'email'],
include: {
relation: 'salesPerson',
scope: {
fields: ['userFk'],
include: {
relation: 'user',
scope: {
fields: ['nickname']
}
}
}
relation: 'salesPersonUser'
}
}
}

View File

@ -33,7 +33,7 @@
</vn-label-value>
<vn-label-value
label="Salesperson"
value="{{$ctrl.claim.client.salesPerson.user.nickname}}">
value="{{$ctrl.claim.client.salesPersonUser.nickname}}">
</vn-label-value>
<vn-label-value
label="Attended by"

View File

@ -20,7 +20,8 @@ module.exports = Self => {
const models = Self.app.models;
try {
const imageQueue = await Self.find({limit: 25});
const imageQueue = await Self.find({where: {error: null}, limit: 25});
/* const tempPath = path.join('/tmp/salix-image'); */
const rootPath = models.Image.getPath();
const tempPath = path.join(rootPath, 'temp');
@ -33,24 +34,41 @@ module.exports = Self => {
const file = fs.createWriteStream(filePath);
https.get(image.url, async response => {
if (response.statusCode != 200) {
const error = new Error(`Could not download the image. Status code ${response.statusCode}`);
file.close();
await errorHandler(image.itemFk, error, filePath);
}
response.pipe(file);
});
file.on('finish', async function() {
await models.Image.registerImage('catalog', fileName, filePath);
await image.destroy();
});
file.on('error', async error => {
await errorHandler(image.itemFk, error, filePath);
});
file.on('error', err => {
fs.unlink(filePath);
throw err;
file.on('finish', async function() {
try {
await models.Image.registerImage('catalog', fileName, filePath);
await image.destroy();
} catch (error) {
await errorHandler(image.itemFk, error, filePath);
}
});
}).on('error', async error => {
await errorHandler(image.itemFk, error, filePath);
});
}
} catch (error) {
await errorHandler(image.itemFk, error);
}
return imageQueue;
} catch (e) {
throw e;
async function errorHandler(rowId, error, filePath) {
const row = await Self.findById(rowId);
await row.updateAttribute('error', error);
if (filePath)
await fs.unlink(filePath);
}
};
};

View File

@ -16,6 +16,10 @@
"url": {
"type": "String",
"required": true
},
"error": {
"type": "String",
"required": true
}
},
"relations": {

View File

@ -2,6 +2,7 @@
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
const buildFilter = require('vn-loopback/util/filter').buildFilter;
const mergeFilters = require('vn-loopback/util/filter').mergeFilters;
const UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
Self.remoteMethod('filter', {
@ -233,7 +234,7 @@ module.exports = Self => {
});
}
stmt.merge(conn.makeSuffix(filter));
stmt.merge(conn.makeWhere(filter.where));
stmts.push(stmt);
stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.ticketGetProblems');
@ -241,9 +242,11 @@ module.exports = Self => {
CREATE TEMPORARY TABLE tmp.ticketGetProblems
(INDEX (ticketFk))
ENGINE = MEMORY
SELECT id ticketFk, clientFk, warehouseFk, shipped
FROM tmp.filter
WHERE alertLevel = 0 OR alertLevel IS NULL`);
SELECT f.id ticketFk, f.clientFk, f.warehouseFk, f.shipped
FROM tmp.filter f
LEFT JOIN alertLevel al ON al.alertLevel = f.alertLevel
WHERE (f.alertLevelCode = 'FREE' OR f.alertLevel IS NULL)
AND f.shipped >= CURDATE()`);
stmts.push('CALL ticketGetProblems()');
stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.ticket');
@ -262,6 +265,9 @@ module.exports = Self => {
LEFT JOIN tmp.ticketProblems tp ON tp.ticketFk = f.id
LEFT JOIN tmp.ticketTotal tt ON tt.ticketFk = f.id`);
if (args.problems != undefined && (!args.from || !args.to))
throw new UserError('Choose a date range or days forward');
let condition;
let hasProblem;
let range;
@ -293,6 +299,7 @@ module.exports = Self => {
stmt.merge(conn.makeWhere(problems));
stmt.merge(conn.makeOrderBy(filter.order));
stmt.merge(conn.makeLimit(filter));
let ticketsIndex = stmts.push(stmt);
stmts.push(

View File

@ -2,7 +2,7 @@
vn-id="model"
url="Tickets/filter"
limit="20"
order="shipped DESC, zoneHour ASC, zoneMinute ASC, clientFk">
order="shipped DESC, zoneHour DESC, zoneMinute DESC, clientFk">
</vn-crud-model>
<vn-portal slot="topbar">
<vn-searchbar

2588
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -40,7 +40,7 @@
"@babel/core": "^7.7.7",
"@babel/plugin-syntax-dynamic-import": "^7.7.4",
"@babel/polyfill": "^7.7.0",
"@babel/preset-env": "^7.7.7",
"@babel/preset-env": "^7.11.0",
"@babel/register": "^7.7.7",
"angular-mocks": "^1.7.9",
"babel-jest": "^26.0.1",

View File

@ -4,8 +4,8 @@ let env = process.env.NODE_ENV ? process.env.NODE_ENV : 'development';
let configPath = `/etc/salix`;
let config = require('../config/print.json');
let configFiles = [
`${appPath}/config/print.local.json`,
`${appPath}/config/print.${env}.json`,
`../config/print.local.json`,
`../config/print.${env}.json`,
`${configPath}/print.json`,
`${configPath}/print.local.json`,
`${configPath}/print.${env}.json`

View File

@ -2,9 +2,13 @@ const Vue = require('vue');
const config = require('../config');
const defaultLocale = config.i18n.locale;
Vue.filter('currency', function(value, currency = 'EUR', locale = defaultLocale) {
const currency = function(value, currency = 'EUR', locale = defaultLocale) {
if (!locale) locale = defaultLocale;
return new Intl.NumberFormat(locale, {
style: 'currency', currency
}).format(parseFloat(value));
});
};
Vue.filter('currency', currency);
module.exports = currency;

View File

@ -1,7 +1,11 @@
const Vue = require('vue');
const strftime = require('strftime');
Vue.filter('date', function(value, specifiers = '%d-%m-%Y') {
const date = function(value, specifiers = '%d-%m-%Y') {
if (!(value instanceof Date)) value = new Date(value);
return strftime(specifiers, value);
});
};
Vue.filter('date', date);
module.exports = date;

View File

@ -2,9 +2,13 @@ const Vue = require('vue');
const config = require('../config');
const defaultLocale = config.i18n.locale;
Vue.filter('number', function(value, locale = defaultLocale) {
const number = function(value, locale = defaultLocale) {
if (!locale) locale = defaultLocale;
return new Intl.NumberFormat(locale, {
style: 'decimal'
}).format(parseFloat(value));
});
};
Vue.filter('number', number);
module.exports = number;

View File

@ -2,11 +2,15 @@ const Vue = require('vue');
const config = require('../config');
const defaultLocale = config.i18n.locale;
Vue.filter('percentage', function(value, minFraction = 2, maxFraction = 2, locale = defaultLocale) {
const percentage = function(value, minFraction = 2, maxFraction = 2, locale = defaultLocale) {
if (!locale) locale = defaultLocale;
return new Intl.NumberFormat(locale, {
style: 'percent',
minimumFractionDigits: minFraction,
maximumFractionDigits: maxFraction
}).format(parseFloat(value));
});
};
Vue.filter('percentage', percentage);
module.exports = percentage;

View File

@ -0,0 +1,16 @@
// Extended locale intl polyfill
const IntlPolyfill = require('intl');
Intl.NumberFormat = IntlPolyfill.NumberFormat;
Intl.DateTimeFormat = IntlPolyfill.DateTimeFormat;
import currency from '../currency.js';
describe('currency filter', () => {
it('should filter the currency in spanish as default', () => {
expect(currency(999, 'EUR')).toEqual('999,00 €');
});
it('should filter the currency in english', () => {
expect(currency(999, 'EUR', 'en')).toEqual('€999.00');
});
});

View File

@ -0,0 +1,27 @@
import date from '../date.js';
describe('date filter', () => {
const superDuperDate = new Date('February 18, 1984 @ 11:30:00 am');
it('should filter the date as %d-%m-%Y by default', () => {
expect(date(superDuperDate)).toEqual('18-02-1984');
});
it('should filter the date as %m-%d-%Y', () => {
const dateFormat = '%m-%d-%Y';
expect(date(superDuperDate, dateFormat)).toEqual('02-18-1984');
});
it('should filter the date as %y-%d-%m', () => {
const dateFormat = '%y-%d-%m';
expect(date(superDuperDate, dateFormat)).toEqual('84-18-02');
});
it('should filter the date as %Y-%d-%m', () => {
const dateFormat = '%Y-%d-%m';
expect(date(superDuperDate, dateFormat)).toEqual('1984-18-02');
});
});

View File

@ -0,0 +1,9 @@
import number from '../number.js';
describe('number filter', () => {
const superDuperNumber = 18021984;
it('should filter the number with commas by default', () => {
expect(number(superDuperNumber)).toEqual('18,021,984');
});
});

View File

@ -0,0 +1,11 @@
import percentage from '../percentage.js';
describe('percentage filter', () => {
it('should filter the percentage also round it correctly', () => {
expect(percentage(99.9999999999999999 / 100)).toEqual('100.00%');
});
it('should filter the percentage and round it correctly', () => {
expect(percentage(1.25444444444444444 / 100)).toEqual('1.25%');
});
});

View File

@ -0,0 +1,10 @@
import uppercase from '../uppercase.js';
describe('uppercase filter', () => {
it('should filter the string to uppercase', () => {
let lowerCase = 'text';
let upperCase = 'TEXT';
expect(uppercase(lowerCase)).toEqual(upperCase);
});
});

View File

@ -1,5 +1,9 @@
const Vue = require('vue');
Vue.filter('uppercase', function(value) {
const uppercase = function(value) {
return value.toUpperCase();
});
};
Vue.filter('uppercase', uppercase);
module.exports = uppercase;