Merge branch 'test' into dev
gitea/salix/pipeline/head This commit looks good Details

This commit is contained in:
Guillermo Bonet 2024-09-04 07:06:22 +02:00
commit c5521ea021
12 changed files with 179 additions and 125 deletions

View File

@ -1,8 +1,9 @@
# Version 24.36 - 2024-08-27 # Version 24.36 - 2024-09-03
### Added 🆕 ### Added 🆕
- chore: refs #7524 WIP limit call by:jorgep - chore: refs #7524 WIP limit call by:jorgep
- chore: refs #7524 modify ormConfig table col (origin/7524-warmfix-modifyColumn) by:jorgep
- feat(update-user): refs #7848 add twoFactor by:alexm - feat(update-user): refs #7848 add twoFactor by:alexm
- feat: #3199 Requested changes by:guillermo - feat: #3199 Requested changes by:guillermo
- feat: refs #3199 Added more scopes ticket_recalcByScope by:guillermo - feat: refs #3199 Added more scopes ticket_recalcByScope by:guillermo
@ -16,6 +17,7 @@
- feat: refs #7524 add default limit (origin/7524-limitSelect) by:jorgep - feat: refs #7524 add default limit (origin/7524-limitSelect) by:jorgep
- feat: refs #7524 add mock limit on find query by:jorgep - feat: refs #7524 add mock limit on find query by:jorgep
- feat: refs #7524 wip remote hooks by:jorgep - feat: refs #7524 wip remote hooks by:jorgep
- feat: refs #7562 Requested changes by:guillermo
- feat: refs #7567 Changed time to call event by:guillermo - feat: refs #7567 Changed time to call event by:guillermo
- feat: refs #7567 Requested changes by:guillermo - feat: refs #7567 Requested changes by:guillermo
- feat: refs #7710 pr revision by:jgallego - feat: refs #7710 pr revision by:jgallego
@ -31,6 +33,7 @@
- feat: refs #7799 Added Fk in vn.item.itemPackingTypeFk by:guillermo - feat: refs #7799 Added Fk in vn.item.itemPackingTypeFk by:guillermo
- feat: refs #7800 Added company Fk by:guillermo - feat: refs #7800 Added company Fk by:guillermo
- feat: refs #7842 Added editorFk in vn.host by:guillermo - feat: refs #7842 Added editorFk in vn.host by:guillermo
- feat: refs #7860 Update new packagings (origin/7860-newPackaging) by:guillermo
- feat: refs #7862 roadmap new fields by:ivanm - feat: refs #7862 roadmap new fields by:ivanm
- feat: refs #7882 Added quadMindsConfig table by:guillermo - feat: refs #7882 Added quadMindsConfig table by:guillermo
@ -55,6 +58,8 @@
- fix: refs #7756 id 0 by:guillermo - fix: refs #7756 id 0 by:guillermo
- fix: refs #7800 tpvMerchantEnable PRIMARY KEY (origin/7800-tpvMerchantEnable) by:guillermo - fix: refs #7800 tpvMerchantEnable PRIMARY KEY (origin/7800-tpvMerchantEnable) by:guillermo
- fix: refs #7800 tpvMerchantEnable PRIMARY KEY by:guillermo - fix: refs #7800 tpvMerchantEnable PRIMARY KEY by:guillermo
- fix: refs #7916 itemShelving_transfer (origin/test, test) by:guillermo
- fix: refs #pako Deleted duplicated version by:guillermo
# Version 24.34 - 2024-08-20 # Version 24.34 - 2024-08-20

View File

