Compare commits

63 Commits

Author SHA1 Message Date
Luis Eduardo Estevao
141e6fd800 Merge branch 'main' of http://172.35.0.216:3000/simplifique/Vendaweb-api
All checks were successful
Build (develop) / Promote (main) / build-and-push-deploy (push) Successful in 1m43s
2026-05-14 12:33:55 -03:00
Luis Eduardo Estevao
936d9d2673 feat: implement optimized product retrieval with Redis caching and locking in SalesService 2026-05-14 12:33:51 -03:00
Gitea Action
7c369a2829 chore: update image tag to 5279ae9 [skip ci] 2026-05-07 17:48:48 +00:00
5279ae95d5 Atualizar k8s/overlays/prod/service-patch.yaml
All checks were successful
Build (develop) / Promote (main) / build-and-push-deploy (push) Successful in 1m15s
2026-05-07 13:47:32 -04:00
Gitea Action
5e04238551 chore: update image tag to 8d52e52 [skip ci] 2026-05-05 17:11:34 +00:00
Luis Eduardo Estevao
8d52e5202a feat: implement Redis caching with locking and optimized product search in SalesService and update compression dependency
All checks were successful
Build (develop) / Promote (main) / build-and-push-deploy (push) Successful in 2m52s
2026-05-05 14:08:34 -03:00
Gitea Action
5c86459157 chore: update image tag to 7535b04 [skip ci] 2026-04-19 21:01:39 +00:00
Luis Eduardo Estevao
7535b0449b feat: implement order creation and management service for web sales integration
Some checks failed
Build (develop) / Promote (main) / build-and-push-deploy (push) Failing after 2m35s
2026-04-19 17:54:03 -03:00
Gitea Action
18e822e949 chore: update image tag to f1c0543 [skip ci] 2026-02-24 23:29:45 +00:00
joelson
f1c0543a0b feat: add prod hpa configuration
All checks were successful
Build (develop) / Promote (main) / build-and-push-deploy (push) Successful in 1m9s
2026-02-24 20:27:05 -03:00
Gitea Action
f67d73d1b8 chore: update image tag to 5a2ea15 [skip ci] 2026-02-20 13:12:41 +00:00
Luis Eduardo Estevao
5a2ea15914 Merge branch 'main' of https://git.simplifiquehc.com.br/simplifique/Vendaweb-api
All checks were successful
Build (develop) / Promote (main) / build-and-push-deploy (push) Successful in 1m11s
2026-02-20 10:06:11 -03:00
Luis Eduardo Estevao
3d4265854f feat: add new service for pre-order creation with transaction management and item processing. 2026-02-20 10:06:06 -03:00
Gitea Action
d010b59066 chore: update image tag to 016c930 [skip ci] 2026-02-19 13:10:26 +00:00
Luis Eduardo Estevao
016c93086c Merge branch 'main' of https://git.simplifiquehc.com.br/simplifique/Vendaweb-api
All checks were successful
Build (develop) / Promote (main) / build-and-push-deploy (push) Successful in 1m13s
2026-02-19 10:05:51 -03:00
Luis Eduardo Estevao
8ae32f3a56 feat: implement customer service with methods for searching and retrieving customer data by name, CPF, or ID. 2026-02-19 10:05:46 -03:00
Gitea Action
35ea219c11 chore: update image tag to 90f2c2e [skip ci] 2026-02-19 13:01:57 +00:00
Luis Eduardo Estevao
90f2c2efee Merge branch 'main' of https://git.simplifiquehc.com.br/simplifique/Vendaweb-api
All checks were successful
Build (develop) / Promote (main) / build-and-push-deploy (push) Successful in 1m19s
2026-02-19 10:00:35 -03:00
Luis Eduardo Estevao
366d6d1f4d feat: Add backoffice list controller and service for various data lookups and new sales customer, order, and pre-order services. Add parameter customerId para find payment plans 2026-02-19 10:00:29 -03:00
Gitea Action
1187693df8 chore: update image tag to 2095866 [skip ci] 2026-02-19 12:05:20 +00:00
Luis Eduardo Estevao
2095866d97 Merge branch 'main' of https://git.simplifiquehc.com.br/simplifique/Vendaweb-api
All checks were successful
Build (develop) / Promote (main) / build-and-push-deploy (push) Successful in 1m19s
2026-02-19 09:03:46 -03:00
Luis Eduardo Estevao
1228970b0d feat: implement SalesService for managing product sales, stock, and related data queries. 2026-02-19 09:03:39 -03:00
Gitea Action
e31226b46a chore: update image tag to 3aa9673 [skip ci] 2026-02-18 16:32:39 +00:00
Luis Eduardo Estevao
3aa967352f Merge branch 'main' of https://git.simplifiquehc.com.br/simplifique/Vendaweb-api
All checks were successful
Build (develop) / Promote (main) / build-and-push-deploy (push) Successful in 1m17s
2026-02-18 13:31:09 -03:00
Luis Eduardo Estevao
175a1b9ccd feat: add ShippingService with methods for retrieving customer shippings, shop collections, customer collections, and delivery schedules. 2026-02-18 13:31:03 -03:00
Gitea Action
5665c4e71d chore: update image tag to c088c38 [skip ci] 2026-02-12 21:10:06 +00:00
c088c38a05 chore: update registry and repository URLs to use internal IP address
All checks were successful
Build (develop) / Promote (main) / build-and-push-deploy (push) Successful in 1m38s
2026-02-12 18:08:05 -03:00
d6d70400ac Merge branch 'main' of http://172.35.0.216:3000/simplifique/Vendaweb-api
Some checks failed
Build (develop) / Promote (main) / build-and-push-deploy (push) Has been cancelled
2026-02-12 18:00:14 -03:00
599a916257 fix: update health check status message to reflect new version 2026-02-12 17:36:55 -03:00
Gitea Action
fa7f05e47b chore: update image tag to e2a36da [skip ci] 2026-02-12 20:34:35 +00:00
Luis Eduardo Estevao
e2a36da1b8 Merge branch 'main' of https://git.simplifiquehc.com.br/simplifique/Vendaweb-api
All checks were successful
Build (develop) / Promote (main) / build-and-push-deploy (push) Successful in 1m22s
2026-02-12 12:59:14 -03:00
Luis Eduardo Estevao
7785f0d0b0 feat: implement sales service with product retrieval and filtering capabilities 2026-02-12 12:59:08 -03:00
Gitea Action
caba86fe3a chore: update image tag to 03519ae [skip ci] 2026-02-11 18:35:37 +00:00
Luis Eduardo Estevao
03519ae299 Merge branch 'main' of https://git.simplifiquehc.com.br/simplifique/Vendaweb-api
All checks were successful
Build (develop) / Promote (main) / build-and-push-deploy (push) Successful in 1m24s
2026-02-11 15:28:13 -03:00
Luis Eduardo Estevao
33f0271a0e feat: implement order creation and cancellation functionality with new entities for city, sales order items, and temporary order items. 2026-02-11 15:28:05 -03:00
Gitea Action
bd47e51262 chore: update image tag to f0ef3dd [skip ci] 2026-02-11 13:52:19 +00:00
Luis Eduardo Estevao
f0ef3dd21c feat: Add new sales and shopping cart management module.
All checks were successful
Build (develop) / Promote (main) / build-and-push-deploy (push) Successful in 1m45s
2026-02-11 10:49:17 -03:00
Gitea Action
f2b2572a35 chore: update image tag to e5dc346 [skip ci] 2026-01-29 23:02:51 +00:00
e5dc346b96 fix: persist shipping fee and refresh k8s docs
All checks were successful
Build (develop) / Promote (main) / build-and-push-deploy (push) Successful in 1m14s
2026-01-29 19:54:47 -03:00
Gitea Action
16882046cf chore: update image tag to fd17be5 [skip ci] 2026-01-29 18:23:08 +00:00
fd17be5408 fix: harden GitOps deploy and rollback
All checks were successful
Build (develop) / Promote (main) / build-and-push-deploy (push) Successful in 1m22s
2026-01-29 15:21:09 -03:00
Gitea Action
ecd298442b chore: update image tag to 589fa29 [skip ci] 2026-01-29 17:59:46 +00:00
589fa2913c fix: correct pipeline to update k8s manifest
All checks were successful
Build (develop) / Promote (main) / build-and-push-deploy (push) Successful in 1m21s
2026-01-29 14:58:20 -03:00
587d097d9b ci: restrict workflow triggers to main branch only
Some checks failed
Build (develop) / Promote (main) / build-and-push-deploy (push) Failing after 1m15s
2026-01-29 14:52:27 -03:00
a694af97c6 feat: add app controller with version and health check endpoints
All checks were successful
Build (develop) / Promote (main) / build-and-push-deploy (push) Successful in 1m33s
2026-01-29 14:48:57 -03:00
6523c5f520 feat: Add API endpoints for application version and health checks.
All checks were successful
Build (develop) / Promote (main) / build-and-push-deploy (push) Successful in 1m21s
2026-01-29 14:31:33 -03:00
0c09ee795e feat: migrate registry to gitea and simplify workflow
All checks were successful
Build (develop) / Promote (main) / build-and-push-deploy (push) Successful in 1m24s
2026-01-29 14:23:24 -03:00
09396e334d feat: migrate registry to gitea and simplify workflow
All checks were successful
Build (develop) / Promote (main) / build-and-push-deploy (push) Successful in 1m25s
2026-01-29 14:20:09 -03:00
605d68b4b0 feat: migrate registry to gitea and simplify workflow
All checks were successful
Build (develop) / Promote (main) / build-and-push-deploy (push) Successful in 7m16s
2026-01-29 14:06:35 -03:00
c707d4a065 feat: migrate registry to gitea and simplify workflow
Some checks failed
Build (develop) / Promote (main) / build-and-push-deploy (push) Has been cancelled
2026-01-29 13:50:01 -03:00
0b28379145 feat: migrate registry to gitea and simplify workflow
Some checks failed
Build (develop) / Promote (main) / build-and-push-deploy (push) Failing after 6s
2026-01-29 13:47:26 -03:00
ca43de8756 fix: use harbor domain instead of ip to fix ssl error
Some checks failed
Build (develop) / Promote (main) / build-and-push-deploy (push) Failing after 20s
2026-01-29 13:31:20 -03:00
bb21ca33e4 fix: update registry url to oci.simplifiquehc.com.br
Some checks failed
Build (develop) / Promote (main) / build-and-push-deploy (push) Failing after 22s
2026-01-29 13:26:13 -03:00
48d6e64ada fix: update registry url to oci.simplifiquehc.com.br
Some checks failed
Build (develop) / Promote (main) / build-and-push-deploy (push) Failing after 24s
2026-01-29 13:24:58 -03:00
e0731db836 fix: update registry url to oci.simplifiquehc.com.br
Some checks failed
Build (develop) / Promote (main) / build-and-push-deploy (push) Failing after 34s
2026-01-29 13:17:15 -03:00
d2265390bd chore: organize project and update service
Some checks failed
Build (develop) / Promote (main) / build-and-push-deploy (push) Failing after 23s
2026-01-29 12:55:15 -03:00
a34c7c415c fix: update workflow to support homolog branch
Some checks failed
Build (develop) / Promote (main) / build-and-push-deploy (push) Failing after 25s
2026-01-29 12:50:47 -03:00
4975d5547d chore: organize project and update service
Some checks failed
Build (develop) / Promote (main) / build-and-push-deploy (push) Failing after 24s
2026-01-29 12:44:11 -03:00
fa6f0e0f49 chore: organize project and update service 2026-01-29 12:43:41 -03:00
c9335a27e5 Merge branch 'docs/k8s-workflow' into homolog 2026-01-29 12:42:01 -03:00
1270c04a2c Update deploy-api.yaml workflow 2026-01-29 02:17:39 -03:00
Luis Eduardo Estevao
ca892daffa feat: implement SalesService for product retrieval, filtering, pagination, and caching.
All checks were successful
Deploy NestJS API / build-and-push-deploy (push) Successful in 2m9s
2026-01-26 06:36:09 -03:00
8e09813741 Atualizar src/main.ts
All checks were successful
Deploy NestJS API / build-and-push-deploy (push) Successful in 2m18s
2026-01-20 18:17:02 -05:00
28 changed files with 924 additions and 744 deletions

View File

@@ -1,23 +1,41 @@
name: Deploy NestJS API name: Build (develop) / Promote (main)
on: [push] on:
push:
branches: [main]
jobs: jobs:
build-and-push-deploy: build-and-push-deploy:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Login no Harbor - name: Build and Push
run: | run: |
echo "${{ secrets.HARBOR_PASSWORD }}" | docker login 172.35.0.216 -u ${{ secrets.HARBOR_USERNAME }} --password-stdin REGISTRY="172.35.0.216:3000"
IMAGE_NAME="$REGISTRY/simplifique/vendaweb-api"
SHA_TAG=$(echo ${{ gitea.sha }} | cut -c1-7)
- name: Build e Push echo "${{ secrets.K8S }}" | docker login "$REGISTRY" -u "${{ gitea.actor }}" --password-stdin
docker build -t "$IMAGE_NAME:$SHA_TAG" -t "$IMAGE_NAME:latest" .
docker push "$IMAGE_NAME:$SHA_TAG"
docker push "$IMAGE_NAME:latest"
- name: Update Manifest and Push to Git
run: | run: |
TAG=${{ gitea.sha }} SHA_TAG=$(echo ${{ gitea.sha }} | cut -c1-7)
docker build -t 172.35.0.216/library/vendaweb-api:$TAG . IMAGE_NAME="172.35.0.216:3000/simplifique/vendaweb-api"
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 MANIFEST_FILE="k8s/overlays/prod/deployment-image-digest-patch.yaml"
docker push 172.35.0.216/library/vendaweb-api:latest
sed -i "s|image: $IMAGE_NAME:.*|image: $IMAGE_NAME:$SHA_TAG|g" "$MANIFEST_FILE"
git config user.name "Gitea Action"
git config user.email "actions@simplifiquehc.com.br"
git add "$MANIFEST_FILE"
git commit -m "chore: update image tag to $SHA_TAG [skip ci]"
git push origin main

View File

