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

This commit is contained in:
Carlos Jimenez Ruiz 2022-05-25 07:39:42 +00:00
commit 402aa567dd
26 changed files with 405 additions and 96 deletions

View File

@ -46,7 +46,7 @@ module.exports = Self => {
const {data} = await Self.getUserStatus(recipient.name); const {data} = await Self.getUserStatus(recipient.name);
if (data) { if (data) {
if (data.status === 'offline' || data.status === 'busy') { if (data.status === 'offline' || data.status === 'busy') {
// Send message to department room // Send message to department room
const workerDepartment = await models.WorkerDepartment.findById(recipientId, { const workerDepartment = await models.WorkerDepartment.findById(recipientId, {
include: { include: {

View File

@ -1,5 +1,5 @@
module.exports = Self => { module.exports = Self => {
Self.remoteMethodCtx('setSaleQuantity', { Self.remoteMethod('setSaleQuantity', {
description: 'Update sale quantity', description: 'Update sale quantity',
accessType: 'WRITE', accessType: 'WRITE',
accepts: [{ accepts: [{
@ -24,11 +24,13 @@ module.exports = Self => {
} }
}); });
Self.setSaleQuantity = async ctx => { Self.setSaleQuantity = async(saleId, quantity) => {
const args = ctx.args;
const models = Self.app.models; const models = Self.app.models;
const sale = await models.Sale.findById(args.saleId); const sale = await models.Sale.findById(saleId);
return await sale.updateAttribute('quantity', args.quantity); return await sale.updateAttributes({
originalQuantity: sale.quantity,
quantity: quantity
});
}; };
}; };

View File

@ -5,19 +5,12 @@ describe('setSaleQuantity()', () => {
const saleId = 30; const saleId = 30;
const newQuantity = 10; const newQuantity = 10;
const ctx = {
args: {
saleId: saleId,
quantity: newQuantity
}
};
const originalSale = await models.Sale.findById(saleId); const originalSale = await models.Sale.findById(saleId);
await models.Collection.setSaleQuantity(ctx); await models.Collection.setSaleQuantity(saleId, newQuantity);
const updateSale = await models.Sale.findById(saleId); const updateSale = await models.Sale.findById(saleId);
expect(updateSale.quantity).toBeLessThan(originalSale.quantity); expect(updateSale.originalQuantity).toEqual(originalSale.quantity);
expect(updateSale.quantity).toEqual(newQuantity); expect(updateSale.quantity).toEqual(newQuantity);
}); });
}); });

View File

@ -1,14 +0,0 @@
create table `vn`.`invoiceOut_queue`
(
invoiceFk int(10) unsigned not null,
queued datetime default now() not null,
printed datetime null,
`status` VARCHAR(50) default '' null,
constraint invoiceOut_queue_pk
primary key (invoiceFk),
constraint invoiceOut_queue_invoiceOut_id_fk
foreign key (invoiceFk) references invoiceOut (id)
on update cascade on delete cascade
)
comment 'Queue for PDF invoicing';

View File

@ -3,7 +3,7 @@ CREATE TABLE `vn`.`clientUnpaid` (
`dated` date NOT NULL, `dated` date NOT NULL,
`amount` double DEFAULT 0, `amount` double DEFAULT 0,
PRIMARY KEY (`clientFk`), PRIMARY KEY (`clientFk`),
CONSTRAINT `clientUnpaid_clientFk` FOREIGN KEY (`clientFk`) REFERENCES `client` (`id`) ON UPDATE CASCADE CONSTRAINT `clientUnpaid_clientFk` FOREIGN KEY (`clientFk`) REFERENCES `vn`.`client` (`id`) ON UPDATE CASCADE
); );
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)

View File

@ -0,0 +1,8 @@
CREATE TABLE `vn`.`invoiceOut_queue` (
`invoiceFk` int(10) unsigned not null,
`queued` datetime default now() not null,
`printed` datetime null,
`status` VARCHAR(50) DEFAULT '' NULL,
CONSTRAINT `invoiceOut_queue_pk` PRIMARY KEY (`invoiceFk`),
CONSTRAINT `invoiceOut_queue_invoiceOut_id_fk` FOREIGN KEY (`invoiceFk`) REFERENCES `vn`.`invoiceOut` (`id`) ON UPDATE CASCADE ON DELETE CASCADE
) comment 'Queue for PDF invoicing';

View File

@ -1633,51 +1633,59 @@ INSERT INTO `hedera`.`orderRowComponent`(`rowFk`, `componentFk`, `price`)
INSERT INTO `hedera`.`visit`(`id`, `firstAgentFk`) INSERT INTO `hedera`.`visit`(`id`, `firstAgentFk`)
VALUES VALUES
(1, NULL), (1, NULL),
(2, NULL), (2, NULL),
(3, NULL), (3, NULL),
(4, NULL), (4, NULL),
(5, NULL), (5, NULL),
(6, NULL), (6, NULL),
(7, NULL), (7, NULL),
(8, NULL), (8, NULL),
(9, NULL); (9, NULL),
(10, NULL),
(11, NULL);
INSERT INTO `hedera`.`visitAgent`(`id`, `visitFk`) INSERT INTO `hedera`.`visitAgent`(`id`, `visitFk`)
VALUES VALUES
(1, 1), (1, 1),
(2, 2), (2, 2),
(3, 3), (3, 3),
(4, 4), (4, 4),
(5, 5), (5, 5),
(6, 6), (6, 6),
(7, 7), (7, 7),
(8, 8), (8, 8),
(9, 9); (9, 9),
(10, 10),
(11, 11);
INSERT INTO `hedera`.`visitAccess`(`id`, `agentFk`, `stamp`) INSERT INTO `hedera`.`visitAccess`(`id`, `agentFk`, `stamp`)
VALUES VALUES
(1, 1, CURDATE()), (1, 1, CURDATE()),
(2, 2, CURDATE()), (2, 2, CURDATE()),
(3, 3, CURDATE()), (3, 3, CURDATE()),
(4, 4, CURDATE()), (4, 4, CURDATE()),
(5, 5, CURDATE()), (5, 5, CURDATE()),
(6, 6, CURDATE()), (6, 6, CURDATE()),
(7, 7, CURDATE()), (7, 7, CURDATE()),
(8, 8, CURDATE()), (8, 8, CURDATE()),
(9, 9, CURDATE()); (9, 9, CURDATE()),
(10, 10, CURDATE()),
(11, 11, CURDATE());
INSERT INTO `hedera`.`visitUser`(`id`, `accessFk`, `userFk`, `stamp`) INSERT INTO `hedera`.`visitUser`(`id`, `accessFk`, `userFk`, `stamp`)
VALUES VALUES
(1, 1, 1101, CURDATE()), (1, 1, 1101, CURDATE()),
(2, 2, 1101, CURDATE()), (2, 2, 1101, CURDATE()),
(3, 3, 1101, CURDATE()), (3, 3, 1101, CURDATE()),
(4, 4, 1102, CURDATE()), (4, 4, 1102, CURDATE()),
(5, 5, 1102, CURDATE()), (5, 5, 1102, CURDATE()),
(6, 6, 1102, CURDATE()), (6, 6, 1102, CURDATE()),
(7, 7, 1103, CURDATE()), (7, 7, 1103, CURDATE()),
(8, 8, 1103, CURDATE()), (8, 8, 1103, CURDATE()),
(9, 9, 1103, CURDATE()); (9, 9, 1103, CURDATE()),
(10, 10, 1102, DATE_SUB(CURDATE(), INTERVAL 1 DAY)),
(11, 11, 1103, DATE_SUB(CURDATE(), INTERVAL 1 DAY));
INSERT INTO `hedera`.`userSession`(`created`, `lastUpdate`, `ssid`, `data`, `userVisitFk`) INSERT INTO `hedera`.`userSession`(`created`, `lastUpdate`, `ssid`, `data`, `userVisitFk`)
VALUES VALUES

View File

@ -101,6 +101,47 @@ export default {
email: 'vn-user-mail-forwarding vn-textfield[ng-model="data.forwardTo"]', email: 'vn-user-mail-forwarding vn-textfield[ng-model="data.forwardTo"]',
save: 'vn-user-mail-forwarding vn-submit' save: 'vn-user-mail-forwarding vn-submit'
}, },
accountAcl: {
addAcl: 'vn-acl-index button vn-icon[icon="add"]',
thirdAcl: 'vn-acl-index vn-list> a:nth-child(3)',
deleteThirdAcl: 'vn-acl-index vn-list > a:nth-child(3) > vn-item-section > vn-icon-button[icon="delete"]',
role: 'vn-acl-create vn-autocomplete[ng-model="$ctrl.acl.principalId"]',
model: 'vn-acl-create vn-autocomplete[ng-model="$ctrl.acl.model"]',
property: 'vn-acl-create vn-autocomplete[ng-model="$ctrl.acl.property"]',
accessType: 'vn-acl-create vn-autocomplete[ng-model="$ctrl.acl.accessType"]',
permission: 'vn-acl-create vn-autocomplete[ng-model="$ctrl.acl.permission"]',
save: 'vn-acl-create vn-submit'
},
accountConnections: {
firstConnection: 'vn-connections vn-list > a:nth-child(1)',
deleteFirstConnection: 'vn-connections vn-list > a:nth-child(1) > vn-item-section > vn-icon-button[icon="exit_to_app"]'
},
accountAccounts: {
syncRoles: 'vn-account-accounts vn-button[label="Synchronize roles"]',
syncUser: 'vn-account-accounts vn-button[label="Synchronize user"]',
syncAll: 'vn-account-accounts vn-button[label="Synchronize all"]',
syncUserName: 'vn-textfield[ng-model="$ctrl.syncUser"]',
syncUserPassword: 'vn-textfield[ng-model="$ctrl.syncPassword"]',
buttonAccept: 'button[response="accept"]'
},
accountLdap: {
checkEnable: 'vn-account-ldap vn-check[ng-model="watcher.hasData"]',
server: 'vn-account-ldap vn-textfield[ng-model="$ctrl.config.server"]',
rdn: 'vn-account-ldap vn-textfield[ng-model="$ctrl.config.rdn"]',
password: 'vn-account-ldap vn-textfield[ng-model="$ctrl.config.password"]',
userDn: 'vn-account-ldap vn-textfield[ng-model="$ctrl.config.userDn"]',
groupDn: 'vn-account-ldap vn-textfield[ng-model="$ctrl.config.groupDn"]',
save: 'vn-account-ldap vn-submit'
},
accountSamba: {
checkEnable: 'vn-account-samba vn-check[ng-model="watcher.hasData"]',
adDomain: 'vn-account-samba vn-textfield[ng-model="$ctrl.config.adDomain"]',
adController: 'vn-account-samba vn-textfield[ng-model="$ctrl.config.adController"]',
adUser: 'vn-account-samba vn-textfield[ng-model="$ctrl.config.adUser"]',
adPassword: 'vn-account-samba vn-textfield[ng-model="$ctrl.config.adPassword"]',
verifyCert: 'vn-account-samba vn-check[ng-model="$ctrl.config.verifyCert"]',
save: 'vn-account-samba vn-submit'
},
clientsIndex: { clientsIndex: {
createClientButton: `vn-float-button` createClientButton: `vn-float-button`
}, },

View File

@ -0,0 +1,60 @@
import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer';
describe('Account ACL path', () => {
let browser;
let page;
beforeAll(async() => {
browser = await getBrowser();
page = browser.page;
await page.loginAndModule('developer', 'account');
await page.accessToSection('account.acl');
});
afterAll(async() => {
await browser.close();
});
it('should go to create new acl', async() => {
await page.waitToClick(selectors.accountAcl.addAcl);
await page.waitForState('account.acl.create');
});
it('should create new acl', async() => {
await page.autocompleteSearch(selectors.accountAcl.role, 'sysadmin');
await page.autocompleteSearch(selectors.accountAcl.model, 'UserAccount');
await page.autocompleteSearch(selectors.accountAcl.accessType, '*');
await page.autocompleteSearch(selectors.accountAcl.permission, 'ALLOW');
await page.waitToClick(selectors.accountAcl.save);
const message = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!');
});
it('should navigate to edit', async() => {
await page.doSearch();
await page.waitToClick(selectors.accountAcl.thirdAcl);
await page.waitForState('account.acl.edit');
});
it('should edit the third acl', async() => {
await page.autocompleteSearch(selectors.accountAcl.model, 'Supplier');
await page.autocompleteSearch(selectors.accountAcl.accessType, 'READ');
await page.waitToClick(selectors.accountAcl.save);
const message = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!');
});
it('should delete the third result', async() => {
const result = await page.waitToGetProperty(selectors.accountAcl.thirdAcl, 'innerText');
await page.waitToClick(selectors.accountAcl.deleteThirdAcl);
await page.waitToClick(selectors.globalItems.acceptButton);
const message = await page.waitForSnackbar();
const newResult = await page.waitToGetProperty(selectors.accountAcl.thirdAcl, 'innerText');
expect(message.text).toContain('ACL removed');
expect(result).not.toEqual(newResult);
});
});

View File

@ -0,0 +1,33 @@
import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer';
describe('Account Connections path', () => {
let browser;
let page;
const account = 'sysadmin';
beforeAll(async() => {
browser = await getBrowser();
page = browser.page;
await page.loginAndModule(account, 'account');
await page.accessToSection('account.connections');
});
afterAll(async() => {
await browser.close();
});
it('should check this is the last connection', async() => {
const firstResult = await page.waitToGetProperty(selectors.accountConnections.firstConnection, 'innerText');
expect(firstResult).toContain(account);
});
it('should kill this connection and then get redirected to the login page', async() => {
await page.waitToClick(selectors.accountConnections.deleteFirstConnection);
await page.waitToClick(selectors.globalItems.acceptButton);
const message = await page.waitForSnackbar();
expect(message.text).toContain('Your session has expired, please login again');
});
});

View File

@ -0,0 +1,49 @@
import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer';
describe('Account Accounts path', () => {
let browser;
let page;
beforeAll(async() => {
browser = await getBrowser();
page = browser.page;
await page.loginAndModule('sysadmin', 'account');
await page.accessToSection('account.accounts');
});
afterAll(async() => {
await browser.close();
});
it('should sync roles', async() => {
await page.waitToClick(selectors.accountAccounts.syncRoles);
const message = await page.waitForSnackbar();
expect(message.text).toContain('Roles synchronized!');
});
it('should sync user', async() => {
await page.waitToClick(selectors.accountAccounts.syncUser);
await page.write(selectors.accountAccounts.syncUserName, 'sysadmin');
await page.write(selectors.accountAccounts.syncUserPassword, 'nightmare');
await page.waitToClick(selectors.accountAccounts.buttonAccept);
const message = await page.waitForSnackbar();
expect(message.text).toContain('User synchronized!');
});
it('should relogin', async() => {
await page.loginAndModule('sysadmin', 'account');
await page.accessToSection('account.accounts');
});
it('should sync all', async() => {
await page.waitToClick(selectors.accountAccounts.syncAll);
const message = await page.waitForSnackbar();
expect(message.text).toContain('Synchronizing in the background');
});
});

View File

@ -0,0 +1,32 @@
import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer';
describe('Account LDAP path', () => {
let browser;
let page;
beforeAll(async() => {
browser = await getBrowser();
page = browser.page;
await page.loginAndModule('sysadmin', 'account');
await page.accessToSection('account.ldap');
});
afterAll(async() => {
await browser.close();
});
it('should set data and save', async() => {
await page.waitToClick(selectors.accountLdap.checkEnable);
await page.write(selectors.accountLdap.server, '1234');
await page.write(selectors.accountLdap.rdn, '1234');
await page.write(selectors.accountLdap.password, 'nightmare');
await page.write(selectors.accountLdap.userDn, 'sysadmin');
await page.write(selectors.accountLdap.groupDn, '1234');
await page.waitToClick(selectors.accountLdap.save);
const message = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!');
});
});

View File

@ -0,0 +1,32 @@
import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer';
describe('Account Samba path', () => {
let browser;
let page;
beforeAll(async() => {
browser = await getBrowser();
page = browser.page;
await page.loginAndModule('sysadmin', 'account');
await page.accessToSection('account.samba');
});
afterAll(async() => {
await browser.close();
});
it('should set data and save', async() => {
await page.waitToClick(selectors.accountSamba.checkEnable);
await page.write(selectors.accountSamba.adDomain, '1234');
await page.write(selectors.accountSamba.adController, '1234');
await page.write(selectors.accountSamba.adUser, 'nightmare');
await page.write(selectors.accountSamba.adPassword, 'sysadmin');
await page.waitToClick(selectors.accountSamba.verifyCert);
await page.waitToClick(selectors.accountSamba.save);
const message = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!');
});
});

View File

@ -146,16 +146,17 @@ export default class MultiCheck extends FormInput {
if (!this.model || !this.model.data) return; if (!this.model || !this.model.data) return;
const data = this.model.data; const data = this.model.data;
const modelParams = this.model.userParams;
const params = { const params = {
filter: { filter: {
modelParams: modelParams,
limit: null limit: null
} }
}; };
if (this.model.userFilter)
Object.assign(params.filter, this.model.userFilter);
if (this.model.userParams)
Object.assign(params, this.model.userParams);
this.rows = data.length; this.rows = data.length;
this.$http.get(this.model.url, {params}) this.$http.get(this.model.url, {params})
.then(res => { .then(res => {
this.allRowsCount = res.data.length; this.allRowsCount = res.data.length;

View File

@ -46,11 +46,13 @@
</div> </div>
</vn-horizontal> </vn-horizontal>
<div id="table"></div> <div id="table"></div>
<vn-pagination <div ng-transclude="pagination">
ng-if="$ctrl.model" <vn-pagination
model="$ctrl.model" ng-if="$ctrl.model"
class="vn-pt-md"> model="$ctrl.model"
</vn-pagination> class="vn-pt-md">
</vn-pagination>
</div>
</div> </div>
<vn-confirm <vn-confirm

View File

@ -497,7 +497,8 @@ ngModule.vnComponent('smartTable', {
controller: SmartTable, controller: SmartTable,
transclude: { transclude: {
table: '?slotTable', table: '?slotTable',
actions: '?slotActions' actions: '?slotActions',
pagination: '?slotPagination'
}, },
bindings: { bindings: {
model: '<?', model: '<?',

View File

@ -98,9 +98,6 @@ module.exports = Self => {
Self.latestBuysFilter = async(ctx, filter, options) => { Self.latestBuysFilter = async(ctx, filter, options) => {
const myOptions = {}; const myOptions = {};
if (filter && filter.modelParams)
ctx.args = filter.modelParams;
if (typeof options == 'object') if (typeof options == 'object')
Object.assign(myOptions, options); Object.assign(myOptions, options);

View File

@ -148,12 +148,12 @@
</td> </td>
<td number> <td number>
<vn-chip class="transparent" translate-attr="buy.groupingMode == 2 ? {title: 'Minimun amount'} : {title: 'Packing'}" ng-class="{'message': buy.groupingMode == 2}"> <vn-chip class="transparent" translate-attr="buy.groupingMode == 2 ? {title: 'Minimun amount'} : {title: 'Packing'}" ng-class="{'message': buy.groupingMode == 2}">
<span translate>{{::buy.packing | dashIfEmpty}}</span> <span>{{::buy.packing | dashIfEmpty}}</span>
</vn-chip> </vn-chip>
</td> </td>
<td number> <td number>
<vn-chip class="transparent" translate-attr="buy.groupingMode == 1 ? {title: 'Minimun amount'} : {title: 'Grouping'}" ng-class="{'message': buy.groupingMode == 1}"> <vn-chip class="transparent" translate-attr="buy.groupingMode == 1 ? {title: 'Minimun amount'} : {title: 'Grouping'}" ng-class="{'message': buy.groupingMode == 1}">
<span translate>{{::buy.grouping | dashIfEmpty}}</span> <span>{{::buy.grouping | dashIfEmpty}}</span>
</vn-chip> </vn-chip>
</td> </td>
<td number>{{::buy.quantity}}</td> <td number>{{::buy.quantity}}</td>

View File

@ -159,8 +159,22 @@ export default class Controller extends Section {
lines: rowsToEdit lines: rowsToEdit
}; };
if (this.checkedDummyCount && this.checkedDummyCount > 0) if (this.checkedDummyCount && this.checkedDummyCount > 0) {
data.filter = this.$.model.userParams; const params = {};
if (this.$.model.userParams) {
const userParams = this.$.model.userParams;
for (let param in userParams) {
let newParam = this.exprBuilder(param, userParams[param]);
if (!newParam)
newParam = {[param]: userParams[param]};
Object.assign(params, newParam);
}
}
if (this.$.model.userFilter)
Object.assign(params, this.$.model.userFilter.where);
data.filter = params;
}
return this.$http.post('Buys/editLatestBuys', data) return this.$http.post('Buys/editLatestBuys', data)
.then(() => { .then(() => {

View File

@ -43,11 +43,9 @@ module.exports = Self => {
TIME(v.stamp) AS hour, TIME(v.stamp) AS hour,
DATE(v.stamp) AS dated, DATE(v.stamp) AS dated,
wtc.workerFk wtc.workerFk
FROM hedera.userSession s FROM hedera.visitUser v
JOIN hedera.visitUser v ON v.id = s.userVisitFk
JOIN client c ON c.id = v.userFk JOIN client c ON c.id = v.userFk
LEFT JOIN account.user u ON c.salesPersonFk = u.id JOIN account.user u ON c.salesPersonFk = u.id
LEFT JOIN worker w ON c.salesPersonFk = w.id
LEFT JOIN sharingCart sc ON sc.workerFk = c.salesPersonFk LEFT JOIN sharingCart sc ON sc.workerFk = c.salesPersonFk
AND CURDATE() BETWEEN sc.started AND sc.ended AND CURDATE() BETWEEN sc.started AND sc.ended
LEFT JOIN workerTeamCollegues wtc LEFT JOIN workerTeamCollegues wtc
@ -58,7 +56,9 @@ module.exports = Self => {
const where = filter.where; const where = filter.where;
where['wtc.workerFk'] = userId; where['wtc.workerFk'] = userId;
stmt.merge(conn.makeSuffix(filter)); stmt.merge(conn.makeWhere(filter.where));
stmt.merge(`GROUP BY clientFk, v.stamp`);
stmt.merge(conn.makePagination(filter));
return conn.executeStmt(stmt, myOptions); return conn.executeStmt(stmt, myOptions);
}; };

View File

@ -6,12 +6,49 @@ describe('SalesMonitor clientsFilter()', () => {
try { try {
const options = {transaction: tx}; const options = {transaction: tx};
const ctx = {req: {accessToken: {userId: 18}}, args: {}}; const ctx = {req: {accessToken: {userId: 18}}, args: {}};
const filter = {order: 'dated DESC'};
const from = new Date();
const to = new Date();
from.setHours(0, 0, 0, 0);
to.setHours(23, 59, 59, 59);
const filter = {
where: {
'v.stamp': {between: [from, to]}
}
};
const result = await models.SalesMonitor.clientsFilter(ctx, filter, options); const result = await models.SalesMonitor.clientsFilter(ctx, filter, options);
expect(result.length).toEqual(9); expect(result.length).toEqual(3);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return the clients web activity filtered', async() => {
const tx = await models.SalesMonitor.beginTransaction({});
try {
const options = {transaction: tx};
const ctx = {req: {accessToken: {userId: 18}}, args: {}};
const yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
const today = new Date();
yesterday.setHours(0, 0, 0, 0);
today.setHours(23, 59, 59, 59);
const filter = {
where: {
'v.stamp': {between: [yesterday, today]}
}
};
const result = await models.SalesMonitor.clientsFilter(ctx, filter, options);
expect(result.length).toEqual(5);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {

View File

@ -88,8 +88,16 @@
</td> </td>
</tr> </tr>
</tbody> </tbody>
<table> </table>
<slot-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> </smart-table>
</vn-card> </vn-card>
<vn-worker-descriptor-popover <vn-worker-descriptor-popover

View File

@ -38,6 +38,9 @@
}, },
"created": { "created": {
"type": "date" "type": "date"
},
"originalQuantity":{
"type": "number"
} }
}, },
"relations": { "relations": {

View File

@ -135,7 +135,8 @@ module.exports = Self => {
function formatDate(date) { function formatDate(date) {
let day = date.getDate(); let day = date.getDate();
if (day < 10) day = `0${day}`; if (day < 10) day = `0${day}`;
let month = date.getMonth();
let month = date.getMonth() + 1;
if (month < 10) month = `0${month}`; if (month < 10) month = `0${month}`;
let year = date.getFullYear(); let year = date.getFullYear();

View File

@ -87,7 +87,7 @@ module.exports = Self => {
function formatDate(date) { function formatDate(date) {
let day = date.getDate(); let day = date.getDate();
if (day < 10) day = `0${day}`; if (day < 10) day = `0${day}`;
let month = date.getMonth(); let month = date.getMonth() + 1;
if (month < 10) month = `0${month}`; if (month < 10) month = `0${month}`;
let year = date.getFullYear(); let year = date.getFullYear();

View File

@ -14,5 +14,6 @@ FROM route r
LEFT JOIN account.user u ON u.id = w.userFk LEFT JOIN account.user u ON u.id = w.userFk
LEFT JOIN agencyMode am ON am.id = r.agencyModeFk LEFT JOIN agencyMode am ON am.id = r.agencyModeFk
LEFT JOIN agency a ON a.id = am.agencyFk LEFT JOIN agency a ON a.id = am.agencyFk
LEFT JOIN supplier s ON s.id = a.supplierFk LEFT JOIN supplierAgencyTerm sa ON sa.agencyFk = a.id
LEFT JOIN supplier s ON s.id = sa.supplierFk
WHERE r.id IN(?) WHERE r.id IN(?)