@ -35,6 +35,7 @@ BEGIN
saleFk INT(11), saleFk INT(11),
isFreezed INTEGER(1) DEFAULT 0, isFreezed INTEGER(1) DEFAULT 0,
risk DECIMAL(10,1) DEFAULT 0, risk DECIMAL(10,1) DEFAULT 0,
hasRisk TINYINT(1) DEFAULT 0,
hasHighRisk TINYINT(1) DEFAULT 0, hasHighRisk TINYINT(1) DEFAULT 0,
hasTicketRequest INTEGER(1) DEFAULT 0, hasTicketRequest INTEGER(1) DEFAULT 0,
itemShortage VARCHAR(255), itemShortage VARCHAR(255),
@ -52,6 +53,7 @@ BEGIN
saleFk, saleFk,
isFreezed, isFreezed,
risk, risk,
hasRisk,
hasHighRisk, hasHighRisk,
hasTicketRequest, hasTicketRequest,
isTaxDataChecked, isTaxDataChecked,
@ -62,6 +64,7 @@ BEGIN
s.id, s.id,
IF(FIND_IN_SET('isFreezed', t.problem), TRUE, FALSE) isFreezed, IF(FIND_IN_SET('isFreezed', t.problem), TRUE, FALSE) isFreezed,
t.risk, t.risk,
IF(FIND_IN_SET('hasRisk', t.problem), TRUE, FALSE) hasRisk,
IF(FIND_IN_SET('hasHighRisk', t.problem), TRUE, FALSE) hasHighRisk, IF(FIND_IN_SET('hasHighRisk', t.problem), TRUE, FALSE) hasHighRisk,
IF(FIND_IN_SET('hasTicketRequest', t.problem), TRUE, FALSE) hasTicketRequest, IF(FIND_IN_SET('hasTicketRequest', t.problem), TRUE, FALSE) hasTicketRequest,
IF(FIND_IN_SET('isTaxDataChecked', t.problem), FALSE, TRUE) isTaxDataChecked, IF(FIND_IN_SET('isTaxDataChecked', t.problem), FALSE, TRUE) isTaxDataChecked,
@ -70,11 +73,15 @@ BEGIN
LEFT(GROUP_CONCAT('RE: ', i.id, ' ', IFNULL(i.longName,'') SEPARATOR ', '), 250), LEFT(GROUP_CONCAT('RE: ', i.id, ' ', IFNULL(i.longName,'') SEPARATOR ', '), 250),
NULL NULL
) hasRounding, ) hasRounding,
IF(FIND_IN_SET('isTooLittle', t.problem), TRUE, FALSE) isTooLittle IF(FIND_IN_SET('isTooLittle', t.problem)
AND util.VN_NOW() < (util.VN_CURDATE() + INTERVAL HOUR(zc.`hour`) HOUR) + INTERVAL MINUTE(zc.`hour`) MINUTE,
TRUE, FALSE) isTooLittle
FROM tmp.sale_getProblems sgp FROM tmp.sale_getProblems sgp
JOIN ticket t ON t.id = sgp.ticketFk JOIN ticket t ON t.id = sgp.ticketFk
LEFT JOIN sale s ON s.ticketFk = t.id LEFT JOIN sale s ON s.ticketFk = t.id
LEFT JOIN item i ON i.id = s.itemFk LEFT JOIN item i ON i.id = s.itemFk
LEFT JOIN zoneClosure zc ON zc.zoneFk = t.zoneFk
AND zc.dated = util.VN_CURDATE()
WHERE s.problem <> '' OR t.problem <> '' OR t.risk WHERE s.problem <> '' OR t.problem <> '' OR t.risk
GROUP BY t.id, s.id; GROUP BY t.id, s.id;

View File

@ -0,0 +1,75 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`sale_setProblemRoundingByBuy`(
vBuyFk INT
)
BEGIN
/**
* Update rounding problem for all sales related to a buy.
*
* @param vBuyFk Buy id
*/
DECLARE vItemFk INT;
DECLARE vWarehouseFk INT;
DECLARE vMaxDated DATE;
DECLARE vMinDated DATE;
DECLARE vLanding DATE;
DECLARE vLastBuy INT;
DECLARE vCurrentBuy INT;
DECLARE vGrouping INT;
SELECT b.itemFk, t.warehouseInFk
INTO vItemFk, vWarehouseFk
FROM buy b
JOIN entry e ON e.id = b.entryFk
JOIN travel t ON t.id = e.travelFk
WHERE b.id = vBuyFk;
IF vItemFk AND vWarehouseFk THEN
SELECT DATE(MAX(t.shipped)) + INTERVAL 1 DAY, DATE(MIN(t.shipped))
INTO vMaxDated, vMinDated
FROM sale s
JOIN ticket t ON t.id = s.ticketFk
WHERE t.shipped >= util.VN_CURDATE()
AND s.itemFk = vItemFk
AND s.quantity > 0;
CALL buy_getUltimate(vItemFk, vWarehouseFk, vMinDated);
SELECT bu.buyFk, b.grouping INTO vLastBuy, vGrouping
FROM tmp.buyUltimate bu
JOIN buy b ON b.id = bu.buyFk;
DROP TEMPORARY TABLE tmp.buyUltimate;
SET vLanding = vMaxDated;
WHILE vCurrentBuy <> vLastBuy OR vLanding > vMinDated DO
SET vMaxDated = vLanding - INTERVAL 1 DAY;
CALL buy_getUltimate(vItemFk, vWarehouseFk, vMaxDated);
SELECT buyFk, landing
INTO vCurrentBuy, vLanding
FROM tmp.buyUltimate;
DROP TEMPORARY TABLE tmp.buyUltimate;
END WHILE;
CREATE OR REPLACE TEMPORARY TABLE tmp.sale
(INDEX(saleFk, isProblemCalcNeeded))
ENGINE = MEMORY
SELECT s.id saleFk,
MOD(s.quantity, vGrouping) hasProblem,
ticket_isProblemCalcNeeded(t.id) isProblemCalcNeeded
FROM sale s
JOIN ticket t ON t.id = s.ticketFk
WHERE s.itemFk = vItemFk
AND s.quantity > 0
AND t.shipped BETWEEN vMinDated AND util.dayEnd(vMaxDated);
CALL sale_setProblem('hasRounding');
DROP TEMPORARY TABLE tmp.sale;
END IF;
END$$
DELIMITER ;

