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 🆕
- 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: #3199 Requested changes 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 mock limit on find query 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 Requested changes by:guillermo
- feat: refs #7710 pr revision by:jgallego
@ -31,6 +33,7 @@
- feat: refs #7799 Added Fk in vn.item.itemPackingTypeFk by:guillermo
- feat: refs #7800 Added company Fk 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 #7882 Added quadMindsConfig table by:guillermo
@ -55,6 +58,8 @@
- fix: refs #7756 id 0 by:guillermo
- fix: refs #7800 tpvMerchantEnable PRIMARY KEY (origin/7800-tpvMerchantEnable) 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

View File

@ -35,6 +35,7 @@ BEGIN
saleFk INT(11),
isFreezed INTEGER(1) DEFAULT 0,
risk DECIMAL(10,1) DEFAULT 0,
hasRisk TINYINT(1) DEFAULT 0,
hasHighRisk TINYINT(1) DEFAULT 0,
hasTicketRequest INTEGER(1) DEFAULT 0,
itemShortage VARCHAR(255),
@ -52,6 +53,7 @@ BEGIN
saleFk,
isFreezed,
risk,
hasRisk,
hasHighRisk,
hasTicketRequest,
isTaxDataChecked,
@ -62,6 +64,7 @@ BEGIN
s.id,
IF(FIND_IN_SET('isFreezed', t.problem), TRUE, FALSE) isFreezed,
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('hasTicketRequest', t.problem), TRUE, FALSE) hasTicketRequest,
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),
NULL
) 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
JOIN ticket t ON t.id = sgp.ticketFk
LEFT JOIN sale s ON s.ticketFk = t.id
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
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,
MAX(isFreezed) isFreezed,
MAX(risk) risk,
MAX(hasRisk) hasRisk,
MAX(hasHighRisk) hasHighRisk,
MAX(hasTicketRequest) hasTicketRequest,
MAX(itemShortage) itemShortage,
@ -32,19 +33,19 @@ BEGIN
FROM tmp.sale_problems
GROUP BY ticketFk;
UPDATE tmp.ticket_problems tp
SET tp.totalProblems = (
(tp.isFreezed) +
IF(tp.risk,TRUE, FALSE) +
(tp.hasTicketRequest) +
(tp.isTaxDataChecked = 0) +
(tp.hasComponentLack) +
(tp.itemDelay) +
(tp.isTooLittle) +
(tp.itemLost) +
(tp.hasRounding) +
(tp.itemShortage) +
(tp.isVip)
UPDATE tmp.ticket_problems
SET totalProblems = (
(isFreezed) +
(hasRisk) +
(hasTicketRequest) +
(!isTaxDataChecked) +
(hasComponentLack) +
(itemDelay IS NOT NULL) +
(isTooLittle) +
(itemLost IS NOT NULL) +
(hasRounding IS NOT NULL) +
(itemShortage IS NOT NULL) +
(isVip)
);
DROP TEMPORARY TABLE tmp.sale_problems;

View File

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

View File

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

View File

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

View File

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

View File

@ -306,6 +306,12 @@ module.exports = Self => {
stmts.push(stmt);
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(`
SELECT f.*, tp.*
FROM tmp.filter f

View File

@ -158,10 +158,16 @@ module.exports = Self => {
stmts.push(stmt);
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(`
SELECT f.*, tp.*
FROM tmp.filter f
LEFT JOIN tmp.ticket_problems tp ON tp.ticketFk = f.id
FROM tmp.filter f
LEFT JOIN tmp.ticket_problems tp ON tp.ticketFk = f.id
`);
if (args.problems != undefined && (!args.originDated && !args.futureDated))

View File

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

View File

@ -58,7 +58,7 @@
<vn-icon
vn-tooltip="Client has debt"
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-tooltip="Client not checked"