This commit is contained in:
Joan Sanchez 2021-10-15 14:07:48 +02:00
commit d5cf57fbb1
14 changed files with 146 additions and 70 deletions

View File

@ -1 +0,0 @@
UPDATE salix.ACL t SET t.principalId = 'employee' WHERE t.id = 269;

View File

@ -1,9 +1,10 @@
<div ng-if="$ctrl.model.moreRows"> <div ng-if="$ctrl.model.moreRows" class="vn-py-md">
<vn-button <div
ng-if="!$ctrl.model.isPaging" ng-if="!$ctrl.model.isPaging"
label="Load more results"
ng-click="$ctrl.onLoadClick()"> ng-click="$ctrl.onLoadClick()">
</vn-button> <vn-button label="Load more results"></vn-button>
<vn-icon icon="arrow_drop_down"/>
</div>
<vn-spinner <vn-spinner
ng-if="$ctrl.model.isPaging" ng-if="$ctrl.model.isPaging"
enable="::true"> enable="::true">

View File

@ -1,7 +1,13 @@
@import "variables";
vn-pagination { vn-pagination {
display: block; display: block;
text-align: center; text-align: center;
color: $color-primary;
vn-button, vn-icon {
display: block
}
& > div > vn-icon-button { & > div > vn-icon-button {
font-size: 2rem; font-size: 2rem;

View File

@ -129,54 +129,20 @@ module.exports = Self => {
const where = buildFilter(ctx.args, (param, value) => { const where = buildFilter(ctx.args, (param, value) => {
switch (param) { switch (param) {
case 'search':
return /^\d+$/.test(value)
? {'t.id': {inq: value}}
: {'t.nickname': {like: `%${value}%`}};
case 'from': case 'from':
return {'t.shipped': {gte: value}}; return {'t.shipped': {gte: value}};
case 'to': case 'to':
return {'t.shipped': {lte: value}}; return {'t.shipped': {lte: value}};
case 'nickname':
return {'t.nickname': {like: `%${value}%`}};
case 'refFk':
return {'t.refFk': value};
case 'salesPersonFk': case 'salesPersonFk':
return {'c.salesPersonFk': value}; return {'c.salesPersonFk': value};
case 'provinceFk':
return {'a.provinceFk': value};
case 'stateFk':
return {'ts.stateFk': value};
case 'mine': case 'mine':
case 'myTeam': case 'myTeam':
if (value) if (value)
return {'c.salesPersonFk': {inq: teamMembersId}}; return {'c.salesPersonFk': {inq: teamMembersId}};
else else
return {'c.salesPersonFk': {nin: teamMembersId}}; return {'c.salesPersonFk': {nin: teamMembersId}};
case 'alertLevel':
return {'ts.alertLevel': value};
case 'pending':
if (value) {
return {and: [
{'st.alertLevel': 0},
{'st.code': {nin: [
'OK',
'BOARDING',
'PRINTED',
'PRINTED_AUTO',
'PICKER_DESIGNED'
]}}
]};
} else {
return {and: [
{'st.alertLevel': {gt: 0}}
]};
}
case 'id': case 'id':
case 'clientFk': case 'clientFk':
case 'agencyModeFk':
case 'warehouseFk':
param = `t.${param}`; param = `t.${param}`;
return {[param]: value}; return {[param]: value};
} }
@ -216,6 +182,7 @@ module.exports = Self => {
ts.code AS alertLevelCode, ts.code AS alertLevelCode,
u.name AS userName, u.name AS userName,
c.salesPersonFk, c.salesPersonFk,
c.credit,
z.hour AS zoneLanding, z.hour AS zoneLanding,
z.name AS zoneName, z.name AS zoneName,
z.id AS zoneFk, z.id AS zoneFk,
@ -246,6 +213,47 @@ module.exports = Self => {
stmt.merge(conn.makeWhere(filter.where)); stmt.merge(conn.makeWhere(filter.where));
stmts.push(stmt); stmts.push(stmt);
// Get client debt balance
stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.clientGetDebt');
stmts.push(`
CREATE TEMPORARY TABLE tmp.clientGetDebt
(INDEX (clientFk))
ENGINE = MEMORY
SELECT DISTINCT clientFk FROM tmp.filter`);
stmt = new ParameterizedSQL('CALL clientGetDebt(?)', [args.to]);
stmts.push(stmt);
stmts.push('DROP TEMPORARY TABLE tmp.clientGetDebt');
stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.tickets');
stmt = new ParameterizedSQL(`
CREATE TEMPORARY TABLE tmp.tickets
(INDEX (id))
ENGINE = MEMORY
SELECT f.*, r.risk AS debt
FROM tmp.filter f
LEFT JOIN tmp.risk r ON f.clientFk = r.clientFk`);
stmts.push(stmt);
// Sum risk to future
stmts.push(`SET @client:= 0`);
stmts.push('SET @risk := 0');
stmts.push(`
UPDATE tmp.tickets
SET debt = IF(@client <> @client:= clientFk,
-totalWithVat + @risk:= - debt + totalWithVat,
-totalWithVat + @risk:= @risk + totalWithVat
)
ORDER BY clientFk, shipped DESC
`);
// Remove positive risks
stmts.push(`
UPDATE tmp.tickets t
SET debt = 0
WHERE t.debt + t.credit >= 0
`);
stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.sale_getProblems'); stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.sale_getProblems');
stmts.push(` stmts.push(`
CREATE TEMPORARY TABLE tmp.sale_getProblems CREATE TEMPORARY TABLE tmp.sale_getProblems
@ -258,27 +266,39 @@ module.exports = Self => {
AND f.shipped >= CURDATE()`); AND f.shipped >= CURDATE()`);
stmts.push('CALL ticket_getProblems(FALSE)'); stmts.push('CALL ticket_getProblems(FALSE)');
stmts.push(`
INSERT INTO tmp.ticket_problems (ticketFk, risk, totalProblems)
SELECT t.id, t.debt + t.credit AS risk, 1
FROM tmp.tickets t
WHERE (t.debt + t.credit) < 0
ON DUPLICATE KEY UPDATE
risk = t.debt + t.credit, totalProblems = totalProblems + 1
`);
stmt = new ParameterizedSQL(` stmt = new ParameterizedSQL(`
SELECT f.*, tp.* SELECT t.*, tp.*,
FROM tmp.filter f ((tp.risk) + cc.riskTolerance < 0) AS hasHighRisk
LEFT JOIN tmp.ticket_problems tp ON tp.ticketFk = f.id`); FROM tmp.tickets t
LEFT JOIN tmp.ticket_problems tp ON tp.ticketFk = t.id
JOIN clientConfig cc`);
const hasProblems = args.problems; const hasProblems = args.problems;
if (hasProblems != undefined && (!args.from && !args.to)) if (hasProblems != undefined && (!args.from && !args.to))
throw new UserError('Choose a date range or days forward'); throw new UserError('Choose a date range or days forward');
let problemsFilter; let finalFilter = {};
let whereProblems;
if (hasProblems === true) { if (hasProblems === true) {
problemsFilter = {or: [ whereProblems = {or: [
{'tp.isFreezed': true}, {'tp.isFreezed': true},
{'tp.risk': {gt: 0}}, {'tp.risk': {lt: 0}},
{'tp.hasTicketRequest': true}, {'tp.hasTicketRequest': true},
{'tp.hasComponentLack': true}, {'tp.hasComponentLack': true},
{'tp.isTaxDataChecked': false}, {'tp.isTaxDataChecked': false},
{'tp.isAvailable': false} {'tp.isAvailable': false}
]}; ]};
} else if (hasProblems === false) { } else if (hasProblems === false) {
problemsFilter = {and: [ whereProblems = {and: [
{'tp.isFreezed': false}, {'tp.isFreezed': false},
{'tp.risk': 0}, {'tp.risk': 0},
{'tp.hasTicketRequest': false}, {'tp.hasTicketRequest': false},
@ -288,8 +308,53 @@ module.exports = Self => {
]}; ]};
} }
if (problemsFilter) if (whereProblems) finalFilter.where = whereProblems;
stmt.merge(conn.makeWhere(problemsFilter));
const myWhere = buildFilter(ctx.args, (param, value) => {
switch (param) {
case 'search':
return /^\d+$/.test(value)
? {'t.id': {inq: value}}
: {'t.nickname': {like: `%${value}%`}};
case 'nickname':
return {'t.nickname': {like: `%${value}%`}};
case 'refFk':
return {'t.refFk': value};
case 'provinceFk':
return {'t.provinceFk': value};
case 'stateFk':
return {'t.stateFk': value};
case 'alertLevel':
return {'t.alertLevel': value};
case 'pending':
if (value) {
return {and: [
{'t.alertLevel': 0},
{'t.alertLevelCode': {nin: [
'OK',
'BOARDING',
'PRINTED',
'PRINTED_AUTO',
'PICKER_DESIGNED'
]}}
]};
} else {
return {and: [
{'t.alertLevel': {gt: 0}}
]};
}
case 'agencyModeFk':
case 'warehouseFk':
param = `t.${param}`;
return {[param]: value};
}
});
finalFilter = mergeFilters(finalFilter, {where: myWhere});
if (finalFilter.where)
stmt.merge(conn.makeWhere(finalFilter.where));
stmt.merge(conn.makeOrderBy(filter.order)); stmt.merge(conn.makeOrderBy(filter.order));
stmt.merge(conn.makeLimit(filter)); stmt.merge(conn.makeLimit(filter));
@ -298,7 +363,9 @@ module.exports = Self => {
stmts.push( stmts.push(
`DROP TEMPORARY TABLE `DROP TEMPORARY TABLE
tmp.filter, tmp.filter,
tmp.ticket_problems`); tmp.ticket_problems,
tmp.sale_getProblems,
tmp.risk`);
let sql = ParameterizedSQL.join(stmts, ';'); let sql = ParameterizedSQL.join(stmts, ';');
let result = await conn.executeStmt(sql); let result = await conn.executeStmt(sql);

View File

@ -23,7 +23,7 @@ describe('SalesMonitor salesFilter()', () => {
const filter = {}; const filter = {};
const result = await app.models.SalesMonitor.salesFilter(ctx, filter); const result = await app.models.SalesMonitor.salesFilter(ctx, filter);
expect(result.length).toEqual(9); expect(result.length).toEqual(13);
}); });
it('should return the tickets matching the problems on false', async() => { it('should return the tickets matching the problems on false', async() => {

View File

@ -70,7 +70,7 @@
<vn-autocomplete vn-one <vn-autocomplete vn-one
data="$ctrl.groupedStates" data="$ctrl.groupedStates"
label="Grouped States" label="Grouped States"
value-field="alertLevel" value-field="id"
show-field="name" show-field="name"
ng-model="filter.alertLevel"> ng-model="filter.alertLevel">
<tpl-item> <tpl-item>

View File

@ -14,7 +14,7 @@ class Controller extends SearchPanel {
this.$http.get('AlertLevels').then(res => { this.$http.get('AlertLevels').then(res => {
for (let state of res.data) { for (let state of res.data) {
groupedStates.push({ groupedStates.push({
alertLevel: state.alertLevel, id: state.id,
code: state.code, code: state.code,
name: this.$t(state.code) name: this.$t(state.code)
}); });

View File

@ -18,7 +18,7 @@ describe('Monitor Component vnMonitorSalesSearchPanel', () => {
jest.spyOn(controller, '$t').mockReturnValue('miCodigo'); jest.spyOn(controller, '$t').mockReturnValue('miCodigo');
const data = [ const data = [
{ {
alertLevel: 9999, id: 9999,
code: 'myCode' code: 'myCode'
} }
]; ];
@ -27,7 +27,7 @@ describe('Monitor Component vnMonitorSalesSearchPanel', () => {
$httpBackend.flush(); $httpBackend.flush();
expect(controller.groupedStates).toEqual([{ expect(controller.groupedStates).toEqual([{
alertLevel: 9999, id: 9999,
code: 'myCode', code: 'myCode',
name: 'miCodigo' name: 'miCodigo'
}]); }]);

View File

@ -51,7 +51,7 @@
<a ng-repeat="ticket in model.data" <a ng-repeat="ticket in model.data"
class="clickable vn-tr search-result" class="clickable vn-tr search-result"
ui-sref="ticket.card.summary({id: {{::ticket.id}}})" target="_blank"> ui-sref="ticket.card.summary({id: {{::ticket.id}}})" target="_blank">
<vn-td class="icon-field"> <vn-td expand>
<vn-icon <vn-icon
ng-show="::ticket.isTaxDataChecked === 0" ng-show="::ticket.isTaxDataChecked === 0"
translate-attr="{title: 'No verified data'}" translate-attr="{title: 'No verified data'}"

View File

@ -119,7 +119,7 @@ module.exports = Self => {
case 'sourceApp': case 'sourceApp':
return {'o.source_app': value}; return {'o.source_app': value};
case 'ticketFk': case 'ticketFk':
return {'ort.ticketFk': value}; return {'ot.ticketFk': value};
case 'isConfirmed': case 'isConfirmed':
return {'o.confirmed': value ? 1 : 0}; return {'o.confirmed': value ? 1 : 0};
case 'myTeam': case 'myTeam':
@ -137,7 +137,10 @@ module.exports = Self => {
let stmt; let stmt;
stmt = new ParameterizedSQL( stmt = new ParameterizedSQL(
`SELECT `CREATE TEMPORARY TABLE tmp.filter
(INDEX (id))
ENGINE = MEMORY
SELECT
o.id, o.id,
o.total, o.total,
o.date_send landed, o.date_send landed,
@ -168,20 +171,20 @@ module.exports = Self => {
LEFT JOIN ticket t ON t.id = ot.ticketFk LEFT JOIN ticket t ON t.id = ot.ticketFk
LEFT JOIN zoneEstimatedDelivery zed ON zed.zoneFk = t.zoneFk`); LEFT JOIN zoneEstimatedDelivery zed ON zed.zoneFk = t.zoneFk`);
if (args && args.ticketFk) {
stmt.merge({
sql: `LEFT JOIN orderTicket ort ON ort.orderFk = o.id`
});
}
stmt.merge(conn.makeWhere(filter.where)); stmt.merge(conn.makeWhere(filter.where));
stmt.merge(`GROUP BY o.id`);
stmt.merge(conn.makePagination(filter)); stmt.merge(conn.makePagination(filter));
stmts.push(stmt); stmts.push(stmt);
stmt = new ParameterizedSQL(`SELECT * FROM tmp.filter`);
stmt.merge(`GROUP BY id`);
stmt.merge(conn.makeOrderBy(filter.order));
const ordersIndex = stmts.push(stmt) - 1;
stmts.push(`DROP TEMPORARY TABLE tmp.filter`);
const sql = ParameterizedSQL.join(stmts, ';'); const sql = ParameterizedSQL.join(stmts, ';');
const result = await conn.executeStmt(sql); const result = await conn.executeStmt(sql);
return result; return result[ordersIndex];
}; };
}; };

View File

@ -17,7 +17,7 @@
<vn-th field="landed" shrink-date>Landed</vn-th> <vn-th field="landed" shrink-date>Landed</vn-th>
<vn-th field="created" center>Hour</vn-th> <vn-th field="created" center>Hour</vn-th>
<vn-th field="agencyName" center>Agency</vn-th> <vn-th field="agencyName" center>Agency</vn-th>
<vn-th center>Total</vn-th> <vn-th field="total" center>Total</vn-th>
</vn-tr> </vn-tr>
</vn-thead> </vn-thead>
<vn-tbody> <vn-tbody>

View File

@ -89,7 +89,7 @@
<vn-autocomplete vn-one <vn-autocomplete vn-one
data="$ctrl.groupedStates" data="$ctrl.groupedStates"
label="Grouped States" label="Grouped States"
value-field="alertLevel" value-field="id"
show-field="name" show-field="name"
ng-model="filter.alertLevel"> ng-model="filter.alertLevel">
<tpl-item> <tpl-item>

View File

@ -14,7 +14,7 @@ class Controller extends SearchPanel {
this.$http.get('AlertLevels').then(res => { this.$http.get('AlertLevels').then(res => {
for (let state of res.data) { for (let state of res.data) {
groupedStates.push({ groupedStates.push({
alertLevel: state.alertLevel, id: state.id,
code: state.code, code: state.code,
name: this.$t(state.code) name: this.$t(state.code)
}); });

View File

@ -18,7 +18,7 @@ describe('Ticket Component vnTicketSearchPanel', () => {
jest.spyOn(controller, '$t').mockReturnValue('miCodigo'); jest.spyOn(controller, '$t').mockReturnValue('miCodigo');
const data = [ const data = [
{ {
alertLevel: 9999, id: 9999,
code: 'myCode' code: 'myCode'
} }
]; ];
@ -27,7 +27,7 @@ describe('Ticket Component vnTicketSearchPanel', () => {
$httpBackend.flush(); $httpBackend.flush();
expect(controller.groupedStates).toEqual([{ expect(controller.groupedStates).toEqual([{
alertLevel: 9999, id: 9999,
code: 'myCode', code: 'myCode',
name: 'miCodigo' name: 'miCodigo'
}]); }]);