feat: implement sales order services, redis-based concurrency control, and build-time path alias resolution for production.
All checks were successful
Build (develop) / Promote (main) / build-and-push-deploy (push) Successful in 3m33s

This commit is contained in:
Luis Eduardo Estevao
2026-05-17 21:00:31 -03:00
parent ce064fc160
commit a63ca5e598
7 changed files with 306 additions and 151 deletions

View File

@@ -7,7 +7,7 @@
"license": "JURUNENSE HOME CENTER",
"scripts": {
"prebuild": "rimraf dist",
"build": "nest build",
"build": "nest build && node scripts/rewrite-dist-src-aliases.js",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"start": "nest start",
"start:dev": "nest start --watch",

View File

@@ -0,0 +1,40 @@
const fs = require('fs');
const path = require('path');
const distDir = path.resolve(__dirname, '..', 'dist');
function walk(dir) {
if (!fs.existsSync(dir)) {
return [];
}
return fs.readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
return walk(fullPath);
}
return fullPath.endsWith('.js') ? [fullPath] : [];
});
}
function toRequirePath(fromFile, srcImport) {
const target = path.join(distDir, srcImport.replace(/^src[\\/]/, ''));
let relative = path.relative(path.dirname(fromFile), target).replace(/\\/g, '/');
if (!relative.startsWith('.')) {
relative = `./${relative}`;
}
return relative;
}
for (const file of walk(distDir)) {
const source = fs.readFileSync(file, 'utf8');
const rewritten = source.replace(/require\((['"])src\/([^'"]+)\1\)/g, (_match, quote, importPath) => {
return `require(${quote}${toRequirePath(file, `src/${importPath}`)}${quote})`;
});
if (rewritten !== source) {
fs.writeFileSync(file, rewritten);
}
}

View File

@@ -1,3 +1,4 @@
import './polyfills/node-util';
import { NestFactory } from '@nestjs/core';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
const compression = require('compression');

View File

@@ -0,0 +1,9 @@
const util = require('util');
if (typeof util.isNullOrUndefined !== 'function') {
util.isNullOrUndefined = (value: any) => value === null || value === undefined;
}
if (typeof util.isObject !== 'function') {
util.isObject = (value: any) => value !== null && typeof value === 'object';
}

View File

@@ -28,11 +28,38 @@ export class OrderService {
) { }
async create(cart: Cart) {
const lockKey = `lock:order:create:${cart.id}`;
const lockValue = `${Date.now()}:${Math.random()}`;
const lockTimeout = 120;
let acquiredLock: string | null = null;
try {
acquiredLock = await this.redisClient.set(lockKey, lockValue, 'NX', 'EX', lockTimeout);
} catch (err) {
console.error('Erro ao adquirir lock no Redis (createOrder):', err?.message || err);
acquiredLock = 'OK';
}
if (acquiredLock !== 'OK') {
throw new HttpException('Venda em processamento para este carrinho. Aguarde a finalizacao e tente novamente.', HttpStatus.CONFLICT);
}
try {
const shopping = await this.findShopping(cart.id);
if (shopping == null)
throw new HttpException("Carrinho de compras não localizado.", HttpStatus.NOT_FOUND);
const order = await this.createOrder(cart);
return order;
} finally {
try {
const currentLockValue = await this.redisClient.get(lockKey);
if (currentLockValue === lockValue) {
await this.redisClient.del(lockKey);
}
} catch (lockErr) {
console.error('Erro ao liberar lock no Redis (createOrder):', lockErr?.message || lockErr);
}
}
}
async deleteOrdersDelivery(orderId: number, userId: number) {
@@ -57,7 +84,7 @@ export class OrderService {
}
} catch (erro) {
if (queryRunner.isTransactionActive) {
await queryRunner.commitTransaction();
await queryRunner.rollbackTransaction();
}
throw erro;
} finally {
@@ -125,7 +152,7 @@ export class OrderService {
}
if (queryRunner.isTransactionActive) {
queryRunner.commitTransaction();
await queryRunner.commitTransaction();
}
await queryRunner.startTransaction();
@@ -320,7 +347,7 @@ export class OrderService {
};
} catch (err) {
console.log(err);
this.deletePreOrder(idPreOrder);
await this.deletePreOrder(idPreOrder);
throw err;
// since we have errors let's rollback changes we made
} finally {
@@ -743,6 +770,9 @@ export class OrderService {
const queryRunner = connection.createQueryRunner();
await queryRunner.connect();
console.log('Consultando usuario ' + idSeller);
await queryRunner.startTransaction();
try {
let sql = 'SELECT NVL(PROXNUMPEDWEB,0) as "proxnumpedweb" FROM PCUSUARI ' +
' WHERE PCUSUARI.CODUSUR = :1 FOR UPDATE';
const seller = await queryRunner.query(sql, [idSeller]);
@@ -750,10 +780,6 @@ export class OrderService {
const idOrder = seller[0].proxnumpedweb;
console.log(idOrder);
await queryRunner.startTransaction();
try {
sql = 'UPDATE PCUSUARI SET PROXNUMPEDWEB = NVL(PROXNUMPEDWEB,0) + 1 ' +
' WHERE PCUSUARI.CODUSUR = :1';
await queryRunner.query(sql, [idSeller]);

View File

@@ -69,7 +69,7 @@ export class SalesService {
pageNumber = 1;
const offSet = (pageNumber - 1) * pageSize;
if (filter && filter.text.length > 0) {
if (filter && filter.text && filter.text.length > 0) {
const description = filter.text.toUpperCase();
console.log('consultando por texto: ' + description);
@@ -116,7 +116,7 @@ export class SalesService {
.addSelect("\"esvlistaprodutos\".QUANTIDADE_ESTOQUE_GERAL", "full_stock")
.addSelect("\"esvlistaprodutos\".TEM_PRODUTO_SIMILAR", "similar")
.addSelect("\"esvlistaprodutos\".TIPO_CAMPANHA", "type_campaing")
.where("(UPPER(\"esvlistaprodutos\".CODFAB) LIKE '%'||REPLACE(:description, '@', '%')||'%' OR UPPER(\"esvlistaprodutos\".descricao) LIKE '%'||REPLACE(:description, '@', '%')||'%')", { description })
.where("(\"esvlistaprodutos\".CODFAB LIKE REPLACE(:description, '@', '%')||'%' OR \"esvlistaprodutos\".descricao LIKE REPLACE(:description, '@', '%')||'%' OR \"esvlistaprodutos\".NOMEECOMMERCE LIKE REPLACE(:description, '@', '%')||'%')", { description })
.andWhere("(\"esvlistaprodutos\".codfilial = :codfilial OR :codfilial = '99')", { codfilial: store })
.andWhere("(\"esvlistaprodutos\".produto_com_reducao_preco = :produtoComReducaoPreco OR :produtoComReducaoPreco = 'N')",
{ produtoComReducaoPreco: (filter.markdown) ? 'S' : 'N' })
@@ -450,8 +450,18 @@ export class SalesService {
}
async searchProduct(store: string, search: string, pageSize: number, pageNumber: number) {
const connectionDb = new Connection(connectionOptions);
await connectionDb.connect();
const cacheKey = `searchProduct:${store}:${pageSize}:${pageNumber}:${search}`;
try {
const cachedProducts = await this.redisClient.get(cacheKey);
if (cachedProducts) {
console.log('searchProduct - Retornando produtos do cache');
return JSON.parse(cachedProducts);
}
} catch (err) {
console.error('Erro ao acessar o Redis no searchProduct:', err?.message || err);
}
const connectionDb = getConnection();
const queryRunner = connectionDb.createQueryRunner();
await queryRunner.connect();
try {
@@ -509,7 +519,7 @@ export class SalesService {
.andWhere("\"esvlistaprodutos\".codfilial = :codfilial OR :codfilial = '99'", { codfilial: store })
.limit(pageSize)
.offset(offSet)
.orderBy("REPLACE(\"esvlistaprodutos\".DESCRICAO,'#', '')", "ASC")
.orderBy("\"esvlistaprodutos\".DESCRICAO", "ASC")
.getRawMany();
if (products.length === 0) {
@@ -558,12 +568,12 @@ export class SalesService {
.andWhere("(\"esvlistaprodutos\".codfilial = :codfilial OR :codfilial = '99')", { codfilial: store })
.limit(pageSize)
.offset(offSet)
.orderBy("REPLACE(\"esvlistaprodutos\".DESCRICAO,'#', '')", "ASC")
.orderBy("\"esvlistaprodutos\".DESCRICAO", "ASC")
.getRawMany();
}
} else {
const description = '%' + search.toUpperCase() + '%';
const description = search.toUpperCase().replace('@', '%') + '%';
console.log('consultando por codigo de fabrica');
products = await queryRunner.manager
.getRepository(SalesProduct)
@@ -605,11 +615,11 @@ export class SalesService {
.addSelect("\"esvlistaprodutos\".QUANTIDADE_ESTOQUE_GERAL", "full_stock")
.addSelect("\"esvlistaprodutos\".TEM_PRODUTO_SIMILAR", "similar")
.addSelect("\"esvlistaprodutos\".TIPO_CAMPANHA", "type_campaing")
.where("UPPER(esvlistaprodutos.CODFAB) like REPLACE(:description, '@', '%')", { description })
.where("esvlistaprodutos.CODFAB like :description", { description })
.andWhere("\"esvlistaprodutos\".codfilial = :codfilial OR :codfilial = '99'", { codfilial: store })
.limit(pageSize)
.offset(offSet)
.orderBy("REPLACE(\"esvlistaprodutos\".DESCRICAO,'#', '')", "ASC")
.orderBy("\"esvlistaprodutos\".DESCRICAO", "ASC")
.getRawMany();
if (products.length == 0) {
@@ -653,11 +663,11 @@ export class SalesService {
.addSelect("\"esvlistaprodutos\".QUANTIDADE_ESTOQUE_GERAL", "full_stock")
.addSelect("\"esvlistaprodutos\".TEM_PRODUTO_SIMILAR", "similar")
.addSelect("\"esvlistaprodutos\".TIPO_CAMPANHA", "type_campaing")
.where("UPPER(esvlistaprodutos.DESCRICAO) like REPLACE(:description, '@', '%')", { description })
.where("(esvlistaprodutos.DESCRICAO like :description OR esvlistaprodutos.NOMEECOMMERCE like :description)", { description })
.andWhere("\"esvlistaprodutos\".codfilial = :codfilial OR :codfilial = '99'", { codfilial: store })
.limit(pageSize)
.offset(offSet)
.orderBy("REPLACE(\"esvlistaprodutos\".DESCRICAO,'#', '')", "ASC")
.orderBy("\"esvlistaprodutos\".DESCRICAO", "ASC")
.getRawMany();
}
@@ -665,6 +675,7 @@ export class SalesService {
products = this.createListImages(products);
console.log(products.length);
try { await this.redisClient.set(cacheKey, JSON.stringify(products), 'EX', 900); } catch (cacheErr) { console.error('Erro ao salvar cache searchProduct:', cacheErr?.message || cacheErr); }
return products;
} catch (error) {
@@ -672,7 +683,7 @@ export class SalesService {
throw error;
} finally {
await queryRunner.release();
await connectionDb.close();
// Nao fecha a conexao global; ela e reutilizada pelo pool do TypeORM.
}
}
@@ -1237,13 +1248,43 @@ export class SalesService {
async searchProduct2(store: string, pageSize: number, pageNumber: number, filter: FilterProduct) {
console.log('searchProduct2');
const cacheKey = `searchProduct2:${store}:${pageSize}:${pageNumber}:${JSON.stringify(filter)}`;
filter = filter || new FilterProduct();
if (pageSize == 0)
pageSize = 500;
if (pageNumber == 0)
pageNumber = 1;
const toBoolean = (value: any) => value === true || value === 'true' || value === 'S';
const escapeSqlText = (value: string) => value.replace(/'/g, "''");
const orderByColumns = {
DESCRICAO: 'DESCRICAO',
PRECOVENDA: 'PRECOVENDA',
PRECOPROMOCIONAL: 'PRECOPROMOCIONAL',
PERCENTUALDESCONTO: 'PERCENTUALDESCONTO',
NOMEMARCA: 'NOMEMARCA',
};
const normalizedFilter = {
...filter,
text: filter.text ? filter.text.trim() : null,
markdown: toBoolean(filter.markdown),
offers: toBoolean(filter.offers),
oportunity: toBoolean(filter.oportunity),
promotion: toBoolean(filter.promotion),
onlyWithStock: toBoolean(filter.onlyWithStock),
brands: filter.brands || [],
};
const cacheKey = `searchProduct2:${store}:${pageSize}:${pageNumber}:${JSON.stringify(normalizedFilter)}`;
try {
const cachedProducts = await this.redisClient.get(cacheKey);
if (cachedProducts) {
console.log('Retornando produtos do cache');
return JSON.parse(cachedProducts);
}
} catch (err) {
console.error('Erro ao acessar o Redis no searchProduct2:', err?.message || err);
}
const sql = 'SELECT esvlistaprodutos.CODPROD "idProduct" ' +
` ,esvlistaprodutos.SEQ "seq" ` +
@@ -1290,59 +1331,73 @@ export class SalesService {
' WHERE 1 = 1 ';
let where = "";
if (filter.text != null) {
where += ` AND ( ESF_REMOVE_ACENTUACAO(UPPER(esvlistaprodutos.descricao)) LIKE ` +
` ESF_REMOVE_ACENTUACAO(REPLACE('${filter.text}', '@', '%'))||'%' ` +
` OR ESF_REMOVE_ACENTUACAO(UPPER(esvlistaprodutos.nomeecommerce)) LIKE ` +
` ESF_REMOVE_ACENTUACAO(REPLACE('${filter.text}', '@', '%'))||'%' ` +
` OR esvlistaprodutos.codprod = REGEXP_REPLACE('${filter.text}', '[^0-9]', '') ` +
` OR esvlistaprodutos.codauxiliar = REGEXP_REPLACE('${filter.text}', '[^0-9]', '') ` +
` OR esvlistaprodutos.nomemarca = REPLACE('${filter.text}', '@', '%') ` +
` OR esvlistaprodutos.codfab LIKE '${filter.text}%' )`;
if (normalizedFilter.text != null && normalizedFilter.text.length > 0) {
const textSearch = escapeSqlText(normalizedFilter.text.toUpperCase()).replace('@', '%');
const numbers = normalizedFilter.text.replace(/[^0-9]/g, '');
if (numbers.length > 0 && numbers === normalizedFilter.text) {
where += ` AND ( esvlistaprodutos.codprod = ${numbers} ` +
` OR esvlistaprodutos.codauxiliar = '${numbers}' )`;
} else {
where += ` AND ( esvlistaprodutos.descricao LIKE '${textSearch}%' ` +
` OR esvlistaprodutos.nomeecommerce LIKE '${textSearch}%' ` +
` OR esvlistaprodutos.nomemarca = '${textSearch}' ` +
` OR esvlistaprodutos.codfab LIKE '${textSearch}%' `;
if (numbers.length > 0) {
where += ` OR esvlistaprodutos.codprod = ${numbers} ` +
` OR esvlistaprodutos.codauxiliar = '${numbers}' `;
}
if (filter.urlCategory != null) {
where += ` AND esvlistaprodutos.urlcategoria like '${filter.urlCategory}%'`;
where += ` )`;
}
}
if (filter.urlCategory != null && filter.urlCategory.length > 0) {
where += ` AND esvlistaprodutos.urlcategoria like '${escapeSqlText(filter.urlCategory)}%'`;
}
if (store !== '99') {
where += ` AND esvlistaprodutos.codfilial = '${escapeSqlText(store)}' `;
}
if (normalizedFilter.markdown) {
where += ` AND esvlistaprodutos.produto_com_reducao_preco = 'S' `;
}
if (normalizedFilter.offers) {
where += ` AND esvlistaprodutos.produto_em_campanha = 'D' `;
}
if (normalizedFilter.oportunity) {
where += ` AND esvlistaprodutos.produto_oportunidade = 'O' `;
}
if (normalizedFilter.promotion) {
where += ` AND esvlistaprodutos.produto_em_promocao = 'S' `;
}
where += ` AND (esvlistaprodutos.codfilial = '${store}' OR '${store}' = '99') `;
where += ` AND (esvlistaprodutos.produto_com_reducao_preco = '${(filter.markdown ? 'S' : 'N')}' OR '${(filter.markdown ? 'S' : 'N')}' = 'N') `;
where += ` AND (esvlistaprodutos.produto_em_campanha = '${(filter.offers ? 'D' : 'N')}' OR '${(filter.offers ? 'S' : 'N')}' = 'N') `;
where += ` AND (esvlistaprodutos.produto_em_campanha = '${(filter.oportunity ? 'O' : 'N')}' OR '${(filter.oportunity ? 'O' : 'N')}' = 'N') `;
where += ` AND (esvlistaprodutos.produto_em_promocao = '${(filter.promotion ? 'S' : 'N')}' OR '${(filter.promotion ? 'S' : 'N')}' = 'N') `;
if (filter.onlyWithStock) {
if (normalizedFilter.onlyWithStock) {
if (filter.storeStock == '' || filter.storeStock == null) {
where += ` AND EXISTS( SELECT P.CODPROD FROM ESVLISTAPRODUTOS P ` +
` WHERE P.CODPROD = ESVLISTAPRODUTOS.CODPROD ` +
` AND P.QTESTOQUE_DISPONIVEL > 0 ) `;
} else {
where += ` AND EXISTS( SELECT P.CODPROD FROM ESVLISTAPRODUTOS P ` +
` WHERE P.CODPROD = ESVLISTAPRODUTOS.CODPROD AND P.CODFILIAL = '${filter.storeStock}' ` +
` WHERE P.CODPROD = ESVLISTAPRODUTOS.CODPROD AND P.CODFILIAL = '${escapeSqlText(filter.storeStock)}' ` +
` AND P.ESTOQUE_DISP_LOJA > 0 ) `;
}
}
if (filter.percentOffMin > 0) {
where += ` AND esvlistaprodutos.PERCENTUALDESCONTO >= ${filter.percentOffMin}`;
if (Number(filter.percentOffMin) > 0) {
where += ` AND esvlistaprodutos.PERCENTUALDESCONTO >= ${Number(filter.percentOffMin)}`;
}
if (filter.percentOffMax > 0) {
where += ` AND esvlistaprodutos.PERCENTUALDESCONTO <= ${filter.percentOffMax}`;
if (Number(filter.percentOffMax) > 0) {
where += ` AND esvlistaprodutos.PERCENTUALDESCONTO <= ${Number(filter.percentOffMax)}`;
}
let xbrands = '';
if (filter && filter.brands && filter.brands.length > 0) {
const brands = filter.brands;
brands.forEach(b => {
if (xbrands.length > 0) {
xbrands += ', ' + '\'' + b + '\'';
} else {
xbrands = '\'' + b + '\'';
}
});
if (normalizedFilter.brands.length > 0) {
const xbrands = normalizedFilter.brands
.filter(b => b != null && b.length > 0)
.map(b => `'${escapeSqlText(b)}'`)
.join(', ');
where += ` AND esvlistaprodutos.nomemarca in ( ${xbrands} )`;
}
const orderBy = `ORDER BY esvlistaprodutos.${(filter.orderBy == null) ? 'DESCRICAO' : filter.orderBy}`;
const orderByColumn = orderByColumns[filter.orderBy] || 'DESCRICAO';
const orderBy = `ORDER BY esvlistaprodutos.${orderByColumn}`;
const skipReg = ((pageNumber - 1) * pageSize);
const pagination = ` OFFSET ${skipReg} ROWS FETCH NEXT ${pageSize} ROWS ONLY`;
@@ -1352,11 +1407,14 @@ export class SalesService {
await queryRunner.connect();
try {
console.log("hora de buscar produtos: " + new Date().toISOString())
let products = await queryRunner.manager.query(sql + where + orderBy + pagination) as SalesProduct[];
console.log("hora final de buscar produtos: " + new Date().toISOString())
products = this.createListImages(products);
console.log("hora de buscar imagens: " + new Date().toISOString())
console.log("Total de produtos: " + products.length);
await this.redisClient.set(cacheKey, JSON.stringify(products), 'EX', 900);
try { await this.redisClient.set(cacheKey, JSON.stringify(products), 'EX', 900); } catch (cacheErr) { console.error('Erro ao salvar cache searchProduct2:', cacheErr?.message || cacheErr); }
return products;
} catch (err) {

View File

@@ -149,16 +149,25 @@ export class ShoppingService {
await this.createShopping(idCart, itemShopping.invoiceStore, itemShopping.seller, queryRunner);
}
console.log('Incluindo item 04 - ' + Date.now().toString());
const item = await this.getItemCartById(itemShopping.idCart, itemShopping.id);
const item = await queryRunner.manager
.getRepository(ShoppingItens)
.createQueryBuilder('estprevendai')
.where("\"estprevendai\".idcart = :idcart", { idcart: idCart })
.andWhere("\"estprevendai\".id = :id", { id: itemShopping.id })
.andWhere("\"estprevendai\".dtcancel is null")
.getOne();
console.log('Incluindo item 05 - ' + Date.now().toString());
if (item) {
itemShopping.id = item.id;
this.updateItem(itemShopping);
return await this.getItemCartById(itemShopping.idCart, itemShopping.id);
await this.updateItemCart(itemShopping, queryRunner);
await this.calculateProfitShoppping(idCart, queryRunner);
await this.updateTotalShopping(idCart, queryRunner);
await queryRunner.commitTransaction();
return itemShopping;
}
console.log('Incluindo item 06 - ' + Date.now().toString());
const recordItens = await queryRunner.query(`SELECT COUNT(1) as "recordNo" FROM ESTPREVENDAI WHERE IDCART = '${itemShopping.idCart}'`);
const recordItens = await queryRunner.query(`SELECT COUNT(1) as "recordNo" FROM ESTPREVENDAI WHERE IDCART = :1`, [idCart]);
let numSeq = 1;
if (recordItens != null && recordItens.length > 0) {
numSeq = recordItens[0].recordNo + 1;
@@ -266,10 +275,10 @@ export class ShoppingService {
console.log('Incluindo item 07 - ' + Date.now().toString());
// await queryRunner.manager.save(createItemShopping);
console.log('Incluindo item 08 - ' + Date.now().toString());
await this.calculateProfitShoppping(idCart, queryRunner);
await this.updateTotalShopping(idCart, queryRunner);
await queryRunner.commitTransaction();
console.log('Incluindo item 09 - ' + Date.now().toString());
await this.calculateProfitShoppping(idCart, queryRunner);
await this.updateTotalShopping(idCart);
return createItemShopping;
@@ -300,13 +309,32 @@ export class ShoppingService {
}
async updateTotalShopping(idCart: string) {
async updateTotalShopping(idCart: string, activeQueryRunner?: QueryRunner) {
if (activeQueryRunner) {
await this.updateTotalShoppingWithRunner(idCart, activeQueryRunner);
return;
}
const connection = new Connection(connectionOptions);
await connection.connect();
const queryRunner = connection.createQueryRunner();
await queryRunner.connect();
await queryRunner.startTransaction();
try {
await this.updateTotalShoppingWithRunner(idCart, queryRunner);
await queryRunner.commitTransaction();
} catch (error) {
await queryRunner.rollbackTransaction();
throw error;
} finally {
await queryRunner.release();
await connection.close();
}
}
private async updateTotalShoppingWithRunner(idCart: string, queryRunner: QueryRunner) {
const prevenda = await queryRunner
.query('SELECT SUM(ESTPREVENDAI.PTABELA * ESTPREVENDAI.QT) as "vltabela" ' +
' ,SUM(ESTPREVENDAI.PVENDA * ESTPREVENDAI.QT) as "vlatend" ' +
@@ -330,26 +358,9 @@ export class ShoppingService {
idCart
]);
}
await queryRunner.commitTransaction();
} catch (error) {
await queryRunner.rollbackTransaction();
throw error;
} finally {
await queryRunner.release();
await connection.close();
}
}
async updateItem(itemShopping: ShoppingItem) {
const connection = new Connection(connectionOptions);
await connection.connect();
const queryRunner = connection.createQueryRunner();
await queryRunner.connect();
await queryRunner.startTransaction();
try {
private async updateItemCart(itemShopping: ShoppingItem, queryRunner: QueryRunner) {
const sql = ' UPDATE ESTPREVENDAI SET ' +
' PVENDA = :1 ' +
' ,PTABELA = :2 ' +
@@ -370,11 +381,20 @@ export class ShoppingService {
itemShopping.environment,
itemShopping.id
]);
}
await queryRunner.commitTransaction();
async updateItem(itemShopping: ShoppingItem) {
const connection = new Connection(connectionOptions);
await connection.connect();
const queryRunner = connection.createQueryRunner();
await queryRunner.connect();
await queryRunner.startTransaction();
try {
await this.updateTotalShopping(itemShopping.idCart);
await this.updateItemCart(itemShopping, queryRunner);
await this.updateTotalShopping(itemShopping.idCart, queryRunner);
await this.calculateProfitShoppping(itemShopping.idCart, queryRunner);
await queryRunner.commitTransaction();
} catch (erro) {
await queryRunner.rollbackTransaction();
@@ -419,9 +439,9 @@ export class ShoppingService {
// })
// .where("\"ESTPREVENDAI\".id = :id", { id: itemShopping.id })
// .execute();
await queryRunner.commitTransaction();
await this.calculateProfitShoppping(itemShopping.idCart, queryRunner);
await this.updateTotalShopping(itemShopping.idCart);
await this.updateTotalShopping(itemShopping.idCart, queryRunner);
await queryRunner.commitTransaction();
return itemShopping;
} catch (erro) {
await queryRunner.rollbackTransaction();
@@ -450,9 +470,11 @@ export class ShoppingService {
id
]);
}
await queryRunner.commitTransaction();
await this.updateTotalShopping(item.idCart);
if (item != null) {
await this.updateTotalShopping(item.idCart, queryRunner);
await this.calculateProfitShoppping(item.idCart, queryRunner);
}
await queryRunner.commitTransaction();
} catch (erro) {
await queryRunner.rollbackTransaction();
throw erro;
@@ -484,8 +506,7 @@ export class ShoppingService {
' ,VLDESCONTO = :3 ' +
' ,CODFUNCDESC = :4 ' +
' WHERE ID = :5 ';
items.filter(item => item.promotion == null || item.promotion == 0)
.forEach(async (item) => {
for (const item of items.filter(item => item.promotion == null || item.promotion == 0)) {
const price = (item.listPrice * (1 - (order.percentDiscount / 100))).toFixed(2);
listPriceTotal += (item.listPrice * item.quantity);
discountTotal += ((Number.parseFloat(item.listPrice.toFixed(2)) - Number.parseFloat(price)) * item.quantity);
@@ -507,7 +528,7 @@ export class ShoppingService {
// })
// .where("\"ESTPREVENDAI\".id = :id", { id: item.id })
// .execute();
});
}
console.log('total de desconto: ' + discountTotal);
const sqlOrder = 'UPDATE ESTPREVENDAC SET ' +
' VLPEDIDO = :1 ' +
@@ -529,9 +550,9 @@ export class ShoppingService {
// })
// .where("\"ESTPREVENDAC\".id = :id", { id: order.id })
// .execute();
await queryRunner.commitTransaction();
await this.calculateProfitShoppping(order.id, queryRunner);
await this.updateTotalShopping(order.id);
await this.updateTotalShopping(order.id, queryRunner);
await queryRunner.commitTransaction();
} catch (err) {
console.log(err);
await queryRunner.rollbackTransaction();