View File

@ -18,6 +18,7 @@ BEGIN
SELECT ticketFk, SELECT ticketFk,
MAX(isFreezed) isFreezed, MAX(isFreezed) isFreezed,
MAX(risk) risk, MAX(risk) risk,
MAX(hasRisk) hasRisk,
MAX(hasHighRisk) hasHighRisk, MAX(hasHighRisk) hasHighRisk,
MAX(hasTicketRequest) hasTicketRequest, MAX(hasTicketRequest) hasTicketRequest,
MAX(itemShortage) itemShortage, MAX(itemShortage) itemShortage,
@ -32,19 +33,19 @@ BEGIN
FROM tmp.sale_problems FROM tmp.sale_problems
GROUP BY ticketFk; GROUP BY ticketFk;
UPDATE tmp.ticket_problems tp UPDATE tmp.ticket_problems
SET tp.totalProblems = ( SET totalProblems = (
(tp.isFreezed) + (isFreezed) +
IF(tp.risk,TRUE, FALSE) + (hasRisk) +
(tp.hasTicketRequest) + (hasTicketRequest) +
(tp.isTaxDataChecked = 0) + (!isTaxDataChecked) +
(tp.hasComponentLack) + (hasComponentLack) +
(tp.itemDelay) + (itemDelay IS NOT NULL) +
(tp.isTooLittle) + (isTooLittle) +
(tp.itemLost) + (itemLost IS NOT NULL) +
(tp.hasRounding) + (hasRounding IS NOT NULL) +
(tp.itemShortage) + (itemShortage IS NOT NULL) +
(tp.isVip) (isVip)
); );
DROP TEMPORARY TABLE tmp.sale_problems; DROP TEMPORARY TABLE tmp.sale_problems;

View File

