1361 - Añadir filtro por año #348
|
@ -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)),
|
||||
|
|
|
@ -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"]',
|
||||
|
|
|
@ -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');
|
||||
});
|
||||
});
|
|
@ -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)",
|
||||
|
|
|
@ -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"
|
||||
}
|
|
@ -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', {
|
||||
|
|
|
@ -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'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
@ -78,4 +78,4 @@
|
|||
on-accept="$ctrl.deleteClaim()"
|
||||
question="Delete claim"
|
||||
message="Are you sure you want to delete this claim?">
|
||||
</vn-confirm>
|
||||
</vn-confirm>
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
@ -16,6 +16,10 @@
|
|||
"url": {
|
||||
"type": "String",
|
||||
"required": true
|
||||
},
|
||||
"error": {
|
||||
"type": "String",
|
||||
"required": true
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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",
|
||||
|
|
|
@ -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`
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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');
|
||||
});
|
||||
});
|
|
@ -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');
|
||||
});
|
||||
});
|
|
@ -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');
|
||||
});
|
||||
});
|
|
@ -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%');
|
||||
});
|
||||
});
|
|
@ -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);
|
||||
});
|
||||
});
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue