diff --git a/.env b/.env new file mode 100644 index 0000000..93f450a --- /dev/null +++ b/.env @@ -0,0 +1,13 @@ +ORACLE_CLIENT_PATH='/usr/lib/oracle/21/client64/lib' + + +###REDIS +REDIS_HOST='172.35.0.217' +REDIS_PORT='6379' + + +####ORACLE +PORT='8065' +DB_USERNAME='simplifique' +DB_PASSWORD='simplifique' +DB_CONNECT_STRING='(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=172.35.0.250)(PORT=1521))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=ORCL)))' diff --git a/.gitea/workflows/deploy-api.yaml b/.gitea/workflows/deploy-api.yaml new file mode 100644 index 0000000..04c29a7 --- /dev/null +++ b/.gitea/workflows/deploy-api.yaml @@ -0,0 +1,27 @@ +name: Deploy NestJS API +on: [push] + +jobs: + build-and-push-deploy: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Login no Harbor + run: | + echo "${{ secrets.HARBOR_PASSWORD }}" | docker login 172.35.0.216 -u ${{ secrets.HARBOR_USERNAME }} --password-stdin + + - name: Build e Push + run: | + TAG=${{ gitea.sha }} + docker build -t 172.35.0.216/library/vendaweb-api:$TAG . + docker tag 172.35.0.216/library/vendaweb-api:$TAG 172.35.0.216/library/vendaweb-api:latest + + docker push 172.35.0.216/library/vendaweb-api:$TAG + docker push 172.35.0.216/library/vendaweb-api:latest + + - name: Notificar Portainer via Webhook + run: | + # O Webhook avisa o Portainer para puxar a nova imagem imediatamente + curl -X POST "${{ secrets.PORTAINER_WEBHOOK_VENDAWEBAPI }}" \ No newline at end of file diff --git a/.gitea/workflows/rollback.md b/.gitea/workflows/rollback.md new file mode 100644 index 0000000..74f0df8 --- /dev/null +++ b/.gitea/workflows/rollback.md @@ -0,0 +1,7 @@ +O Rollback via Git (Mais Seguro) + +No Gitea, faça um git revert no commit que deu erro. + +Dê o git push. + +O Portainer detectará a mudança e atualizará o serviço para a versão estável de forma oficial. \ No newline at end of file diff --git a/.gitignore b/.gitignore index 62da189..24123c3 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,6 @@ lerna-debug.log* !.vscode/launch.json !.vscode/extensions.json +# Environment variables +.env + diff --git a/Dockerfile b/Dockerfile index 8212c4d..b06031e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,32 +1,39 @@ -FROM node:16 +# Estágio 1: Build +FROM node:16-bullseye-slim AS builder +WORKDIR /app +COPY package*.json ./ +RUN npm install --legacy-peer-deps +COPY . . +RUN npm run build +FROM node:16-bullseye-slim +# Instalar dependências do Oracle RUN apt-get update && apt-get install -y \ - apt-transport-https \ - ca-certificates \ libaio1 \ unzip \ wget \ - libc6 \ - libncurses5 && \ - mkdir -p /opt/oracle && \ - wget https://download.oracle.com/otn_software/linux/instantclient/instantclient-basic-linuxx64.zip -O /opt/oracle/instantclient-basic-linuxx64.zip && \ - unzip /opt/oracle/instantclient-basic-linuxx64.zip -d /opt/oracle && \ - rm /opt/oracle/instantclient-basic-linuxx64.zip && \ - ln -s /opt/oracle/instantclient_* /opt/oracle/instantclient && \ - echo "/opt/oracle/instantclient" > /etc/ld.so.conf.d/oracle-instantclient.conf && \ - ldconfig + && mkdir -p /opt/oracle +# Instalar Oracle Instant Client +RUN wget https://download.oracle.com/otn_software/linux/instantclient/instantclient-basic-linuxx64.zip -O /opt/oracle/client.zip && \ + unzip /opt/oracle/client.zip -d /opt/oracle && \ + rm /opt/oracle/client.zip && \ + ln -s /opt/oracle/instantclient_* /opt/oracle/instantclient + +# Configurar o sistema para encontrar as bibliotecas do Oracle +ENV LD_LIBRARY_PATH=/opt/oracle/instantclient +RUN echo "/opt/oracle/instantclient" > /etc/ld.so.conf.d/oracle-instantclient.conf && ldconfig WORKDIR /app +# Copiar apenas o necessário do estágio anterior +COPY --from=builder /app/dist ./dist +COPY --from=builder /app/package*.json ./ +COPY --from=builder /app/node_modules ./node_modules -COPY package*.json ./ - - -RUN npm install --legacy-peer-deps - -COPY . . - +# Variáveis de ambiente padrão para o driver oracledb +ENV OCI_LIB_DIR=/opt/oracle/instantclient +ENV OCI_INC_DIR=/opt/oracle/instantclient/sdk/include CMD ["npm", "run", "start:prod"] \ No newline at end of file diff --git a/README.md b/README.md index a59ef92..9cee7a2 100644 --- a/README.md +++ b/README.md @@ -1,75 +1,75 @@ -

- Nest Logo -

- -[travis-image]: https://api.travis-ci.org/nestjs/nest.svg?branch=master -[travis-url]: https://travis-ci.org/nestjs/nest -[linux-image]: https://img.shields.io/travis/nestjs/nest/master.svg?label=linux -[linux-url]: https://travis-ci.org/nestjs/nest - -

A progressive Node.js framework for building efficient and scalable server-side applications, heavily inspired by Angular.

-

-NPM Version -Package License -NPM Downloads -Travis -Linux -Coverage -Gitter -Backers on Open Collective -Sponsors on Open Collective - - -

- - -## Description - -[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository. - -## Installation - -```bash -$ npm install -``` - -## Running the app - -```bash -# development -$ npm run start - -# watch mode -$ npm run start:dev - -# production mode -$ npm run start:prod -``` - -## Test - -```bash -# unit tests -$ npm run test - -# e2e tests -$ npm run test:e2e - -# test coverage -$ npm run test:cov -``` - -## Support - -Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support). - -## Stay in touch - -- Author - [Kamil Myśliwiec](https://kamilmysliwiec.com) -- Website - [https://nestjs.com](https://nestjs.com/) -- Twitter - [@nestframework](https://twitter.com/nestframework) - -## License - - Nest is [MIT licensed](LICENSE). +

+ Nest Logo +

+ +[travis-image]: https://api.travis-ci.org/nestjs/nest.svg?branch=master +[travis-url]: https://travis-ci.org/nestjs/nest +[linux-image]: https://img.shields.io/travis/nestjs/nest/master.svg?label=linux +[linux-url]: https://travis-ci.org/nestjs/nest + +

A progressive Node.js framework for building efficient and scalable server-side applications, heavily inspired by Angular.

+

+NPM Version +Package License +NPM Downloads +Travis +Linux +Coverage +Gitter +Backers on Open Collective +Sponsors on Open Collective + + +

+ + +## Description + +[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository. + +## Installation + +```bash +$ npm install +``` + +## Running the app + +```bash +# development +$ npm run start + +# watch mode +$ npm run start:dev + +# production mode +$ npm run start:prod +``` + +## Test + +```bash +# unit tests +$ npm run test + +# e2e tests +$ npm run test:e2e + +# test coverage +$ npm run test:cov +``` + +## Support + +Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support). + +## Stay in touch + +- Author - [Kamil Myśliwiec](https://kamilmysliwiec.com) +- Website - [https://nestjs.com](https://nestjs.com/) +- Twitter - [@nestframework](https://twitter.com/nestframework) + +## License + + Nest is [MIT licensed](LICENSE). diff --git a/docker-compose.yml b/docker-compose.yml index 6aa3eac..661cdbb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,14 +1,18 @@ version: '3.8' services: - vendaweb: - image: link70/vendaweb - deploy: - replicas: 20 - resources: - limits: - cpus: '0.5' - memory: 512M + vendaweb-api: + image: 172.35.0.216/library/vendaweb-api:latest ports: - "8065:8065" - restart: always \ No newline at end of file + networks: + - simplifique-network + deploy: + replicas: 4 + update_config: + order: start-first + parallelism: 1 + +networks: + simplifique-network: + external: true \ No newline at end of file diff --git a/src/Auth/services/user.service.ts b/src/Auth/services/user.service.ts index 86584c5..d62aa80 100644 --- a/src/Auth/services/user.service.ts +++ b/src/Auth/services/user.service.ts @@ -93,7 +93,7 @@ export class UserService { ' WHERE PCEMPR.CODFILIAL = PCFILIAL.CODIGO (+)' + ' AND PCPARAMFILIAL.CODFILIAL = \'99\' ' + ' AND PCPARAMFILIAL.NOME = \'CON_CODSETORGERENTELOJA\' ' + - ' AND PCEMPR.EMAIL = :username AND PCEMPR.SENHABD = CRYPT(:password, USUARIOBD)'; + ' AND PCEMPR.USUARIOBD = :username AND PCEMPR.SENHABD = CRYPT(:password, USUARIOBD)'; const users = await queryRunner.manager .query(sql, [user.email, user.password]); @@ -141,8 +141,8 @@ export class UserService { const noDeliveryDays = await queryRunner.manager .query(sqlDiasSemEntrega, [Number.parseInt(users[0].deliveryTime)]); - const days = Number.parseInt(deliveryDays2[0].days) + - ( noDeliveryDays.length > 0 ? Number.parseInt(noDeliveryDays[0].daysNoDelivery) : 0 ); + const days = Number.parseInt(deliveryDays2[0].days) + + (noDeliveryDays.length > 0 ? Number.parseInt(noDeliveryDays[0].daysNoDelivery) : 0); const userDb = users[0]; console.log(userDb); diff --git a/src/app.controller.ts b/src/app.controller.ts index 470a286..1902f02 100644 --- a/src/app.controller.ts +++ b/src/app.controller.ts @@ -12,9 +12,9 @@ export class AppController { } @Get('health') -@ApiOperation({ summary: 'Health check' }) -healthCheck() { - return { status: 'ok' }; -} + @ApiOperation({ summary: 'Health check' }) + healthCheck() { + return { status: 'SIMPLIFIQUE HOME CENTER 2026' }; + } } diff --git a/src/configs/typeorm.config.ts b/src/configs/typeorm.config.ts index 3b30a6b..2bf88a4 100644 --- a/src/configs/typeorm.config.ts +++ b/src/configs/typeorm.config.ts @@ -1,18 +1,17 @@ import { TypeOrmModuleOptions } from '@nestjs/typeorm'; import { ConnectionOptions } from 'typeorm'; +import 'dotenv/config'; export const typeOrmConfig: TypeOrmModuleOptions = { type: "oracle", - // host: "192.168.100.40", - // username: "LIVIA", - // password: "LIVIA", - host: "10.1.1.241", - username: "SEVEN", - password: "USR54SEV", - // username: "API", - // password: "E05H5KIEQV3YKDJR", + host: "172.35.0.250", + username: process.env.DB_USERNAME || "simplifique", + password: process.env.DB_PASSWORD || "simplifique", + connectString: + process.env.DB_CONNECT_STRING || + '(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=172.35.0.250)(PORT=1521))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=ORCL)))', port: 1521, - sid: "WINT", + sid: "ORCL", synchronize: false, logging: false, entities: [__dirname + '/../**/*.entity.{js,ts}'], @@ -21,11 +20,14 @@ export const typeOrmConfig: TypeOrmModuleOptions = { export const connectionOptions: ConnectionOptions = { type: "oracle", - host: "10.1.1.241", - username: "SEVEN", - password: "USR54SEV", + host: "172.35.0.250", + username: process.env.DB_USERNAME || "simplifique", + password: process.env.DB_PASSWORD || "simplifique", + connectString: + process.env.DB_CONNECT_STRING || + '(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=172.35.0.250)(PORT=1521))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=ORCL)))', port: 1521, - sid: "WINT", + sid: "ORCL", synchronize: false, logging: false, entities: [__dirname + '/../**/*.entity.{js,ts}'], diff --git a/src/domain/entity/tables/pcclient.entity.ts b/src/domain/entity/tables/pcclient.entity.ts index f5570be..5a6cee5 100644 --- a/src/domain/entity/tables/pcclient.entity.ts +++ b/src/domain/entity/tables/pcclient.entity.ts @@ -1355,7 +1355,7 @@ export class Pcclient { @Column({ name: 'ORGAOPUBMUNICIPAL' }) orgaopubmunicipal: string; - @Column({ name: 'CODCIDADECOM' }) + @Column({ name: 'CODCIDADECOM' }) codcidadecom: number; @Column({ name: 'CODPROMOCAOMED' }) @@ -1622,8 +1622,8 @@ export class Pcclient { @Column({ name: 'CODCONDCOMERCIAL' }) codcondcomercial: string; - @Column({ name: 'MEIOCOMUNICACAO' }) - meiocomunicacao: string; + // @Column({ name: 'MEIOCOMUNICACAO' }) + // meiocomunicacao: string; @Column({ name: 'CODGRUPOCOMERCIALMED' }) codgrupocomercialmed: number; @@ -1645,5 +1645,5 @@ export class Pcclient { @OneToMany(() => Pcpedc, pedidos => pedidos.pcclient) pedidos: Pcpedc[]; - + } \ No newline at end of file diff --git a/src/redis/redis.providers.ts b/src/redis/redis.providers.ts index e32e868..0b5e372 100644 --- a/src/redis/redis.providers.ts +++ b/src/redis/redis.providers.ts @@ -1,12 +1,23 @@ import { Provider } from '@nestjs/common'; + import Redis = require('ioredis'); + + export const redisProvider: Provider = { + provide: 'REDIS_CLIENT', + useFactory: () => { + return new Redis({ - host: '10.1.1.109', + + host: '172.35.0.217', + port: 6379, + }); + }, -}; + +}; \ No newline at end of file diff --git a/src/sales/customer/customer.service.ts b/src/sales/customer/customer.service.ts index 60d5f7d..9ffc223 100644 --- a/src/sales/customer/customer.service.ts +++ b/src/sales/customer/customer.service.ts @@ -44,7 +44,7 @@ export class CustomerService { ' ,pccidade.codibge as "ibgeCode" ' + ' ,pcclient.dtnasc as "birthdate" ' + ' ,pcclient.codatv1 as "ramoId" ' + - ' ,pcclient.meiocomunicacao as "communicate" ' + + // ' ,pcclient.meiocomunicacao as "communicate" ' + ' ,pcclient.latitude as "latitude" ' + ' ,pcclient.longitude as "longitude" ' + ' ,pcclient.codmunicipio as "ibgeCode" ' + @@ -102,16 +102,16 @@ export class CustomerService { ' ,pcclient.telent as "phone" ' + ' ,pcclient.telcelent as "cellPhone" ' + ' ,pcclient.ieent as "numberState" ' + - ' ,pcclient.codcategoria as "categoryId" ' + - ' ,pcclient.codsubcategoria as "subCategoryId" ' + + // ' ,pcclient.codcategoria as "categoryId" ' + + // ' ,pcclient.codsubcategoria as "subCategoryId" ' + ' ,pcclient.codpraca as "placeId" ' + ' ,pcclient.codusur1 as "sellerId" ' + ' ,pccidade.codibge as "ibgeCode" ' + ' ,pcclient.dtnasc as "birthdate" ' + ' ,pcclient.codatv1 as "ramoId" ' + - ' ,pcclient.meiocomunicacao as "communicate" ' + + // ' ,pcclient.meiocomunicacao as "communicate" ' + ' ,pcclient.latitude as "latitude" ' + - ' ,pcclient.longitude as "longitude" ' + + ' ,pcclient.longitude as "longitude" ' + ' ,pcclient.codmunicipio as "ibgeCode" ' + ' ,pcclient.codcidade as "cityId" ' + ' ,pcclient.tipoendereco as "addressType" ' + @@ -158,7 +158,7 @@ export class CustomerService { ' ,pccidade.codibge as "ibgeCode" ' + ' ,pcclient.dtnasc as "birthdate" ' + ' ,pcclient.codatv1 as "ramoId" ' + - ' ,pcclient.meiocomunicacao as "communicate" ' + + //' ,pcclient.meiocomunicacao as "communicate" ' + ' ,pcclient.latitude as "latitude" ' + ' ,pcclient.longitude as "longitude" ' + ' ,pcclient.codmunicipio as "ibgeCode" ' + @@ -173,7 +173,7 @@ export class CustomerService { FROM PCPRACA WHERE PCPRACA.CODPRACA = ${customer[0].placeId}`); - return {...customer[0], place: place[0]}; + return { ...customer[0], place: place[0] }; } catch (error) { console.log(error); throw error; @@ -267,16 +267,16 @@ export class CustomerService { newCustomer.telcelent = customer.cellPhone; newCustomer.celularwhatsapp = customer.cellPhone; newCustomer.codusur1 = customer.sellerId; - newCustomer.codatv1 = ( customer.ramo != null && customer.ramo.id > 0 ) ? customer.ramo.id : newCustomer.codatv1; + newCustomer.codatv1 = (customer.ramo != null && customer.ramo.id > 0) ? customer.ramo.id : newCustomer.codatv1; //Endereço de entrega newCustomer.cepent = customer.zipCode; newCustomer.enderent = customer.address.toUpperCase(); newCustomer.numeroent = customer.addressNumber; - if ( customer.complement !== null && customer.complement.length > 80 ) { - newCustomer.complementoent = customer.complement.substring(0, 80 ).toUpperCase(); + if (customer.complement !== null && customer.complement.length > 80) { + newCustomer.complementoent = customer.complement.substring(0, 80).toUpperCase(); } else { - if ( customer.complement != null ) { - newCustomer.complementoent = customer.complement.toUpperCase(); + if (customer.complement != null) { + newCustomer.complementoent = customer.complement.toUpperCase(); } } newCustomer.bairroent = customer.neighborhood.toUpperCase(); @@ -286,10 +286,10 @@ export class CustomerService { newCustomer.cepcom = customer.zipCode; newCustomer.endercom = customer.address.toUpperCase(); newCustomer.numerocom = customer.addressNumber.toUpperCase(); - if ( customer.complement !== null && customer.complement.length > 80 ) { - newCustomer.complementocom = customer.complement.substring(0, 80 ).toUpperCase(); + if (customer.complement !== null && customer.complement.length > 80) { + newCustomer.complementocom = customer.complement.substring(0, 80).toUpperCase(); } else { - if ( customer.complement != null ) { + if (customer.complement != null) { newCustomer.complementocom = customer.complement.toUpperCase(); } } @@ -300,12 +300,12 @@ export class CustomerService { newCustomer.cepcob = customer.zipCode; newCustomer.endercob = customer.address.toUpperCase(); newCustomer.numerocob = customer.addressNumber; - if ( customer.complement !== null && customer.complement.length > 80 ) { - newCustomer.complementocob = customer.complement.substring(0, 80 ).toUpperCase(); + if (customer.complement !== null && customer.complement.length > 80) { + newCustomer.complementocob = customer.complement.substring(0, 80).toUpperCase(); } else { - if ( customer.complement ) { + if (customer.complement) { newCustomer.complementocob = customer.complement.toUpperCase(); - } + } } newCustomer.bairrocob = customer.neighborhood.toUpperCase(); newCustomer.municcob = customer.city.toUpperCase(); @@ -317,7 +317,7 @@ export class CustomerService { newCustomer.codmunicipio = Number.parseInt(customer.ibgeCode); newCustomer.codcidadecom = newCustomer.codcidade; newCustomer.dtnasc = customer.birthdate; - newCustomer.meiocomunicacao = customer.communicate; + // newCustomer.meiocomunicacao = customer.communicate; newCustomer.codfunccad = customer.idUser; newCustomer.codfunccadastro = customer.idUser; newCustomer.codfuncultalter = customer.idUser; @@ -341,7 +341,7 @@ export class CustomerService { city: customer.city, state: customer.state, allowMessage: customer.allowMessage, cellPhone: customer.cellPhone, category: customer.category, subCategory: customer.subCategory, - place: customer.place, ramo: customer.ramo, meiocomunicacao: customer.communicate, + place: customer.place, ramo: customer.ramo, /*meiocomunicacao: customer.communicate,*/ latitude: customer.latitude, longitude: customer.longitude, ibgeCode: customer.ibgeCode, addressType: customer.addressType, }; @@ -361,8 +361,8 @@ export class CustomerService { city: customer.city, state: customer.state, allowMessage: customer.allowMessage, cellPhone: customer.cellPhone, category: customer.category, subCategory: customer.subCategory, - place: customer.place, meiocomunicacao: customer.communicate, - ramo: customer.ramo, latitude: customer.latitude, longitude: customer.longitude, + place: customer.place, /*meiocomunicacao: customer.communicate,*/ + ramo: customer.ramo, latitude: customer.latitude, longitude: customer.longitude, ibgeCode: customer.ibgeCode, addressType: customer.addressType, }; } @@ -378,7 +378,7 @@ export class CustomerService { await queryRunner.connect(); await queryRunner.startTransaction(); try { - console.log("MEIO DE COMUNICACAO: " + client.meiocomunicacao); + //console.log("MEIO DE COMUNICACAO: " + client.meiocomunicacao); await queryRunner.manager .createQueryBuilder() .update(Pcclient) @@ -418,13 +418,13 @@ export class CustomerService { codmunicipio: client.codmunicipio, codcidadecom: client.codcidade, dtnasc: client.dtnasc, - codatv1: client.codatv1, - meiocomunicacao: client.meiocomunicacao, + codatv1: client.codatv1, + // meiocomunicacao: client.meiocomunicacao, codfuncultalter: client.codfuncultalter, - dtultalter: client.dtultalter, + dtultalter: client.dtultalter, latitude: client.latitude, - longitude: client.longitude, - tipoendereco: client.tipoendereco + longitude: client.longitude, + tipoendereco: client.tipoendereco }) .where({ codcli: client.codcli }) .execute(); @@ -434,7 +434,7 @@ export class CustomerService { await queryRunner.rollbackTransaction(); throw err; } finally { - if ( queryRunner.isTransactionActive) { + if (queryRunner.isTransactionActive) { await queryRunner.rollbackTransaction(); } await queryRunner.release(); @@ -532,13 +532,13 @@ export class CustomerService { const connection = new Connection(connectionOptions); const queryRunner = connection.createQueryRunner(); try { - - await connection.connect(); - - await queryRunner.connect(); - // lets now open a new transaction: - await queryRunner.startTransaction(); + await connection.connect(); + + await queryRunner.connect(); + + // lets now open a new transaction: + await queryRunner.startTransaction(); let sql = `SELECT PROXNUMCLI as "proxnumcli" FROM PCCONSUM WHERE 1 = 1 FOR UPDATE`; @@ -566,14 +566,14 @@ export class CustomerService { } catch (err) { // since we have errors let's rollback changes we made - if ( queryRunner.isTransactionActive) { + if (queryRunner.isTransactionActive) { await queryRunner.rollbackTransaction(); } console.log(err); return -1; } finally { - if ( queryRunner.isTransactionActive) { + if (queryRunner.isTransactionActive) { await queryRunner.rollbackTransaction(); } // you need to release query runner which is manually created: @@ -603,7 +603,7 @@ export class CustomerService { console.log(err); throw err; } finally { - if ( queryRunner.isTransactionActive) { + if (queryRunner.isTransactionActive) { await queryRunner.rollbackTransaction(); } await queryRunner.release(); diff --git a/src/sales/sales/sales.controller.ts b/src/sales/sales/sales.controller.ts index 0e01487..a67bf88 100644 --- a/src/sales/sales/sales.controller.ts +++ b/src/sales/sales/sales.controller.ts @@ -176,6 +176,20 @@ export class SalesController { } } + + @Get('product/simil/:id') + @ApiOperation({ summary: 'Get products similar' }) + @ApiParam({ name: 'id', description: 'Product ID' }) + async getProductSimil(@Headers() headers, @Param('id') id: number) { + try { + const { store } = this.extractPaginationParams(headers); + return await this.salesService.GetProductsSimil(store, id); + } catch (e) { + throw new HttpException(e.message, HttpStatus.BAD_REQUEST); + } + } + + @Get('stock/:storeid/:id') @ApiOperation({ summary: 'Get product stock information' }) @ApiParam({ name: 'storeid', description: 'Store ID' }) diff --git a/src/sales/sales/sales.service.ts b/src/sales/sales/sales.service.ts index a9ffd36..7769578 100644 --- a/src/sales/sales/sales.service.ts +++ b/src/sales/sales/sales.service.ts @@ -20,10 +20,10 @@ import Redis = require('ioredis'); @Injectable() export class SalesService { - constructor( - @Inject('REDIS_CLIENT') private readonly redisClient: Redis.Redis, - private readonly customerService: CustomerService - ) {} + constructor( + @Inject('REDIS_CLIENT') private readonly redisClient: Redis.Redis, + private readonly customerService: CustomerService + ) { } async GetProducts2(store: string, pageSize: number, pageNumber: number, filter: FilterProduct = null,) { @@ -77,14 +77,16 @@ export class SalesService { esvlistaprodutos.LETRABASETINTOMETRICO as "letter", esvlistaprodutos.LINHATINTOMETRICO as "line", esvlistaprodutos.LITRAGEM as "can", - esvlistaprodutos.QUANTIDADE_ESTOQUE_GERAL as "full_stock" + esvlistaprodutos.QUANTIDADE_ESTOQUE_GERAL as "full_stock", + esvlistaprodutos.TEM_PRODUTO_SIMILAR as "similar", + NVL(esvlistaprodutos.TIPO, 'SEM') as "type_campaing" FROM ESVLISTAPRODUTOS - WHERE 1 = 1`; + WHERE 1 = 1 `; if (filter && filter.text.length > 0) { const description = filter.text.toUpperCase(); console.log('consultando por codigo de fabrica'); - + let products = await queryRunner.manager .getRepository(SalesProduct) .createQueryBuilder('esvlistaprodutos') @@ -127,6 +129,8 @@ export class SalesService { .addSelect("\"esvlistaprodutos\".LINHATINTOMETRICO", "line") .addSelect("\"esvlistaprodutos\".LITRAGEM", "can") .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 }) .andWhere("(\"esvlistaprodutos\".codfilial = :codfilial OR :codfilial = '99')", { codfilial: store }) .andWhere("(\"esvlistaprodutos\".produto_com_reducao_preco = :produtoComReducaoPreco OR :produtoComReducaoPreco = 'N')", @@ -184,6 +188,8 @@ export class SalesService { .addSelect("\"esvlistaprodutos\".LINHATINTOMETRICO", "line") .addSelect("\"esvlistaprodutos\".LITRAGEM", "can") .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 }) .andWhere("(\"esvlistaprodutos\".codfilial = :codfilial OR :codfilial = '99')", { codfilial: store }) .andWhere("(\"esvlistaprodutos\".produto_com_reducao_preco = :produtoComReducaoPreco OR :produtoComReducaoPreco = 'N')", @@ -260,6 +266,8 @@ export class SalesService { .addSelect("\"esvlistaprodutos\".LINHATINTOMETRICO", "line") .addSelect("\"esvlistaprodutos\".LITRAGEM", "can") .addSelect("\"esvlistaprodutos\".QUANTIDADE_ESTOQUE_GERAL", "full_stock") + .addSelect("\"esvlistaprodutos\".TEM_PRODUTO_SIMILAR", "similar") + .addSelect("\"esvlistaprodutos\".TIPO_CAMPANHA", "type_campaing") .where("esvlistaprodutos.brand in (" + xbrands + ")") .andWhere("\"esvlistaprodutos\".URLCATEGORIA LIKE :urlCategoria||'%'", { urlCategoria: filter.urlCategory }) .andWhere("(\"esvlistaprodutos\".codfilial = :codfilial OR :codfilial = '99')", { codfilial: store }) @@ -324,6 +332,8 @@ export class SalesService { .addSelect("\"esvlistaprodutos\".LINHATINTOMETRICO", "line") .addSelect("\"esvlistaprodutos\".LITRAGEM", "can") .addSelect("\"esvlistaprodutos\".QUANTIDADE_ESTOQUE_GERAL", "full_stock") + .addSelect("\"esvlistaprodutos\".TEM_PRODUTO_SIMILAR", "similar") + .addSelect("\"esvlistaprodutos\".TIPO_CAMPANHA", "type_campaing") .where("(\"esvlistaprodutos\".codfilial = :codfilial OR :codfilial = '99')", { codfilial: store }) .andWhere("(\"esvlistaprodutos\".produto_com_reducao_preco = :produtoComReducaoPreco OR :produtoComReducaoPreco = 'N')", { produtoComReducaoPreco: (filter.markdown.toString() == 'true') ? 'S' : 'N' }) @@ -357,92 +367,92 @@ export class SalesService { pageSize: number, pageNumber: number, urlDepartment: string - ): Promise { + ): Promise { const cacheKey = - 'searchByDepartment:' + - store + - '_' + - pageSize + - '_' + - pageNumber + - '_' + - urlDepartment; + 'searchByDepartment:' + + store + + '_' + + pageSize + + '_' + + pageNumber + + '_' + + urlDepartment; const lockKey = 'lock:' + cacheKey; const lockTimeout = 30; // lock expira em 30 segundos - + try { - const cachedResult = await this.redisClient.get(cacheKey); - if (cachedResult) { - console.log('Retornando resultado do cache (searchByDepartment)'); - return JSON.parse(cachedResult); - } + const cachedResult = await this.redisClient.get(cacheKey); + if (cachedResult) { + console.log('Retornando resultado do cache (searchByDepartment)'); + return JSON.parse(cachedResult); + } } catch (err) { - console.error('Erro ao acessar o Redis no searchByDepartment:', err?.message || err); + console.error('Erro ao acessar o Redis no searchByDepartment:', err?.message || err); } - + const lockValue = Date.now() + lockTimeout * 1000 + 1; let acquiredLock: string | null = null; try { - acquiredLock = await this.redisClient.set(lockKey, lockValue, 'NX', 'EX', lockTimeout); + acquiredLock = await this.redisClient.set(lockKey, lockValue, 'NX', 'EX', lockTimeout); } catch (err) { - console.error('Erro ao adquirir lock no Redis (searchByDepartment):', err?.message || err); + console.error('Erro ao adquirir lock no Redis (searchByDepartment):', err?.message || err); } - + if (acquiredLock === 'OK') { - const connectionDb = new Connection(connectionOptions); - await connectionDb.connect(); - const queryRunner = connectionDb.createQueryRunner(); - await queryRunner.connect(); - try { - if (pageSize === 0) pageSize = 50; - if (pageNumber === 0) pageNumber = 1; - const offSet = (pageNumber - 1) * pageSize; - - let products = await queryRunner.manager - .getRepository(SalesProduct) - .createQueryBuilder('esvlistaprodutos') - .where('"esvlistaprodutos".urldepartamento = :urlDepartment', { urlDepartment }) - .andWhere('("esvlistaprodutos".codfilial = :codfilial OR :codfilial = \'99\')', { codfilial: store }) - .limit(pageSize) - .offset(offSet) - .orderBy('"esvlistaprodutos".DESCRICAO', 'ASC') - .getMany(); - - products = this.createListImages(products); - + const connectionDb = new Connection(connectionOptions); + await connectionDb.connect(); + const queryRunner = connectionDb.createQueryRunner(); + await queryRunner.connect(); try { - await this.redisClient.set(cacheKey, JSON.stringify(products), 'EX', 3600); - } catch (cacheErr) { - console.error('Erro ao salvar o resultado no cache (searchByDepartment):', cacheErr?.message || cacheErr); + if (pageSize === 0) pageSize = 50; + if (pageNumber === 0) pageNumber = 1; + const offSet = (pageNumber - 1) * pageSize; + + let products = await queryRunner.manager + .getRepository(SalesProduct) + .createQueryBuilder('esvlistaprodutos') + .where('"esvlistaprodutos".urldepartamento = :urlDepartment', { urlDepartment }) + .andWhere('("esvlistaprodutos".codfilial = :codfilial OR :codfilial = \'99\')', { codfilial: store }) + .limit(pageSize) + .offset(offSet) + .orderBy('"esvlistaprodutos".DESCRICAO', 'ASC') + .getMany(); + + products = this.createListImages(products); + + try { + await this.redisClient.set(cacheKey, JSON.stringify(products), 'EX', 3600); + } catch (cacheErr) { + console.error('Erro ao salvar o resultado no cache (searchByDepartment):', cacheErr?.message || cacheErr); + } + + return products; + } catch (error) { + console.error('Erro ao executar a query no searchByDepartment:', error?.message || error); + throw error; + } finally { + await queryRunner.release(); + await connectionDb.close(); + + try { + const currentLockValue = await this.redisClient.get(lockKey); + if (currentLockValue === lockValue.toString()) { + await this.redisClient.del(lockKey); + } + } catch (lockErr) { + console.error('Erro ao liberar o lock do Redis (searchByDepartment):', lockErr?.message || lockErr); + } } - - return products; - } catch (error) { - console.error('Erro ao executar a query no searchByDepartment:', error?.message || error); - throw error; - } finally { - await queryRunner.release(); - await connectionDb.close(); - - try { - const currentLockValue = await this.redisClient.get(lockKey); - if (currentLockValue === lockValue.toString()) { - await this.redisClient.del(lockKey); - } - } catch (lockErr) { - console.error('Erro ao liberar o lock do Redis (searchByDepartment):', lockErr?.message || lockErr); - } - } } else { - console.log('Lock não adquirido (searchByDepartment), aguardando e tentando novamente...'); - await this.sleep(1000); - return this.searchByDepartment(store, pageSize, pageNumber, urlDepartment); + console.log('Lock não adquirido (searchByDepartment), aguardando e tentando novamente...'); + await this.sleep(1000); + return this.searchByDepartment(store, pageSize, pageNumber, urlDepartment); } - } - - - - + } + + + + async searchBySection(store: string, pageSize: number, pageNumber: number, urlDepartment: string, urlSection: string): Promise { const connectionDb = new Connection(connectionOptions); @@ -562,6 +572,8 @@ export class SalesService { .addSelect("\"esvlistaprodutos\".PRODUTO_EM_CAMPANHA", "compaing") .addSelect("\"esvlistaprodutos\".BASETINTOMETRICO", "base") .addSelect("\"esvlistaprodutos\".QUANTIDADE_ESTOQUE_GERAL", "full_stock") + .addSelect("\"esvlistaprodutos\".TEM_PRODUTO_SIMILAR", "similar") + .addSelect("\"esvlistaprodutos\".TIPO_CAMPANHA", "type_campaing") .where("esvlistaprodutos.idProduct = :id", { id: numbers }) .andWhere("\"esvlistaprodutos\".codfilial = :codfilial OR :codfilial = '99'", { codfilial: store }) .limit(pageSize) @@ -609,6 +621,8 @@ export class SalesService { .addSelect("\"esvlistaprodutos\".PRODUTO_EM_CAMPANHA", "compaing") .addSelect("\"esvlistaprodutos\".BASETINTOMETRICO", "base") .addSelect("\"esvlistaprodutos\".QUANTIDADE_ESTOQUE_GERAL", "full_stock") + .addSelect("\"esvlistaprodutos\".TEM_PRODUTO_SIMILAR", "similar") + .addSelect("\"esvlistaprodutos\".TIPO_CAMPANHA", "type_campaing") .where("esvlistaprodutos.CODAUXILIAR = :id", { id: numbers }) .andWhere("(\"esvlistaprodutos\".codfilial = :codfilial OR :codfilial = '99')", { codfilial: store }) .limit(pageSize) @@ -658,6 +672,8 @@ export class SalesService { .addSelect("\"esvlistaprodutos\".PRODUTO_EM_CAMPANHA", "compaing") .addSelect("\"esvlistaprodutos\".BASETINTOMETRICO", "base") .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 }) .andWhere("\"esvlistaprodutos\".codfilial = :codfilial OR :codfilial = '99'", { codfilial: store }) .limit(pageSize) @@ -704,6 +720,8 @@ export class SalesService { .addSelect("\"esvlistaprodutos\".PRODUTO_EM_CAMPANHA", "compaing") .addSelect("\"esvlistaprodutos\".BASETINTOMETRICO", "base") .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 }) .andWhere("\"esvlistaprodutos\".codfilial = :codfilial OR :codfilial = '99'", { codfilial: store }) .limit(pageSize) @@ -773,6 +791,8 @@ export class SalesService { .addSelect("\"esvlistaprodutos\".PRODUTO_EM_CAMPANHA", "compaing") .addSelect("\"esvlistaprodutos\".BASETINTOMETRICO", "base") .addSelect("\"esvlistaprodutos\".QUANTIDADE_ESTOQUE_GERAL", "full_stock") + .addSelect("\"esvlistaprodutos\".TEM_PRODUTO_SIMILAR", "similar") + .addSelect("\"esvlistaprodutos\".TIPO_CAMPANHA", "type_campaing") .where("esvlistaprodutos.idProduct = :id", { id: id }) .andWhere("\"esvlistaprodutos\".codfilial = :codfilial", { codfilial: store }) .orderBy("REPLACE(\"esvlistaprodutos\".DESCRICAO,'#', '')", "ASC") @@ -834,6 +854,8 @@ export class SalesService { ,esvlistaprodutos.PRODUTO_EM_CAMPANHA as "compaing" ,esvlistaprodutos.BASETINTOMETRICO as "base" ,esvlistaprodutos.QUANTIDADE_ESTOQUE_GERAL as "full_stock" + ,esvlistaprodutos.TEM_PRODUTO_SIMILAR as "similar" + ,esvlistaprodutos.TIPO_CAMPANHA as "type_campaing" FROM ESVLISTAPRODUTOS, ESTCOMPREJUNTO WHERE ESVLISTAPRODUTOS.CODPROD = ESTCOMPREJUNTO.CODPROD AND ESTCOMPREJUNTO.CODPRODVENDA = ${id} @@ -851,6 +873,68 @@ export class SalesService { } } + async GetProductsSimil(store: string, id: number) { + const connectionDb = new Connection(connectionOptions); + await connectionDb.connect(); + const queryRunner = connectionDb.createQueryRunner(); + await queryRunner.connect(); + try { + const sql = `SELECT esvlistaprodutos.CODPROD as "idProduct" + ,esvlistaprodutos.SEQ as "seq" + ,esvlistaprodutos.DESCRICAO as "smallDescription" + ,esvlistaprodutos.NOMEECOMMERCE as "title" + ,esvlistaprodutos.CODFAB as "idProvider" + ,esvlistaprodutos.CODAUXILIAR as "ean" + ,esvlistaprodutos.TIPOPRODUTO as "productType" + ,esvlistaprodutos.DADOSTECNICOS as "technicalData" + ,esvlistaprodutos.INFORMACOESTECNICAS as "description" + ,esvlistaprodutos.URLIMAGEM as "urlImage" + ,esvlistaprodutos.NOMEMARCA as "brand" + ,esvlistaprodutos.NOMEDEPARTAMENTO as "department" + ,esvlistaprodutos.NOMESECAO as "section" + ,esvlistaprodutos.NOMECATEGORIA as "category" + ,esvlistaprodutos.NOMEFORNECEDOR as "supplier" + ,esvlistaprodutos.CODIGOFILIAL as "store" + ,esvlistaprodutos.CLASSEVENDA as "saleAbc" + ,esvlistaprodutos.CLASSEESTOQUE as "stockAbc" + ,esvlistaprodutos.FORALINHA as "outLine" + ,esvlistaprodutos.PRECOVENDA as "listPrice" + ,esvlistaprodutos.PRECOPROMOCIONAL as "salePrice" + ,esvlistaprodutos.PRECOPROMOCIONAL as "salePromotion" + ,esvlistaprodutos.PERCENTUALDESCONTO as"offPercent" + ,esvlistaprodutos.QTESTOQUE_DISPONIVEL as "stock" + ,esvlistaprodutos.QTCAIXAS as "boxStock" + ,esvlistaprodutos.ESTOQUE_DISP_LOJA as "store_stock" + ,esvlistaprodutos.ESTOQUE_DISP_CAIXA_LOJA as "store_boxStock" + ,esvlistaprodutos.ESTOQUE_DISP_LOJA as "store_stock" + ,esvlistaprodutos.ESTOQUE_DISP_CAIXA_LOJA as "store_boxStock" + ,esvlistaprodutos.MULTIPLO as "mutiple" + ,esvlistaprodutos.UNIDADE as "unity" + ,esvlistaprodutos.URLDEPARTAMENTO as "urlDepartment" + ,esvlistaprodutos.URLSECAO as "urlSection" + ,esvlistaprodutos.PRODUTO_COM_REDUCAO_PRECO as "downPrice" + ,esvlistaprodutos.PRODUTO_EM_CAMPANHA as "compaing" + ,esvlistaprodutos.BASETINTOMETRICO as "base" + ,esvlistaprodutos.QUANTIDADE_ESTOQUE_GERAL as "full_stock" + ,esvlistaprodutos.TEM_PRODUTO_SIMILAR as "similar" + ,esvlistaprodutos.TIPO_CAMPANHA as "type_campaing" + FROM ESVLISTAPRODUTOS, PCPRODSIMIL + WHERE ESVLISTAPRODUTOS.CODPROD = PCPRODSIMIL.CODSIMIL + AND PCPRODSIMIL.CODPROD = ${id} + AND ESVLISTAPRODUTOS.CODFILIAL = '${store}' + ORDER BY REPLACE(esvlistaprodutos.DESCRICAO,'#', '')`; + let products: SalesProduct[] = await queryRunner.query(sql); + + products = this.createListImages(products); + return products; + } catch (error) { + throw error; + } finally { + await queryRunner.release(); + await connectionDb.close(); + } + } + async GetStocks(storeId: string, id: number) { const connectionDb = new Connection(connectionOptions); await connectionDb.connect(); @@ -874,9 +958,9 @@ export class SalesService { WHERE ESVESTOQUEVENDA.CODPROD = ${id} AND ESVESTOQUEVENDA.CODFILIAL = PCFILIAL.CODIGO ORDER BY TO_NUMBER(ESVESTOQUEVENDA.CODFILIAL) `; - - const stock = await queryRunner.query(sql); - + + const stock = await queryRunner.query(sql); + // return await queryRunner.manager // .getRepository(Stock) // .createQueryBuilder('esvestoquevenda') @@ -1126,71 +1210,71 @@ export class SalesService { const cacheKey = 'departments'; const lockKey = 'departments_lock'; const lockTimeout = 30; - - try { - const cachedDepartments = await this.redisClient.get(cacheKey); - if (cachedDepartments) { - console.log('Buscando departamentos no Redis'); - return JSON.parse(cachedDepartments); - } - } catch (err) { - console.error('Erro ao acessar o Redis (cache):', err); - } - const lockValue = Date.now() + lockTimeout * 1000 + 1; + + // try { + // const cachedDepartments = await this.redisClient.get(cacheKey); + // if (cachedDepartments) { + // console.log('Buscando departamentos no Redis'); + // return JSON.parse(cachedDepartments); + // } + // } catch (err) { + // console.error('Erro ao acessar o Redis (cache):', err); + // } + const lockValue = Date.now() + lockTimeout * 1000 + 1; const acquiredLock = await this.redisClient.set(lockKey, lockValue, 'NX', 'EX', lockTimeout); - + if (acquiredLock === 'OK') { - const connectionDb = new Connection(connectionOptions); - await connectionDb.connect(); - const queryRunner = connectionDb.createQueryRunner(); - await queryRunner.connect(); - - try { - const departments = await queryRunner.manager - .getRepository(Esvdepartamento) - .createQueryBuilder('Esvdepartamento') - .innerJoinAndSelect('Esvdepartamento.secoes', 'secoes') - .innerJoinAndSelect('secoes.categorias', 'categorias') - .where('"Esvdepartamento".tituloecommerce is not null') - .orderBy('"Esvdepartamento".tituloecommerce, "secoes".tituloecommerce, "categorias".tituloecommerce') - .getMany(); - + const connectionDb = new Connection(connectionOptions); + await connectionDb.connect(); + const queryRunner = connectionDb.createQueryRunner(); + await queryRunner.connect(); + try { - await this.redisClient.set(cacheKey, JSON.stringify(departments), 'EX', 3600); - } catch (cacheErr) { - console.error('Erro ao armazenar dados no Redis:', cacheErr); + const departments = await queryRunner.manager + .getRepository(Esvdepartamento) + .createQueryBuilder('Esvdepartamento') + .innerJoinAndSelect('Esvdepartamento.secoes', 'secoes') + .leftJoinAndSelect('secoes.categorias', 'categorias') + .where('"Esvdepartamento".tituloecommerce is not null') + .orderBy('"Esvdepartamento".tituloecommerce, "secoes".tituloecommerce, "categorias".tituloecommerce') + .getMany(); + + try { + await this.redisClient.set(cacheKey, JSON.stringify(departments), 'EX', 3600); + } catch (cacheErr) { + console.error('Erro ao armazenar dados no Redis:', cacheErr); + } + + return departments; + } catch (dbErr) { + console.error('Erro na consulta ao banco de dados:', dbErr); + throw dbErr; + } finally { + await queryRunner.release(); + await connectionDb.close(); + + // Libera o lock somente se ainda for o proprietário + try { + const currentLockValue = await this.redisClient.get(lockKey); + if (currentLockValue === lockValue.toString()) { + await this.redisClient.del(lockKey); + } + } catch (lockErr) { + console.error('Erro ao liberar o lock do Redis:', lockErr); + } } - - return departments; - } catch (dbErr) { - console.error('Erro na consulta ao banco de dados:', dbErr); - throw dbErr; - } finally { - await queryRunner.release(); - await connectionDb.close(); - - // Libera o lock somente se ainda for o proprietário - try { - const currentLockValue = await this.redisClient.get(lockKey); - if (currentLockValue === lockValue.toString()) { - await this.redisClient.del(lockKey); - } - } catch (lockErr) { - console.error('Erro ao liberar o lock do Redis:', lockErr); - } - } } else { - console.log('Lock não adquirido, aguardando a liberação...'); - await this.sleep(1000); // aguarda 1 segundo - return this.getDepartments(); + console.log('Lock não adquirido, aguardando a liberação...'); + await this.sleep(1000); // aguarda 1 segundo + return this.getDepartments(); } - } - private sleep(ms: number): Promise { + } + private sleep(ms: number): Promise { return new Promise(resolve => setTimeout(resolve, ms)); - } - - - + } + + + async getCategory() { @@ -1217,15 +1301,15 @@ 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)}`; - + const cachedProducts = await this.redisClient.get(cacheKey); if (cachedProducts) { console.log('Retornando produtos do cache'); return JSON.parse(cachedProducts); } - + const sql = 'SELECT esvlistaprodutos.CODPROD "idProduct" ' + ` ,esvlistaprodutos.SEQ "seq" ` + ' ,esvlistaprodutos.DESCRICAO "smallDescription" ' + @@ -1265,9 +1349,11 @@ export class SalesService { ' ,esvlistaprodutos.LINHATINTOMETRICO "line" ' + ' ,esvlistaprodutos.LITRAGEM "can" ' + ' ,esvlistaprodutos.QUANTIDADE_ESTOQUE_GERAL "full_stock" ' + + ' ,esvlistaprodutos.TEM_PRODUTO_SIMILAR "similar" ' + + ' ,esvlistaprodutos.TIPO_CAMPANHA "type_campaing" ' + ' FROM esvlistaprodutos ' + - ' WHERE 1 = 1'; - + ' WHERE 1 = 1 '; + let where = ""; if (filter.text != null) { where += ` AND ( ESF_REMOVE_ACENTUACAO(UPPER(esvlistaprodutos.descricao)) LIKE ` + @@ -1287,7 +1373,7 @@ export class SalesService { 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 (filter.storeStock == '' || filter.storeStock == null) { where += ` AND EXISTS( SELECT P.CODPROD FROM ESVLISTAPRODUTOS P ` + @@ -1299,15 +1385,15 @@ export class SalesService { ` AND P.ESTOQUE_DISP_LOJA > 0 ) `; } } - + if (filter.percentOffMin > 0) { where += ` AND esvlistaprodutos.PERCENTUALDESCONTO >= ${filter.percentOffMin}`; } - + if (filter.percentOffMax > 0) { where += ` AND esvlistaprodutos.PERCENTUALDESCONTO <= ${filter.percentOffMax}`; } - + let xbrands = ''; if (filter && filter.brands && filter.brands.length > 0) { const brands = filter.brands; @@ -1320,24 +1406,24 @@ export class SalesService { }); where += ` AND esvlistaprodutos.nomemarca in ( ${xbrands} )`; } - + const orderBy = `ORDER BY esvlistaprodutos.${(filter.orderBy == null) ? 'DESCRICAO' : filter.orderBy}`; - + const skipReg = ((pageNumber - 1) * pageSize); const pagination = ` OFFSET ${skipReg} ROWS FETCH NEXT ${pageSize} ROWS ONLY`; - + const connectionDb = new Connection(connectionOptions); await connectionDb.connect(); const queryRunner = connectionDb.createQueryRunner(); await queryRunner.connect(); - + try { let products = await queryRunner.manager.query(sql + where + orderBy + pagination) as SalesProduct[]; products = this.createListImages(products); console.log("Total de produtos: " + products.length); - + await this.redisClient.set(cacheKey, JSON.stringify(products), 'EX', 3600); - + return products; } catch (err) { console.log(err); @@ -1347,7 +1433,7 @@ export class SalesService { await connectionDb.close(); } } - + async calculateDeliveryTax(cartId: string, ibgeCode: string) { @@ -1402,7 +1488,7 @@ export class SalesService { WHERE ID = '${cartId}'`; await queryRunner.manager - .query(sql); + .query(sql); await queryRunner.commitTransaction(); } catch (err) { await queryRunner.rollbackTransaction(); @@ -1457,26 +1543,26 @@ export class SalesService { await queryRunner.release(); await connectionDb.close(); } - + } - + async getPlacesInterior() { const connectionDb = new Connection(connectionOptions); await connectionDb.connect(); const queryRunner = connectionDb.createQueryRunner(); await queryRunner.connect(); - + try { const sql = ` SELECT DISTINCT ESTPREVENTREGAPRACA.CODPRACA, PCPRACA.PRACA FROM ESTPREVENTREGAPRACA, PCPRACA WHERE ESTPREVENTREGAPRACA.CODPRACA = PCPRACA.CODPRACA `; - + const places = await queryRunner.query(sql); - - + + return places; } catch (err) { throw err; @@ -1485,7 +1571,7 @@ export class SalesService { await connectionDb.close(); } } - + async getDeliveryTime(saleDate: string, invoiceStoreId: string, placeId: string, cartId: string) { const connection = new Connection(connectionOptions); @@ -1494,7 +1580,7 @@ export class SalesService { await queryRunner.connect(); try { const sql = `SELECT ESF_CALCULAR_PRAZO_ENTREGA_PROGRAMADA(TO_DATE('${saleDate}', 'DD-MM-YYYY'), ${invoiceStoreId}, ${placeId}, '${cartId}') AS "days" FROM DUAL`; - // const sql = `SELECT ESF_CALCULAR_PRAZO_ENTREGA(TO_DATE('${saleDate}', 'DD-MM-YYYY')) AS "days" FROM DUAL`; + // const sql = `SELECT ESF_CALCULAR_PRAZO_ENTREGA(TO_DATE('${saleDate}', 'DD-MM-YYYY')) AS "days" FROM DUAL`; const timeDays = await queryRunner.query(sql); const sqlRetiraPosterior = `SELECT ( PROXIMO_DIA_UTIL(TO_DATE('${saleDate}', 'DD-MM-YYYY'), '4') - TRUNC(SYSDATE) ) AS "days" FROM DUAL`;