@@ -1,39 +1,55 @@
# Estágio 1: Build ARG NODE_VERSION=16.20
FROM node:16-bullseye-slim AS builder ARG DEBIAN_VARIANT=bullseye
FROM node:${NODE_VERSION}-${DEBIAN_VARIANT} AS builder
WORKDIR /app WORKDIR /app
COPY package*.json ./
RUN npm install --legacy-peer-deps
COPY . .
RUN npm run build
FROM node:16-bullseye-slim ARG INSTANTCLIENT_ZIP_URL=https://download.oracle.com/otn_software/linux/instantclient/instantclient-basiclite-linuxx64.zip
# Instalar dependências do Oracle RUN apt-get update \
RUN apt-get update && apt-get install -y \ && apt-get install -y --no-install-recommends ca-certificates wget unzip libaio1 libnsl2 \
libaio1 \ && rm -rf /var/lib/apt/lists/* \
unzip \ && mkdir -p /opt/oracle \
wget \ && wget -q "${INSTANTCLIENT_ZIP_URL}" -O /opt/oracle/instantclient.zip \
&& mkdir -p /opt/oracle && unzip -q /opt/oracle/instantclient.zip -d /opt/oracle \
&& rm /opt/oracle/instantclient.zip \
&& rm -f /opt/oracle/instantclient_*/ojdbc*.jar \
/opt/oracle/instantclient_*/ucp*.jar \
/opt/oracle/instantclient_*/xstreams.jar \
/opt/oracle/instantclient_*/adrci \
/opt/oracle/instantclient_*/genezi \
/opt/oracle/instantclient_*/uidrvci \
&& ln -s "$(ls -d /opt/oracle/instantclient_* | head -n 1)" /opt/oracle/instantclient
# 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 ENV LD_LIBRARY_PATH=/opt/oracle/instantclient
RUN echo "/opt/oracle/instantclient" > /etc/ld.so.conf.d/oracle-instantclient.conf && ldconfig ENV PATH=/opt/oracle/instantclient:$PATH
COPY package*.json ./
ENV NPM_CONFIG_LEGACY_PEER_DEPS=true
RUN npm ci
COPY . .
RUN npm run build \
&& npm prune --omit=dev --legacy-peer-deps \
&& npm cache clean --force
FROM node:${NODE_VERSION}-${DEBIAN_VARIANT}-slim AS runtime
WORKDIR /app WORKDIR /app
# Copiar apenas o necessário do estágio anterior ENV NODE_ENV=production
COPY --from=builder /app/dist ./dist ENV LD_LIBRARY_PATH=/opt/oracle/instantclient
ENV PATH=/opt/oracle/instantclient:$PATH
RUN apt-get update \
&& apt-get install -y --no-install-recommends libaio1 libnsl2 \
&& rm -rf /var/lib/apt/lists/*
COPY --from=builder /opt/oracle /opt/oracle
COPY --from=builder /app/package*.json ./ COPY --from=builder /app/package*.json ./
COPY --from=builder /app/node_modules ./node_modules COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
# Variáveis de ambiente padrão para o driver oracledb EXPOSE 8065
ENV OCI_LIB_DIR=/opt/oracle/instantclient
ENV OCI_INC_DIR=/opt/oracle/instantclient/sdk/include
CMD ["npm", "run", "start:prod"] CMD ["node", "dist/main"]

View File

@@ -1,76 +0,0 @@
# Documentação do Kubernetes
Este documento descreve a infraestrutura e configuração do Kubernetes para o projeto **Vendaweb-api**, utilizando uma abordagem GitOps com ArgoCD e Kustomize.
## Estrutura de Diretórios e Arquivos
A configuração do Kubernetes está localizada no diretório `k8s/` e segue uma estrutura organizada para facilitar a manutenção e escalabilidade:
```
k8s/
├── argocd/ # Configurações do ArgoCD
│ └── application-prod.yaml # Definição da Application para o ambiente de produção
├── base/ # Recursos base do Kubernetes (Kustomize Base)
│ ├── configmap.yaml # ConfigMap base
│ ├── deployment.yaml # Deployment base da aplicação
│ ├── kustomization.yaml # Arquivo principal do Kustomize Base
│ ├── secret.yaml # Secret base
│ └── service.yaml # Service base
└── overlays/ # Sobrescritas para diferentes ambientes (Kustomize Overlays)
└── prod/ # Ambiente de produção
├── application-prod.yaml
├── deployment-image-digest-patch.yaml
├── kustomization.yaml
└── service-patch.yaml
```
## Recursos Base (`k8s/base`)
O diretório `base` contém as definições padrão dos recursos que são comuns a todos os ambientes.
### Deployment (`deployment.yaml`)
- **Nome**: `vendaweb-api`
- **Replicas**: 15 (Configuração base)
- **Imagem**: `172.35.0.216/library/vendaweb-api:latest`
- **Porta do Container**: 8065
- **Resources**:
- Requests: CPU 100m, Memory 256Mi
- Limits: CPU 500m, Memory 512Mi
- **Probes**: Liveness, Readiness e Startup probes configurados no endpoint `/v1/health`.
- **Environment**: Configurações carregadas via ConfigMap e Secret.
### Service (`service.yaml`)
- **Tipo**: ClusterIP
- **Porta**: 8065 (TCP)
## Ambientes (`k8s/overlays`)
### Produção (`k8s/overlays/prod`)
A sobreposição de produção personaliza a configuração base para o ambiente produtivo.
- **Namespace**: `vendaweb-prod`
- **Patches**: Aplica modificações específicas (ex: digest da imagem, configurações específicas de serviço) via `kustomization.yaml`.
## Deploy com ArgoCD (`k8s/argocd`)
O deploy é gerenciado pelo ArgoCD, que sincroniza o estado do cluster com o repositório Git.
### Application (`application-prod.yaml`)
- **Nome**: `vendaweb-api-prod`
- **Namespace do ArgoCD**: `argocd`
- **Origem (Source)**:
- Repositório: `https://git.simplifiquehc.com.br/simplifique/Vendaweb-api.git`
- Revisão: `main`
- Path: `k8s/overlays/prod` (Aponta para o overlay de produção)
- **Destino (Destination)**:
- Cluster: `https://kubernetes.default.svc`
- Namespace: `vendaweb-api` (Nota: O patch define `vendaweb-prod`, verifique a consistência)
- **Sync Policy**: Automatizado com `selfHeal` ativado e criação automática de namespace.
---
**Observação**: Certifique-se de que as credenciais do Harbor (`imagePullSecrets`) estejam corretamente configuradas no namespace de destino para permitir o pull da imagem.

View File

@@ -14,7 +14,7 @@ Os workflows estão definidos no diretório `.gitea/workflows/`. O principal wor
Este workflow é acionado automaticamente no evento: Este workflow é acionado automaticamente no evento:
- `push`: Em qualquer branch (configuração atual `on: [push]`). - `push`: Na branch `main`.
### Jobs ### Jobs
@@ -39,10 +39,13 @@ Este job é responsável por construir a imagem Docker e enviá-la para o regist
3. **Build e Push** 3. **Build e Push**
- Constrói a imagem Docker da aplicação. - Constrói a imagem Docker da aplicação.
- Tags geradas: - Tags geradas:
- `172.35.0.216/library/vendaweb-api:$TAG` (onde `$TAG` é o SHA do commit do Gitea `gitea.sha`) - `git.simplifiquehc.com.br/simplifique/vendaweb-api:$TAG` (onde `$TAG` é o SHA curto do commit)
- `172.35.0.216/library/vendaweb-api:latest` - `git.simplifiquehc.com.br/simplifique/vendaweb-api:latest`
- Envia ambas as tags para o registry. - Envia ambas as tags para o registry.
4. **Atualizar Manifest e Push no Git**
- Atualiza `k8s/overlays/prod/deployment-image-digest-patch.yaml` para apontar para a tag `$TAG`.
## Variáveis e Segredos (Secrets) ## Variáveis e Segredos (Secrets)
Para que o workflow funcione corretamente, as seguintes secrets devem estar configuradas nas configurações do repositório no Gitea: Para que o workflow funcione corretamente, as seguintes secrets devem estar configuradas nas configurações do repositório no Gitea:

156
k8s/README.md Normal file
View File

@@ -0,0 +1,156 @@
# Kubernetes Infra (k8s) - vendaweb-api
Este diretorio contem os manifests Kubernetes do `vendaweb-api` usando Kustomize (base + overlays).
## Visao geral
- App: `vendaweb-api` (Deployment + Service)
- Porta HTTP do container/Service: `8067`
- Healthcheck usado pelos probes: `GET /v1/health`
- Config via `ConfigMap` + `Secret` (injetados com `envFrom`)
- Overlay prod:
- Namespace: `vendaweb-prod`
- Service: `NodePort` (porta externa `30001`)
- Replicas: `15`
## Estrutura
- `k8s/base/`
- `deployment.yaml`: deployment padrao (replicas 3), porta 8067, probes `/v1/health`, `imagePullSecrets: gitea-auth`
- `service.yaml`: `ClusterIP` expondo 8067
- `configmap.yaml`: variaveis nao sensiveis (ex.: Redis/DB host/port)
- `secret.yaml`: variaveis sensiveis (ex.: usuario/senha do DB)
- `kustomization.yaml`: agrega os recursos do base
- `k8s/overlays/prod/`
- `kustomization.yaml`: aplica patches e define `namespace: vendaweb-prod`
- `service-patch.yaml`: muda Service para `NodePort` e fixa `nodePort: 30001`
- `deployment-prod-patch.yaml`: ajusta `replicas: 15`
- `deployment-image-digest-patch.yaml`: sobrescreve a `image:` do container
- `k8s/argocd/application-prod.yaml`
- Aplica o overlay `k8s/overlays/prod` via Argo CD
- Sync automatizado com `selfHeal` e `prune`
## Portas e acesso
- Dentro do cluster: Service `vendaweb-api:8067`
- Overlay prod (NodePort): porta externa `30001` (mapeia para `8067`)
Notas:
- O processo Node/Nest escuta em `8067` (ver `src/main.ts`).
- A variavel `PORT` em `.env` nao e usada pelo bootstrap atual; o k8s esta configurado para 8067.
## Deploy com kubectl/kustomize
Gerar o YAML final (sem aplicar):
```bash
kubectl kustomize k8s/overlays/prod
```
Aplicar o overlay prod:
```bash
kubectl apply -k k8s/overlays/prod
```
Validar o que sera aplicado (dry-run):
```bash
kubectl apply -k k8s/overlays/prod --dry-run=server
```
Ver diffs (se seu kubectl suportar):
```bash
kubectl diff -k k8s/overlays/prod
```
## Argo CD (prod)
O Argo CD esta configurado em `k8s/argocd/application-prod.yaml` para:
- `path: k8s/overlays/prod`
- `targetRevision: main`
- `destination.namespace: vendaweb-prod` (com `CreateNamespace=true`)
Se voce esta usando Argo CD, o fluxo recomendado e:
- atualizar manifests no Git (overlay prod)
- deixar o Argo CD sincronizar automaticamente
## Configuracao (ConfigMap/Secret)
- `k8s/base/configmap.yaml` (`vendaweb-api-config`)
- `REDIS_HOST`, `REDIS_PORT`, `DB_HOST`, `DB_PORT`, `DB_SERVICE_NAME`
- `k8s/base/secret.yaml` (`vendaweb-api-secrets`)
- `DB_USERNAME`, `DB_PASSWORD`
Importante:
- O `Secret` esta em `stringData` no repositorio (texto puro). Para ambiente real, prefira um gerenciador de segredos (ExternalSecrets, SOPS, Vault etc.) e nao commite credenciais.
## Imagem e pipeline
O workflow `.gitea/workflows/deploy-api.yaml`:
- builda e publica `git.simplifiquehc.com.br/simplifique/vendaweb-api:<sha7>` e `:latest`
- atualiza `k8s/overlays/prod/deployment-image-digest-patch.yaml` para apontar para o tag do commit
Isso e pensado para o Argo CD detectar a alteracao no Git e aplicar.
## Comandos uteis (day-2)
Assumindo namespace `vendaweb-prod`:
```bash
kubectl -n vendaweb-prod get all
kubectl -n vendaweb-prod get pods -l app=vendaweb-api -o wide
kubectl -n vendaweb-prod describe deploy/vendaweb-api
kubectl -n vendaweb-prod describe pod -l app=vendaweb-api
```
Logs:
```bash
kubectl -n vendaweb-prod logs deploy/vendaweb-api --tail=200
kubectl -n vendaweb-prod logs -l app=vendaweb-api --tail=200 --all-containers
kubectl -n vendaweb-prod logs -l app=vendaweb-api -f
```
Rollout:
```bash
kubectl -n vendaweb-prod rollout status deploy/vendaweb-api
kubectl -n vendaweb-prod rollout history deploy/vendaweb-api
kubectl -n vendaweb-prod rollout restart deploy/vendaweb-api
```
Exec/Debug:
```bash
kubectl -n vendaweb-prod exec -it deploy/vendaweb-api -- sh
kubectl -n vendaweb-prod port-forward svc/vendaweb-api 8067:8067
```
## Troubleshooting rapido
- `ImagePullBackOff`:
- conferir `imagePullSecrets: gitea-auth` no namespace (`kubectl -n vendaweb-prod get secret gitea-auth`)
- conferir o valor de `image:` no overlay prod
- `CrashLoopBackOff`:
- ver logs do pod e eventos (`kubectl -n vendaweb-prod describe pod ...`)
- validar variaveis do `ConfigMap`/`Secret`
- Probes falhando:
- garantir que a rota `/v1/health` responde 200 e que a app esta ouvindo em `8067`
## Mudancas comuns
- Alterar porta externa (NodePort): `k8s/overlays/prod/service-patch.yaml`
- Alterar replicas em prod: `k8s/overlays/prod/deployment-prod-patch.yaml`
- Alterar imagem/tag em prod: `k8s/overlays/prod/deployment-image-digest-patch.yaml`
- Alterar envs: `k8s/base/configmap.yaml` e `k8s/base/secret.yaml`

View File

@@ -6,14 +6,22 @@ metadata:
spec: spec:
project: default project: default
source: source:
repoURL: https://git.simplifiquehc.com.br/simplifique/Vendaweb-api.git repoURL: http://172.35.0.216:3000/simplifique/Vendaweb-api.git
targetRevision: main targetRevision: main
path: k8s/overlays/prod path: k8s/overlays/prod
destination: destination:
server: https://kubernetes.default.svc server: https://kubernetes.default.svc
namespace: vendaweb-api namespace: vendaweb-prod
syncPolicy: syncPolicy:
automated: automated:
selfHeal: true selfHeal: true
prune: true
retry:
limit: 2
backoff:
duration: 5s
factor: 2
maxDuration: 3m
syncOptions: syncOptions:
- CreateNamespace=true - CreateNamespace=true
- PruneLast=true

View File

@@ -5,7 +5,15 @@ metadata:
labels: labels:
app: vendaweb-api app: vendaweb-api
spec: spec:
replicas: 15 replicas: 3
revisionHistoryLimit: 5
minReadySeconds: 10
progressDeadlineSeconds: 600
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector: selector:
matchLabels: matchLabels:
app: vendaweb-api app: vendaweb-api
@@ -15,10 +23,11 @@ spec:
app: vendaweb-api app: vendaweb-api
spec: spec:
imagePullSecrets: imagePullSecrets:
- name: harbor-secret - name: gitea-auth
terminationGracePeriodSeconds: 30
containers: containers:
- name: api - name: api
image: 172.35.0.216/library/vendaweb-api:latest image: 172.35.0.216:3000/simplifique/vendaweb-api:589fa29
imagePullPolicy: IfNotPresent imagePullPolicy: IfNotPresent
ports: ports:
- name: http - name: http

View File

@@ -7,4 +7,4 @@ spec:
spec: spec:
containers: containers:
- name: api - name: api
image: 172.35.0.216/library/vendaweb-api@sha256:aac490fcb4ef7baa95f1df01fa50d2d44bdb4ed12b235e5dd89e1d7dc3cd0a3a image: 172.35.0.216:3000/simplifique/vendaweb-api:5279ae9

View File

@@ -0,0 +1,6 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: vendaweb-api
spec:
replicas: 2

View File

@@ -0,0 +1,18 @@
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: vendaweb-api
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: vendaweb-api
minReplicas: 2
maxReplicas: 15
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70

View File

@@ -5,7 +5,9 @@ namespace: vendaweb-prod
resources: resources:
- ../../base - ../../base
- hpa.yaml
patches: patches:
- path: deployment-image-digest-patch.yaml
- path: service-patch.yaml - path: service-patch.yaml
- path: deployment-prod-patch.yaml
- path: deployment-image-digest-patch.yaml

View File

@@ -8,4 +8,4 @@ spec:
- name: http - name: http
port: 8067 port: 8067
targetPort: 8067 targetPort: 8067
nodePort: 30001 nodePort: 32619

45
package-lock.json generated
View File

@@ -20,7 +20,7 @@
"@types/cache-manager": "^3.4.3", "@types/cache-manager": "^3.4.3",
"cache-manager": "^3.6.3", "cache-manager": "^3.6.3",
"cache-manager-redis-store": "^3.0.1", "cache-manager-redis-store": "^3.0.1",
"compression": "^1.7.4", "compression": "^1.8.1",
"crc": "^4.3.2", "crc": "^4.3.2",
"fs": "0.0.1-security", "fs": "0.0.1-security",
"guid-typescript": "^1.0.9", "guid-typescript": "^1.0.9",
@@ -4181,16 +4181,17 @@
} }
}, },
"node_modules/compression": { "node_modules/compression": {
"version": "1.7.4", "version": "1.8.1",
"resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz",
"integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==",
"license": "MIT",
"dependencies": { "dependencies": {
"accepts": "~1.3.5", "bytes": "3.1.2",
"bytes": "3.0.0", "compressible": "~2.0.18",
"compressible": "~2.0.16",
"debug": "2.6.9", "debug": "2.6.9",
"on-headers": "~1.0.2", "negotiator": "~0.6.4",
"safe-buffer": "5.1.2", "on-headers": "~1.1.0",
"safe-buffer": "5.2.1",
"vary": "~1.1.2" "vary": "~1.1.2"
}, },
"engines": { "engines": {
@@ -4198,17 +4199,22 @@
} }
}, },
"node_modules/compression/node_modules/bytes": { "node_modules/compression/node_modules/bytes": {
"version": "3.0.0", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
"integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
"license": "MIT",
"engines": { "engines": {
"node": ">= 0.8" "node": ">= 0.8"
} }
}, },
"node_modules/compression/node_modules/safe-buffer": { "node_modules/compression/node_modules/negotiator": {
"version": "5.1.2", "version": "0.6.4",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
}, },
"node_modules/concat-map": { "node_modules/concat-map": {
"version": "0.0.1", "version": "0.0.1",
@@ -9810,9 +9816,10 @@
} }
}, },
"node_modules/on-headers": { "node_modules/on-headers": {
"version": "1.0.2", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz",
"integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==",
"license": "MIT",
"engines": { "engines": {
"node": ">= 0.8" "node": ">= 0.8"
} }

View File

@@ -32,7 +32,7 @@
"@types/cache-manager": "^3.4.3", "@types/cache-manager": "^3.4.3",
"cache-manager": "^3.6.3", "cache-manager": "^3.6.3",
"cache-manager-redis-store": "^3.0.1", "cache-manager-redis-store": "^3.0.1",
"compression": "^1.7.4", "compression": "^1.8.1",
"crc": "^4.3.2", "crc": "^4.3.2",
"fs": "0.0.1-security", "fs": "0.0.1-security",
"guid-typescript": "^1.0.9", "guid-typescript": "^1.0.9",

View File

@@ -14,7 +14,7 @@ export class AppController {
@Get('health') @Get('health')
@ApiOperation({ summary: 'Health check' }) @ApiOperation({ summary: 'Health check' })
healthCheck() { healthCheck() {
return { status: 'SIMPLIFIQUE HOME CENTER 2026' }; return { status: 'NOVA VERSAO 2026' };
} }
} }

View File

@@ -28,7 +28,7 @@ export class ListsController {
* Consulta tabela de checkouts da filial informada * Consulta tabela de checkouts da filial informada
*/ */
@Get('checkout/:store') @Get('checkout/:store')
@ApiParam({name: 'Código da filial',}) @ApiParam({ name: 'Código da filial', })
async getCheckout(@Param('store') idStore: string) { async getCheckout(@Param('store') idStore: string) {
return this.listsServices.GetCheckout(idStore); return this.listsServices.GetCheckout(idStore);
} }
@@ -44,9 +44,9 @@ export class ListsController {
/** /**
* Consulta tabela de plano de pagamento para pedido de venda * Consulta tabela de plano de pagamento para pedido de venda
*/ */
@Get('paymentplan/:billindid') @Get('paymentplan/:billindid/:customerId')
async getPaymentPlan(@Param('billindid') billingId: string) { async getPaymentPlan(@Param('billindid') billingId: string, @Param('customerId') customerId: string) {
return this.listsServices.GetPaymentPlan(billingId); return this.listsServices.GetPaymentPlan(billingId, customerId);
} }
/** /**

View File

@@ -15,11 +15,11 @@ export class ListsService {
await queryRunner.connect(); await queryRunner.connect();
try { try {
const sql = `SELECT PCFILIAL.CODIGO as "id", ` + const sql = `SELECT PCFILIAL.CODIGO as "id", ` +
` PCFILIAL.RAZAOSOCIAL as "name", ` + ` PCFILIAL.RAZAOSOCIAL as "name", ` +
` PCFILIAL.CODIGO|| ' - '|| PCFILIAL.FANTASIA as "shortName" ` + ` PCFILIAL.CODIGO|| ' - '|| PCFILIAL.FANTASIA as "shortName" ` +
` FROM PCFILIAL ` + ` FROM PCFILIAL ` +
` WHERE PCFILIAL.CODIGO <> '99' ` + ` WHERE PCFILIAL.CODIGO <> '99' ` +
` ORDER BY PCFILIAL.CODIGO `; ` ORDER BY PCFILIAL.CODIGO `;
const stores = await queryRunner.query(sql); const stores = await queryRunner.query(sql);
return stores as Store[]; return stores as Store[];
} catch (error) { } catch (error) {
@@ -37,12 +37,12 @@ export class ListsService {
const queryRunner = connection.createQueryRunner(); const queryRunner = connection.createQueryRunner();
await queryRunner.connect(); await queryRunner.connect();
const sql = `SELECT PCFILIAL.CODIGO as "id", ` + const sql = `SELECT PCFILIAL.CODIGO as "id", ` +
` PCFILIAL.RAZAOSOCIAL as "name", ` + ` PCFILIAL.RAZAOSOCIAL as "name", ` +
` PCFILIAL.CODIGO|| ' - '|| PCFILIAL.FANTASIA as "shortName" ` + ` PCFILIAL.CODIGO|| ' - '|| PCFILIAL.FANTASIA as "shortName" ` +
` FROM PCFILIAL `; ` FROM PCFILIAL `;
const whereByUser = " WHERE PCFILIAL.CODIGO <> '99' AND " + const whereByUser = " WHERE PCFILIAL.CODIGO <> '99' AND " +
" ((PCFILIAL.CODIGO IN ( SELECT PCLIB.CODIGOA FROM PCLIB WHERE PCLIB.CODTABELA = 1 AND PCLIB.CODFUNC = :iduser )) OR " + " ((PCFILIAL.CODIGO IN ( SELECT PCLIB.CODIGOA FROM PCLIB WHERE PCLIB.CODTABELA = 1 AND PCLIB.CODFUNC = :iduser )) OR " +
" (EXISTS(SELECT PCLIB.CODIGOA FROM PCLIB WHERE PCLIB.CODTABELA = 1 AND PCLIB.CODFUNC = :iduser AND PCLIB.CODIGOA = '99')) ) "; " (EXISTS(SELECT PCLIB.CODIGOA FROM PCLIB WHERE PCLIB.CODTABELA = 1 AND PCLIB.CODFUNC = :iduser AND PCLIB.CODIGOA = '99')) ) ";
const orderBy = ` ORDER BY PCFILIAL.CODIGO` const orderBy = ` ORDER BY PCFILIAL.CODIGO`
try { try {
@@ -66,7 +66,7 @@ export class ListsService {
const checkouts = await queryRunner.manager const checkouts = await queryRunner.manager
.getRepository(Checkout) .getRepository(Checkout)
.createQueryBuilder('pccaixa') .createQueryBuilder('pccaixa')
.where("\"pccaixa\".CODFILIAL = :idStore", {idStore: idStore}) .where("\"pccaixa\".CODFILIAL = :idStore", { idStore: idStore })
.orderBy("\"pccaixa\".NUMCAIXA") .orderBy("\"pccaixa\".NUMCAIXA")
.getMany(); .getMany();
return checkouts; return checkouts;
@@ -89,7 +89,7 @@ export class ListsService {
.getRepository(Pcempr) .getRepository(Pcempr)
.createQueryBuilder('pcempr') .createQueryBuilder('pcempr')
.select("\"pcempr\".matricula as \"id\", \"pcempr\".nome as \"name\", \"pcempr\".email as \"email\", \"pcempr\".usuariobd as \"smallName\"") .select("\"pcempr\".matricula as \"id\", \"pcempr\".nome as \"name\", \"pcempr\".email as \"email\", \"pcempr\".usuariobd as \"smallName\"")
.where("\"pcempr\".CODFILIAL = :idStore", {idStore: idStore}) .where("\"pcempr\".CODFILIAL = :idStore", { idStore: idStore })
.orderBy("\"pcempr\".NOME") .orderBy("\"pcempr\".NOME")
.getRawMany(); .getRawMany();
return checkouts; return checkouts;
@@ -102,20 +102,24 @@ export class ListsService {
} }
} }
async GetPaymentPlan(billingId: string){ async GetPaymentPlan(billingId: string, clientId: string) {
const connection = new Connection(connectionOptions); const connection = new Connection(connectionOptions);
await connection.connect(); await connection.connect();
const queryRunner = connection.createQueryRunner(); const queryRunner = connection.createQueryRunner();
await queryRunner.connect(); await queryRunner.connect();
try { try {
const sql = ' SELECT PCPLPAG.CODPLPAG as "codplpag", PCPLPAG.DESCRICAO as "descricao", ' + const sql = `SELECT PCPLPAG.CODPLPAG as "codplpag", PCPLPAG.DESCRICAO as "descricao",
' NVL(PCPLPAG.NUMDIAS,0) as "numdias" ' + NVL(PCPLPAG.NUMDIAS,0) as "numdias"
' FROM PCPLPAG ' + FROM PCPLPAG, PCCLIENT, PCPLPAG PLANO_CLI
' WHERE EXISTS(SELECT PCCOBPLPAG.CODCOB FROM PCCOBPLPAG ' + WHERE PCCLIENT.CODCLI = :CODCLI
' WHERE PCCOBPLPAG.CODPLPAG = PCPLPAG.CODPLPAG ' + AND PCCLIENT.CODPLPAG = PLANO_CLI.CODPLPAG (+)
' AND PCCOBPLPAG.CODCOB = :CODCOB ) ' AND PCPLPAG.NUMDIAS <= NVL(PLANO_CLI.NUMDIAS,9999)
' ORDER BY PCPAG.DESCRICAO '; AND EXISTS(SELECT PCCOBPLPAG.CODCOB FROM PCCOBPLPAG
const paymentPlans = await queryRunner.query(sql, [billingId]); WHERE PCCOBPLPAG.CODPLPAG = PCPLPAG.CODPLPAG
AND PCCOBPLPAG.CODCOB = :CODCOB )
ORDER BY PCPLPAG.DESCRICAO`;
const paymentPlans = await queryRunner.query(sql, [clientId, billingId]);
return paymentPlans; return paymentPlans;
} catch (error) { } catch (error) {
throw error; throw error;
@@ -125,20 +129,20 @@ export class ListsService {
} }
} }
async GetBilling(clienteId: number){ async GetBilling(clienteId: number) {
const connection = new Connection(connectionOptions); const connection = new Connection(connectionOptions);
await connection.connect(); await connection.connect();
const queryRunner = connection.createQueryRunner(); const queryRunner = connection.createQueryRunner();
await queryRunner.connect(); await queryRunner.connect();
try { try {
const sql = ' SELECT PCCOB.CODCOB as "codcob", PCCOB.CODCOB ||\' - \'||PCCOB.COBRANCA as "cobranca" ' + const sql = ' SELECT PCCOB.CODCOB as "codcob", PCCOB.CODCOB ||\' - \'||PCCOB.COBRANCA as "cobranca" ' +
' FROM PCCOB ' + ' FROM PCCOB ' +
' WHERE NVL(PCCOB.enviacobrancafv, \'N\') = \'S\' ' + ' WHERE NVL(PCCOB.enviacobrancafv, \'N\') = \'S\' ' +
' AND ( ( NOT EXISTS(SELECT PCCOBCLI.CODCOB FROM PCCOBCLI WHERE PCCOBCLI.CODCLI = :CODCLI ) AND ' + ' AND ( ( NOT EXISTS(SELECT PCCOBCLI.CODCOB FROM PCCOBCLI WHERE PCCOBCLI.CODCLI = :CODCLI ) AND ' +
' ( PCCOB.NIVELVENDA <= ( SELECT C.NIVELVENDA FROM PCCLIENT, PCCOB C ' + ' ( PCCOB.NIVELVENDA >= ( SELECT C.NIVELVENDA FROM PCCLIENT, PCCOB C ' +
' WHERE PCCLIENT.CODCLI = :CODCLI AND PCCLIENT.CODCOB = C.CODCOB ) ) ) OR ' + ' WHERE PCCLIENT.CODCLI = :CODCLI AND PCCLIENT.CODCOB = C.CODCOB ) ) ) OR ' +
' EXISTS(SELECT PCCOBCLI.CODCOB FROM PCCOBCLI WHERE PCCOBCLI.CODCLI = :CODCLI AND PCCOBCLI.CODCOB = PCCOB.CODCOB ) ) ' + ' EXISTS(SELECT PCCOBCLI.CODCOB FROM PCCOBCLI WHERE PCCOBCLI.CODCLI = :CODCLI AND PCCOBCLI.CODCOB = PCCOB.CODCOB ) ) ' +
' ORDER BY PCCOB.CODCOB'; ' ORDER BY PCCOB.CODCOB';
const billings = await queryRunner.query(sql, [clienteId]); const billings = await queryRunner.query(sql, [clienteId]);
return billings; return billings;
} catch (error) { } catch (error) {
@@ -149,16 +153,16 @@ export class ListsService {
} }
} }
async GetPartners(){ async GetPartners() {
const connection = new Connection(connectionOptions); const connection = new Connection(connectionOptions);
await connection.connect(); await connection.connect();
const queryRunner = connection.createQueryRunner(); const queryRunner = connection.createQueryRunner();
await queryRunner.connect(); await queryRunner.connect();
try { try {
const sql = ' SELECT ESTPARCEIRO.ID as "id" ' + const sql = ' SELECT ESTPARCEIRO.ID as "id" ' +
' ,REGEXP_REPLACE(ESTPARCEIRO.CPF, \'[^0-9]\',\'\') || \' - \' ||ESTPARCEIRO.NOME as "name" ' + ' ,REGEXP_REPLACE(ESTPARCEIRO.CPF, \'[^0-9]\',\'\') || \' - \' ||ESTPARCEIRO.NOME as "name" ' +
' FROM ESTPARCEIRO ' + ' FROM ESTPARCEIRO ' +
' WHERE 1 = 1 '; ' WHERE 1 = 1 ';
const partners = await queryRunner.manager const partners = await queryRunner.manager
.query(sql); .query(sql);
return partners; return partners;
@@ -170,18 +174,18 @@ export class ListsService {
} }
} }
async GetPreCustomer(idCart: string){ async GetPreCustomer(idCart: string) {
const connection = new Connection(connectionOptions); const connection = new Connection(connectionOptions);
await connection.connect(); await connection.connect();
const queryRunner = connection.createQueryRunner(); const queryRunner = connection.createQueryRunner();
await queryRunner.connect(); await queryRunner.connect();
try { try {
const sql = ' select CPF as "document" '+ const sql = ' select CPF as "document" ' +
' ,NOME as "name" ' + ' ,NOME as "name" ' +
' ,TELEFONE as "phone" ' + ' ,TELEFONE as "phone" ' +
' ,IDCART as "idCart" ' + ' ,IDCART as "idCart" ' +
' from estvendaprecliente ' + ' from estvendaprecliente ' +
' where IDCART = :idcart '; ' where IDCART = :idcart ';
console.log(idCart); console.log(idCart);
const preCustomer = await queryRunner const preCustomer = await queryRunner
.query(sql, [idCart]); .query(sql, [idCart]);
@@ -195,16 +199,16 @@ export class ListsService {
} }
} }
async GetPlaces(){ async GetPlaces() {
const connection = new Connection(connectionOptions); const connection = new Connection(connectionOptions);
await connection.connect(); await connection.connect();
const queryRunner = connection.createQueryRunner(); const queryRunner = connection.createQueryRunner();
await queryRunner.connect(); await queryRunner.connect();
try { try {
const sql = ' SELECT PCPRACA.CODPRACA as "id" ' + const sql = ' SELECT PCPRACA.CODPRACA as "id" ' +
' ,PCPRACA.PRACA as "name" ' + ' ,PCPRACA.PRACA as "name" ' +
' FROM PCPRACA ' + ' FROM PCPRACA ' +
' WHERE 1 = 1'; ' WHERE 1 = 1';
const places = await queryRunner.manager const places = await queryRunner.manager
.query(sql); .query(sql);
return places; return places;
@@ -216,16 +220,16 @@ export class ListsService {
} }
} }
async GetStorePlaces(){ async GetStorePlaces() {
const connection = new Connection(connectionOptions); const connection = new Connection(connectionOptions);
await connection.connect(); await connection.connect();
const queryRunner = connection.createQueryRunner(); const queryRunner = connection.createQueryRunner();
await queryRunner.connect(); await queryRunner.connect();
try { try {
const sql = ' SELECT PCPRACA.CODPRACA as "id" ' + const sql = ' SELECT PCPRACA.CODPRACA as "id" ' +
' ,PCPRACA.PRACA as "name" ' + ' ,PCPRACA.PRACA as "name" ' +
' FROM PCPRACA ' + ' FROM PCPRACA ' +
' WHERE PCPRACA.CODPRACAPRINCIPAL = 1004'; ' WHERE PCPRACA.CODPRACAPRINCIPAL = 1004';
const places = await queryRunner.manager const places = await queryRunner.manager
.query(sql); .query(sql);
return places; return places;
@@ -237,17 +241,17 @@ export class ListsService {
} }
} }
async GetRamo(){ async GetRamo() {
const connection = new Connection(connectionOptions); const connection = new Connection(connectionOptions);
await connection.connect(); await connection.connect();
const queryRunner = connection.createQueryRunner(); const queryRunner = connection.createQueryRunner();
await queryRunner.connect(); await queryRunner.connect();
try { try {
const sql = ' SELECT PCATIVI.CODATIV as "id" ' + const sql = ' SELECT PCATIVI.CODATIV as "id" ' +
' ,PCATIVI.RAMO as "name" ' + ' ,PCATIVI.RAMO as "name" ' +
' FROM PCATIVI ' + ' FROM PCATIVI ' +
' WHERE 1 = 1 ' + ' WHERE 1 = 1 ' +
' ORDER BY PCATIVI.RAMO'; ' ORDER BY PCATIVI.RAMO';
const ramos = await queryRunner.manager const ramos = await queryRunner.manager
.query(sql); .query(sql);
return ramos; return ramos;
@@ -259,14 +263,14 @@ export class ListsService {
} }
} }
async GetStates(state: string){ async GetStates(state: string) {
const connection = new Connection(connectionOptions); const connection = new Connection(connectionOptions);
await connection.connect(); await connection.connect();
const queryRunner = connection.createQueryRunner(); const queryRunner = connection.createQueryRunner();
await queryRunner.connect(); await queryRunner.connect();
try { try {
const sql = ' SELECT PCESTADO.ESTADO as "name" FROM PCESTADO' + const sql = ' SELECT PCESTADO.ESTADO as "name" FROM PCESTADO' +
' WHERE PCESTADO.UF = :1'; ' WHERE PCESTADO.UF = :1';
const states = await queryRunner.manager const states = await queryRunner.manager
.query(sql, [state]); .query(sql, [state]);
return states[0].name; return states[0].name;
@@ -278,7 +282,7 @@ export class ListsService {
} }
} }
async getSupervisores(){ async getSupervisores() {
const connection = new Connection(connectionOptions); const connection = new Connection(connectionOptions);
await connection.connect(); await connection.connect();
const queryRunner = connection.createQueryRunner(); const queryRunner = connection.createQueryRunner();
@@ -299,4 +303,4 @@ export class ListsService {
} }
} }
} }

View File

@@ -128,20 +128,20 @@ export class ShippingService {
.getRepository(Esvretiralojascliente) .getRepository(Esvretiralojascliente)
.createQueryBuilder('ESVRETIRALOJASCLIENTE') .createQueryBuilder('ESVRETIRALOJASCLIENTE')
.select([ .select([
'codfilial as "codigoFilial"' 'codfilial as "codigoFilial"'
,'numped as "numeroPedido"' , 'numped as "numeroPedido"'
,'numnota as "numeroNota"' , 'numnota as "numeroNota"'
,'dtfat as "dataFaturamento"' , 'dtfat as "dataFaturamento"'
,'datapedido as "dataPedido"' , 'datapedido as "dataPedido"'
,'codcli as "codigoCliente"' , 'codcli as "codigoCliente"'
,'cliente as "nomeCliente"' , 'cliente as "nomeCliente"'
,'codfilialretira as "codigoLoja"' , 'codfilialretira as "codigoLoja"'
,'razaosocial as "nomeLoja"' , 'razaosocial as "nomeLoja"'
,'qtitens as "quantidadeItens"' , 'qtitens as "quantidadeItens"'
,'quantidade as "quantidade"' , 'quantidade as "quantidade"'
]) ])
.where("email = 'eduardoestevao.gyn@gmail.com'") .where("email = 'eduardoestevao.gyn@gmail.com'")
.andWhere("codfilial = :codfilial", {codfilial: id}) .andWhere("codfilial = :codfilial", { codfilial: id })
.getRawMany(); .getRawMany();
return deliveries; return deliveries;
@@ -169,13 +169,13 @@ export class ShippingService {
const sql = `SELECT PCDIASUTEIS.DATA as "dateDelivery", const sql = `SELECT PCDIASUTEIS.DATA as "dateDelivery",
NVL (PCDIASUTEIS.DIAROTA, 'N') as "delivery", NVL (PCDIASUTEIS.DIAROTA, 'N') as "delivery",
CASE WHEN NVL (PCDIASUTEIS.DIAROTA, 'N') = 'N' THEN 0 CASE WHEN NVL (PCDIASUTEIS.DIAROTA, 'N') = 'N' THEN 0
ELSE (PARAMFILIAL.OBTERCOMONUMBER ('CAPACIDADE_LOGISTICA', 12)) END as "deliverySize", ELSE (PARAMFILIAL.OBTERCOMONUMBER ('CAPACIDADE_LOGISTICA', 1)) END as "deliverySize",
ROUND ( (NVL (VENDAS.TOTPESO, 0) / 1000), 3) as "saleWeigth", ROUND ( (NVL (VENDAS.TOTPESO, 0) / 1000), 3) as "saleWeigth",
CASE WHEN NVL (PCDIASUTEIS.DIAROTA, 'N') = 'N' THEN 0 CASE WHEN NVL (PCDIASUTEIS.DIAROTA, 'N') = 'N' THEN 0
ELSE ROUND ( ELSE ROUND (
GREATEST ( GREATEST (
( ( PARAMFILIAL.OBTERCOMONUMBER ('CAPACIDADE_LOGISTICA', ( ( PARAMFILIAL.OBTERCOMONUMBER ('CAPACIDADE_LOGISTICA',
12) 1)
* 1000) * 1000)
- NVL (VENDAS.TOTPESO, 0)) - NVL (VENDAS.TOTPESO, 0))
/ 1000, / 1000,
@@ -186,7 +186,9 @@ export class ShippingService {
FROM PCPEDC FROM PCPEDC
WHERE PCPEDC.POSICAO IN ('L', 'M') WHERE PCPEDC.POSICAO IN ('L', 'M')
AND PCPEDC.CONDVENDA = 8 AND PCPEDC.CONDVENDA = 8
AND PCPEDC.CODFILIAL IN (12, 13, 4, 6) AND EXISTS(SELECT 1 FROM PCPEDI
WHERE PCPEDI.NUMPED = PCPEDC.NUMPED
AND PCPEDI.CODFILIALRETIRA IN (1) )
AND EXISTS AND EXISTS
(SELECT TV7.NUMPED (SELECT TV7.NUMPED
FROM PCPEDC TV7 FROM PCPEDC TV7
@@ -194,19 +196,19 @@ export class ShippingService {
AND TV7.POSICAO = 'F') AND TV7.POSICAO = 'F')
AND PCPEDC.DTENTREGA >= TRUNC (SYSDATE) + 3 AND PCPEDC.DTENTREGA >= TRUNC (SYSDATE) + 3
GROUP BY PCPEDC.DTENTREGA) VENDAS GROUP BY PCPEDC.DTENTREGA) VENDAS
WHERE PCDIASUTEIS.CODFILIAL = 12 AND PCDIASUTEIS.DATA BETWEEN TRUNC (SYSDATE) + 3 AND TRUNC(SYSDATE) + 20 --AND NVL(PCDIASUTEIS.DIAROTA,'N') = 'S' WHERE PCDIASUTEIS.CODFILIAL = 1 AND PCDIASUTEIS.DATA BETWEEN TRUNC (SYSDATE) + 3 AND TRUNC(SYSDATE) + 20 --AND NVL(PCDIASUTEIS.DIAROTA,'N') = 'S'
AND PCDIASUTEIS.DATA = VENDAS.DTENTREGA(+) AND PCDIASUTEIS.DATA = VENDAS.DTENTREGA(+)
ORDER BY PCDIASUTEIS.DATA `; ORDER BY PCDIASUTEIS.DATA `;
const data = await queryRunner.query(sql); const data = await queryRunner.query(sql);
const sqlDeliveryDate = `SELECT TRUNC(SYSDATE) + esf_calcular_prazo_entrega_programada(TRUNC(SYSDATE), const sqlDeliveryDate = `SELECT TRUNC(SYSDATE) + esf_calcular_prazo_entrega_programada(TRUNC(SYSDATE),
'12', '1',
129, '', 0, 500) as "date" 169, '', 0, 500) as "date"
FROM DUAL`; FROM DUAL`;
const dataDeliveryDate = await queryRunner.query(sqlDeliveryDate); const dataDeliveryDate = await queryRunner.query(sqlDeliveryDate);
const dataComplete = { dateDelivery: dataDeliveryDate[0].date, deliveries: [...data] }; const dataComplete = { dateDelivery: dataDeliveryDate[0].date, deliveries: [...data] };
return dataComplete; return dataComplete;

View File

@@ -26,9 +26,6 @@ export class Pccidade {
@Column({ name: 'CODMUNSIAFI' }) @Column({ name: 'CODMUNSIAFI' })
codmunsiafi: number; codmunsiafi: number;
@Column({ name: 'DTMXSALTER' })
dtmxsalter: Date;
@Column({ name: 'LATITUDE' }) @Column({ name: 'LATITUDE' })
latitude: string; latitude: string;

View File

@@ -2,94 +2,91 @@ import { Column, Entity, PrimaryColumn } from "typeorm";
@Entity("PCORCAVENDAI") @Entity("PCORCAVENDAI")
export class Pcorcavendai { export class Pcorcavendai {
@PrimaryColumn({name: 'NUMORCA'}) @PrimaryColumn({ name: 'NUMORCA' })
numorca: number; numorca: number;
@PrimaryColumn({name: 'CODPROD'}) @PrimaryColumn({ name: 'CODPROD' })
codprod: number; codprod: number;
@PrimaryColumn({name: 'NUMSEQ'}) @PrimaryColumn({ name: 'NUMSEQ' })
numseq: number; numseq: number;
@Column({name: 'DATA'}) @Column({ name: 'DATA' })
data: Date; data: Date;
@Column({name: 'CODCLI'}) @Column({ name: 'CODCLI' })
codcli: number; codcli: number;
@Column({name: 'CODUSUR'}) @Column({ name: 'CODUSUR' })
codusur: number; codusur: number;
@Column({name: 'QT'}) @Column({ name: 'QT' })
qt: number; qt: number;
@Column({name: 'PVENDA'}) @Column({ name: 'PVENDA' })
pvenda: number; pvenda: number;
@Column({name: 'PTABELA'}) @Column({ name: 'PTABELA' })
ptabela: number; ptabela: number;
@Column({name: 'NUMCAR'}) @Column({ name: 'NUMCAR' })
numcar: number; numcar: number;
@Column({name: 'POSICAO'}) @Column({ name: 'POSICAO' })
posicao: string; posicao: string;
@Column({name: 'ST'}) @Column({ name: 'ST' })
st: number; st: number;
@Column({name: 'VLCUSTOFIN'}) @Column({ name: 'VLCUSTOFIN' })
vlcustofin: number; vlcustofin: number;
@Column({name: 'VLCUSTOREAL'}) @Column({ name: 'VLCUSTOREAL' })
vlcustoreal: number; vlcustoreal: number;
@Column({name: 'PERCOM'}) @Column({ name: 'PERCOM' })
percom: number; percom: number;
@Column({name: 'PERDESC'}) @Column({ name: 'PERDESC' })
perdesc: number; perdesc: number;
@Column({name: 'PVENDABASE'}) @Column({ name: 'PVENDABASE' })
pvendabase: number; pvendabase: number;
@Column({name: 'CODST'}) @Column({ name: 'CODST' })
codst: number; codst: number;
@Column({name: 'CUSTOFINEST'}) @Column({ name: 'CUSTOFINEST' })
custofinest: number; custofinest: number;
@Column({name: 'CODAUXILIAR'}) @Column({ name: 'CODAUXILIAR' })
codauxiliar: number; codauxiliar: number;
@Column({name: 'CODFILIALRETIRA'}) @Column({ name: 'CODFILIALRETIRA' })
codfilialretira: string; codfilialretira: string;
@Column({name: 'PORIGINAL'}) @Column({ name: 'PORIGINAL' })
poriginal: number; poriginal: number;
@Column({name: 'VLCUSTOCONT'}) @Column({ name: 'VLCUSTOCONT' })
vlcustocont: number; vlcustocont: number;
@Column({name: 'VLCUSTOREP'}) @Column({ name: 'VLCUSTOREP' })
vlcustorep: number; vlcustorep: number;
@Column({name: 'PBASERCA'}) @Column({ name: 'PBASERCA' })
pbaserca: number; pbaserca: number;
@Column({name: 'PVENDA1'}) @Column({ name: 'PVENDA1' })
pvenda1: number; pvenda1: number;
@Column({name: 'TIPOENTREGA'}) @Column({ name: 'TIPOENTREGA' })
tipoentrega: string; tipoentrega: string;
@Column({name: 'COMPLEMENTO'}) @Column({ name: 'COMPLEMENTO' })
complemento: string; complemento: string;
@Column({name: 'AMBIENTE'}) @Column({ name: 'AMBIENTE' })
ambiente: string; ambiente: string;
@Column({name: 'RETIRAPOSTERIOR_IMEDIATA'})
rp_imediata: string;
} }

View File

@@ -3,167 +3,165 @@ import { Column, Entity, PrimaryColumn } from "typeorm";
@Entity('PCPEDITEMP') @Entity('PCPEDITEMP')
export class Pcpeditemp { export class Pcpeditemp {
@Column({ name: 'TIPOINTEGRACAO' }) @Column({ name: 'TIPOINTEGRACAO' })
tipointegracao: string; tipointegracao: string;
@Column({ name: 'OBSERVACAO_PC' }) @Column({ name: 'OBSERVACAO_PC' })
observacao_pc: string; observacao_pc: string;
@Column({ name: 'NUMPEDCLI' }) @Column({ name: 'NUMPEDCLI' })
numpedcli: string; numpedcli: string;
@PrimaryColumn({ name: 'NUMPEDRCA' }) @PrimaryColumn({ name: 'NUMPEDRCA' })
numpedrca: number; numpedrca: number;
@Column({ name: 'CODCLI' }) @Column({ name: 'CODCLI' })
codcli: number; codcli: number;
@Column({ name: 'CODUSUR' }) @Column({ name: 'CODUSUR' })
codusur: number; codusur: number;
@Column({ name: 'DATA' }) @Column({ name: 'DATA' })
data: Date; data: Date;
@PrimaryColumn({ name: 'CODPROD' }) @PrimaryColumn({ name: 'CODPROD' })
codprod: number; codprod: number;
@Column({ name: 'QT' }) @Column({ name: 'QT' })
qt: number; qt: number;
@Column({ name: 'QT_FATURADA' }) @Column({ name: 'QT_FATURADA' })
qt_faturada: number; qt_faturada: number;
@Column({ name: 'PVENDA' }) @Column({ name: 'PVENDA' })
pvenda: number; pvenda: number;
@Column({ name: 'PTABELA' }) @Column({ name: 'PTABELA' })
ptabela: number; ptabela: number;
@Column({ name: 'PERDESC' }) @Column({ name: 'PERDESC' })
perdesc: number; perdesc: number;
@PrimaryColumn({ name: 'NUMSEQ' }) @PrimaryColumn({ name: 'NUMSEQ' })
numseq: number; numseq: number;
@Column({ name: 'CODAUXILIAR' }) @Column({ name: 'CODAUXILIAR' })
codauxiliar: number; codauxiliar: number;
@Column({ name: 'CODCERTIFIC' }) @Column({ name: 'CODCERTIFIC' })
codcertific: number; codcertific: number;
@Column({ name: 'CODFILIALRETIRA' }) @Column({ name: 'CODFILIALRETIRA' })
codfilialretira: string; codfilialretira: string;
@Column({ name: 'NUMLOTE' }) @Column({ name: 'NUMLOTE' })
numlote: string; numlote: string;
@Column({ name: 'COMPLEMENTO' }) @Column({ name: 'COMPLEMENTO' })
complemento: string; complemento: string;
@Column({ name: 'CODPLPAG' }) @Column({ name: 'CODPLPAG' })
codplpag: number; codplpag: number;
@Column({ name: 'CODPROMOCAO' }) @Column({ name: 'CODPROMOCAO' })
codpromocao: string; codpromocao: string;
@Column({ name: 'PRAZOMEDIO' }) @Column({ name: 'PRAZOMEDIO' })
prazomedio: number; prazomedio: number;
@Column({ name: 'LOCALIZACAO' }) @Column({ name: 'LOCALIZACAO' })
localizacao: string; localizacao: string;
@Column({ name: 'PBONIFIC' }) @Column({ name: 'PBONIFIC' })
pbonific: number; pbonific: number;
@Column({ name: 'CODDEGUSTACAO' }) @Column({ name: 'CODDEGUSTACAO' })
coddegustacao: number; coddegustacao: number;
@Column({ name: 'PESOBRUTO' }) @Column({ name: 'PESOBRUTO' })
pesobruto: number; pesobruto: number;
@Column({ name: 'EANCODPROD' }) @Column({ name: 'EANCODPROD' })
eancodprod: number; eancodprod: number;
@Column({ name: 'CODNAOATENDIMENTO' }) @Column({ name: 'CODNAOATENDIMENTO' })
codnaoatendimento: number; codnaoatendimento: number;
@Column({ name: 'OBSINTEGRACAO1' }) @Column({ name: 'OBSINTEGRACAO1' })
obsintegracao1: string; obsintegracao1: string;
@Column({ name: 'OBSINTEGRACAO2' }) @Column({ name: 'OBSINTEGRACAO2' })
obsintegracao2: string; obsintegracao2: string;
@Column({ name: 'NUMPEDWEB' }) @Column({ name: 'NUMPEDWEB' })
numpedweb: number; numpedweb: number;
@Column({ name: 'TRANSACAO' }) @Column({ name: 'TRANSACAO' })
transacao: number; transacao: number;
@Column({ name: 'IDVENDA' }) @Column({ name: 'IDVENDA' })
idvenda: number; idvenda: number;
@Column({ name: 'INTEGRADORA' }) @Column({ name: 'INTEGRADORA' })
integradora: number; integradora: number;
@Column({ name: 'CODRETORNO' }) @Column({ name: 'CODRETORNO' })
codretorno: number; codretorno: number;
@Column({ name: 'COMISSAOATIM' }) @Column({ name: 'COMISSAOATIM' })
comissaoatim: number; comissaoatim: number;
@Column({ name: 'TIPOENTREGA' }) @Column({ name: 'TIPOENTREGA' })
tipoentrega: string; tipoentrega: string;
@Column({ name: 'CODRETORNOS' }) @Column({ name: 'CODRETORNOS' })
codretornos: string; codretornos: string;
@Column({ name: 'DTINCLUSAO' }) @Column({ name: 'DTINCLUSAO' })
dtinclusao: Date; dtinclusao: Date;
@Column({ name: 'CODPRODCESTA' }) @Column({ name: 'CODPRODCESTA' })
codprodcesta: number; codprodcesta: number;
@Column({ name: 'BONIFIC' }) @Column({ name: 'BONIFIC' })
bonific: string; bonific: string;
@Column({ name: 'DTIMP' }) @Column({ name: 'DTIMP' })
dtimp: Date; dtimp: Date;
@Column({ name: 'PBASERCA' }) @Column({ name: 'PBASERCA' })
pbaserca: number; pbaserca: number;
@Column({ name: 'VLFRETE' }) @Column({ name: 'VLFRETE' })
vlfrete: number; vlfrete: number;
@Column({ name: 'FATORCONVERSAO' }) @Column({ name: 'FATORCONVERSAO' })
fatorconversao: number; fatorconversao: number;
@Column({ name: 'IDKITPRODUTO' }) @Column({ name: 'IDKITPRODUTO' })
idkitproduto: string; idkitproduto: string;
@Column({ name: 'MOVIMENTACONTACORRENTERCA' }) @Column({ name: 'MOVIMENTACONTACORRENTERCA' })
movimentacontacorrenterca: string; movimentacontacorrenterca: string;
@Column({ name: 'PORIGINAL' }) @Column({ name: 'PORIGINAL' })
poriginal: number; poriginal: number;
@Column({ name: 'ESC_EMBALAGEMPRESENTE' }) @Column({ name: 'ESC_EMBALAGEMPRESENTE' })
esc_embalagempresente: string; esc_embalagempresente: string;
@Column({ name: 'QTUNITEMB' }) @Column({ name: 'QTUNITEMB' })
qtunitemb: number; qtunitemb: number;
@Column({ name: 'IDREMESSAWEB' }) @Column({ name: 'IDREMESSAWEB' })
idremessaweb: number; idremessaweb: number;
@Column({ name: 'CODFILIAL' }) @Column({ name: 'CODFILIAL' })
codfilial: string; codfilial: string;
@Column({ name: 'CODCLIPARTILHA' }) @Column({ name: 'CODCLIPARTILHA' })
codclipartilha: number; codclipartilha: number;
@Column({name: 'RETIRAPOSTERIOR_IMEDIATA'})
rp_imediata: string;
} }

View File

@@ -6,20 +6,25 @@ import 'reflect-metadata';
import { CustomLoggerService } from './services/custom-logger.service'; import { CustomLoggerService } from './services/custom-logger.service';
async function bootstrap() { async function bootstrap() {
const app = await NestFactory.create(AppModule, { cors: true, logger: new CustomLoggerService()}); const app = await NestFactory.create(AppModule, {
cors: true,
logger: new CustomLoggerService(),
});
app.enableCors(); app.enableCors();
app.use(compression()); app.use(compression());
const options = new DocumentBuilder() const options = new DocumentBuilder()
.setTitle('API Venda web') .setTitle('API Venda web')
.setDescription(`API criada para realizar todo processo da venda assistida, como criação de oraçamento de venda, pedido de venda .setDescription(
`API criada para realizar todo processo da venda assistida, como criação de oraçamento de venda, pedido de venda
cadastro de novos clientes, novos endereços. A API também fornece dados para o portal de parceiros como a manutenção cadastro de novos clientes, novos endereços. A API também fornece dados para o portal de parceiros como a manutenção
do cadastro de parceiros, consulta de venda de movimentação e pagamentos, e fechamento das comissões dos parceiros.`) do cadastro de parceiros, consulta de venda de movimentação e pagamentos, e fechamento das comissões dos parceiros.`,
.setVersion("2023.1.2") )
.addTag("VendaWeb") .setVersion('2023.1.2')
.addTag("Autenticação") .addTag('VendaWeb')
.addTag('Auth')
.build(); .build();
const document = SwaggerModule.createDocument(app, options); const document = SwaggerModule.createDocument(app, options);
SwaggerModule.setup("docs", app, document); SwaggerModule.setup('docs', app, document);
await app.listen(8067); await app.listen(8067);
} }
bootstrap(); bootstrap();

View File

@@ -469,9 +469,9 @@ export class CustomerService {
async InitializeCustomer() { async InitializeCustomer() {
const cliente = new Pcclient(); const cliente = new Pcclient();
cliente.codusur1 = 1; cliente.codusur1 = 1;
cliente.codplpag = 10; cliente.codplpag = 18;
cliente.codpraca = 119; cliente.codpraca = 169;
cliente.codcob = "D"; cliente.codcob = "CAR";
cliente.dtcadastro = new Date(); cliente.dtcadastro = new Date();
cliente.codcontab = "1"; cliente.codcontab = "1";
cliente.aceitavendafracao = "N"; cliente.aceitavendafracao = "N";
@@ -502,7 +502,7 @@ export class CustomerService {
cliente.tv10usacustoproduto = "N"; cliente.tv10usacustoproduto = "N";
cliente.inscestadual = "ISENTO"; cliente.inscestadual = "ISENTO";
cliente.codpais = 1058; //Brasil cliente.codpais = 1058; //Brasil
cliente.observacao = "Importado do E-Commerce"; cliente.observacao = "Cadastrado Venda Web";
cliente.aceitachterceiros = "S"; cliente.aceitachterceiros = "S";
cliente.agregarvalorstdescfin = "N"; cliente.agregarvalorstdescfin = "N";
cliente.anvisa = "N"; cliente.anvisa = "N";
@@ -523,6 +523,7 @@ export class CustomerService {
cliente.fretedespacho = "0"; cliente.fretedespacho = "0";
cliente.aceitavendafracao = "S"; cliente.aceitavendafracao = "S";
cliente.validarmultiplovenda = "S"; cliente.validarmultiplovenda = "S";
cliente.isentotxentrega = "S";
return cliente; return cliente;
} }

View File

@@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/camelcase */ /* eslint-disable @typescript-eslint/camelcase */
import { HttpException, HttpStatus, Injectable,Inject } from '@nestjs/common'; import { HttpException, HttpStatus, Injectable, Inject } from '@nestjs/common';
import { ShoppingItens } from 'src/domain/entity/tables/estprevendai.entity'; import { ShoppingItens } from 'src/domain/entity/tables/estprevendai.entity';
import { Sale } from 'src/domain/entity/tables/estvenda.entity'; import { Sale } from 'src/domain/entity/tables/estvenda.entity';
import { Pcpedctemp } from 'src/domain/entity/tables/pcpedctemp.entity'; import { Pcpedctemp } from 'src/domain/entity/tables/pcpedctemp.entity';
@@ -165,8 +165,8 @@ export class OrderService {
` OR EXISTS(SELECT PCCOB.CODCOB FROM PCCOB ` + ` OR EXISTS(SELECT PCCOB.CODCOB FROM PCCOB ` +
` WHERE PCCOB.CODCOB = PCPEDC.CODCOB ` + ` WHERE PCCOB.CODCOB = PCPEDC.CODCOB ` +
` AND NVL(PCCOB.CARTAO,'N') = 'S') ) `; ` AND NVL(PCCOB.CARTAO,'N') = 'S') ) `;
await queryRunner.manager // await queryRunner.manager
.query(sql, [order.numped]); // .query(sql, [order.numped]);
sql = `UPDATE PCPEDI SET POSICAO = 'L' WHERE NUMPED = :1 ` + sql = `UPDATE PCPEDI SET POSICAO = 'L' WHERE NUMPED = :1 ` +
` AND EXISTS( SELECT PCPEDC.NUMPED FROM PCPEDC ` + ` AND EXISTS( SELECT PCPEDC.NUMPED FROM PCPEDC ` +
` WHERE PCPEDC.NUMPED = PCPEDI.NUMPED ` + ` WHERE PCPEDC.NUMPED = PCPEDI.NUMPED ` +
@@ -175,10 +175,10 @@ export class OrderService {
` OR EXISTS(SELECT PCCOB.CODCOB FROM PCCOB ` + ` OR EXISTS(SELECT PCCOB.CODCOB FROM PCCOB ` +
` WHERE PCCOB.CODCOB = PCPEDC.CODCOB ` + ` WHERE PCCOB.CODCOB = PCPEDC.CODCOB ` +
` AND NVL(PCCOB.CARTAO,'N') = 'S') ) )`; ` AND NVL(PCCOB.CARTAO,'N') = 'S') ) )`;
await queryRunner.manager // await queryRunner.manager
.query(sql, [order.numped]); // .query(sql, [order.numped]);
await this.updateStatusItem(queryRunner, order.numped); // await this.updateStatusItem(queryRunner, order.numped);
sql = ` UPDATE PCPEDC SET ` + sql = ` UPDATE PCPEDC SET ` +
@@ -204,7 +204,7 @@ export class OrderService {
` AND EXISTS(SELECT TV7.NUMPED FROM PCPEDC TV7 WHERE TV7.NUMPED = PCPEDC.NUMPEDENTFUT ` + ` AND EXISTS(SELECT TV7.NUMPED FROM PCPEDC TV7 WHERE TV7.NUMPED = PCPEDC.NUMPEDENTFUT ` +
` AND TV7.POSICAO = 'L' )`; ` AND TV7.POSICAO = 'L' )`;
await queryRunner.manager.query(sql, [order.numped]); // await queryRunner.manager.query(sql, [order.numped]);
sql = ` UPDATE PCPEDC SET ` + sql = ` UPDATE PCPEDC SET ` +
` POSICAO = ( SELECT PCPEDI.POSICAO FROM PCPEDI WHERE PCPEDI.NUMPED = PCPEDC.NUMPED AND ROWNUM = 1 ) ` + ` POSICAO = ( SELECT PCPEDI.POSICAO FROM PCPEDI WHERE PCPEDI.NUMPED = PCPEDC.NUMPED AND ROWNUM = 1 ) ` +
` , MOTIVOPOSICAO = NULL ` + ` , MOTIVOPOSICAO = NULL ` +
@@ -227,7 +227,7 @@ export class OrderService {
` AND PCPEDC.NUMPEDENTFUT = :1 ` + ` AND PCPEDC.NUMPEDENTFUT = :1 ` +
` AND EXISTS(SELECT TV7.NUMPED FROM PCPEDC TV7 WHERE TV7.NUMPED = PCPEDC.NUMPEDENTFUT ` + ` AND EXISTS(SELECT TV7.NUMPED FROM PCPEDC TV7 WHERE TV7.NUMPED = PCPEDC.NUMPEDENTFUT ` +
` AND TV7.POSICAO = 'L' )`; ` AND TV7.POSICAO = 'L' )`;
await queryRunner.manager.query(sql, [order.numped]); // await queryRunner.manager.query(sql, [order.numped]);
// atualizar campos padrão para rotina 4116 // atualizar campos padrão para rotina 4116
sql = ` UPDATE PCPEDC SET ` + sql = ` UPDATE PCPEDC SET ` +
@@ -527,6 +527,7 @@ export class OrderService {
preOrder.esc_ajustarfinanceiro = "N"; preOrder.esc_ajustarfinanceiro = "N";
preOrder.esc_obternsu = "N"; preOrder.esc_obternsu = "N";
preOrder.esc_vloutrasdespweb = 0; preOrder.esc_vloutrasdespweb = 0;
preOrder.vloutrasdesp = cart.shippingValue;
preOrder.pedidopagoecommerce = "S"; preOrder.pedidopagoecommerce = "S";
preOrder.numpedmktplace = ""; preOrder.numpedmktplace = "";
preOrder.numitens = cart.itens.length; preOrder.numitens = cart.itens.length;
@@ -538,7 +539,7 @@ export class OrderService {
//Dados do cliente //Dados do cliente
preOrder.codcli = cart.idCustomer; preOrder.codcli = cart.idCustomer;
preOrder.codpraca = (cart.shippingPriority == "M" && cart.idStorePlace != null ) ? cart.idStorePlace : customer.codpraca; preOrder.codpraca = (cart.shippingPriority == "M" && cart.idStorePlace != null) ? cart.idStorePlace : customer.codpraca;
preOrder.fretedespacho = customer.fretedespacho; preOrder.fretedespacho = customer.fretedespacho;
preOrder.codfornecfrete = cart.carrierId; preOrder.codfornecfrete = cart.carrierId;
@@ -585,8 +586,8 @@ export class OrderService {
itemOrder.codauxiliar = componente.ean; itemOrder.codauxiliar = componente.ean;
itemOrder.codfilialretira = item.idStock; itemOrder.codfilialretira = item.idStock;
itemOrder.tipoentrega = (item.deliveryMethod == 'RA') ? "RP" : item.deliveryMethod; itemOrder.tipoentrega = (item.deliveryMethod == 'RA') ? "RP" : item.deliveryMethod;
itemOrder.rp_imediata = (item.deliveryMethod == 'RA') ? "S" : "N"; // itemOrder.rp_imediata = (item.deliveryMethod == 'RA') ? "S" : "N";
if ( item.deliveryMethod == 'RA') { if (item.deliveryMethod == 'RA') {
preOrder.dtentrega = new Date(); preOrder.dtentrega = new Date();
} }
itemOrder.ptabela = Number.parseFloat(listPrice); itemOrder.ptabela = Number.parseFloat(listPrice);
@@ -618,8 +619,8 @@ export class OrderService {
itemOrder.codauxiliar = item.ean; itemOrder.codauxiliar = item.ean;
itemOrder.codfilialretira = item.idStock; itemOrder.codfilialretira = item.idStock;
itemOrder.tipoentrega = (item.deliveryMethod == 'RA') ? "RP" : item.deliveryMethod; itemOrder.tipoentrega = (item.deliveryMethod == 'RA') ? "RP" : item.deliveryMethod;
itemOrder.rp_imediata = (item.deliveryMethod == 'RA') ? "S" : "N"; //itemOrder.rp_imediata = (item.deliveryMethod == 'RA') ? "S" : "N";
if ( item.deliveryMethod == 'RA') { if (item.deliveryMethod == 'RA') {
preOrder.dtentrega = new Date(); preOrder.dtentrega = new Date();
} }
itemOrder.ptabela = item.listPrice; itemOrder.ptabela = item.listPrice;
@@ -643,34 +644,34 @@ export class OrderService {
//#endregion //#endregion
if (cart.shippingValue > 0) { // if (cart.shippingValue > 0) {
const itemOrder = new Pcpeditemp(); // const itemOrder = new Pcpeditemp();
itemOrder.tipointegracao = "W"; // itemOrder.tipointegracao = "W";
itemOrder.integradora = 10; // itemOrder.integradora = 10;
itemOrder.numpedrca = idPreOrder; // itemOrder.numpedrca = idPreOrder;
itemOrder.numpedweb = idPreOrder; // itemOrder.numpedweb = idPreOrder;
itemOrder.codcli = cart.idCustomer; // itemOrder.codcli = cart.idCustomer;
itemOrder.codusur = idSellerPreorder; //cart.idSeller; // itemOrder.codusur = idSellerPreorder; //cart.idSeller;
itemOrder.numseq = numeroSeq; // itemOrder.numseq = numeroSeq;
itemOrder.codprod = 48500; // itemOrder.codprod = 48500;
itemOrder.codauxiliar = 48500; // itemOrder.codauxiliar = 48500;
itemOrder.codfilialretira = '12'; // itemOrder.codfilialretira = '12';
itemOrder.tipoentrega = 'EF'; // itemOrder.tipoentrega = 'EF';
itemOrder.ptabela = Number.parseFloat(cart.shippingValue.toString()); // itemOrder.ptabela = Number.parseFloat(cart.shippingValue.toString());
itemOrder.pvenda = Number.parseFloat(cart.shippingValue.toString()); // itemOrder.pvenda = Number.parseFloat(cart.shippingValue.toString());
itemOrder.qt = 1; // itemOrder.qt = 1;
itemOrder.data = new Date(); // itemOrder.data = new Date();
await queryRunner.manager // await queryRunner.manager
.createQueryBuilder() // .createQueryBuilder()
.insert() // .insert()
.into(Pcpeditemp) // .into(Pcpeditemp)
.values(itemOrder) // .values(itemOrder)
.execute(); // .execute();
numeroSeq = numeroSeq + 1; // numeroSeq = numeroSeq + 1;
} // }
// execute some operations on this transaction: // execute some operations on this transaction:
await queryRunner.manager await queryRunner.manager
@@ -825,12 +826,12 @@ export class OrderService {
` WHERE PCPEDC.CODCLI = PCCLIENT.CODCLI ` + ` WHERE PCPEDC.CODCLI = PCCLIENT.CODCLI ` +
` AND PCPEDC.CONDVENDA IN (1,7) ` + ` AND PCPEDC.CONDVENDA IN (1,7) ` +
` AND PCPEDC.DTCANCEL IS NULL AND PCPEDC.POSICAO NOT IN ('C') `; ` AND PCPEDC.DTCANCEL IS NULL AND PCPEDC.POSICAO NOT IN ('C') `;
` AND PCPEDC.ROTINALANC = 'VENDAWEB' `; ` AND EXISTS(SELECT 1 FROM ESTPREVENDAC WHERE ESTPREVENDAC.NUMPED = PCPEDC.NUMPED ) `; //PCPEDC.ROTINALANC = 'VENDAWEB' `;
if (store != null && store != '') { if (store != null && store != '') {
sqlWhere += ` AND PCPEDC.CODFILIAL = '${store}' `; sqlWhere += ` AND PCPEDC.CODFILIAL = '${store}' `;
} }
if (document != null && document != '') { if (document != null && document != '') {
sqlWhere += ` AND REGEXP_REPLACE(PCCLIENT.CGCENT, '[^0-9]', '') = REGEXP_REPLACE('${document}', '[^0-9]', '')`; sqlWhere += ` AND ((REGEXP_REPLACE(PCCLIENT.CGCENT, '[^0-9]', '') = REGEXP_REPLACE('${document}', '[^0-9]', '') ) OR ( PCCLIENT.CODCLI = REGEXP_REPLACE('${document}', '[^0-9]', '')) )`;
} }
if (name != null && name != '') { if (name != null && name != '') {
sqlWhere += ` AND PCCLIENT.CLIENTE LIKE '${name.replace('@', '%')}'||'%'`; sqlWhere += ` AND PCCLIENT.CLIENTE LIKE '${name.replace('@', '%')}'||'%'`;
@@ -953,7 +954,7 @@ export class OrderService {
const partners = await this.listsService.GetPartners(); const partners = await this.listsService.GetPartners();
const address = await this.addressCustomerService.getAddress(order[0].customerId, order[0].addressId); const address = await this.addressCustomerService.getAddress(order[0].customerId, order[0].addressId);
const billing = billinds.find(data => data.codcob === order[0].billindId); const billing = billinds.find(data => data.codcob === order[0].billindId);
const paymentPlans = await this.listsService.GetPaymentPlan(billing.codcob); const paymentPlans = await this.listsService.GetPaymentPlan(billing.codcob, order[0].customerId);
const paymentPlan = paymentPlans.find(data => data.codplpag === order[0].paymentPlanId); const paymentPlan = paymentPlans.find(data => data.codplpag === order[0].paymentPlanId);
const partner = partners.find(data => data.id === order[0].partnerId); const partner = partners.find(data => data.id === order[0].partnerId);
@@ -1064,7 +1065,7 @@ export class OrderService {
async getProductsOrder(store: string, initialDate: Date, finalDate: Date, async getProductsOrder(store: string, initialDate: Date, finalDate: Date,
document: string, name: string, sellerId: number, idOrder: string, document: string, name: string, sellerId: number, idOrder: string,
typeFilterProduct: string, productText: string typeFilterProduct: string, productText: string
) { ) {
const sql = `SELECT PCPEDC.DATA as "date" const sql = `SELECT PCPEDC.DATA as "date"
,PCPEDC.NUMPED as "orderId" ,PCPEDC.NUMPED as "orderId"
@@ -1103,52 +1104,52 @@ export class OrderService {
let sqlWhere = ''; let sqlWhere = '';
if (store != null && store != '' && store != '99') { if (store != null && store != '' && store != '99') {
sqlWhere += ` AND PCPEDC.CODFILIAL = '${store}' `; sqlWhere += ` AND PCPEDC.CODFILIAL = '${store}' `;
} }
if (document != null && document != '') { if (document != null && document != '') {
sqlWhere += ` AND REGEXP_REPLACE(PCCLIENT.CGCENT, '[^0-9]', '') = REGEXP_REPLACE('${document}', '[^0-9]', '')`; sqlWhere += ` AND REGEXP_REPLACE(PCCLIENT.CGCENT, '[^0-9]', '') = REGEXP_REPLACE('${document}', '[^0-9]', '')`;
} }
if (name != null && name != '') { if (name != null && name != '') {
sqlWhere += ` AND PCCLIENT.CLIENTE LIKE '${name.replace('@', '%')}'||'%'`; sqlWhere += ` AND PCCLIENT.CLIENTE LIKE '${name.replace('@', '%')}'||'%'`;
} }
if (sellerId > 0) { if (sellerId > 0) {
sqlWhere += ` AND PCPEDC.CODUSUR = ${sellerId} `; sqlWhere += ` AND PCPEDC.CODUSUR = ${sellerId} `;
} }
if (idOrder.trim() != null && idOrder.trim() != '') { if (idOrder.trim() != null && idOrder.trim() != '') {
sqlWhere += ` AND PCPEDC.NUMPED = ${idOrder} `; sqlWhere += ` AND PCPEDC.NUMPED = ${idOrder} `;
} }
if ( typeFilterProduct != '') { if (typeFilterProduct != '') {
switch (typeFilterProduct) { switch (typeFilterProduct) {
case 'ID': case 'ID':
sqlWhere += ` AND PCPEDI.CODPROD = ${productText} `; sqlWhere += ` AND PCPEDI.CODPROD = ${productText} `;
break; break;
case 'EAN': case 'EAN':
sqlWhere += ` AND PCPRODUT.CODAUXILIAR = ${productText} `; sqlWhere += ` AND PCPRODUT.CODAUXILIAR = ${productText} `;
break; break;
case 'TEXT': case 'TEXT':
sqlWhere += ` AND PCPRODUT.DESCRICAO LIKE '${productText}%' `; sqlWhere += ` AND PCPRODUT.DESCRICAO LIKE '${productText}%' `;
break; break;
case 'PARTNER': case 'PARTNER':
sqlWhere += ` AND PCPRODUT.CODFAB like '${productText}%'`; sqlWhere += ` AND PCPRODUT.CODFAB like '${productText}%'`;
break; break;
default: break; default: break;
}
} }
}
//tratamento de data// //tratamento de data//
const startDate = new Date(initialDate); const startDate = new Date(initialDate);
let day = startDate.getDate(); let day = startDate.getDate();
let month = ("00" + (startDate.getMonth() + 1)).slice(-2); let month = ("00" + (startDate.getMonth() + 1)).slice(-2);
let year = startDate.getFullYear(); let year = startDate.getFullYear();
const startFormat = day + "/" + month + "/" + year; const startFormat = day + "/" + month + "/" + year;
const endDate = new Date(finalDate); const endDate = new Date(finalDate);
day = endDate.getDate(); day = endDate.getDate();
month = ("00" + (endDate.getMonth() + 1)).slice(-2); month = ("00" + (endDate.getMonth() + 1)).slice(-2);
year = endDate.getFullYear(); year = endDate.getFullYear();
const endFormat = day + "/" + month + "/" + year; const endFormat = day + "/" + month + "/" + year;
sqlWhere += ` AND PCPEDI.DATA BETWEEN TO_DATE('${startFormat}', 'DD/MM/YYYY') AND TO_DATE('${endFormat}', 'DD/MM/YYYY') `; sqlWhere += ` AND PCPEDI.DATA BETWEEN TO_DATE('${startFormat}', 'DD/MM/YYYY') AND TO_DATE('${endFormat}', 'DD/MM/YYYY') `;
const connection = new Connection(connectionOptions); const connection = new Connection(connectionOptions);

View File

@@ -51,7 +51,7 @@ export class PreOrderService {
if (shopping.length > 0) { if (shopping.length > 0) {
idPreOrder = shopping[0].idPreOrder; idPreOrder = shopping[0].idPreOrder;
const existPreOrder = await queryRunner const existPreOrder = await queryRunner
.query('SELECT PCORCAVENDAC.CODUSUR as "idRca" FROM PCORCAVENDAC WHERE NUMORCA = :NUMORCA', [idPreOrder]); .query('SELECT PCORCAVENDAC.CODUSUR as "idRca" FROM PCORCAVENDAC WHERE NUMORCA = :NUMORCA', [idPreOrder]);
idRca = existPreOrder[0].idRca; idRca = existPreOrder[0].idRca;
await queryRunner.query('DELETE FROM PCORCAVENDAI WHERE NUMORCA = :1', [idPreOrder]); await queryRunner.query('DELETE FROM PCORCAVENDAI WHERE NUMORCA = :1', [idPreOrder]);
await queryRunner.query('DELETE FROM PCORCAVENDAC WHERE NUMORCA = :1', [idPreOrder]); await queryRunner.query('DELETE FROM PCORCAVENDAC WHERE NUMORCA = :1', [idPreOrder]);
@@ -70,9 +70,9 @@ export class PreOrderService {
cart.id, cart.preCustomerName, cart.preCustomerPhone, cart.idSeller, idPreOrder]); cart.id, cart.preCustomerName, cart.preCustomerPhone, cart.idSeller, idPreOrder]);
} }
} else { } else {
if ( cart.preCustomerDocument != null ) { if (cart.preCustomerDocument != null) {
await queryRunner.query(`DELETE FROM ESTVENDAPRECLIENTE WHERE IDCART = :1 AND REGEXP_REPLACE(:CPF, '[^0-9]', '')`, await queryRunner.query(`DELETE FROM ESTVENDAPRECLIENTE WHERE IDCART = :1 AND REGEXP_REPLACE(:CPF, '[^0-9]', '')`,
[cart.id, cart.preCustomerDocument]); [cart.id, cart.preCustomerDocument]);
} }
} }
@@ -92,7 +92,7 @@ export class PreOrderService {
itemPreOrder.codcli = cart.idCustomer; itemPreOrder.codcli = cart.idCustomer;
itemPreOrder.codprod = item.idProduct; itemPreOrder.codprod = item.idProduct;
itemPreOrder.codauxiliar = item.ean; itemPreOrder.codauxiliar = item.ean;
itemPreOrder.codusur = ( idRca > 0 ) ? idRca : cart.idSeller; itemPreOrder.codusur = (idRca > 0) ? idRca : cart.idSeller;
itemPreOrder.qt = item.quantity; itemPreOrder.qt = item.quantity;
itemPreOrder.pvenda = item.salePrice; itemPreOrder.pvenda = item.salePrice;
itemPreOrder.ptabela = item.listPrice; itemPreOrder.ptabela = item.listPrice;
@@ -120,7 +120,7 @@ export class PreOrderService {
itemPreOrder.pvenda1 = 0; itemPreOrder.pvenda1 = 0;
itemPreOrder.tipoentrega = item.deliveryMethod; itemPreOrder.tipoentrega = item.deliveryMethod;
// eslint-disable-next-line @typescript-eslint/camelcase // eslint-disable-next-line @typescript-eslint/camelcase
itemPreOrder.rp_imediata = (item.deliveryMethod == "RA") ? "S" : "N"; // itemPreOrder.rp_imediata = (item.deliveryMethod == "RA") ? "S" : "N";
itemPreOrder.complemento = item.descriptionAux; itemPreOrder.complemento = item.descriptionAux;
itemPreOrder.ambiente = item.environment; itemPreOrder.ambiente = item.environment;
@@ -137,52 +137,52 @@ export class PreOrderService {
numeroSeq = numeroSeq + 1; numeroSeq = numeroSeq + 1;
} }
if (cart.shippingValue > 0) { // if (cart.shippingValue > 0) {
const itemPreOrder = new Pcorcavendai(); // const itemPreOrder = new Pcorcavendai();
itemPreOrder.numorca = preOrder.numorca; // itemPreOrder.numorca = preOrder.numorca;
itemPreOrder.data = this.formatDate(new Date()); // itemPreOrder.data = this.formatDate(new Date());
itemPreOrder.codcli = cart.idCustomer; // itemPreOrder.codcli = cart.idCustomer;
itemPreOrder.codprod = 48500; // itemPreOrder.codprod = 48500;
itemPreOrder.codauxiliar = 48500; // itemPreOrder.codauxiliar = 48500;
itemPreOrder.codusur = ( idRca > 0 ) ? idRca : cart.idSeller; // itemPreOrder.codusur = (idRca > 0) ? idRca : cart.idSeller;
itemPreOrder.qt = 1; // itemPreOrder.qt = 1;
itemPreOrder.pvenda = Number.parseFloat(cart.shippingValue.toString()); // itemPreOrder.pvenda = Number.parseFloat(cart.shippingValue.toString());
itemPreOrder.ptabela = Number.parseFloat(cart.shippingValue.toString()); // itemPreOrder.ptabela = Number.parseFloat(cart.shippingValue.toString());
itemPreOrder.numcar = 0; // itemPreOrder.numcar = 0;
itemPreOrder.posicao = 'L'; // itemPreOrder.posicao = 'L';
itemPreOrder.st = 0; // itemPreOrder.st = 0;
itemPreOrder.vlcustocont = 0; // itemPreOrder.vlcustocont = 0;
itemPreOrder.vlcustofin = 0; // itemPreOrder.vlcustofin = 0;
itemPreOrder.vlcustoreal = 0; // itemPreOrder.vlcustoreal = 0;
itemPreOrder.vlcustorep = 0; // itemPreOrder.vlcustorep = 0;
itemPreOrder.percom = 0; // itemPreOrder.percom = 0;
itemPreOrder.perdesc = 0; // itemPreOrder.perdesc = 0;
itemPreOrder.numseq = numeroSeq; // itemPreOrder.numseq = numeroSeq;
itemPreOrder.pvendabase = 0; // itemPreOrder.pvendabase = 0;
itemPreOrder.codst = await this. // itemPreOrder.codst = await this.
sharedService. // sharedService.
getTaxId(48500, // getTaxId(48500,
cart.saleStore, // cart.saleStore,
customer.estent); // customer.estent);
itemPreOrder.custofinest = 0; // itemPreOrder.custofinest = 0;
itemPreOrder.codauxiliar = 48500; // itemPreOrder.codauxiliar = 48500;
itemPreOrder.codfilialretira = cart.saleStore; // itemPreOrder.codfilialretira = cart.saleStore;
itemPreOrder.poriginal = 0; // itemPreOrder.poriginal = 0;
itemPreOrder.pvendabase = 0; // itemPreOrder.pvendabase = 0;
itemPreOrder.pvenda1 = 0; // itemPreOrder.pvenda1 = 0;
itemPreOrder.tipoentrega = 'EF'; // itemPreOrder.tipoentrega = 'EF';
console.log('Processo 3'); // console.log('Processo 3');
await queryRunner.manager // await queryRunner.manager
.createQueryBuilder() // .createQueryBuilder()
.insert() // .insert()
.into(Pcorcavendai) // .into(Pcorcavendai)
.values(itemPreOrder) // .values(itemPreOrder)
.execute(); // .execute();
console.log('Processo 4'); // console.log('Processo 4');
numeroSeq = numeroSeq + 1; // numeroSeq = numeroSeq + 1;
} // }
//#region create PCORCAVENDAC //#region create PCORCAVENDAC
console.log('Processo 5' + cart); console.log('Processo 5' + cart);
@@ -201,7 +201,7 @@ export class PreOrderService {
preOrder.minuto = new Date().getMinutes(); preOrder.minuto = new Date().getMinutes();
preOrder.dtentrega = cart.shippingDate; // dateDelivery; preOrder.dtentrega = cart.shippingDate; // dateDelivery;
preOrder.codfilial = cart.saleStore, preOrder.codfilial = cart.saleStore,
preOrder.codusur = ( idRca > 0 ) ? idRca : cart.idSeller; preOrder.codusur = (idRca > 0) ? idRca : cart.idSeller;
preOrder.codemitente = cart.userId; preOrder.codemitente = cart.userId;
preOrder.codusur3 = cart.idProfessional; preOrder.codusur3 = cart.idProfessional;
preOrder.tipoprioridadeentrega = cart.shippingPriority; preOrder.tipoprioridadeentrega = cart.shippingPriority;
@@ -209,8 +209,8 @@ export class PreOrderService {
preOrder.codsupervisor = supervisor[0].codsupervisor; preOrder.codsupervisor = supervisor[0].codsupervisor;
} }
preOrder.codemitente = cart.userId; preOrder.codemitente = cart.userId;
preOrder.vlfrete = cart.shippingValue; preOrder.vlfrete = 0;
preOrder.vloutrasdesp = 0; preOrder.vloutrasdesp = cart.shippingValue;
preOrder.numitens = cart.itens.length; preOrder.numitens = cart.itens.length;
preOrder.obs1 = cart.notation1; preOrder.obs1 = cart.notation1;
preOrder.obs2 = cart.notation2; preOrder.obs2 = cart.notation2;
@@ -352,11 +352,11 @@ export class PreOrderService {
sql += ` AND PCORCAVENDAC.NUMORCA = ${idPreOrder} `; sql += ` AND PCORCAVENDAC.NUMORCA = ${idPreOrder} `;
} }
if ( document.length > 0 ) { if (document.length > 0) {
sql += ` AND REGEXP_REPLACE(PCCLIENT.CGCENT, '[^0-9]', '') = REGEXP_REPLACE(${document}, '[^0-9]', '') `; sql += ` AND REGEXP_REPLACE(PCCLIENT.CGCENT, '[^0-9]', '') = REGEXP_REPLACE(${document}, '[^0-9]', '') `;
} }
if ( nameCustomer.length > 0 ) { if (nameCustomer.length > 0) {
sql += ` AND PCCLIENT.CLIENTE LIKE UPPER('${nameCustomer}')||'%' `; sql += ` AND PCCLIENT.CLIENTE LIKE UPPER('${nameCustomer}')||'%' `;
} }
@@ -411,7 +411,7 @@ export class PreOrderService {
} }
await queryRunner.query("BEGIN ESK_VENDA.ATUALIZAR_PRECO_VENDA(:idcart, :paymentPlanId); END;", await queryRunner.query("BEGIN ESK_VENDA.ATUALIZAR_PRECO_VENDA(:idcart, :paymentPlanId); END;",
[preOrder[0].cartId, preOrder[0].paymentPlanId]); [preOrder[0].cartId, preOrder[0].paymentPlanId]);
const invoiceStores = await this.listsService.GetStoreAll(); const invoiceStores = await this.listsService.GetStoreAll();
const invoiceStore = await invoiceStores.find(data => data.id === preOrder[0].invoiceStore); const invoiceStore = await invoiceStores.find(data => data.id === preOrder[0].invoiceStore);
@@ -425,7 +425,7 @@ export class PreOrderService {
} }
// const address = await this.addressCustomerService.getAddress(preOrder[0].customerId, preOrder[0].addressId); // const address = await this.addressCustomerService.getAddress(preOrder[0].customerId, preOrder[0].addressId);
const billing = billinds.find(data => data.codcob === preOrder[0].billindId); const billing = billinds.find(data => data.codcob === preOrder[0].billindId);
const paymentPlans = await this.listsService.GetPaymentPlan((billing !== null && billing !== undefined) ? billing.codcob : '9999'); const paymentPlans = await this.listsService.GetPaymentPlan((billing !== null && billing !== undefined) ? billing.codcob : '9999', preOrder[0].customerId);
const paymentPlan = paymentPlans.find(data => data.codplpag === preOrder[0].paymentPlanId); const paymentPlan = paymentPlans.find(data => data.codplpag === preOrder[0].paymentPlanId);
const partner = partners.find(data => data.id === preOrder[0].partnerId); const partner = partners.find(data => data.id === preOrder[0].partnerId);

View File

@@ -27,8 +27,39 @@ export class SalesService {
async GetProducts2(store: string, pageSize: number, pageNumber: number, filter: FilterProduct = null,) { async GetProducts2(store: string, pageSize: number, pageNumber: number, filter: FilterProduct = null,) {
const connectionDb = new Connection(connectionOptions); const cacheKey = `GetProducts2:${store}:${pageSize}:${pageNumber}:${JSON.stringify(filter)}`;
await connectionDb.connect(); const lockKey = `lock:${cacheKey}`;
const lockTimeout = 30;
// Fase 1: Verificar cache Redis
try {
const cachedResult = await this.redisClient.get(cacheKey);
if (cachedResult) {
console.log('GetProducts2 - Retornando resultado do cache');
return JSON.parse(cachedResult);
}
} catch (err) {
console.error('Erro ao acessar o Redis no GetProducts2:', err?.message || err);
}
// Lock para evitar thundering herd
const lockValue = Date.now() + lockTimeout * 1000 + 1;
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 (GetProducts2):', err?.message || err);
acquiredLock = 'OK'; // Em caso de erro no Redis, prosseguir sem lock
}
if (acquiredLock !== 'OK') {
console.log('Lock não adquirido (GetProducts2), aguardando...');
await this.sleep(1000);
return this.GetProducts2(store, pageSize, pageNumber, filter);
}
// Fase 2: Reutilizar conexão via pool
const connectionDb = getConnection();
const queryRunner = connectionDb.createQueryRunner(); const queryRunner = connectionDb.createQueryRunner();
await queryRunner.connect(); await queryRunner.connect();
try { try {
@@ -38,55 +69,11 @@ export class SalesService {
pageNumber = 1; pageNumber = 1;
const offSet = (pageNumber - 1) * pageSize; const offSet = (pageNumber - 1) * pageSize;
const sqlProduto = `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.PRECOPROMOCIONAL_AVISTA as "salePromotion_cash",
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.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.LETRABASETINTOMETRICO as "letter",
esvlistaprodutos.LINHATINTOMETRICO as "line",
esvlistaprodutos.LITRAGEM as "can",
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 `;
if (filter && filter.text.length > 0) { if (filter && filter.text.length > 0) {
const description = filter.text.toUpperCase(); const description = filter.text.toUpperCase();
console.log('consultando por codigo de fabrica'); console.log('consultando por texto: ' + description);
// Fase 3: Query unificada - busca por CODFAB OU DESCRICAO em uma única query
let products = await queryRunner.manager let products = await queryRunner.manager
.getRepository(SalesProduct) .getRepository(SalesProduct)
.createQueryBuilder('esvlistaprodutos') .createQueryBuilder('esvlistaprodutos')
@@ -97,8 +84,6 @@ export class SalesService {
.addSelect("\"esvlistaprodutos\".CODFAB", "idProvider") .addSelect("\"esvlistaprodutos\".CODFAB", "idProvider")
.addSelect("\"esvlistaprodutos\".CODAUXILIAR", "ean") .addSelect("\"esvlistaprodutos\".CODAUXILIAR", "ean")
.addSelect("\"esvlistaprodutos\".TIPOPRODUTO", "productType") .addSelect("\"esvlistaprodutos\".TIPOPRODUTO", "productType")
.addSelect("\"esvlistaprodutos\".DADOSTECNICOS", "technicalData")
.addSelect("\"esvlistaprodutos\".INFORMACOESTECNICAS", "description")
.addSelect("\"esvlistaprodutos\".URLIMAGEM", "urlImage") .addSelect("\"esvlistaprodutos\".URLIMAGEM", "urlImage")
.addSelect("\"esvlistaprodutos\".NOMEMARCA", "brand") .addSelect("\"esvlistaprodutos\".NOMEMARCA", "brand")
.addSelect("\"esvlistaprodutos\".NOMEDEPARTAMENTO", "department") .addSelect("\"esvlistaprodutos\".NOMEDEPARTAMENTO", "department")
@@ -125,19 +110,19 @@ export class SalesService {
.addSelect("\"esvlistaprodutos\".PRODUTO_COM_REDUCAO_PRECO", "downPrice") .addSelect("\"esvlistaprodutos\".PRODUTO_COM_REDUCAO_PRECO", "downPrice")
.addSelect("\"esvlistaprodutos\".PRODUTO_EM_CAMPANHA", "compaing") .addSelect("\"esvlistaprodutos\".PRODUTO_EM_CAMPANHA", "compaing")
.addSelect("\"esvlistaprodutos\".BASETINTOMETRICO", "base") .addSelect("\"esvlistaprodutos\".BASETINTOMETRICO", "base")
.addSelect("\"esvlistaprodutos\".LETRATINTOMETRICO", "letter") .addSelect("\"esvlistaprodutos\".LETRABASETINTOMETRICO", "letter")
.addSelect("\"esvlistaprodutos\".LINHATINTOMETRICO", "line") .addSelect("\"esvlistaprodutos\".LINHATINTOMETRICO", "line")
.addSelect("\"esvlistaprodutos\".LITRAGEM", "can") .addSelect("\"esvlistaprodutos\".LITRAGEM", "can")
.addSelect("\"esvlistaprodutos\".QUANTIDADE_ESTOQUE_GERAL", "full_stock") .addSelect("\"esvlistaprodutos\".QUANTIDADE_ESTOQUE_GERAL", "full_stock")
.addSelect("\"esvlistaprodutos\".TEM_PRODUTO_SIMILAR", "similar") .addSelect("\"esvlistaprodutos\".TEM_PRODUTO_SIMILAR", "similar")
.addSelect("\"esvlistaprodutos\".TIPO_CAMPANHA", "type_campaing") .addSelect("\"esvlistaprodutos\".TIPO_CAMPANHA", "type_campaing")
.where("UPPER(\"esvlistaprodutos\".CODFAB) LIKE '%'||REPLACE(:description, '@', '%')||'%'", { description }) .where("(UPPER(\"esvlistaprodutos\".CODFAB) LIKE '%'||REPLACE(:description, '@', '%')||'%' OR UPPER(\"esvlistaprodutos\".descricao) LIKE '%'||REPLACE(:description, '@', '%')||'%')", { description })
.andWhere("(\"esvlistaprodutos\".codfilial = :codfilial OR :codfilial = '99')", { codfilial: store }) .andWhere("(\"esvlistaprodutos\".codfilial = :codfilial OR :codfilial = '99')", { codfilial: store })
.andWhere("(\"esvlistaprodutos\".produto_com_reducao_preco = :produtoComReducaoPreco OR :produtoComReducaoPreco = 'N')", .andWhere("(\"esvlistaprodutos\".produto_com_reducao_preco = :produtoComReducaoPreco OR :produtoComReducaoPreco = 'N')",
{ produtoComReducaoPreco: (filter.markdown) ? 'S' : 'N' }) { produtoComReducaoPreco: (filter.markdown) ? 'S' : 'N' })
.andWhere("(\"esvlistaprodutos\".produto_em_campanha = :campaign OR :campaign = 'N')", .andWhere("(\"esvlistaprodutos\".produto_em_campanha = :campaign OR :campaign = 'N')",
{ campaign: (filter.campaign) ? 'I' : 'N' }) { campaign: (filter.campaign) ? 'I' : 'N' })
.andWhere("(\"esvlistaprodutos\".produto_em_campanha = :oportunity OR :oportunity = 'N')", .andWhere("(\"esvlistaprodutos\".produto_oportunidade = :oportunity OR :oportunity = 'N')",
{ oportunity: (filter.oportunity) ? 'O' : 'N' }) { oportunity: (filter.oportunity) ? 'O' : 'N' })
.andWhere("(\"esvlistaprodutos\".produto_em_promocao = :produtoEmPromocao OR :produtoEmPromocao = 'N')", .andWhere("(\"esvlistaprodutos\".produto_em_promocao = :produtoEmPromocao OR :produtoEmPromocao = 'N')",
{ produtoEmPromocao: (filter.promotion) ? 'S' : 'N' }) { produtoEmPromocao: (filter.promotion) ? 'S' : 'N' })
@@ -145,69 +130,9 @@ export class SalesService {
.offset(offSet) .offset(offSet)
.orderBy("\"esvlistaprodutos\".DESCRICAO", "ASC") .orderBy("\"esvlistaprodutos\".DESCRICAO", "ASC")
.getRawMany(); .getRawMany();
if (products.length == 0) {
products = await queryRunner.manager
.getRepository(SalesProduct)
.createQueryBuilder('esvlistaprodutos')
.select("\"esvlistaprodutos\".CODPROD", "idProduct")
.addSelect("\"esvlistaprodutos\".SEQ", "seq")
.addSelect("\"esvlistaprodutos\".DESCRICAO", "smallDescription")
.addSelect("\"esvlistaprodutos\".NOMEECOMMERCE", "title")
.addSelect("\"esvlistaprodutos\".CODFAB", "idProvider")
.addSelect("\"esvlistaprodutos\".CODAUXILIAR", "ean")
.addSelect("\"esvlistaprodutos\".TIPOPRODUTO", "productType")
.addSelect("\"esvlistaprodutos\".DADOSTECNICOS", "technicalData")
.addSelect("\"esvlistaprodutos\".INFORMACOESTECNICAS", "description")
.addSelect("\"esvlistaprodutos\".URLIMAGEM", "urlImage")
.addSelect("\"esvlistaprodutos\".NOMEMARCA", "brand")
.addSelect("\"esvlistaprodutos\".NOMEDEPARTAMENTO", "department")
.addSelect("\"esvlistaprodutos\".NOMESECAO", "section")
.addSelect("\"esvlistaprodutos\".NOMECATEGORIA", "category")
.addSelect("\"esvlistaprodutos\".NOMEFORNECEDOR", "supplier")
.addSelect("\"esvlistaprodutos\".CODIGOFILIAL", "store")
.addSelect("\"esvlistaprodutos\".CLASSEVENDA", "saleAbc")
.addSelect("\"esvlistaprodutos\".CLASSEESTOQUE", "stockAbc")
.addSelect("\"esvlistaprodutos\".FORALINHA", "outLine")
.addSelect("\"esvlistaprodutos\".PRECOVENDA", "listPrice")
.addSelect("\"esvlistaprodutos\".PRECOPROMOCIONAL", "salePrice")
.addSelect("\"esvlistaprodutos\".PRECOPROMOCIONAL", "salePromotion")
.addSelect("\"esvlistaprodutos\".PRECOPROMOCIONAL_AVISTA", "salePromotion_cash")
.addSelect("\"esvlistaprodutos\".PERCENTUALDESCONTO", "offPercent")
.addSelect("\"esvlistaprodutos\".QTESTOQUE_DISPONIVEL", "stock")
.addSelect("\"esvlistaprodutos\".QTCAIXAS", "boxStock")
.addSelect("\"esvlistaprodutos\".ESTOQUE_DISP_LOJA", "store_stock")
.addSelect("\"esvlistaprodutos\".ESTOQUE_DISP_CAIXA_LOJA", "store_boxStock")
.addSelect("\"esvlistaprodutos\".MULTIPLO", "mutiple")
.addSelect("\"esvlistaprodutos\".UNIDADE", "unity")
.addSelect("\"esvlistaprodutos\".URLDEPARTAMENTO", "urlDepartment")
.addSelect("\"esvlistaprodutos\".URLSECAO", "urlSection")
.addSelect("\"esvlistaprodutos\".PRODUTO_COM_REDUCAO_PRECO", "downPrice")
.addSelect("\"esvlistaprodutos\".PRODUTO_EM_CAMPANHA", "compaing")
.addSelect("\"esvlistaprodutos\".BASETINTOMETRICO", "base")
.addSelect("\"esvlistaprodutos\".LETRATINTOMETRICO", "letter")
.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')",
{ produtoComReducaoPreco: (filter.markdown) ? 'S' : 'N' })
.andWhere("(\"esvlistaprodutos\".produto_em_campanha = :campaign OR :campaign = 'N')",
{ campaign: (filter.campaign) ? 'I' : 'N' })
.andWhere("(\"esvlistaprodutos\".produto_oportunidade = :oportunity OR :oportunity = 'N')",
{ oportunity: (filter.oportunity) ? 'O' : 'N' })
.andWhere("(\"esvlistaprodutos\".produto_em_promocao = :produtoEmPromocao OR :produtoEmPromocao = 'N')",
{ produtoEmPromocao: (filter.promotion) ? 'S' : 'N' })
.orderBy("\"esvlistaprodutos\".CLASSEVENDA")
.limit(pageSize)
.offset(offSet)
.orderBy("\"esvlistaprodutos\".DESCRICAO", "ASC")
.getRawMany();
}
products = this.createListImages(products); products = this.createListImages(products);
console.log(products.length + ' produtos'); console.log(products.length + ' produtos');
try { await this.redisClient.set(cacheKey, JSON.stringify(products), 'EX', 900); } catch (cacheErr) { console.error('Erro ao salvar cache GetProducts2:', cacheErr?.message || cacheErr); }
return products; return products;
} }
@@ -234,8 +159,6 @@ export class SalesService {
.addSelect("\"esvlistaprodutos\".CODFAB", "idProvider") .addSelect("\"esvlistaprodutos\".CODFAB", "idProvider")
.addSelect("\"esvlistaprodutos\".CODAUXILIAR", "ean") .addSelect("\"esvlistaprodutos\".CODAUXILIAR", "ean")
.addSelect("\"esvlistaprodutos\".TIPOPRODUTO", "productType") .addSelect("\"esvlistaprodutos\".TIPOPRODUTO", "productType")
.addSelect("\"esvlistaprodutos\".DADOSTECNICOS", "technicalData")
.addSelect("\"esvlistaprodutos\".INFORMACOESTECNICAS", "description")
.addSelect("\"esvlistaprodutos\".URLIMAGEM", "urlImage") .addSelect("\"esvlistaprodutos\".URLIMAGEM", "urlImage")
.addSelect("\"esvlistaprodutos\".NOMEMARCA", "brand") .addSelect("\"esvlistaprodutos\".NOMEMARCA", "brand")
.addSelect("\"esvlistaprodutos\".NOMEDEPARTAMENTO", "department") .addSelect("\"esvlistaprodutos\".NOMEDEPARTAMENTO", "department")
@@ -262,7 +185,7 @@ export class SalesService {
.addSelect("\"esvlistaprodutos\".PRODUTO_COM_REDUCAO_PRECO", "downPrice") .addSelect("\"esvlistaprodutos\".PRODUTO_COM_REDUCAO_PRECO", "downPrice")
.addSelect("\"esvlistaprodutos\".PRODUTO_EM_CAMPANHA", "compaing") .addSelect("\"esvlistaprodutos\".PRODUTO_EM_CAMPANHA", "compaing")
.addSelect("\"esvlistaprodutos\".BASETINTOMETRICO", "base") .addSelect("\"esvlistaprodutos\".BASETINTOMETRICO", "base")
.addSelect("\"esvlistaprodutos\".LETRATINTOMETRICO", "letter") .addSelect("\"esvlistaprodutos\".LETRABASETINTOMETRICO", "letter")
.addSelect("\"esvlistaprodutos\".LINHATINTOMETRICO", "line") .addSelect("\"esvlistaprodutos\".LINHATINTOMETRICO", "line")
.addSelect("\"esvlistaprodutos\".LITRAGEM", "can") .addSelect("\"esvlistaprodutos\".LITRAGEM", "can")
.addSelect("\"esvlistaprodutos\".QUANTIDADE_ESTOQUE_GERAL", "full_stock") .addSelect("\"esvlistaprodutos\".QUANTIDADE_ESTOQUE_GERAL", "full_stock")
@@ -285,6 +208,7 @@ export class SalesService {
.getRawMany(); .getRawMany();
products = this.createListImages(products); products = this.createListImages(products);
console.log(products.length + ' produtos'); console.log(products.length + ' produtos');
try { await this.redisClient.set(cacheKey, JSON.stringify(products), 'EX', 900); } catch (cacheErr) { console.error('Erro ao salvar cache GetProducts2:', cacheErr?.message || cacheErr); }
return products; return products;
} else { } else {
@@ -300,8 +224,6 @@ export class SalesService {
.addSelect("\"esvlistaprodutos\".CODFAB", "idProvider") .addSelect("\"esvlistaprodutos\".CODFAB", "idProvider")
.addSelect("\"esvlistaprodutos\".CODAUXILIAR", "ean") .addSelect("\"esvlistaprodutos\".CODAUXILIAR", "ean")
.addSelect("\"esvlistaprodutos\".TIPOPRODUTO", "productType") .addSelect("\"esvlistaprodutos\".TIPOPRODUTO", "productType")
.addSelect("\"esvlistaprodutos\".DADOSTECNICOS", "technicalData")
.addSelect("\"esvlistaprodutos\".INFORMACOESTECNICAS", "description")
.addSelect("\"esvlistaprodutos\".URLIMAGEM", "urlImage") .addSelect("\"esvlistaprodutos\".URLIMAGEM", "urlImage")
.addSelect("\"esvlistaprodutos\".NOMEMARCA", "brand") .addSelect("\"esvlistaprodutos\".NOMEMARCA", "brand")
.addSelect("\"esvlistaprodutos\".NOMEDEPARTAMENTO", "department") .addSelect("\"esvlistaprodutos\".NOMEDEPARTAMENTO", "department")
@@ -328,7 +250,7 @@ export class SalesService {
.addSelect("\"esvlistaprodutos\".PRODUTO_COM_REDUCAO_PRECO", "downPrice") .addSelect("\"esvlistaprodutos\".PRODUTO_COM_REDUCAO_PRECO", "downPrice")
.addSelect("\"esvlistaprodutos\".PRODUTO_EM_CAMPANHA", "compaing") .addSelect("\"esvlistaprodutos\".PRODUTO_EM_CAMPANHA", "compaing")
.addSelect("\"esvlistaprodutos\".BASETINTOMETRICO", "base") .addSelect("\"esvlistaprodutos\".BASETINTOMETRICO", "base")
.addSelect("\"esvlistaprodutos\".LETRATINTOMETRICO", "letter") .addSelect("\"esvlistaprodutos\".LETRABASETINTOMETRICO", "letter")
.addSelect("\"esvlistaprodutos\".LINHATINTOMETRICO", "line") .addSelect("\"esvlistaprodutos\".LINHATINTOMETRICO", "line")
.addSelect("\"esvlistaprodutos\".LITRAGEM", "can") .addSelect("\"esvlistaprodutos\".LITRAGEM", "can")
.addSelect("\"esvlistaprodutos\".QUANTIDADE_ESTOQUE_GERAL", "full_stock") .addSelect("\"esvlistaprodutos\".QUANTIDADE_ESTOQUE_GERAL", "full_stock")
@@ -349,6 +271,7 @@ export class SalesService {
.getRawMany(); .getRawMany();
products = this.createListImages(products); products = this.createListImages(products);
console.log(products.length + ' produtos'); console.log(products.length + ' produtos');
try { await this.redisClient.set(cacheKey, JSON.stringify(products), 'EX', 900); } catch (cacheErr) { console.error('Erro ao salvar cache GetProducts2:', cacheErr?.message || cacheErr); }
return products; return products;
} }
@@ -357,7 +280,15 @@ export class SalesService {
throw error; throw error;
} finally { } finally {
await queryRunner.release(); await queryRunner.release();
await connectionDb.close(); // Não fecha a conexão - reutilizada pelo pool
try {
const currentLockValue = await this.redisClient.get(lockKey);
if (currentLockValue === lockValue.toString()) {
await this.redisClient.del(lockKey);
}
} catch (lockErr) {
console.error('Erro ao liberar lock Redis (GetProducts2):', lockErr?.message || lockErr);
}
} }
} }
@@ -957,6 +888,9 @@ export class SalesService {
FROM ESVESTOQUEVENDA, PCFILIAL FROM ESVESTOQUEVENDA, PCFILIAL
WHERE ESVESTOQUEVENDA.CODPROD = ${id} WHERE ESVESTOQUEVENDA.CODPROD = ${id}
AND ESVESTOQUEVENDA.CODFILIAL = PCFILIAL.CODIGO AND ESVESTOQUEVENDA.CODFILIAL = PCFILIAL.CODIGO
AND EXISTS(SELECT 1 FROM PCFILIALRETIRA R
WHERE R.CODFILIALVENDA = '${storeId}'
AND R.CODFILIALRETIRA = ESVESTOQUEVENDA.CODFILIAL)
ORDER BY TO_NUMBER(ESVESTOQUEVENDA.CODFILIAL) `; ORDER BY TO_NUMBER(ESVESTOQUEVENDA.CODFILIAL) `;
const stock = await queryRunner.query(sql); const stock = await queryRunner.query(sql);
@@ -1111,17 +1045,18 @@ export class SalesService {
} }
createListImages(products: SalesProduct[]): SalesProduct[] { createListImages(products: SalesProduct[]): SalesProduct[] {
products.forEach(product => { for (let i = 0; i < products.length; i++) {
const product = products[i];
product.images = []; product.images = [];
if (product.urlImage != null) { if (product.urlImage != null && product.urlImage.length > 0) {
let urlImage = product.urlImage; product.images = product.urlImage
if (urlImage.indexOf(";") == -1) { .split(';')
urlImage += ";"; .map(img => img.trim())
} .filter(img => img.length > 0);
const images = product.urlImage.split(";");
product.images = images.map(i => i.trim());
} }
}); // Adiciona thumbnail para acesso rápido no frontend
(product as any).thumbnail = product.images.length > 0 ? product.images[0] : null;
}
return products; return products;
} }
@@ -1412,8 +1347,7 @@ export class SalesService {
const skipReg = ((pageNumber - 1) * pageSize); const skipReg = ((pageNumber - 1) * pageSize);
const pagination = ` OFFSET ${skipReg} ROWS FETCH NEXT ${pageSize} ROWS ONLY`; const pagination = ` OFFSET ${skipReg} ROWS FETCH NEXT ${pageSize} ROWS ONLY`;
const connectionDb = new Connection(connectionOptions); const connectionDb = getConnection();
await connectionDb.connect();
const queryRunner = connectionDb.createQueryRunner(); const queryRunner = connectionDb.createQueryRunner();
await queryRunner.connect(); await queryRunner.connect();
@@ -1422,7 +1356,7 @@ export class SalesService {
products = this.createListImages(products); products = this.createListImages(products);
console.log("Total de produtos: " + products.length); console.log("Total de produtos: " + products.length);
await this.redisClient.set(cacheKey, JSON.stringify(products), 'EX', 3600); await this.redisClient.set(cacheKey, JSON.stringify(products), 'EX', 900);
return products; return products;
} catch (err) { } catch (err) {
@@ -1430,7 +1364,7 @@ export class SalesService {
throw err; throw err;
} finally { } finally {
await queryRunner.release(); await queryRunner.release();
await connectionDb.close(); // Não fecha a conexão - reutilizada pelo pool
} }
} }
@@ -1448,7 +1382,7 @@ export class SalesService {
const queryRunner = connectionDb.createQueryRunner(); const queryRunner = connectionDb.createQueryRunner();
await queryRunner.connect(); await queryRunner.connect();
try { try {
const sql = 'SELECT ESVCALCULOFRETE.CODTABELAFRETE as "id" ' + /*const sql = 'SELECT ESVCALCULOFRETE.CODTABELAFRETE as "id" ' +
' ,ESVCALCULOFRETE.CODFILIAL as "store" ' + ' ,ESVCALCULOFRETE.CODFILIAL as "store" ' +
' ,ESVCALCULOFRETE.CODCIDADE as "cityId" ' + ' ,ESVCALCULOFRETE.CODCIDADE as "cityId" ' +
' ,PCCIDADE.NOMECIDADE as "cityName" ' + ' ,PCCIDADE.NOMECIDADE as "cityName" ' +
@@ -1462,7 +1396,22 @@ export class SalesService {
' AND ESVCALCULOFRETE.CODCIDADE = PCCIDADE.CODCIDADE ' + ' AND ESVCALCULOFRETE.CODCIDADE = PCCIDADE.CODCIDADE ' +
' AND ESVCALCULOFRETE.CODCIDADE = :1 ' + ' AND ESVCALCULOFRETE.CODCIDADE = :1 ' +
' AND ESVCALCULOFRETE.IDCART = :2 ' + ' AND ESVCALCULOFRETE.IDCART = :2 ' +
' ORDER BY VLFRETE'; ' ORDER BY VLFRETE';*/
const sql = `SELECT 0 as "id"
,'1' as "store"
,ESVCALCULOFRETE.CODCIDADE as "cityId"
,PCCIDADE.NOMECIDADE as "cityName"
,NULL as "carrierId"
,'SIMPLIFIQUE HOMECENTER' as "carrierName"
,0 as "minSale"
,ESVCALCULOFRETE.VLFRETE as "deliveryValue"
,NULL as "deliveryTime"
FROM ESVCALCULOFRETE, PCCIDADE
WHERE ESVCALCULOFRETE.CODCIDADE = PCCIDADE.CODCIDADE
AND ESVCALCULOFRETE.CODCIDADE = :1
AND ESVCALCULOFRETE.IDCART = :2
ORDER BY VLFRETE`;
const deliveryTaxTable = await queryRunner.manager const deliveryTaxTable = await queryRunner.manager
.query(sql, [cityId, cartId]); .query(sql, [cityId, cartId]);
@@ -1506,7 +1455,7 @@ export class SalesService {
await this.updatePriorityDelivery(dataDeliveryTax.cartId, dataDeliveryTax.priorityDelivery); await this.updatePriorityDelivery(dataDeliveryTax.cartId, dataDeliveryTax.priorityDelivery);
if (cityId == 0) { if (cityId == 0) {
cityId = Number.parseInt(dataDeliveryTax.ibgeCode); cityId = Number.parseInt(dataDeliveryTax.ibgeCode ?? dataDeliveryTax.cityId);
// throw new HttpException('Cidade não localiza para cálculo da taxa de entrega', HttpStatus.BAD_REQUEST); // throw new HttpException('Cidade não localiza para cálculo da taxa de entrega', HttpStatus.BAD_REQUEST);
} }
const connectionDb = new Connection(connectionOptions); const connectionDb = new Connection(connectionOptions);
@@ -1514,7 +1463,22 @@ export class SalesService {
const queryRunner = connectionDb.createQueryRunner(); const queryRunner = connectionDb.createQueryRunner();
await queryRunner.connect(); await queryRunner.connect();
try { try {
const sql = 'SELECT ESVCALCULOFRETE.CODTABELAFRETE as "id" ' + const sql = `SELECT 0 as "id"
,'1' as "store"
,ESVCALCULOFRETE.CODCIDADE as "cityId"
,PCCIDADE.NOMECIDADE as "cityName"
,NULL as "carrierId"
,'SIMPLIFIQUE HOMECENTER' as "carrierName"
,0 as "minSale"
,ESVCALCULOFRETE.VLFRETE as "deliveryValue"
,NULL as "deliveryTime"
FROM ESVCALCULOFRETE, PCCIDADE
WHERE ESVCALCULOFRETE.CODCIDADE = PCCIDADE.CODCIDADE
AND ESVCALCULOFRETE.CODCIDADE = :1
AND ESVCALCULOFRETE.IDCART = :2
ORDER BY VLFRETE`;
/*const sql = 'SELECT ESVCALCULOFRETE.CODTABELAFRETE as "id" ' +
' ,ESVCALCULOFRETE.CODFILIAL as "store" ' + ' ,ESVCALCULOFRETE.CODFILIAL as "store" ' +
' ,ESVCALCULOFRETE.CODCIDADE as "cityId" ' + ' ,ESVCALCULOFRETE.CODCIDADE as "cityId" ' +
' ,PCCIDADE.NOMECIDADE as "cityName" ' + ' ,PCCIDADE.NOMECIDADE as "cityName" ' +
@@ -1528,7 +1492,7 @@ export class SalesService {
' AND ESVCALCULOFRETE.CODCIDADE = PCCIDADE.CODCIDADE ' + ' AND ESVCALCULOFRETE.CODCIDADE = PCCIDADE.CODCIDADE ' +
' AND ESVCALCULOFRETE.CODCIDADE = :1 ' + ' AND ESVCALCULOFRETE.CODCIDADE = :1 ' +
' AND ESVCALCULOFRETE.IDCART = :2 ' + ' AND ESVCALCULOFRETE.IDCART = :2 ' +
' ORDER BY VLFRETE'; ' ORDER BY VLFRETE';*/
let deliveryTaxTable = await queryRunner.manager let deliveryTaxTable = await queryRunner.manager
.query(sql, [dataDeliveryTax.cityId, dataDeliveryTax.cartId]); .query(sql, [dataDeliveryTax.cityId, dataDeliveryTax.cartId]);
@@ -1583,7 +1547,7 @@ export class SalesService {
// 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 timeDays = await queryRunner.query(sql);
const sqlRetiraPosterior = `SELECT ( PROXIMO_DIA_UTIL(TO_DATE('${saleDate}', 'DD-MM-YYYY'), '4') - TRUNC(SYSDATE) ) AS "days" FROM DUAL`; const sqlRetiraPosterior = `SELECT ( PROXIMO_DIA_UTIL(TO_DATE('${saleDate}', 'DD-MM-YYYY'), '1') - TRUNC(SYSDATE) ) AS "days" FROM DUAL`;
const timeDaysRetiraPosterior = await queryRunner.query(sqlRetiraPosterior); const timeDaysRetiraPosterior = await queryRunner.query(sqlRetiraPosterior);
return { deliveryDays: timeDays[0].days, retiraPosteriorDays: timeDaysRetiraPosterior[0].days }; return { deliveryDays: timeDays[0].days, retiraPosteriorDays: timeDaysRetiraPosterior[0].days };

View File

@@ -6,15 +6,16 @@ import { OrderDiscount } from 'src/domain/models/order-discount.model';
import { OrderTaxDelivery } from 'src/domain/models/order-taxdelivery.model'; import { OrderTaxDelivery } from 'src/domain/models/order-taxdelivery.model';
import { LogOrder } from 'src/domain/models/log-order.model'; import { LogOrder } from 'src/domain/models/log-order.model';
import { ApiTags } from '@nestjs/swagger'; import { ApiTags } from '@nestjs/swagger';
import { Cart } from 'src/domain/models/cart.model';
@ApiTags('Shopping') @ApiTags('Shopping')
@Controller('api/v1/shopping') @Controller('api/v1/shopping')
export class ShoppingController { export class ShoppingController {
constructor(private shoppingService: ShoppingService){} constructor(private shoppingService: ShoppingService) { }
@Get('cart/:id') @Get('cart/:id')
async getCart(@Param('id') id: string){ async getCart(@Param('id') id: string) {
try { try {
const cart = await this.shoppingService.GetItensCart(id); const cart = await this.shoppingService.GetItensCart(id);
if (cart == null || cart.length == 0) if (cart == null || cart.length == 0)
@@ -27,10 +28,10 @@ export class ShoppingController {
} }
@Get(':id') @Get(':id')
async getPreVenda(@Param('id') id: string ){ async getPreVenda(@Param('id') id: string) {
try { try {
const cart = await this.shoppingService.getShopping(id); const cart = await this.shoppingService.getShopping(id);
if (cart == null ) if (cart == null)
throw new HttpException("Carrinho de compras não encontrado", HttpStatus.NOT_FOUND); throw new HttpException("Carrinho de compras não encontrado", HttpStatus.NOT_FOUND);
return cart; return cart;
} catch (error) { } catch (error) {
@@ -39,15 +40,24 @@ export class ShoppingController {
} }
} }
@Put('cart')
async updateCart(@Body() cart: Cart) {
try {
return await this.shoppingService.updateShopping(cart);
} catch (error) {
throw new HttpException(error.message, HttpStatus.BAD_REQUEST);
}
}
@Get('cart/:idcart/item/:idProduct/tipoentrega/:deliveryType') @Get('cart/:idcart/item/:idProduct/tipoentrega/:deliveryType')
async getItemCart(@Req() request, @Param('idCart') idCart: string, async getItemCart(@Req() request, @Param('idCart') idCart: string,
@Param('idProduct') idProduct: string, @Param('deliveryType') deliveryType: string){ @Param('idProduct') idProduct: string, @Param('deliveryType') deliveryType: string) {
let store = '99'; let store = '99';
try { try {
if (request.headers['x-store']) if (request.headers['x-store'])
store = request.headers['x-store']; store = request.headers['x-store'];
const cart = await this.shoppingService.getItemCart(idCart, idProduct, store, deliveryType); const cart = await this.shoppingService.getItemCart(idCart, idProduct, store, deliveryType);
if (cart == null ) if (cart == null)
throw new HttpException("Item não foi encontrado no carrinho de compras.", HttpStatus.NOT_FOUND); throw new HttpException("Item não foi encontrado no carrinho de compras.", HttpStatus.NOT_FOUND);
return cart; return cart;
} catch (error) { } catch (error) {
@@ -57,8 +67,8 @@ export class ShoppingController {
} }
@Get('cart/lot/:productId/:customerId') @Get('cart/lot/:productId/:customerId')
async getLotProduct( @Req() request, @Param('productId') productId: number, async getLotProduct(@Req() request, @Param('productId') productId: number,
@Param('customerId') customerId: number ) { @Param('customerId') customerId: number) {
let store = '99'; let store = '99';
try { try {
if (request.headers['x-store']) if (request.headers['x-store'])
@@ -73,7 +83,7 @@ export class ShoppingController {
@Post('item') @Post('item')
async createItemShopping(@Body() item: ShoppingItem){ async createItemShopping(@Body() item: ShoppingItem) {
console.log('createItemShopping') console.log('createItemShopping')
try { try {
return await this.shoppingService.createItemCart(item); return await this.shoppingService.createItemCart(item);
@@ -83,7 +93,7 @@ export class ShoppingController {
} }
@Post('log') @Post('log')
async logOrderShopping(@Body() logOrder: LogOrder){ async logOrderShopping(@Body() logOrder: LogOrder) {
try { try {
console.log('logOrderShopping') console.log('logOrderShopping')
return await this.shoppingService.createLogShopping(logOrder); return await this.shoppingService.createLogShopping(logOrder);
@@ -93,10 +103,10 @@ export class ShoppingController {
} }
@Put('item') @Put('item')
async updateQuantityItem(@Body() item: ShoppingItem){ async updateQuantityItem(@Body() item: ShoppingItem) {
console.log(item); console.log(item);
try { try {
if (item.id == null){ if (item.id == null) {
throw new HttpException('Item sem Id informado, faça a inclusão do item no carrinho.', HttpStatus.BAD_REQUEST); throw new HttpException('Item sem Id informado, faça a inclusão do item no carrinho.', HttpStatus.BAD_REQUEST);
} }
const itemCreate = await this.shoppingService.updateItem(item); const itemCreate = await this.shoppingService.updateItem(item);
@@ -107,10 +117,10 @@ export class ShoppingController {
} }
@Put('item/discount') @Put('item/discount')
async updatePriceItem(@Body() item: ShoppingItem){ async updatePriceItem(@Body() item: ShoppingItem) {
console.log(item); console.log(item);
try { try {
if (item.id == null){ if (item.id == null) {
throw new HttpException('Item sem Id informado, faça a inclusão do item no carrinho.', HttpStatus.BAD_REQUEST); throw new HttpException('Item sem Id informado, faça a inclusão do item no carrinho.', HttpStatus.BAD_REQUEST);
} }
const itemCreate = await this.shoppingService.updatePrice(item); const itemCreate = await this.shoppingService.updatePrice(item);
@@ -142,7 +152,7 @@ export class ShoppingController {
} }
@Delete('item/delete/:id') @Delete('item/delete/:id')
async deleteItem(@Param('id') id: string){ async deleteItem(@Param('id') id: string) {
try { try {
await this.shoppingService.deleteItem(id); await this.shoppingService.deleteItem(id);
return new ResultModel(true, 'Item excluído com sucesso!', id, null,); return new ResultModel(true, 'Item excluído com sucesso!', id, null,);
@@ -165,4 +175,4 @@ export class ShoppingController {
} }
} }

View File

@@ -8,6 +8,7 @@ import { Shopping } from 'src/domain/entity/tables/estprevendac.entity';
import { OrderTaxDelivery } from 'src/domain/models/order-taxdelivery.model'; import { OrderTaxDelivery } from 'src/domain/models/order-taxdelivery.model';
import { connectionOptions } from 'src/configs/typeorm.config'; import { connectionOptions } from 'src/configs/typeorm.config';
import { LogOrder } from 'src/domain/models/log-order.model'; import { LogOrder } from 'src/domain/models/log-order.model';
import { Cart } from 'src/domain/models/cart.model';
@Injectable() @Injectable()
export class ShoppingService { export class ShoppingService {
@@ -167,7 +168,7 @@ export class ShoppingService {
AND E.CODFILIAL = '${itemShopping.stockStore}'`); AND E.CODFILIAL = '${itemShopping.stockStore}'`);
let quantityStock = 0; let quantityStock = 0;
if ( dataStockItem.length > 0 ) { if (dataStockItem.length > 0) {
quantityStock = dataStockItem[0].quantityStock; quantityStock = dataStockItem[0].quantityStock;
} }
@@ -605,6 +606,39 @@ export class ShoppingService {
} }
} }
async updateShopping(shopping: any) {
const connection = new Connection(connectionOptions);
await connection.connect();
const queryRunner = connection.createQueryRunner();
await queryRunner.connect();
try {
console.log(JSON.stringify(shopping));
const sql = `UPDATE ESTPREVENDAC
SET ESTPREVENDAC.CODCLI = :codcli
,ESTPREVENDAC.codendentcli = :codendentcli
,ESTPREVENDAC.codplpag = :codplpag
,ESTPREVENDAC.codcob = :codcob
,ESTPREVENDAC.codfilial = :codfilial
WHERE ID = :id `;
await queryRunner.query(sql, [
shopping.codcli,
shopping.codendentcli,
shopping.codplpag,
shopping.codcob,
shopping.saleStore,
shopping.id
]);
return shopping;
} catch (error) {
throw error;
} finally {
await queryRunner.release();
await connection.close();
}
}
async updatePriceShopping(idCart: string, idPaymentPlan: number) { async updatePriceShopping(idCart: string, idPaymentPlan: number) {
const connection = new Connection(connectionOptions); const connection = new Connection(connectionOptions);
await connection.connect(); await connection.connect();