@ -27,25 +27,25 @@ module.exports = function(Self) {
}; };
}); });
this.beforeRemote('**', async ctx => { // this.beforeRemote('**', async ctx => {
if (!this.hasFilter(ctx)) return; // if (!this.hasFilter(ctx)) return;
const defaultLimit = this.app.orm.selectLimit; // const defaultLimit = this.app.orm.selectLimit;
const filter = ctx.args.filter || {limit: defaultLimit}; // const filter = ctx.args.filter || {limit: defaultLimit};
if (filter.limit > defaultLimit) { // if (filter.limit > defaultLimit) {
filter.limit = defaultLimit; // filter.limit = defaultLimit;
ctx.args.filter = filter; // ctx.args.filter = filter;
} // }
}); // });
this.afterRemote('**', async ctx => { // this.afterRemote('**', async ctx => {
if (!this.hasFilter(ctx)) return; // if (!this.hasFilter(ctx)) return;
const {result} = ctx; // const {result} = ctx;
const length = Array.isArray(result) ? result.length : result ? 1 : 0; // const length = Array.isArray(result) ? result.length : result ? 1 : 0;
if (length >= this.app.orm.selectLimit) throw new UserError('Too many records'); // if (length >= this.app.orm.selectLimit) throw new UserError('Too many records');
}); // });
// Register field ACL validation // Register field ACL validation
/* /*

View File

@ -1,6 +1,6 @@
module.exports = async function(app) { // module.exports = async function(app) {
if (!app.orm) { // if (!app.orm) {
const ormConfig = await app.models.OrmConfig.findOne(); // const ormConfig = await app.models.OrmConfig.findOne();
app.orm = ormConfig; // app.orm = ormConfig;
} // }
}; // };

View File

@ -238,51 +238,8 @@ module.exports = Self => {
stmts.push(`SET SESSION optimizer_search_depth = @_optimizer_search_depth`); stmts.push(`SET SESSION optimizer_search_depth = @_optimizer_search_depth`);
// Get client debt balance
stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.clientGetDebt');
stmts.push(`
CREATE TEMPORARY TABLE tmp.clientGetDebt
(PRIMARY KEY (clientFk))
ENGINE = MEMORY
SELECT DISTINCT clientFk FROM tmp.filter`);
stmt = new ParameterizedSQL('CALL client_getDebt(?)', [args.to]);
stmts.push(stmt);
stmts.push('DROP TEMPORARY TABLE tmp.clientGetDebt');
stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.tickets');
stmt = new ParameterizedSQL(` stmt = new ParameterizedSQL(`
CREATE TEMPORARY TABLE tmp.tickets CREATE OR REPLACE TEMPORARY TABLE tmp.sale_getProblems
(PRIMARY KEY (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');
stmt = new ParameterizedSQL(`
CREATE TEMPORARY TABLE tmp.sale_getProblems
(INDEX (ticketFk)) (INDEX (ticketFk))
ENGINE = MEMORY ENGINE = MEMORY
SELECT f.id ticketFk, f.clientFk, f.warehouseFk, f.shipped SELECT f.id ticketFk, f.clientFk, f.warehouseFk, f.shipped
@ -294,36 +251,30 @@ module.exports = Self => {
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
`);
stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.sale_getWarnings');
stmt = new ParameterizedSQL(` stmt = new ParameterizedSQL(`
CREATE TEMPORARY TABLE tmp.sale_getWarnings CREATE OR REPLACE TEMPORARY TABLE tmp.sale_getWarnings
(INDEX (ticketFk, agencyModeFk)) (INDEX (ticketFk, agencyModeFk))
ENGINE = MEMORY ENGINE = MEMORY
SELECT f.id ticketFk, f.agencyModeFk SELECT f.id ticketFk, f.agencyModeFk
FROM tmp.filter f`); FROM tmp.filter f
`);
stmts.push(stmt); stmts.push(stmt);
stmts.push('CALL ticket_getWarnings()'); stmts.push('CALL ticket_getWarnings()');
stmt = new ParameterizedSQL(` stmt = new ParameterizedSQL(`
SELECT t.*, UPDATE tmp.ticket_problems
tp.*, SET risk = IF(hasRisk, risk, 0)
((tp.risk) + cc.riskTolerance < 0) AS hasHighRisk, `);
tw.* stmts.push(stmt);
FROM tmp.tickets t
LEFT JOIN tmp.ticket_problems tp ON tp.ticketFk = t.id stmt = new ParameterizedSQL(`
LEFT JOIN tmp.ticket_warnings tw ON tw.ticketFk = t.id SELECT *
JOIN clientConfig cc`); FROM tmp.filter f
LEFT JOIN tmp.ticket_problems tp ON tp.ticketFk = f.id
LEFT JOIN tmp.ticket_warnings tw ON tw.ticketFk = f.id
`);
stmts.push(stmt);
const hasProblems = args.problems; const hasProblems = args.problems;
if (hasProblems != undefined && (!args.from && !args.to)) if (hasProblems != undefined && (!args.from && !args.to))
@ -359,23 +310,23 @@ module.exports = Self => {
switch (param) { switch (param) {
case 'search': case 'search':
return /^\d+$/.test(value) return /^\d+$/.test(value)
? {'t.id': {inq: value}} ? {'f.id': {inq: value}}
: {'t.nickname': {like: `%${value}%`}}; : {'f.nickname': {like: `%${value}%`}};
case 'nickname': case 'nickname':
return {'t.nickname': {like: `%${value}%`}}; return {'f.nickname': {like: `%${value}%`}};
case 'refFk': case 'refFk':
return {'t.refFk': value}; return {'f.refFk': value};
case 'provinceFk': case 'provinceFk':
return {'t.provinceFk': value}; return {'f.provinceFk': value};
case 'stateFk': case 'stateFk':
return {'t.stateFk': value}; return {'f.stateFk': value};
case 'alertLevel': case 'alertLevel':
return {'t.alertLevel': value}; return {'f.alertLevel': value};
case 'pending': case 'pending':
if (value) { if (value) {
return {'t.alertLevelCode': {inq: [ return {'f.alertLevelCode': {inq: [
'FIXING', 'FIXING',
'FREE', 'FREE',
'NOT_READY', 'NOT_READY',
@ -385,7 +336,7 @@ module.exports = Self => {
'WAITING_FOR_PAYMENT' 'WAITING_FOR_PAYMENT'
]}}; ]}};
} else { } else {
return {'t.alertLevelCode': {inq: [ return {'f.alertLevelCode': {inq: [
'ON_PREPARATION', 'ON_PREPARATION',
'ON_CHECKING', 'ON_CHECKING',
'CHECKED', 'CHECKED',
@ -409,7 +360,7 @@ module.exports = Self => {
} }
case 'agencyModeFk': case 'agencyModeFk':
case 'warehouseFk': case 'warehouseFk':
param = `t.${param}`; param = `f.${param}`;
return {[param]: value}; return {[param]: value};
} }
}); });
@ -422,14 +373,14 @@ module.exports = Self => {
stmt.merge(conn.makeLimit(filter)); stmt.merge(conn.makeLimit(filter));
const ticketsIndex = stmts.push(stmt) - 1; const ticketsIndex = stmts.push(stmt) - 1;
stmts.push( stmts.push(`
`DROP TEMPORARY TABLE DROP TEMPORARY TABLE
tmp.filter, tmp.filter,
tmp.ticket_problems, tmp.ticket_problems,
tmp.sale_getProblems, tmp.sale_getProblems,
tmp.sale_getWarnings, tmp.sale_getWarnings,
tmp.ticket_warnings, tmp.ticket_warnings
tmp.risk`); `);
const sql = ParameterizedSQL.join(stmts, ';'); const sql = ParameterizedSQL.join(stmts, ';');
const result = await conn.executeStmt(sql, myOptions); const result = await conn.executeStmt(sql, myOptions);

View File

@ -39,7 +39,7 @@ describe('SalesMonitor salesFilter()', () => {
const filter = {}; const filter = {};
const result = await models.SalesMonitor.salesFilter(ctx, filter, options); const result = await models.SalesMonitor.salesFilter(ctx, filter, options);
expect(result.length).toBeGreaterThan(11); expect(result.length).toBeGreaterThan(10);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {
@ -68,7 +68,7 @@ describe('SalesMonitor salesFilter()', () => {
const filter = {}; const filter = {};
const result = await models.SalesMonitor.salesFilter(ctx, filter, options); const result = await models.SalesMonitor.salesFilter(ctx, filter, options);
expect(result.length).toEqual(0); expect(result.length).toEqual(4);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {
@ -218,8 +218,8 @@ describe('SalesMonitor salesFilter()', () => {
const firstTicket = result.shift(); const firstTicket = result.shift();
const secondTicket = result.shift(); const secondTicket = result.shift();
expect(firstTicket.totalProblems).toEqual(1); expect(firstTicket.totalProblems).toEqual(3);
expect(secondTicket.totalProblems).toEqual(1); expect(secondTicket.totalProblems).toEqual(3);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {

View File

@ -306,6 +306,12 @@ module.exports = Self => {
stmts.push(stmt); stmts.push(stmt);
stmts.push('CALL ticket_getProblems(FALSE)'); stmts.push('CALL ticket_getProblems(FALSE)');
stmt = new ParameterizedSQL(`
UPDATE tmp.ticket_problems
SET risk = IF(hasRisk, risk, 0)
`);
stmts.push(stmt);
stmt = new ParameterizedSQL(` stmt = new ParameterizedSQL(`
SELECT f.*, tp.* SELECT f.*, tp.*
FROM tmp.filter f FROM tmp.filter f

View File

@ -158,6 +158,12 @@ module.exports = Self => {
stmts.push(stmt); stmts.push(stmt);
stmts.push('CALL ticket_getProblems(FALSE)'); stmts.push('CALL ticket_getProblems(FALSE)');
stmt = new ParameterizedSQL(`
UPDATE tmp.ticket_problems
SET risk = IF(hasRisk, risk, 0)
`);
stmts.push(stmt);
stmt = new ParameterizedSQL(` stmt = new ParameterizedSQL(`
SELECT f.*, tp.* SELECT f.*, tp.*
FROM tmp.filter f FROM tmp.filter f

View File

@ -69,6 +69,9 @@
}, },
"cmrFk": { "cmrFk": {
"type": "number" "type": "number"
},
"problem": {
"type": "string"
} }
}, },
"relations": { "relations": {

View File

@ -58,7 +58,7 @@
<vn-icon <vn-icon
vn-tooltip="Client has debt" vn-tooltip="Client has debt"
icon="icon-risk" icon="icon-risk"
ng-if="$ctrl.ticket.client.debt > $ctrl.ticket.client.credit"> ng-if="$ctrl.ticket.problem.includes('hasRisk')">
</vn-icon> </vn-icon>
<vn-icon <vn-icon
vn-tooltip="Client not checked" vn-tooltip="Client not checked"