Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 7529-workerPIT
gitea/salix/pipeline/pr-dev This commit looks good
Details
gitea/salix/pipeline/pr-dev This commit looks good
Details
This commit is contained in:
commit
0a726a8fe7
|
@ -32,8 +32,7 @@ RUN apt-get update \
|
||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
&& apt-get install -y --no-install-recommends \
|
&& apt-get install -y --no-install-recommends \
|
||||||
samba-common-bin samba-dsdb-modules\
|
samba-common-bin samba-dsdb-modules\
|
||||||
&& rm -rf /var/lib/apt/lists/* \
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
&& npm -g install pm2
|
|
||||||
|
|
||||||
# Salix
|
# Salix
|
||||||
|
|
||||||
|
@ -55,7 +54,4 @@ COPY \
|
||||||
README.md \
|
README.md \
|
||||||
./
|
./
|
||||||
|
|
||||||
CMD ["pm2-runtime", "./back/process.yml"]
|
CMD ["node", "--tls-min-v1.0", "--openssl-legacy-provider", "./loopback/server/server.js"]
|
||||||
|
|
||||||
HEALTHCHECK --interval=15s --timeout=10s \
|
|
||||||
CMD curl -f http://localhost:3000/api/Applications/status || exit 1
|
|
|
@ -19,8 +19,15 @@ module.exports = Self => {
|
||||||
|
|
||||||
if (typeof options == 'object')
|
if (typeof options == 'object')
|
||||||
Object.assign(myOptions, options);
|
Object.assign(myOptions, options);
|
||||||
const [info, info2, [{'@vCollectionFk': collectionFk}]] = await Self.rawSql(
|
|
||||||
'CALL vn.collection_getAssigned(?, @vCollectionFk);SELECT @vCollectionFk', [userId], myOptions);
|
const randStr = Math.random().toString(36).substring(3);
|
||||||
|
const result = await Self.rawSql(`
|
||||||
|
CALL vn.collection_getAssigned(?, @vCollectionFk);
|
||||||
|
SELECT @vCollectionFk ?
|
||||||
|
`, [userId, randStr], myOptions);
|
||||||
|
|
||||||
|
const collectionFk = result.find(item => item[0]?.[randStr] !== undefined)?.[0]?.[randStr];
|
||||||
|
|
||||||
if (!collectionFk) throw new UserError('There are not picking tickets');
|
if (!collectionFk) throw new UserError('There are not picking tickets');
|
||||||
await Self.rawSql('CALL vn.collection_printSticker(?, NULL)', [collectionFk], myOptions);
|
await Self.rawSql('CALL vn.collection_printSticker(?, NULL)', [collectionFk], myOptions);
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,8 @@ module.exports = Self => {
|
||||||
p.code parkingCodePrevia,
|
p.code parkingCodePrevia,
|
||||||
p.pickingOrder pickingOrderPrevia,
|
p.pickingOrder pickingOrderPrevia,
|
||||||
iss.id itemShelvingSaleFk,
|
iss.id itemShelvingSaleFk,
|
||||||
iss.isPicked
|
iss.isPicked,
|
||||||
|
iss.itemShelvingFk
|
||||||
FROM ticketCollection tc
|
FROM ticketCollection tc
|
||||||
LEFT JOIN collection c ON c.id = tc.collectionFk
|
LEFT JOIN collection c ON c.id = tc.collectionFk
|
||||||
JOIN sale s ON s.ticketFk = tc.ticketFk
|
JOIN sale s ON s.ticketFk = tc.ticketFk
|
||||||
|
@ -102,7 +103,8 @@ module.exports = Self => {
|
||||||
p.code,
|
p.code,
|
||||||
p.pickingOrder,
|
p.pickingOrder,
|
||||||
iss.id itemShelvingSaleFk,
|
iss.id itemShelvingSaleFk,
|
||||||
iss.isPicked
|
iss.isPicked,
|
||||||
|
iss.itemShelvingFk
|
||||||
FROM sectorCollection sc
|
FROM sectorCollection sc
|
||||||
JOIN sectorCollectionSaleGroup ss ON ss.sectorCollectionFk = sc.id
|
JOIN sectorCollectionSaleGroup ss ON ss.sectorCollectionFk = sc.id
|
||||||
JOIN saleGroup sg ON sg.id = ss.saleGroupFk
|
JOIN saleGroup sg ON sg.id = ss.saleGroupFk
|
||||||
|
|
|
@ -4,21 +4,45 @@ module.exports = Self => {
|
||||||
/**
|
/**
|
||||||
* Returns basic headers
|
* Returns basic headers
|
||||||
*
|
*
|
||||||
* @param {string} cookie - The docuware cookie
|
|
||||||
* @return {object} - The headers
|
* @return {object} - The headers
|
||||||
*/
|
*/
|
||||||
Self.getOptions = async() => {
|
Self.getOptions = async() => {
|
||||||
const docuwareConfig = await Self.app.models.DocuwareConfig.findOne();
|
const docuwareConfig = await Self.app.models.DocuwareConfig.findOne();
|
||||||
|
const now = Date.vnNow();
|
||||||
|
let {url, username, password, token, expired} = docuwareConfig;
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV && (!expired || expired < now + 60)) {
|
||||||
|
const {data: {IdentityServiceUrl}} = await axios.get(`${url}/Home/IdentityServiceInfo`);
|
||||||
|
const {data: {token_endpoint}} = await axios.get(`${IdentityServiceUrl}/.well-known/openid-configuration`);
|
||||||
|
const {data} = await axios.post(token_endpoint, {
|
||||||
|
grant_type: 'password',
|
||||||
|
scope: 'docuware.platform',
|
||||||
|
client_id: 'docuware.platform.net.client',
|
||||||
|
username,
|
||||||
|
password
|
||||||
|
}, {headers: {
|
||||||
|
'Accept': 'application/json',
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded'
|
||||||
|
}});
|
||||||
|
|
||||||
|
const newToken = data.access_token;
|
||||||
|
token = data.token_type + ' ' + newToken;
|
||||||
|
await docuwareConfig.updateAttributes({
|
||||||
|
token,
|
||||||
|
expired: now + data.expires_in
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const headers = {
|
const headers = {
|
||||||
headers: {
|
headers: {
|
||||||
'Accept': 'application/json',
|
'Accept': 'application/json',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Cookie': docuwareConfig.cookie
|
'Authorization': token
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
url: docuwareConfig.url,
|
url,
|
||||||
headers
|
headers
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,87 +2,54 @@ const axios = require('axios');
|
||||||
const models = require('vn-loopback/server/server').models;
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
|
||||||
describe('Docuware core', () => {
|
describe('Docuware core', () => {
|
||||||
beforeAll(() => {
|
const fileCabinetCode = 'deliveryNote';
|
||||||
|
beforeAll(async() => {
|
||||||
process.env.NODE_ENV = 'testing';
|
process.env.NODE_ENV = 'testing';
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(() => {
|
const docuwareInfo = await models.Docuware.findOne({
|
||||||
delete process.env.NODE_ENV;
|
where: {
|
||||||
});
|
code: fileCabinetCode
|
||||||
|
}
|
||||||
describe('getOptions()', () => {
|
|
||||||
it('should return url and headers', async() => {
|
|
||||||
const result = await models.Docuware.getOptions();
|
|
||||||
|
|
||||||
expect(result.url).toBeDefined();
|
|
||||||
expect(result.headers).toBeDefined();
|
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
describe('getDialog()', () => {
|
spyOn(axios, 'get').and.callFake(url => {
|
||||||
it('should return dialogId', async() => {
|
if (url.includes('IdentityServiceInfo')) return {data: {IdentityServiceUrl: 'IdentityServiceUrl'}};
|
||||||
const dialogs = {
|
if (url.includes('IdentityServiceUrl')) return {data: {token_endpoint: 'token_endpoint'}};
|
||||||
data: {
|
if (url.includes('dialogs')) {
|
||||||
Dialog: [
|
return {
|
||||||
{
|
data: {
|
||||||
DisplayName: 'find',
|
Dialog: [
|
||||||
Id: 'getDialogTest'
|
{
|
||||||
}
|
DisplayName: 'find',
|
||||||
]
|
Id: 'getDialogTest'
|
||||||
}
|
}
|
||||||
};
|
]
|
||||||
spyOn(axios, 'get').and.returnValue(new Promise(resolve => resolve(dialogs)));
|
}
|
||||||
const result = await models.Docuware.getDialog('deliveryNote', 'find', 'randomFileCabinetId');
|
};
|
||||||
|
}
|
||||||
|
|
||||||
expect(result).toEqual('getDialogTest');
|
if (url.includes('FileCabinets')) {
|
||||||
});
|
return {data: {
|
||||||
});
|
|
||||||
|
|
||||||
describe('getFileCabinet()', () => {
|
|
||||||
it('should return fileCabinetId', async() => {
|
|
||||||
const code = 'deliveryNote';
|
|
||||||
const docuwareInfo = await models.Docuware.findOne({
|
|
||||||
where: {
|
|
||||||
code
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const dialogs = {
|
|
||||||
data: {
|
|
||||||
FileCabinet: [
|
FileCabinet: [
|
||||||
{
|
{
|
||||||
Name: docuwareInfo.fileCabinetName,
|
Name: docuwareInfo.fileCabinetName,
|
||||||
Id: 'getFileCabinetTest'
|
Id: 'getFileCabinetTest'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}};
|
||||||
};
|
}
|
||||||
spyOn(axios, 'get').and.returnValue(new Promise(resolve => resolve(dialogs)));
|
|
||||||
const result = await models.Docuware.getFileCabinet(code);
|
|
||||||
|
|
||||||
expect(result).toEqual('getFileCabinetTest');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('get()', () => {
|
|
||||||
it('should return data without parse', async() => {
|
|
||||||
spyOn(models.Docuware, 'getFileCabinet').and.returnValue((new Promise(resolve => resolve(Math.random()))));
|
|
||||||
spyOn(models.Docuware, 'getDialog').and.returnValue((new Promise(resolve => resolve(Math.random()))));
|
|
||||||
const data = {
|
|
||||||
data: {
|
|
||||||
id: 1
|
|
||||||
}
|
|
||||||
};
|
|
||||||
spyOn(axios, 'post').and.returnValue(new Promise(resolve => resolve(data)));
|
|
||||||
const result = await models.Docuware.get('deliveryNote');
|
|
||||||
|
|
||||||
expect(result.id).toEqual(1);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return data with parse', async() => {
|
spyOn(axios, 'post').and.callFake(url => {
|
||||||
spyOn(models.Docuware, 'getFileCabinet').and.returnValue((new Promise(resolve => resolve(Math.random()))));
|
if (url.includes('token_endpoint')) {
|
||||||
spyOn(models.Docuware, 'getDialog').and.returnValue((new Promise(resolve => resolve(Math.random()))));
|
return {data: {
|
||||||
const data = {
|
access_token: 'access_token',
|
||||||
data: {
|
token_type: 'bearer',
|
||||||
|
expires_in: 10000
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
if (url.includes('DialogExpression')) {
|
||||||
|
return {data: {
|
||||||
Items: [{
|
Items: [{
|
||||||
Fields: [
|
Fields: [
|
||||||
{
|
{
|
||||||
|
@ -103,12 +70,52 @@ describe('Docuware core', () => {
|
||||||
]
|
]
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
delete process.env.NODE_ENV;
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getOptions()', () => {
|
||||||
|
it('should return url and headers', async() => {
|
||||||
|
const result = await models.Docuware.getOptions();
|
||||||
|
|
||||||
|
expect(result.url).toBeDefined();
|
||||||
|
expect(result.headers).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Dialog()', () => {
|
||||||
|
it('should return dialogId', async() => {
|
||||||
|
const result = await models.Docuware.getDialog('deliveryNote', 'find', 'randomFileCabinetId');
|
||||||
|
|
||||||
|
expect(result).toEqual('getDialogTest');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getFileCabinet()', () => {
|
||||||
|
it('should return fileCabinetId', async() => {
|
||||||
|
const result = await models.Docuware.getFileCabinet(fileCabinetCode);
|
||||||
|
|
||||||
|
expect(result).toEqual('getFileCabinetTest');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('get()', () => {
|
||||||
|
it('should return data without parse', async() => {
|
||||||
|
const [result] = await models.Docuware.get('deliveryNote');
|
||||||
|
|
||||||
|
expect(result.firstRequiredField).toEqual(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return data with parse', async() => {
|
||||||
const parse = {
|
const parse = {
|
||||||
'firstRequiredField': 'id',
|
'firstRequiredField': 'id',
|
||||||
'secondRequiredField': 'name',
|
'secondRequiredField': 'name',
|
||||||
};
|
};
|
||||||
spyOn(axios, 'post').and.returnValue(new Promise(resolve => resolve(data)));
|
|
||||||
const [result] = await models.Docuware.get('deliveryNote', null, parse);
|
const [result] = await models.Docuware.get('deliveryNote', null, parse);
|
||||||
|
|
||||||
expect(result.id).toEqual(1);
|
expect(result.id).toEqual(1);
|
||||||
|
@ -119,17 +126,14 @@ describe('Docuware core', () => {
|
||||||
|
|
||||||
describe('getById()', () => {
|
describe('getById()', () => {
|
||||||
it('should return data', async() => {
|
it('should return data', async() => {
|
||||||
spyOn(models.Docuware, 'getFileCabinet').and.returnValue((new Promise(resolve => resolve(Math.random()))));
|
spyOn(models.Docuware, 'get');
|
||||||
spyOn(models.Docuware, 'getDialog').and.returnValue((new Promise(resolve => resolve(Math.random()))));
|
await models.Docuware.getById('deliveryNote', 1);
|
||||||
const data = {
|
|
||||||
data: {
|
|
||||||
id: 1
|
|
||||||
}
|
|
||||||
};
|
|
||||||
spyOn(axios, 'post').and.returnValue(new Promise(resolve => resolve(data)));
|
|
||||||
const result = await models.Docuware.getById('deliveryNote', 1);
|
|
||||||
|
|
||||||
expect(result.id).toEqual(1);
|
expect(models.Docuware.get).toHaveBeenCalledWith(
|
||||||
|
'deliveryNote',
|
||||||
|
{condition: [Object({DBName: 'N__ALBAR_N', Value: [1]})]},
|
||||||
|
undefined
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -143,7 +143,7 @@ module.exports = Self => {
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'multipart/form-data',
|
'Content-Type': 'multipart/form-data',
|
||||||
'X-File-ModifiedDate': Date.vnNew(),
|
'X-File-ModifiedDate': Date.vnNew(),
|
||||||
'Cookie': docuwareOptions.headers.headers.Cookie,
|
'Authorization': docuwareOptions.headers.headers.Authorization,
|
||||||
...data.getHeaders()
|
...data.getHeaders()
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -72,9 +72,9 @@ describe('Renew Token', () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(error).toBeDefined();
|
expect(error).toBeDefined();
|
||||||
const query = 'SELECT * FROM util.debug';
|
|
||||||
|
|
||||||
const debugLog = await models.Application.rawSql(query, null);
|
const query = 'SELECT * FROM util.debug WHERE variable = "renewToken"';
|
||||||
|
const debugLog = await models.Application.rawSql(query);
|
||||||
|
|
||||||
expect(debugLog.length).toEqual(1);
|
expect(debugLog.length).toEqual(1);
|
||||||
});
|
});
|
||||||
|
|
|
@ -175,6 +175,9 @@
|
||||||
"PrintConfig": {
|
"PrintConfig": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
"QueueMember": {
|
||||||
|
"dataSource": "vn"
|
||||||
|
},
|
||||||
"ViaexpressConfig": {
|
"ViaexpressConfig": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
|
|
@ -16,17 +16,17 @@
|
||||||
"url": {
|
"url": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"cookie": {
|
"token": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"username": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"password": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"expired":{
|
||||||
|
"type": "number"
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"acls": [
|
|
||||||
{
|
|
||||||
"property": "*",
|
|
||||||
"accessType": "*",
|
|
||||||
"principalType": "ROLE",
|
|
||||||
"principalId": "$everyone",
|
|
||||||
"permission": "ALLOW"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
{
|
||||||
|
"name": "QueueMember",
|
||||||
|
"base": "VnModel",
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "pbx.queueMember"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "number",
|
||||||
|
"id": true
|
||||||
|
},
|
||||||
|
"queue": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"extension": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"relations": {
|
||||||
|
"queueRelation": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Queue",
|
||||||
|
"foreignKey": "queue",
|
||||||
|
"primaryKey": "name"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"acls": [
|
||||||
|
{
|
||||||
|
"property": "*",
|
||||||
|
"accessType": "READ",
|
||||||
|
"principalType": "ROLE",
|
||||||
|
"principalId": "employee",
|
||||||
|
"permission": "ALLOW"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -1,7 +0,0 @@
|
||||||
apps:
|
|
||||||
- script: ./loopback/server/server.js
|
|
||||||
name: salix-back
|
|
||||||
instances: 1
|
|
||||||
max_restarts: 0
|
|
||||||
autorestart: false
|
|
||||||
node_args: --tls-min-v1.0 --openssl-legacy-provider
|
|
|
@ -185,6 +185,7 @@ INSERT INTO `vn`.`warehouse`(`id`, `name`, `code`, `isComparative`, `isInventory
|
||||||
(3, 'Warehouse Three', NULL, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0),
|
(3, 'Warehouse Three', NULL, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0),
|
||||||
(4, 'Warehouse Four', NULL, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1),
|
(4, 'Warehouse Four', NULL, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1),
|
||||||
(5, 'Warehouse Five', NULL, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0),
|
(5, 'Warehouse Five', NULL, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0),
|
||||||
|
(6, 'Warehouse six', 'vnh', 1, 1, 1, 1, 0, 0, 1, 1, 0, 0),
|
||||||
(13, 'Inventory', 'inv', 1, 1, 1, 0, 0, 0, 1, 0, 0, 0),
|
(13, 'Inventory', 'inv', 1, 1, 1, 0, 0, 0, 1, 0, 0, 0),
|
||||||
(60, 'Algemesi', NULL, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0);
|
(60, 'Algemesi', NULL, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0);
|
||||||
|
|
||||||
|
@ -387,23 +388,23 @@ INSERT INTO `vn`.`contactChannel`(`id`, `name`)
|
||||||
(4, 'GCN Channel'),
|
(4, 'GCN Channel'),
|
||||||
(5, 'The Newspaper');
|
(5, 'The Newspaper');
|
||||||
|
|
||||||
INSERT INTO `vn`.`client`(`id`,`name`,`fi`,`socialName`,`contact`,`street`,`city`,`postcode`,`phone`,`mobile`,`isRelevant`,`email`,`iban`,`dueDay`,`accountingAccount`,`isEqualizated`,`provinceFk`,`hasToInvoice`,`credit`,`countryFk`,`isActive`,`gestdocFk`,`quality`,`payMethodFk`,`created`,`isToBeMailed`,`contactChannelFk`,`hasSepaVnl`,`hasCoreVnl`,`hasCoreVnh`,`riskCalculated`, `hasToInvoiceByAddress`,`isTaxDataChecked`,`isFreezed`,`creditInsurance`,`isCreatedAsServed`,`hasInvoiceSimplified`,`salesPersonFk`,`isVies`,`businessTypeFk`,`typeFk`)
|
INSERT INTO `vn`.`client`(`id`,`name`,`fi`,`socialName`,`contact`,`street`,`city`,`postcode`,`phone`,`mobile`,`isRelevant`,`email`,`iban`,`dueDay`,`accountingAccount`,`isEqualizated`,`provinceFk`,`hasToInvoice`,`credit`,`countryFk`,`isActive`,`quality`,`payMethodFk`,`created`,`isToBeMailed`,`contactChannelFk`,`hasSepaVnl`,`hasCoreVnl`,`hasCoreVnh`,`riskCalculated`, `hasToInvoiceByAddress`,`isTaxDataChecked`,`isFreezed`,`creditInsurance`,`isCreatedAsServed`,`hasInvoiceSimplified`,`salesPersonFk`,`isVies`,`businessTypeFk`,`typeFk`)
|
||||||
VALUES
|
VALUES
|
||||||
(1101, 'Bruce Wayne', '84612325V', 'BATMAN', 'Alfred', '1007 MOUNTAIN DRIVE, GOTHAM', 'Gotham', 46460, 1111111111, 222222222, 1, 'BruceWayne@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, NULL, 0, 0, 18, 0, 'florist','normal'),
|
(1101, 'Bruce Wayne', '84612325V', 'BATMAN', 'Alfred', '1007 MOUNTAIN DRIVE, GOTHAM', 'Gotham', 46460, 1111111111, 222222222, 1, 'BruceWayne@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, NULL, 0, 0, 18, 0, 'florist','normal'),
|
||||||
(1102, 'Petter Parker', '87945234L', 'SPIDER MAN', 'Aunt May', '20 INGRAM STREET, QUEENS, USA', 'Gotham', 46460, 1111111111, 222222222, 1, 'PetterParker@mydomain.com', NULL, 0, 1234567890, 0, 2, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, NULL, 0, 0, 18, 0, 'florist','normal'),
|
(1102, 'Petter Parker', '87945234L', 'SPIDER MAN', 'Aunt May', '20 INGRAM STREET, QUEENS, USA', 'Gotham', 46460, 1111111111, 222222222, 1, 'PetterParker@mydomain.com', NULL, 0, 1234567890, 0, 2, 1, 300, 1, 1, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, NULL, 0, 0, 18, 0, 'florist','normal'),
|
||||||
(1103, 'Clark Kent', '06815934E', 'SUPER MAN', 'lois lane', '344 CLINTON STREET, APARTAMENT 3-D', 'Gotham', 46460, 1111111111, 222222222, 1, 'ClarkKent@mydomain.com', NULL, 0, 1234567890, 0, 3, 1, 0, 19, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, NULL, 0, 0, 18, 0, 'florist','normal'),
|
(1103, 'Clark Kent', '06815934E', 'SUPER MAN', 'lois lane', '344 CLINTON STREET, APARTAMENT 3-D', 'Gotham', 46460, 1111111111, 222222222, 1, 'ClarkKent@mydomain.com', NULL, 0, 1234567890, 0, 3, 1, 0, 19, 1, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, NULL, 0, 0, 18, 0, 'florist','normal'),
|
||||||
(1104, 'Tony Stark', '06089160W', 'IRON MAN', 'Pepper Potts', '10880 MALIBU POINT, 90265', 'Gotham', 46460, 1111111111, 222222222, 1, 'TonyStark@mydomain.com', NULL, 0, 1234567890, 0, 2, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, NULL, 0, 0, 18, 0, 'florist','normal'),
|
(1104, 'Tony Stark', '06089160W', 'IRON MAN', 'Pepper Potts', '10880 MALIBU POINT, 90265', 'Gotham', 46460, 1111111111, 222222222, 1, 'TonyStark@mydomain.com', NULL, 0, 1234567890, 0, 2, 1, 300, 1, 1, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, NULL, 0, 0, 18, 0, 'florist','normal'),
|
||||||
(1105, 'Max Eisenhardt', '251628698', 'MAGNETO', 'Rogue', 'UNKNOWN WHEREABOUTS', 'Gotham', 46460, 1111111111, 222222222, 1, 'MaxEisenhardt@mydomain.com', NULL, 0, 1234567890, 0, 3, 1, 300, 8, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, NULL, 0, 0, 18, 0, 'florist','normal'),
|
(1105, 'Max Eisenhardt', '251628698', 'MAGNETO', 'Rogue', 'UNKNOWN WHEREABOUTS', 'Gotham', 46460, 1111111111, 222222222, 1, 'MaxEisenhardt@mydomain.com', NULL, 0, 1234567890, 0, 3, 1, 300, 8, 1, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, NULL, 0, 0, 18, 0, 'florist','normal'),
|
||||||
(1106, 'DavidCharlesHaller', '53136686Q', 'LEGION', 'Charles Xavier', 'CITY OF NEW YORK, NEW YORK, USA', 'Gotham', 46460, 1111111111, 222222222, 1, 'DavidCharlesHaller@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 0, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, NULL, 0, 0, 19, 0, 'florist','normal'),
|
(1106, 'DavidCharlesHaller', '53136686Q', 'LEGION', 'Charles Xavier', 'CITY OF NEW YORK, NEW YORK, USA', 'Gotham', 46460, 1111111111, 222222222, 1, 'DavidCharlesHaller@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 0, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, NULL, 0, 0, 19, 0, 'florist','normal'),
|
||||||
(1107, 'Hank Pym', '09854837G', 'ANT MAN', 'Hawk', 'ANTHILL, SAN FRANCISCO, CALIFORNIA', 'Gotham', 46460, 1111111111, 222222222, 1, 'HankPym@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 0, 0, NULL, 0, 0, 19, 0, 'florist','normal'),
|
(1107, 'Hank Pym', '09854837G', 'ANT MAN', 'Hawk', 'ANTHILL, SAN FRANCISCO, CALIFORNIA', 'Gotham', 46460, 1111111111, 222222222, 1, 'HankPym@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 0, 0, NULL, 0, 0, 19, 0, 'florist','normal'),
|
||||||
(1108, 'Charles Xavier', '22641921P', 'PROFESSOR X', 'Beast', '3800 VICTORY PKWY, CINCINNATI, OH 45207, USA', 'Gotham', 46460, 1111111111, 222222222, 1, 'CharlesXavier@mydomain.com', NULL, 0, 1234567890, 0, 5, 1, 300, 13, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, NULL, 0, 0, 19, 0, 'florist','normal'),
|
(1108, 'Charles Xavier', '22641921P', 'PROFESSOR X', 'Beast', '3800 VICTORY PKWY, CINCINNATI, OH 45207, USA', 'Gotham', 46460, 1111111111, 222222222, 1, 'CharlesXavier@mydomain.com', NULL, 0, 1234567890, 0, 5, 1, 300, 13, 1, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, NULL, 0, 0, 19, 0, 'florist','normal'),
|
||||||
(1109, 'Bruce Banner', '16104829E', 'HULK', 'Black widow', 'SOMEWHERE IN NEW YORK', 'Gotham', 46460, 1111111111, 222222222, 1, 'BruceBanner@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 0, 0, NULL, 0, 0, 9, 0, 'florist','normal'),
|
(1109, 'Bruce Banner', '16104829E', 'HULK', 'Black widow', 'SOMEWHERE IN NEW YORK', 'Gotham', 46460, 1111111111, 222222222, 1, 'BruceBanner@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 0, 0, NULL, 0, 0, 9, 0, 'florist','normal'),
|
||||||
(1110, 'Jessica Jones', '58282869H', 'JESSICA JONES', 'Luke Cage', 'NYCC 2015 POSTER', 'Gotham', 46460, 1111111111, 222222222, 1, 'JessicaJones@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, NULL, 0, 0, NULL, 1, 'florist','normal'),
|
(1110, 'Jessica Jones', '58282869H', 'JESSICA JONES', 'Luke Cage', 'NYCC 2015 POSTER', 'Gotham', 46460, 1111111111, 222222222, 1, 'JessicaJones@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 0, NULL, 0, 0, NULL, 1, 'florist','normal'),
|
||||||
(1111, 'Missing', NULL, 'MISSING MAN', 'Anton', 'THE SPACE, UNIVERSE FAR AWAY', 'Gotham', 46460, 1111111111, 222222222, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 0, 1, 0, NULL, 1, 0, NULL, 0, 'others','loses'),
|
(1111, 'Missing', NULL, 'MISSING MAN', 'Anton', 'THE SPACE, UNIVERSE FAR AWAY', 'Gotham', 46460, 1111111111, 222222222, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 0, 1, 0, NULL, 1, 0, NULL, 0, 'others','loses'),
|
||||||
(1112, 'Trash', NULL, 'GARBAGE MAN', 'Unknown name', 'NEW YORK CITY, UNDERGROUND', 'Gotham', 46460, 1111111111, 222222222, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 0, 1, 0, NULL, 1, 0, NULL, 0, 'others','loses');
|
(1112, 'Trash', NULL, 'GARBAGE MAN', 'Unknown name', 'NEW YORK CITY, UNDERGROUND', 'Gotham', 46460, 1111111111, 222222222, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, 10, 5, util.VN_CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 0, 1, 0, NULL, 1, 0, NULL, 0, 'others','loses');
|
||||||
|
|
||||||
INSERT INTO `vn`.`client`(`id`, `name`, `fi`, `socialName`, `contact`, `street`, `city`, `postcode`, `isRelevant`, `email`, `iban`,`dueDay`,`accountingAccount`, `isEqualizated`, `provinceFk`, `hasToInvoice`, `credit`, `countryFk`, `isActive`, `gestdocFk`, `quality`, `payMethodFk`,`created`, `isTaxDataChecked`)
|
INSERT INTO `vn`.`client`(`id`, `name`, `fi`, `socialName`, `contact`, `street`, `city`, `postcode`, `isRelevant`, `email`, `iban`,`dueDay`,`accountingAccount`, `isEqualizated`, `provinceFk`, `hasToInvoice`, `credit`, `countryFk`, `isActive`, `quality`, `payMethodFk`,`created`, `isTaxDataChecked`)
|
||||||
SELECT id, name, CONCAT(RPAD(CONCAT(id,9),8,id),'A'), UPPER(CONCAT(name, 'Social')), CONCAT(name, 'Contact'), CONCAT(name, 'Street'), 'GOTHAM', 46460, 1, CONCAT(name,'@mydomain.com'), NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5, util.VN_CURDATE(), 1
|
SELECT id, name, CONCAT(RPAD(CONCAT(id,9),8,id),'A'), UPPER(CONCAT(name, 'Social')), CONCAT(name, 'Contact'), CONCAT(name, 'Street'), 'GOTHAM', 46460, 1, CONCAT(name,'@mydomain.com'), NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, 10, 5, util.VN_CURDATE(), 1
|
||||||
FROM `account`.`role` `r`
|
FROM `account`.`role` `r`
|
||||||
WHERE `r`.`hasLogin` = 1;
|
WHERE `r`.`hasLogin` = 1;
|
||||||
|
|
||||||
|
@ -545,7 +546,8 @@ INSERT INTO `vn`.`observationType`(`id`,`description`, `code`)
|
||||||
(6, 'Weight', 'weight'),
|
(6, 'Weight', 'weight'),
|
||||||
(7, 'InvoiceOut', 'invoiceOut'),
|
(7, 'InvoiceOut', 'invoiceOut'),
|
||||||
(8, 'DropOff', 'dropOff'),
|
(8, 'DropOff', 'dropOff'),
|
||||||
(9, 'Sustitución', 'substitution');
|
(9, 'Sustitución', 'substitution'),
|
||||||
|
(10, 'Finance', 'finance');
|
||||||
|
|
||||||
INSERT INTO `vn`.`addressObservation`(`id`,`addressFk`,`observationTypeFk`,`description`)
|
INSERT INTO `vn`.`addressObservation`(`id`,`addressFk`,`observationTypeFk`,`description`)
|
||||||
VALUES
|
VALUES
|
||||||
|
@ -3941,6 +3943,11 @@ INSERT INTO vn.medicalReview
|
||||||
(id, workerFk, centerFk, `date`, `time`, isFit, amount, invoice, remark)
|
(id, workerFk, centerFk, `date`, `time`, isFit, amount, invoice, remark)
|
||||||
VALUES(3, 9, 2, '2000-01-01', '8:00', 1, 150.0, NULL, NULL);
|
VALUES(3, 9, 2, '2000-01-01', '8:00', 1, 150.0, NULL, NULL);
|
||||||
|
|
||||||
|
INSERT INTO vn.stockBought (workerFk, bought, reserve, dated)
|
||||||
|
VALUES(35, 1.00, 1.00, '2001-01-01');
|
||||||
|
INSERT INTO vn.auctionConfig (id,conversionCoefficient,warehouseFk)
|
||||||
|
VALUES (1,0.6,6);
|
||||||
|
|
||||||
INSERT INTO vn.payrollComponent
|
INSERT INTO vn.payrollComponent
|
||||||
(id, name, isSalaryAgreed, isVariable, isException)
|
(id, name, isSalaryAgreed, isVariable, isException)
|
||||||
VALUES
|
VALUES
|
||||||
|
@ -3982,3 +3989,25 @@ VALUES
|
||||||
INSERT IGNORE INTO ormConfig
|
INSERT IGNORE INTO ormConfig
|
||||||
SET id =1,
|
SET id =1,
|
||||||
selectLimit = 1000;
|
selectLimit = 1000;
|
||||||
|
|
||||||
|
INSERT INTO pbx.queueMultiConfig
|
||||||
|
SET id = 'ring',
|
||||||
|
strategy = 20,
|
||||||
|
timeout = 2,
|
||||||
|
retry = 0,
|
||||||
|
weight = 0,
|
||||||
|
maxLen = 0,
|
||||||
|
ringInUse = 0;
|
||||||
|
|
||||||
|
INSERT INTO pbx.queue (description, name, config)
|
||||||
|
VALUES ('X-men', '1000', 1),
|
||||||
|
('Avengers', '2000', 1);
|
||||||
|
|
||||||
|
INSERT IGNORE INTO pbx.queueMember
|
||||||
|
SET queue = '1000',
|
||||||
|
extension = '1010';
|
||||||
|
|
||||||
|
UPDATE vn.department SET pbxQueue = '1000' WHERE name = "CAMARA";
|
||||||
|
UPDATE vn.department SET pbxQueue = '2000' WHERE name = "VENTAS";
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ BEGIN
|
||||||
SELECT DISTINCT warehouseFk
|
SELECT DISTINCT warehouseFk
|
||||||
FROM orderRow
|
FROM orderRow
|
||||||
WHERE orderFk = vOrderFk
|
WHERE orderFk = vOrderFk
|
||||||
AND shipped = util.VN_CURDATE();
|
AND shipment = util.VN_CURDATE();
|
||||||
|
|
||||||
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
|
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,6 @@ BEGIN
|
||||||
DECLARE vItemFk INT;
|
DECLARE vItemFk INT;
|
||||||
DECLARE vConcept VARCHAR(30);
|
DECLARE vConcept VARCHAR(30);
|
||||||
DECLARE vAmount INT;
|
DECLARE vAmount INT;
|
||||||
DECLARE vAvailable INT;
|
|
||||||
DECLARE vPrice DECIMAL(10,2);
|
DECLARE vPrice DECIMAL(10,2);
|
||||||
DECLARE vSaleFk INT;
|
DECLARE vSaleFk INT;
|
||||||
DECLARE vRowFk INT;
|
DECLARE vRowFk INT;
|
||||||
|
@ -32,7 +31,6 @@ BEGIN
|
||||||
DECLARE vClientFk INT;
|
DECLARE vClientFk INT;
|
||||||
DECLARE vCompanyFk INT;
|
DECLARE vCompanyFk INT;
|
||||||
DECLARE vAgencyModeFk INT;
|
DECLARE vAgencyModeFk INT;
|
||||||
DECLARE vCalcFk INT;
|
|
||||||
DECLARE vIsTaxDataChecked BOOL;
|
DECLARE vIsTaxDataChecked BOOL;
|
||||||
|
|
||||||
DECLARE vDates CURSOR FOR
|
DECLARE vDates CURSOR FOR
|
||||||
|
@ -98,22 +96,8 @@ BEGIN
|
||||||
SELECT employeeFk INTO vUserFk FROM orderConfig;
|
SELECT employeeFk INTO vUserFk FROM orderConfig;
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
START TRANSACTION;
|
|
||||||
|
|
||||||
CALL order_checkEditable(vSelf);
|
|
||||||
|
|
||||||
CALL orderRow_updateOverstocking(vSelf);
|
CALL orderRow_updateOverstocking(vSelf);
|
||||||
|
|
||||||
-- Check order is not empty
|
|
||||||
SELECT COUNT(*) > 0 INTO vHasRows
|
|
||||||
FROM orderRow
|
|
||||||
WHERE orderFk = vSelf
|
|
||||||
AND amount > 0;
|
|
||||||
|
|
||||||
IF NOT vHasRows THEN
|
|
||||||
CALL util.throw('ORDER_EMPTY');
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
-- Check if any product has a quantity of 0
|
-- Check if any product has a quantity of 0
|
||||||
SELECT EXISTS (
|
SELECT EXISTS (
|
||||||
SELECT id
|
SELECT id
|
||||||
|
@ -123,7 +107,21 @@ BEGIN
|
||||||
) INTO vHas0Amount;
|
) INTO vHas0Amount;
|
||||||
|
|
||||||
IF vHas0Amount THEN
|
IF vHas0Amount THEN
|
||||||
CALL util.throw('Remove lines with quantity = 0 before confirming');
|
CALL util.throw('Hay líneas vacías. Por favor, elimínelas');
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
START TRANSACTION;
|
||||||
|
|
||||||
|
CALL order_checkEditable(vSelf);
|
||||||
|
|
||||||
|
-- Check order is not empty
|
||||||
|
SELECT COUNT(*) > 0 INTO vHasRows
|
||||||
|
FROM orderRow
|
||||||
|
WHERE orderFk = vSelf
|
||||||
|
AND amount > 0;
|
||||||
|
|
||||||
|
IF NOT vHasRows THEN
|
||||||
|
CALL util.throw('ORDER_EMPTY');
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
-- Crea los tickets del pedido
|
-- Crea los tickets del pedido
|
||||||
|
|
|
@ -4,7 +4,7 @@ CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `hedera`.`orderRow_afterIns
|
||||||
FOR EACH ROW
|
FOR EACH ROW
|
||||||
BEGIN
|
BEGIN
|
||||||
UPDATE `order`
|
UPDATE `order`
|
||||||
SET rowUpdated = NOW()
|
SET rowUpdated = util.VN_NOW()
|
||||||
WHERE id = NEW.orderFk;
|
WHERE id = NEW.orderFk;
|
||||||
END$$
|
END$$
|
||||||
DELIMITER ;
|
DELIMITER ;
|
|
@ -23,6 +23,13 @@ BEGIN
|
||||||
DELETE FROM messageInbox WHERE sendDate < v2Months;
|
DELETE FROM messageInbox WHERE sendDate < v2Months;
|
||||||
DELETE FROM messageInbox WHERE sendDate < v2Months;
|
DELETE FROM messageInbox WHERE sendDate < v2Months;
|
||||||
DELETE FROM workerTimeControl WHERE timed < v4Years;
|
DELETE FROM workerTimeControl WHERE timed < v4Years;
|
||||||
|
DELETE FROM itemShelvingSale
|
||||||
|
WHERE itemShelvingFk IN (
|
||||||
|
SELECT id
|
||||||
|
FROM itemShelving
|
||||||
|
WHERE created < util.VN_CURDATE()
|
||||||
|
AND visible = 0
|
||||||
|
);
|
||||||
DELETE FROM itemShelving WHERE created < util.VN_CURDATE() AND visible = 0;
|
DELETE FROM itemShelving WHERE created < util.VN_CURDATE() AND visible = 0;
|
||||||
DELETE FROM ticketDown WHERE created < util.yesterday();
|
DELETE FROM ticketDown WHERE created < util.yesterday();
|
||||||
DELETE IGNORE FROM expedition WHERE created < v26Months;
|
DELETE IGNORE FROM expedition WHERE created < v26Months;
|
||||||
|
|
|
@ -45,6 +45,12 @@ BEGIN
|
||||||
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
|
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
|
||||||
-- Si hay colecciones sin terminar, sale del proceso
|
-- Si hay colecciones sin terminar, sale del proceso
|
||||||
|
|
||||||
|
DECLARE EXIT HANDLER FOR SQLEXCEPTION
|
||||||
|
BEGIN
|
||||||
|
ROLLBACK;
|
||||||
|
RESIGNAL;
|
||||||
|
END;
|
||||||
|
|
||||||
CALL collection_get(vUserFk);
|
CALL collection_get(vUserFk);
|
||||||
|
|
||||||
SELECT (pc.maxNotReadyCollections - COUNT(*)) <= 0, pc.maxNotAssignedCollectionLifeTime
|
SELECT (pc.maxNotReadyCollections - COUNT(*)) <= 0, pc.maxNotAssignedCollectionLifeTime
|
||||||
|
@ -118,9 +124,19 @@ BEGIN
|
||||||
IF vCollectionFk IS NULL THEN
|
IF vCollectionFk IS NULL THEN
|
||||||
CALL collection_new(vUserFk, vCollectionFk);
|
CALL collection_new(vUserFk, vCollectionFk);
|
||||||
|
|
||||||
UPDATE `collection`
|
START TRANSACTION;
|
||||||
SET workerFk = vUserFk
|
|
||||||
WHERE id = vCollectionFk;
|
SELECT workerFk INTO vCollectionWorker
|
||||||
|
FROM `collection`
|
||||||
|
WHERE id = vCollectionFk FOR UPDATE;
|
||||||
|
|
||||||
|
IF vCollectionWorker IS NULL THEN
|
||||||
|
UPDATE `collection`
|
||||||
|
SET workerFk = vUserFk
|
||||||
|
WHERE id = vCollectionFk;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
END IF;
|
END IF;
|
||||||
END$$
|
END$$
|
||||||
DELIMITER ;
|
DELIMITER ;
|
|
@ -5,100 +5,139 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`collection_getAssigne
|
||||||
)
|
)
|
||||||
BEGIN
|
BEGIN
|
||||||
/**
|
/**
|
||||||
* Comprueba si existen colecciones libres que se ajustan al perfil del usuario
|
* Comprueba si existen colecciones libres que se ajustan
|
||||||
* y le asigna la más antigua.
|
* al perfil del usuario y le asigna la más antigua.
|
||||||
* Añade un registro al semillero de colecciones y hace la reserva para la colección
|
* Añade un registro al semillero de colecciones.
|
||||||
*
|
*
|
||||||
* @param vUserFk Id de usuario
|
* @param vUserFk Id de usuario
|
||||||
* @param vCollectionFk Id de colección
|
* @param vCollectionFk Id de colección
|
||||||
*/
|
*/
|
||||||
DECLARE vHasTooMuchCollections BOOL;
|
DECLARE vHasTooMuchCollections BOOL;
|
||||||
DECLARE vItemPackingTypeFk VARCHAR(1);
|
DECLARE vDone BOOL DEFAULT FALSE;
|
||||||
DECLARE vWarehouseFk INT;
|
DECLARE vCollectionWorker INT;
|
||||||
DECLARE vLockName VARCHAR(215);
|
DECLARE vMaxNotAssignedCollectionLifeTime TIME;
|
||||||
DECLARE vLockTime INT DEFAULT 30;
|
|
||||||
|
DECLARE vCollections CURSOR FOR
|
||||||
|
WITH collections AS (
|
||||||
|
SELECT tc.collectionFk,
|
||||||
|
SUM(sv.volume) volume,
|
||||||
|
c.saleTotalCount,
|
||||||
|
c.itemPackingTypeFk,
|
||||||
|
c.trainFk,
|
||||||
|
c.warehouseFk,
|
||||||
|
c.wagons
|
||||||
|
FROM vn.ticketCollection tc
|
||||||
|
JOIN vn.collection c ON c.id = tc.collectionFk
|
||||||
|
JOIN vn.saleVolume sv ON sv.ticketFk = tc.ticketFk
|
||||||
|
WHERE c.workerFk IS NULL
|
||||||
|
AND sv.shipped >= util.VN_CURDATE()
|
||||||
|
GROUP BY tc.collectionFk
|
||||||
|
) SELECT c.collectionFk
|
||||||
|
FROM collections c
|
||||||
|
JOIN vn.operator o
|
||||||
|
WHERE o.workerFk = vUserFk
|
||||||
|
AND (c.saleTotalCount <= o.linesLimit OR o.linesLimit IS NULL)
|
||||||
|
AND (c.itemPackingTypeFk = o.itemPackingTypeFk OR o.itemPackingTypeFk IS NULL)
|
||||||
|
AND o.numberOfWagons = c.wagons
|
||||||
|
AND o.trainFk = c.trainFk
|
||||||
|
AND o.warehouseFk = c.warehouseFk;
|
||||||
|
|
||||||
|
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
|
||||||
|
-- Si hay colecciones sin terminar, sale del proceso
|
||||||
|
|
||||||
DECLARE EXIT HANDLER FOR SQLEXCEPTION
|
DECLARE EXIT HANDLER FOR SQLEXCEPTION
|
||||||
BEGIN
|
BEGIN
|
||||||
IF vLockName IS NOT NULL THEN
|
ROLLBACK;
|
||||||
DO RELEASE_LOCK(vLockName);
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
RESIGNAL;
|
RESIGNAL;
|
||||||
END;
|
END;
|
||||||
|
|
||||||
-- Si hay colecciones sin terminar, sale del proceso
|
|
||||||
CALL collection_get(vUserFk);
|
CALL collection_get(vUserFk);
|
||||||
|
|
||||||
SELECT (pc.maxNotReadyCollections - COUNT(*)) <= 0,
|
SELECT (pc.maxNotReadyCollections - COUNT(*)) <= 0, pc.maxNotAssignedCollectionLifeTime
|
||||||
pc.collection_assign_lockname
|
INTO vHasTooMuchCollections, vMaxNotAssignedCollectionLifeTime
|
||||||
INTO vHasTooMuchCollections,
|
FROM productionConfig pc
|
||||||
vLockName
|
LEFT JOIN tmp.collection ON TRUE;
|
||||||
FROM tmp.collection c
|
|
||||||
JOIN productionConfig pc;
|
|
||||||
|
|
||||||
DROP TEMPORARY TABLE tmp.collection;
|
DROP TEMPORARY TABLE tmp.collection;
|
||||||
|
|
||||||
IF vHasTooMuchCollections THEN
|
IF vHasTooMuchCollections THEN
|
||||||
CALL util.throw('There are pending collections');
|
CALL util.throw('Hay colecciones pendientes');
|
||||||
END IF;
|
|
||||||
|
|
||||||
SELECT warehouseFk, itemPackingTypeFk
|
|
||||||
INTO vWarehouseFk, vItemPackingTypeFk
|
|
||||||
FROM operator
|
|
||||||
WHERE workerFk = vUserFk;
|
|
||||||
|
|
||||||
SET vLockName = CONCAT_WS('/',
|
|
||||||
vLockName,
|
|
||||||
vWarehouseFk,
|
|
||||||
vItemPackingTypeFk
|
|
||||||
);
|
|
||||||
|
|
||||||
IF NOT GET_LOCK(vLockName, vLockTime) THEN
|
|
||||||
CALL util.throw(CONCAT('Cannot get lock: ', vLockName));
|
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
-- Se eliminan las colecciones sin asignar que estan obsoletas
|
-- Se eliminan las colecciones sin asignar que estan obsoletas
|
||||||
INSERT INTO ticketTracking(stateFk, ticketFk)
|
|
||||||
SELECT s.id, tc.ticketFk
|
|
||||||
FROM collection c
|
|
||||||
JOIN ticketCollection tc ON tc.collectionFk = c.id
|
|
||||||
JOIN state s ON s.code = 'PRINTED_AUTO'
|
|
||||||
JOIN productionConfig pc
|
|
||||||
WHERE c.workerFk IS NULL
|
|
||||||
AND TIMEDIFF(util.VN_NOW(), c.created) > pc.maxNotAssignedCollectionLifeTime;
|
|
||||||
|
|
||||||
DELETE c
|
INSERT INTO ticketTracking(stateFk, ticketFk)
|
||||||
FROM collection c
|
SELECT s.id, tc.ticketFk
|
||||||
JOIN productionConfig pc
|
FROM `collection` c
|
||||||
WHERE c.workerFk IS NULL
|
JOIN ticketCollection tc ON tc.collectionFk = c.id
|
||||||
AND TIMEDIFF(util.VN_NOW(), c.created) > pc.maxNotAssignedCollectionLifeTime;
|
JOIN `state` s ON s.code = 'PRINTED_AUTO'
|
||||||
|
WHERE c.workerFk IS NULL
|
||||||
|
AND TIMEDIFF(util.VN_NOW(), c.created) > vMaxNotAssignedCollectionLifeTime;
|
||||||
|
|
||||||
|
DELETE FROM `collection`
|
||||||
|
WHERE workerFk IS NULL
|
||||||
|
AND TIMEDIFF(util.VN_NOW(), created) > vMaxNotAssignedCollectionLifeTime;
|
||||||
|
|
||||||
-- Se añade registro al semillero
|
-- Se añade registro al semillero
|
||||||
INSERT INTO collectionHotbed
|
|
||||||
SET userFk = vUserFk;
|
INSERT INTO collectionHotbed(userFk) VALUES(vUserFk);
|
||||||
|
|
||||||
-- Comprueba si hay colecciones disponibles que se ajustan a su configuracion
|
-- Comprueba si hay colecciones disponibles que se ajustan a su configuracion
|
||||||
SELECT MIN(c.id) INTO vCollectionFk
|
|
||||||
FROM collection c
|
OPEN vCollections;
|
||||||
JOIN operator o ON (o.itemPackingTypeFk = c.itemPackingTypeFk
|
l: LOOP
|
||||||
OR c.itemPackingTypeFk IS NULL)
|
SET vDone = FALSE;
|
||||||
AND o.numberOfWagons = c.wagons
|
FETCH vCollections INTO vCollectionFk;
|
||||||
AND o.trainFk = c.trainFk
|
|
||||||
AND o.warehouseFk = c.warehouseFk
|
IF vDone THEN
|
||||||
AND c.workerFk IS NULL
|
LEAVE l;
|
||||||
WHERE o.workerFk = vUserFk;
|
END IF;
|
||||||
|
|
||||||
|
BEGIN
|
||||||
|
DECLARE EXIT HANDLER FOR SQLEXCEPTION
|
||||||
|
BEGIN
|
||||||
|
ROLLBACK;
|
||||||
|
SET vCollectionFk = NULL;
|
||||||
|
RESIGNAL;
|
||||||
|
END;
|
||||||
|
|
||||||
|
START TRANSACTION;
|
||||||
|
|
||||||
|
SELECT workerFk INTO vCollectionWorker
|
||||||
|
FROM `collection`
|
||||||
|
WHERE id = vCollectionFk FOR UPDATE;
|
||||||
|
|
||||||
|
IF vCollectionWorker IS NULL THEN
|
||||||
|
UPDATE `collection`
|
||||||
|
SET workerFk = vUserFk
|
||||||
|
WHERE id = vCollectionFk;
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
LEAVE l;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
ROLLBACK;
|
||||||
|
END;
|
||||||
|
END LOOP;
|
||||||
|
CLOSE vCollections;
|
||||||
|
|
||||||
IF vCollectionFk IS NULL THEN
|
IF vCollectionFk IS NULL THEN
|
||||||
CALL collection_new(vUserFk, vCollectionFk);
|
CALL collection_new(vUserFk, vCollectionFk);
|
||||||
|
|
||||||
|
START TRANSACTION;
|
||||||
|
|
||||||
|
SELECT workerFk INTO vCollectionWorker
|
||||||
|
FROM `collection`
|
||||||
|
WHERE id = vCollectionFk FOR UPDATE;
|
||||||
|
|
||||||
|
IF vCollectionWorker IS NULL THEN
|
||||||
|
UPDATE `collection`
|
||||||
|
SET workerFk = vUserFk
|
||||||
|
WHERE id = vCollectionFk;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
UPDATE collection
|
|
||||||
SET workerFk = vUserFk
|
|
||||||
WHERE id = vCollectionFk;
|
|
||||||
|
|
||||||
CALL itemShelvingSale_addByCollection(vCollectionFk);
|
CALL itemShelvingSale_addByCollection(vCollectionFk);
|
||||||
|
|
||||||
DO RELEASE_LOCK(vLockName);
|
|
||||||
END$$
|
END$$
|
||||||
DELIMITER ;
|
DELIMITER ;
|
|
@ -45,7 +45,7 @@ BEGIN
|
||||||
LEFT JOIN observation ob ON ob.ticketFk = t.id
|
LEFT JOIN observation ob ON ob.ticketFk = t.id
|
||||||
WHERE t.id = vParamFk
|
WHERE t.id = vParamFk
|
||||||
AND t.shipped >= vYesterday
|
AND t.shipped >= vYesterday
|
||||||
UNION ALL
|
UNION
|
||||||
SELECT t.id ticketFk,
|
SELECT t.id ticketFk,
|
||||||
IF(NOT(vItemPackingTypeFk <=> 'V'), cc.code, CONCAT(SUBSTRING('ABCDEFGH', tc.wagon, 1), '-', tc.`level`)) `level`,
|
IF(NOT(vItemPackingTypeFk <=> 'V'), cc.code, CONCAT(SUBSTRING('ABCDEFGH', tc.wagon, 1), '-', tc.`level`)) `level`,
|
||||||
am.name agencyName,
|
am.name agencyName,
|
||||||
|
@ -66,7 +66,7 @@ BEGIN
|
||||||
LEFT JOIN vn.worker w ON w.id = c.salesPersonFk
|
LEFT JOIN vn.worker w ON w.id = c.salesPersonFk
|
||||||
LEFT JOIN observation ob ON ob.ticketFk = t.id
|
LEFT JOIN observation ob ON ob.ticketFk = t.id
|
||||||
WHERE tc.collectionFk = vParamFk
|
WHERE tc.collectionFk = vParamFk
|
||||||
UNION ALL
|
UNION
|
||||||
SELECT sg.ticketFk,
|
SELECT sg.ticketFk,
|
||||||
NULL `level`,
|
NULL `level`,
|
||||||
am.name agencyName,
|
am.name agencyName,
|
||||||
|
@ -83,6 +83,7 @@ BEGIN
|
||||||
LEFT JOIN observation ob ON ob.ticketFk = t.id
|
LEFT JOIN observation ob ON ob.ticketFk = t.id
|
||||||
LEFT JOIN vn.client c ON c.id = t.clientFk
|
LEFT JOIN vn.client c ON c.id = t.clientFk
|
||||||
WHERE sc.id = vParamFk
|
WHERE sc.id = vParamFk
|
||||||
AND t.shipped >= vYesterday;
|
AND t.shipped >= vYesterday
|
||||||
|
GROUP BY ticketFk;
|
||||||
END$$
|
END$$
|
||||||
DELIMITER ;
|
DELIMITER ;
|
||||||
|
|
|
@ -5,22 +5,26 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`expeditionPallet_buil
|
||||||
vWorkerFk INT,
|
vWorkerFk INT,
|
||||||
OUT vPalletFk INT
|
OUT vPalletFk INT
|
||||||
)
|
)
|
||||||
BEGIN
|
proc: BEGIN
|
||||||
/** Construye un pallet de expediciones.
|
/**
|
||||||
|
* Builds an expedition pallet.
|
||||||
*
|
*
|
||||||
* Primero comprueba si esas expediciones ya pertenecen a otro pallet,
|
* First, it checks if these expeditions already belong to another pallet,
|
||||||
* en cuyo caso actualiza ese pallet.
|
* in which case it returns an error.
|
||||||
*
|
*
|
||||||
* @param vExpeditions JSON_ARRAY con esta estructura [exp1, exp2, exp3, ...]
|
* @param vExpeditions JSON_ARRAY with this structure [exp1, exp2, exp3, ...]
|
||||||
* @param vArcId INT Identificador de arcRead
|
* @param vArcId INT Identifier of arcRead
|
||||||
* @param vWorkerFk INT Identificador de worker
|
* @param vWorkerFk INT Identifier of worker
|
||||||
* @param out vPalletFk Identificador de expeditionPallet
|
* @param out vPalletFk Identifier of expeditionPallet
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DECLARE vCounter INT;
|
DECLARE vCounter INT;
|
||||||
DECLARE vExpeditionFk INT;
|
DECLARE vExpeditionFk INT;
|
||||||
DECLARE vTruckFk INT;
|
DECLARE vTruckFk INT;
|
||||||
DECLARE vPrinterFk INT;
|
DECLARE vPrinterFk INT;
|
||||||
DECLARE vExpeditionStateTypeFk INT;
|
DECLARE vExpeditionStateTypeFk INT;
|
||||||
|
DECLARE vFreeExpeditionCount INT;
|
||||||
|
DECLARE vExpeditionWithPallet INT;
|
||||||
|
|
||||||
CREATE OR REPLACE TEMPORARY TABLE tExpedition (
|
CREATE OR REPLACE TEMPORARY TABLE tExpedition (
|
||||||
expeditionFk INT,
|
expeditionFk INT,
|
||||||
|
@ -44,48 +48,63 @@ BEGIN
|
||||||
WHERE e.id = vExpeditionFk;
|
WHERE e.id = vExpeditionFk;
|
||||||
END WHILE;
|
END WHILE;
|
||||||
|
|
||||||
SELECT palletFk INTO vPalletFk
|
SELECT COUNT(expeditionFk) INTO vFreeExpeditionCount
|
||||||
FROM (
|
FROM tExpedition
|
||||||
SELECT palletFk, count(*) n
|
WHERE palletFk IS NULL;
|
||||||
FROM tExpedition
|
|
||||||
WHERE palletFk > 0
|
|
||||||
GROUP BY palletFk
|
|
||||||
ORDER BY n DESC
|
|
||||||
LIMIT 100
|
|
||||||
) sub
|
|
||||||
LIMIT 1;
|
|
||||||
|
|
||||||
IF vPalletFk IS NULL THEN
|
SELECT COUNT(expeditionFk) INTO vExpeditionWithPallet
|
||||||
SELECT roadmapStopFk INTO vTruckFk
|
FROM tExpedition
|
||||||
FROM (
|
WHERE palletFk;
|
||||||
SELECT rm.roadmapStopFk, count(*) n
|
|
||||||
FROM routesMonitor rm
|
|
||||||
JOIN tExpedition e ON e.routeFk = rm.routeFk
|
|
||||||
GROUP BY roadmapStopFk
|
|
||||||
ORDER BY n DESC
|
|
||||||
LIMIT 1
|
|
||||||
) sub;
|
|
||||||
|
|
||||||
IF vTruckFk IS NULL THEN
|
IF vExpeditionWithPallet THEN
|
||||||
CALL util.throw ('TRUCK_NOT_AVAILABLE');
|
UPDATE arcRead
|
||||||
END IF;
|
SET error = (
|
||||||
|
SELECT GROUP_CONCAT(expeditionFk SEPARATOR ', ')
|
||||||
INSERT INTO expeditionPallet SET truckFk = vTruckFk;
|
FROM tExpedition
|
||||||
|
WHERE palletFk
|
||||||
SET vPalletFk = LAST_INSERT_ID();
|
)
|
||||||
|
WHERE id = vArcId;
|
||||||
|
LEAVE proc;
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
|
IF NOT vFreeExpeditionCount THEN
|
||||||
|
CALL util.throw ('NO_FREE_EXPEDITIONS');
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
SELECT roadmapStopFk INTO vTruckFk
|
||||||
|
FROM (
|
||||||
|
SELECT rm.roadmapStopFk, count(*) n
|
||||||
|
FROM routesMonitor rm
|
||||||
|
JOIN tExpedition e ON e.routeFk = rm.routeFk
|
||||||
|
WHERE e.palletFk IS NULL
|
||||||
|
GROUP BY roadmapStopFk
|
||||||
|
ORDER BY n DESC
|
||||||
|
LIMIT 1
|
||||||
|
) sub;
|
||||||
|
|
||||||
|
IF vTruckFk IS NULL THEN
|
||||||
|
CALL util.throw ('TRUCK_NOT_AVAILABLE');
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
INSERT INTO expeditionPallet SET truckFk = vTruckFk;
|
||||||
|
|
||||||
|
SET vPalletFk = LAST_INSERT_ID();
|
||||||
|
|
||||||
INSERT INTO expeditionScan(expeditionFk, palletFk, workerFk)
|
INSERT INTO expeditionScan(expeditionFk, palletFk, workerFk)
|
||||||
SELECT expeditionFk, vPalletFk, vWorkerFk
|
SELECT expeditionFk, vPalletFk, vWorkerFk
|
||||||
FROM tExpedition
|
FROM tExpedition
|
||||||
ON DUPLICATE KEY UPDATE palletFk = vPalletFk, workerFk = vWorkerFk;
|
WHERE palletFk IS NULL;
|
||||||
|
|
||||||
SELECT id INTO vExpeditionStateTypeFk
|
SELECT id INTO vExpeditionStateTypeFk
|
||||||
FROM expeditionStateType
|
FROM expeditionStateType
|
||||||
WHERE code = 'PALLETIZED';
|
WHERE code = 'PALLETIZED';
|
||||||
|
|
||||||
INSERT INTO expeditionState(expeditionFk, typeFk)
|
INSERT INTO expeditionState(expeditionFk, typeFk)
|
||||||
SELECT expeditionFk, vExpeditionStateTypeFk FROM tExpedition;
|
SELECT expeditionFk, vExpeditionStateTypeFk
|
||||||
|
FROM tExpedition
|
||||||
|
WHERE palletFk IS NULL;
|
||||||
|
|
||||||
|
UPDATE arcRead SET error = NULL WHERE id = vArcId;
|
||||||
|
|
||||||
SELECT printerFk INTO vPrinterFk FROM arcRead WHERE id = vArcId;
|
SELECT printerFk INTO vPrinterFk FROM arcRead WHERE id = vArcId;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`itemShelvingSale_deleteAdded`(
|
||||||
|
vSelf INT(11)
|
||||||
|
)
|
||||||
|
proc: BEGIN
|
||||||
|
/**
|
||||||
|
* Borra una reservea devolviendo la cantidad al itemShelving
|
||||||
|
*
|
||||||
|
* @param vSelf Identificador del itemShelvingSale
|
||||||
|
*/
|
||||||
|
DECLARE vSaleFk INT;
|
||||||
|
DECLARE vHasSalesPicked BOOL;
|
||||||
|
|
||||||
|
DECLARE EXIT HANDLER FOR SQLEXCEPTION
|
||||||
|
BEGIN
|
||||||
|
ROLLBACK;
|
||||||
|
RESIGNAL;
|
||||||
|
END;
|
||||||
|
|
||||||
|
START TRANSACTION;
|
||||||
|
|
||||||
|
SELECT iss.saleFk INTO vSaleFk
|
||||||
|
FROM itemShelvingSale iss
|
||||||
|
JOIN sale s ON s.id = iss.saleFk
|
||||||
|
WHERE iss.id = vSelf AND s.isAdded
|
||||||
|
FOR UPDATE;
|
||||||
|
|
||||||
|
IF vSaleFk IS NULL THEN
|
||||||
|
CALL util.throw('The sale can not be deleted');
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
SELECT COUNT(*) INTO vHasSalesPicked
|
||||||
|
FROM itemShelvingSale
|
||||||
|
WHERE saleFk = vSaleFk AND isPicked;
|
||||||
|
|
||||||
|
IF vHasSalesPicked THEN
|
||||||
|
CALL util.throw('A sale with picked sales cannot be deleted');
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
UPDATE itemShelvingSale iss
|
||||||
|
JOIN itemShelving ish ON ish.id = iss.itemShelvingFk
|
||||||
|
SET ish.available = ish.available + iss.quantity
|
||||||
|
WHERE iss.saleFk = vSaleFk;
|
||||||
|
|
||||||
|
DELETE FROM sale WHERE id = vSaleFk;
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -8,17 +8,18 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`item_getSimilar`(
|
||||||
)
|
)
|
||||||
BEGIN
|
BEGIN
|
||||||
/**
|
/**
|
||||||
* Propone articulos ordenados, con la cantidad
|
* Propone articulos ordenados, con la cantidad
|
||||||
* de veces usado y segun sus caracteristicas.
|
* de veces usado y segun sus caracteristicas.
|
||||||
*
|
*
|
||||||
* @param vSelf Id de artículo
|
* @param vSelf Id de artículo
|
||||||
* @param vWarehouseFk Id de almacen
|
* @param vWarehouseFk Id de almacen
|
||||||
* @param vDated Fecha
|
* @param vDated Fecha
|
||||||
* @param vShowType Mostrar tipos
|
* @param vShowType Mostrar tipos
|
||||||
* @param vDaysInForward Días de alcance para las ventas
|
* @param vDaysInForward Días de alcance para las ventas (https://redmine.verdnatura.es/issues/7956#note-4)
|
||||||
*/
|
*/
|
||||||
DECLARE vAvailableCalcFk INT;
|
DECLARE vAvailableCalcFk INT;
|
||||||
DECLARE vVisibleCalcFk INT;
|
DECLARE vVisibleCalcFk INT;
|
||||||
|
DECLARE vTypeFk INT;
|
||||||
DECLARE vPriority INT DEFAULT 1;
|
DECLARE vPriority INT DEFAULT 1;
|
||||||
|
|
||||||
CALL cache.available_refresh(vAvailableCalcFk, FALSE, vWarehouseFk, vDated);
|
CALL cache.available_refresh(vAvailableCalcFk, FALSE, vWarehouseFk, vDated);
|
||||||
|
@ -42,19 +43,9 @@ BEGIN
|
||||||
AND it.priority = vPriority
|
AND it.priority = vPriority
|
||||||
LEFT JOIN vn.tag t ON t.id = it.tagFk
|
LEFT JOIN vn.tag t ON t.id = it.tagFk
|
||||||
WHERE i.id = vSelf
|
WHERE i.id = vSelf
|
||||||
),
|
|
||||||
sold AS (
|
|
||||||
SELECT SUM(s.quantity) quantity, s.itemFk
|
|
||||||
FROM vn.sale s
|
|
||||||
JOIN vn.ticket t ON t.id = s.ticketFk
|
|
||||||
LEFT JOIN vn.itemShelvingSale iss ON iss.saleFk = s.id
|
|
||||||
WHERE t.shipped >= CURDATE() + INTERVAL vDaysInForward DAY
|
|
||||||
AND iss.saleFk IS NULL
|
|
||||||
AND t.warehouseFk = vWarehouseFk
|
|
||||||
GROUP BY s.itemFk
|
|
||||||
)
|
)
|
||||||
SELECT i.id itemFk,
|
SELECT i.id itemFk,
|
||||||
LEAST(CAST(sd.quantity AS INT), v.visible) advanceable,
|
NULL advanceable, -- https://redmine.verdnatura.es/issues/7956#note-4
|
||||||
i.longName,
|
i.longName,
|
||||||
i.subName,
|
i.subName,
|
||||||
i.tag5,
|
i.tag5,
|
||||||
|
@ -79,7 +70,6 @@ BEGIN
|
||||||
v.visible located,
|
v.visible located,
|
||||||
b.price2
|
b.price2
|
||||||
FROM vn.item i
|
FROM vn.item i
|
||||||
LEFT JOIN sold sd ON sd.itemFk = i.id
|
|
||||||
JOIN cache.available a ON a.item_id = i.id
|
JOIN cache.available a ON a.item_id = i.id
|
||||||
AND a.calc_id = vAvailableCalcFk
|
AND a.calc_id = vAvailableCalcFk
|
||||||
LEFT JOIN cache.visible v ON v.item_id = i.id
|
LEFT JOIN cache.visible v ON v.item_id = i.id
|
||||||
|
@ -93,21 +83,20 @@ BEGIN
|
||||||
LEFT JOIN vn.tag t ON t.id = it.tagFk
|
LEFT JOIN vn.tag t ON t.id = it.tagFk
|
||||||
LEFT JOIN vn.buy b ON b.id = lb.buy_id
|
LEFT JOIN vn.buy b ON b.id = lb.buy_id
|
||||||
JOIN itemTags its
|
JOIN itemTags its
|
||||||
WHERE (a.available > 0 OR sd.quantity < v.visible)
|
WHERE a.available > 0
|
||||||
AND (i.typeFk = its.typeFk OR NOT vShowType)
|
AND (i.typeFk = its.typeFk OR NOT vShowType)
|
||||||
AND i.id <> vSelf
|
AND i.id <> vSelf
|
||||||
ORDER BY (a.available > 0) DESC,
|
ORDER BY `counter` DESC,
|
||||||
`counter` DESC,
|
(t.name = its.name) DESC,
|
||||||
(t.name = its.name) DESC,
|
(it.value = its.value) DESC,
|
||||||
(it.value = its.value) DESC,
|
(i.tag5 = its.tag5) DESC,
|
||||||
(i.tag5 = its.tag5) DESC,
|
match5 DESC,
|
||||||
match5 DESC,
|
(i.tag6 = its.tag6) DESC,
|
||||||
(i.tag6 = its.tag6) DESC,
|
match6 DESC,
|
||||||
match6 DESC,
|
(i.tag7 = its.tag7) DESC,
|
||||||
(i.tag7 = its.tag7) DESC,
|
match7 DESC,
|
||||||
match7 DESC,
|
(i.tag8 = its.tag8) DESC,
|
||||||
(i.tag8 = its.tag8) DESC,
|
match8 DESC
|
||||||
match8 DESC
|
|
||||||
LIMIT 100;
|
LIMIT 100;
|
||||||
END$$
|
END$$
|
||||||
DELIMITER ;
|
DELIMITER ;
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
DELIMITER $$
|
||||||
|
|
||||||
|
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`queueMember_updateQueue`(
|
||||||
|
vBusinessFk INT
|
||||||
|
)
|
||||||
|
BEGIN
|
||||||
|
/**
|
||||||
|
* Elimina la entrada de la cola anterior y luego inserta la nueva para un trabajador.
|
||||||
|
*
|
||||||
|
* @param vBusinessFk ID del negocio
|
||||||
|
*/
|
||||||
|
DECLARE vNewQueue VARCHAR(10);
|
||||||
|
DECLARE vExtension VARCHAR(10);
|
||||||
|
DECLARE exit handler FOR SQLEXCEPTION
|
||||||
|
|
||||||
|
SELECT d.pbxQueue, s.extension
|
||||||
|
INTO vNewQueue, vExtension
|
||||||
|
FROM business b
|
||||||
|
JOIN department d ON d.id = b.departmentFk
|
||||||
|
JOIN pbx.sip s ON s.user_id = b.workerFk
|
||||||
|
WHERE b.id = vBusinessFk;
|
||||||
|
|
||||||
|
DELETE FROM pbx.queueMember
|
||||||
|
WHERE extension = vExtension COLLATE utf8_general_ci;
|
||||||
|
|
||||||
|
INSERT IGNORE INTO pbx.queueMember (queue, extension)
|
||||||
|
VALUES (vNewQueue, vExtension);
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -0,0 +1,20 @@
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`saleTracking_sectorCollectionAddPrevOK`(
|
||||||
|
vSectorCollectionFk INT
|
||||||
|
)
|
||||||
|
BEGIN
|
||||||
|
/**
|
||||||
|
* Inserta los registros de sectorCollection con el estado PREVIA OK si la reserva está picked
|
||||||
|
*
|
||||||
|
* @param vSectorCollectionFk Identificador de vn.sectorCollection
|
||||||
|
*/
|
||||||
|
REPLACE saleTracking(saleFk, isChecked, workerFk, stateFk)
|
||||||
|
SELECT sgd.saleFk, TRUE, sc.userFk, s.id
|
||||||
|
FROM sectorCollection sc
|
||||||
|
JOIN sectorCollectionSaleGroup scsg ON scsg.sectorCollectionFk = sc.id
|
||||||
|
JOIN saleGroupDetail sgd ON sgd.saleGroupFk = scsg.saleGroupFk
|
||||||
|
JOIN state s ON s.code = 'OK PREVIOUS'
|
||||||
|
JOIN itemShelvingSale iss ON iss.saleFk = sgd.saleFk
|
||||||
|
WHERE sc.id = vSectorCollectionFk AND iss.isPicked;
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -40,7 +40,7 @@ BEGIN
|
||||||
isTooLittle BOOL DEFAULT FALSE,
|
isTooLittle BOOL DEFAULT FALSE,
|
||||||
isVip BOOL DEFAULT FALSE,
|
isVip BOOL DEFAULT FALSE,
|
||||||
PRIMARY KEY (ticketFk, saleFk)
|
PRIMARY KEY (ticketFk, saleFk)
|
||||||
) ENGINE = MEMORY;
|
); -- No memory
|
||||||
|
|
||||||
INSERT INTO tmp.sale_problems(ticketFk,
|
INSERT INTO tmp.sale_problems(ticketFk,
|
||||||
saleFk,
|
saleFk,
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
DELIMITER $$
|
DELIMITER $$
|
||||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`ticket_getTax`(IN vTaxArea VARCHAR(25))
|
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`ticket_getTax`(
|
||||||
|
vTaxArea VARCHAR(25)
|
||||||
|
)
|
||||||
BEGIN
|
BEGIN
|
||||||
/**
|
/**
|
||||||
* Calcula la base imponible, el IVA y el recargo de equivalencia para
|
* Calcula la base imponible, el IVA y el recargo de equivalencia para
|
||||||
|
@ -33,30 +35,39 @@ BEGIN
|
||||||
CREATE OR REPLACE TEMPORARY TABLE tmp.ticketTax
|
CREATE OR REPLACE TEMPORARY TABLE tmp.ticketTax
|
||||||
(PRIMARY KEY (ticketFk, code, rate))
|
(PRIMARY KEY (ticketFk, code, rate))
|
||||||
ENGINE = MEMORY
|
ENGINE = MEMORY
|
||||||
SELECT * FROM (
|
WITH sales AS (
|
||||||
SELECT tmpTicket.ticketFk,
|
SELECT s.ticketFk,
|
||||||
bp.pgcFk,
|
s.itemFk,
|
||||||
SUM(s.quantity * s.price * (100 - s.discount) / 100 ) taxableBase,
|
s.quantity * s.price * (100 - s.discount) / 100 total,
|
||||||
pgc.rate,
|
t.companyFk,
|
||||||
tc.code,
|
t.addressFk,
|
||||||
bp.priority
|
su.countryFk,
|
||||||
FROM tmp.ticket tmpTicket
|
ata.areaFk,
|
||||||
JOIN sale s ON s.ticketFk = tmpTicket.ticketFk
|
itc.taxClassFk
|
||||||
JOIN item i ON i.id = s.itemFk
|
FROM vn.sale s
|
||||||
JOIN ticket t ON t.id = tmpTicket.ticketFk
|
JOIN tmp.ticket tmp ON tmp.ticketFk = s.ticketFk
|
||||||
JOIN supplier su ON su.id = t.companyFk
|
JOIN vn.ticket t ON t.id = s.ticketFk
|
||||||
|
JOIN vn.supplier su ON su.id = t.companyFk
|
||||||
JOIN tmp.addressTaxArea ata ON ata.addressFk = t.addressFk
|
JOIN tmp.addressTaxArea ata ON ata.addressFk = t.addressFk
|
||||||
AND ata.companyFk = t.companyFk
|
AND ata.companyFk = t.companyFk
|
||||||
JOIN itemTaxCountry itc ON itc.itemFk = i.id
|
JOIN vn.itemTaxCountry itc ON itc.itemFk = s.itemFk
|
||||||
AND itc.countryFk = su.countryFk
|
AND itc.countryFk = su.countryFk
|
||||||
JOIN bookingPlanner bp ON bp.countryFk = su.countryFk
|
HAVING total
|
||||||
AND bp.taxAreaFk = ata.areaFk
|
)
|
||||||
AND bp.taxClassFk = itc.taxClassFk
|
SELECT s.ticketFk,
|
||||||
JOIN pgc ON pgc.code = bp.pgcFk
|
bp.pgcFk,
|
||||||
JOIN taxClass tc ON tc.id = bp.taxClassFk
|
SUM(s.total) taxableBase,
|
||||||
GROUP BY tmpTicket.ticketFk, pgc.code, pgc.rate
|
pgc.rate,
|
||||||
HAVING taxableBase
|
tc.code,
|
||||||
) t3
|
bp.priority
|
||||||
|
FROM sales s
|
||||||
|
JOIN vn.bookingPlanner bp ON bp.countryFk = s.countryFk
|
||||||
|
AND bp.taxAreaFk = s.areaFk
|
||||||
|
AND bp.taxClassFk = s.taxClassFk
|
||||||
|
JOIN vn.pgc ON pgc.code = bp.pgcFk
|
||||||
|
JOIN vn.taxClass tc ON tc.id = bp.taxClassFk
|
||||||
|
GROUP BY s.ticketFk, pgc.code, pgc.rate
|
||||||
|
HAVING taxableBase
|
||||||
ORDER BY priority;
|
ORDER BY priority;
|
||||||
|
|
||||||
CREATE OR REPLACE TEMPORARY TABLE tmp.ticketServiceTax
|
CREATE OR REPLACE TEMPORARY TABLE tmp.ticketServiceTax
|
||||||
|
|
|
@ -21,6 +21,8 @@ BEGIN
|
||||||
SET businessFk = vNewBusinessFk
|
SET businessFk = vNewBusinessFk
|
||||||
WHERE id = vSelf;
|
WHERE id = vSelf;
|
||||||
|
|
||||||
|
CALL queueMember_updateQueue(vNewBusinessFk);
|
||||||
|
|
||||||
IF vOldBusinessFk IS NULL THEN
|
IF vOldBusinessFk IS NULL THEN
|
||||||
CALL account.account_enable(vSelf);
|
CALL account.account_enable(vSelf);
|
||||||
|
|
||||||
|
|
|
@ -3,10 +3,20 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`business_afterUpdate`
|
||||||
AFTER UPDATE ON `business`
|
AFTER UPDATE ON `business`
|
||||||
FOR EACH ROW
|
FOR EACH ROW
|
||||||
BEGIN
|
BEGIN
|
||||||
|
DECLARE vIsActive BOOL;
|
||||||
|
DECLARE vExtension VARCHAR(10);
|
||||||
|
|
||||||
CALL worker_updateBusiness(NEW.workerFk);
|
CALL worker_updateBusiness(NEW.workerFk);
|
||||||
|
|
||||||
IF NOT (OLD.workerFk <=> NEW.workerFk) THEN
|
IF NOT (OLD.workerFk <=> NEW.workerFk) THEN
|
||||||
CALL worker_updateBusiness(OLD.workerFk);
|
CALL worker_updateBusiness(OLD.workerFk);
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
|
IF NOT (OLD.departmentFk <=> NEW.departmentFk) THEN
|
||||||
|
SELECT COUNT(*) INTO vIsActive FROM worker WHERE businessFk = NEW.id;
|
||||||
|
IF vIsActive THEN
|
||||||
|
CALL queueMember_updateQueue(NEW.id);
|
||||||
|
END IF;
|
||||||
|
END IF;
|
||||||
END$$
|
END$$
|
||||||
DELIMITER ;
|
DELIMITER ;
|
||||||
|
|
|
@ -3,10 +3,10 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`itemShelvingSale_afterI
|
||||||
AFTER INSERT ON `itemShelvingSale`
|
AFTER INSERT ON `itemShelvingSale`
|
||||||
FOR EACH ROW
|
FOR EACH ROW
|
||||||
BEGIN
|
BEGIN
|
||||||
|
|
||||||
UPDATE sale s
|
UPDATE sale s
|
||||||
JOIN operator o ON o.workerFk = account.myUser_getId()
|
JOIN operator o ON o.workerFk = account.myUser_getId()
|
||||||
SET s.isPicked = IF(o.isOnReservationMode, s.isPicked, TRUE)
|
JOIN sector se ON se.id = o.sectorFk
|
||||||
WHERE id = NEW.saleFk;
|
SET s.isPicked = IF(IFNULL(se.isOnReservationMode, o.isOnReservationMode), s.isPicked, TRUE)
|
||||||
|
WHERE s.id = NEW.saleFk;
|
||||||
END$$
|
END$$
|
||||||
DELIMITER ;
|
DELIMITER ;
|
|
@ -9,5 +9,8 @@ BEGIN
|
||||||
SET NEW.userFk = account.myUser_getId();
|
SET NEW.userFk = account.myUser_getId();
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
|
IF NEW.shelvingFk <> OLD.shelvingFk THEN
|
||||||
|
SET NEW.movingState = NULL;
|
||||||
|
END IF;
|
||||||
END$$
|
END$$
|
||||||
DELIMITER ;
|
DELIMITER ;
|
||||||
|
|
|
@ -22,7 +22,6 @@ AS SELECT `c`.`id` AS `id_cliente`,
|
||||||
`c`.`credit` AS `credito`,
|
`c`.`credit` AS `credito`,
|
||||||
`c`.`countryFk` AS `Id_Pais`,
|
`c`.`countryFk` AS `Id_Pais`,
|
||||||
`c`.`isActive` AS `activo`,
|
`c`.`isActive` AS `activo`,
|
||||||
`c`.`gestdocFk` AS `gestdoc_id`,
|
|
||||||
`c`.`quality` AS `calidad`,
|
`c`.`quality` AS `calidad`,
|
||||||
`c`.`payMethodFk` AS `pay_met_id`,
|
`c`.`payMethodFk` AS `pay_met_id`,
|
||||||
`c`.`created` AS `created`,
|
`c`.`created` AS `created`,
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
ALTER TABLE vn.clientObservation DROP COLUMN IF EXISTS observationTypeFk;
|
||||||
|
ALTER TABLE vn.clientObservation ADD COLUMN IF NOT EXISTS observationTypeFk TINYINT(3) UNSIGNED NULL;
|
||||||
|
ALTER TABLE vn.clientObservation ADD CONSTRAINT clientObservationTypeFk FOREIGN KEY IF NOT EXISTS (observationTypeFk) REFERENCES vn.observationType(id);
|
|
@ -0,0 +1,3 @@
|
||||||
|
INSERT IGNORE INTO vn.observationType
|
||||||
|
SET description = 'Finance',
|
||||||
|
code = 'finance';
|
|
@ -0,0 +1,3 @@
|
||||||
|
DELETE FROM salix.ACL
|
||||||
|
WHERE model = 'WorkerLog'
|
||||||
|
AND property = '*';
|
|
@ -0,0 +1,3 @@
|
||||||
|
UPDATE vn.sale
|
||||||
|
SET originalQuantity = quantity
|
||||||
|
WHERE originalQuantity IS NULL
|
|
@ -0,0 +1 @@
|
||||||
|
ALTER TABLE vn.sale MODIFY COLUMN originalQuantity decimal(10,2) DEFAULT 0.00 NOT NULL COMMENT 'Se utiliza para notificar a través de rocket los cambios de quantity';
|
|
@ -0,0 +1,3 @@
|
||||||
|
ALTER TABLE vn.itemShelving DROP FOREIGN KEY itemShelving_fk2;
|
||||||
|
ALTER TABLE vn.itemShelving ADD CONSTRAINT itemShelving_fk2
|
||||||
|
FOREIGN KEY (shelvingFk) REFERENCES vn.shelving(code) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
@ -0,0 +1,2 @@
|
||||||
|
-- Place your SQL code here
|
||||||
|
ALTER TABLE vn.itemShelving ADD IF NOT EXISTS isMoving BOOL DEFAULT FALSE NOT NULL COMMENT 'Indica que se ha marcado este registro para transferirlo a otro sector';
|
|
@ -0,0 +1,3 @@
|
||||||
|
-- Place your SQL code here
|
||||||
|
ALTER TABLE vn.itemShelving DROP COLUMN IF EXISTS isMoving;
|
||||||
|
ALTER TABLE vn.itemShelving ADD IF NOT EXISTS movingState ENUM('selected','printed') NULL;
|
|
@ -0,0 +1,3 @@
|
||||||
|
-- Place your SQL code here
|
||||||
|
ALTER TABLE hedera.`order` ADD IF NOT EXISTS rowUpdated DATETIME NULL
|
||||||
|
COMMENT 'Timestamp for last updated record in orderRow table';
|
|
@ -0,0 +1,3 @@
|
||||||
|
-- Place your SQL code here
|
||||||
|
ALTER TABLE hedera.`order` ADD IF NOT EXISTS rowUpdated DATETIME NULL
|
||||||
|
COMMENT 'Timestamp for last updated record in orderRow table';
|
|
@ -0,0 +1,2 @@
|
||||||
|
|
||||||
|
ALTER TABLE vn.sector ADD isOnReservationMode tinyint(1) DEFAULT FALSE NULL;
|
|
@ -0,0 +1,6 @@
|
||||||
|
ALTER TABLE `vn`.`operator`
|
||||||
|
ADD COLUMN `machineFk` int(11) DEFAULT NULL,
|
||||||
|
ADD CONSTRAINT `operator_machine_FK` FOREIGN KEY (`machineFk`) REFERENCES `vn`.`machine` (`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId)
|
||||||
|
VALUES ('Machine','*','*','ALLOW','ROLE','productionBoss');
|
|
@ -0,0 +1,4 @@
|
||||||
|
ALTER TABLE vn.docuwareConfig ADD IF NOT EXISTS username varchar(100) NULL;
|
||||||
|
ALTER TABLE vn.docuwareConfig ADD IF NOT EXISTS password varchar(100) NULL;
|
||||||
|
ALTER TABLE vn.docuwareConfig ADD IF NOT EXISTS token text NULL;
|
||||||
|
ALTER TABLE vn.docuwareConfig ADD IF NOT EXISTS expired int(11) NULL;
|
|
@ -0,0 +1,3 @@
|
||||||
|
-- Place your SQL code here
|
||||||
|
ALTER TABLE vn.itemShelving DROP COLUMN IF EXISTS isMoving;
|
||||||
|
ALTER TABLE vn.itemShelving ADD IF NOT EXISTS movingState ENUM('selected','printed') NULL;
|
|
@ -0,0 +1,3 @@
|
||||||
|
-- Place your SQL code here
|
||||||
|
ALTER TABLE vn.itemShelving DROP COLUMN IF EXISTS isMoving;
|
||||||
|
ALTER TABLE vn.itemShelving ADD IF NOT EXISTS movingState ENUM('selected','printed') NULL;
|
|
@ -0,0 +1,3 @@
|
||||||
|
ALTER TABLE `vn`.`ticketConfig`
|
||||||
|
ADD COLUMN `closureDaysAgo` int(11) NOT NULL DEFAULT 2 COMMENT 'Number of days to look back for ticket closure',
|
||||||
|
ADD CONSTRAINT `closureDaysAgo_check` CHECK (`closureDaysAgo` > 0);
|
|
@ -0,0 +1 @@
|
||||||
|
ALTER TABLE vn.client CHANGE gestdocFk gestdocFk__ int(11) DEFAULT NULL NULL COMMENT '@deprecated 2024-10-17';
|
|
@ -1,42 +0,0 @@
|
||||||
import selectors from '../../helpers/selectors';
|
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
describe('Client Add notes path', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
await page.loginAndModule('employee', 'client');
|
|
||||||
await page.accessToSearchResult('Bruce Banner');
|
|
||||||
await page.accessToSection('client.card.note.index');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should reach the notes index`, async() => {
|
|
||||||
await page.waitForState('client.card.note.index');
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should click on the add note button`, async() => {
|
|
||||||
await page.waitToClick(selectors.clientNotes.addNoteFloatButton);
|
|
||||||
await page.waitForState('client.card.note.create');
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should create a note`, async() => {
|
|
||||||
await page.waitForSelector(selectors.clientNotes.note);
|
|
||||||
await page.type(`${selectors.clientNotes.note} textarea`, 'Meeting with Black Widow 21st 9am');
|
|
||||||
await page.waitToClick(selectors.clientNotes.saveButton);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should confirm the note was created', async() => {
|
|
||||||
const result = await page.waitToGetProperty(selectors.clientNotes.firstNoteText, 'innerText');
|
|
||||||
|
|
||||||
expect(result).toEqual('Meeting with Black Widow 21st 9am');
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -28,12 +28,12 @@ describe('Client defaulter path', () => {
|
||||||
const salesPersonName =
|
const salesPersonName =
|
||||||
await page.waitToGetProperty(selectors.clientDefaulter.firstSalesPersonName, 'innerText');
|
await page.waitToGetProperty(selectors.clientDefaulter.firstSalesPersonName, 'innerText');
|
||||||
|
|
||||||
expect(clientName).toEqual('Bruce Banner');
|
expect(clientName).toEqual('Ororo Munroe');
|
||||||
expect(salesPersonName).toEqual('developer');
|
expect(salesPersonName).toEqual('salesperson');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should first observation not changed', async() => {
|
it('should first observation not changed', async() => {
|
||||||
const expectedObservation = 'Meeting with Black Widow 21st 9am';
|
const expectedObservation = 'Madness, as you know, is like gravity, all it takes is a little push';
|
||||||
const result = await page.waitToGetProperty(selectors.clientDefaulter.firstObservation, 'value');
|
const result = await page.waitToGetProperty(selectors.clientDefaulter.firstObservation, 'value');
|
||||||
|
|
||||||
expect(result).toContain(expectedObservation);
|
expect(result).toContain(expectedObservation);
|
||||||
|
@ -62,13 +62,4 @@ describe('Client defaulter path', () => {
|
||||||
await page.write(selectors.clientDefaulter.observation, 'My new observation');
|
await page.write(selectors.clientDefaulter.observation, 'My new observation');
|
||||||
await page.waitToClick(selectors.clientDefaulter.saveButton);
|
await page.waitToClick(selectors.clientDefaulter.saveButton);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should first observation changed', async() => {
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
await page.waitForSelector(selectors.clientDefaulter.firstObservation);
|
|
||||||
const result = await page.waitToGetProperty(selectors.clientDefaulter.firstObservation, 'value');
|
|
||||||
|
|
||||||
expect(message.text).toContain('Observation saved!');
|
|
||||||
expect(result).toContain('My new observation');
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
const $ = {
|
|
||||||
id: 'vn-order-summary vn-one:nth-child(1) > vn-label-value:nth-child(1) span',
|
|
||||||
alias: 'vn-order-summary vn-one:nth-child(1) > vn-label-value:nth-child(2) span',
|
|
||||||
consignee: 'vn-order-summary vn-one:nth-child(2) > vn-label-value:nth-child(6) span',
|
|
||||||
subtotal: 'vn-order-summary vn-one.taxes > p:nth-child(1)',
|
|
||||||
vat: 'vn-order-summary vn-one.taxes > p:nth-child(2)',
|
|
||||||
total: 'vn-order-summary vn-one.taxes > p:nth-child(3)',
|
|
||||||
sale: 'vn-order-summary vn-tbody > vn-tr',
|
|
||||||
};
|
|
||||||
|
|
||||||
describe('Order summary path', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
await page.loginAndModule('employee', 'order');
|
|
||||||
await page.accessToSearchResult('16');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should reach the order summary section and check data', async() => {
|
|
||||||
await page.waitForState('order.card.summary');
|
|
||||||
|
|
||||||
const id = await page.innerText($.id);
|
|
||||||
const alias = await page.innerText($.alias);
|
|
||||||
const consignee = await page.innerText($.consignee);
|
|
||||||
const subtotal = await page.innerText($.subtotal);
|
|
||||||
const vat = await page.innerText($.vat);
|
|
||||||
const total = await page.innerText($.total);
|
|
||||||
const sale = await page.countElement($.sale);
|
|
||||||
|
|
||||||
expect(id).toEqual('16');
|
|
||||||
expect(alias).toEqual('Many places');
|
|
||||||
expect(consignee).toEqual('address 26 - Gotham (Province one)');
|
|
||||||
expect(subtotal.length).toBeGreaterThan(1);
|
|
||||||
expect(vat.length).toBeGreaterThan(1);
|
|
||||||
expect(total.length).toBeGreaterThan(1);
|
|
||||||
expect(sale).toBeGreaterThan(0);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,69 +0,0 @@
|
||||||
import selectors from '../../helpers/selectors.js';
|
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
const $ = {
|
|
||||||
form: 'vn-order-basic-data form',
|
|
||||||
observation: 'vn-order-basic-data form [vn-name="note"]',
|
|
||||||
saveButton: `vn-order-basic-data form button[type=submit]`,
|
|
||||||
acceptButton: '.vn-confirm.shown button[response="accept"]'
|
|
||||||
};
|
|
||||||
|
|
||||||
describe('Order edit basic data path', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
|
|
||||||
await page.loginAndModule('employee', 'order');
|
|
||||||
await page.accessToSearchResult('1');
|
|
||||||
await page.accessToSection('order.card.basicData');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when confirmed order', () => {
|
|
||||||
it('should not be able to change the client', async() => {
|
|
||||||
const message = await page.sendForm($.form, {
|
|
||||||
client: 'Tony Stark',
|
|
||||||
address: 'Tony Stark',
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(message.text).toContain(`You can't make changes on the basic data`);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when new order', () => {
|
|
||||||
it('should create an order and edit its basic data', async() => {
|
|
||||||
await page.waitToClick(selectors.globalItems.returnToModuleIndexButton);
|
|
||||||
await page.waitToClick($.acceptButton);
|
|
||||||
await page.waitForContentLoaded();
|
|
||||||
await page.waitToClick(selectors.ordersIndex.createOrderButton);
|
|
||||||
await page.waitForState('order.create');
|
|
||||||
|
|
||||||
await page.autocompleteSearch(selectors.createOrderView.client, 'Jessica Jones');
|
|
||||||
await page.pickDate(selectors.createOrderView.landedDatePicker);
|
|
||||||
await page.autocompleteSearch(selectors.createOrderView.agency, 'Other agency');
|
|
||||||
await page.waitToClick(selectors.createOrderView.createButton);
|
|
||||||
await page.waitForState('order.card.catalog');
|
|
||||||
|
|
||||||
await page.accessToSection('order.card.basicData');
|
|
||||||
|
|
||||||
const values = {
|
|
||||||
client: 'Tony Stark',
|
|
||||||
address: 'Tony Stark',
|
|
||||||
agencyMode: 'Other agency'
|
|
||||||
};
|
|
||||||
|
|
||||||
const message = await page.sendForm($.form, values);
|
|
||||||
await page.reloadSection('order.card.basicData');
|
|
||||||
const formValues = await page.fetchForm($.form, Object.keys(values));
|
|
||||||
|
|
||||||
expect(message.isSuccess).toBeTrue();
|
|
||||||
expect(formValues).toEqual(values);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,48 +0,0 @@
|
||||||
import selectors from '../../helpers/selectors.js';
|
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
describe('Order lines', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
await page.loginAndModule('employee', 'order');
|
|
||||||
await page.accessToSearchResult('8');
|
|
||||||
await page.accessToSection('order.card.line');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should check the order subtotal', async() => {
|
|
||||||
const result = await page
|
|
||||||
.waitToGetProperty(selectors.orderLine.orderSubtotal, 'innerText');
|
|
||||||
|
|
||||||
expect(result).toContain('112.30');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should delete the first line in the order', async() => {
|
|
||||||
await page.waitToClick(selectors.orderLine.firstLineDeleteButton);
|
|
||||||
await page.waitToClick(selectors.orderLine.confirmButton);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should confirm the order subtotal has changed', async() => {
|
|
||||||
await page.waitForTextInElement(selectors.orderLine.orderSubtotal, '92.80');
|
|
||||||
const result = await page
|
|
||||||
.waitToGetProperty(selectors.orderLine.orderSubtotal, 'innerText');
|
|
||||||
|
|
||||||
expect(result).toContain('92.80');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should confirm the whole order and redirect to ticket index filtered by clientFk', async() => {
|
|
||||||
await page.waitToClick(selectors.orderLine.confirmOrder);
|
|
||||||
|
|
||||||
await page.expectURL('ticket/index');
|
|
||||||
await page.expectURL('clientFk');
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,97 +0,0 @@
|
||||||
import selectors from '../../helpers/selectors.js';
|
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
describe('Order catalog', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
await page.loginAndModule('employee', 'order');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should open the create new order form', async() => {
|
|
||||||
await page.waitToClick(selectors.ordersIndex.createOrderButton);
|
|
||||||
await page.waitForState('order.create');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create a new order', async() => {
|
|
||||||
await page.autocompleteSearch(selectors.createOrderView.client, 'Tony Stark');
|
|
||||||
await page.pickDate(selectors.createOrderView.landedDatePicker);
|
|
||||||
await page.autocompleteSearch(selectors.createOrderView.agency, 'Other agency');
|
|
||||||
await page.waitToClick(selectors.createOrderView.createButton);
|
|
||||||
await page.waitForState('order.card.catalog');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should add the realm and type filters and obtain results', async() => {
|
|
||||||
await page.waitToClick(selectors.orderCatalog.plantRealmButton);
|
|
||||||
await page.autocompleteSearch(selectors.orderCatalog.type, 'Anthurium');
|
|
||||||
await page.waitForNumberOfElements('section.product', 4);
|
|
||||||
const result = await page.countElement('section.product');
|
|
||||||
|
|
||||||
expect(result).toEqual(4);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should perfom an "OR" search for the item tag colors silver and brown', async() => {
|
|
||||||
await page.waitToClick(selectors.orderCatalog.openTagSearch);
|
|
||||||
await page.autocompleteSearch(selectors.orderCatalog.tag, 'Color');
|
|
||||||
await page.autocompleteSearch(selectors.orderCatalog.firstTagAutocomplete, 'silver');
|
|
||||||
await page.waitToClick(selectors.orderCatalog.addTagButton);
|
|
||||||
await page.autocompleteSearch(selectors.orderCatalog.secondTagAutocomplete, 'brown');
|
|
||||||
await page.waitToClick(selectors.orderCatalog.searchTagButton);
|
|
||||||
await page.waitForNumberOfElements('section.product', 4);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should perfom an "OR" search for the item tag tallos 2 and 9', async() => {
|
|
||||||
await page.waitToClick(selectors.orderCatalog.openTagSearch);
|
|
||||||
await page.autocompleteSearch(selectors.orderCatalog.tag, 'Tallos');
|
|
||||||
await page.write(selectors.orderCatalog.firstTagValue, '2');
|
|
||||||
await page.waitToClick(selectors.orderCatalog.addTagButton);
|
|
||||||
await page.write(selectors.orderCatalog.secondTagValue, '9');
|
|
||||||
await page.waitToClick(selectors.orderCatalog.searchTagButton);
|
|
||||||
await page.waitForNumberOfElements('section.product', 2);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should perform a general search for category', async() => {
|
|
||||||
await page.write(selectors.orderCatalog.itemTagValue, 'concussion');
|
|
||||||
await page.keyboard.press('Enter');
|
|
||||||
await page.waitForNumberOfElements('section.product', 2);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should perfom an "AND" search for the item tag tallos 2', async() => {
|
|
||||||
await page.waitToClick(selectors.orderCatalog.openTagSearch);
|
|
||||||
await page.autocompleteSearch(selectors.orderCatalog.tag, 'Tallos');
|
|
||||||
await page.write(selectors.orderCatalog.firstTagValue, '2');
|
|
||||||
await page.waitToClick(selectors.orderCatalog.searchTagButton);
|
|
||||||
await page.waitForNumberOfElements('section.product', 1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should remove the tag filters and have 4 results', async() => {
|
|
||||||
await page.waitForContentLoaded();
|
|
||||||
await page.waitToClick(selectors.orderCatalog.sixthFilterRemoveButton);
|
|
||||||
await page.waitForContentLoaded();
|
|
||||||
await page.waitToClick(selectors.orderCatalog.fifthFilterRemoveButton);
|
|
||||||
await page.waitForContentLoaded();
|
|
||||||
await page.waitToClick(selectors.orderCatalog.fourthFilterRemoveButton);
|
|
||||||
await page.waitForContentLoaded();
|
|
||||||
await page.waitToClick(selectors.orderCatalog.thirdFilterRemoveButton);
|
|
||||||
|
|
||||||
await page.waitForNumberOfElements('.product', 4);
|
|
||||||
const result = await page.countElement('section.product');
|
|
||||||
|
|
||||||
expect(result).toEqual(4);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should search for an item by id', async() => {
|
|
||||||
await page.accessToSearchResult('2');
|
|
||||||
await page.waitForNumberOfElements('section.product', 1);
|
|
||||||
const result = await page.countElement('section.product');
|
|
||||||
|
|
||||||
expect(result).toEqual(1);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,34 +0,0 @@
|
||||||
import selectors from '../../helpers/selectors.js';
|
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
describe('Order Index', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
await page.loginAndModule('employee', 'order');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should check the second search result doesn't contain a total of 0€`, async() => {
|
|
||||||
await page.waitToClick(selectors.globalItems.searchButton);
|
|
||||||
const result = await page.waitToGetProperty(selectors.ordersIndex.secondSearchResultTotal, 'innerText');
|
|
||||||
|
|
||||||
expect(result).not.toContain('0.00');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should search including empty orders', async() => {
|
|
||||||
await page.waitToClick(selectors.ordersIndex.openAdvancedSearch);
|
|
||||||
await page.waitToClick(selectors.ordersIndex.advancedSearchShowEmptyCheckbox);
|
|
||||||
await page.waitToClick(selectors.ordersIndex.advancedSearchButton);
|
|
||||||
await page.waitForTextInElement(selectors.ordersIndex.secondSearchResultTotal, '0.00');
|
|
||||||
const result = await page.waitToGetProperty(selectors.ordersIndex.secondSearchResultTotal, 'innerText');
|
|
||||||
|
|
||||||
expect(result).toContain('0.00');
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -66,10 +66,16 @@ export default class App {
|
||||||
]}
|
]}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const hasId = !isNaN(parseInt(route.split('/')[1]));
|
||||||
|
|
||||||
if (this.logger.$params.q)
|
if (this.logger.$params.q) {
|
||||||
newRoute = newRoute.concat(`?table=${this.logger.$params.q}`);
|
let tableValue = this.logger.$params.q;
|
||||||
|
const q = JSON.parse(tableValue);
|
||||||
|
if (typeof q === 'number')
|
||||||
|
tableValue = JSON.stringify({id: tableValue});
|
||||||
|
newRoute = newRoute.concat(`?table=${tableValue}`);
|
||||||
|
} else if (!hasId && this.logger.$params.id && newRoute.indexOf(this.logger.$params.id) < 0)
|
||||||
|
newRoute = newRoute.concat(`${this.logger.$params.id}`);
|
||||||
|
|
||||||
return this.logger.$http.get('Urls/findOne', {filter})
|
return this.logger.$http.get('Urls/findOne', {filter})
|
||||||
.then(res => {
|
.then(res => {
|
||||||
|
|
|
@ -240,5 +240,6 @@
|
||||||
"There is already a tray with the same height": "There is already a tray with the same height",
|
"There is already a tray with the same height": "There is already a tray with the same height",
|
||||||
"The height must be greater than 50cm": "The height must be greater than 50cm",
|
"The height must be greater than 50cm": "The height must be greater than 50cm",
|
||||||
"The maximum height of the wagon is 200cm": "The maximum height of the wagon is 200cm",
|
"The maximum height of the wagon is 200cm": "The maximum height of the wagon is 200cm",
|
||||||
"The quantity claimed cannot be greater than the quantity of the line": "The quantity claimed cannot be greater than the quantity of the line"
|
"The quantity claimed cannot be greater than the quantity of the line": "The quantity claimed cannot be greater than the quantity of the line",
|
||||||
|
"There are tickets for this area, delete them first": "There are tickets for this area, delete them first"
|
||||||
}
|
}
|
||||||
|
|
|
@ -381,5 +381,7 @@
|
||||||
"The entry does not have stickers": "La entrada no tiene etiquetas",
|
"The entry does not have stickers": "La entrada no tiene etiquetas",
|
||||||
"This buyer has already made a reservation for this date": "Este comprador ya ha hecho una reserva para esta fecha",
|
"This buyer has already made a reservation for this date": "Este comprador ya ha hecho una reserva para esta fecha",
|
||||||
"No valid travel thermograph found": "No se encontró un termógrafo válido",
|
"No valid travel thermograph found": "No se encontró un termógrafo válido",
|
||||||
"The quantity claimed cannot be greater than the quantity of the line": "La cantidad reclamada no puede ser mayor que la cantidad de la línea"
|
"The quantity claimed cannot be greater than the quantity of the line": "La cantidad reclamada no puede ser mayor que la cantidad de la línea",
|
||||||
|
"type cannot be blank": "Se debe rellenar el tipo",
|
||||||
|
"There are tickets for this area, delete them first": "Hay tickets para esta sección, borralos primero"
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,12 @@
|
||||||
"type": "belongsTo",
|
"type": "belongsTo",
|
||||||
"model": "VnUser",
|
"model": "VnUser",
|
||||||
"foreignKey": "user_id"
|
"foreignKey": "user_id"
|
||||||
|
},
|
||||||
|
"queueMember": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "QueueMember",
|
||||||
|
"foreignKey": "extension",
|
||||||
|
"primaryKey": "extension"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
module.exports = function(Self) {
|
module.exports = function(Self) {
|
||||||
Self.validate('text', isEnabled, {message: 'Description cannot be blank'});
|
Self.validate('text', function(err) {
|
||||||
function isEnabled(err) {
|
|
||||||
if (!this.text) err();
|
if (!this.text) err();
|
||||||
}
|
}, {message: 'Description cannot be blank'});
|
||||||
|
|
||||||
|
Self.validate('observationTypeFk', function(err) {
|
||||||
|
if (!this.observationTypeFk) err();
|
||||||
|
}, {message: 'type cannot be blank'});
|
||||||
|
|
||||||
Self.observe('before save', function(ctx, next) {
|
Self.observe('before save', function(ctx, next) {
|
||||||
ctx.instance.created = Date();
|
ctx.instance.created = Date();
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
{
|
{
|
||||||
"name": "ClientObservation",
|
"name": "ClientObservation",
|
||||||
"description": "Client notes",
|
"description": "Client notes",
|
||||||
"base": "VnModel",
|
"base": "VnModel",
|
||||||
"mixins": {
|
"mixins": {
|
||||||
"Loggable": true
|
"Loggable": true
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"mysql": {
|
"mysql": {
|
||||||
"table": "clientObservation"
|
"table": "clientObservation"
|
||||||
|
@ -26,6 +26,10 @@
|
||||||
"created": {
|
"created": {
|
||||||
"type": "date",
|
"type": "date",
|
||||||
"description": "Creation date and time"
|
"description": "Creation date and time"
|
||||||
|
},
|
||||||
|
"observationTypeFk": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Type of observation"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"relations": {
|
"relations": {
|
||||||
|
@ -44,11 +48,15 @@
|
||||||
"include": {
|
"include": {
|
||||||
"relation": "worker",
|
"relation": "worker",
|
||||||
"scope": {
|
"scope": {
|
||||||
"fields": ["id"],
|
"fields": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
"include": {
|
"include": {
|
||||||
"relation": "user",
|
"relation": "user",
|
||||||
"scope": {
|
"scope": {
|
||||||
"fields": ["nickname"]
|
"fields": [
|
||||||
|
"nickname"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@
|
||||||
<th field="clientFk">
|
<th field="clientFk">
|
||||||
<span translate>Client</span>
|
<span translate>Client</span>
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th field="isWorker">
|
||||||
<span translate>Es trabajador</span>
|
<span translate>Es trabajador</span>
|
||||||
</th>
|
</th>
|
||||||
<th field="salesPersonFk">
|
<th field="salesPersonFk">
|
||||||
|
|
|
@ -57,6 +57,11 @@ export default class Controller extends Section {
|
||||||
field: 'observation',
|
field: 'observation',
|
||||||
searchable: false
|
searchable: false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
field: 'isWorker',
|
||||||
|
checkbox: true,
|
||||||
|
|
||||||
|
},
|
||||||
{
|
{
|
||||||
field: 'created',
|
field: 'created',
|
||||||
datepicker: true
|
datepicker: true
|
||||||
|
@ -73,9 +78,6 @@ export default class Controller extends Section {
|
||||||
|
|
||||||
set defaulters(value) {
|
set defaulters(value) {
|
||||||
if (!value || !value.length) return;
|
if (!value || !value.length) return;
|
||||||
for (let defaulter of value)
|
|
||||||
defaulter.isWorker = defaulter.businessTypeFk === 'worker';
|
|
||||||
|
|
||||||
this._defaulters = value;
|
this._defaulters = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,6 +166,8 @@ export default class Controller extends Section {
|
||||||
|
|
||||||
exprBuilder(param, value) {
|
exprBuilder(param, value) {
|
||||||
switch (param) {
|
switch (param) {
|
||||||
|
case 'isWorker':
|
||||||
|
return {isWorker: value};
|
||||||
case 'creditInsurance':
|
case 'creditInsurance':
|
||||||
case 'amount':
|
case 'amount':
|
||||||
case 'clientFk':
|
case 'clientFk':
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
<vn-crud-model
|
|
||||||
vn-id="model"
|
|
||||||
url="clientObservations"
|
|
||||||
filter="$ctrl.filter"
|
|
||||||
link="{clientFk: $ctrl.$params.id}"
|
|
||||||
data="notes"
|
|
||||||
auto-load="true">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-data-viewer
|
|
||||||
model="model"
|
|
||||||
class="vn-w-md">
|
|
||||||
<vn-card class="vn-pa-md">
|
|
||||||
<div
|
|
||||||
ng-repeat="note in notes"
|
|
||||||
class="note vn-pa-sm border-solid border-radius vn-mb-md">
|
|
||||||
<vn-horizontal class="vn-mb-sm" style="color: #666">
|
|
||||||
<vn-one>{{::note.worker.user.nickname}}</vn-one>
|
|
||||||
<vn-auto>{{::note.created | date:'dd/MM/yyyy HH:mm'}}</vn-auto>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal class="text">
|
|
||||||
{{::note.text}}
|
|
||||||
</vn-horizontal>
|
|
||||||
</div>
|
|
||||||
</vn-card>
|
|
||||||
</vn-data-viewer>
|
|
||||||
<a vn-tooltip="New note"
|
|
||||||
ui-sref="client.card.note.create({id: $ctrl.$params.id})"
|
|
||||||
vn-bind="+"
|
|
||||||
fixed-bottom-right>
|
|
||||||
<vn-float-button icon="add"></vn-float-button>
|
|
||||||
</a>
|
|
|
@ -5,9 +5,10 @@ import './style.scss';
|
||||||
export default class Controller extends Section {
|
export default class Controller extends Section {
|
||||||
constructor($element, $) {
|
constructor($element, $) {
|
||||||
super($element, $);
|
super($element, $);
|
||||||
this.filter = {
|
}
|
||||||
order: 'created DESC',
|
async $onInit() {
|
||||||
};
|
this.$state.go('home');
|
||||||
|
window.location.href = await this.vnApp.getUrl(`customer/${this.$params.id}/notes`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ describe('Entry filter()', () => {
|
||||||
|
|
||||||
const result = await models.Entry.filter(ctx, options);
|
const result = await models.Entry.filter(ctx, options);
|
||||||
|
|
||||||
expect(result.length).toEqual(11);
|
expect(result.length).toEqual(12);
|
||||||
|
|
||||||
await tx.rollback();
|
await tx.rollback();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -152,7 +152,7 @@ describe('Entry filter()', () => {
|
||||||
|
|
||||||
const result = await models.Entry.filter(ctx, options);
|
const result = await models.Entry.filter(ctx, options);
|
||||||
|
|
||||||
expect(result.length).toEqual(10);
|
expect(result.length).toEqual(11);
|
||||||
|
|
||||||
await tx.rollback();
|
await tx.rollback();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
@ -45,8 +45,8 @@ module.exports = Self => {
|
||||||
i.id itemFk,
|
i.id itemFk,
|
||||||
i.name itemName,
|
i.name itemName,
|
||||||
ti.quantity,
|
ti.quantity,
|
||||||
(ac.conversionCoefficient * (ti.quantity / b.packing) * buy_getVolume(b.id))
|
ROUND((ac.conversionCoefficient * (ti.quantity / b.packing) * buy_getVolume(b.id))
|
||||||
/ (vc.trolleyM3 * 1000000) volume,
|
/ (vc.trolleyM3 * 1000000),1) volume,
|
||||||
b.packagingFk packagingFk,
|
b.packagingFk packagingFk,
|
||||||
b.packing
|
b.packing
|
||||||
FROM tmp.item ti
|
FROM tmp.item ti
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
<slot-descriptor>
|
||||||
|
<vn-entry-descriptor></vn-entry-descriptor>
|
||||||
|
</slot-descriptor>
|
|
@ -0,0 +1,9 @@
|
||||||
|
import ngModule from '../module';
|
||||||
|
import DescriptorPopover from 'salix/components/descriptor-popover';
|
||||||
|
|
||||||
|
class Controller extends DescriptorPopover {}
|
||||||
|
|
||||||
|
ngModule.vnComponent('vnEntryDescriptorPopover', {
|
||||||
|
slotTemplate: require('./index.html'),
|
||||||
|
controller: Controller
|
||||||
|
});
|
|
@ -0,0 +1,65 @@
|
||||||
|
<vn-descriptor-content
|
||||||
|
module="entry"
|
||||||
|
description="$ctrl.entry.supplier.nickname"
|
||||||
|
summary="$ctrl.$.summary">
|
||||||
|
<slot-menu>
|
||||||
|
<vn-item
|
||||||
|
ng-click="$ctrl.showEntryReport()"
|
||||||
|
translate>
|
||||||
|
Show entry report
|
||||||
|
</vn-item>
|
||||||
|
</slot-menu>
|
||||||
|
<slot-body>
|
||||||
|
<div class="attributes">
|
||||||
|
<vn-label-value label="Agency "
|
||||||
|
value="{{$ctrl.entry.travel.agency.name}}">
|
||||||
|
</vn-label-value>
|
||||||
|
<vn-label-value label="Landed"
|
||||||
|
value="{{$ctrl.entry.travel.landed | date: 'dd/MM/yyyy'}}">
|
||||||
|
</vn-label-value>
|
||||||
|
<vn-label-value label="Warehouse Out"
|
||||||
|
value="{{$ctrl.entry.travel.warehouseOut.name}}">
|
||||||
|
</vn-label-value>
|
||||||
|
</div>
|
||||||
|
<div class="icons">
|
||||||
|
<vn-icon
|
||||||
|
vn-tooltip="Is inventory entry"
|
||||||
|
icon="icon-inventory"
|
||||||
|
ng-if="$ctrl.entry.isExcludedFromAvailable">
|
||||||
|
</vn-icon>
|
||||||
|
<vn-icon
|
||||||
|
vn-tooltip="Is virtual entry"
|
||||||
|
icon="icon-net"
|
||||||
|
ng-if="$ctrl.entry.isRaid">
|
||||||
|
</vn-icon>
|
||||||
|
</div>
|
||||||
|
<div class="quicklinks">
|
||||||
|
<div ng-transclude="btnOne">
|
||||||
|
<vn-quick-link
|
||||||
|
tooltip="Supplier card"
|
||||||
|
state="['supplier.index', {q: $ctrl.entry.supplier.id }]"
|
||||||
|
icon="icon-supplier">
|
||||||
|
</vn-quick-link>
|
||||||
|
</div>
|
||||||
|
<div ng-transclude="btnTwo">
|
||||||
|
<vn-quick-link
|
||||||
|
tooltip="All travels with current agency"
|
||||||
|
state="['travel.index', {q: $ctrl.travelFilter}]"
|
||||||
|
icon="local_airport">
|
||||||
|
</vn-quick-link>
|
||||||
|
</div>
|
||||||
|
<div ng-transclude="btnThree">
|
||||||
|
<vn-quick-link
|
||||||
|
tooltip="All entries with current supplier"
|
||||||
|
state="['entry.index', {q: $ctrl.entryFilter}]"
|
||||||
|
icon="icon-entry">
|
||||||
|
</vn-quick-link>
|
||||||
|
</div>
|
||||||
|
<div ng-transclude="btnThree">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</slot-body>
|
||||||
|
</vn-descriptor-content>
|
||||||
|
<vn-popup vn-id="summary">
|
||||||
|
<vn-entry-summary entry="$ctrl.entry"></vn-entry-summary>
|
||||||
|
</vn-popup>
|
|
@ -0,0 +1,99 @@
|
||||||
|
import ngModule from '../module';
|
||||||
|
import Descriptor from 'salix/components/descriptor';
|
||||||
|
|
||||||
|
class Controller extends Descriptor {
|
||||||
|
get entry() {
|
||||||
|
return this.entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
set entry(value) {
|
||||||
|
this.entity = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
get travelFilter() {
|
||||||
|
let travelFilter;
|
||||||
|
const entryTravel = this.entry && this.entry.travel;
|
||||||
|
|
||||||
|
if (entryTravel && entryTravel.agencyModeFk) {
|
||||||
|
travelFilter = this.entry && JSON.stringify({
|
||||||
|
agencyModeFk: entryTravel.agencyModeFk
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return travelFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
get entryFilter() {
|
||||||
|
let entryTravel = this.entry && this.entry.travel;
|
||||||
|
|
||||||
|
if (!entryTravel || !entryTravel.landed) return null;
|
||||||
|
|
||||||
|
const date = new Date(entryTravel.landed);
|
||||||
|
date.setHours(0, 0, 0, 0);
|
||||||
|
|
||||||
|
const from = new Date(date.getTime());
|
||||||
|
from.setDate(from.getDate() - 10);
|
||||||
|
|
||||||
|
const to = new Date(date.getTime());
|
||||||
|
to.setDate(to.getDate() + 10);
|
||||||
|
|
||||||
|
return JSON.stringify({
|
||||||
|
supplierFk: this.entry.supplierFk,
|
||||||
|
from,
|
||||||
|
to
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
loadData() {
|
||||||
|
const filter = {
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
relation: 'travel',
|
||||||
|
scope: {
|
||||||
|
fields: ['id', 'landed', 'agencyModeFk', 'warehouseOutFk'],
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
relation: 'agency',
|
||||||
|
scope: {
|
||||||
|
fields: ['name']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
relation: 'warehouseOut',
|
||||||
|
scope: {
|
||||||
|
fields: ['name']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
relation: 'warehouseIn',
|
||||||
|
scope: {
|
||||||
|
fields: ['name']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
relation: 'supplier',
|
||||||
|
scope: {
|
||||||
|
fields: ['id', 'nickname']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.getData(`Entries/${this.id}`, {filter})
|
||||||
|
.then(res => this.entity = res.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
showEntryReport() {
|
||||||
|
this.vnReport.show(`Entries/${this.id}/entry-order-pdf`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngModule.vnComponent('vnEntryDescriptor', {
|
||||||
|
template: require('./index.html'),
|
||||||
|
controller: Controller,
|
||||||
|
bindings: {
|
||||||
|
entry: '<'
|
||||||
|
}
|
||||||
|
});
|
|
@ -1,3 +1,6 @@
|
||||||
export * from './module';
|
export * from './module';
|
||||||
|
|
||||||
import './main';
|
import './main';
|
||||||
|
import './descriptor';
|
||||||
|
import './descriptor-popover';
|
||||||
|
import './summary';
|
||||||
|
|
|
@ -8,6 +8,12 @@
|
||||||
"main": [
|
"main": [
|
||||||
{"state": "entry.index", "icon": "icon-entry"},
|
{"state": "entry.index", "icon": "icon-entry"},
|
||||||
{"state": "entry.latestBuys", "icon": "contact_support"}
|
{"state": "entry.latestBuys", "icon": "contact_support"}
|
||||||
|
],
|
||||||
|
"card": [
|
||||||
|
{"state": "entry.card.basicData", "icon": "settings"},
|
||||||
|
{"state": "entry.card.buy.index", "icon": "icon-lines"},
|
||||||
|
{"state": "entry.card.observation", "icon": "insert_drive_file"},
|
||||||
|
{"state": "entry.card.log", "icon": "history"}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"keybindings": [
|
"keybindings": [
|
||||||
|
@ -27,6 +33,90 @@
|
||||||
"component": "vn-entry-index",
|
"component": "vn-entry-index",
|
||||||
"description": "Entries",
|
"description": "Entries",
|
||||||
"acl": ["buyer", "administrative"]
|
"acl": ["buyer", "administrative"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "/latest-buys?q",
|
||||||
|
"state": "entry.latestBuys",
|
||||||
|
"component": "vn-entry-latest-buys",
|
||||||
|
"description": "Latest buys",
|
||||||
|
"acl": ["buyer", "administrative"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "/create?supplierFk&travelFk&companyFk",
|
||||||
|
"state": "entry.create",
|
||||||
|
"component": "vn-entry-create",
|
||||||
|
"description": "New entry",
|
||||||
|
"acl": ["buyer", "administrative"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "/:id",
|
||||||
|
"state": "entry.card",
|
||||||
|
"abstract": true,
|
||||||
|
"component": "vn-entry-card"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "/summary",
|
||||||
|
"state": "entry.card.summary",
|
||||||
|
"component": "vn-entry-summary",
|
||||||
|
"description": "Summary",
|
||||||
|
"params": {
|
||||||
|
"entry": "$ctrl.entry"
|
||||||
|
},
|
||||||
|
"acl": ["buyer", "administrative"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "/basic-data",
|
||||||
|
"state": "entry.card.basicData",
|
||||||
|
"component": "vn-entry-basic-data",
|
||||||
|
"description": "Basic data",
|
||||||
|
"params": {
|
||||||
|
"entry": "$ctrl.entry"
|
||||||
|
},
|
||||||
|
"acl": ["buyer", "administrative"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "/observation",
|
||||||
|
"state": "entry.card.observation",
|
||||||
|
"component": "vn-entry-observation",
|
||||||
|
"description": "Notes",
|
||||||
|
"params": {
|
||||||
|
"entry": "$ctrl.entry"
|
||||||
|
},
|
||||||
|
"acl": ["buyer", "administrative"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url" : "/log",
|
||||||
|
"state": "entry.card.log",
|
||||||
|
"component": "vn-entry-log",
|
||||||
|
"description": "Log",
|
||||||
|
"acl": ["buyer", "administrative"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "/buy",
|
||||||
|
"state": "entry.card.buy",
|
||||||
|
"abstract": true,
|
||||||
|
"component": "ui-view",
|
||||||
|
"acl": ["buyer"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url" : "/index",
|
||||||
|
"state": "entry.card.buy.index",
|
||||||
|
"component": "vn-entry-buy-index",
|
||||||
|
"description": "Buys",
|
||||||
|
"params": {
|
||||||
|
"entry": "$ctrl.entry"
|
||||||
|
},
|
||||||
|
"acl": ["buyer", "administrative"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url" : "/import",
|
||||||
|
"state": "entry.card.buy.import",
|
||||||
|
"component": "vn-entry-buy-import",
|
||||||
|
"description": "Import buys",
|
||||||
|
"params": {
|
||||||
|
"entry": "$ctrl.entry"
|
||||||
|
},
|
||||||
|
"acl": ["buyer"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,195 @@
|
||||||
|
<vn-crud-model
|
||||||
|
vn-id="buysModel"
|
||||||
|
url="Entries/{{$ctrl.entry.id}}/getBuys"
|
||||||
|
limit="5"
|
||||||
|
data="buys"
|
||||||
|
auto-load="true">
|
||||||
|
</vn-crud-model>
|
||||||
|
<vn-card class="summary">
|
||||||
|
<h5>
|
||||||
|
<a ng-if="::$ctrl.entryData.id"
|
||||||
|
vn-tooltip="Go to the entry"
|
||||||
|
ui-sref="entry.card.summary({id: {{::$ctrl.entryData.id}}})"
|
||||||
|
name="goToSummary">
|
||||||
|
<vn-icon-button icon="launch"></vn-icon-button>
|
||||||
|
</a>
|
||||||
|
<span> #{{$ctrl.entryData.id}} - {{$ctrl.entryData.supplier.nickname}}</span>
|
||||||
|
</h5>
|
||||||
|
<vn-horizontal>
|
||||||
|
<vn-one>
|
||||||
|
<vn-label-value label="Commission"
|
||||||
|
value="{{$ctrl.entryData.commission}}">
|
||||||
|
</vn-label-value>
|
||||||
|
<vn-label-value label="Currency"
|
||||||
|
value="{{$ctrl.entryData.currency.name}}">
|
||||||
|
</vn-label-value>
|
||||||
|
<vn-label-value label="Company"
|
||||||
|
value="{{$ctrl.entryData.company.code}}">
|
||||||
|
</vn-label-value>
|
||||||
|
<vn-label-value label="Reference"
|
||||||
|
value="{{$ctrl.entryData.reference}}">
|
||||||
|
</vn-label-value>
|
||||||
|
<vn-label-value label="Invoice number"
|
||||||
|
value="{{$ctrl.entryData.invoiceNumber}}">
|
||||||
|
</vn-label-value>
|
||||||
|
</vn-one>
|
||||||
|
<vn-one>
|
||||||
|
<vn-label-value label="Reference">
|
||||||
|
<span
|
||||||
|
ng-click="travelDescriptor.show($event, $ctrl.entryData.travel.id)"
|
||||||
|
class="link">
|
||||||
|
{{$ctrl.entryData.travel.ref}}
|
||||||
|
</span>
|
||||||
|
</vn-label-value>
|
||||||
|
<vn-label-value label="Agency"
|
||||||
|
value="{{$ctrl.entryData.travel.agency.name}}">
|
||||||
|
</vn-label-value>
|
||||||
|
<vn-label-value label="Shipped"
|
||||||
|
value="{{$ctrl.entryData.travel.shipped | date: 'dd/MM/yyyy'}}">
|
||||||
|
</vn-label-value>
|
||||||
|
<vn-label-value label="Warehouse Out"
|
||||||
|
value="{{$ctrl.entryData.travel.warehouseOut.name}}">
|
||||||
|
</vn-label-value>
|
||||||
|
<vn-check
|
||||||
|
label="Delivered"
|
||||||
|
ng-model="$ctrl.entryData.travel.isDelivered"
|
||||||
|
disabled="true">
|
||||||
|
</vn-check>
|
||||||
|
<vn-label-value label="Landed"
|
||||||
|
value="{{$ctrl.entryData.travel.landed | date: 'dd/MM/yyyy'}}">
|
||||||
|
</vn-label-value>
|
||||||
|
<vn-label-value label="Warehouse In"
|
||||||
|
value="{{$ctrl.entryData.travel.warehouseIn.name}}">
|
||||||
|
</vn-label-value>
|
||||||
|
<vn-check
|
||||||
|
label="Received"
|
||||||
|
ng-model="$ctrl.entryData.travel.isReceived"
|
||||||
|
disabled="true">
|
||||||
|
</vn-check>
|
||||||
|
</vn-one>
|
||||||
|
<vn-one>
|
||||||
|
<vn-vertical>
|
||||||
|
<vn-check
|
||||||
|
label="Ordered"
|
||||||
|
ng-model="$ctrl.entryData.isOrdered"
|
||||||
|
disabled="true">
|
||||||
|
</vn-check>
|
||||||
|
<vn-check
|
||||||
|
label="Confirmed"
|
||||||
|
ng-model="$ctrl.entryData.isConfirmed"
|
||||||
|
disabled="true">
|
||||||
|
</vn-check>
|
||||||
|
<vn-check
|
||||||
|
label="Booked"
|
||||||
|
ng-model="$ctrl.entryData.isBooked"
|
||||||
|
disabled="true">
|
||||||
|
</vn-check>
|
||||||
|
<vn-check
|
||||||
|
label="Raid"
|
||||||
|
ng-model="$ctrl.entryData.isRaid"
|
||||||
|
disabled="true">
|
||||||
|
</vn-check>
|
||||||
|
<vn-check
|
||||||
|
label="Inventory"
|
||||||
|
ng-model="$ctrl.entryData.isExcludedFromAvailable"
|
||||||
|
disabled="true">
|
||||||
|
</vn-check>
|
||||||
|
</vn-vertical>
|
||||||
|
</vn-one>
|
||||||
|
</vn-horizontal>
|
||||||
|
<vn-horizontal>
|
||||||
|
<vn-auto name="buys">
|
||||||
|
<h4 translate>Buys</h4>
|
||||||
|
<table class="vn-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th translate center field="quantity">Quantity</th>
|
||||||
|
<th translate center field="sticker">Stickers</th>
|
||||||
|
<th translate center field="packagingFk">Package</th>
|
||||||
|
<th translate center field="weight">Weight</th>
|
||||||
|
<th translate center field="packing">Packing</th>
|
||||||
|
<th translate center field="grouping">Grouping</th>
|
||||||
|
<th translate center field="buyingValue">Buying value</th>
|
||||||
|
<th translate center field="price3">Import</th>
|
||||||
|
<th translate center expand field="price">PVP</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody ng-repeat="line in buys">
|
||||||
|
<tr>
|
||||||
|
<td center title="{{::line.quantity}}">{{::line.quantity}}</td>
|
||||||
|
<td center title="{{::line.stickers | dashIfEmpty}}">{{::line.stickers | dashIfEmpty}}</td>
|
||||||
|
<td center title="{{::line.packagingFk | dashIfEmpty}}">{{::line.packagingFk | dashIfEmpty}}</td>
|
||||||
|
<td center title="{{::line.weight}}">{{::line.weight}}</td>
|
||||||
|
<td center>
|
||||||
|
<vn-chip class="transparent" translate-attr="line.groupingMode == 'packing' ? {title: 'Minimun amount'} : {title: 'Packing'}" ng-class="{'message': line.groupingMode == 'packing'}">
|
||||||
|
<span>{{::line.packing | dashIfEmpty}}</span>
|
||||||
|
</vn-chip>
|
||||||
|
</td>
|
||||||
|
<td center>
|
||||||
|
<vn-chip class="transparent" translate-attr="line.groupingMode == 'grouping' ? {title: 'Minimun amount'} : {title: 'Grouping'}" ng-class="{'message': line.groupingMode == 'grouping'}">
|
||||||
|
<span>{{::line.grouping | dashIfEmpty}}</span>
|
||||||
|
</vn-chip>
|
||||||
|
</vn-td>
|
||||||
|
<td center title="{{::line.buyingValue | currency: 'EUR':2}}">{{::line.buyingValue | currency: 'EUR':2}}</td>
|
||||||
|
<td center title="{{::line.quantity * line.buyingValue | currency: 'EUR':2}}">{{::line.quantity * line.buyingValue | currency: 'EUR':2}}</td>
|
||||||
|
<td center title="Grouping / Packing">{{::line.price2 | currency: 'EUR':2 | dashIfEmpty}} / {{::line.price3 | currency: 'EUR':2 | dashIfEmpty}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="dark-row">
|
||||||
|
<td shrink>
|
||||||
|
<span
|
||||||
|
translate-attr="{title: 'Item type'}">
|
||||||
|
{{::line.item.itemType.code}}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td shrink>
|
||||||
|
<span
|
||||||
|
ng-click="itemDescriptor.show($event, line.item.id)"
|
||||||
|
class="link">
|
||||||
|
{{::line.item.id}}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td number shrink>
|
||||||
|
<span
|
||||||
|
translate-attr="{title: 'Item size'}">
|
||||||
|
{{::line.item.size}}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td center>
|
||||||
|
<span
|
||||||
|
translate-attr="{title: 'Minimum price'}">
|
||||||
|
{{::line.item.minPrice | currency: 'EUR':2}}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td vn-fetched-tags colspan="6">
|
||||||
|
<div>
|
||||||
|
<vn-one title="{{::line.item.concept}}">{{::line.item.name}}</vn-one>
|
||||||
|
<vn-one ng-if="::line.item.subName">
|
||||||
|
<h3 title="{{::line.item.subName}}">{{::line.item.subName}}</h3>
|
||||||
|
</vn-one>
|
||||||
|
</div>
|
||||||
|
<vn-fetched-tags
|
||||||
|
max-length="6"
|
||||||
|
item="::line.item"
|
||||||
|
tabindex="-1">
|
||||||
|
</vn-fetched-tags>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="empty-row">
|
||||||
|
<td colspan="10"></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<vn-pagination
|
||||||
|
model="buysModel"
|
||||||
|
class="vn-pt-xs">
|
||||||
|
</vn-pagination>
|
||||||
|
</vn-auto>
|
||||||
|
</vn-horizontal>
|
||||||
|
</vn-card>
|
||||||
|
<vn-item-descriptor-popover
|
||||||
|
vn-id="item-descriptor"
|
||||||
|
warehouse-fk="$ctrl.vnConfig.warehouseFk">
|
||||||
|
</vn-item-descriptor-popover>
|
||||||
|
<vn-travel-descriptor-popover
|
||||||
|
vn-id="travelDescriptor">
|
||||||
|
</vn-travel-descriptor-popover>
|
|
@ -0,0 +1,33 @@
|
||||||
|
import ngModule from '../module';
|
||||||
|
import './style.scss';
|
||||||
|
import Summary from 'salix/components/summary';
|
||||||
|
|
||||||
|
class Controller extends Summary {
|
||||||
|
get entry() {
|
||||||
|
if (!this._entry)
|
||||||
|
return this.$params;
|
||||||
|
|
||||||
|
return this._entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
set entry(value) {
|
||||||
|
this._entry = value;
|
||||||
|
|
||||||
|
if (value && value.id)
|
||||||
|
this.getEntryData();
|
||||||
|
}
|
||||||
|
|
||||||
|
getEntryData() {
|
||||||
|
return this.$http.get(`Entries/${this.entry.id}/getEntry`).then(response => {
|
||||||
|
this.entryData = response.data;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngModule.vnComponent('vnEntrySummary', {
|
||||||
|
template: require('./index.html'),
|
||||||
|
controller: Controller,
|
||||||
|
bindings: {
|
||||||
|
entry: '<'
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,30 @@
|
||||||
|
@import "variables";
|
||||||
|
|
||||||
|
|
||||||
|
vn-entry-summary .summary {
|
||||||
|
max-width: $width-lg;
|
||||||
|
|
||||||
|
.dark-row {
|
||||||
|
background-color: lighten($color-marginal, 10%);
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody tr:nth-child(1) {
|
||||||
|
border-top: $border-thin;
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody tr:nth-child(1),
|
||||||
|
tbody tr:nth-child(2) {
|
||||||
|
border-left: $border-thin;
|
||||||
|
border-right: $border-thin
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody tr:nth-child(3) {
|
||||||
|
height: inherit
|
||||||
|
}
|
||||||
|
|
||||||
|
tr {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$color-font-link-medium: lighten($color-font-link, 20%)
|
|
@ -48,13 +48,13 @@ module.exports = Self => {
|
||||||
let stmt;
|
let stmt;
|
||||||
stmts.push(new ParameterizedSQL(
|
stmts.push(new ParameterizedSQL(
|
||||||
`CREATE OR REPLACE TEMPORARY TABLE tmp.ticket
|
`CREATE OR REPLACE TEMPORARY TABLE tmp.ticket
|
||||||
(KEY (ticketFk))
|
(INDEX (ticketFk))
|
||||||
ENGINE = MEMORY
|
ENGINE = MEMORY
|
||||||
SELECT id ticketFk
|
SELECT id ticketFk
|
||||||
FROM ticket t
|
FROM ticket
|
||||||
WHERE shipped BETWEEN ? AND util.dayEnd(?)
|
WHERE shipped BETWEEN ? AND util.dayEnd(?)
|
||||||
AND refFk IS NULL`, [args.from, args.to]));
|
AND refFk IS NULL`, [args.from, args.to]));
|
||||||
stmts.push(`CALL vn.ticket_getTax(NULL)`);
|
stmts.push(`CALL ticket_getTax(NULL)`);
|
||||||
stmts.push(new ParameterizedSQL(
|
stmts.push(new ParameterizedSQL(
|
||||||
`CREATE OR REPLACE TEMPORARY TABLE tmp.filter
|
`CREATE OR REPLACE TEMPORARY TABLE tmp.filter
|
||||||
ENGINE = MEMORY
|
ENGINE = MEMORY
|
||||||
|
@ -71,12 +71,12 @@ module.exports = Self => {
|
||||||
c.isTaxDataChecked,
|
c.isTaxDataChecked,
|
||||||
w.id comercialId,
|
w.id comercialId,
|
||||||
u.name workerName
|
u.name workerName
|
||||||
FROM vn.ticket t
|
FROM ticket t
|
||||||
JOIN vn.company co ON co.id = t.companyFk
|
JOIN company co ON co.id = t.companyFk
|
||||||
JOIN vn.sale s ON s.ticketFk = t.id
|
JOIN sale s ON s.ticketFk = t.id
|
||||||
JOIN vn.client c ON c.id = t.clientFk
|
JOIN client c ON c.id = t.clientFk
|
||||||
JOIN vn.country cou ON cou.id = c.countryFk
|
JOIN country cou ON cou.id = c.countryFk
|
||||||
LEFT JOIN vn.worker w ON w.id = c.salesPersonFk
|
LEFT JOIN worker w ON w.id = c.salesPersonFk
|
||||||
JOIN account.user u ON u.id = w.id
|
JOIN account.user u ON u.id = w.id
|
||||||
LEFT JOIN (
|
LEFT JOIN (
|
||||||
SELECT ticketFk, taxableBase
|
SELECT ticketFk, taxableBase
|
||||||
|
|
|
@ -34,6 +34,11 @@ module.exports = Self => {
|
||||||
try {
|
try {
|
||||||
const promises = [];
|
const promises = [];
|
||||||
for (let itemShelvingId of itemShelvingIds) {
|
for (let itemShelvingId of itemShelvingIds) {
|
||||||
|
const itemShelvingSaleToDelete = models.ItemShelvingSale.destroyAll({
|
||||||
|
itemShelvingFk: itemShelvingId
|
||||||
|
}, myOptions);
|
||||||
|
promises.push(itemShelvingSaleToDelete);
|
||||||
|
|
||||||
const itemShelvingToDelete = models.ItemShelving.destroyById(itemShelvingId, myOptions);
|
const itemShelvingToDelete = models.ItemShelving.destroyById(itemShelvingId, myOptions);
|
||||||
promises.push(itemShelvingToDelete);
|
promises.push(itemShelvingToDelete);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ describe('ItemShelving deleteItemShelvings()', () => {
|
||||||
const itemShelvingIds = [1, 2];
|
const itemShelvingIds = [1, 2];
|
||||||
const result = await models.ItemShelving.deleteItemShelvings(itemShelvingIds, options);
|
const result = await models.ItemShelving.deleteItemShelvings(itemShelvingIds, options);
|
||||||
|
|
||||||
expect(result.length).toEqual(2);
|
expect(result.length).toEqual(4);
|
||||||
|
|
||||||
await tx.rollback();
|
await tx.rollback();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
const {models} = require('vn-loopback/server/server');
|
const {models} = require('vn-loopback/server/server');
|
||||||
describe('item lastEntriesFilter()', () => {
|
describe('item lastEntriesFilter()', () => {
|
||||||
it('should return one entry for the given item', async() => {
|
it('should return two entry for the given item', async() => {
|
||||||
const minDate = Date.vnNew();
|
const minDate = Date.vnNew();
|
||||||
minDate.setHours(0, 0, 0, 0);
|
minDate.setHours(0, 0, 0, 0);
|
||||||
const maxDate = Date.vnNew();
|
const maxDate = Date.vnNew();
|
||||||
|
@ -13,7 +13,7 @@ describe('item lastEntriesFilter()', () => {
|
||||||
const filter = {where: {itemFk: 1, landed: {between: [minDate, maxDate]}}};
|
const filter = {where: {itemFk: 1, landed: {between: [minDate, maxDate]}}};
|
||||||
const result = await models.Item.lastEntriesFilter(filter, options);
|
const result = await models.Item.lastEntriesFilter(filter, options);
|
||||||
|
|
||||||
expect(result.length).toEqual(1);
|
expect(result.length).toEqual(2);
|
||||||
|
|
||||||
await tx.rollback();
|
await tx.rollback();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -22,7 +22,7 @@ describe('item lastEntriesFilter()', () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return five entries for the given item', async() => {
|
it('should return six entries for the given item', async() => {
|
||||||
const minDate = Date.vnNew();
|
const minDate = Date.vnNew();
|
||||||
minDate.setHours(0, 0, 0, 0);
|
minDate.setHours(0, 0, 0, 0);
|
||||||
minDate.setMonth(minDate.getMonth() - 2, 1);
|
minDate.setMonth(minDate.getMonth() - 2, 1);
|
||||||
|
@ -37,7 +37,7 @@ describe('item lastEntriesFilter()', () => {
|
||||||
const filter = {where: {itemFk: 1, landed: {between: [minDate, maxDate]}}};
|
const filter = {where: {itemFk: 1, landed: {between: [minDate, maxDate]}}};
|
||||||
const result = await models.Item.lastEntriesFilter(filter, options);
|
const result = await models.Item.lastEntriesFilter(filter, options);
|
||||||
|
|
||||||
expect(result.length).toEqual(5);
|
expect(result.length).toEqual(6);
|
||||||
|
|
||||||
await tx.rollback();
|
await tx.rollback();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
"name": "Items",
|
"name": "Items",
|
||||||
"icon": "icon-item",
|
"icon": "icon-item",
|
||||||
"validations" : true,
|
"validations" : true,
|
||||||
"dependencies": ["worker", "client", "ticket"],
|
"dependencies": ["worker", "client", "ticket", "entry"],
|
||||||
"menus": {
|
"menus": {
|
||||||
"main": [
|
"main": [
|
||||||
{"state": "item.index", "icon": "icon-item"},
|
{"state": "item.index", "icon": "icon-item"},
|
||||||
|
|
|
@ -1,8 +1,3 @@
|
||||||
export * from './module';
|
export * from './module';
|
||||||
|
|
||||||
import './main';
|
import './main';
|
||||||
import './index/';
|
|
||||||
import './index/tickets';
|
|
||||||
import './index/clients';
|
|
||||||
import './index/orders';
|
|
||||||
import './index/search-panel';
|
|
||||||
|
|
|
@ -1,110 +0,0 @@
|
||||||
<vn-crud-model
|
|
||||||
vn-id="model"
|
|
||||||
url="SalesMonitors/clientsFilter"
|
|
||||||
limit="6"
|
|
||||||
filter="$ctrl.filter"
|
|
||||||
order="dated DESC, hour DESC"
|
|
||||||
auto-load="true">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-horizontal class="header">
|
|
||||||
<vn-one translate>
|
|
||||||
Clients on website
|
|
||||||
</vn-one>
|
|
||||||
<vn-none>
|
|
||||||
<vn-icon class="arrow"
|
|
||||||
icon="keyboard_arrow_up"
|
|
||||||
vn-tooltip="Minimize/Maximize"
|
|
||||||
ng-click="$ctrl.main.toggle()">
|
|
||||||
</vn-icon>
|
|
||||||
</vn-none>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-card vn-id="card">
|
|
||||||
<smart-table
|
|
||||||
model="model"
|
|
||||||
options="$ctrl.smartTableOptions"
|
|
||||||
expr-builder="$ctrl.exprBuilder(param, value)"
|
|
||||||
disabled-table-filter="true"
|
|
||||||
disabled-table-order="true"
|
|
||||||
class="scrollable sm">
|
|
||||||
<slot-actions>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-date-picker
|
|
||||||
class="vn-pa-xs"
|
|
||||||
label="From"
|
|
||||||
ng-model="$ctrl.dateFrom"
|
|
||||||
on-change="$ctrl.addFilterDate()">
|
|
||||||
</vn-date-picker>
|
|
||||||
<vn-date-picker
|
|
||||||
class="vn-pa-xs"
|
|
||||||
label="To"
|
|
||||||
ng-model="$ctrl.dateTo"
|
|
||||||
on-change="$ctrl.addFilterDate()">
|
|
||||||
</vn-date-picker>
|
|
||||||
</vn-horizontal>
|
|
||||||
</slot-actions>
|
|
||||||
<slot-table>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th field="dated">
|
|
||||||
<span translate>Date</span>
|
|
||||||
</th>
|
|
||||||
<th field="hour">
|
|
||||||
<span translate>Hour</span>
|
|
||||||
</th>
|
|
||||||
<th field="salesPersonFk" class="expendable">
|
|
||||||
<span translate>Salesperson</span>
|
|
||||||
</th>
|
|
||||||
<th field="clientFk">
|
|
||||||
<span translate>Client</span>
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr ng-repeat="visit in model.data track by visit.id">
|
|
||||||
<td shrink-date>
|
|
||||||
<span class="chip">
|
|
||||||
{{::visit.dated | date:'dd/MM/yy'}}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td shrink-date>
|
|
||||||
<span class="chip">
|
|
||||||
{{::visit.hour | date: 'HH:mm'}}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td class="shrink expendable">
|
|
||||||
<span
|
|
||||||
title="{{::visit.salesPerson}}"
|
|
||||||
vn-click-stop="workerDescriptor.show($event, visit.salesPersonFk)"
|
|
||||||
class="link">
|
|
||||||
{{::visit.salesPerson | dashIfEmpty}}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<span
|
|
||||||
title="{{::visit.clientName}}"
|
|
||||||
vn-click-stop="clientDescriptor.show($event, visit.clientFk)"
|
|
||||||
class="link">
|
|
||||||
{{::visit.clientName}}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</slot-table>
|
|
||||||
<slot-pagination>
|
|
||||||
<vn-pagination
|
|
||||||
model="model"
|
|
||||||
class="vn-pt-xs"
|
|
||||||
scroll-selector="vn-monitor-sales-clients smart-table"
|
|
||||||
scroll-offset="100">
|
|
||||||
</vn-pagination>
|
|
||||||
</slot-pagination>
|
|
||||||
</smart-table>
|
|
||||||
</vn-card>
|
|
||||||
<vn-worker-descriptor-popover
|
|
||||||
vn-id="workerDescriptor">
|
|
||||||
</vn-worker-descriptor-popover>
|
|
||||||
<vn-client-descriptor-popover
|
|
||||||
vn-id="clientDescriptor">
|
|
||||||
</vn-client-descriptor-popover>
|
|
|
@ -1,96 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
export default class Controller extends Section {
|
|
||||||
constructor($element, $) {
|
|
||||||
super($element, $);
|
|
||||||
|
|
||||||
const date = Date.vnNew();
|
|
||||||
this.dateFrom = date;
|
|
||||||
this.dateTo = date;
|
|
||||||
this.filter = {
|
|
||||||
where: {
|
|
||||||
'v.stamp': {
|
|
||||||
between: this.dateRange()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.smartTableOptions = {
|
|
||||||
activeButtons: {
|
|
||||||
search: true
|
|
||||||
},
|
|
||||||
columns: [
|
|
||||||
{
|
|
||||||
field: 'clientFk',
|
|
||||||
autocomplete: {
|
|
||||||
url: 'Clients',
|
|
||||||
showField: 'name',
|
|
||||||
valueField: 'id'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'salesPersonFk',
|
|
||||||
autocomplete: {
|
|
||||||
url: 'Workers/activeWithInheritedRole',
|
|
||||||
where: `{role: 'salesPerson'}`,
|
|
||||||
searchFunction: '{firstName: $search}',
|
|
||||||
showField: 'nickname',
|
|
||||||
valueField: 'id',
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'dated',
|
|
||||||
searchable: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'hour',
|
|
||||||
searchable: false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
exprBuilder(param, value) {
|
|
||||||
switch (param) {
|
|
||||||
case 'clientFk':
|
|
||||||
return {[`c.id`]: value};
|
|
||||||
case 'salesPersonFk':
|
|
||||||
return {[`c.${param}`]: value};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dateRange() {
|
|
||||||
let from = this.dateFrom;
|
|
||||||
let to = this.dateTo;
|
|
||||||
if (!from)
|
|
||||||
from = Date.vnNew();
|
|
||||||
if (!to)
|
|
||||||
to = Date.vnNew();
|
|
||||||
const minHour = new Date(from);
|
|
||||||
minHour.setHours(0, 0, 0, 0);
|
|
||||||
const maxHour = new Date(to);
|
|
||||||
maxHour.setHours(23, 59, 59, 59);
|
|
||||||
|
|
||||||
return [minHour, maxHour];
|
|
||||||
}
|
|
||||||
|
|
||||||
addFilterDate() {
|
|
||||||
this.$.model.filter = {
|
|
||||||
where: {
|
|
||||||
'v.stamp': {
|
|
||||||
between: this.dateRange()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.$.model.refresh();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnMonitorSalesClients', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
require: {
|
|
||||||
main: '^vnMonitorIndex'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,5 +0,0 @@
|
||||||
<vn-horizontal ng-class="{'hidden': $ctrl.isTopPanelHidden}">
|
|
||||||
<vn-monitor-sales-clients class="vn-mb-sm"></vn-monitor-sales-clients>
|
|
||||||
<vn-monitor-sales-orders></vn-monitor-sales-orders>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-monitor-sales-tickets></vn-monitor-sales-tickets>
|
|
|
@ -1,34 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
import './style.scss';
|
|
||||||
|
|
||||||
export default class Controller extends Section {
|
|
||||||
constructor($element, $) {
|
|
||||||
super($element, $);
|
|
||||||
|
|
||||||
const isTopPanelHidden = localStorage.getItem('ticketTopPanelHidden');
|
|
||||||
if (isTopPanelHidden === 'true')
|
|
||||||
this.isTopPanelHidden = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
toggle() {
|
|
||||||
const monitor = this.element.querySelector('vn-horizontal');
|
|
||||||
const isHidden = monitor.classList.contains('hidden');
|
|
||||||
|
|
||||||
if (!isHidden) {
|
|
||||||
monitor.classList.add('hidden');
|
|
||||||
localStorage.setItem('ticketTopPanelHidden', true);
|
|
||||||
} else {
|
|
||||||
monitor.classList.remove('hidden');
|
|
||||||
localStorage.setItem('ticketTopPanelHidden', false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnMonitorIndex', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
require: {
|
|
||||||
main: '^vnMonitorIndex'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,38 +0,0 @@
|
||||||
import './index.js';
|
|
||||||
describe('Component vnMonitorIndex', () => {
|
|
||||||
let controller;
|
|
||||||
let $element;
|
|
||||||
|
|
||||||
beforeEach(ngModule('monitor'));
|
|
||||||
|
|
||||||
beforeEach(inject(($compile, $rootScope) => {
|
|
||||||
$element = $compile('<vn-monitor-index></vn-monitor-index>')($rootScope);
|
|
||||||
controller = $element.controller('vnMonitorIndex');
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('toggle()', () => {
|
|
||||||
it('should add the hidden class to the horizontal contaning the panel to hide', () => {
|
|
||||||
controller.toggle();
|
|
||||||
|
|
||||||
const targetElement = $element[0].querySelector('vn-horizontal');
|
|
||||||
const firstClass = targetElement.classList[0];
|
|
||||||
|
|
||||||
const isTopPanelHidden = localStorage.getItem('ticketTopPanelHidden');
|
|
||||||
|
|
||||||
expect(firstClass).toEqual('hidden');
|
|
||||||
expect(isTopPanelHidden).toEqual('true');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should remove the hidden class to the horizontal contaning the panel to hide', () => {
|
|
||||||
const targetElement = $element[0].querySelector('vn-horizontal');
|
|
||||||
targetElement.classList.add('hidden');
|
|
||||||
controller.toggle();
|
|
||||||
const firstClass = targetElement.classList[0];
|
|
||||||
|
|
||||||
const isTopPanelHidden = localStorage.getItem('ticketTopPanelHidden');
|
|
||||||
|
|
||||||
expect(firstClass).toBeUndefined();
|
|
||||||
expect(isTopPanelHidden).toEqual('false');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,16 +0,0 @@
|
||||||
Tickets monitor: Monitor de tickets
|
|
||||||
Clients on website: Clientes activos en la web
|
|
||||||
Recent order actions: Acciones recientes en pedidos
|
|
||||||
Search tickets: Buscar tickets
|
|
||||||
Delete selected elements: Eliminar los elementos seleccionados
|
|
||||||
All the selected elements will be deleted. Are you sure you want to continue?: Todos los elementos seleccionados serán eliminados. ¿Seguro que quieres continuar?
|
|
||||||
Component lack: Faltan componentes
|
|
||||||
Ticket too little: Ticket demasiado pequeño
|
|
||||||
Minimize/Maximize: Minimizar/Maximizar
|
|
||||||
Problems: Problemas
|
|
||||||
Theoretical: Teórica
|
|
||||||
Practical: Práctica
|
|
||||||
Preparation: Preparación
|
|
||||||
Auto-refresh: Auto-refresco
|
|
||||||
Toggle auto-refresh every 2 minutes: Conmuta el refresco automático cada 2 minutos
|
|
||||||
Is fragile: Es frágil
|
|
|
@ -1,141 +0,0 @@
|
||||||
<vn-crud-model auto-load="true"
|
|
||||||
vn-id="model"
|
|
||||||
url="SalesMonitors/ordersFilter"
|
|
||||||
limit="6"
|
|
||||||
order="date_make DESC">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-horizontal class="header">
|
|
||||||
<vn-one translate>
|
|
||||||
Recent order actions
|
|
||||||
</vn-one>
|
|
||||||
<vn-none>
|
|
||||||
<vn-icon
|
|
||||||
icon="delete"
|
|
||||||
vn-tooltip="Delete"
|
|
||||||
ng-if="$ctrl.totalChecked > 0"
|
|
||||||
ng-click="delete.show()">
|
|
||||||
</vn-icon>
|
|
||||||
<vn-icon class="arrow"
|
|
||||||
icon="keyboard_arrow_up"
|
|
||||||
vn-tooltip="Minimize/Maximize"
|
|
||||||
ng-click="$ctrl.main.toggle()">
|
|
||||||
</vn-icon>
|
|
||||||
<vn-icon
|
|
||||||
icon="refresh"
|
|
||||||
vn-tooltip="Refresh"
|
|
||||||
ng-click="model.refresh()">
|
|
||||||
</vn-icon>
|
|
||||||
</vn-none>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-card>
|
|
||||||
<vn-table model="model" class="scrollable">
|
|
||||||
<vn-thead>
|
|
||||||
<vn-tr>
|
|
||||||
<vn-th shrink>
|
|
||||||
<vn-multi-check
|
|
||||||
model="model">
|
|
||||||
</vn-multi-check>
|
|
||||||
</vn-th>
|
|
||||||
<vn-th field="date_send" shrink-datetime>Date</vn-th>
|
|
||||||
<vn-th field="clientFk">Client</vn-th>
|
|
||||||
<vn-th field="salesPersonFk" shrink>SalesPerson</vn-th>
|
|
||||||
</vn-tr>
|
|
||||||
</vn-thead>
|
|
||||||
<a ng-repeat="order in model.data track by order.id"
|
|
||||||
class="clickable vn-tbody"
|
|
||||||
ui-sref="order.card.summary({id: {{::order.id}}})" target="_blank">
|
|
||||||
<vn-tr>
|
|
||||||
<vn-td>
|
|
||||||
<vn-check
|
|
||||||
ng-model="order.checked"
|
|
||||||
vn-click-stop>
|
|
||||||
</vn-check>
|
|
||||||
</vn-td>
|
|
||||||
<vn-td>
|
|
||||||
<span class="chip {{::$ctrl.chipColor(order.date_send)}}">
|
|
||||||
{{::order.date_send | date: 'dd/MM/yyyy'}}
|
|
||||||
</span>
|
|
||||||
</vn-td>
|
|
||||||
<vn-td>
|
|
||||||
<span
|
|
||||||
title="{{::order.clientName}}"
|
|
||||||
vn-click-stop="clientDescriptor.show($event, order.clientFk)"
|
|
||||||
class="link">
|
|
||||||
{{::order.clientName}}
|
|
||||||
</span>
|
|
||||||
</vn-td>
|
|
||||||
<vn-td>
|
|
||||||
<span
|
|
||||||
title="{{::order.salesPerson}}"
|
|
||||||
vn-click-stop="workerDescriptor.show($event, order.salesPersonFk)"
|
|
||||||
class="link">
|
|
||||||
{{::order.salesPerson | dashIfEmpty}}
|
|
||||||
</span>
|
|
||||||
</vn-td>
|
|
||||||
</vn-tr>
|
|
||||||
<vn-tr>
|
|
||||||
<vn-td></vn-td>
|
|
||||||
<vn-td>
|
|
||||||
<span>
|
|
||||||
{{::order.date_make | date: 'dd/MM/yyyy HH:mm'}}
|
|
||||||
</span>
|
|
||||||
</vn-td>
|
|
||||||
<vn-td>
|
|
||||||
<span title="{{::order.agencyName}}">
|
|
||||||
{{::order.agencyName | dashIfEmpty}}
|
|
||||||
</span>
|
|
||||||
</vn-td>
|
|
||||||
<vn-td>
|
|
||||||
{{::order.import | currency: 'EUR':2}}
|
|
||||||
</vn-td>
|
|
||||||
</vn-tr>
|
|
||||||
</a>
|
|
||||||
</vn-table>
|
|
||||||
<vn-pagination
|
|
||||||
model="model"
|
|
||||||
class="vn-pt-xs"
|
|
||||||
scroll-selector="vn-monitor-sales-orders vn-table"
|
|
||||||
scroll-offset="100">
|
|
||||||
</vn-pagination>
|
|
||||||
</vn-card>
|
|
||||||
<vn-worker-descriptor-popover
|
|
||||||
vn-id="workerDescriptor">
|
|
||||||
</vn-worker-descriptor-popover>
|
|
||||||
<vn-client-descriptor-popover
|
|
||||||
vn-id="clientDescriptor">
|
|
||||||
</vn-client-descriptor-popover>
|
|
||||||
<vn-contextmenu vn-id="contextmenu" targets="['vn-monitor-sales-orders vn-table']" model="model"
|
|
||||||
expr-builder="$ctrl.exprBuilder(param, value)">
|
|
||||||
<slot-menu>
|
|
||||||
<vn-item translate
|
|
||||||
ng-if="contextmenu.isFilterAllowed()"
|
|
||||||
ng-click="contextmenu.filterBySelection()">
|
|
||||||
Filter by selection
|
|
||||||
</vn-item>
|
|
||||||
<vn-item translate
|
|
||||||
ng-if="contextmenu.isFilterAllowed()"
|
|
||||||
ng-click="contextmenu.excludeSelection()">
|
|
||||||
Exclude selection
|
|
||||||
</vn-item>
|
|
||||||
<vn-item translate
|
|
||||||
ng-if="contextmenu.isFilterAllowed()"
|
|
||||||
ng-click="contextmenu.removeFilter()">
|
|
||||||
Remove filter
|
|
||||||
</vn-item>
|
|
||||||
<vn-item translate
|
|
||||||
ng-click="contextmenu.removeAllFilters()">
|
|
||||||
Remove all filters
|
|
||||||
</vn-item>
|
|
||||||
<vn-item translate
|
|
||||||
ng-if="contextmenu.isActionAllowed()"
|
|
||||||
ng-click="contextmenu.copyValue()">
|
|
||||||
Copy value
|
|
||||||
</vn-item>
|
|
||||||
</slot-menu>
|
|
||||||
</vn-contextmenu>
|
|
||||||
<vn-confirm
|
|
||||||
vn-id="delete"
|
|
||||||
on-accept="$ctrl.onDelete()"
|
|
||||||
question="All the selected elements will be deleted. Are you sure you want to continue?"
|
|
||||||
message="Delete selected elements">
|
|
||||||
</vn-confirm>
|
|
|
@ -1,74 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
import './style.scss';
|
|
||||||
|
|
||||||
export default class Controller extends Section {
|
|
||||||
get checked() {
|
|
||||||
const rows = this.$.model.data || [];
|
|
||||||
const checkedRows = [];
|
|
||||||
for (let row of rows) {
|
|
||||||
if (row.checked)
|
|
||||||
checkedRows.push(row.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return checkedRows;
|
|
||||||
}
|
|
||||||
|
|
||||||
get totalChecked() {
|
|
||||||
return this.checked.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
onDelete() {
|
|
||||||
const params = {deletes: this.checked};
|
|
||||||
const query = `SalesMonitors/deleteOrders`;
|
|
||||||
this.$http.post(query, params).then(
|
|
||||||
() => this.$.model.refresh());
|
|
||||||
}
|
|
||||||
|
|
||||||
chipColor(date) {
|
|
||||||
const today = Date.vnNew();
|
|
||||||
today.setHours(0, 0, 0, 0);
|
|
||||||
|
|
||||||
const orderLanded = new Date(date);
|
|
||||||
orderLanded.setHours(0, 0, 0, 0);
|
|
||||||
|
|
||||||
const difference = today - orderLanded;
|
|
||||||
|
|
||||||
if (difference == 0)
|
|
||||||
return 'warning';
|
|
||||||
if (difference < 0)
|
|
||||||
return 'success';
|
|
||||||
if (difference > 0)
|
|
||||||
return 'alert';
|
|
||||||
}
|
|
||||||
|
|
||||||
exprBuilder(param, value) {
|
|
||||||
switch (param) {
|
|
||||||
case 'date_send':
|
|
||||||
return {[`o.date_send`]: {
|
|
||||||
between: this.dateRange(value)}
|
|
||||||
};
|
|
||||||
case 'clientFk':
|
|
||||||
return {[`c.id`]: value};
|
|
||||||
case 'salesPersonFk':
|
|
||||||
return {[`c.${param}`]: value};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dateRange(value) {
|
|
||||||
const minHour = new Date(value);
|
|
||||||
minHour.setHours(0, 0, 0, 0);
|
|
||||||
const maxHour = new Date(value);
|
|
||||||
maxHour.setHours(23, 59, 59, 59);
|
|
||||||
|
|
||||||
return [minHour, maxHour];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnMonitorSalesOrders', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
require: {
|
|
||||||
main: '^vnMonitorIndex'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,50 +0,0 @@
|
||||||
import './index.js';
|
|
||||||
import crudModel from 'core/mocks/crud-model';
|
|
||||||
|
|
||||||
describe('Component vnMonitorSalesOrders', () => {
|
|
||||||
let controller;
|
|
||||||
let $httpBackend;
|
|
||||||
|
|
||||||
beforeEach(ngModule('monitor'));
|
|
||||||
|
|
||||||
beforeEach(inject(($componentController, _$httpBackend_) => {
|
|
||||||
$httpBackend = _$httpBackend_;
|
|
||||||
const $element = angular.element('<vn-monitor-sales-orders></vn-monitor-sales-orders>');
|
|
||||||
controller = $componentController('vnMonitorSalesOrders', {$element});
|
|
||||||
controller.$.model = crudModel;
|
|
||||||
controller.$.model.data = [
|
|
||||||
{id: 1, name: 'My item 1'},
|
|
||||||
{id: 2, name: 'My item 2'},
|
|
||||||
{id: 3, name: 'My item 3'}
|
|
||||||
];
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('checked() getter', () => {
|
|
||||||
it('should return a the selected rows', () => {
|
|
||||||
const modelData = controller.$.model.data;
|
|
||||||
modelData[0].checked = true;
|
|
||||||
modelData[1].checked = true;
|
|
||||||
|
|
||||||
const result = controller.checked;
|
|
||||||
|
|
||||||
expect(result).toEqual(expect.arrayContaining([1, 2]));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onDelete()', () => {
|
|
||||||
it('should make a query and then call to the model refresh() method', () => {
|
|
||||||
jest.spyOn(controller.$.model, 'refresh');
|
|
||||||
|
|
||||||
const modelData = controller.$.model.data;
|
|
||||||
modelData[0].checked = true;
|
|
||||||
modelData[1].checked = true;
|
|
||||||
|
|
||||||
const expectedParams = {deletes: [1, 2]};
|
|
||||||
$httpBackend.expect('POST', 'SalesMonitors/deleteOrders', expectedParams).respond(200);
|
|
||||||
controller.onDelete();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.$.model.refresh).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,19 +0,0 @@
|
||||||
@import "variables";
|
|
||||||
|
|
||||||
vn-monitor-sales-orders {
|
|
||||||
vn-table.scrollable {
|
|
||||||
max-height: 350px;
|
|
||||||
overflow-x: hidden
|
|
||||||
}
|
|
||||||
|
|
||||||
vn-table a.vn-tbody {
|
|
||||||
& > vn-tr:nth-child(2) {
|
|
||||||
color: gray;
|
|
||||||
|
|
||||||
& > vn-td {
|
|
||||||
border-bottom: $border;
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,120 +0,0 @@
|
||||||
<div class="search-panel">
|
|
||||||
<vn-crud-model
|
|
||||||
auto-load="true"
|
|
||||||
url="Warehouses"
|
|
||||||
data="warehouses">
|
|
||||||
</vn-crud-model>
|
|
||||||
<form id="manifold-form" ng-submit="$ctrl.onSearch()">
|
|
||||||
<vn-horizontal class="vn-px-lg vn-pt-lg">
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="General search"
|
|
||||||
ng-model="filter.search"
|
|
||||||
info="Search ticket by id or alias"
|
|
||||||
vn-focus>
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal class="vn-px-lg">
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Client id"
|
|
||||||
ng-model="filter.clientFk">
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Order id"
|
|
||||||
ng-model="filter.orderFk">
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal class="vn-px-lg">
|
|
||||||
<vn-input-number
|
|
||||||
vn-one
|
|
||||||
min="0"
|
|
||||||
step="1"
|
|
||||||
label="Days onward"
|
|
||||||
ng-model="filter.scopeDays"
|
|
||||||
on-change="$ctrl.scopeDays = value"
|
|
||||||
display-controls="true">
|
|
||||||
</vn-input-number>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal class="vn-px-lg">
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Nickname"
|
|
||||||
ng-model="filter.nickname">
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-worker-autocomplete
|
|
||||||
vn-one
|
|
||||||
ng-model="filter.salesPersonFk"
|
|
||||||
departments="['VT']"
|
|
||||||
label="Sales person">
|
|
||||||
</vn-worker-autocomplete>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Invoice"
|
|
||||||
ng-model="filter.refFk">
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal class="vn-px-lg">
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
label="Agency"
|
|
||||||
ng-model="filter.agencyModeFk"
|
|
||||||
url="AgencyModes/isActive">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
label="State"
|
|
||||||
ng-model="filter.stateFk"
|
|
||||||
url="States">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-autocomplete vn-one
|
|
||||||
data="$ctrl.groupedStates"
|
|
||||||
label="Grouped States"
|
|
||||||
value-field="id"
|
|
||||||
show-field="name"
|
|
||||||
ng-model="filter.alertLevel">
|
|
||||||
<tpl-item>
|
|
||||||
{{name}}
|
|
||||||
</tpl-item>
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal class="vn-px-lg">
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
label="Warehouse"
|
|
||||||
ng-model="filter.warehouseFk"
|
|
||||||
data="warehouses">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
label="Province"
|
|
||||||
ng-model="filter.provinceFk"
|
|
||||||
url="Provinces">
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal class="vn-px-lg">
|
|
||||||
<vn-check
|
|
||||||
vn-one
|
|
||||||
label="My team"
|
|
||||||
ng-model="filter.myTeam"
|
|
||||||
triple-state="true">
|
|
||||||
</vn-check>
|
|
||||||
<vn-check
|
|
||||||
vn-one
|
|
||||||
label="With problems"
|
|
||||||
ng-model="filter.problems"
|
|
||||||
triple-state="true">
|
|
||||||
</vn-check>
|
|
||||||
<vn-check
|
|
||||||
vn-one
|
|
||||||
label="Pending"
|
|
||||||
ng-model="filter.pending"
|
|
||||||
triple-state="true">
|
|
||||||
</vn-check>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal class="vn-px-lg vn-pb-lg vn-mt-lg">
|
|
||||||
<vn-submit label="Search"></vn-submit>
|
|
||||||
</vn-horizontal>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
|
@ -1,59 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import SearchPanel from 'core/components/searchbar/search-panel';
|
|
||||||
|
|
||||||
class Controller extends SearchPanel {
|
|
||||||
constructor($, $element) {
|
|
||||||
super($, $element);
|
|
||||||
this.filter = this.$.filter;
|
|
||||||
|
|
||||||
this.getGroupedStates();
|
|
||||||
}
|
|
||||||
|
|
||||||
getGroupedStates() {
|
|
||||||
let groupedStates = [];
|
|
||||||
this.$http.get('AlertLevels').then(res => {
|
|
||||||
for (let state of res.data) {
|
|
||||||
groupedStates.push({
|
|
||||||
id: state.id,
|
|
||||||
code: state.code,
|
|
||||||
name: this.$t(state.code)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this.groupedStates = groupedStates;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
get from() {
|
|
||||||
return this._from;
|
|
||||||
}
|
|
||||||
|
|
||||||
set from(value) {
|
|
||||||
this._from = value;
|
|
||||||
this.filter.scopeDays = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
get to() {
|
|
||||||
return this._to;
|
|
||||||
}
|
|
||||||
|
|
||||||
set to(value) {
|
|
||||||
this._to = value;
|
|
||||||
this.filter.scopeDays = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
get scopeDays() {
|
|
||||||
return this._scopeDays;
|
|
||||||
}
|
|
||||||
|
|
||||||
set scopeDays(value) {
|
|
||||||
this._scopeDays = value;
|
|
||||||
|
|
||||||
this.filter.from = null;
|
|
||||||
this.filter.to = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnMonitorSalesSearchPanel', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,71 +0,0 @@
|
||||||
import './index';
|
|
||||||
|
|
||||||
describe('Monitor Component vnMonitorSalesSearchPanel', () => {
|
|
||||||
let $httpBackend;
|
|
||||||
let controller;
|
|
||||||
|
|
||||||
beforeEach(ngModule('monitor'));
|
|
||||||
|
|
||||||
beforeEach(inject(($componentController, _$httpBackend_) => {
|
|
||||||
$httpBackend = _$httpBackend_;
|
|
||||||
controller = $componentController('vnMonitorSalesSearchPanel', {$element: null});
|
|
||||||
controller.$t = () => {};
|
|
||||||
controller.filter = {};
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('getGroupedStates()', () => {
|
|
||||||
it('should set an array of groupedStates with the adition of a name translation', () => {
|
|
||||||
jest.spyOn(controller, '$t').mockReturnValue('miCodigo');
|
|
||||||
const data = [
|
|
||||||
{
|
|
||||||
id: 9999,
|
|
||||||
code: 'myCode'
|
|
||||||
}
|
|
||||||
];
|
|
||||||
$httpBackend.whenGET('AlertLevels').respond(data);
|
|
||||||
controller.getGroupedStates();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.groupedStates).toEqual([{
|
|
||||||
id: 9999,
|
|
||||||
code: 'myCode',
|
|
||||||
name: 'miCodigo'
|
|
||||||
}]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('from() setter', () => {
|
|
||||||
it('should clear the scope days when setting the from property', () => {
|
|
||||||
controller.filter.scopeDays = 1;
|
|
||||||
|
|
||||||
controller.from = Date.vnNew();
|
|
||||||
|
|
||||||
expect(controller.filter.scopeDays).toBeNull();
|
|
||||||
expect(controller.from).toBeDefined();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('to() setter', () => {
|
|
||||||
it('should clear the scope days when setting the to property', () => {
|
|
||||||
controller.filter.scopeDays = 1;
|
|
||||||
|
|
||||||
controller.to = Date.vnNew();
|
|
||||||
|
|
||||||
expect(controller.filter.scopeDays).toBeNull();
|
|
||||||
expect(controller.to).toBeDefined();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('scopeDays() setter', () => {
|
|
||||||
it('should clear the date range when setting the scopeDays property', () => {
|
|
||||||
controller.filter.from = Date.vnNew();
|
|
||||||
controller.filter.to = Date.vnNew();
|
|
||||||
|
|
||||||
controller.scopeDays = 1;
|
|
||||||
|
|
||||||
expect(controller.filter.from).toBeNull();
|
|
||||||
expect(controller.filter.to).toBeNull();
|
|
||||||
expect(controller.scopeDays).toBeDefined();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,85 +0,0 @@
|
||||||
@import "variables";
|
|
||||||
@import "effects";
|
|
||||||
|
|
||||||
vn-monitor-index {
|
|
||||||
.header {
|
|
||||||
padding: 12px 0 5px 0;
|
|
||||||
color: gray;
|
|
||||||
font-size: 1.2rem;
|
|
||||||
border-bottom: $border;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
|
|
||||||
& > vn-none > vn-icon {
|
|
||||||
@extend %clickable-light;
|
|
||||||
color: $color-button;
|
|
||||||
font-size: 1.4rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
vn-none > .arrow {
|
|
||||||
transition: transform 200ms;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vn-monitor-sales-clients {
|
|
||||||
vn-card {
|
|
||||||
margin-right: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header {
|
|
||||||
padding-right: 15px;
|
|
||||||
|
|
||||||
& > vn-none > .arrow {
|
|
||||||
display: none
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vn-table.scrollable {
|
|
||||||
height: 300px
|
|
||||||
}
|
|
||||||
|
|
||||||
vn-horizontal {
|
|
||||||
flex-wrap: wrap
|
|
||||||
}
|
|
||||||
|
|
||||||
.hidden {
|
|
||||||
vn-card {
|
|
||||||
display: none
|
|
||||||
}
|
|
||||||
|
|
||||||
.header > vn-none > .arrow {
|
|
||||||
transform: rotate(180deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width:1150px) {
|
|
||||||
vn-monitor-index {
|
|
||||||
& > vn-horizontal {
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
vn-monitor-sales-clients,
|
|
||||||
vn-monitor-sales-orders {
|
|
||||||
width: 100%
|
|
||||||
}
|
|
||||||
|
|
||||||
vn-monitor-sales-clients {
|
|
||||||
margin-bottom: 15px
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vn-monitor-sales-clients {
|
|
||||||
vn-card {
|
|
||||||
margin-right: 0
|
|
||||||
}
|
|
||||||
|
|
||||||
.header {
|
|
||||||
padding-right: 0;
|
|
||||||
|
|
||||||
& > vn-none > .arrow {
|
|
||||||
display: inline-block
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,270 +0,0 @@
|
||||||
<vn-crud-model
|
|
||||||
vn-id="model"
|
|
||||||
url="SalesMonitors/salesFilter"
|
|
||||||
auto-load="false"
|
|
||||||
limit="20">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-portal slot="topbar">
|
|
||||||
<vn-searchbar
|
|
||||||
vn-focus
|
|
||||||
panel="vn-monitor-sales-search-panel"
|
|
||||||
placeholder="Search tickets"
|
|
||||||
info="Search ticket by id or alias"
|
|
||||||
model="model"
|
|
||||||
fetch-params="$ctrl.fetchParams($params)"
|
|
||||||
suggested-filter="$ctrl.filterParams"
|
|
||||||
auto-state="false">
|
|
||||||
</vn-searchbar>
|
|
||||||
</vn-portal>
|
|
||||||
<vn-horizontal class="header">
|
|
||||||
<vn-one translate>
|
|
||||||
Tickets monitor
|
|
||||||
</vn-one>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-card>
|
|
||||||
<smart-table
|
|
||||||
model="model"
|
|
||||||
view-config-id="ticketsMonitor"
|
|
||||||
options="$ctrl.smartTableOptions"
|
|
||||||
expr-builder="$ctrl.exprBuilder(param, value)">
|
|
||||||
<slot-actions>
|
|
||||||
<vn-check
|
|
||||||
label="Auto-refresh"
|
|
||||||
vn-tooltip="Toggle auto-refresh every 2 minutes"
|
|
||||||
on-change="$ctrl.autoRefresh(value)">
|
|
||||||
</vn-check>
|
|
||||||
</slot-actions>
|
|
||||||
<slot-table>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th field="totalProblems" menu-enabled="false">
|
|
||||||
<span translate>Problems</span>
|
|
||||||
</th>
|
|
||||||
<th field="id">
|
|
||||||
<span translate>Identifier</span>
|
|
||||||
</th>
|
|
||||||
<th field="nickname">
|
|
||||||
<span translate>Client</span>
|
|
||||||
</th>
|
|
||||||
<th field="salesPersonFk">
|
|
||||||
<span translate>Salesperson</span>
|
|
||||||
</th>
|
|
||||||
<th field="shippedDate" shrink-date filter-enabled="false">
|
|
||||||
<span translate>Date</span>
|
|
||||||
</th>
|
|
||||||
<th field="theoreticalHour" filter-enabled="false">
|
|
||||||
<span translate>Theoretical</span>
|
|
||||||
</th>
|
|
||||||
<th field="practicalHour" filter-enabled="false">
|
|
||||||
<span translate>Practical</span>
|
|
||||||
</th>
|
|
||||||
<th field="preparationHour" filter-enabled="false">
|
|
||||||
<span translate>Preparation</span>
|
|
||||||
</th>
|
|
||||||
<th field="provinceFk">
|
|
||||||
<span translate>Province</span>
|
|
||||||
</th>
|
|
||||||
<th field="stateFk">
|
|
||||||
<span translate>State</span>
|
|
||||||
</th>
|
|
||||||
<th field="isFragile" number>
|
|
||||||
<span translate>Fragile</span>
|
|
||||||
</th>
|
|
||||||
<th field="zoneFk">
|
|
||||||
<span translate>Zone</span>
|
|
||||||
</th>
|
|
||||||
<th field="totalWithVat" shrink>
|
|
||||||
<span translate>Total</span>
|
|
||||||
</th>
|
|
||||||
<th shrink></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr ng-repeat="ticket in model.data track by ticket.id"
|
|
||||||
vn-anchor="{
|
|
||||||
state: 'ticket.card.summary',
|
|
||||||
params: {id: ticket.id},
|
|
||||||
target: '_blank'
|
|
||||||
}">
|
|
||||||
<td>
|
|
||||||
<vn-icon
|
|
||||||
ng-show="ticket.isTaxDataChecked === 0"
|
|
||||||
translate-attr="{title: 'No verified data'}"
|
|
||||||
class="bright"
|
|
||||||
icon="icon-no036">
|
|
||||||
</vn-icon>
|
|
||||||
<vn-icon
|
|
||||||
ng-show="ticket.hasTicketRequest"
|
|
||||||
translate-attr="{title: 'Purchase request'}"
|
|
||||||
class="bright"
|
|
||||||
icon="icon-buyrequest">
|
|
||||||
</vn-icon>
|
|
||||||
<vn-icon
|
|
||||||
ng-show="ticket.itemShortage"
|
|
||||||
translate-attr="{title: 'Not visible'}"
|
|
||||||
class="bright"
|
|
||||||
icon="icon-unavailable">
|
|
||||||
</vn-icon>
|
|
||||||
<vn-icon
|
|
||||||
ng-show="ticket.isFreezed"
|
|
||||||
translate-attr="{title: 'Client frozen'}"
|
|
||||||
class="bright"
|
|
||||||
icon="icon-frozen">
|
|
||||||
</vn-icon>
|
|
||||||
<vn-icon
|
|
||||||
ng-show="ticket.risk"
|
|
||||||
ng-class="{'highRisk': ticket.hasHighRisk}"
|
|
||||||
title="{{$ctrl.$t('Risk')}}: {{ticket.risk}}"
|
|
||||||
class="bright"
|
|
||||||
icon="icon-risk">
|
|
||||||
</vn-icon>
|
|
||||||
<vn-icon
|
|
||||||
ng-show="ticket.hasComponentLack"
|
|
||||||
translate-attr="{title: 'Component lack'}"
|
|
||||||
class="bright"
|
|
||||||
icon="icon-components">
|
|
||||||
</vn-icon>
|
|
||||||
<vn-icon
|
|
||||||
ng-show="ticket.isTooLittle"
|
|
||||||
translate-attr="{title: 'Ticket too little'}"
|
|
||||||
class="bright"
|
|
||||||
icon="icon-isTooLittle">
|
|
||||||
</vn-icon>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<span
|
|
||||||
vn-click-stop="ticketDescriptor.show($event, ticket.id)"
|
|
||||||
class="link">
|
|
||||||
{{ticket.id}}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td name="nickname">
|
|
||||||
<span
|
|
||||||
title="{{ticket.nickname}}"
|
|
||||||
vn-click-stop="clientDescriptor.show($event, ticket.clientFk)"
|
|
||||||
class="link">
|
|
||||||
{{ticket.nickname}}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<span
|
|
||||||
title="{{ticket.userName}}"
|
|
||||||
vn-click-stop="workerDescriptor.show($event, ticket.salesPersonFk)"
|
|
||||||
class="link">
|
|
||||||
{{ticket.userName | dashIfEmpty}}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<span class="chip {{$ctrl.compareDate(ticket.shippedDate)}}">
|
|
||||||
{{ticket.shippedDate | date: 'dd/MM/yyyy'}}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td>{{ticket.zoneLanding | date: 'HH:mm'}}</td>
|
|
||||||
<td>{{ticket.practicalHour | date: 'HH:mm'}}</td>
|
|
||||||
<td>{{ticket.shipped | date: 'HH:mm'}}</td>
|
|
||||||
<td>{{ticket.province}}</td>
|
|
||||||
<td>
|
|
||||||
<span
|
|
||||||
ng-show="ticket.refFk"
|
|
||||||
title="{{ticket.refFk}}"
|
|
||||||
vn-click-stop="invoiceOutDescriptor.show($event, ticket.invoiceOutId)"
|
|
||||||
class="link">
|
|
||||||
{{ticket.refFk}}
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
ng-show="!ticket.refFk"
|
|
||||||
class="chip {{ticket.classColor}}">
|
|
||||||
{{ticket.state}}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td number>
|
|
||||||
<vn-icon
|
|
||||||
ng-show="ticket.isFragile"
|
|
||||||
translate-attr="{title: 'Is fragile'}"
|
|
||||||
class="bright"
|
|
||||||
icon="local_bar">
|
|
||||||
</vn-icon>
|
|
||||||
</td>
|
|
||||||
<td name="zone">
|
|
||||||
<span
|
|
||||||
title="{{ticket.zoneName}}"
|
|
||||||
vn-click-stop="zoneDescriptor.show($event, ticket.zoneFk)"
|
|
||||||
class="link">
|
|
||||||
{{ticket.zoneName | dashIfEmpty}}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td number>
|
|
||||||
<span class="chip {{$ctrl.totalPriceColor(ticket)}}">
|
|
||||||
{{(ticket.totalWithVat ? ticket.totalWithVat : 0) | currency: 'EUR': 2}}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td actions>
|
|
||||||
<vn-icon-button
|
|
||||||
vn-anchor="{
|
|
||||||
state: 'ticket.card.sale',
|
|
||||||
params: {id: ticket.id},
|
|
||||||
target: '_blank'
|
|
||||||
}"
|
|
||||||
vn-tooltip="Go to lines"
|
|
||||||
icon="icon-lines">
|
|
||||||
</vn-icon-button>
|
|
||||||
<vn-icon-button
|
|
||||||
vn-click-stop="$ctrl.preview(ticket)"
|
|
||||||
vn-tooltip="Preview"
|
|
||||||
icon="preview">
|
|
||||||
</vn-icon-button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</slot-table>
|
|
||||||
</smart-table>
|
|
||||||
</vn-card>
|
|
||||||
<vn-ticket-descriptor-popover
|
|
||||||
vn-id="ticketDescriptor">
|
|
||||||
</vn-ticket-descriptor-popover>
|
|
||||||
<vn-worker-descriptor-popover
|
|
||||||
vn-id="workerDescriptor">
|
|
||||||
</vn-worker-descriptor-popover>
|
|
||||||
<vn-client-descriptor-popover
|
|
||||||
vn-id="clientDescriptor">
|
|
||||||
</vn-client-descriptor-popover>
|
|
||||||
<vn-zone-descriptor-popover
|
|
||||||
vn-id="zoneDescriptor">
|
|
||||||
</vn-zone-descriptor-popover>
|
|
||||||
<vn-popup vn-id="summary">
|
|
||||||
<vn-ticket-summary
|
|
||||||
ticket="$ctrl.selectedTicket"
|
|
||||||
model="model">
|
|
||||||
</vn-ticket-summary>
|
|
||||||
</vn-popup>
|
|
||||||
<vn-contextmenu vn-id="contextmenu" targets="['vn-monitor-sales-tickets smart-table']" model="model"
|
|
||||||
expr-builder="$ctrl.exprBuilder(param, value)">
|
|
||||||
<slot-menu>
|
|
||||||
<vn-item translate
|
|
||||||
ng-if="contextmenu.isFilterAllowed()"
|
|
||||||
ng-click="contextmenu.filterBySelection()">
|
|
||||||
Filter by selection
|
|
||||||
</vn-item>
|
|
||||||
<vn-item translate
|
|
||||||
ng-if="contextmenu.isFilterAllowed()"
|
|
||||||
ng-click="contextmenu.excludeSelection()">
|
|
||||||
Exclude selection
|
|
||||||
</vn-item>
|
|
||||||
<vn-item translate
|
|
||||||
ng-if="contextmenu.isFilterAllowed()"
|
|
||||||
ng-click="contextmenu.removeFilter()">
|
|
||||||
Remove filter
|
|
||||||
</vn-item>
|
|
||||||
<vn-item translate
|
|
||||||
ng-click="contextmenu.removeAllFilters()">
|
|
||||||
Remove all filters
|
|
||||||
</vn-item>
|
|
||||||
<vn-item translate
|
|
||||||
ng-if="contextmenu.isActionAllowed()"
|
|
||||||
ng-click="contextmenu.copyValue()">
|
|
||||||
Copy value
|
|
||||||
</vn-item>
|
|
||||||
</slot-menu>
|
|
||||||
</vn-contextmenu>
|
|
|
@ -1,178 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
import './style.scss';
|
|
||||||
|
|
||||||
export default class Controller extends Section {
|
|
||||||
constructor($element, $) {
|
|
||||||
super($element, $);
|
|
||||||
|
|
||||||
this.filterParams = this.fetchParams();
|
|
||||||
this.smartTableOptions = {
|
|
||||||
activeButtons: {
|
|
||||||
search: true,
|
|
||||||
shownColumns: true,
|
|
||||||
},
|
|
||||||
columns: [
|
|
||||||
{
|
|
||||||
field: 'totalProblems',
|
|
||||||
searchable: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'salesPersonFk',
|
|
||||||
autocomplete: {
|
|
||||||
url: 'Workers/activeWithInheritedRole',
|
|
||||||
where: `{role: 'salesPerson'}`,
|
|
||||||
searchFunction: '{firstName: $search}',
|
|
||||||
showField: 'nickname',
|
|
||||||
valueField: 'id',
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'provinceFk',
|
|
||||||
autocomplete: {
|
|
||||||
url: 'Provinces',
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'stateFk',
|
|
||||||
autocomplete: {
|
|
||||||
url: 'States',
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'zoneFk',
|
|
||||||
autocomplete: {
|
|
||||||
url: 'Zones',
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'warehouseFk',
|
|
||||||
autocomplete: {
|
|
||||||
url: 'Warehouses',
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'shippedDate',
|
|
||||||
datepicker: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'theoreticalHour',
|
|
||||||
searchable: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'preparationHour',
|
|
||||||
searchable: false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
$onInit() {
|
|
||||||
if (!this.$params.q) {
|
|
||||||
this.$.$applyAsync(
|
|
||||||
() => this.$.model.applyFilter(null, this.filterParams));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fetchParams($params = {}) {
|
|
||||||
const excludedParams = [
|
|
||||||
'search',
|
|
||||||
'clientFk',
|
|
||||||
'orderFk',
|
|
||||||
'refFk',
|
|
||||||
'scopeDays'
|
|
||||||
];
|
|
||||||
|
|
||||||
const hasExcludedParams = excludedParams.some(param => {
|
|
||||||
return $params && $params[param] != undefined;
|
|
||||||
});
|
|
||||||
const hasParams = Object.entries($params).length;
|
|
||||||
if (!hasParams || !hasExcludedParams)
|
|
||||||
$params.scopeDays = 1;
|
|
||||||
|
|
||||||
if (typeof $params.scopeDays === 'number') {
|
|
||||||
const from = Date.vnNew();
|
|
||||||
from.setHours(0, 0, 0, 0);
|
|
||||||
|
|
||||||
const to = new Date(from.getTime());
|
|
||||||
to.setDate(to.getDate() + $params.scopeDays);
|
|
||||||
to.setHours(23, 59, 59, 999);
|
|
||||||
|
|
||||||
Object.assign($params, {from, to});
|
|
||||||
}
|
|
||||||
|
|
||||||
return $params;
|
|
||||||
}
|
|
||||||
|
|
||||||
compareDate(date) {
|
|
||||||
let today = Date.vnNew();
|
|
||||||
today.setHours(0, 0, 0, 0);
|
|
||||||
let timeTicket = new Date(date);
|
|
||||||
timeTicket.setHours(0, 0, 0, 0);
|
|
||||||
|
|
||||||
let comparation = today - timeTicket;
|
|
||||||
|
|
||||||
if (comparation == 0)
|
|
||||||
return 'warning';
|
|
||||||
if (comparation < 0)
|
|
||||||
return 'success';
|
|
||||||
}
|
|
||||||
|
|
||||||
totalPriceColor(ticket) {
|
|
||||||
const total = parseInt(ticket.totalWithVat);
|
|
||||||
if (total > 0 && total < 50)
|
|
||||||
return 'warning';
|
|
||||||
}
|
|
||||||
|
|
||||||
exprBuilder(param, value) {
|
|
||||||
switch (param) {
|
|
||||||
case 'stateFk':
|
|
||||||
return {'ts.stateFk': value};
|
|
||||||
case 'salesPersonFk':
|
|
||||||
return {'c.salesPersonFk': value};
|
|
||||||
case 'provinceFk':
|
|
||||||
return {'a.provinceFk': value};
|
|
||||||
case 'theoreticalHour':
|
|
||||||
return {'z.hour': value};
|
|
||||||
case 'practicalHour':
|
|
||||||
return {'zed.etc': value};
|
|
||||||
case 'shippedDate':
|
|
||||||
return {'t.shipped': {
|
|
||||||
between: this.dateRange(value)}
|
|
||||||
};
|
|
||||||
case 'nickname':
|
|
||||||
return {[`t.nickname`]: {like: `%${value}%`}};
|
|
||||||
case 'zoneFk':
|
|
||||||
case 'totalWithVat':
|
|
||||||
return {[`t.${param}`]: value};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dateRange(value) {
|
|
||||||
const minHour = new Date(value);
|
|
||||||
minHour.setHours(0, 0, 0, 0);
|
|
||||||
const maxHour = new Date(value);
|
|
||||||
maxHour.setHours(23, 59, 59, 59);
|
|
||||||
|
|
||||||
return [minHour, maxHour];
|
|
||||||
}
|
|
||||||
|
|
||||||
preview(ticket) {
|
|
||||||
this.selectedTicket = ticket;
|
|
||||||
this.$.summary.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
autoRefresh(value) {
|
|
||||||
if (value)
|
|
||||||
this.refreshTimer = setInterval(() => this.$.model.refresh(), 120000);
|
|
||||||
else {
|
|
||||||
clearInterval(this.refreshTimer);
|
|
||||||
this.refreshTimer = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnMonitorSalesTickets', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,133 +0,0 @@
|
||||||
import './index.js';
|
|
||||||
describe('Component vnMonitorSalesTickets', () => {
|
|
||||||
let controller;
|
|
||||||
let $window;
|
|
||||||
let tickets = [{
|
|
||||||
id: 1,
|
|
||||||
clientFk: 1,
|
|
||||||
checked: false,
|
|
||||||
totalWithVat: 10.5
|
|
||||||
}, {
|
|
||||||
id: 2,
|
|
||||||
clientFk: 1,
|
|
||||||
checked: true,
|
|
||||||
totalWithVat: 20.5
|
|
||||||
}, {
|
|
||||||
id: 3,
|
|
||||||
clientFk: 1,
|
|
||||||
checked: true,
|
|
||||||
totalWithVat: 30
|
|
||||||
}];
|
|
||||||
|
|
||||||
beforeEach(ngModule('monitor'));
|
|
||||||
|
|
||||||
beforeEach(inject(($componentController, _$window_) => {
|
|
||||||
$window = _$window_;
|
|
||||||
const $element = angular.element('<vn-monitor-sales-tickets></vn-monitor-sales-tickets>');
|
|
||||||
controller = $componentController('vnMonitorSalesTickets', {$element});
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('fetchParams()', () => {
|
|
||||||
it('should return a range of dates with passed scope days', () => {
|
|
||||||
let params = controller.fetchParams({
|
|
||||||
scopeDays: 2
|
|
||||||
});
|
|
||||||
const from = Date.vnNew();
|
|
||||||
from.setHours(0, 0, 0, 0);
|
|
||||||
const to = new Date(from.getTime());
|
|
||||||
to.setDate(to.getDate() + params.scopeDays);
|
|
||||||
to.setHours(23, 59, 59, 999);
|
|
||||||
|
|
||||||
const expectedParams = {
|
|
||||||
from,
|
|
||||||
scopeDays: params.scopeDays,
|
|
||||||
to
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(params).toEqual(expectedParams);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return default value for scope days', () => {
|
|
||||||
let params = controller.fetchParams({
|
|
||||||
scopeDays: 1
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(params.scopeDays).toEqual(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return the given scope days', () => {
|
|
||||||
let params = controller.fetchParams({
|
|
||||||
scopeDays: 2
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(params.scopeDays).toEqual(2);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('compareDate()', () => {
|
|
||||||
it('should return warning when the date is the present', () => {
|
|
||||||
let today = Date.vnNew();
|
|
||||||
let result = controller.compareDate(today);
|
|
||||||
|
|
||||||
expect(result).toEqual('warning');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return sucess when the date is in the future', () => {
|
|
||||||
let futureDate = Date.vnNew();
|
|
||||||
futureDate = futureDate.setDate(futureDate.getDate() + 10);
|
|
||||||
let result = controller.compareDate(futureDate);
|
|
||||||
|
|
||||||
expect(result).toEqual('success');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return undefined when the date is in the past', () => {
|
|
||||||
let pastDate = Date.vnNew();
|
|
||||||
pastDate = pastDate.setDate(pastDate.getDate() - 10);
|
|
||||||
let result = controller.compareDate(pastDate);
|
|
||||||
|
|
||||||
expect(result).toEqual(undefined);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('totalPriceColor()', () => {
|
|
||||||
it('should return "warning" when the ticket amount is less than 50€', () => {
|
|
||||||
const result = controller.totalPriceColor({totalWithVat: '8.50'});
|
|
||||||
|
|
||||||
expect(result).toEqual('warning');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('dateRange()', () => {
|
|
||||||
it('should return two dates with the hours at the start and end of the given date', () => {
|
|
||||||
const now = Date.vnNew();
|
|
||||||
|
|
||||||
const today = now.getDate();
|
|
||||||
|
|
||||||
const dateRange = controller.dateRange(now);
|
|
||||||
const start = dateRange[0].toString();
|
|
||||||
const end = dateRange[1].toString();
|
|
||||||
|
|
||||||
expect(start).toContain(today);
|
|
||||||
expect(start).toContain('00:00:00');
|
|
||||||
|
|
||||||
expect(end).toContain(today);
|
|
||||||
expect(end).toContain('23:59:59');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('preview()', () => {
|
|
||||||
it('should show the dialog summary', () => {
|
|
||||||
controller.$.summary = {show: () => {}};
|
|
||||||
jest.spyOn(controller.$.summary, 'show');
|
|
||||||
|
|
||||||
let event = new MouseEvent('click', {
|
|
||||||
view: $window,
|
|
||||||
bubbles: true,
|
|
||||||
cancelable: true
|
|
||||||
});
|
|
||||||
controller.preview(event, tickets[0]);
|
|
||||||
|
|
||||||
expect(controller.$.summary.show).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,47 +0,0 @@
|
||||||
@import "variables";
|
|
||||||
|
|
||||||
vn-monitor-sales-tickets {
|
|
||||||
@media screen and (max-width: 1440px) {
|
|
||||||
.expendable {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vn-th.icon-field,
|
|
||||||
vn-th.icon-field *,
|
|
||||||
vn-td.icon-field,
|
|
||||||
vn-td.icon-field * {
|
|
||||||
padding: 0;
|
|
||||||
max-width: 50px
|
|
||||||
}
|
|
||||||
|
|
||||||
vn-th[field="nickname"],
|
|
||||||
vn-td[name="nickname"] {
|
|
||||||
min-width: 250px
|
|
||||||
}
|
|
||||||
|
|
||||||
vn-td.icon-field > vn-icon {
|
|
||||||
margin-left: 3px;
|
|
||||||
margin-right: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
vn-table.scrollable.lg {
|
|
||||||
height: 736px
|
|
||||||
}
|
|
||||||
|
|
||||||
tbody tr[ng-repeat]:focus {
|
|
||||||
background-color: $color-primary-light
|
|
||||||
}
|
|
||||||
|
|
||||||
.highRisk i {
|
|
||||||
color: $color-alert
|
|
||||||
}
|
|
||||||
|
|
||||||
td[name="nickname"] {
|
|
||||||
max-width: 200px
|
|
||||||
}
|
|
||||||
|
|
||||||
td[name="zone"] {
|
|
||||||
max-width: 150px
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue