Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 2205-loggable_relations_fix
This commit is contained in:
commit
a3e7771295
|
@ -0,0 +1 @@
|
||||||
|
UPDATE `salix`.`ACL` SET `accessType`='WRITE' WHERE `id`='213';
|
|
@ -828,6 +828,12 @@ export default {
|
||||||
},
|
},
|
||||||
travelThermograph: {
|
travelThermograph: {
|
||||||
add: 'vn-travel-thermograph-index vn-float-button[icon="add"]',
|
add: 'vn-travel-thermograph-index vn-float-button[icon="add"]',
|
||||||
|
addThermographIcon: 'vn-travel-thermograph-create vn-autocomplete vn-icon[icon="add_circle"]',
|
||||||
|
newThermographId: 'vn-textfield[ng-model="$ctrl.newThermograph.thermographId"]',
|
||||||
|
newThermographModel: 'vn-autocomplete[ng-model="$ctrl.newThermograph.model"]',
|
||||||
|
newThermographWarehouse: 'vn-autocomplete[ng-model="$ctrl.newThermograph.warehouseId"]',
|
||||||
|
newThermographTemperature: 'vn-autocomplete[ng-model="$ctrl.newThermograph.temperature"]',
|
||||||
|
createThermographButton: 'form button[response="accept"]',
|
||||||
thermographID: 'vn-travel-thermograph-create vn-autocomplete[ng-model="$ctrl.dms.thermographId"]',
|
thermographID: 'vn-travel-thermograph-create vn-autocomplete[ng-model="$ctrl.dms.thermographId"]',
|
||||||
uploadIcon: 'vn-travel-thermograph-create vn-icon[icon="icon-attach"]',
|
uploadIcon: 'vn-travel-thermograph-create vn-icon[icon="icon-attach"]',
|
||||||
createdThermograph: 'vn-travel-thermograph-index vn-tbody > vn-tr',
|
createdThermograph: 'vn-travel-thermograph-index vn-tbody > vn-tr',
|
||||||
|
|
|
@ -2,6 +2,7 @@ import selectors from '../../helpers/selectors.js';
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
import getBrowser from '../../helpers/puppeteer';
|
||||||
|
|
||||||
describe('Travel thermograph path', () => {
|
describe('Travel thermograph path', () => {
|
||||||
|
const thermographName = '7H3-37H3RN4L-FL4M3';
|
||||||
let browser;
|
let browser;
|
||||||
let page;
|
let page;
|
||||||
|
|
||||||
|
@ -26,10 +27,18 @@ describe('Travel thermograph path', () => {
|
||||||
await page.waitForState('travel.card.thermograph.create');
|
await page.waitForState('travel.card.thermograph.create');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should select the thermograph and then the file to upload', async() => {
|
it('should click on the add thermograph icon of the thermograph autocomplete', async() => {
|
||||||
|
await page.waitToClick(selectors.travelThermograph.addThermographIcon);
|
||||||
|
await page.write(selectors.travelThermograph.newThermographId, thermographName);
|
||||||
|
await page.autocompleteSearch(selectors.travelThermograph.newThermographModel, 'TEMPMATE');
|
||||||
|
await page.autocompleteSearch(selectors.travelThermograph.newThermographWarehouse, 'Warehouse Two');
|
||||||
|
await page.autocompleteSearch(selectors.travelThermograph.newThermographTemperature, 'WARM');
|
||||||
|
await page.waitToClick(selectors.travelThermograph.createThermographButton);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should select the file to upload', async() => {
|
||||||
let currentDir = process.cwd();
|
let currentDir = process.cwd();
|
||||||
let filePath = `${currentDir}/e2e/dms/ecc/3.jpeg`;
|
let filePath = `${currentDir}/e2e/dms/ecc/3.jpeg`;
|
||||||
await page.autocompleteSearch(selectors.travelThermograph.thermographID, '138350-0');
|
|
||||||
|
|
||||||
const [fileChooser] = await Promise.all([
|
const [fileChooser] = await Promise.all([
|
||||||
page.waitForFileChooser(),
|
page.waitForFileChooser(),
|
||||||
|
@ -38,11 +47,17 @@ describe('Travel thermograph path', () => {
|
||||||
await fileChooser.accept([filePath]);
|
await fileChooser.accept([filePath]);
|
||||||
|
|
||||||
await page.waitToClick(selectors.travelThermograph.upload);
|
await page.waitToClick(selectors.travelThermograph.upload);
|
||||||
|
|
||||||
|
const message = await page.waitForSnackbar();
|
||||||
|
const state = await page.getState();
|
||||||
|
|
||||||
|
expect(message.type).toBe('success');
|
||||||
|
expect(state).toBe('travel.card.thermograph.index');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should reload the section and check everything was saved', async() => {
|
it('should check everything was saved correctly', async() => {
|
||||||
let createdThermograph = await page.waitToGetProperty(selectors.travelThermograph.createdThermograph, 'innerText');
|
const result = await page.waitToGetProperty(selectors.travelThermograph.createdThermograph, 'innerText');
|
||||||
|
|
||||||
expect(createdThermograph).toContain('138350-0');
|
expect(result).toContain(thermographName);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
|
|
||||||
|
module.exports = Self => {
|
||||||
|
/**
|
||||||
|
* Returns a set of allowed values defined on table scheme
|
||||||
|
* @param {String} column - Model or Table column name
|
||||||
|
* @return {Array} - Array of set values
|
||||||
|
*/
|
||||||
|
Self.getEnumValues = async function(column) {
|
||||||
|
let model = this.app.models[this.modelName].definition;
|
||||||
|
let properties = model.properties;
|
||||||
|
let tableName = this.modelName;
|
||||||
|
let schema = null;
|
||||||
|
|
||||||
|
if (model.settings && model.settings.mysql) {
|
||||||
|
let tableSplit = model.settings.mysql.table.split('.');
|
||||||
|
tableName = tableSplit.pop();
|
||||||
|
schema = tableSplit.pop() || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let property = properties[column];
|
||||||
|
|
||||||
|
if (!property)
|
||||||
|
throw new UserError(`Column does not exist`);
|
||||||
|
|
||||||
|
let columnName = property.mysql
|
||||||
|
? property.mysql.columnName
|
||||||
|
: column;
|
||||||
|
|
||||||
|
let columnInfo = await this.rawSql(
|
||||||
|
`SELECT column_type columnType
|
||||||
|
FROM information_schema.columns
|
||||||
|
WHERE table_name = ?
|
||||||
|
AND table_schema = IFNULL(?, DATABASE())
|
||||||
|
AND column_name = ?`,
|
||||||
|
[tableName, schema, columnName]
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!columnInfo || !columnInfo[0])
|
||||||
|
throw new UserError(`Cannot fetch column values`);
|
||||||
|
|
||||||
|
let setValues;
|
||||||
|
setValues = columnInfo[0].columnType
|
||||||
|
.replace(/^enum\((.*)\)$/i, '$1')
|
||||||
|
.replace(/'/g, '')
|
||||||
|
.match(new RegExp(/(\w+)+/, 'ig'));
|
||||||
|
|
||||||
|
let values = [];
|
||||||
|
setValues.forEach(setValue => {
|
||||||
|
values.push({value: setValue});
|
||||||
|
});
|
||||||
|
|
||||||
|
return values;
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,18 @@
|
||||||
|
const app = require('vn-loopback/server/server');
|
||||||
|
|
||||||
|
describe('Model getEnumValues()', () => {
|
||||||
|
it('should extend getEnumValues properties to any model passed', () => {
|
||||||
|
let exampleModel = app.models.TravelThermograph;
|
||||||
|
|
||||||
|
expect(exampleModel.getEnumValues).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return an array of enum values from a given column', async() => {
|
||||||
|
let result = await app.models.TravelThermograph.getSetValues('temperature');
|
||||||
|
|
||||||
|
expect(result.length).toEqual(3);
|
||||||
|
expect(result[0].value).toEqual('enum');
|
||||||
|
expect(result[1].value).toEqual('COOL');
|
||||||
|
expect(result[2].value).toEqual('WARM');
|
||||||
|
});
|
||||||
|
});
|
|
@ -6,6 +6,7 @@ module.exports = function(Self) {
|
||||||
Self.ParameterizedSQL = ParameterizedSQL;
|
Self.ParameterizedSQL = ParameterizedSQL;
|
||||||
|
|
||||||
require('../methods/vn-model/getSetValues')(Self);
|
require('../methods/vn-model/getSetValues')(Self);
|
||||||
|
require('../methods/vn-model/getEnumValues')(Self);
|
||||||
|
|
||||||
Object.assign(Self, {
|
Object.assign(Self, {
|
||||||
setup() {
|
setup() {
|
||||||
|
|
|
@ -132,5 +132,5 @@
|
||||||
"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",
|
||||||
"AMOUNT_NOT_MATCH_GROUPING": "AMOUNT_NOT_MATCH_GROUPING"
|
"This thermograph id already exists": "La id del termógrafo ya existe"
|
||||||
}
|
}
|
|
@ -2,11 +2,11 @@
|
||||||
module="claim"
|
module="claim"
|
||||||
description="$ctrl.claim.client.name">
|
description="$ctrl.claim.client.name">
|
||||||
<slot-menu>
|
<slot-menu>
|
||||||
<a class="vn-item"
|
<vn-item
|
||||||
ui-sref="ticket.create({clientFk: $ctrl.client.id})"
|
ng-click="$ctrl.showPickupOrder()"
|
||||||
translate>
|
translate>
|
||||||
Show Pickup order
|
Show Pickup order
|
||||||
</a>
|
</vn-item>
|
||||||
<vn-item
|
<vn-item
|
||||||
ng-click="confirmPickupOrder.show()"
|
ng-click="confirmPickupOrder.show()"
|
||||||
translate>
|
translate>
|
||||||
|
|
|
@ -12,7 +12,7 @@ class Controller extends Descriptor {
|
||||||
|
|
||||||
showPickupOrder() {
|
showPickupOrder() {
|
||||||
this.showReport('claim-pickup-order', {
|
this.showReport('claim-pickup-order', {
|
||||||
clientId: this.claim.clientFk,
|
recipientId: this.claim.clientFk,
|
||||||
claimId: this.claim.id
|
claimId: this.claim.id
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ class Controller extends Descriptor {
|
||||||
sendPickupOrder() {
|
sendPickupOrder() {
|
||||||
return this.sendEmail('claim-pickup-order', {
|
return this.sendEmail('claim-pickup-order', {
|
||||||
recipient: this.claim.client.email,
|
recipient: this.claim.client.email,
|
||||||
clientId: this.claim.clientFk,
|
recipientId: this.claim.clientFk,
|
||||||
claimId: this.claim.id
|
claimId: this.claim.id
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ describe('Item Component vnClaimDescriptor', () => {
|
||||||
controller.showReport = jest.fn();
|
controller.showReport = jest.fn();
|
||||||
|
|
||||||
const params = {
|
const params = {
|
||||||
clientId: claim.clientFk,
|
recipientId: claim.clientFk,
|
||||||
claimId: claim.id
|
claimId: claim.id
|
||||||
};
|
};
|
||||||
controller.showPickupOrder();
|
controller.showPickupOrder();
|
||||||
|
@ -38,7 +38,7 @@ describe('Item Component vnClaimDescriptor', () => {
|
||||||
|
|
||||||
const params = {
|
const params = {
|
||||||
recipient: claim.client.email,
|
recipient: claim.client.email,
|
||||||
clientId: claim.clientFk,
|
recipientId: claim.clientFk,
|
||||||
claimId: claim.id
|
claimId: claim.id
|
||||||
};
|
};
|
||||||
controller.sendPickupOrder();
|
controller.sendPickupOrder();
|
||||||
|
|
|
@ -257,7 +257,7 @@ module.exports = Self => {
|
||||||
if (!instance.email) return;
|
if (!instance.email) return;
|
||||||
const params = {
|
const params = {
|
||||||
authorization: authorization,
|
authorization: authorization,
|
||||||
clientId: instance.id,
|
recipientId: instance.id,
|
||||||
recipient: instance.email
|
recipient: instance.email
|
||||||
};
|
};
|
||||||
await request.get(`${origin}/api/email/payment-update`, {
|
await request.get(`${origin}/api/email/payment-update`, {
|
||||||
|
|
|
@ -42,7 +42,7 @@ class Controller extends Descriptor {
|
||||||
|
|
||||||
onConsumerReportAccept() {
|
onConsumerReportAccept() {
|
||||||
this.showReport('campaign-metrics', {
|
this.showReport('campaign-metrics', {
|
||||||
clientId: this.id,
|
recipientId: this.id,
|
||||||
from: this.from,
|
from: this.from,
|
||||||
to: this.to,
|
to: this.to,
|
||||||
});
|
});
|
||||||
|
|
|
@ -61,7 +61,7 @@ class Controller extends Section {
|
||||||
send(isPreview, cb) {
|
send(isPreview, cb) {
|
||||||
const sampleType = this.$.sampleType.selection;
|
const sampleType = this.$.sampleType.selection;
|
||||||
const params = {
|
const params = {
|
||||||
clientId: this.$params.id,
|
recipientId: this.$params.id,
|
||||||
recipient: this.clientSample.recipient
|
recipient: this.clientSample.recipient
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ describe('Client', () => {
|
||||||
code: 'MyReport'
|
code: 'MyReport'
|
||||||
};
|
};
|
||||||
controller.clientSample = {
|
controller.clientSample = {
|
||||||
clientId: 101
|
recipientId: 101
|
||||||
};
|
};
|
||||||
|
|
||||||
controller.send(false, () => {});
|
controller.send(false, () => {});
|
||||||
|
@ -81,7 +81,7 @@ describe('Client', () => {
|
||||||
|
|
||||||
controller.$.sampleType.selection = null;
|
controller.$.sampleType.selection = null;
|
||||||
controller.clientSample = {
|
controller.clientSample = {
|
||||||
clientId: 101,
|
recipientId: 101,
|
||||||
recipient: 'client@email.com'
|
recipient: 'client@email.com'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@ describe('Client', () => {
|
||||||
code: 'MyReport'
|
code: 'MyReport'
|
||||||
};
|
};
|
||||||
controller.clientSample = {
|
controller.clientSample = {
|
||||||
clientId: 101,
|
recipientId: 101,
|
||||||
recipient: 'client@email.com'
|
recipient: 'client@email.com'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -113,11 +113,11 @@ describe('Client', () => {
|
||||||
code: 'MyReport'
|
code: 'MyReport'
|
||||||
};
|
};
|
||||||
controller.clientSample = {
|
controller.clientSample = {
|
||||||
clientId: 101,
|
recipientId: 101,
|
||||||
recipient: 'client@email.com'
|
recipient: 'client@email.com'
|
||||||
};
|
};
|
||||||
const expectedParams = {
|
const expectedParams = {
|
||||||
clientId: 101,
|
recipientId: 101,
|
||||||
recipient: 'client@email.com'
|
recipient: 'client@email.com'
|
||||||
};
|
};
|
||||||
const serializedParams = $httpParamSerializer(expectedParams);
|
const serializedParams = $httpParamSerializer(expectedParams);
|
||||||
|
@ -133,12 +133,12 @@ describe('Client', () => {
|
||||||
code: 'MyReport'
|
code: 'MyReport'
|
||||||
};
|
};
|
||||||
controller.clientSample = {
|
controller.clientSample = {
|
||||||
clientId: 101,
|
recipientId: 101,
|
||||||
recipient: 'client@email.com',
|
recipient: 'client@email.com',
|
||||||
companyFk: 442
|
companyFk: 442
|
||||||
};
|
};
|
||||||
const expectedParams = {
|
const expectedParams = {
|
||||||
clientId: 101,
|
recipientId: 101,
|
||||||
recipient: 'client@email.com',
|
recipient: 'client@email.com',
|
||||||
companyId: 442
|
companyId: 442
|
||||||
};
|
};
|
||||||
|
|
|
@ -37,7 +37,6 @@ class Controller extends Descriptor {
|
||||||
|
|
||||||
showEntryReport() {
|
showEntryReport() {
|
||||||
this.showReport('entry-order', {
|
this.showReport('entry-order', {
|
||||||
clientId: this.vnConfig.storage.currentUserWorkerId,
|
|
||||||
entryId: this.entry.id
|
entryId: this.entry.id
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ module.exports = Self => {
|
||||||
Self.getSummary = async id => {
|
Self.getSummary = async id => {
|
||||||
let promises = [];
|
let promises = [];
|
||||||
let summary = {};
|
let summary = {};
|
||||||
|
const models = Self.app.models;
|
||||||
|
|
||||||
// Item basic data and taxes
|
// Item basic data and taxes
|
||||||
let filter = {
|
let filter = {
|
||||||
|
@ -66,7 +67,7 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
promises.push(Self.app.models.Item.find(filter));
|
promises.push(models.Item.find(filter));
|
||||||
|
|
||||||
// Tags
|
// Tags
|
||||||
filter = {
|
filter = {
|
||||||
|
@ -78,21 +79,21 @@ module.exports = Self => {
|
||||||
relation: 'tag'
|
relation: 'tag'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
promises.push(Self.app.models.ItemTag.find(filter));
|
promises.push(models.ItemTag.find(filter));
|
||||||
|
|
||||||
// Botanical
|
// Botanical
|
||||||
filter = {
|
filter = {
|
||||||
where: {itemFk: id},
|
where: {itemFk: id},
|
||||||
include: [{relation: 'genus'}, {relation: 'specie'}]
|
include: [{relation: 'genus'}, {relation: 'specie'}]
|
||||||
};
|
};
|
||||||
promises.push(Self.app.models.ItemBotanical.find(filter));
|
promises.push(models.ItemBotanical.find(filter));
|
||||||
|
|
||||||
// Niches
|
// Niches
|
||||||
filter = {
|
filter = {
|
||||||
where: {itemFk: id},
|
where: {itemFk: id},
|
||||||
include: {relation: 'warehouse'}
|
include: {relation: 'warehouse'}
|
||||||
};
|
};
|
||||||
promises.push(Self.app.models.ItemNiche.find(filter));
|
promises.push(models.ItemNiche.find(filter));
|
||||||
|
|
||||||
let res = await Promise.all(promises);
|
let res = await Promise.all(promises);
|
||||||
|
|
||||||
|
@ -101,15 +102,10 @@ module.exports = Self => {
|
||||||
[summary.botanical] = res[2];
|
[summary.botanical] = res[2];
|
||||||
summary.niches = res[3];
|
summary.niches = res[3];
|
||||||
|
|
||||||
// Visible Avaible
|
res = await models.Item.getVisibleAvailable(summary.item.id, summary.item.itemType().warehouseFk);
|
||||||
let query = `
|
|
||||||
CALL vn.item_getVisibleAvailable(?,curdate(),?,?)`;
|
|
||||||
|
|
||||||
let options = [summary.item.id, summary.item.itemType().warehouseFk, false];
|
summary.available = res.available;
|
||||||
[res] = await Self.rawSql(query, options);
|
summary.visible = res.visible;
|
||||||
|
|
||||||
summary.available = res[0].available ? res[0].available : '-';
|
|
||||||
summary.visible = res[0].visible ? res[0].visible : '-';
|
|
||||||
return summary;
|
return summary;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethod('getVisibleAvailable', {
|
Self.remoteMethod('getVisibleAvailable', {
|
||||||
description: 'Returns visible and available for params',
|
description: 'Returns visible and available for params',
|
||||||
|
@ -11,6 +12,11 @@ module.exports = Self => {
|
||||||
arg: 'warehouseFk',
|
arg: 'warehouseFk',
|
||||||
type: 'Number',
|
type: 'Number',
|
||||||
required: true,
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'dated',
|
||||||
|
type: 'Date',
|
||||||
|
required: false,
|
||||||
}],
|
}],
|
||||||
returns: {
|
returns: {
|
||||||
type: ['object'],
|
type: ['object'],
|
||||||
|
@ -22,15 +28,35 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.getVisibleAvailable = async(id, warehouseFk) => {
|
Self.getVisibleAvailable = async(id, warehouseFk, dated = new Date()) => {
|
||||||
let query = `
|
let stmts = [];
|
||||||
CALL vn.item_getVisibleAvailable(?,curdate(),?,?)`;
|
|
||||||
|
|
||||||
let options = [id, warehouseFk, false];
|
stmts.push(new ParameterizedSQL(
|
||||||
[res] = await Self.rawSql(query, options);
|
'CALL cache.available_refresh(@availableCalc, FALSE, ?, ?)', [
|
||||||
|
warehouseFk,
|
||||||
|
dated
|
||||||
|
]
|
||||||
|
));
|
||||||
|
stmts.push(new ParameterizedSQL(
|
||||||
|
'CALL cache.visible_refresh(@visibleCalc, FALSE,?)', [
|
||||||
|
warehouseFk
|
||||||
|
]
|
||||||
|
));
|
||||||
|
const visibleIndex = stmts.push(new ParameterizedSQL(
|
||||||
|
'SELECT visible FROM cache.visible WHERE calc_id = @visibleCalc AND item_id = ?', [
|
||||||
|
id
|
||||||
|
]
|
||||||
|
)) - 1;
|
||||||
|
const availableIndex = stmts.push(new ParameterizedSQL(
|
||||||
|
'SELECT available FROM cache.available WHERE calc_id = @availableCalc AND item_id = ?', [
|
||||||
|
id
|
||||||
|
]
|
||||||
|
)) - 1;
|
||||||
|
const sql = ParameterizedSQL.join(stmts, ';');
|
||||||
|
let res = await Self.rawStmt(sql);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
available: res[0].available,
|
available: res[availableIndex][0] ? res[availableIndex][0].available : 0,
|
||||||
visible: res[0].visible};
|
visible: res[visibleIndex][0] ? res[visibleIndex][0].visible : 0};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -61,13 +61,9 @@ module.exports = Self => {
|
||||||
}, options);
|
}, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
let query = `
|
res = await models.Item.getVisibleAvailable(itemFk, warehouseFk);
|
||||||
CALL vn.item_getVisibleAvailable(?,curdate(),?,?)`;
|
|
||||||
|
|
||||||
let params = [itemFk, warehouseFk, true];
|
let newQuantity = res.visible - quantity;
|
||||||
let [res] = await Self.rawSql(query, params, options);
|
|
||||||
|
|
||||||
let newQuantity = res[0].visible - quantity;
|
|
||||||
|
|
||||||
await models.Sale.create({
|
await models.Sale.create({
|
||||||
ticketFk: ticketFk,
|
ticketFk: ticketFk,
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
const app = require('vn-loopback/server/server');
|
||||||
|
|
||||||
|
describe('item getVisibleAvailable()', () => {
|
||||||
|
it('should check available visible for today', async() => {
|
||||||
|
const itemFk = 1;
|
||||||
|
const warehouseFk = 1;
|
||||||
|
const dated = new Date();
|
||||||
|
let result = await app.models.Item.getVisibleAvailable(itemFk, warehouseFk, dated);
|
||||||
|
|
||||||
|
expect(result.available).toEqual(187);
|
||||||
|
expect(result.visible).toEqual(92);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should check available visible for no dated', async() => {
|
||||||
|
const itemFk = 1;
|
||||||
|
const warehouseFk = 1;
|
||||||
|
let result = await app.models.Item.getVisibleAvailable(itemFk, warehouseFk);
|
||||||
|
|
||||||
|
expect(result.available).toEqual(187);
|
||||||
|
expect(result.visible).toEqual(92);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should check available visible for yesterday', async() => {
|
||||||
|
const itemFk = 1;
|
||||||
|
const warehouseFk = 1;
|
||||||
|
let dated = new Date();
|
||||||
|
dated.setDate(dated.getDate() - 1);
|
||||||
|
let result = await app.models.Item.getVisibleAvailable(itemFk, warehouseFk, dated);
|
||||||
|
|
||||||
|
expect(result.available).toEqual(0);
|
||||||
|
expect(result.visible).toEqual(92);
|
||||||
|
});
|
||||||
|
});
|
|
@ -14,13 +14,8 @@ describe('regularize()', () => {
|
||||||
|
|
||||||
it('should create a new ticket and add a line', async() => {
|
it('should create a new ticket and add a line', async() => {
|
||||||
let ctx = {req: {accessToken: {userId: 18}}};
|
let ctx = {req: {accessToken: {userId: 18}}};
|
||||||
|
let res = await app.models.Item.getVisibleAvailable(itemFk, warehouseFk);
|
||||||
let query = `CALL vn.item_getVisibleAvailable(?,curdate(),?,?)`;
|
let visible = res.visible;
|
||||||
|
|
||||||
let options = [itemFk, warehouseFk, true];
|
|
||||||
|
|
||||||
let [res] = await app.models.Item.rawSql(query, options);
|
|
||||||
let visible = res[0].visible;
|
|
||||||
let saleQuantity = visible - 11;
|
let saleQuantity = visible - 11;
|
||||||
|
|
||||||
let ticketFk = await app.models.Item.regularize(ctx, itemFk, 11, warehouseFk);
|
let ticketFk = await app.models.Item.regularize(ctx, itemFk, 11, warehouseFk);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<slot-descriptor>
|
<slot-descriptor>
|
||||||
<vn-item-descriptor warehouse-fk="$ctrl.warehouseFk">
|
<vn-item-descriptor warehouse-fk="$ctrl.warehouseFk" dated="$ctrl.dated">
|
||||||
<btn-three>
|
<btn-three>
|
||||||
<vn-quick-link
|
<vn-quick-link
|
||||||
tooltip="Item diary"
|
tooltip="Item diary"
|
||||||
|
|
|
@ -2,14 +2,16 @@ import ngModule from '../module';
|
||||||
import DescriptorPopover from 'salix/components/descriptor-popover';
|
import DescriptorPopover from 'salix/components/descriptor-popover';
|
||||||
|
|
||||||
class Controller extends DescriptorPopover {
|
class Controller extends DescriptorPopover {
|
||||||
show(parent, id, lineFk) {
|
show(parent, id, lineFk, dated) {
|
||||||
super.show(parent, id);
|
super.show(parent, id);
|
||||||
this.lineFk = lineFk;
|
this.lineFk = lineFk;
|
||||||
|
this.dated = dated;
|
||||||
}
|
}
|
||||||
|
|
||||||
hide() {
|
hide() {
|
||||||
super.hide();
|
super.hide();
|
||||||
this.lineFk = null;
|
this.lineFk = null;
|
||||||
|
this.dated = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +20,7 @@ ngModule.vnComponent('vnItemDescriptorPopover', {
|
||||||
controller: Controller,
|
controller: Controller,
|
||||||
bindings: {
|
bindings: {
|
||||||
warehouseFk: '<?',
|
warehouseFk: '<?',
|
||||||
lineFk: '<?'
|
lineFk: '<?',
|
||||||
|
dated: '<?'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -31,7 +31,8 @@ class Controller extends Descriptor {
|
||||||
if (!this.item) return;
|
if (!this.item) return;
|
||||||
|
|
||||||
const params = {
|
const params = {
|
||||||
warehouseFk: this.item.itemType.warehouseFk
|
warehouseFk: this.item.itemType.warehouseFk,
|
||||||
|
dated: this.dated
|
||||||
};
|
};
|
||||||
|
|
||||||
return this.$http.get(`Items/${this.id}/getVisibleAvailable`, {params})
|
return this.$http.get(`Items/${this.id}/getVisibleAvailable`, {params})
|
||||||
|
@ -65,6 +66,7 @@ ngModule.vnComponent('vnItemDescriptor', {
|
||||||
template: require('./index.html'),
|
template: require('./index.html'),
|
||||||
controller: Controller,
|
controller: Controller,
|
||||||
bindings: {
|
bindings: {
|
||||||
item: '<'
|
item: '<',
|
||||||
|
dated: '<'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -33,4 +33,14 @@ describe('vnItemDescriptor', () => {
|
||||||
expect(controller.item).toEqual(item);
|
expect(controller.item).toEqual(item);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('updateStock()', () => {
|
||||||
|
it(`should perform a get query to store the item data into the controller`, () => {
|
||||||
|
$httpBackend.expectGET(`Items/${item.id}/getCard`).respond(item);
|
||||||
|
controller.id = item.id;
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.item).toEqual(item);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -12,7 +12,7 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.getSourceValues = async () => {
|
Self.getSourceValues = async() => {
|
||||||
return Self.getSetValues('sourceApp');
|
return Self.getSetValues('sourceApp');
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,19 +12,16 @@ class Controller extends Descriptor {
|
||||||
|
|
||||||
showRouteReport() {
|
showRouteReport() {
|
||||||
this.showReport('driver-route', {
|
this.showReport('driver-route', {
|
||||||
clientId: this.vnConfig.storage.currentUserWorkerId,
|
|
||||||
routeId: this.id
|
routeId: this.id
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
sendRouteReport() {
|
sendRouteReport() {
|
||||||
const params = {
|
const workerUser = this.route.worker.user;
|
||||||
recipient: user.emailUser.email,
|
this.sendEmail('driver-route', {
|
||||||
clientId: this.vnConfig.storage.currentUserWorkerId,
|
recipient: workerUser.emailUser.email,
|
||||||
routeId: this.id
|
routeId: this.id
|
||||||
};
|
});
|
||||||
return this.$http.get(`email/driver-route`, {params})
|
|
||||||
.then(() => this.vnApp.showSuccess(this.$t('Report sent')));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateVolume() {
|
updateVolume() {
|
||||||
|
|
|
@ -47,14 +47,9 @@ module.exports = Self => {
|
||||||
include: {relation: 'ticket'}
|
include: {relation: 'ticket'}
|
||||||
}, options);
|
}, options);
|
||||||
|
|
||||||
let [[stock]] = await Self.rawSql(`CALL vn.item_getVisibleAvailable(?,?,?,?)`, [
|
const res = await models.Item.getVisibleAvailable(ctx.args.itemFk, request.ticket().warehouseFk, request.ticket().shipped);
|
||||||
ctx.args.itemFk,
|
|
||||||
request.ticket().shipped,
|
|
||||||
request.ticket().warehouseFk,
|
|
||||||
false
|
|
||||||
], options);
|
|
||||||
|
|
||||||
if (stock.available < 0)
|
if (res.available < 0)
|
||||||
throw new UserError(`This item is not available`);
|
throw new UserError(`This item is not available`);
|
||||||
|
|
||||||
if (request.saleFk) {
|
if (request.saleFk) {
|
||||||
|
|
|
@ -42,15 +42,9 @@ module.exports = Self => {
|
||||||
const item = await models.Item.findById(itemId);
|
const item = await models.Item.findById(itemId);
|
||||||
const ticket = await models.Ticket.findById(id);
|
const ticket = await models.Ticket.findById(id);
|
||||||
|
|
||||||
const shouldRefresh = false;
|
const res = await models.Item.getVisibleAvailable(itemId, ticket.warehouseFk, ticket.shipped);
|
||||||
const [[stock]] = await Self.rawSql(`CALL vn.item_getVisibleAvailable(?, ?, ?, ?)`, [
|
|
||||||
itemId,
|
|
||||||
ticket.shipped,
|
|
||||||
ticket.warehouseFk,
|
|
||||||
shouldRefresh
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (stock.available < quantity)
|
if (res.available < quantity)
|
||||||
throw new UserError(`This item is not available`);
|
throw new UserError(`This item is not available`);
|
||||||
|
|
||||||
const newSale = await models.Sale.create({
|
const newSale = await models.Sale.create({
|
||||||
|
|
|
@ -102,15 +102,15 @@ class Controller extends Descriptor {
|
||||||
|
|
||||||
showDeliveryNote() {
|
showDeliveryNote() {
|
||||||
this.showReport('delivery-note', {
|
this.showReport('delivery-note', {
|
||||||
clientId: this.ticket.client.id,
|
recipientId: this.ticket.client.id,
|
||||||
ticketId: this.id,
|
ticketId: this.id,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
sendDeliveryNote() {
|
sendDeliveryNote() {
|
||||||
return this.sendEmail('delivery-note', {
|
return this.sendEmail('delivery-note', {
|
||||||
|
recipientId: this.ticket.client.id,
|
||||||
recipient: this.ticket.client.email,
|
recipient: this.ticket.client.email,
|
||||||
clientId: this.ticket.client.id,
|
|
||||||
ticketId: this.id
|
ticketId: this.id
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,7 +121,7 @@
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td number shrink>
|
<vn-td number shrink>
|
||||||
<span
|
<span
|
||||||
ng-click="descriptor.show($event, sale.itemFk, sale.id)"
|
ng-click="descriptor.show($event, sale.itemFk, sale.id, $ctrl.ticket.shipped)"
|
||||||
class="link">
|
class="link">
|
||||||
{{sale.itemFk | zeroFill:6}}
|
{{sale.itemFk | zeroFill:6}}
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethod('createThermograph', {
|
||||||
|
description: 'Creates a new thermograph',
|
||||||
|
accessType: 'WRITE',
|
||||||
|
accepts: [{
|
||||||
|
arg: 'thermographId',
|
||||||
|
type: 'String',
|
||||||
|
description: 'The thermograph id',
|
||||||
|
required: true
|
||||||
|
}, {
|
||||||
|
arg: 'model',
|
||||||
|
type: 'String',
|
||||||
|
description: 'The thermograph model',
|
||||||
|
required: true
|
||||||
|
}, {
|
||||||
|
arg: 'temperature',
|
||||||
|
type: 'String',
|
||||||
|
description: 'The thermograph temperature',
|
||||||
|
required: true
|
||||||
|
}, {
|
||||||
|
arg: 'warehouseId',
|
||||||
|
type: 'Number',
|
||||||
|
description: 'The warehouse id',
|
||||||
|
required: true
|
||||||
|
}],
|
||||||
|
returns: {
|
||||||
|
type: 'Object',
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/createThermograph`,
|
||||||
|
verb: 'POST'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.createThermograph = async(thermographId, model, temperature, warehouseId) => {
|
||||||
|
const models = Self.app.models;
|
||||||
|
const tx = await Self.beginTransaction({});
|
||||||
|
|
||||||
|
try {
|
||||||
|
const options = {transaction: tx};
|
||||||
|
const thermograph = await models.Thermograph.create({
|
||||||
|
id: thermographId,
|
||||||
|
model: model
|
||||||
|
}, options);
|
||||||
|
|
||||||
|
await Self.rawSql(`
|
||||||
|
INSERT INTO travelThermograph(thermographFk, warehouseFk, temperature, created)
|
||||||
|
VALUES (?, ?,?, NOW())
|
||||||
|
`, [thermograph.id, warehouseId, temperature], options);
|
||||||
|
|
||||||
|
await tx.commit();
|
||||||
|
|
||||||
|
return thermograph;
|
||||||
|
} catch (err) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,18 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethod('getThermographModels', {
|
||||||
|
description: 'Gets the thermograph models',
|
||||||
|
accessType: 'READ',
|
||||||
|
returns: {
|
||||||
|
type: ['String'],
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/getThermographModels`,
|
||||||
|
verb: 'GET'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.getThermographModels = async() => {
|
||||||
|
return Self.getEnumValues('model');
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,49 @@
|
||||||
|
const app = require('vn-loopback/server/server');
|
||||||
|
|
||||||
|
describe('Termograph createThermograph()', () => {
|
||||||
|
const models = app.models;
|
||||||
|
const thermographId = '99999-1';
|
||||||
|
const model = 'DISPOSABLE';
|
||||||
|
const temperature = 'COOL';
|
||||||
|
const warehouseId = 1;
|
||||||
|
let createdThermograph;
|
||||||
|
|
||||||
|
afterAll(async done => {
|
||||||
|
let travelThermograpToDelete = await models.TravelThermograph.findOne({where: {thermographFk: createdThermograph.id}});
|
||||||
|
let thermograpToDelete = await models.Thermograph.findById(createdThermograph.id);
|
||||||
|
|
||||||
|
await travelThermograpToDelete.destroy();
|
||||||
|
await thermograpToDelete.destroy();
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should create a thermograph which is saved in both thermograph and travelThermograph`, async() => {
|
||||||
|
let createdTravelThermograpth = await models.TravelThermograph.findOne({where: {thermographFk: thermographId}});
|
||||||
|
|
||||||
|
expect(createdTravelThermograpth).toBeNull();
|
||||||
|
|
||||||
|
createdThermograph = await models.Thermograph.createThermograph(thermographId, model, temperature, warehouseId);
|
||||||
|
|
||||||
|
expect(createdThermograph.id).toEqual(thermographId);
|
||||||
|
expect(createdThermograph.model).toEqual(model);
|
||||||
|
|
||||||
|
createdTravelThermograpth = await models.TravelThermograph.findOne({where: {thermographFk: thermographId}});
|
||||||
|
|
||||||
|
expect(createdTravelThermograpth.warehouseFk).toEqual(warehouseId);
|
||||||
|
expect(createdTravelThermograpth.temperature).toEqual(temperature);
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should not be able to created duplicated entries`, async() => {
|
||||||
|
let error;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await models.Thermograph.createThermograph(thermographId, model, temperature, warehouseId);
|
||||||
|
} catch (e) {
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(error).toBeDefined();
|
||||||
|
expect(error.message).toBe('This thermograph id already exists');
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,18 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethod('getThermographTemperatures', {
|
||||||
|
description: 'Gets the thermograph temperatures',
|
||||||
|
accessType: 'READ',
|
||||||
|
returns: {
|
||||||
|
type: ['String'],
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/getThermographTemperatures`,
|
||||||
|
verb: 'GET'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.getThermographTemperatures = async() => {
|
||||||
|
return Self.getEnumValues('temperature');
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,12 @@
|
||||||
|
let UserError = require('vn-loopback/util/user-error');
|
||||||
|
|
||||||
|
module.exports = Self => {
|
||||||
|
require('../methods/thermograph/createThermograph')(Self);
|
||||||
|
require('../methods/thermograph/getThermographModels')(Self);
|
||||||
|
|
||||||
|
Self.rewriteDbError(function(err) {
|
||||||
|
if (err.code === 'ER_DUP_ENTRY')
|
||||||
|
return new UserError(`This thermograph id already exists`);
|
||||||
|
return err;
|
||||||
|
});
|
||||||
|
};
|
|
@ -10,10 +10,12 @@
|
||||||
"id": {
|
"id": {
|
||||||
"type": "String",
|
"type": "String",
|
||||||
"id": true,
|
"id": true,
|
||||||
"description": "Identifier"
|
"description": "Identifier",
|
||||||
|
"required": true
|
||||||
},
|
},
|
||||||
"model": {
|
"model": {
|
||||||
"type": "String"
|
"type": "String",
|
||||||
|
"required": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
require('../methods/travel-thermograph/allowedContentTypes')(Self);
|
require('../methods/travel-thermograph/allowedContentTypes')(Self);
|
||||||
|
require('../methods/travel-thermograph/getThermographTemperatures')(Self);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -21,10 +21,15 @@
|
||||||
"type": "Date"
|
"type": "Date"
|
||||||
},
|
},
|
||||||
"temperature": {
|
"temperature": {
|
||||||
"type": "String"
|
"type": "String",
|
||||||
|
"required": true
|
||||||
},
|
},
|
||||||
"result": {
|
"result": {
|
||||||
"type": "String"
|
"type": "String"
|
||||||
|
},
|
||||||
|
"warehouseFk": {
|
||||||
|
"type": "Number",
|
||||||
|
"required": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"relations": {
|
"relations": {
|
||||||
|
|
|
@ -17,6 +17,18 @@
|
||||||
where="{travelFk: null}"
|
where="{travelFk: null}"
|
||||||
show-field="thermographFk"
|
show-field="thermographFk"
|
||||||
value-field="thermographFk">
|
value-field="thermographFk">
|
||||||
|
<tpl-item>
|
||||||
|
{{thermographFk}}
|
||||||
|
</tpl-item>
|
||||||
|
<append>
|
||||||
|
<vn-icon-button
|
||||||
|
icon="add_circle"
|
||||||
|
vn-tooltip="New thermograph"
|
||||||
|
ng-click="$ctrl.onAddThermographClick($event)"
|
||||||
|
vn-acl="buyer"
|
||||||
|
vn-acl-action="remove">
|
||||||
|
</vn-icon-button>
|
||||||
|
</append>
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
<vn-textfield vn-one
|
<vn-textfield vn-one
|
||||||
label="State"
|
label="State"
|
||||||
|
@ -84,3 +96,63 @@
|
||||||
</vn-button-bar>
|
</vn-button-bar>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
<!-- Create thermograph dialog -->
|
||||||
|
<vn-crud-model
|
||||||
|
vn-id="modelsModel"
|
||||||
|
url="Thermographs/getThermographModels"
|
||||||
|
data="thermographModels">
|
||||||
|
</vn-crud-model>
|
||||||
|
<vn-crud-model
|
||||||
|
vn-id="temperaturesModel"
|
||||||
|
url="TravelThermographs/getThermographTemperatures"
|
||||||
|
data="thermographTemperatures">
|
||||||
|
</vn-crud-model>
|
||||||
|
<vn-dialog class="edit"
|
||||||
|
vn-id="newThermographDialog"
|
||||||
|
on-accept="$ctrl.onNewThermographAccept()"
|
||||||
|
message="New thermograph">
|
||||||
|
<tpl-body>
|
||||||
|
<vn-horizontal>
|
||||||
|
<vn-textfield
|
||||||
|
vn-one
|
||||||
|
required="true"
|
||||||
|
label="Identifier"
|
||||||
|
ng-model="$ctrl.newThermograph.thermographId"
|
||||||
|
vn-focus>
|
||||||
|
</vn-textfield>
|
||||||
|
<vn-autocomplete
|
||||||
|
vn-one
|
||||||
|
required="true"
|
||||||
|
label="Model"
|
||||||
|
ng-model="$ctrl.newThermograph.model"
|
||||||
|
data="thermographModels"
|
||||||
|
show-field="value"
|
||||||
|
value-field="value">
|
||||||
|
</vn-autocomplete>
|
||||||
|
</vn-horizontal>
|
||||||
|
<vn-horizontal>
|
||||||
|
<vn-autocomplete
|
||||||
|
vn-one
|
||||||
|
required="true"
|
||||||
|
label="Warehouse"
|
||||||
|
ng-model="$ctrl.newThermograph.warehouseId"
|
||||||
|
url="Warehouses"
|
||||||
|
show-field="name"
|
||||||
|
value-field="id">
|
||||||
|
</vn-autocomplete>
|
||||||
|
<vn-autocomplete
|
||||||
|
vn-one
|
||||||
|
required="true"
|
||||||
|
label="Temperature"
|
||||||
|
ng-model="$ctrl.newThermograph.temperature"
|
||||||
|
data="thermographTemperatures"
|
||||||
|
show-field="value"
|
||||||
|
value-field="value">
|
||||||
|
</vn-autocomplete>
|
||||||
|
</vn-horizontal>
|
||||||
|
</tpl-body>
|
||||||
|
<tpl-buttons>
|
||||||
|
<input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
|
||||||
|
<button response="accept" translate>Create</button>
|
||||||
|
</tpl-buttons>
|
||||||
|
</vn-dialog>
|
|
@ -55,6 +55,28 @@ class Controller extends Section {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onAddThermographClick(event) {
|
||||||
|
const defaultTemperature = 'COOL';
|
||||||
|
const defaultModel = 'DISPOSABLE';
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
this.newThermograph = {
|
||||||
|
thermographId: this.thermographId,
|
||||||
|
warehouseId: this.warehouseId,
|
||||||
|
temperature: defaultTemperature,
|
||||||
|
model: defaultModel
|
||||||
|
};
|
||||||
|
|
||||||
|
this.$.modelsModel.refresh();
|
||||||
|
this.$.temperaturesModel.refresh();
|
||||||
|
this.$.newThermographDialog.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
onNewThermographAccept() {
|
||||||
|
return this.$http.post(`Thermographs/createThermograph`, this.newThermograph)
|
||||||
|
.then(res => this.dms.thermographId = res.data.id);
|
||||||
|
}
|
||||||
|
|
||||||
onSubmit() {
|
onSubmit() {
|
||||||
const query = `Travels/${this.travel.id}/createThermograph`;
|
const query = `Travels/${this.travel.id}/createThermograph`;
|
||||||
const options = {
|
const options = {
|
||||||
|
|
|
@ -63,5 +63,32 @@ describe('Ticket', () => {
|
||||||
expect(controller.allowedContentTypes).toEqual('application/pdf, image/png, image/jpg');
|
expect(controller.allowedContentTypes).toEqual('application/pdf, image/png, image/jpg');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('onAddThermographClick()', () => {
|
||||||
|
it('should call the show() function of the create thermograph dialog', () => {
|
||||||
|
controller.$.newThermographDialog = {show: jest.fn()};
|
||||||
|
controller.$.modelsModel = {refresh: jest.fn()};
|
||||||
|
controller.$.temperaturesModel = {refresh: jest.fn()};
|
||||||
|
|
||||||
|
const event = new Event('click');
|
||||||
|
jest.spyOn(event, 'preventDefault');
|
||||||
|
|
||||||
|
controller.onAddThermographClick(event);
|
||||||
|
|
||||||
|
expect(event.preventDefault).toHaveBeenCalledTimes(1);
|
||||||
|
expect(controller.$.newThermographDialog.show).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('onNewThermographAccept()', () => {
|
||||||
|
it('should set the created thermograph id on to the controller for the autocomplete to use it', () => {
|
||||||
|
const response = {id: 'the created id'};
|
||||||
|
$httpBackend.when('POST', `Thermographs/createThermograph`).respond(response);
|
||||||
|
controller.onNewThermographAccept();
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.dms.thermographId).toEqual(response.id);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -15,4 +15,6 @@ Add thermograph: Añadir termógrafo
|
||||||
Edit thermograph: Editar termógrafo
|
Edit thermograph: Editar termógrafo
|
||||||
Thermograph deleted: Termógrafo eliminado
|
Thermograph deleted: Termógrafo eliminado
|
||||||
Thermograph: Termógrafo
|
Thermograph: Termógrafo
|
||||||
Are you sure you want to remove the thermograph?: ¿Seguro que quieres quitar el termógrafo?
|
New thermograph: Nuevo termógrafo
|
||||||
|
Are you sure you want to remove the thermograph?: ¿Seguro que quieres quitar el termógrafo?
|
||||||
|
Identifier: Identificador
|
|
@ -61,8 +61,8 @@ describe('Zone Component vnZoneDeliveryDays', () => {
|
||||||
expect(controller.$.data).toEqual(expectedData);
|
expect(controller.$.data).toEqual(expectedData);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
// Petición #2259 cread
|
|
||||||
xdescribe('onSelection()', () => {
|
describe('onSelection()', () => {
|
||||||
it('should not call the show popover method if events array is empty', () => {
|
it('should not call the show popover method if events array is empty', () => {
|
||||||
jest.spyOn(controller.$.zoneEvents, 'show');
|
jest.spyOn(controller.$.zoneEvents, 'show');
|
||||||
|
|
||||||
|
|
|
@ -3244,7 +3244,7 @@
|
||||||
},
|
},
|
||||||
"util": {
|
"util": {
|
||||||
"version": "0.10.3",
|
"version": "0.10.3",
|
||||||
"resolved": "http://registry.npmjs.org/util/-/util-0.10.3.tgz",
|
"resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
|
||||||
"integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
|
"integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -4060,7 +4060,7 @@
|
||||||
"base": {
|
"base": {
|
||||||
"version": "0.11.2",
|
"version": "0.11.2",
|
||||||
"resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
|
"resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
|
||||||
"integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
|
"integrity": "sha1-e95c7RRbbVUakNuH+DxVi060io8=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"cache-base": "^1.0.1",
|
"cache-base": "^1.0.1",
|
||||||
|
@ -4577,7 +4577,7 @@
|
||||||
"cache-base": {
|
"cache-base": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
|
||||||
"integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==",
|
"integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"collection-visit": "^1.0.0",
|
"collection-visit": "^1.0.0",
|
||||||
|
@ -4754,7 +4754,7 @@
|
||||||
"class-utils": {
|
"class-utils": {
|
||||||
"version": "0.3.6",
|
"version": "0.3.6",
|
||||||
"resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
|
"resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
|
||||||
"integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==",
|
"integrity": "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"arr-union": "^3.1.0",
|
"arr-union": "^3.1.0",
|
||||||
|
@ -5816,7 +5816,7 @@
|
||||||
"dot-prop": {
|
"dot-prop": {
|
||||||
"version": "4.2.0",
|
"version": "4.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz",
|
||||||
"integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==",
|
"integrity": "sha1-HxngwuGqDjJ5fEl5nyg3rGr2nFc=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"is-obj": "^1.0.0"
|
"is-obj": "^1.0.0"
|
||||||
}
|
}
|
||||||
|
@ -6751,7 +6751,7 @@
|
||||||
},
|
},
|
||||||
"file-loader": {
|
"file-loader": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"resolved": "http://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz",
|
||||||
"integrity": "sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg==",
|
"integrity": "sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -7918,7 +7918,7 @@
|
||||||
"global-modules": {
|
"global-modules": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz",
|
||||||
"integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==",
|
"integrity": "sha1-bXcPDrUjrHgWTXK15xqIdyZcw+o=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"global-prefix": "^1.0.1",
|
"global-prefix": "^1.0.1",
|
||||||
|
@ -8500,7 +8500,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"es6-promise": {
|
"es6-promise": {
|
||||||
"version": "3.3.1",
|
"version": "3.3.1",
|
||||||
"resolved": "http://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz",
|
||||||
"integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=",
|
"integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
@ -9579,7 +9579,7 @@
|
||||||
"is-plain-object": {
|
"is-plain-object": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
|
||||||
"integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
|
"integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"isobject": "^3.0.1"
|
"isobject": "^3.0.1"
|
||||||
|
@ -9935,7 +9935,7 @@
|
||||||
"jasmine-spec-reporter": {
|
"jasmine-spec-reporter": {
|
||||||
"version": "4.2.1",
|
"version": "4.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-4.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-4.2.1.tgz",
|
||||||
"integrity": "sha512-FZBoZu7VE5nR7Nilzy+Np8KuVIOxF4oXDPDknehCYBDE080EnlPu0afdZNmpGDBRCUBv3mj5qgqCRmk6W/K8vg==",
|
"integrity": "sha1-HWMq7ANBZwrTJPkrqEtLMrNeniI=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"colors": "1.1.2"
|
"colors": "1.1.2"
|
||||||
|
@ -11932,7 +11932,7 @@
|
||||||
},
|
},
|
||||||
"minimist": {
|
"minimist": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
||||||
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
|
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
|
||||||
},
|
},
|
||||||
"mississippi": {
|
"mississippi": {
|
||||||
|
@ -12972,7 +12972,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"minimist": {
|
"minimist": {
|
||||||
"version": "0.0.10",
|
"version": "0.0.10",
|
||||||
"resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
|
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
|
||||||
"integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=",
|
"integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
@ -14180,7 +14180,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"jsesc": {
|
"jsesc": {
|
||||||
"version": "0.5.0",
|
"version": "0.5.0",
|
||||||
"resolved": "http://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
|
||||||
"integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=",
|
"integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=",
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
|
@ -14558,7 +14558,7 @@
|
||||||
},
|
},
|
||||||
"safe-regex": {
|
"safe-regex": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
|
||||||
"integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
|
"integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -14648,7 +14648,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"source-map": {
|
"source-map": {
|
||||||
"version": "0.4.4",
|
"version": "0.4.4",
|
||||||
"resolved": "http://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
|
||||||
"integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
|
"integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -15006,7 +15006,7 @@
|
||||||
"snapdragon-node": {
|
"snapdragon-node": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz",
|
||||||
"integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==",
|
"integrity": "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"define-property": "^1.0.0",
|
"define-property": "^1.0.0",
|
||||||
|
@ -15057,7 +15057,7 @@
|
||||||
"snapdragon-util": {
|
"snapdragon-util": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
|
||||||
"integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==",
|
"integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"kind-of": "^3.2.0"
|
"kind-of": "^3.2.0"
|
||||||
|
@ -15332,7 +15332,7 @@
|
||||||
"split-string": {
|
"split-string": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
|
||||||
"integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==",
|
"integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"extend-shallow": "^3.0.0"
|
"extend-shallow": "^3.0.0"
|
||||||
|
@ -16409,7 +16409,7 @@
|
||||||
"touch": {
|
"touch": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
|
||||||
"integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==",
|
"integrity": "sha1-/jZfX3XsntTlaCXgu3bSSrdK+Ds=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"nopt": "~1.0.10"
|
"nopt": "~1.0.10"
|
||||||
|
|
|
@ -87,17 +87,29 @@ class Component {
|
||||||
return component;
|
return component;
|
||||||
}
|
}
|
||||||
|
|
||||||
async render() {
|
component() {
|
||||||
|
if (this._component)
|
||||||
|
return this._component;
|
||||||
|
|
||||||
const component = this.build();
|
const component = this.build();
|
||||||
const i18n = new VueI18n(config.i18n);
|
const i18n = new VueI18n(config.i18n);
|
||||||
const app = new Vue({
|
this._component = new Vue({
|
||||||
i18n: i18n,
|
i18n: i18n,
|
||||||
render: h => h(component, {
|
render: h => h(component, {
|
||||||
props: this.args
|
props: this.args
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
return renderer.renderToString(app);
|
return this._component;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {Promise} Rendered component
|
||||||
|
*/
|
||||||
|
async render() {
|
||||||
|
return renderer.renderToString(
|
||||||
|
this.component()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,9 +15,10 @@ module.exports = {
|
||||||
const props = this.args;
|
const props = this.args;
|
||||||
let query = '';
|
let query = '';
|
||||||
for (let param in props) {
|
for (let param in props) {
|
||||||
if (query != '')
|
if (!(props[param] instanceof Object)) {
|
||||||
query += '&';
|
if (query != '') query += '&';
|
||||||
query += `${param}=${props[param]}`;
|
query += `${param}=${props[param]}`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return query;
|
return query;
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const smtp = require('./smtp');
|
const smtp = require('./smtp');
|
||||||
|
const config = require('./config');
|
||||||
const Component = require('./component');
|
const Component = require('./component');
|
||||||
const Report = require('./report');
|
const Report = require('./report');
|
||||||
const db = require('./database');
|
|
||||||
const config = require('./config');
|
|
||||||
|
|
||||||
if (!process.env.OPENSSL_CONF)
|
if (!process.env.OPENSSL_CONF)
|
||||||
process.env.OPENSSL_CONF = '/etc/ssl/';
|
process.env.OPENSSL_CONF = '/etc/ssl/';
|
||||||
|
@ -20,27 +19,22 @@ class Email extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
async getSubject() {
|
async getSubject() {
|
||||||
if (!this.lang) await this.getLang();
|
const component = await this.component();
|
||||||
const locale = this.locale.messages;
|
let locale = this.args.auth.locale;
|
||||||
const userLocale = locale[this.lang];
|
|
||||||
|
|
||||||
if (!userLocale) {
|
if (this.args.recipientId)
|
||||||
|
locale = await component.getLocale(this.args.recipientId);
|
||||||
|
|
||||||
|
const messages = this.locale.messages;
|
||||||
|
const userTranslations = messages[locale];
|
||||||
|
|
||||||
|
if (!userTranslations) {
|
||||||
const fallbackLocale = config.i18n.fallbackLocale;
|
const fallbackLocale = config.i18n.fallbackLocale;
|
||||||
|
|
||||||
return locale[fallbackLocale].subject;
|
return messages[fallbackLocale].subject;
|
||||||
}
|
}
|
||||||
|
|
||||||
return userLocale.subject;
|
return userTranslations.subject;
|
||||||
}
|
|
||||||
|
|
||||||
async getLang() {
|
|
||||||
const clientId = this.args.clientId;
|
|
||||||
const lang = await db.findOne(`
|
|
||||||
SELECT lang FROM account.user
|
|
||||||
WHERE id = ?`, [clientId]).then(rows => {
|
|
||||||
return rows.lang;
|
|
||||||
});
|
|
||||||
this.lang = lang;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async send() {
|
async send() {
|
||||||
|
@ -80,6 +74,7 @@ class Email extends Component {
|
||||||
const localeSubject = await this.getSubject();
|
const localeSubject = await this.getSubject();
|
||||||
const options = {
|
const options = {
|
||||||
to: this.args.recipient,
|
to: this.args.recipient,
|
||||||
|
replyTo: this.args.auth.email,
|
||||||
subject: localeSubject,
|
subject: localeSubject,
|
||||||
html: rendered,
|
html: rendered,
|
||||||
attachments: attachments
|
attachments: attachments
|
||||||
|
|
|
@ -19,8 +19,7 @@ const validator = {
|
||||||
throw new Error(`Required properties not found [${required}]`);
|
throw new Error(`Required properties not found [${required}]`);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
props: ['isPreview']
|
props: ['isPreview', 'authorization']
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
Vue.mixin(validator);
|
Vue.mixin(validator);
|
||||||
|
|
|
@ -4,28 +4,27 @@ const config = require('../config');
|
||||||
const fallbackLocale = config.i18n.fallbackLocale;
|
const fallbackLocale = config.i18n.fallbackLocale;
|
||||||
const userLocale = {
|
const userLocale = {
|
||||||
async serverPrefetch() {
|
async serverPrefetch() {
|
||||||
if (this.clientId)
|
if (this.auth)
|
||||||
this.locale = await this.getLocale(this.clientId);
|
this.$i18n.locale = this.auth.locale;
|
||||||
|
|
||||||
if (this.locale)
|
if (this.recipientId)
|
||||||
this.$i18n.locale = this.locale;
|
this.$i18n.locale = await this.getLocale(this.recipientId);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getLocale(clientId) {
|
getLocale(recipientId) {
|
||||||
return db.findOne(`
|
return db.findOne(`
|
||||||
SELECT IF(u.lang IS NOT NULL, u.lang, LOWER(ct.code)) lang
|
SELECT IF(u.lang IS NOT NULL, u.lang, LOWER(ct.code)) lang
|
||||||
FROM client c
|
FROM client c
|
||||||
JOIN country ct ON ct.id = c.countryFk
|
JOIN country ct ON ct.id = c.countryFk
|
||||||
JOIN account.user u ON u.id = c.id
|
JOIN account.user u ON u.id = c.id
|
||||||
WHERE c.id = ?`, [clientId]).then(rows => {
|
WHERE c.id = ?`, [recipientId]).then(rows => {
|
||||||
if (rows)
|
if (rows)
|
||||||
return rows.lang;
|
return rows.lang;
|
||||||
else return fallbackLocale;
|
else return fallbackLocale;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
props: ['clientId']
|
props: ['auth', 'recipientId']
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
Vue.mixin(userLocale);
|
Vue.mixin(userLocale);
|
||||||
|
|
|
@ -17,17 +17,32 @@ module.exports = app => {
|
||||||
for (let method of methods)
|
for (let method of methods)
|
||||||
paths.push(`/api/${method}/*`);
|
paths.push(`/api/${method}/*`);
|
||||||
|
|
||||||
app.use(paths, async function(request, response, next) {
|
app.use(paths, async function(req, res, next) {
|
||||||
const authorization = getToken(request);
|
const token = getToken(req);
|
||||||
const query = `SELECT userId, ttl, created
|
const query = `SELECT at.id, at.userId, eu.email, u.lang, at.ttl, at.created
|
||||||
FROM salix.AccessToken WHERE id = ?`;
|
FROM salix.AccessToken at
|
||||||
|
JOIN account.user u ON u.id = at.userid
|
||||||
|
JOIN account.emailUser eu ON eu.userFk = u.id
|
||||||
|
WHERE at.id = ?`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const authToken = await db.findOne(query, [authorization]);
|
const auth = await db.findOne(query, [token]);
|
||||||
|
|
||||||
if (!authToken || isTokenExpired(authToken.created, authToken.ttl))
|
if (!auth || isTokenExpired(auth.created, auth.ttl))
|
||||||
throw new Error('Invalid authorization token');
|
throw new Error('Invalid authorization token');
|
||||||
|
|
||||||
|
const args = Object.assign({}, req.query);
|
||||||
|
const props = Object.assign(args, req.body);
|
||||||
|
props.authorization = auth.id;
|
||||||
|
|
||||||
|
req.args = props;
|
||||||
|
req.args.auth = {
|
||||||
|
userId: auth.userId,
|
||||||
|
token: auth.id,
|
||||||
|
email: auth.email,
|
||||||
|
locale: auth.lang
|
||||||
|
};
|
||||||
|
|
||||||
next();
|
next();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
next(error);
|
next(error);
|
||||||
|
@ -36,12 +51,9 @@ module.exports = app => {
|
||||||
|
|
||||||
function getToken(request) {
|
function getToken(request) {
|
||||||
const headers = request.headers;
|
const headers = request.headers;
|
||||||
const params = request.query;
|
const queryParams = request.query;
|
||||||
|
|
||||||
if (headers.authorization)
|
return headers.authorization || queryParams.authorization;
|
||||||
params.authorization = headers.authorization;
|
|
||||||
|
|
||||||
return headers.authorization || params.authorization;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function isTokenExpired(created, ttl) {
|
function isTokenExpired(created, ttl) {
|
||||||
|
|
|
@ -27,7 +27,7 @@ module.exports = {
|
||||||
await db.rawSql(`
|
await db.rawSql(`
|
||||||
INSERT INTO vn.mail (sender, replyTo, sent, subject, body, status)
|
INSERT INTO vn.mail (sender, replyTo, sent, subject, body, status)
|
||||||
VALUES (:recipient, :sender, 1, :subject, :body, :status)`, {
|
VALUES (:recipient, :sender, 1, :subject, :body, :status)`, {
|
||||||
sender: config.app.senderEmail,
|
sender: options.replyTo,
|
||||||
recipient: options.to,
|
recipient: options.to,
|
||||||
subject: options.subject,
|
subject: options.subject,
|
||||||
body: options.text || options.html,
|
body: options.text || options.html,
|
||||||
|
|
|
@ -29,7 +29,7 @@ module.exports = app => {
|
||||||
|
|
||||||
const args = {
|
const args = {
|
||||||
ticketId: ticket.id,
|
ticketId: ticket.id,
|
||||||
clientId: ticket.clientFk,
|
recipientId: ticket.clientFk,
|
||||||
recipient: ticket.recipient
|
recipient: ticket.recipient
|
||||||
};
|
};
|
||||||
const email = new Email('delivery-note-link', args);
|
const email = new Email('delivery-note-link', args);
|
||||||
|
|
|
@ -2,19 +2,11 @@ const Email = require('../core/email');
|
||||||
|
|
||||||
module.exports = app => {
|
module.exports = app => {
|
||||||
app.get(`/api/email/:name`, async(req, res, next) => {
|
app.get(`/api/email/:name`, async(req, res, next) => {
|
||||||
const args = req.query;
|
|
||||||
const requiredArgs = ['clientId', 'recipient'];
|
|
||||||
const argList = requiredArgs.join(',');
|
|
||||||
const hasRequiredArgs = requiredArgs.every(arg => {
|
|
||||||
return args[arg];
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!hasRequiredArgs)
|
const reportName = req.params.name;
|
||||||
throw new Error(`Required properties not found [${argList}]`);
|
const email = new Email(reportName, req.args);
|
||||||
|
|
||||||
const email = new Email(req.params.name, args);
|
if (req.args.isPreview === 'true') {
|
||||||
if (args.isPreview === 'true') {
|
|
||||||
const rendered = await email.render();
|
const rendered = await email.render();
|
||||||
|
|
||||||
res.send(rendered);
|
res.send(rendered);
|
||||||
|
|
|
@ -2,20 +2,10 @@ const Report = require('../core/report');
|
||||||
|
|
||||||
module.exports = app => {
|
module.exports = app => {
|
||||||
app.get(`/api/report/:name`, async(req, res, next) => {
|
app.get(`/api/report/:name`, async(req, res, next) => {
|
||||||
const args = req.query;
|
|
||||||
const requiredArgs = ['clientId'];
|
|
||||||
const argList = requiredArgs.join(',');
|
|
||||||
const hasRequiredArgs = requiredArgs.every(arg => {
|
|
||||||
return args[arg];
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!hasRequiredArgs)
|
|
||||||
throw new Error(`Required properties not found [${argList}]`);
|
|
||||||
|
|
||||||
const reportName = req.params.name;
|
const reportName = req.params.name;
|
||||||
const fileName = getFileName(reportName, args);
|
const fileName = getFileName(reportName, req.args);
|
||||||
const report = new Report(reportName, args);
|
const report = new Report(reportName, req.args);
|
||||||
const stream = await report.toPdfStream();
|
const stream = await report.toPdfStream();
|
||||||
|
|
||||||
res.setHeader('Content-type', 'application/pdf');
|
res.setHeader('Content-type', 'application/pdf');
|
||||||
|
@ -38,8 +28,7 @@ module.exports = app => {
|
||||||
const keys = Object.keys(args);
|
const keys = Object.keys(args);
|
||||||
|
|
||||||
for (let arg of keys) {
|
for (let arg of keys) {
|
||||||
// FIXME: #2197 - Remove clientId as a required param
|
if (arg.endsWith('Id'))
|
||||||
if (arg != 'clientId' && arg.endsWith('Id'))
|
|
||||||
identifiers.push(arg);
|
identifiers.push(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html v-bind:lang="locale">
|
<html v-bind:lang="$i18n.locale">
|
||||||
<head>
|
<head>
|
||||||
<meta name="viewport" content="width=device-width">
|
<meta name="viewport" content="width=device-width">
|
||||||
<meta name="format-detection" content="telephone=no">
|
<meta name="format-detection" content="telephone=no">
|
||||||
|
@ -43,9 +43,9 @@
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr v-for="waste in wastes" v-bind:key="waste.buyer">
|
<tr v-for="waste in wastes" v-bind:key="waste.buyer">
|
||||||
<td class="font gray">{{waste.buyer}}</td>
|
<td class="font gray">{{waste.buyer}}</td>
|
||||||
<td class="number">{{(waste.percentage / 100) | percentage(2, 2, locale)}}</td>
|
<td class="number">{{(waste.percentage / 100) | percentage(2, 2, $i18n.locale)}}</td>
|
||||||
<td class="number">{{waste.dwindle | currency('EUR', locale)}}</td>
|
<td class="number">{{waste.dwindle | currency('EUR', $i18n.locale)}}</td>
|
||||||
<td class="number">{{waste.total | currency('EUR', locale)}}</td>
|
<td class="number">{{waste.total | currency('EUR', $i18n.locale)}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html v-bind:lang="locale">
|
<html v-bind:lang="$i18n.locale">
|
||||||
<head>
|
<head>
|
||||||
<meta name="viewport" content="width=device-width">
|
<meta name="viewport" content="width=device-width">
|
||||||
<meta name="format-detection" content="telephone=no">
|
<meta name="format-detection" content="telephone=no">
|
||||||
|
|
|
@ -10,7 +10,7 @@ module.exports = {
|
||||||
'email-footer': emailFooter.build()
|
'email-footer': emailFooter.build()
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
clientId: {
|
recipientId: {
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
from: {
|
from: {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html v-bind:lang="locale">
|
<html v-bind:lang="$i18n.locale">
|
||||||
<head>
|
<head>
|
||||||
<meta name="viewport" content="width=device-width">
|
<meta name="viewport" content="width=device-width">
|
||||||
<meta name="format-detection" content="telephone=no">
|
<meta name="format-detection" content="telephone=no">
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html v-bind:lang="locale">
|
<html v-bind:lang="$i18n.locale">
|
||||||
<head>
|
<head>
|
||||||
<meta name="viewport" content="width=device-width">
|
<meta name="viewport" content="width=device-width">
|
||||||
<meta name="format-detection" content="telephone=no">
|
<meta name="format-detection" content="telephone=no">
|
||||||
|
|
|
@ -6,7 +6,7 @@ const emailFooter = new Component('email-footer');
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: 'client-welcome',
|
name: 'client-welcome',
|
||||||
async serverPrefetch() {
|
async serverPrefetch() {
|
||||||
this.client = await this.fetchClient(this.clientId);
|
this.client = await this.fetchClient(this.recipientId);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
fetchClient(clientId) {
|
fetchClient(clientId) {
|
||||||
|
@ -29,7 +29,7 @@ module.exports = {
|
||||||
'email-footer': emailFooter.build()
|
'email-footer': emailFooter.build()
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
clientId: {
|
recipientId: {
|
||||||
required: true
|
required: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html v-bind:lang="locale">
|
<html v-bind:lang="$i18n.locale">
|
||||||
<head>
|
<head>
|
||||||
<meta name="viewport" content="width=device-width">
|
<meta name="viewport" content="width=device-width">
|
||||||
<meta name="format-detection" content="telephone=no">
|
<meta name="format-detection" content="telephone=no">
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html v-bind:lang="locale">
|
<html v-bind:lang="$i18n.locale">
|
||||||
<head>
|
<head>
|
||||||
<meta name="viewport" content="width=device-width">
|
<meta name="viewport" content="width=device-width">
|
||||||
<meta name="format-detection" content="telephone=no">
|
<meta name="format-detection" content="telephone=no">
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html v-bind:lang="locale">
|
<html v-bind:lang="$i18n.locale">
|
||||||
<head>
|
<head>
|
||||||
<meta name="viewport" content="width=device-width">
|
<meta name="viewport" content="width=device-width">
|
||||||
<meta name="format-detection" content="telephone=no">
|
<meta name="format-detection" content="telephone=no">
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html v-bind:lang="locale">
|
<html v-bind:lang="$i18n.locale">
|
||||||
<head>
|
<head>
|
||||||
<meta name="viewport" content="width=device-width">
|
<meta name="viewport" content="width=device-width">
|
||||||
<meta name="format-detection" content="telephone=no">
|
<meta name="format-detection" content="telephone=no">
|
||||||
|
|
|
@ -8,7 +8,7 @@ const attachments = require('./attachments.json');
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: 'letter-debtor-nd',
|
name: 'letter-debtor-nd',
|
||||||
async serverPrefetch() {
|
async serverPrefetch() {
|
||||||
this.debtor = await this.fetchDebtor(this.clientId, this.companyId);
|
this.debtor = await this.fetchDebtor(this.recipientId, this.companyId);
|
||||||
|
|
||||||
if (!this.debtor)
|
if (!this.debtor)
|
||||||
throw new Error('Something went wrong');
|
throw new Error('Something went wrong');
|
||||||
|
@ -40,7 +40,7 @@ module.exports = {
|
||||||
authorization: {
|
authorization: {
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
clientId: {
|
recipientId: {
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
companyId: {
|
companyId: {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html v-bind:lang="locale">
|
<html v-bind:lang="$i18n.locale">
|
||||||
<head>
|
<head>
|
||||||
<meta name="viewport" content="width=device-width">
|
<meta name="viewport" content="width=device-width">
|
||||||
<meta name="format-detection" content="telephone=no">
|
<meta name="format-detection" content="telephone=no">
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
<!-- Block -->
|
<!-- Block -->
|
||||||
<div class="grid-row">
|
<div class="grid-row">
|
||||||
<div class="grid-block vn-pa-lg">
|
<div class="grid-block vn-pa-lg">
|
||||||
<h1>{{ $t('title') }}</h1>
|
<h1>{{ $t('title') }} {{$i18n.locale}}</h1>
|
||||||
<p>{{ $t('sections.introduction.title') }},</p>
|
<p>{{ $t('sections.introduction.title') }},</p>
|
||||||
<p>{{ $t('sections.introduction.description') }}</p>
|
<p>{{ $t('sections.introduction.description') }}</p>
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ const attachments = require('./attachments.json');
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: 'letter-debtor-st',
|
name: 'letter-debtor-st',
|
||||||
async serverPrefetch() {
|
async serverPrefetch() {
|
||||||
this.debtor = await this.fetchDebtor(this.clientId, this.companyId);
|
this.debtor = await this.fetchDebtor(this.recipientId, this.companyId);
|
||||||
|
|
||||||
if (!this.debtor)
|
if (!this.debtor)
|
||||||
throw new Error('Something went wrong');
|
throw new Error('Something went wrong');
|
||||||
|
@ -37,10 +37,7 @@ module.exports = {
|
||||||
'attachment': attachment.build()
|
'attachment': attachment.build()
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
authorization: {
|
recipientId: {
|
||||||
required: true
|
|
||||||
},
|
|
||||||
clientId: {
|
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
companyId: {
|
companyId: {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html v-bind:lang="locale">
|
<html v-bind:lang="$i18n.locale">
|
||||||
<head>
|
<head>
|
||||||
<meta name="viewport" content="width=device-width">
|
<meta name="viewport" content="width=device-width">
|
||||||
<meta name="format-detection" content="telephone=no">
|
<meta name="format-detection" content="telephone=no">
|
||||||
|
|
|
@ -6,7 +6,7 @@ const emailFooter = new Component('email-footer');
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: 'payment-update',
|
name: 'payment-update',
|
||||||
async serverPrefetch() {
|
async serverPrefetch() {
|
||||||
this.payMethod = await this.fetchPayMethod(this.clientId);
|
this.payMethod = await this.fetchPayMethod(this.recipientId);
|
||||||
|
|
||||||
if (!this.payMethod)
|
if (!this.payMethod)
|
||||||
throw new Error('Something went wrong');
|
throw new Error('Something went wrong');
|
||||||
|
@ -34,7 +34,7 @@ module.exports = {
|
||||||
'email-footer': emailFooter.build()
|
'email-footer': emailFooter.build()
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
clientId: {
|
recipientId: {
|
||||||
required: true
|
required: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html v-bind:lang="locale">
|
<html v-bind:lang="$i18n.locale">
|
||||||
<head>
|
<head>
|
||||||
<meta name="viewport" content="width=device-width">
|
<meta name="viewport" content="width=device-width">
|
||||||
<meta name="format-detection" content="telephone=no">
|
<meta name="format-detection" content="telephone=no">
|
||||||
|
|
|
@ -8,7 +8,7 @@ const attachments = require('./attachments.json');
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: 'printer-setup',
|
name: 'printer-setup',
|
||||||
async serverPrefetch() {
|
async serverPrefetch() {
|
||||||
this.client = await this.fetchClient(this.clientId);
|
this.client = await this.fetchClient(this.recipientId);
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {attachments};
|
return {attachments};
|
||||||
|
@ -16,19 +16,19 @@ module.exports = {
|
||||||
methods: {
|
methods: {
|
||||||
fetchClient(clientId) {
|
fetchClient(clientId) {
|
||||||
return db.findOne(`
|
return db.findOne(`
|
||||||
SELECT
|
SELECT
|
||||||
c.id,
|
c.id,
|
||||||
u.lang locale,
|
u.lang locale,
|
||||||
u.name AS userName,
|
u.name AS userName,
|
||||||
c.email recipient,
|
c.email recipient,
|
||||||
CONCAT(w.lastName, ' ', w.firstName) salesPersonName,
|
CONCAT(w.lastName, ' ', w.firstName) salesPersonName,
|
||||||
w.phone AS salesPersonPhone,
|
w.phone AS salesPersonPhone,
|
||||||
CONCAT(wu.name, '@verdnatura.es') AS salesPersonEmail
|
CONCAT(wu.name, '@verdnatura.es') AS salesPersonEmail
|
||||||
FROM client c
|
FROM client c
|
||||||
JOIN account.user u ON u.id = c.id
|
JOIN account.user u ON u.id = c.id
|
||||||
LEFT JOIN worker w ON w.id = c.salesPersonFk
|
LEFT JOIN worker w ON w.id = c.salesPersonFk
|
||||||
LEFT JOIN account.user wu ON wu.id = w.userFk
|
LEFT JOIN account.user wu ON wu.id = w.userFk
|
||||||
WHERE c.id = ?`, [clientId]);
|
WHERE c.id = ?`, [clientId]);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
@ -37,7 +37,7 @@ module.exports = {
|
||||||
'attachment': attachment.build()
|
'attachment': attachment.build()
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
clientId: {
|
recipientId: {
|
||||||
required: true
|
required: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html v-bind:lang="locale">
|
<html v-bind:lang="$i18n.locale">
|
||||||
<head>
|
<head>
|
||||||
<meta name="viewport" content="width=device-width">
|
<meta name="viewport" content="width=device-width">
|
||||||
<meta name="format-detection" content="telephone=no">
|
<meta name="format-detection" content="telephone=no">
|
||||||
|
|
|
@ -15,7 +15,7 @@ module.exports = {
|
||||||
'attachment': attachment.build()
|
'attachment': attachment.build()
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
clientId: {
|
recipientId: {
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
companyId: {
|
companyId: {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html v-bind:lang="locale">
|
<html v-bind:lang="$i18n.locale">
|
||||||
<body>
|
<body>
|
||||||
<table class="grid">
|
<table class="grid">
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|
|
@ -9,9 +9,8 @@ module.exports = {
|
||||||
this.to = new Date(this.to);
|
this.to = new Date(this.to);
|
||||||
this.from = new Date(this.from);
|
this.from = new Date(this.from);
|
||||||
|
|
||||||
this.client = await this.fetchClient(this.clientId);
|
this.client = await this.fetchClient(this.recipientId);
|
||||||
|
this.sales = await this.fetchSales(this.recipientId, this.from, this.to);
|
||||||
this.sales = await this.fetchSales(this.clientId, this.from, this.to);
|
|
||||||
|
|
||||||
if (!this.client)
|
if (!this.client)
|
||||||
throw new Error('Something went wrong');
|
throw new Error('Something went wrong');
|
||||||
|
@ -63,7 +62,7 @@ module.exports = {
|
||||||
'report-footer': reportFooter.build()
|
'report-footer': reportFooter.build()
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
clientId: {
|
recipientId: {
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
from: {
|
from: {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html v-bind:lang="locale">
|
<html v-bind:lang="$i18n.locale">
|
||||||
<body>
|
<body>
|
||||||
<table class="grid">
|
<table class="grid">
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html v-bind:lang="locale">
|
<html v-bind:lang="$i18n.locale">
|
||||||
<body>
|
<body>
|
||||||
<table class="grid">
|
<table class="grid">
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -88,10 +88,10 @@
|
||||||
<td>{{sale.itemFk}}</td>
|
<td>{{sale.itemFk}}</td>
|
||||||
<td class="number">{{sale.quantity}}</td>
|
<td class="number">{{sale.quantity}}</td>
|
||||||
<td width="50%">{{sale.concept}}</td>
|
<td width="50%">{{sale.concept}}</td>
|
||||||
<td class="number">{{sale.price | currency('EUR', locale)}}</td>
|
<td class="number">{{sale.price | currency('EUR', $i18n.locale)}}</td>
|
||||||
<td class="centered">{{(sale.discount / 100) | percentage}}</td>
|
<td class="centered">{{(sale.discount / 100) | percentage}}</td>
|
||||||
<td class="centered">{{sale.vatType}}</td>
|
<td class="centered">{{sale.vatType}}</td>
|
||||||
<td class="number">{{sale.price * sale.quantity * (1 - sale.discount / 100) | currency('EUR', locale)}}</td>
|
<td class="number">{{sale.price * sale.quantity * (1 - sale.discount / 100) | currency('EUR', $i18n.locale)}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="description">
|
<tr class="description">
|
||||||
<td colspan="2" class="centered">
|
<td colspan="2" class="centered">
|
||||||
|
@ -125,7 +125,7 @@
|
||||||
<td colspan="6">
|
<td colspan="6">
|
||||||
<span class="pull-right">{{$t('subtotal')}}</span>
|
<span class="pull-right">{{$t('subtotal')}}</span>
|
||||||
</td>
|
</td>
|
||||||
<td class="number">{{getSubTotal() | currency('EUR', locale)}}</td>
|
<td class="number">{{getSubTotal() | currency('EUR', $i18n.locale)}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tfoot>
|
</tfoot>
|
||||||
</table>
|
</table>
|
||||||
|
@ -149,13 +149,13 @@
|
||||||
<td>{{service.description}}</td>
|
<td>{{service.description}}</td>
|
||||||
<td class="number">{{service.quantity}}</td>
|
<td class="number">{{service.quantity}}</td>
|
||||||
<td>{{service.taxDescription}}</td>
|
<td>{{service.taxDescription}}</td>
|
||||||
<td class="number">{{service.price | currency('EUR', locale)}}</td>
|
<td class="number">{{service.price | currency('EUR', $i18n.locale)}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
<tfoot>
|
<tfoot>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="3"></td>
|
<td colspan="3"></td>
|
||||||
<td class="number">{{$t('total')}} {{serviceTotal | currency('EUR', locale)}}</td>
|
<td class="number">{{$t('total')}} {{serviceTotal | currency('EUR', $i18n.locale)}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tfoot>
|
</tfoot>
|
||||||
</table>
|
</table>
|
||||||
|
@ -180,24 +180,24 @@
|
||||||
<tr v-for="tax in taxes">
|
<tr v-for="tax in taxes">
|
||||||
<td width="45%">{{tax.name}}</td>
|
<td width="45%">{{tax.name}}</td>
|
||||||
<td width="20%" class="number">
|
<td width="20%" class="number">
|
||||||
{{tax.Base | currency('EUR', locale)}}
|
{{tax.Base | currency('EUR', $i18n.locale)}}
|
||||||
</td>
|
</td>
|
||||||
<td>{{tax.vatPercent | percentage}}</td>
|
<td>{{tax.vatPercent | percentage}}</td>
|
||||||
<td class="number">{{tax.tax | currency('EUR', locale)}}</td>
|
<td class="number">{{tax.tax | currency('EUR', $i18n.locale)}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
<tfoot>
|
<tfoot>
|
||||||
<tr class="font bold">
|
<tr class="font bold">
|
||||||
<td width="45%">{{$t('subtotal')}}</td>
|
<td width="45%">{{$t('subtotal')}}</td>
|
||||||
<td width="20%" class="number">
|
<td width="20%" class="number">
|
||||||
{{getTotalBase() | currency('EUR', locale)}}
|
{{getTotalBase() | currency('EUR', $i18n.locale)}}
|
||||||
</td>
|
</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td class="number">{{getTotalTax()| currency('EUR', locale)}}</td>
|
<td class="number">{{getTotalTax()| currency('EUR', $i18n.locale)}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="font bold">
|
<tr class="font bold">
|
||||||
<td colspan="2">{{$t('total')}}</td>
|
<td colspan="2">{{$t('total')}}</td>
|
||||||
<td colspan="2" class="number">{{getTotal() | currency('EUR', locale)}}</td>
|
<td colspan="2" class="number">{{getTotal() | currency('EUR', $i18n.locale)}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tfoot>
|
</tfoot>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html v-bind:lang="locale">
|
<html v-bind:lang="$i18n.locale">
|
||||||
<body>
|
<body>
|
||||||
<table class="grid">
|
<table class="grid">
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -141,7 +141,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="font gray align-right">{{$t('import')}}</th>
|
<th class="font gray align-right">{{$t('import')}}</th>
|
||||||
<td>{{ticket.import | currency('EUR', locale)}}</td>
|
<td>{{ticket.import | currency('EUR', $i18n.locale)}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html v-bind:lang="locale">
|
<html v-bind:lang="$i18n.locale">
|
||||||
<body>
|
<body>
|
||||||
<table class="grid">
|
<table class="grid">
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -77,8 +77,8 @@
|
||||||
<td class="number">{{buy.packing}}</td>
|
<td class="number">{{buy.packing}}</td>
|
||||||
<td width="50%">{{buy.itemName}}</td>
|
<td width="50%">{{buy.itemName}}</td>
|
||||||
<td width="10%" class="number">{{buy.quantity | number}}</td>
|
<td width="10%" class="number">{{buy.quantity | number}}</td>
|
||||||
<td width="15%" class="number">{{buy.buyingValue | currency('EUR', locale)}}</td>
|
<td width="15%" class="number">{{buy.buyingValue | currency('EUR', $i18n.locale)}}</td>
|
||||||
<td width="15%" class="number">{{buy.buyingValue * buy.quantity | currency('EUR', locale)}}</td>
|
<td width="15%" class="number">{{buy.buyingValue * buy.quantity | currency('EUR', $i18n.locale)}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="description">
|
<tr class="description">
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
|
@ -106,7 +106,7 @@
|
||||||
<td colspan="5">
|
<td colspan="5">
|
||||||
<span class="pull-right">{{$t('total')}}</span>
|
<span class="pull-right">{{$t('total')}}</span>
|
||||||
</td>
|
</td>
|
||||||
<td class="number">{{getTotal() | currency('EUR', locale)}}</td>
|
<td class="number">{{getTotal() | currency('EUR', $i18n.locale)}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tfoot>
|
</tfoot>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html v-bind:lang="locale">
|
<html v-bind:lang="$i18n.locale">
|
||||||
<body>
|
<body>
|
||||||
<table class="grid">
|
<table class="grid">
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html v-bind:lang="locale">
|
<html v-bind:lang="$i18n.locale">
|
||||||
<body>
|
<body>
|
||||||
<table class="grid">
|
<table class="grid">
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|
|
@ -6,8 +6,8 @@ const reportFooter = new Component('report-footer');
|
||||||
module.exports = {
|
module.exports = {
|
||||||
name: 'letter-debtor',
|
name: 'letter-debtor',
|
||||||
async serverPrefetch() {
|
async serverPrefetch() {
|
||||||
this.client = await this.fetchClient(this.clientId);
|
this.client = await this.fetchClient(this.recipientId);
|
||||||
this.sales = await this.fetchSales(this.clientId, this.companyId);
|
this.sales = await this.fetchSales(this.recipientId, this.companyId);
|
||||||
|
|
||||||
if (!this.client)
|
if (!this.client)
|
||||||
throw new Error('Something went wrong');
|
throw new Error('Something went wrong');
|
||||||
|
@ -79,7 +79,7 @@ module.exports = {
|
||||||
'report-footer': reportFooter.build()
|
'report-footer': reportFooter.build()
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
clientId: {
|
recipientId: {
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
companyId: {
|
companyId: {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html v-bind:lang="locale">
|
<html v-bind:lang="$i18n.locale">
|
||||||
<body>
|
<body>
|
||||||
<table class="grid">
|
<table class="grid">
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html v-bind:lang="locale">
|
<html v-bind:lang="$i18n.locale">
|
||||||
<body>
|
<body>
|
||||||
<table class="grid">
|
<table class="grid">
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|
|
@ -6,8 +6,8 @@ const reportFooter = new Component('report-footer');
|
||||||
const rptSepaCore = {
|
const rptSepaCore = {
|
||||||
name: 'sepa-core',
|
name: 'sepa-core',
|
||||||
async serverPrefetch() {
|
async serverPrefetch() {
|
||||||
this.client = await this.fetchClient(this.clientId, this.companyId);
|
this.client = await this.fetchClient(this.recipientId, this.companyId);
|
||||||
this.supplier = await this.fetchSupplier(this.clientId, this.companyId);
|
this.supplier = await this.fetchSupplier(this.recipientId, this.companyId);
|
||||||
|
|
||||||
if (!this.client)
|
if (!this.client)
|
||||||
throw new Error('Something went wrong');
|
throw new Error('Something went wrong');
|
||||||
|
@ -67,7 +67,7 @@ const rptSepaCore = {
|
||||||
'report-footer': reportFooter.build()
|
'report-footer': reportFooter.build()
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
clientId: {
|
recipientId: {
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
companyId: {
|
companyId: {
|
||||||
|
@ -76,5 +76,4 @@ const rptSepaCore = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
module.exports = rptSepaCore;
|
module.exports = rptSepaCore;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html v-bind:lang="locale">
|
<html v-bind:lang="$i18n.locale">
|
||||||
<body>
|
<body>
|
||||||
<table class="grid">
|
<table class="grid">
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|
Loading…
Reference in New Issue