feat(monitor): show client risk to future on tickets
gitea/salix/pipeline/head This commit looks good
Details
gitea/salix/pipeline/head This commit looks good
Details
Refs: 2624
This commit is contained in:
parent
e278491ad2
commit
85b4730c6c
|
@ -130,54 +130,20 @@ module.exports = Self => {
|
|||
|
||||
const where = buildFilter(ctx.args, (param, value) => {
|
||||
switch (param) {
|
||||
case 'search':
|
||||
return /^\d+$/.test(value)
|
||||
? {'t.id': {inq: value}}
|
||||
: {'t.nickname': {like: `%${value}%`}};
|
||||
case 'from':
|
||||
return {'t.shipped': {gte: value}};
|
||||
case 'to':
|
||||
return {'t.shipped': {lte: value}};
|
||||
case 'nickname':
|
||||
return {'t.nickname': {like: `%${value}%`}};
|
||||
case 'refFk':
|
||||
return {'t.refFk': value};
|
||||
case 'salesPersonFk':
|
||||
return {'c.salesPersonFk': value};
|
||||
case 'provinceFk':
|
||||
return {'a.provinceFk': value};
|
||||
case 'stateFk':
|
||||
return {'ts.stateFk': value};
|
||||
case 'mine':
|
||||
case 'myTeam':
|
||||
if (value)
|
||||
return {'c.salesPersonFk': {inq: teamMembersId}};
|
||||
else
|
||||
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 'clientFk':
|
||||
case 'agencyModeFk':
|
||||
case 'warehouseFk':
|
||||
param = `t.${param}`;
|
||||
return {[param]: value};
|
||||
}
|
||||
|
@ -217,6 +183,7 @@ module.exports = Self => {
|
|||
ts.code AS alertLevelCode,
|
||||
u.name AS userName,
|
||||
c.salesPersonFk,
|
||||
c.credit,
|
||||
z.hour AS zoneLanding,
|
||||
z.name AS zoneName,
|
||||
z.id AS zoneFk,
|
||||
|
@ -247,6 +214,47 @@ module.exports = Self => {
|
|||
stmt.merge(conn.makeWhere(filter.where));
|
||||
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 = NULL
|
||||
WHERE t.debt + t.credit >= 0
|
||||
`);
|
||||
|
||||
stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.sale_getProblems');
|
||||
stmts.push(`
|
||||
CREATE TEMPORARY TABLE tmp.sale_getProblems
|
||||
|
@ -260,17 +268,20 @@ module.exports = Self => {
|
|||
stmts.push('CALL ticket_getProblems(FALSE)');
|
||||
|
||||
stmt = new ParameterizedSQL(`
|
||||
SELECT f.*, tp.*
|
||||
FROM tmp.filter f
|
||||
LEFT JOIN tmp.ticket_problems tp ON tp.ticketFk = f.id`);
|
||||
SELECT t.*, tp.*, t.debt + t.credit AS risk,
|
||||
((t.debt + t.credit) + cc.riskTolerance < 0) AS hasHighRisk
|
||||
FROM tmp.tickets t
|
||||
LEFT JOIN tmp.ticket_problems tp ON tp.ticketFk = t.id
|
||||
JOIN clientConfig cc`);
|
||||
|
||||
const hasProblems = args.problems;
|
||||
if (hasProblems != undefined && (!args.from && !args.to))
|
||||
throw new UserError('Choose a date range or days forward');
|
||||
|
||||
let problemsFilter;
|
||||
let finalFilter = {};
|
||||
let whereProblems;
|
||||
if (hasProblems === true) {
|
||||
problemsFilter = {or: [
|
||||
whereProblems = {or: [
|
||||
{'tp.isFreezed': true},
|
||||
{'tp.risk': {gt: 0}},
|
||||
{'tp.hasTicketRequest': true},
|
||||
|
@ -279,7 +290,7 @@ module.exports = Self => {
|
|||
{'tp.isAvailable': false}
|
||||
]};
|
||||
} else if (hasProblems === false) {
|
||||
problemsFilter = {and: [
|
||||
whereProblems = {and: [
|
||||
{'tp.isFreezed': false},
|
||||
{'tp.risk': 0},
|
||||
{'tp.hasTicketRequest': false},
|
||||
|
@ -289,8 +300,53 @@ module.exports = Self => {
|
|||
]};
|
||||
}
|
||||
|
||||
if (problemsFilter)
|
||||
stmt.merge(conn.makeWhere(problemsFilter));
|
||||
if (whereProblems) finalFilter.where = whereProblems;
|
||||
|
||||
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.makeLimit(filter));
|
||||
|
@ -299,7 +355,9 @@ module.exports = Self => {
|
|||
stmts.push(
|
||||
`DROP TEMPORARY TABLE
|
||||
tmp.filter,
|
||||
tmp.ticket_problems`);
|
||||
tmp.ticket_problems,
|
||||
tmp.sale_getProblems,
|
||||
tmp.risk`);
|
||||
|
||||
let sql = ParameterizedSQL.join(stmts, ';');
|
||||
let result = await conn.executeStmt(sql);
|
||||
|
|
|
@ -70,7 +70,7 @@
|
|||
<vn-autocomplete vn-one
|
||||
data="$ctrl.groupedStates"
|
||||
label="Grouped States"
|
||||
value-field="alertLevel"
|
||||
value-field="id"
|
||||
show-field="name"
|
||||
ng-model="filter.alertLevel">
|
||||
<tpl-item>
|
||||
|
|
|
@ -14,7 +14,7 @@ class Controller extends SearchPanel {
|
|||
this.$http.get('AlertLevels').then(res => {
|
||||
for (let state of res.data) {
|
||||
groupedStates.push({
|
||||
alertLevel: state.alertLevel,
|
||||
id: state.id,
|
||||
code: state.code,
|
||||
name: this.$t(state.code)
|
||||
});
|
||||
|
|
|
@ -18,7 +18,7 @@ describe('Monitor Component vnMonitorSalesSearchPanel', () => {
|
|||
jest.spyOn(controller, '$t').mockReturnValue('miCodigo');
|
||||
const data = [
|
||||
{
|
||||
alertLevel: 9999,
|
||||
id: 9999,
|
||||
code: 'myCode'
|
||||
}
|
||||
];
|
||||
|
@ -27,7 +27,7 @@ describe('Monitor Component vnMonitorSalesSearchPanel', () => {
|
|||
$httpBackend.flush();
|
||||
|
||||
expect(controller.groupedStates).toEqual([{
|
||||
alertLevel: 9999,
|
||||
id: 9999,
|
||||
code: 'myCode',
|
||||
name: 'miCodigo'
|
||||
}]);
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
<a ng-repeat="ticket in model.data"
|
||||
class="clickable vn-tr search-result"
|
||||
ui-sref="ticket.card.summary({id: {{::ticket.id}}})" target="_blank">
|
||||
<vn-td class="icon-field">
|
||||
<vn-td expand>
|
||||
<vn-icon
|
||||
ng-show="::ticket.isTaxDataChecked === 0"
|
||||
translate-attr="{title: 'No verified data'}"
|
||||
|
|
|
@ -89,7 +89,7 @@
|
|||
<vn-autocomplete vn-one
|
||||
data="$ctrl.groupedStates"
|
||||
label="Grouped States"
|
||||
value-field="alertLevel"
|
||||
value-field="id"
|
||||
show-field="name"
|
||||
ng-model="filter.alertLevel">
|
||||
<tpl-item>
|
||||
|
|
|
@ -14,7 +14,7 @@ class Controller extends SearchPanel {
|
|||
this.$http.get('AlertLevels').then(res => {
|
||||
for (let state of res.data) {
|
||||
groupedStates.push({
|
||||
alertLevel: state.alertLevel,
|
||||
id: state.id,
|
||||
code: state.code,
|
||||
name: this.$t(state.code)
|
||||
});
|
||||
|
|
|
@ -18,7 +18,7 @@ describe('Ticket Component vnTicketSearchPanel', () => {
|
|||
jest.spyOn(controller, '$t').mockReturnValue('miCodigo');
|
||||
const data = [
|
||||
{
|
||||
alertLevel: 9999,
|
||||
id: 9999,
|
||||
code: 'myCode'
|
||||
}
|
||||
];
|
||||
|
@ -27,7 +27,7 @@ describe('Ticket Component vnTicketSearchPanel', () => {
|
|||
$httpBackend.flush();
|
||||
|
||||
expect(controller.groupedStates).toEqual([{
|
||||
alertLevel: 9999,
|
||||
id: 9999,
|
||||
code: 'myCode',
|
||||
name: 'miCodigo'
|
||||
}]);
|
||||
|
|
Loading…
Reference in New Issue