Compare commits
62 Commits
34793295c9
..
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 636daca703 | |||
| 9bf294a1f3 | |||
| 839f6de691 | |||
| 826041b07a | |||
| f87e5b9d8e | |||
| 652177862d | |||
| ac2e7f5dab | |||
| f94a108948 | |||
| d51b677f26 | |||
| 9170d8cd5a | |||
| 5f70b95589 | |||
| d2bd576277 | |||
| 23bfe1ecbe | |||
| 47a27fb54f | |||
| f61100bf25 | |||
| 25e589551b | |||
| 5ce560ce97 | |||
| b2d8fdc8a0 | |||
| c11166b365 | |||
| 7ae027633b | |||
| a975f9d02a | |||
| cd3492d625 | |||
| 816c5ebb50 | |||
| 4836ee4d01 | |||
| ea6f1bfdd0 | |||
| b53b7d3ed3 | |||
| 6f65123816 | |||
| 2c97b7302d | |||
| 2dc9480170 | |||
| 9aa12184a1 | |||
| 1d47fb1a1d | |||
| fc27b9d616 | |||
| 98099e97e7 | |||
| d526f6ed2c | |||
| 62b659246f | |||
| c5c522f69c | |||
| 758bb03a26 | |||
| 23ae3556de | |||
| 12b11cc238 | |||
| 2d13a8bd9c | |||
| 2a2c020627 | |||
| ba3c544ff8 | |||
| 5baf5bfea6 | |||
| 83e7c26133 | |||
| 1b26c515c0 | |||
| 2a4e778c31 | |||
| 5e6bd33cdd | |||
| 9a76880b1d | |||
| c53eb2dba3 | |||
| 578e445917 | |||
| a1e8f40417 | |||
| afa83895a2 | |||
| 4e61ff618e | |||
| fbe7230865 | |||
| 658496320b | |||
| 4af07fe3e8 | |||
| 6a48f203a9 | |||
| a486127ade | |||
| ad470d2166 | |||
| a68a7f594d | |||
| 58a7c359d8 | |||
| dee96b6e91 |
@@ -16,6 +16,11 @@ PORT="5002"
|
|||||||
DB_ROOT_PASSWORD="root_password"
|
DB_ROOT_PASSWORD="root_password"
|
||||||
NODE_ENV="production"
|
NODE_ENV="production"
|
||||||
|
|
||||||
|
REDIS_HOST="redis"
|
||||||
|
REDIS_PORT="6379"
|
||||||
|
REDIS_DB="0"
|
||||||
|
REDIS_PASSWORD=""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ARVANCLOUD_ENDPOINT=https://s3.ir-thr-at1.arvanstorage.com
|
ARVANCLOUD_ENDPOINT=https://s3.ir-thr-at1.arvanstorage.com
|
||||||
|
|||||||
Vendored
+11
-3
@@ -11,13 +11,21 @@
|
|||||||
"[typescript]": {
|
"[typescript]": {
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
},
|
},
|
||||||
"editor.formatOnSave": true,
|
|
||||||
"cSpell.words": [
|
"cSpell.words": [
|
||||||
"ARVANCLOUD",
|
"ARVANCLOUD",
|
||||||
"autoincrement",
|
"autoincrement",
|
||||||
"Cardex",
|
"Cardex",
|
||||||
|
"consfee",
|
||||||
"fkey",
|
"fkey",
|
||||||
"iban",
|
"iban",
|
||||||
"MAYKET"
|
"indatim",
|
||||||
]
|
"inno",
|
||||||
|
"inty",
|
||||||
|
"irtaxid",
|
||||||
|
"MAYKET",
|
||||||
|
"setm",
|
||||||
|
"spro",
|
||||||
|
"sstid"
|
||||||
|
],
|
||||||
|
"editor.formatOnSave": true
|
||||||
}
|
}
|
||||||
|
|||||||
+63
@@ -0,0 +1,63 @@
|
|||||||
|
# AI Agent Specification
|
||||||
|
|
||||||
|
## Identity
|
||||||
|
- Name: `consumer_api_agent`
|
||||||
|
- Purpose: Assist with development, refactoring, migration, debugging, and data-safe operations for this repository.
|
||||||
|
- Scope: Entire project rooted at `consumer_api`.
|
||||||
|
|
||||||
|
## Core Responsibilities
|
||||||
|
- Implement and refactor backend features in NestJS modules.
|
||||||
|
- Keep Prisma schema/migrations consistent and safe.
|
||||||
|
- Preserve API behavior unless explicitly asked to change it.
|
||||||
|
- Prefer minimal, focused changes over broad rewrites.
|
||||||
|
|
||||||
|
## Working Rules
|
||||||
|
- Follow repository instructions in `AGENTS.md`.
|
||||||
|
- Respect existing project conventions (naming, DTO patterns, response mapping).
|
||||||
|
- Do not revert unrelated user changes.
|
||||||
|
- Do not run destructive DB commands unless explicitly requested.
|
||||||
|
- For risky DB operations, perform backup-first workflow.
|
||||||
|
|
||||||
|
## Code Standards
|
||||||
|
- Keep functions small and cohesive.
|
||||||
|
- Extract reusable logic to utilities/services when complexity grows.
|
||||||
|
- Validate DTO inputs at boundaries.
|
||||||
|
- Use typed response DTO aliases where possible.
|
||||||
|
- Keep Prisma queries explicit with `select` for response control.
|
||||||
|
|
||||||
|
## Database Safety
|
||||||
|
- Never run `prisma migrate reset` on important environments unless explicitly approved.
|
||||||
|
- Treat applied migration files as immutable history.
|
||||||
|
- Prefer forward-only migrations.
|
||||||
|
- For data updates:
|
||||||
|
- Use transactions.
|
||||||
|
- Verify row counts before/after.
|
||||||
|
- Keep operations idempotent when feasible.
|
||||||
|
|
||||||
|
## API Patterns
|
||||||
|
- List endpoints: paginate + summary payload.
|
||||||
|
- Detail endpoints: full resource shape.
|
||||||
|
- Enum presentation: use shared translator utility (`translateEnumValue`).
|
||||||
|
- Fiscal status fallback rule: if no fiscal record, return `NOT_SEND`.
|
||||||
|
|
||||||
|
## Execution Checklist
|
||||||
|
1. Read target module/controller/service/DTO before edits.
|
||||||
|
2. Apply minimal patch.
|
||||||
|
3. Run typecheck (`pnpm -s tsc --noEmit`).
|
||||||
|
4. If data logic changed, verify behavior with targeted checks.
|
||||||
|
5. Summarize changed files and behavior impact.
|
||||||
|
|
||||||
|
## Useful Commands
|
||||||
|
- Type check:
|
||||||
|
- `pnpm -s tsc --noEmit`
|
||||||
|
- Prisma migration status:
|
||||||
|
- `pnpm prisma migrate status`
|
||||||
|
- Create migration:
|
||||||
|
- `pnpm prisma migrate dev --name <name>`
|
||||||
|
- Apply production migrations:
|
||||||
|
- `pnpm prisma migrate deploy`
|
||||||
|
|
||||||
|
## Communication Style
|
||||||
|
- Be concise, direct, and implementation-focused.
|
||||||
|
- Call out assumptions and risky steps before execution.
|
||||||
|
- Provide concrete next actions after each completed task.
|
||||||
@@ -0,0 +1,182 @@
|
|||||||
|
# AGENTS.md
|
||||||
|
|
||||||
|
## Stack
|
||||||
|
|
||||||
|
- NestJS
|
||||||
|
- Prisma
|
||||||
|
- TypeScript
|
||||||
|
- pnpm
|
||||||
|
- RTK enabled
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Core Rules
|
||||||
|
|
||||||
|
- Keep changes minimal.
|
||||||
|
- Do not touch unrelated files.
|
||||||
|
- Prefer existing patterns over new abstractions.
|
||||||
|
- Preserve API behavior unless requested otherwise.
|
||||||
|
- Prefer forward Prisma migrations.
|
||||||
|
- Never edit applied migrations in shared environments.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# EXECUTION RULES
|
||||||
|
|
||||||
|
- Keep responses short.
|
||||||
|
- Do not narrate thoughts.
|
||||||
|
- Do not explain obvious steps.
|
||||||
|
- Do not create plans for simple tasks.
|
||||||
|
- Prefer implementation over exploration.
|
||||||
|
|
||||||
|
Avoid:
|
||||||
|
|
||||||
|
- “I think…”
|
||||||
|
- “Let me check…”
|
||||||
|
- “I should inspect…”
|
||||||
|
- “I’m going to…”
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# RTK Rules
|
||||||
|
|
||||||
|
Always prefer RTK commands.
|
||||||
|
|
||||||
|
Use:
|
||||||
|
|
||||||
|
- `rtk ls`
|
||||||
|
- `rtk grep`
|
||||||
|
- `rtk smart`
|
||||||
|
- `rtk read`
|
||||||
|
- `rtk git diff`
|
||||||
|
- `rtk git status`
|
||||||
|
|
||||||
|
Avoid raw:
|
||||||
|
|
||||||
|
- `cat`
|
||||||
|
- `grep`
|
||||||
|
- `rg`
|
||||||
|
- `git diff`
|
||||||
|
- recursive repository scans
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Reading Strategy
|
||||||
|
|
||||||
|
1. `rtk grep`
|
||||||
|
2. `rtk smart`
|
||||||
|
3. `rtk read`
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
- Read only necessary files.
|
||||||
|
- Do not read sibling files unless needed.
|
||||||
|
- Do not reread unchanged files.
|
||||||
|
- Stop searching once target location is found.
|
||||||
|
- Edit quickly after locating target.
|
||||||
|
|
||||||
|
Avoid:
|
||||||
|
|
||||||
|
- opening entire modules
|
||||||
|
- multi-file chained reads
|
||||||
|
- large diff dumps
|
||||||
|
- exploratory scans
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Forbidden Paths
|
||||||
|
|
||||||
|
Do not inspect unless required:
|
||||||
|
|
||||||
|
- `node_modules/`
|
||||||
|
- `dist/`
|
||||||
|
- `coverage/`
|
||||||
|
- `.prisma/`
|
||||||
|
- `prisma/migrations/`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Prisma Rules
|
||||||
|
|
||||||
|
- Use transactions for multi-step writes.
|
||||||
|
- Prefer explicit `select/include`.
|
||||||
|
- Normalize `Decimal` values with `Number(...)`.
|
||||||
|
- Keep migrations forward-safe.
|
||||||
|
- Use:
|
||||||
|
- `pnpm prisma migrate dev --name <name>` for new local migrations
|
||||||
|
- `pnpm prisma migrate deploy` for applying existing migrations
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# NestJS Rules
|
||||||
|
|
||||||
|
- Keep layering:
|
||||||
|
- controller
|
||||||
|
- service
|
||||||
|
- prisma/shared service
|
||||||
|
|
||||||
|
- Reuse shared services.
|
||||||
|
- Keep DTO validation strict.
|
||||||
|
- Avoid `any`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Validation
|
||||||
|
|
||||||
|
Typecheck before handoff:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm -s tsc --noEmit
|
||||||
|
```
|
||||||
|
|
||||||
|
# INVESTIGATION LIMITS
|
||||||
|
|
||||||
|
For localized fixes:
|
||||||
|
|
||||||
|
- maximum 3 file reads before first edit
|
||||||
|
- maximum 1 related-file read unless required
|
||||||
|
- maximum 5 total file reads before implementation
|
||||||
|
|
||||||
|
Stop searching once the target service, controller, DTO, schema, or repository method is identified.
|
||||||
|
|
||||||
|
# TARGETED READ RULES
|
||||||
|
|
||||||
|
Do not read files larger than 300 lines unless required.
|
||||||
|
|
||||||
|
For known symbols:
|
||||||
|
|
||||||
|
1. rtk grep
|
||||||
|
2. rtk smart
|
||||||
|
3. read only the relevant section
|
||||||
|
|
||||||
|
Avoid opening entire services, modules, or controllers for localized changes.
|
||||||
|
|
||||||
|
Prefer symbol-level inspection.
|
||||||
|
|
||||||
|
# REVIEW MODE
|
||||||
|
|
||||||
|
During reviews:
|
||||||
|
|
||||||
|
- inspect changed files only
|
||||||
|
- avoid repository-wide searches
|
||||||
|
- avoid architecture exploration
|
||||||
|
- avoid reading unrelated modules
|
||||||
|
|
||||||
|
Review only code affected by the diff.
|
||||||
|
|
||||||
|
# HARD TOKEN LIMITS
|
||||||
|
|
||||||
|
For localized fixes:
|
||||||
|
|
||||||
|
- Never read more than 5 files before the first edit.
|
||||||
|
- Never read a file larger than 300 lines unless the target symbol cannot be isolated.
|
||||||
|
- Never open an entire service, controller, or module when a symbol-level read is possible.
|
||||||
|
- Never reread a file already summarized by `rtk smart` unless implementation details are required.
|
||||||
|
|
||||||
|
When a file exceeds 300 lines:
|
||||||
|
|
||||||
|
1. rtk grep
|
||||||
|
2. rtk smart
|
||||||
|
3. read only the required section
|
||||||
|
|
||||||
|
Avoid full-file reads.
|
||||||
+21
-25
@@ -1,48 +1,44 @@
|
|||||||
FROM node:22-slim AS deps
|
FROM node:22-slim AS base
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
ARG NPM_REGISTRY=https://registry.npmjs.org/
|
ARG NPM_REGISTRY=https://hub.megan.ir/npm/
|
||||||
ENV NPM_CONFIG_REGISTRY=${NPM_REGISTRY}
|
ENV NPM_CONFIG_REGISTRY=${NPM_REGISTRY}
|
||||||
ENV npm_config_registry=${NPM_REGISTRY}
|
ENV npm_config_registry=${NPM_REGISTRY}
|
||||||
|
ENV PNPM_HOME="/pnpm"
|
||||||
|
ENV PNPM_STORE_DIR="/pnpm/store"
|
||||||
|
ENV PATH="${PNPM_HOME}:${PATH}"
|
||||||
|
ENV COREPACK_NPM_REGISTRY=${NPM_REGISTRY}
|
||||||
|
ARG PNPM_VERSION=10.17.1
|
||||||
|
|
||||||
RUN corepack enable
|
RUN npm config set registry ${NPM_REGISTRY} \
|
||||||
RUN npm config set registry ${NPM_REGISTRY}
|
&& npm install -g pnpm@${PNPM_VERSION}
|
||||||
|
|
||||||
|
FROM base AS build
|
||||||
|
|
||||||
COPY package.json pnpm-lock.yaml ./
|
COPY package.json pnpm-lock.yaml ./
|
||||||
RUN pnpm install --frozen-lockfile
|
RUN --mount=type=cache,id=pnpm-store-build,sharing=locked,target=/pnpm/store \
|
||||||
|
pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
|
||||||
FROM node:22-slim AS build
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
ARG NPM_REGISTRY=https://registry.npmjs.org/
|
|
||||||
ENV NPM_CONFIG_REGISTRY=${NPM_REGISTRY}
|
|
||||||
ENV npm_config_registry=${NPM_REGISTRY}
|
|
||||||
|
|
||||||
RUN corepack enable
|
|
||||||
RUN npm config set registry ${NPM_REGISTRY}
|
|
||||||
|
|
||||||
COPY --from=deps /app/node_modules ./node_modules
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
ENV PRISMA_CLIENT_ENGINE_TYPE=binary
|
ENV PRISMA_CLIENT_ENGINE_TYPE=binary
|
||||||
|
RUN pnpm run build
|
||||||
|
|
||||||
RUN pnpm run build && pnpm prune --prod
|
FROM base AS prod-deps
|
||||||
|
|
||||||
|
COPY package.json pnpm-lock.yaml ./
|
||||||
|
RUN --mount=type=cache,id=pnpm-store-prod,sharing=locked,target=/pnpm/store \
|
||||||
|
pnpm install --prod --frozen-lockfile \
|
||||||
|
&& rm -rf /root/.npm /root/.cache
|
||||||
|
|
||||||
FROM node:22-slim AS runtime
|
FROM node:22-slim AS runtime
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
ARG NPM_REGISTRY=https://registry.npmjs.org/
|
|
||||||
ENV NPM_CONFIG_REGISTRY=${NPM_REGISTRY}
|
|
||||||
ENV npm_config_registry=${NPM_REGISTRY}
|
|
||||||
|
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
|
|
||||||
COPY --from=build /app/node_modules ./node_modules
|
COPY --from=prod-deps /app/node_modules ./node_modules
|
||||||
COPY --from=build /app/dist ./dist
|
COPY --from=build /app/dist ./dist
|
||||||
COPY --from=build /app/prisma ./prisma
|
COPY --from=build /app/prisma ./prisma
|
||||||
COPY --from=build /app/package.json ./package.json
|
COPY --from=build /app/package.json ./package.json
|
||||||
|
|
||||||
|
USER node
|
||||||
CMD ["node", "dist/src/main.js"]
|
CMD ["node", "dist/src/main.js"]
|
||||||
|
|
||||||
|
|||||||
+1533
File diff suppressed because one or more lines are too long
+74
-5
@@ -15,7 +15,6 @@ services:
|
|||||||
- "${DATABASE_PORT}:3306"
|
- "${DATABASE_PORT}:3306"
|
||||||
volumes:
|
volumes:
|
||||||
- db_data:/var/lib/mysql
|
- db_data:/var/lib/mysql
|
||||||
- ./prisma/migrations:/docker-entrypoint-initdb.d
|
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: "mysqladmin ping -h 127.0.0.1 -u ${DATABASE_USER} -p'${DB_ROOT_PASSWORD}'"
|
test: "mysqladmin ping -h 127.0.0.1 -u ${DATABASE_USER} -p'${DB_ROOT_PASSWORD}'"
|
||||||
interval: 15s # Shortened interval, as MySQL is starting fast now
|
interval: 15s # Shortened interval, as MySQL is starting fast now
|
||||||
@@ -26,6 +25,24 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- psp_consumer_network
|
- psp_consumer_network
|
||||||
|
|
||||||
|
redis:
|
||||||
|
image: redis:7-alpine
|
||||||
|
platform: ${DOCKER_PLATFORM:-linux/amd64}
|
||||||
|
container_name: psp_consumer_api_redis
|
||||||
|
restart: unless-stopped
|
||||||
|
command: redis-server --appendonly yes
|
||||||
|
ports:
|
||||||
|
- "${REDIS_PORT:-6379}:6379"
|
||||||
|
volumes:
|
||||||
|
- redis_data:/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "redis-cli", "ping"]
|
||||||
|
interval: 15s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
networks:
|
||||||
|
- psp_consumer_network
|
||||||
|
|
||||||
api:
|
api:
|
||||||
platform: ${DOCKER_PLATFORM:-linux/amd64}
|
platform: ${DOCKER_PLATFORM:-linux/amd64}
|
||||||
build:
|
build:
|
||||||
@@ -52,6 +69,8 @@ services:
|
|||||||
depends_on:
|
depends_on:
|
||||||
database:
|
database:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
|
redis:
|
||||||
|
condition: service_healthy
|
||||||
environment:
|
environment:
|
||||||
NODE_ENV: ${NODE_ENV:-production}
|
NODE_ENV: ${NODE_ENV:-production}
|
||||||
PORT: ${PORT}
|
PORT: ${PORT}
|
||||||
@@ -66,12 +85,19 @@ services:
|
|||||||
JWT_EXPIRES_IN: ${JWT_EXPIRES_IN}
|
JWT_EXPIRES_IN: ${JWT_EXPIRES_IN}
|
||||||
CORS_ORIGINS: ${CORS_ORIGINS:-http://localhost:5000,http://127.0.0.1:5000}
|
CORS_ORIGINS: ${CORS_ORIGINS:-http://localhost:5000,http://127.0.0.1:5000}
|
||||||
OTP_STATIC_CODE: ${OTP_STATIC_CODE} # From .env
|
OTP_STATIC_CODE: ${OTP_STATIC_CODE} # From .env
|
||||||
|
REDIS_HOST: ${REDIS_HOST:-redis}
|
||||||
|
REDIS_PORT: ${REDIS_PORT:-6379}
|
||||||
|
REDIS_DB: ${REDIS_DB:-0}
|
||||||
|
REDIS_PASSWORD: ${REDIS_PASSWORD:-}
|
||||||
ports:
|
ports:
|
||||||
- "${PORT:-5002}:5002"
|
- "${PORT:-5002}:5002"
|
||||||
volumes:
|
read_only: true
|
||||||
- ./src:/app/src
|
tmpfs:
|
||||||
- /app/dist
|
- /tmp
|
||||||
- /app/node_modules
|
security_opt:
|
||||||
|
- no-new-privileges:true
|
||||||
|
cap_drop:
|
||||||
|
- ALL
|
||||||
networks:
|
networks:
|
||||||
- psp_consumer_network
|
- psp_consumer_network
|
||||||
# healthcheck:
|
# healthcheck:
|
||||||
@@ -89,9 +115,52 @@ services:
|
|||||||
# retries: 3
|
# retries: 3
|
||||||
# start_period: 10s
|
# start_period: 10s
|
||||||
|
|
||||||
|
# seed:
|
||||||
|
# platform: ${DOCKER_PLATFORM:-linux/amd64}
|
||||||
|
# build:
|
||||||
|
# context: .
|
||||||
|
# dockerfile: Dockerfile
|
||||||
|
# target: build
|
||||||
|
# args:
|
||||||
|
# NODE_ENV: ${NODE_ENV:-production}
|
||||||
|
# PORT: ${PORT}
|
||||||
|
# DATABASE_NAME: ${DATABASE_NAME}
|
||||||
|
# DATABASE_USER: ${DATABASE_USER}
|
||||||
|
# DATABASE_PASSWORD: ${DATABASE_PASSWORD}
|
||||||
|
# DATABASE_PORT: ${DATABASE_PORT}
|
||||||
|
# DATABASE_HOST: ${DATABASE_HOST}
|
||||||
|
# DATABASE_URL: mysql://${DATABASE_USER}:${DATABASE_PASSWORD}@${DATABASE_HOST}:${DATABASE_PORT}/${DATABASE_NAME}
|
||||||
|
# SHADOW_DATABASE_URL: mysql://${DATABASE_USER}:${DATABASE_PASSWORD}@${DATABASE_HOST}:${DATABASE_PORT}/${DATABASE_NAME}_shadow
|
||||||
|
# JWT_SECRET: ${JWT_SECRET}
|
||||||
|
# JWT_EXPIRES_IN: ${JWT_EXPIRES_IN}
|
||||||
|
# OTP_STATIC_CODE: ${OTP_STATIC_CODE}
|
||||||
|
# depends_on:
|
||||||
|
# database:
|
||||||
|
# condition: service_healthy
|
||||||
|
# environment:
|
||||||
|
# NODE_ENV: ${NODE_ENV:-production}
|
||||||
|
# PORT: ${PORT}
|
||||||
|
# DATABASE_NAME: ${DATABASE_NAME}
|
||||||
|
# DATABASE_USER: ${DATABASE_USER}
|
||||||
|
# DATABASE_PASSWORD: ${DATABASE_PASSWORD}
|
||||||
|
# DATABASE_PORT: ${DATABASE_PORT}
|
||||||
|
# DATABASE_HOST: ${DATABASE_HOST}
|
||||||
|
# DATABASE_URL: mysql://${DATABASE_USER}:${DATABASE_PASSWORD}@${DATABASE_HOST}:${DATABASE_PORT}/${DATABASE_NAME}
|
||||||
|
# SHADOW_DATABASE_URL: mysql://${DATABASE_USER}:${DATABASE_PASSWORD}@${DATABASE_HOST}:${DATABASE_PORT}/${DATABASE_NAME}_shadow
|
||||||
|
# JWT_SECRET: ${JWT_SECRET}
|
||||||
|
# JWT_EXPIRES_IN: ${JWT_EXPIRES_IN}
|
||||||
|
# OTP_STATIC_CODE: ${OTP_STATIC_CODE}
|
||||||
|
# networks:
|
||||||
|
# - psp_consumer_network
|
||||||
|
# profiles:
|
||||||
|
# - tools
|
||||||
|
# command: ["pnpm", "seed:sku"]
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
db_data:
|
db_data:
|
||||||
driver: local
|
driver: local
|
||||||
|
redis_data:
|
||||||
|
driver: local
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
psp_consumer_network:
|
psp_consumer_network:
|
||||||
|
|||||||
+5
-1
@@ -9,6 +9,7 @@
|
|||||||
"@nestjs/platform-express": "^11.1.19",
|
"@nestjs/platform-express": "^11.1.19",
|
||||||
"@nestjs/swagger": "^11.3.2",
|
"@nestjs/swagger": "^11.3.2",
|
||||||
"@prisma/adapter-mariadb": "^7.7.0",
|
"@prisma/adapter-mariadb": "^7.7.0",
|
||||||
|
"@prisma/client": "^7.7.0",
|
||||||
"@types/bcrypt": "^6.0.0",
|
"@types/bcrypt": "^6.0.0",
|
||||||
"@types/multer": "^2.1.0",
|
"@types/multer": "^2.1.0",
|
||||||
"bcrypt": "^6.0.0",
|
"bcrypt": "^6.0.0",
|
||||||
@@ -17,6 +18,7 @@
|
|||||||
"cookie-parser": "^1.4.7",
|
"cookie-parser": "^1.4.7",
|
||||||
"dayjs": "^1.11.20",
|
"dayjs": "^1.11.20",
|
||||||
"dotenv": "^17.4.2",
|
"dotenv": "^17.4.2",
|
||||||
|
"ioredis": "^5.8.2",
|
||||||
"jalaliday": "^3.1.1",
|
"jalaliday": "^3.1.1",
|
||||||
"jsonwebtoken": "^9.0.3",
|
"jsonwebtoken": "^9.0.3",
|
||||||
"multer": "^2.1.1",
|
"multer": "^2.1.1",
|
||||||
@@ -33,7 +35,6 @@
|
|||||||
"@nestjs/cli": "^11.0.21",
|
"@nestjs/cli": "^11.0.21",
|
||||||
"@nestjs/schematics": "^11.1.0",
|
"@nestjs/schematics": "^11.1.0",
|
||||||
"@nestjs/testing": "^11.1.19",
|
"@nestjs/testing": "^11.1.19",
|
||||||
"@prisma/client": "^7.7.0",
|
|
||||||
"@types/cookie-parser": "^1.4.10",
|
"@types/cookie-parser": "^1.4.10",
|
||||||
"@types/express": "^5.0.6",
|
"@types/express": "^5.0.6",
|
||||||
"@types/jest": "^30.0.0",
|
"@types/jest": "^30.0.0",
|
||||||
@@ -44,6 +45,7 @@
|
|||||||
"eslint-plugin-prettier": "^5.5.5",
|
"eslint-plugin-prettier": "^5.5.5",
|
||||||
"globals": "^16.5.0",
|
"globals": "^16.5.0",
|
||||||
"jest": "^30.3.0",
|
"jest": "^30.3.0",
|
||||||
|
"plop": "^4.0.5",
|
||||||
"prettier": "^3.8.3",
|
"prettier": "^3.8.3",
|
||||||
"prettier-plugin-prisma": "^5.0.0",
|
"prettier-plugin-prisma": "^5.0.0",
|
||||||
"source-map-support": "^0.5.21",
|
"source-map-support": "^0.5.21",
|
||||||
@@ -81,8 +83,10 @@
|
|||||||
"db:reset": "tsx scripts/dump-triggers.ts && npx prisma migrate reset --force",
|
"db:reset": "tsx scripts/dump-triggers.ts && npx prisma migrate reset --force",
|
||||||
"dump-triggers": "tsx scripts/dump-triggers.ts",
|
"dump-triggers": "tsx scripts/dump-triggers.ts",
|
||||||
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
|
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
|
||||||
|
"generate": "plop",
|
||||||
"generate:permissions": "tsx scripts/generate-permissions.ts",
|
"generate:permissions": "tsx scripts/generate-permissions.ts",
|
||||||
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
|
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
|
||||||
|
"seed:sku": "tsx scripts/seedStockKeepingUnits.ts",
|
||||||
"start": "nest start",
|
"start": "nest start",
|
||||||
"start:debug": "nest start --debug --watch",
|
"start:debug": "nest start --debug --watch",
|
||||||
"start:dev": "nest start --watch",
|
"start:dev": "nest start --watch",
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
import {
|
||||||
|
Body,
|
||||||
|
Controller,
|
||||||
|
Delete,
|
||||||
|
Get,
|
||||||
|
Param,
|
||||||
|
Patch,
|
||||||
|
Post,
|
||||||
|
} from '@nestjs/common';
|
||||||
|
import { {{pascalCase name}}Service } from './{{kebabCase name}}.service';
|
||||||
|
import { Create{{pascalCase name}}Dto } from './dto/create-{{kebabCase name}}.dto';
|
||||||
|
import { Update{{pascalCase name}}Dto } from './dto/update-{{kebabCase name}}.dto';
|
||||||
|
|
||||||
|
@Controller('{{kebabCase name}}')
|
||||||
|
export class {{pascalCase name}}Controller {
|
||||||
|
constructor(private readonly service: {{pascalCase name}}Service) {}
|
||||||
|
|
||||||
|
|
||||||
|
@Get()
|
||||||
|
findAll() {
|
||||||
|
return this.service.findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get(':id')
|
||||||
|
findOne(@Param('id') id: string) {
|
||||||
|
return this.service.findOne(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post()
|
||||||
|
create(@Body() dto: Create{{pascalCase name}}Dto) {
|
||||||
|
return this.service.create(dto);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Patch(':id')
|
||||||
|
update(
|
||||||
|
@Param('id') id: string,
|
||||||
|
@Body() dto: Update{{pascalCase name}}Dto,
|
||||||
|
) {
|
||||||
|
return this.service.update(id, dto);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Delete(':id')
|
||||||
|
remove(@Param('id') id: string) {
|
||||||
|
return this.service.remove(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import { IsString, IsNumber, IsBoolean, IsEmail } from 'class-validator';
|
||||||
|
|
||||||
|
export class Create{{pascalCase name}}Dto {
|
||||||
|
{{#each parsedFields}}
|
||||||
|
@{{validator}}()
|
||||||
|
{{name}}: {{type}};
|
||||||
|
|
||||||
|
{{/each}}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { {{pascalCase name}}Service } from './{{kebabCase name}}.service';
|
||||||
|
import { {{pascalCase name}}Controller } from './{{kebabCase name}}.controller';
|
||||||
|
import { PrismaService } from '{{prismaImportPath modulePath name}}';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
controllers: [{{pascalCase name}}Controller],
|
||||||
|
providers: [{{pascalCase name}}Service, PrismaService],
|
||||||
|
})
|
||||||
|
export class {{pascalCase name}}Module {}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { PrismaService } from '@/prisma/prisma.service';
|
||||||
|
import { ResponseMapper } from '@/common/response/response-mapper'
|
||||||
|
import { Create{{pascalCase name}}Dto } from './dto/create-{{kebabCase name}}.dto';
|
||||||
|
import { Update{{pascalCase name}}Dto } from './dto/update-{{kebabCase name}}.dto';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class {{pascalCase name}}Service {
|
||||||
|
constructor(private readonly prisma: PrismaService) {}
|
||||||
|
|
||||||
|
private readonly summarySelect = {
|
||||||
|
id: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly select = {
|
||||||
|
...this.summarySelect,
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly where = () => ({})
|
||||||
|
|
||||||
|
|
||||||
|
async findAll() {
|
||||||
|
const items = await this.prisma.{{camelCase name}}.findMany({
|
||||||
|
where: this.where(),
|
||||||
|
select: this.summarySelect,
|
||||||
|
});
|
||||||
|
return ResponseMapper.list(items)
|
||||||
|
}
|
||||||
|
|
||||||
|
async findOne(id: string) {
|
||||||
|
const item = this.prisma.{{camelCase name}}.findUnique({
|
||||||
|
where: {...this.where(), id },
|
||||||
|
select: this.select,
|
||||||
|
});
|
||||||
|
|
||||||
|
return ResponseMapper.single(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
async create(createDto: Create{{pascalCase name}}Dto) {
|
||||||
|
const item = this.prisma.{{camelCase name}}.create({
|
||||||
|
data: createDto,
|
||||||
|
select: this.select,
|
||||||
|
});
|
||||||
|
|
||||||
|
return ResponseMapper.create(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
async update(id: string, updateDto: Update{{pascalCase name}}Dto) {
|
||||||
|
const item = this.prisma.{{camelCase name}}.update({
|
||||||
|
where: { id },
|
||||||
|
data: updateDto,
|
||||||
|
select: this.select,
|
||||||
|
});
|
||||||
|
|
||||||
|
return ResponseMapper.update(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
async remove(id: string) {
|
||||||
|
return this.prisma.{{camelCase name}}.delete({
|
||||||
|
where: { id },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
import { PartialType } from '@nestjs/swagger'
|
||||||
|
import { Create{{pascalCase name}}Dto } from './create-{{kebabCase name}}.dto';
|
||||||
|
|
||||||
|
export class Update{{pascalCase name}}Dto extends PartialType(Create{{pascalCase name}}Dto) {}
|
||||||
+125
@@ -0,0 +1,125 @@
|
|||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
module.exports = function (plop) {
|
||||||
|
// -------------------------
|
||||||
|
// Case helpers
|
||||||
|
// -------------------------
|
||||||
|
const toKebab = str =>
|
||||||
|
str
|
||||||
|
.replace(/([a-z])([A-Z])/g, '$1-$2')
|
||||||
|
.replace(/\s+/g, '-')
|
||||||
|
.toLowerCase()
|
||||||
|
|
||||||
|
const toPascal = str =>
|
||||||
|
str
|
||||||
|
.split(/[-_\s]+/)
|
||||||
|
.map(part => part.charAt(0).toUpperCase() + part.slice(1))
|
||||||
|
.join('')
|
||||||
|
|
||||||
|
const toCamel = str => {
|
||||||
|
const pascal = toPascal(str)
|
||||||
|
return pascal.charAt(0).toLowerCase() + pascal.slice(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
plop.setHelper('kebabCase', toKebab)
|
||||||
|
plop.setHelper('pascalCase', toPascal)
|
||||||
|
plop.setHelper('camelCase', toCamel)
|
||||||
|
|
||||||
|
// -------------------------
|
||||||
|
// Dynamic relative import helper
|
||||||
|
// -------------------------
|
||||||
|
plop.setHelper('prismaImportPath', (modulePath, name) => {
|
||||||
|
return '@/prisma/prisma.service'
|
||||||
|
})
|
||||||
|
|
||||||
|
// -------------------------
|
||||||
|
// Generator
|
||||||
|
// -------------------------
|
||||||
|
plop.setGenerator('resource', {
|
||||||
|
description: 'Generate Nested NestJS Prisma Resource',
|
||||||
|
prompts: [
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
name: 'name',
|
||||||
|
message: 'Module name (e.g. user, blog-post):',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
name: 'modulePath',
|
||||||
|
message: 'Nested path inside modules (e.g. admin/users) — leave empty for root:',
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
name: 'fields',
|
||||||
|
message:
|
||||||
|
'DTO fields (comma-separated, e.g. name:string,email:email,age:number,isActive:boolean):',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
actions(data) {
|
||||||
|
// sanitize path
|
||||||
|
data.modulePath = data.modulePath.replace(/^\/+|\/+$/g, '')
|
||||||
|
|
||||||
|
// Parse fields
|
||||||
|
const rawFields = data.fields || ''
|
||||||
|
data.parsedFields = rawFields
|
||||||
|
.split(',')
|
||||||
|
.filter(Boolean)
|
||||||
|
.map(field => {
|
||||||
|
const [name, type] = field.split(':').map(v => v.trim())
|
||||||
|
|
||||||
|
let validator = 'IsString'
|
||||||
|
let finalType = 'string'
|
||||||
|
|
||||||
|
if (type === 'number') {
|
||||||
|
validator = 'IsNumber'
|
||||||
|
finalType = 'number'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === 'boolean') {
|
||||||
|
validator = 'IsBoolean'
|
||||||
|
finalType = 'boolean'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === 'email') {
|
||||||
|
validator = 'IsEmail'
|
||||||
|
finalType = 'string'
|
||||||
|
}
|
||||||
|
|
||||||
|
return { name, validator, type: finalType }
|
||||||
|
})
|
||||||
|
|
||||||
|
const basePath = data.modulePath
|
||||||
|
? `src/modules/${data.modulePath}/{{kebabCase name}}`
|
||||||
|
: `src/modules/{{kebabCase name}}`
|
||||||
|
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
type: 'add',
|
||||||
|
path: `${basePath}/{{kebabCase name}}.module.ts`,
|
||||||
|
templateFile: 'plop-templates/module.hbs',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'add',
|
||||||
|
path: `${basePath}/{{kebabCase name}}.service.ts`,
|
||||||
|
templateFile: 'plop-templates/service.hbs',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'add',
|
||||||
|
path: `${basePath}/{{kebabCase name}}.controller.ts`,
|
||||||
|
templateFile: 'plop-templates/controller.hbs',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'add',
|
||||||
|
path: `${basePath}/dto/create-{{kebabCase name}}.dto.ts`,
|
||||||
|
templateFile: 'plop-templates/create-dto.hbs',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'add',
|
||||||
|
path: `${basePath}/dto/update-{{kebabCase name}}.dto.ts`,
|
||||||
|
templateFile: 'plop-templates/update-dto.hbs',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
Generated
+562
-65
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,913 @@
|
|||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `admin_accounts` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`updated_at` TIMESTAMP(0) NOT NULL,
|
||||||
|
`admin_id` VARCHAR(191) NOT NULL,
|
||||||
|
`account_id` VARCHAR(191) NOT NULL,
|
||||||
|
|
||||||
|
UNIQUE INDEX `admin_accounts_account_id_key`(`account_id`),
|
||||||
|
INDEX `admin_accounts_admin_id_fkey`(`admin_id`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `admins` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`mobile_number` VARCHAR(191) NOT NULL,
|
||||||
|
`national_code` VARCHAR(191) NULL,
|
||||||
|
`first_name` VARCHAR(191) NOT NULL,
|
||||||
|
`last_name` VARCHAR(191) NOT NULL,
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`updated_at` TIMESTAMP(0) NOT NULL,
|
||||||
|
|
||||||
|
UNIQUE INDEX `admins_mobile_number_key`(`mobile_number`),
|
||||||
|
UNIQUE INDEX `admins_national_code_key`(`national_code`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `accounts` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`username` VARCHAR(191) NOT NULL,
|
||||||
|
`password` VARCHAR(191) NOT NULL,
|
||||||
|
`status` ENUM('ACTIVE', 'SUSPENDED') NOT NULL,
|
||||||
|
`type` ENUM('ADMIN', 'PROVIDER', 'PARTNER', 'CONSUMER') NOT NULL,
|
||||||
|
|
||||||
|
UNIQUE INDEX `accounts_username_key`(`username`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `device_brands` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`name` VARCHAR(191) NOT NULL,
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`updated_at` TIMESTAMP(0) NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `devices` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`name` VARCHAR(191) NOT NULL,
|
||||||
|
`os_version` VARCHAR(191) NULL,
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`updated_at` TIMESTAMP(0) NOT NULL,
|
||||||
|
`brand_id` VARCHAR(191) NOT NULL,
|
||||||
|
|
||||||
|
INDEX `devices_brand_id_idx`(`brand_id`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `license_charged_transactions` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`activation_expires_at` DATETIME(3) NOT NULL,
|
||||||
|
`tracking_code` VARCHAR(191) NOT NULL,
|
||||||
|
`purchased_count` INTEGER NOT NULL,
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`updated_at` TIMESTAMP(0) NOT NULL,
|
||||||
|
`partner_id` VARCHAR(191) NOT NULL,
|
||||||
|
|
||||||
|
UNIQUE INDEX `license_charged_transactions_tracking_code_key`(`tracking_code`),
|
||||||
|
INDEX `license_charged_transactions_partner_id_idx`(`partner_id`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `licenses` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`accounts_limit` INTEGER NOT NULL DEFAULT 2,
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`updated_at` TIMESTAMP(0) NOT NULL,
|
||||||
|
`charge_transaction_id` VARCHAR(191) NOT NULL,
|
||||||
|
|
||||||
|
INDEX `licenses_charge_transaction_id_idx`(`charge_transaction_id`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `licenses_activated` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`starts_at` DATETIME(3) NOT NULL,
|
||||||
|
`expires_at` DATETIME(3) NOT NULL,
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`updated_at` TIMESTAMP(0) NOT NULL,
|
||||||
|
`license_id` VARCHAR(191) NOT NULL,
|
||||||
|
`business_activity_id` VARCHAR(191) NOT NULL,
|
||||||
|
|
||||||
|
UNIQUE INDEX `licenses_activated_id_key`(`id`),
|
||||||
|
UNIQUE INDEX `licenses_activated_license_id_key`(`license_id`),
|
||||||
|
UNIQUE INDEX `licenses_activated_business_activity_id_key`(`business_activity_id`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `license_renew_charge_transaction` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`activation_expires_at` DATETIME(3) NOT NULL,
|
||||||
|
`tracking_code` VARCHAR(191) NOT NULL,
|
||||||
|
`purchased_count` INTEGER NOT NULL,
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`updated_at` TIMESTAMP(0) NOT NULL,
|
||||||
|
`partner_id` VARCHAR(191) NOT NULL,
|
||||||
|
|
||||||
|
UNIQUE INDEX `license_renew_charge_transaction_tracking_code_key`(`tracking_code`),
|
||||||
|
INDEX `license_renew_charge_transaction_partner_id_idx`(`partner_id`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `license_renew` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`expires_at` DATETIME(3) NOT NULL,
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`updated_at` TIMESTAMP(0) NOT NULL,
|
||||||
|
`charge_transaction_id` VARCHAR(191) NOT NULL,
|
||||||
|
`activation_id` VARCHAR(191) NULL,
|
||||||
|
|
||||||
|
INDEX `license_renew_activation_id_idx`(`activation_id`),
|
||||||
|
INDEX `license_renew_charge_transaction_id_idx`(`charge_transaction_id`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `partner_account_quota_charge_transaction` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`activation_expires_at` DATETIME(3) NOT NULL,
|
||||||
|
`tracking_code` VARCHAR(191) NOT NULL,
|
||||||
|
`purchased_count` INTEGER NOT NULL,
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`updated_at` TIMESTAMP(0) NOT NULL,
|
||||||
|
`partner_id` VARCHAR(191) NOT NULL,
|
||||||
|
|
||||||
|
UNIQUE INDEX `partner_account_quota_charge_transaction_tracking_code_key`(`tracking_code`),
|
||||||
|
INDEX `partner_account_quota_charge_transaction_partner_id_idx`(`partner_id`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `partner_account_quota_credit` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`updated_at` TIMESTAMP(0) NOT NULL,
|
||||||
|
`charge_transaction_id` VARCHAR(191) NULL,
|
||||||
|
|
||||||
|
INDEX `partner_account_quota_credit_charge_transaction_id_idx`(`charge_transaction_id`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `license_account_allocation` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`updated_at` TIMESTAMP(0) NOT NULL,
|
||||||
|
`license_activation_id` VARCHAR(191) NULL,
|
||||||
|
`account_id` VARCHAR(191) NULL,
|
||||||
|
`credit_id` VARCHAR(191) NULL,
|
||||||
|
|
||||||
|
UNIQUE INDEX `license_account_allocation_account_id_key`(`account_id`),
|
||||||
|
UNIQUE INDEX `license_account_allocation_credit_id_key`(`credit_id`),
|
||||||
|
INDEX `license_account_allocation_license_activation_id_idx`(`license_activation_id`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `partner_accounts` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`role` ENUM('OWNER', 'MANAGER', 'OPERATOR') NOT NULL,
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`updated_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`partner_id` VARCHAR(191) NOT NULL,
|
||||||
|
`account_id` VARCHAR(191) NOT NULL,
|
||||||
|
|
||||||
|
UNIQUE INDEX `partner_accounts_account_id_key`(`account_id`),
|
||||||
|
INDEX `partner_accounts_partner_id_fkey`(`partner_id`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `partners` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`name` VARCHAR(191) NOT NULL,
|
||||||
|
`code` VARCHAR(191) NOT NULL,
|
||||||
|
`status` ENUM('ACTIVE', 'SUSPENDED') NOT NULL DEFAULT 'ACTIVE',
|
||||||
|
`logo_url` VARCHAR(191) NULL,
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`updated_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`tsp_provider` ENUM('NAMA', 'SUN') NOT NULL DEFAULT 'NAMA',
|
||||||
|
|
||||||
|
UNIQUE INDEX `partners_code_key`(`code`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `permission_consumers` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`consumer_account_id` VARCHAR(191) NOT NULL,
|
||||||
|
|
||||||
|
UNIQUE INDEX `permission_consumers_consumer_account_id_key`(`consumer_account_id`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `permission_poses` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`role` ENUM('MANAGER', 'OPERATOR') NOT NULL,
|
||||||
|
`pos_id` VARCHAR(191) NOT NULL,
|
||||||
|
`permission_id` VARCHAR(191) NOT NULL,
|
||||||
|
|
||||||
|
INDEX `permission_poses_pos_id_fkey`(`pos_id`),
|
||||||
|
UNIQUE INDEX `permission_poses_permission_id_pos_id_key`(`permission_id`, `pos_id`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `permission_complexes` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`role` ENUM('MANAGER', 'OPERATOR') NOT NULL,
|
||||||
|
`complex_id` VARCHAR(191) NOT NULL,
|
||||||
|
`permission_id` VARCHAR(191) NOT NULL,
|
||||||
|
|
||||||
|
INDEX `permission_complexes_complex_id_fkey`(`complex_id`),
|
||||||
|
UNIQUE INDEX `permission_complexes_permission_id_complex_id_key`(`permission_id`, `complex_id`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `permission_business_activities` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`role` ENUM('MANAGER', 'OPERATOR') NOT NULL,
|
||||||
|
`business_id` VARCHAR(191) NOT NULL,
|
||||||
|
`permission_id` VARCHAR(191) NOT NULL,
|
||||||
|
|
||||||
|
INDEX `permission_business_activities_business_id_fkey`(`business_id`),
|
||||||
|
UNIQUE INDEX `permission_business_activities_permission_id_business_id_key`(`permission_id`, `business_id`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `provider_accounts` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`role` ENUM('OWNER', 'MANAGER', 'OPERATOR') NOT NULL,
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`updated_at` TIMESTAMP(0) NOT NULL,
|
||||||
|
`provider_id` VARCHAR(191) NOT NULL,
|
||||||
|
`account_id` VARCHAR(191) NOT NULL,
|
||||||
|
|
||||||
|
UNIQUE INDEX `provider_accounts_account_id_key`(`account_id`),
|
||||||
|
INDEX `provider_accounts_provider_id_fkey`(`provider_id`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `providers` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`code` VARCHAR(191) NOT NULL,
|
||||||
|
`status` ENUM('ACTIVE', 'SUSPENDED') NOT NULL DEFAULT 'ACTIVE',
|
||||||
|
`name` VARCHAR(191) NOT NULL,
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`updated_at` TIMESTAMP(0) NOT NULL,
|
||||||
|
|
||||||
|
UNIQUE INDEX `providers_code_key`(`code`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `consumer_account_device` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`device_id` VARCHAR(191) NOT NULL,
|
||||||
|
`device_name` VARCHAR(191) NULL,
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`updated_at` TIMESTAMP(0) NOT NULL,
|
||||||
|
`consumer_account_id` VARCHAR(191) NOT NULL,
|
||||||
|
|
||||||
|
UNIQUE INDEX `consumer_account_device_device_id_key`(`device_id`),
|
||||||
|
UNIQUE INDEX `consumer_account_device_consumer_account_id_key`(`consumer_account_id`),
|
||||||
|
INDEX `consumer_account_device_consumer_account_id_idx`(`consumer_account_id`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `application_released_info` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`version` VARCHAR(191) NOT NULL,
|
||||||
|
`build_number` VARCHAR(191) NOT NULL,
|
||||||
|
`is_minimum_supported` BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
`release_type` ENUM('STABLE', 'BETA', 'ALPHA') NOT NULL,
|
||||||
|
`platform` ENUM('ANDROID', 'IOS') NOT NULL,
|
||||||
|
`notes` JSON NULL,
|
||||||
|
`release_date` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`updated_at` TIMESTAMP(0) NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `consumer_accounts` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`role` ENUM('OWNER', 'MANAGER', 'OPERATOR') NOT NULL,
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`updated_at` TIMESTAMP(0) NOT NULL,
|
||||||
|
`consumer_id` VARCHAR(191) NOT NULL,
|
||||||
|
`account_id` VARCHAR(191) NOT NULL,
|
||||||
|
|
||||||
|
UNIQUE INDEX `consumer_accounts_account_id_key`(`account_id`),
|
||||||
|
INDEX `consumer_accounts_consumer_id_fkey`(`consumer_id`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `consumers` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`type` ENUM('INDIVIDUAL', 'LEGAL') NOT NULL,
|
||||||
|
`status` ENUM('ACTIVE', 'SUSPENDED') NOT NULL DEFAULT 'ACTIVE',
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`updated_at` TIMESTAMP(0) NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `consumers_individual` (
|
||||||
|
`first_name` VARCHAR(191) NOT NULL,
|
||||||
|
`last_name` VARCHAR(191) NOT NULL,
|
||||||
|
`mobile_number` VARCHAR(191) NOT NULL,
|
||||||
|
`national_code` VARCHAR(191) NOT NULL,
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`updated_at` TIMESTAMP(0) NOT NULL,
|
||||||
|
`partner_id` VARCHAR(191) NOT NULL,
|
||||||
|
`consumer_id` VARCHAR(191) NOT NULL,
|
||||||
|
|
||||||
|
UNIQUE INDEX `consumers_individual_mobile_number_consumer_id_key`(`mobile_number`, `consumer_id`),
|
||||||
|
UNIQUE INDEX `consumers_individual_partner_id_national_code_key`(`partner_id`, `national_code`),
|
||||||
|
PRIMARY KEY (`consumer_id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `consumers_legal` (
|
||||||
|
`name` VARCHAR(191) NOT NULL,
|
||||||
|
`registration_code` VARCHAR(191) NOT NULL,
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`updated_at` TIMESTAMP(0) NOT NULL,
|
||||||
|
`partner_id` VARCHAR(191) NOT NULL,
|
||||||
|
`consumer_id` VARCHAR(191) NOT NULL,
|
||||||
|
|
||||||
|
UNIQUE INDEX `consumers_legal_partner_id_registration_code_key`(`partner_id`, `registration_code`),
|
||||||
|
PRIMARY KEY (`consumer_id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `business_activities` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`economic_code` VARCHAR(191) NOT NULL,
|
||||||
|
`name` VARCHAR(191) NOT NULL,
|
||||||
|
`fiscal_id` VARCHAR(191) NOT NULL,
|
||||||
|
`partner_token` VARCHAR(191) NOT NULL,
|
||||||
|
`invoice_number_sequence` DECIMAL(20, 0) NOT NULL DEFAULT 1,
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`updated_at` TIMESTAMP(0) NOT NULL,
|
||||||
|
`guild_id` VARCHAR(191) NOT NULL,
|
||||||
|
`consumer_id` VARCHAR(191) NOT NULL,
|
||||||
|
|
||||||
|
INDEX `business_activities_consumer_id_fkey`(`consumer_id`),
|
||||||
|
INDEX `business_activities_guild_id_fkey`(`guild_id`),
|
||||||
|
UNIQUE INDEX `business_activities_economic_code_consumer_id_key`(`economic_code`, `consumer_id`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `complexes` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`name` VARCHAR(191) NOT NULL,
|
||||||
|
`branch_code` VARCHAR(191) NOT NULL,
|
||||||
|
`address` VARCHAR(191) NULL,
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`updated_at` TIMESTAMP(0) NOT NULL,
|
||||||
|
`business_activity_id` VARCHAR(191) NOT NULL,
|
||||||
|
|
||||||
|
INDEX `complexes_business_activity_id_fkey`(`business_activity_id`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `poses` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`name` VARCHAR(191) NOT NULL,
|
||||||
|
`model` VARCHAR(191) NULL,
|
||||||
|
`serial_number` VARCHAR(191) NULL,
|
||||||
|
`status` ENUM('ACTIVE', 'DISABLED') NOT NULL DEFAULT 'ACTIVE',
|
||||||
|
`pos_type` ENUM('PSP', 'MOBILE', 'WEB', 'API') NOT NULL,
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`updated_at` TIMESTAMP(0) NOT NULL,
|
||||||
|
`complex_id` VARCHAR(191) NOT NULL,
|
||||||
|
`device_id` VARCHAR(191) NULL,
|
||||||
|
`provider_id` VARCHAR(191) NULL,
|
||||||
|
`account_id` VARCHAR(191) NOT NULL,
|
||||||
|
|
||||||
|
UNIQUE INDEX `poses_serial_number_key`(`serial_number`),
|
||||||
|
UNIQUE INDEX `poses_account_id_key`(`account_id`),
|
||||||
|
INDEX `poses_complex_id_fkey`(`complex_id`),
|
||||||
|
INDEX `poses_device_id_fkey`(`device_id`),
|
||||||
|
INDEX `poses_provider_id_fkey`(`provider_id`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `consumer_account_good_favorites` (
|
||||||
|
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||||||
|
`consumer_account_id` VARCHAR(191) NOT NULL,
|
||||||
|
`good_id` VARCHAR(191) NOT NULL,
|
||||||
|
|
||||||
|
INDEX `consumer_account_good_favorites_good_id_idx`(`good_id`),
|
||||||
|
INDEX `consumer_account_good_favorites_consumer_account_id_idx`(`consumer_account_id`),
|
||||||
|
PRIMARY KEY (`consumer_account_id`, `good_id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `goods` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`name` VARCHAR(255) NOT NULL,
|
||||||
|
`is_default_guild_good` BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
`pricing_model` ENUM('STANDARD', 'GOLD') NOT NULL,
|
||||||
|
`description` TEXT NULL,
|
||||||
|
`local_sku` VARCHAR(100) NULL,
|
||||||
|
`barcode` VARCHAR(100) NULL,
|
||||||
|
`base_sale_price` DECIMAL(15, 0) NULL DEFAULT 0,
|
||||||
|
`image_url` VARCHAR(255) NULL,
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`updated_at` TIMESTAMP(0) NOT NULL,
|
||||||
|
`deleted_at` TIMESTAMP(0) NULL,
|
||||||
|
`sku_id` VARCHAR(191) NOT NULL,
|
||||||
|
`measure_unit_id` VARCHAR(191) NOT NULL,
|
||||||
|
`category_id` VARCHAR(191) NULL,
|
||||||
|
`business_activity_id` VARCHAR(191) NULL,
|
||||||
|
|
||||||
|
UNIQUE INDEX `goods_local_sku_key`(`local_sku`),
|
||||||
|
UNIQUE INDEX `goods_barcode_key`(`barcode`),
|
||||||
|
INDEX `goods_category_id_idx`(`category_id`),
|
||||||
|
INDEX `goods_business_activity_id_fkey`(`business_activity_id`),
|
||||||
|
INDEX `goods_measure_unit_id_fkey`(`measure_unit_id`),
|
||||||
|
INDEX `goods_sku_id_fkey`(`sku_id`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `good_categories` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`name` VARCHAR(100) NOT NULL,
|
||||||
|
`description` TEXT NULL,
|
||||||
|
`image_url` VARCHAR(255) NULL,
|
||||||
|
`complex_id` VARCHAR(191) NULL,
|
||||||
|
`is_default_guild_good` BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
`guild_id` VARCHAR(191) NULL,
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`updated_at` TIMESTAMP(0) NOT NULL,
|
||||||
|
`deleted_at` TIMESTAMP(0) NULL,
|
||||||
|
|
||||||
|
INDEX `good_categories_complex_id_fkey`(`complex_id`),
|
||||||
|
INDEX `good_categories_guild_id_fkey`(`guild_id`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `guilds` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`name` VARCHAR(191) NOT NULL,
|
||||||
|
`invoice_template` ENUM('SALE', 'FX_SALE', 'GOLD_JEWELRY', 'CONTRACT', 'UTILITY', 'AIR_TICKET', 'EXPORT', 'BILL_OF_LADING', 'PETROCHEMICAL', 'COMMODITY_EXCHANGE', 'INSURANCE') NOT NULL,
|
||||||
|
`code` VARCHAR(191) NULL,
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`updated_at` TIMESTAMP(0) NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `measure_units` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`code` VARCHAR(191) NOT NULL,
|
||||||
|
`name` VARCHAR(191) NOT NULL,
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`updated_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
|
||||||
|
UNIQUE INDEX `measure_units_code_key`(`code`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `stock_keeping_units` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`code` VARCHAR(191) NOT NULL,
|
||||||
|
`name` VARCHAR(191) NOT NULL,
|
||||||
|
`VAT` DECIMAL(5, 2) NOT NULL,
|
||||||
|
`is_public` BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
`is_domestic` BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
`guild_id` VARCHAR(191) NOT NULL,
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`updated_at` TIMESTAMP(0) NOT NULL,
|
||||||
|
|
||||||
|
UNIQUE INDEX `stock_keeping_units_code_key`(`code`),
|
||||||
|
INDEX `stock_keeping_units_code_idx`(`code`),
|
||||||
|
INDEX `stock_keeping_units_guild_id_fkey`(`guild_id`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `trigger_logs` (
|
||||||
|
`id` INTEGER NOT NULL AUTO_INCREMENT,
|
||||||
|
`message` TEXT NOT NULL,
|
||||||
|
`createdAt` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`name` TEXT NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `customers` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`is_favorite` BOOLEAN NULL DEFAULT false,
|
||||||
|
`type` ENUM('INDIVIDUAL', 'LEGAL', 'UNKNOWN') NOT NULL,
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`updated_at` TIMESTAMP(0) NOT NULL,
|
||||||
|
`deleted_at` TIMESTAMP(0) NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `customer_individuals` (
|
||||||
|
`first_name` VARCHAR(255) NOT NULL,
|
||||||
|
`last_name` VARCHAR(255) NOT NULL,
|
||||||
|
`national_id` CHAR(10) NOT NULL,
|
||||||
|
`mobile_number` CHAR(15) NOT NULL,
|
||||||
|
`postal_code` CHAR(10) NOT NULL,
|
||||||
|
`economic_code` CHAR(10) NULL,
|
||||||
|
`customer_id` VARCHAR(191) NOT NULL,
|
||||||
|
`business_activity_id` VARCHAR(191) NOT NULL,
|
||||||
|
|
||||||
|
INDEX `customer_individuals_business_activity_id_idx`(`business_activity_id`),
|
||||||
|
UNIQUE INDEX `customer_individuals_business_activity_id_national_id_key`(`business_activity_id`, `national_id`),
|
||||||
|
PRIMARY KEY (`customer_id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `customer_legal` (
|
||||||
|
`name` VARCHAR(255) NOT NULL,
|
||||||
|
`economic_code` CHAR(10) NOT NULL,
|
||||||
|
`registration_number` CHAR(20) NULL,
|
||||||
|
`postal_code` CHAR(10) NOT NULL,
|
||||||
|
`customer_id` VARCHAR(191) NOT NULL,
|
||||||
|
`business_activity_id` VARCHAR(191) NOT NULL,
|
||||||
|
|
||||||
|
INDEX `customer_legal_business_activity_id_idx`(`business_activity_id`),
|
||||||
|
UNIQUE INDEX `customer_legal_business_activity_id_economic_code_key`(`business_activity_id`, `economic_code`),
|
||||||
|
PRIMARY KEY (`customer_id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `sales_invoices` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`code` VARCHAR(100) NOT NULL,
|
||||||
|
`total_amount` DECIMAL(15, 2) NOT NULL,
|
||||||
|
`invoice_number` INTEGER NOT NULL,
|
||||||
|
`invoice_date` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`type` ENUM('ORIGINAL', 'CORRECTION', 'REVOKE', 'RETURN') NOT NULL,
|
||||||
|
`tax_id` VARCHAR(32) NULL,
|
||||||
|
`notes` TEXT NULL,
|
||||||
|
`unknown_customer` JSON NULL,
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`updated_at` TIMESTAMP(0) NOT NULL,
|
||||||
|
`main_id` VARCHAR(50) NULL,
|
||||||
|
`ref_id` VARCHAR(50) NULL,
|
||||||
|
`customer_id` VARCHAR(191) NULL,
|
||||||
|
`consumer_account_id` VARCHAR(191) NOT NULL,
|
||||||
|
`pos_id` VARCHAR(191) NOT NULL,
|
||||||
|
`settlement_type` ENUM('CASH', 'CREDIT', 'MIXED') NOT NULL,
|
||||||
|
`discount_amount` DECIMAL(15, 2) NULL,
|
||||||
|
`tax_amount` DECIMAL(15, 2) NULL,
|
||||||
|
|
||||||
|
UNIQUE INDEX `sales_invoices_code_key`(`code`),
|
||||||
|
UNIQUE INDEX `sales_invoices_tax_id_key`(`tax_id`),
|
||||||
|
UNIQUE INDEX `sales_invoices_ref_id_key`(`ref_id`),
|
||||||
|
INDEX `sales_invoices_ref_id_idx`(`ref_id`),
|
||||||
|
INDEX `sales_invoices_tax_id_idx`(`tax_id`),
|
||||||
|
INDEX `sales_invoices_consumer_account_id_fkey`(`consumer_account_id`),
|
||||||
|
INDEX `sales_invoices_customer_id_fkey`(`customer_id`),
|
||||||
|
INDEX `sales_invoices_pos_id_fkey`(`pos_id`),
|
||||||
|
UNIQUE INDEX `sales_invoices_invoice_number_pos_id_key`(`invoice_number`, `pos_id`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `sales_invoice_items` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`quantity` DECIMAL(10, 0) NOT NULL,
|
||||||
|
`measure_unit_text` VARCHAR(50) NOT NULL,
|
||||||
|
`measure_unit_code` VARCHAR(50) NOT NULL,
|
||||||
|
`sku_code` VARCHAR(50) NOT NULL,
|
||||||
|
`sku_vat` DECIMAL(15, 2) NOT NULL DEFAULT 0.00,
|
||||||
|
`unit_price` DECIMAL(15, 2) NOT NULL DEFAULT 0.00,
|
||||||
|
`total_amount` DECIMAL(15, 2) NOT NULL DEFAULT 0.00,
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`discount` DECIMAL(15, 2) NOT NULL DEFAULT 0.00,
|
||||||
|
`notes` TEXT NULL,
|
||||||
|
`payload` JSON NULL,
|
||||||
|
`good_snapshot` JSON NOT NULL,
|
||||||
|
`invoice_id` VARCHAR(191) NOT NULL,
|
||||||
|
`good_id` VARCHAR(191) NOT NULL,
|
||||||
|
`service_id` VARCHAR(191) NULL,
|
||||||
|
`discount_amount` DECIMAL(15, 2) NULL,
|
||||||
|
`tax_amount` DECIMAL(15, 2) NULL,
|
||||||
|
|
||||||
|
INDEX `sales_invoice_items_invoice_id_good_id_idx`(`invoice_id`, `good_id`),
|
||||||
|
INDEX `sales_invoice_items_good_id_fkey`(`good_id`),
|
||||||
|
INDEX `sales_invoice_items_service_id_fkey`(`service_id`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `sale_invoice_tsp_attempts` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`attempt_no` INTEGER NOT NULL,
|
||||||
|
`status` ENUM('NOT_SEND', 'QUEUED', 'FISCAL_QUEUED', 'SEND_FAILURE', 'SUCCESS', 'FAILURE') NOT NULL,
|
||||||
|
`message` TEXT NOT NULL,
|
||||||
|
`sent_at` TIMESTAMP(0) NULL,
|
||||||
|
`received_at` TIMESTAMP(0) NULL,
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`invoice_id` VARCHAR(191) NOT NULL,
|
||||||
|
`provider_request_payload` JSON NOT NULL,
|
||||||
|
`raw_request_payload` JSON NOT NULL,
|
||||||
|
`error_message` TEXT NULL,
|
||||||
|
`fiscal_warnings` JSON NULL,
|
||||||
|
`provider_response` JSON NULL,
|
||||||
|
`validation_errors` JSON NULL,
|
||||||
|
|
||||||
|
INDEX `sale_invoice_tsp_attempts_status_idx`(`status`),
|
||||||
|
INDEX `sale_invoice_tsp_attempts_invoice_id_idx`(`invoice_id`),
|
||||||
|
UNIQUE INDEX `sale_invoice_tsp_attempts_invoice_id_attempt_no_key`(`invoice_id`, `attempt_no`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `sales_invoice_payments` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`amount` DECIMAL(15, 2) NOT NULL,
|
||||||
|
`payment_method` ENUM('CHEQUE', 'SET_OFF', 'CASH', 'TERMINAL', 'PAYMENT_GATEWAY', 'CARD', 'BANK', 'OTHER') NOT NULL,
|
||||||
|
`paid_at` TIMESTAMP(0) NOT NULL,
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`invoice_id` VARCHAR(191) NOT NULL,
|
||||||
|
|
||||||
|
INDEX `sales_invoice_payments_invoice_id_idx`(`invoice_id`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `sales_invoice_payment_terminal_info` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`terminal_id` VARCHAR(191) NOT NULL,
|
||||||
|
`stan` VARCHAR(191) NOT NULL,
|
||||||
|
`rrn` VARCHAR(191) NOT NULL,
|
||||||
|
`transaction_date_time` DATETIME(3) NOT NULL,
|
||||||
|
`customer_card_no` VARCHAR(191) NULL,
|
||||||
|
`description` VARCHAR(191) NULL,
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`payment_id` VARCHAR(191) NOT NULL,
|
||||||
|
|
||||||
|
UNIQUE INDEX `sales_invoice_payment_terminal_info_payment_id_key`(`payment_id`),
|
||||||
|
UNIQUE INDEX `sales_invoice_payment_terminal_info_terminal_id_stan_rrn_pay_key`(`terminal_id`, `stan`, `rrn`, `payment_id`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `services` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`name` VARCHAR(255) NOT NULL,
|
||||||
|
`description` TEXT NULL,
|
||||||
|
`sku` VARCHAR(100) NOT NULL,
|
||||||
|
`local_sku` VARCHAR(100) NULL,
|
||||||
|
`barcode` VARCHAR(100) NULL,
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`updated_at` TIMESTAMP(0) NOT NULL,
|
||||||
|
`deleted_at` TIMESTAMP(0) NULL,
|
||||||
|
`category_id` VARCHAR(191) NULL,
|
||||||
|
`base_sale_price` DECIMAL(15, 0) NOT NULL DEFAULT 0,
|
||||||
|
`account_id` VARCHAR(191) NOT NULL,
|
||||||
|
`complex_id` VARCHAR(191) NOT NULL,
|
||||||
|
|
||||||
|
UNIQUE INDEX `services_sku_key`(`sku`),
|
||||||
|
UNIQUE INDEX `services_local_sku_key`(`local_sku`),
|
||||||
|
UNIQUE INDEX `services_barcode_key`(`barcode`),
|
||||||
|
INDEX `services_category_id_idx`(`category_id`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `service_categories` (
|
||||||
|
`id` VARCHAR(191) NOT NULL,
|
||||||
|
`name` VARCHAR(100) NOT NULL,
|
||||||
|
`description` TEXT NULL,
|
||||||
|
`image_url` VARCHAR(255) NULL,
|
||||||
|
`account_id` VARCHAR(191) NOT NULL,
|
||||||
|
`complex_id` VARCHAR(191) NOT NULL,
|
||||||
|
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
||||||
|
`updated_at` TIMESTAMP(0) NOT NULL,
|
||||||
|
`deleted_at` TIMESTAMP(0) NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `admin_accounts` ADD CONSTRAINT `admin_accounts_account_id_fkey` FOREIGN KEY (`account_id`) REFERENCES `accounts`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `admin_accounts` ADD CONSTRAINT `admin_accounts_admin_id_fkey` FOREIGN KEY (`admin_id`) REFERENCES `admins`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `devices` ADD CONSTRAINT `devices_brand_id_fkey` FOREIGN KEY (`brand_id`) REFERENCES `device_brands`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `license_charged_transactions` ADD CONSTRAINT `license_charged_transactions_partner_id_fkey` FOREIGN KEY (`partner_id`) REFERENCES `partners`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `licenses` ADD CONSTRAINT `licenses_charge_transaction_id_fkey` FOREIGN KEY (`charge_transaction_id`) REFERENCES `license_charged_transactions`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `licenses_activated` ADD CONSTRAINT `licenses_activated_business_activity_id_fkey` FOREIGN KEY (`business_activity_id`) REFERENCES `business_activities`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `licenses_activated` ADD CONSTRAINT `licenses_activated_license_id_fkey` FOREIGN KEY (`license_id`) REFERENCES `licenses`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `license_renew_charge_transaction` ADD CONSTRAINT `license_renew_charge_transaction_partner_id_fkey` FOREIGN KEY (`partner_id`) REFERENCES `partners`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `license_renew` ADD CONSTRAINT `license_renew_activation_id_fkey` FOREIGN KEY (`activation_id`) REFERENCES `licenses_activated`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `license_renew` ADD CONSTRAINT `license_renew_charge_transaction_id_fkey` FOREIGN KEY (`charge_transaction_id`) REFERENCES `license_renew_charge_transaction`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `partner_account_quota_charge_transaction` ADD CONSTRAINT `partner_account_quota_charge_transaction_partner_id_fkey` FOREIGN KEY (`partner_id`) REFERENCES `partners`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `partner_account_quota_credit` ADD CONSTRAINT `partner_account_quota_credit_charge_transaction_id_fkey` FOREIGN KEY (`charge_transaction_id`) REFERENCES `partner_account_quota_charge_transaction`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `license_account_allocation` ADD CONSTRAINT `license_account_allocation_account_id_fkey` FOREIGN KEY (`account_id`) REFERENCES `consumer_accounts`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `license_account_allocation` ADD CONSTRAINT `license_account_allocation_credit_id_fkey` FOREIGN KEY (`credit_id`) REFERENCES `partner_account_quota_credit`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `license_account_allocation` ADD CONSTRAINT `license_account_allocation_license_activation_id_fkey` FOREIGN KEY (`license_activation_id`) REFERENCES `licenses_activated`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `partner_accounts` ADD CONSTRAINT `partner_accounts_account_id_fkey` FOREIGN KEY (`account_id`) REFERENCES `accounts`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `partner_accounts` ADD CONSTRAINT `partner_accounts_partner_id_fkey` FOREIGN KEY (`partner_id`) REFERENCES `partners`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `permission_consumers` ADD CONSTRAINT `permission_consumers_consumer_account_id_fkey` FOREIGN KEY (`consumer_account_id`) REFERENCES `consumer_accounts`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `permission_poses` ADD CONSTRAINT `permission_poses_permission_id_fkey` FOREIGN KEY (`permission_id`) REFERENCES `permission_consumers`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `permission_poses` ADD CONSTRAINT `permission_poses_pos_id_fkey` FOREIGN KEY (`pos_id`) REFERENCES `poses`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `permission_complexes` ADD CONSTRAINT `permission_complexes_complex_id_fkey` FOREIGN KEY (`complex_id`) REFERENCES `complexes`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `permission_complexes` ADD CONSTRAINT `permission_complexes_permission_id_fkey` FOREIGN KEY (`permission_id`) REFERENCES `permission_consumers`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `permission_business_activities` ADD CONSTRAINT `permission_business_activities_business_id_fkey` FOREIGN KEY (`business_id`) REFERENCES `business_activities`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `permission_business_activities` ADD CONSTRAINT `permission_business_activities_permission_id_fkey` FOREIGN KEY (`permission_id`) REFERENCES `permission_consumers`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `provider_accounts` ADD CONSTRAINT `provider_accounts_account_id_fkey` FOREIGN KEY (`account_id`) REFERENCES `accounts`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `provider_accounts` ADD CONSTRAINT `provider_accounts_provider_id_fkey` FOREIGN KEY (`provider_id`) REFERENCES `providers`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `consumer_account_device` ADD CONSTRAINT `consumer_account_device_consumer_account_id_fkey` FOREIGN KEY (`consumer_account_id`) REFERENCES `consumer_accounts`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `consumer_accounts` ADD CONSTRAINT `consumer_accounts_account_id_fkey` FOREIGN KEY (`account_id`) REFERENCES `accounts`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `consumer_accounts` ADD CONSTRAINT `consumer_accounts_consumer_id_fkey` FOREIGN KEY (`consumer_id`) REFERENCES `consumers`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `consumers_individual` ADD CONSTRAINT `consumers_individual_consumer_id_fkey` FOREIGN KEY (`consumer_id`) REFERENCES `consumers`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `consumers_individual` ADD CONSTRAINT `consumers_individual_partner_id_fkey` FOREIGN KEY (`partner_id`) REFERENCES `partners`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `consumers_legal` ADD CONSTRAINT `consumers_legal_consumer_id_fkey` FOREIGN KEY (`consumer_id`) REFERENCES `consumers`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `consumers_legal` ADD CONSTRAINT `consumers_legal_partner_id_fkey` FOREIGN KEY (`partner_id`) REFERENCES `partners`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `business_activities` ADD CONSTRAINT `business_activities_consumer_id_fkey` FOREIGN KEY (`consumer_id`) REFERENCES `consumers`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `business_activities` ADD CONSTRAINT `business_activities_guild_id_fkey` FOREIGN KEY (`guild_id`) REFERENCES `guilds`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `complexes` ADD CONSTRAINT `complexes_business_activity_id_fkey` FOREIGN KEY (`business_activity_id`) REFERENCES `business_activities`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `poses` ADD CONSTRAINT `poses_account_id_fkey` FOREIGN KEY (`account_id`) REFERENCES `consumer_accounts`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `poses` ADD CONSTRAINT `poses_complex_id_fkey` FOREIGN KEY (`complex_id`) REFERENCES `complexes`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `poses` ADD CONSTRAINT `poses_device_id_fkey` FOREIGN KEY (`device_id`) REFERENCES `devices`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `poses` ADD CONSTRAINT `poses_provider_id_fkey` FOREIGN KEY (`provider_id`) REFERENCES `providers`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `consumer_account_good_favorites` ADD CONSTRAINT `consumer_account_good_favorites_consumer_account_id_fkey` FOREIGN KEY (`consumer_account_id`) REFERENCES `consumer_accounts`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `consumer_account_good_favorites` ADD CONSTRAINT `consumer_account_good_favorites_good_id_fkey` FOREIGN KEY (`good_id`) REFERENCES `goods`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `goods` ADD CONSTRAINT `goods_business_activity_id_fkey` FOREIGN KEY (`business_activity_id`) REFERENCES `business_activities`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `goods` ADD CONSTRAINT `goods_category_id_fkey` FOREIGN KEY (`category_id`) REFERENCES `good_categories`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `goods` ADD CONSTRAINT `goods_measure_unit_id_fkey` FOREIGN KEY (`measure_unit_id`) REFERENCES `measure_units`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `goods` ADD CONSTRAINT `goods_sku_id_fkey` FOREIGN KEY (`sku_id`) REFERENCES `stock_keeping_units`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `good_categories` ADD CONSTRAINT `good_categories_complex_id_fkey` FOREIGN KEY (`complex_id`) REFERENCES `complexes`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `good_categories` ADD CONSTRAINT `good_categories_guild_id_fkey` FOREIGN KEY (`guild_id`) REFERENCES `guilds`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `stock_keeping_units` ADD CONSTRAINT `stock_keeping_units_guild_id_fkey` FOREIGN KEY (`guild_id`) REFERENCES `guilds`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `customer_individuals` ADD CONSTRAINT `customer_individuals_business_activity_id_fkey` FOREIGN KEY (`business_activity_id`) REFERENCES `business_activities`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `customer_individuals` ADD CONSTRAINT `customer_individuals_customer_id_fkey` FOREIGN KEY (`customer_id`) REFERENCES `customers`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `customer_legal` ADD CONSTRAINT `customer_legal_business_activity_id_fkey` FOREIGN KEY (`business_activity_id`) REFERENCES `business_activities`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `customer_legal` ADD CONSTRAINT `customer_legal_customer_id_fkey` FOREIGN KEY (`customer_id`) REFERENCES `customers`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `sales_invoices` ADD CONSTRAINT `sales_invoices_consumer_account_id_fkey` FOREIGN KEY (`consumer_account_id`) REFERENCES `consumer_accounts`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `sales_invoices` ADD CONSTRAINT `sales_invoices_customer_id_fkey` FOREIGN KEY (`customer_id`) REFERENCES `customers`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `sales_invoices` ADD CONSTRAINT `sales_invoices_pos_id_fkey` FOREIGN KEY (`pos_id`) REFERENCES `poses`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `sales_invoices` ADD CONSTRAINT `sales_invoices_ref_id_fkey` FOREIGN KEY (`ref_id`) REFERENCES `sales_invoices`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `sales_invoice_items` ADD CONSTRAINT `sales_invoice_items_good_id_fkey` FOREIGN KEY (`good_id`) REFERENCES `goods`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `sales_invoice_items` ADD CONSTRAINT `sales_invoice_items_invoice_id_fkey` FOREIGN KEY (`invoice_id`) REFERENCES `sales_invoices`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `sales_invoice_items` ADD CONSTRAINT `sales_invoice_items_service_id_fkey` FOREIGN KEY (`service_id`) REFERENCES `services`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `sale_invoice_tsp_attempts` ADD CONSTRAINT `sale_invoice_tsp_attempts_invoice_id_fkey` FOREIGN KEY (`invoice_id`) REFERENCES `sales_invoices`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `sales_invoice_payments` ADD CONSTRAINT `sales_invoice_payments_invoice_id_fkey` FOREIGN KEY (`invoice_id`) REFERENCES `sales_invoices`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `sales_invoice_payment_terminal_info` ADD CONSTRAINT `sales_invoice_payment_terminal_info_payment_id_fkey` FOREIGN KEY (`payment_id`) REFERENCES `sales_invoice_payments`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `services` ADD CONSTRAINT `services_category_id_fkey` FOREIGN KEY (`category_id`) REFERENCES `service_categories`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
|
||||||
@@ -1,571 +0,0 @@
|
|||||||
-- CreateTable
|
|
||||||
CREATE TABLE `admin_accounts` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`updated_at` TIMESTAMP(0) NOT NULL,
|
|
||||||
`admin_id` VARCHAR(191) NOT NULL,
|
|
||||||
`account_id` VARCHAR(191) NOT NULL,
|
|
||||||
|
|
||||||
UNIQUE INDEX `admin_accounts_account_id_key`(`account_id`),
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `admins` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`mobile_number` VARCHAR(191) NOT NULL,
|
|
||||||
`national_code` VARCHAR(191) NULL,
|
|
||||||
`first_name` VARCHAR(191) NOT NULL,
|
|
||||||
`last_name` VARCHAR(191) NOT NULL,
|
|
||||||
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`updated_at` TIMESTAMP(0) NOT NULL,
|
|
||||||
|
|
||||||
UNIQUE INDEX `admins_mobile_number_key`(`mobile_number`),
|
|
||||||
UNIQUE INDEX `admins_national_code_key`(`national_code`),
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `accounts` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`username` VARCHAR(191) NOT NULL,
|
|
||||||
`password` VARCHAR(191) NOT NULL,
|
|
||||||
`status` ENUM('ACTIVE', 'SUSPENDED') NOT NULL,
|
|
||||||
`type` ENUM('ADMIN', 'PROVIDER', 'PARTNER', 'CONSUMER') NOT NULL,
|
|
||||||
|
|
||||||
UNIQUE INDEX `accounts_username_key`(`username`),
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `consumer_accounts` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`role` ENUM('OWNER', 'MANAGER', 'OPERATOR') NOT NULL,
|
|
||||||
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`updated_at` TIMESTAMP(0) NOT NULL,
|
|
||||||
`consumer_id` VARCHAR(191) NOT NULL,
|
|
||||||
`account_id` VARCHAR(191) NOT NULL,
|
|
||||||
|
|
||||||
UNIQUE INDEX `consumer_accounts_account_id_key`(`account_id`),
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `consumers` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`mobile_number` VARCHAR(191) NOT NULL,
|
|
||||||
`first_name` VARCHAR(191) NOT NULL,
|
|
||||||
`last_name` VARCHAR(191) NOT NULL,
|
|
||||||
`status` ENUM('ACTIVE', 'SUSPENDED') NOT NULL DEFAULT 'ACTIVE',
|
|
||||||
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`updated_at` TIMESTAMP(0) NOT NULL,
|
|
||||||
|
|
||||||
UNIQUE INDEX `consumers_mobile_number_key`(`mobile_number`),
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `business_activities` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`name` VARCHAR(191) NOT NULL,
|
|
||||||
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`updated_at` TIMESTAMP(0) NOT NULL,
|
|
||||||
`guild_id` VARCHAR(191) NOT NULL,
|
|
||||||
`consumer_id` VARCHAR(191) NOT NULL,
|
|
||||||
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `complexes` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`name` VARCHAR(191) NOT NULL,
|
|
||||||
`address` VARCHAR(191) NULL,
|
|
||||||
`tax_id` VARCHAR(191) NULL,
|
|
||||||
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`updated_at` TIMESTAMP(0) NOT NULL,
|
|
||||||
`business_activity_id` VARCHAR(191) NOT NULL,
|
|
||||||
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `poses` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`name` VARCHAR(191) NOT NULL,
|
|
||||||
`serial` VARCHAR(191) NOT NULL,
|
|
||||||
`model` VARCHAR(191) NULL,
|
|
||||||
`status` ENUM('ACTIVE', 'DISABLED') NOT NULL DEFAULT 'ACTIVE',
|
|
||||||
`pos_type` ENUM('PSP', 'MOBILE', 'WEB', 'API') NOT NULL,
|
|
||||||
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`updated_at` TIMESTAMP(0) NOT NULL,
|
|
||||||
`complex_id` VARCHAR(191) NOT NULL,
|
|
||||||
`device_id` VARCHAR(191) NULL,
|
|
||||||
`provider_id` VARCHAR(191) NULL,
|
|
||||||
|
|
||||||
UNIQUE INDEX `poses_serial_key`(`serial`),
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `device_brands` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`name` VARCHAR(191) NOT NULL,
|
|
||||||
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`updated_at` TIMESTAMP(0) NOT NULL,
|
|
||||||
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `devices` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`name` VARCHAR(191) NOT NULL,
|
|
||||||
`os_version` VARCHAR(191) NULL,
|
|
||||||
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`updated_at` TIMESTAMP(0) NOT NULL,
|
|
||||||
`brand_id` VARCHAR(191) NOT NULL,
|
|
||||||
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `licenses` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`starts_at` DATETIME(3) NOT NULL,
|
|
||||||
`expires_at` DATETIME(3) NOT NULL,
|
|
||||||
`status` ENUM('ACTIVE', 'EXPIRED', 'SUSPENDED') NOT NULL,
|
|
||||||
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`updated_at` TIMESTAMP(0) NOT NULL,
|
|
||||||
`partner_id` VARCHAR(191) NULL,
|
|
||||||
`consumer_id` VARCHAR(191) NOT NULL,
|
|
||||||
|
|
||||||
UNIQUE INDEX `licenses_consumer_id_key`(`consumer_id`),
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `partner_accounts` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`role` ENUM('OWNER', 'MANAGER', 'OPERATOR') NOT NULL,
|
|
||||||
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`updated_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`partner_id` VARCHAR(191) NOT NULL,
|
|
||||||
`account_id` VARCHAR(191) NOT NULL,
|
|
||||||
|
|
||||||
UNIQUE INDEX `partner_accounts_account_id_key`(`account_id`),
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `partners` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`name` VARCHAR(191) NOT NULL,
|
|
||||||
`code` VARCHAR(191) NOT NULL,
|
|
||||||
`license_quota` INTEGER NULL DEFAULT 0,
|
|
||||||
`status` ENUM('ACTIVE', 'SUSPENDED') NOT NULL DEFAULT 'ACTIVE',
|
|
||||||
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`updated_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
|
|
||||||
UNIQUE INDEX `partners_code_key`(`code`),
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `permission_consumers` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`consumer_account_id` VARCHAR(191) NOT NULL,
|
|
||||||
|
|
||||||
UNIQUE INDEX `permission_consumers_consumer_account_id_key`(`consumer_account_id`),
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `permission_poses` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`role` ENUM('MANAGER', 'OPERATOR') NOT NULL,
|
|
||||||
`pos_id` VARCHAR(191) NOT NULL,
|
|
||||||
`permission_id` VARCHAR(191) NOT NULL,
|
|
||||||
|
|
||||||
UNIQUE INDEX `permission_poses_permission_id_pos_id_key`(`permission_id`, `pos_id`),
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `permission_complexes` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`role` ENUM('MANAGER', 'OPERATOR') NOT NULL,
|
|
||||||
`complex_id` VARCHAR(191) NOT NULL,
|
|
||||||
`permission_id` VARCHAR(191) NOT NULL,
|
|
||||||
|
|
||||||
UNIQUE INDEX `permission_complexes_permission_id_complex_id_key`(`permission_id`, `complex_id`),
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `permission_business_activities` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`role` ENUM('MANAGER', 'OPERATOR') NOT NULL,
|
|
||||||
`business_id` VARCHAR(191) NOT NULL,
|
|
||||||
`permission_id` VARCHAR(191) NOT NULL,
|
|
||||||
|
|
||||||
UNIQUE INDEX `permission_business_activities_permission_id_business_id_key`(`permission_id`, `business_id`),
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `provider_accounts` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`role` ENUM('OWNER', 'MANAGER', 'OPERATOR') NOT NULL,
|
|
||||||
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`updated_at` TIMESTAMP(0) NOT NULL,
|
|
||||||
`provider_id` VARCHAR(191) NOT NULL,
|
|
||||||
`account_id` VARCHAR(191) NOT NULL,
|
|
||||||
|
|
||||||
UNIQUE INDEX `provider_accounts_account_id_key`(`account_id`),
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `providers` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`code` VARCHAR(191) NOT NULL,
|
|
||||||
`status` ENUM('ACTIVE', 'SUSPENDED') NOT NULL DEFAULT 'ACTIVE',
|
|
||||||
`name` VARCHAR(191) NOT NULL,
|
|
||||||
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`updated_at` TIMESTAMP(0) NOT NULL,
|
|
||||||
|
|
||||||
UNIQUE INDEX `providers_code_key`(`code`),
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `trigger_logs` (
|
|
||||||
`id` INTEGER NOT NULL AUTO_INCREMENT,
|
|
||||||
`message` TEXT NOT NULL,
|
|
||||||
`createdAt` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`name` TEXT NOT NULL,
|
|
||||||
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `user_devices` (
|
|
||||||
`account_id` VARCHAR(255) NULL,
|
|
||||||
`app_version` VARCHAR(20) NOT NULL,
|
|
||||||
`build_number` VARCHAR(20) NOT NULL,
|
|
||||||
`uuid` VARCHAR(255) NOT NULL,
|
|
||||||
`platform` VARCHAR(100) NOT NULL,
|
|
||||||
`brand` VARCHAR(100) NOT NULL,
|
|
||||||
`model` VARCHAR(100) NOT NULL,
|
|
||||||
`device` VARCHAR(100) NOT NULL,
|
|
||||||
`os_version` VARCHAR(20) NOT NULL,
|
|
||||||
`sdk_version` VARCHAR(20) NOT NULL,
|
|
||||||
`release_number` VARCHAR(20) NOT NULL,
|
|
||||||
`browser_name` VARCHAR(100) NULL,
|
|
||||||
`fcm_token` VARCHAR(100) NULL,
|
|
||||||
|
|
||||||
UNIQUE INDEX `user_devices_uuid_key`(`uuid`),
|
|
||||||
PRIMARY KEY (`uuid`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `customers` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`is_favorite` BOOLEAN NULL DEFAULT false,
|
|
||||||
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`updated_at` TIMESTAMP(0) NOT NULL,
|
|
||||||
`deleted_at` TIMESTAMP(0) NULL,
|
|
||||||
`type` ENUM('INDIVIDUAL', 'LEGAL', 'UNKNOWN') NOT NULL,
|
|
||||||
`unknown_customer` JSON NULL,
|
|
||||||
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `customer_individuals` (
|
|
||||||
`first_name` VARCHAR(255) NOT NULL,
|
|
||||||
`last_name` VARCHAR(255) NOT NULL,
|
|
||||||
`national_id` CHAR(10) NOT NULL,
|
|
||||||
`postal_code` CHAR(10) NOT NULL,
|
|
||||||
`economic_code` CHAR(10) NULL,
|
|
||||||
`customer_id` VARCHAR(191) NOT NULL,
|
|
||||||
`complex_id` VARCHAR(191) NOT NULL,
|
|
||||||
|
|
||||||
INDEX `customer_individuals_complex_id_idx`(`complex_id`),
|
|
||||||
UNIQUE INDEX `customer_individuals_complex_id_national_id_key`(`complex_id`, `national_id`),
|
|
||||||
PRIMARY KEY (`customer_id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `customer_legal` (
|
|
||||||
`company_name` VARCHAR(255) NOT NULL,
|
|
||||||
`economic_code` CHAR(10) NOT NULL,
|
|
||||||
`registration_number` CHAR(20) NOT NULL,
|
|
||||||
`postal_code` CHAR(10) NOT NULL,
|
|
||||||
`customer_id` VARCHAR(191) NOT NULL,
|
|
||||||
`complex_id` VARCHAR(191) NOT NULL,
|
|
||||||
|
|
||||||
INDEX `customer_legal_complex_id_idx`(`complex_id`),
|
|
||||||
UNIQUE INDEX `customer_legal_complex_id_registration_number_key`(`complex_id`, `registration_number`),
|
|
||||||
PRIMARY KEY (`customer_id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `goods` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`name` VARCHAR(255) NOT NULL,
|
|
||||||
`is_default_guild_good` BOOLEAN NOT NULL DEFAULT false,
|
|
||||||
`sku` VARCHAR(100) NOT NULL,
|
|
||||||
`unit_type` ENUM('COUNT', 'GRAM', 'KILOGRAM', 'MILLILITER', 'LITER', 'METER', 'HOUR') NOT NULL,
|
|
||||||
`pricing_model` ENUM('STANDARD', 'GOLD') NOT NULL,
|
|
||||||
`description` TEXT NULL,
|
|
||||||
`local_sku` VARCHAR(100) NULL,
|
|
||||||
`barcode` VARCHAR(100) NULL,
|
|
||||||
`base_sale_price` DECIMAL(15, 0) NULL DEFAULT 0.00,
|
|
||||||
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`updated_at` TIMESTAMP(0) NOT NULL,
|
|
||||||
`deleted_at` TIMESTAMP(0) NULL,
|
|
||||||
`complex_id` VARCHAR(191) NULL,
|
|
||||||
`category_id` VARCHAR(191) NULL,
|
|
||||||
|
|
||||||
UNIQUE INDEX `goods_local_sku_key`(`local_sku`),
|
|
||||||
UNIQUE INDEX `goods_barcode_key`(`barcode`),
|
|
||||||
INDEX `goods_category_id_idx`(`category_id`),
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `good_categories` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`name` VARCHAR(100) NOT NULL,
|
|
||||||
`description` TEXT NULL,
|
|
||||||
`image_url` VARCHAR(255) NULL,
|
|
||||||
`complex_id` VARCHAR(191) NULL,
|
|
||||||
`is_default_guild_good` BOOLEAN NOT NULL DEFAULT false,
|
|
||||||
`guild_id` VARCHAR(191) NULL,
|
|
||||||
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`updated_at` TIMESTAMP(0) NOT NULL,
|
|
||||||
`deleted_at` TIMESTAMP(0) NULL,
|
|
||||||
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `guilds` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`name` VARCHAR(191) NOT NULL,
|
|
||||||
`code` VARCHAR(191) NULL,
|
|
||||||
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`updated_at` TIMESTAMP(0) NOT NULL,
|
|
||||||
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `sales_invoices` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`code` VARCHAR(100) NOT NULL,
|
|
||||||
`total_amount` DECIMAL(15, 2) NOT NULL,
|
|
||||||
`notes` TEXT NULL,
|
|
||||||
`unknown_customer` JSON NULL,
|
|
||||||
`invoice_date` TIMESTAMP(0) NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`updated_at` TIMESTAMP(0) NOT NULL,
|
|
||||||
`customer_id` VARCHAR(191) NULL,
|
|
||||||
`account_id` VARCHAR(191) NOT NULL,
|
|
||||||
`pos_id` VARCHAR(191) NOT NULL,
|
|
||||||
|
|
||||||
UNIQUE INDEX `sales_invoices_code_key`(`code`),
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `sales_invoice_items` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`quantity` DECIMAL(10, 0) NOT NULL,
|
|
||||||
`unit_type` ENUM('COUNT', 'GRAM', 'KILOGRAM', 'MILLILITER', 'LITER', 'METER', 'HOUR') NOT NULL,
|
|
||||||
`unit_price` DECIMAL(15, 2) NOT NULL DEFAULT 0.00,
|
|
||||||
`total_amount` DECIMAL(15, 2) NOT NULL DEFAULT 0.00,
|
|
||||||
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`discount` DECIMAL(15, 2) NOT NULL DEFAULT 0.00,
|
|
||||||
`notes` TEXT NULL,
|
|
||||||
`invoice_id` VARCHAR(191) NOT NULL,
|
|
||||||
`good_id` VARCHAR(191) NULL,
|
|
||||||
`service_id` VARCHAR(191) NULL,
|
|
||||||
`payload` JSON NULL,
|
|
||||||
|
|
||||||
INDEX `sales_invoice_items_invoice_id_good_id_idx`(`invoice_id`, `good_id`),
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `sales_invoice_payments` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`invoice_id` VARCHAR(191) NOT NULL,
|
|
||||||
`amount` DECIMAL(15, 2) NOT NULL,
|
|
||||||
`payment_method` ENUM('TERMINAL', 'CASH', 'SET_OFF', 'CARD', 'BANK', 'CHECK', 'OTHER') NOT NULL,
|
|
||||||
`paid_at` DATETIME(3) NOT NULL,
|
|
||||||
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
|
||||||
|
|
||||||
INDEX `sales_invoice_payments_invoice_id_idx`(`invoice_id`),
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `services` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`name` VARCHAR(255) NOT NULL,
|
|
||||||
`description` TEXT NULL,
|
|
||||||
`sku` VARCHAR(100) NOT NULL,
|
|
||||||
`local_sku` VARCHAR(100) NULL,
|
|
||||||
`barcode` VARCHAR(100) NULL,
|
|
||||||
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`updated_at` TIMESTAMP(0) NOT NULL,
|
|
||||||
`deleted_at` TIMESTAMP(0) NULL,
|
|
||||||
`category_id` VARCHAR(191) NULL,
|
|
||||||
`base_sale_price` DECIMAL(15, 0) NOT NULL DEFAULT 0.00,
|
|
||||||
`account_id` VARCHAR(191) NOT NULL,
|
|
||||||
`complex_id` VARCHAR(191) NOT NULL,
|
|
||||||
|
|
||||||
UNIQUE INDEX `services_sku_key`(`sku`),
|
|
||||||
UNIQUE INDEX `services_local_sku_key`(`local_sku`),
|
|
||||||
UNIQUE INDEX `services_barcode_key`(`barcode`),
|
|
||||||
INDEX `services_category_id_idx`(`category_id`),
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `service_categories` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`name` VARCHAR(100) NOT NULL,
|
|
||||||
`description` TEXT NULL,
|
|
||||||
`image_url` VARCHAR(255) NULL,
|
|
||||||
`account_id` VARCHAR(191) NOT NULL,
|
|
||||||
`complex_id` VARCHAR(191) NOT NULL,
|
|
||||||
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`updated_at` TIMESTAMP(0) NOT NULL,
|
|
||||||
`deleted_at` TIMESTAMP(0) NULL,
|
|
||||||
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `admin_accounts` ADD CONSTRAINT `admin_accounts_admin_id_fkey` FOREIGN KEY (`admin_id`) REFERENCES `admins`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `admin_accounts` ADD CONSTRAINT `admin_accounts_account_id_fkey` FOREIGN KEY (`account_id`) REFERENCES `accounts`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `consumer_accounts` ADD CONSTRAINT `consumer_accounts_consumer_id_fkey` FOREIGN KEY (`consumer_id`) REFERENCES `consumers`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `consumer_accounts` ADD CONSTRAINT `consumer_accounts_account_id_fkey` FOREIGN KEY (`account_id`) REFERENCES `accounts`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `business_activities` ADD CONSTRAINT `business_activities_guild_id_fkey` FOREIGN KEY (`guild_id`) REFERENCES `guilds`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `business_activities` ADD CONSTRAINT `business_activities_consumer_id_fkey` FOREIGN KEY (`consumer_id`) REFERENCES `consumers`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `complexes` ADD CONSTRAINT `complexes_business_activity_id_fkey` FOREIGN KEY (`business_activity_id`) REFERENCES `business_activities`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `poses` ADD CONSTRAINT `poses_complex_id_fkey` FOREIGN KEY (`complex_id`) REFERENCES `complexes`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `poses` ADD CONSTRAINT `poses_device_id_fkey` FOREIGN KEY (`device_id`) REFERENCES `devices`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `poses` ADD CONSTRAINT `poses_provider_id_fkey` FOREIGN KEY (`provider_id`) REFERENCES `providers`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `devices` ADD CONSTRAINT `devices_brand_id_fkey` FOREIGN KEY (`brand_id`) REFERENCES `device_brands`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `licenses` ADD CONSTRAINT `licenses_partner_id_fkey` FOREIGN KEY (`partner_id`) REFERENCES `partners`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `licenses` ADD CONSTRAINT `licenses_consumer_id_fkey` FOREIGN KEY (`consumer_id`) REFERENCES `consumers`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `partner_accounts` ADD CONSTRAINT `partner_accounts_partner_id_fkey` FOREIGN KEY (`partner_id`) REFERENCES `partners`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `partner_accounts` ADD CONSTRAINT `partner_accounts_account_id_fkey` FOREIGN KEY (`account_id`) REFERENCES `accounts`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `permission_consumers` ADD CONSTRAINT `permission_consumers_consumer_account_id_fkey` FOREIGN KEY (`consumer_account_id`) REFERENCES `consumer_accounts`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `permission_poses` ADD CONSTRAINT `permission_poses_pos_id_fkey` FOREIGN KEY (`pos_id`) REFERENCES `poses`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `permission_poses` ADD CONSTRAINT `permission_poses_permission_id_fkey` FOREIGN KEY (`permission_id`) REFERENCES `permission_consumers`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `permission_complexes` ADD CONSTRAINT `permission_complexes_complex_id_fkey` FOREIGN KEY (`complex_id`) REFERENCES `complexes`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `permission_complexes` ADD CONSTRAINT `permission_complexes_permission_id_fkey` FOREIGN KEY (`permission_id`) REFERENCES `permission_consumers`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `permission_business_activities` ADD CONSTRAINT `permission_business_activities_business_id_fkey` FOREIGN KEY (`business_id`) REFERENCES `business_activities`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `permission_business_activities` ADD CONSTRAINT `permission_business_activities_permission_id_fkey` FOREIGN KEY (`permission_id`) REFERENCES `permission_consumers`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `provider_accounts` ADD CONSTRAINT `provider_accounts_provider_id_fkey` FOREIGN KEY (`provider_id`) REFERENCES `providers`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `provider_accounts` ADD CONSTRAINT `provider_accounts_account_id_fkey` FOREIGN KEY (`account_id`) REFERENCES `accounts`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `customer_individuals` ADD CONSTRAINT `customer_individuals_customer_id_fkey` FOREIGN KEY (`customer_id`) REFERENCES `customers`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `customer_individuals` ADD CONSTRAINT `customer_individuals_complex_id_fkey` FOREIGN KEY (`complex_id`) REFERENCES `complexes`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `customer_legal` ADD CONSTRAINT `customer_legal_customer_id_fkey` FOREIGN KEY (`customer_id`) REFERENCES `customers`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `customer_legal` ADD CONSTRAINT `customer_legal_complex_id_fkey` FOREIGN KEY (`complex_id`) REFERENCES `complexes`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `goods` ADD CONSTRAINT `goods_category_id_fkey` FOREIGN KEY (`category_id`) REFERENCES `good_categories`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `goods` ADD CONSTRAINT `goods_complex_id_fkey` FOREIGN KEY (`complex_id`) REFERENCES `complexes`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `good_categories` ADD CONSTRAINT `good_categories_guild_id_fkey` FOREIGN KEY (`guild_id`) REFERENCES `guilds`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `good_categories` ADD CONSTRAINT `good_categories_complex_id_fkey` FOREIGN KEY (`complex_id`) REFERENCES `complexes`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `sales_invoices` ADD CONSTRAINT `sales_invoices_customer_id_fkey` FOREIGN KEY (`customer_id`) REFERENCES `customers`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `sales_invoices` ADD CONSTRAINT `sales_invoices_pos_id_fkey` FOREIGN KEY (`pos_id`) REFERENCES `poses`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `sales_invoices` ADD CONSTRAINT `sales_invoices_account_id_fkey` FOREIGN KEY (`account_id`) REFERENCES `consumer_accounts`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `sales_invoice_items` ADD CONSTRAINT `sales_invoice_items_invoice_id_fkey` FOREIGN KEY (`invoice_id`) REFERENCES `sales_invoices`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `sales_invoice_items` ADD CONSTRAINT `sales_invoice_items_good_id_fkey` FOREIGN KEY (`good_id`) REFERENCES `goods`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `sales_invoice_items` ADD CONSTRAINT `sales_invoice_items_service_id_fkey` FOREIGN KEY (`service_id`) REFERENCES `services`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `sales_invoice_payments` ADD CONSTRAINT `sales_invoice_payments_invoice_id_fkey` FOREIGN KEY (`invoice_id`) REFERENCES `sales_invoices`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `services` ADD CONSTRAINT `services_category_id_fkey` FOREIGN KEY (`category_id`) REFERENCES `service_categories`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
-- DropForeignKey
|
|
||||||
ALTER TABLE `permission_business_activities` DROP FOREIGN KEY `permission_business_activities_business_id_fkey`;
|
|
||||||
|
|
||||||
-- DropForeignKey
|
|
||||||
ALTER TABLE `permission_business_activities` DROP FOREIGN KEY `permission_business_activities_permission_id_fkey`;
|
|
||||||
|
|
||||||
-- DropForeignKey
|
|
||||||
ALTER TABLE `permission_complexes` DROP FOREIGN KEY `permission_complexes_complex_id_fkey`;
|
|
||||||
|
|
||||||
-- DropForeignKey
|
|
||||||
ALTER TABLE `permission_complexes` DROP FOREIGN KEY `permission_complexes_permission_id_fkey`;
|
|
||||||
|
|
||||||
-- DropForeignKey
|
|
||||||
ALTER TABLE `permission_consumers` DROP FOREIGN KEY `permission_consumers_consumer_account_id_fkey`;
|
|
||||||
|
|
||||||
-- DropForeignKey
|
|
||||||
ALTER TABLE `permission_poses` DROP FOREIGN KEY `permission_poses_permission_id_fkey`;
|
|
||||||
|
|
||||||
-- DropForeignKey
|
|
||||||
ALTER TABLE `permission_poses` DROP FOREIGN KEY `permission_poses_pos_id_fkey`;
|
|
||||||
|
|
||||||
-- DropIndex
|
|
||||||
DROP INDEX `permission_business_activities_business_id_fkey` ON `permission_business_activities`;
|
|
||||||
|
|
||||||
-- DropIndex
|
|
||||||
DROP INDEX `permission_complexes_complex_id_fkey` ON `permission_complexes`;
|
|
||||||
|
|
||||||
-- DropIndex
|
|
||||||
DROP INDEX `permission_poses_pos_id_fkey` ON `permission_poses`;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `permission_consumers` ADD CONSTRAINT `permission_consumers_consumer_account_id_fkey` FOREIGN KEY (`consumer_account_id`) REFERENCES `consumer_accounts`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `permission_poses` ADD CONSTRAINT `permission_poses_pos_id_fkey` FOREIGN KEY (`pos_id`) REFERENCES `poses`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `permission_poses` ADD CONSTRAINT `permission_poses_permission_id_fkey` FOREIGN KEY (`permission_id`) REFERENCES `permission_consumers`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `permission_complexes` ADD CONSTRAINT `permission_complexes_complex_id_fkey` FOREIGN KEY (`complex_id`) REFERENCES `complexes`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `permission_complexes` ADD CONSTRAINT `permission_complexes_permission_id_fkey` FOREIGN KEY (`permission_id`) REFERENCES `permission_consumers`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `permission_business_activities` ADD CONSTRAINT `permission_business_activities_business_id_fkey` FOREIGN KEY (`business_id`) REFERENCES `business_activities`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `permission_business_activities` ADD CONSTRAINT `permission_business_activities_permission_id_fkey` FOREIGN KEY (`permission_id`) REFERENCES `permission_consumers`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
-- AlterTable
|
|
||||||
ALTER TABLE `goods` ADD COLUMN `image_url` VARCHAR(255) NULL;
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
/*
|
|
||||||
Warnings:
|
|
||||||
|
|
||||||
- You are about to drop the column `consumer_id` on the `licenses` table. All the data in the column will be lost.
|
|
||||||
- You are about to drop the column `expires_at` on the `licenses` table. All the data in the column will be lost.
|
|
||||||
- You are about to drop the column `starts_at` on the `licenses` table. All the data in the column will be lost.
|
|
||||||
- You are about to drop the column `status` on the `licenses` table. All the data in the column will be lost.
|
|
||||||
- A unique constraint covering the columns `[activated_license_id]` on the table `consumers` will be added. If there are existing duplicate values, this will fail.
|
|
||||||
- Added the required column `activation_expires_at` to the `licenses` table without a default value. This is not possible if the table is not empty.
|
|
||||||
- Added the required column `charged_license_transaction_id` to the `licenses` table without a default value. This is not possible if the table is not empty.
|
|
||||||
- Made the column `partner_id` on table `licenses` required. This step will fail if there are existing NULL values in that column.
|
|
||||||
|
|
||||||
*/
|
|
||||||
-- DropForeignKey
|
|
||||||
ALTER TABLE `licenses` DROP FOREIGN KEY `licenses_consumer_id_fkey`;
|
|
||||||
|
|
||||||
-- DropForeignKey
|
|
||||||
ALTER TABLE `licenses` DROP FOREIGN KEY `licenses_partner_id_fkey`;
|
|
||||||
|
|
||||||
-- DropIndex
|
|
||||||
DROP INDEX `licenses_consumer_id_key` ON `licenses`;
|
|
||||||
|
|
||||||
-- DropIndex
|
|
||||||
DROP INDEX `licenses_partner_id_fkey` ON `licenses`;
|
|
||||||
|
|
||||||
-- AlterTable
|
|
||||||
ALTER TABLE `consumers` ADD COLUMN `activated_license_id` VARCHAR(191) NULL;
|
|
||||||
|
|
||||||
-- AlterTable
|
|
||||||
ALTER TABLE `licenses` DROP COLUMN `consumer_id`,
|
|
||||||
DROP COLUMN `expires_at`,
|
|
||||||
DROP COLUMN `starts_at`,
|
|
||||||
DROP COLUMN `status`,
|
|
||||||
ADD COLUMN `activation_expires_at` DATETIME(3) NOT NULL,
|
|
||||||
ADD COLUMN `charged_license_transaction_id` VARCHAR(191) NOT NULL,
|
|
||||||
MODIFY `partner_id` VARCHAR(191) NOT NULL;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `activated_licenses` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`starts_at` DATETIME(3) NOT NULL,
|
|
||||||
`expires_at` DATETIME(3) NOT NULL,
|
|
||||||
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`updated_at` TIMESTAMP(0) NOT NULL,
|
|
||||||
`license_id` VARCHAR(191) NOT NULL,
|
|
||||||
|
|
||||||
UNIQUE INDEX `activated_licenses_id_key`(`id`),
|
|
||||||
UNIQUE INDEX `activated_licenses_license_id_key`(`license_id`),
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `charged_license_transactions` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`updated_at` TIMESTAMP(0) NOT NULL,
|
|
||||||
`partner_id` VARCHAR(191) NOT NULL,
|
|
||||||
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateIndex
|
|
||||||
CREATE UNIQUE INDEX `consumers_activated_license_id_key` ON `consumers`(`activated_license_id`);
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `consumers` ADD CONSTRAINT `consumers_activated_license_id_fkey` FOREIGN KEY (`activated_license_id`) REFERENCES `activated_licenses`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `licenses` ADD CONSTRAINT `licenses_partner_id_fkey` FOREIGN KEY (`partner_id`) REFERENCES `partners`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `licenses` ADD CONSTRAINT `licenses_charged_license_transaction_id_fkey` FOREIGN KEY (`charged_license_transaction_id`) REFERENCES `charged_license_transactions`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `activated_licenses` ADD CONSTRAINT `activated_licenses_license_id_fkey` FOREIGN KEY (`license_id`) REFERENCES `licenses`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `charged_license_transactions` ADD CONSTRAINT `charged_license_transactions_partner_id_fkey` FOREIGN KEY (`partner_id`) REFERENCES `partners`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
/*
|
|
||||||
Warnings:
|
|
||||||
|
|
||||||
- You are about to drop the column `activated_license_id` on the `consumers` table. All the data in the column will be lost.
|
|
||||||
- You are about to drop the column `activation_expires_at` on the `licenses` table. All the data in the column will be lost.
|
|
||||||
- You are about to drop the column `partner_id` on the `licenses` table. All the data in the column will be lost.
|
|
||||||
- You are about to drop the column `license_quota` on the `partners` table. All the data in the column will be lost.
|
|
||||||
- Added the required column `consumer_id` to the `activated_licenses` table without a default value. This is not possible if the table is not empty.
|
|
||||||
- Added the required column `activation_expires_at` to the `charged_license_transactions` table without a default value. This is not possible if the table is not empty.
|
|
||||||
|
|
||||||
*/
|
|
||||||
-- DropForeignKey
|
|
||||||
ALTER TABLE `consumers` DROP FOREIGN KEY `consumers_activated_license_id_fkey`;
|
|
||||||
|
|
||||||
-- DropForeignKey
|
|
||||||
ALTER TABLE `licenses` DROP FOREIGN KEY `licenses_partner_id_fkey`;
|
|
||||||
|
|
||||||
-- DropIndex
|
|
||||||
DROP INDEX `consumers_activated_license_id_key` ON `consumers`;
|
|
||||||
|
|
||||||
-- DropIndex
|
|
||||||
DROP INDEX `licenses_partner_id_fkey` ON `licenses`;
|
|
||||||
|
|
||||||
-- AlterTable
|
|
||||||
ALTER TABLE `activated_licenses` ADD COLUMN `consumer_id` VARCHAR(191) NOT NULL;
|
|
||||||
|
|
||||||
-- AlterTable
|
|
||||||
ALTER TABLE `charged_license_transactions` ADD COLUMN `activation_expires_at` DATETIME(3) NOT NULL;
|
|
||||||
|
|
||||||
-- AlterTable
|
|
||||||
ALTER TABLE `consumers` DROP COLUMN `activated_license_id`;
|
|
||||||
|
|
||||||
-- AlterTable
|
|
||||||
ALTER TABLE `licenses` DROP COLUMN `activation_expires_at`,
|
|
||||||
DROP COLUMN `partner_id`;
|
|
||||||
|
|
||||||
-- AlterTable
|
|
||||||
ALTER TABLE `partners` DROP COLUMN `license_quota`;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `activated_licenses` ADD CONSTRAINT `activated_licenses_consumer_id_fkey` FOREIGN KEY (`consumer_id`) REFERENCES `consumers`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
-70
@@ -1,70 +0,0 @@
|
|||||||
/*
|
|
||||||
Warnings:
|
|
||||||
|
|
||||||
- You are about to drop the `user_devices` table. If the table is not empty, all the data it contains will be lost.
|
|
||||||
- A unique constraint covering the columns `[tracking_code]` on the table `charged_license_transactions` will be added. If there are existing duplicate values, this will fail.
|
|
||||||
- Added the required column `tracking_code` to the `charged_license_transactions` table without a default value. This is not possible if the table is not empty.
|
|
||||||
|
|
||||||
*/
|
|
||||||
-- DropTable
|
|
||||||
DROP TABLE `user_devices`;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `consumer_devices` (
|
|
||||||
`uuid` VARCHAR(255) NOT NULL,
|
|
||||||
`app_version` VARCHAR(20) NOT NULL,
|
|
||||||
`build_number` VARCHAR(20) NOT NULL,
|
|
||||||
`platform` VARCHAR(100) NOT NULL,
|
|
||||||
`brand` VARCHAR(100) NOT NULL,
|
|
||||||
`model` VARCHAR(100) NOT NULL,
|
|
||||||
`device` VARCHAR(100) NOT NULL,
|
|
||||||
`os_version` VARCHAR(20) NOT NULL,
|
|
||||||
`sdk_version` VARCHAR(20) NOT NULL,
|
|
||||||
`release_number` VARCHAR(20) NOT NULL,
|
|
||||||
`browser_name` VARCHAR(100) NULL,
|
|
||||||
`fcm_token` VARCHAR(100) NULL,
|
|
||||||
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`updated_at` TIMESTAMP(0) NOT NULL,
|
|
||||||
`consumer_id` VARCHAR(191) NOT NULL,
|
|
||||||
UNIQUE INDEX `consumer_devices_uuid_key` (`uuid`),
|
|
||||||
PRIMARY KEY (`uuid`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `application_released_info` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`version` VARCHAR(191) NOT NULL,
|
|
||||||
`build_number` VARCHAR(191) NOT NULL,
|
|
||||||
`is_stable` BOOLEAN NOT NULL DEFAULT TRUE,
|
|
||||||
`is_minimum_supported` BOOLEAN NOT NULL DEFAULT FALSE,
|
|
||||||
`type` ENUM('ANDROID', 'IOS') NOT NULL,
|
|
||||||
`notes` JSON NULL,
|
|
||||||
`release_date` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`updated_at` TIMESTAMP(0) NOT NULL,
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `consumer_devices`
|
|
||||||
ADD CONSTRAINT `consumer_devices_consumer_id_fkey` FOREIGN KEY (`consumer_id`) REFERENCES `consumers` (`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
ALTER TABLE `charged_license_transactions`
|
|
||||||
ADD COLUMN `tracking_code` VARCHAR(191) NULL;
|
|
||||||
|
|
||||||
UPDATE `charged_license_transactions`
|
|
||||||
SET
|
|
||||||
`tracking_code` = CONCAT(
|
|
||||||
'TRX-',
|
|
||||||
UPPER(
|
|
||||||
REPLACE (`id`, '-', '')
|
|
||||||
)
|
|
||||||
)
|
|
||||||
WHERE
|
|
||||||
`tracking_code` IS NULL
|
|
||||||
OR `tracking_code` = '';
|
|
||||||
|
|
||||||
ALTER TABLE `charged_license_transactions`
|
|
||||||
MODIFY `tracking_code` VARCHAR(191) NOT NULL;
|
|
||||||
|
|
||||||
CREATE UNIQUE INDEX `charged_license_transactions_tracking_code_key` ON `charged_license_transactions` (`tracking_code`);
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
/*
|
|
||||||
Warnings:
|
|
||||||
|
|
||||||
- You are about to drop the column `is_stable` on the `application_released_info` table. All the data in the column will be lost.
|
|
||||||
- You are about to drop the column `type` on the `application_released_info` table. All the data in the column will be lost.
|
|
||||||
- Added the required column `platform` to the `application_released_info` table without a default value. This is not possible if the table is not empty.
|
|
||||||
- Added the required column `release_type` to the `application_released_info` table without a default value. This is not possible if the table is not empty.
|
|
||||||
- Added the required column `publisher` to the `consumer_devices` table without a default value. This is not possible if the table is not empty.
|
|
||||||
|
|
||||||
*/
|
|
||||||
-- AlterTable
|
|
||||||
ALTER TABLE `application_released_info` DROP COLUMN `is_stable`,
|
|
||||||
DROP COLUMN `type`,
|
|
||||||
ADD COLUMN `platform` ENUM('ANDROID', 'IOS') NOT NULL,
|
|
||||||
ADD COLUMN `release_type` ENUM('STABLE', 'BETA', 'ALPHA') NOT NULL;
|
|
||||||
|
|
||||||
-- AlterTable
|
|
||||||
ALTER TABLE `consumer_devices` ADD COLUMN `publisher` ENUM('DIRECT', 'CAFE_BAZAR', 'MAYKET') NOT NULL,
|
|
||||||
ADD COLUMN `user_agent` VARCHAR(100) NULL;
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
Warnings:
|
|
||||||
|
|
||||||
- You are about to drop the column `tax_id` on the `complexes` table. All the data in the column will be lost.
|
|
||||||
- A unique constraint covering the columns `[economic_code]` on the table `business_activities` will be added. If there are existing duplicate values, this will fail.
|
|
||||||
- A unique constraint covering the columns `[mobile_number,national_code,partner_id]` on the table `consumers` will be added. If there are existing duplicate values, this will fail.
|
|
||||||
- Added the required column `economic_code` to the `business_activities` table without a default value. This is not possible if the table is not empty.
|
|
||||||
- Added the required column `national_code` to the `consumers` table without a default value. This is not possible if the table is not empty.
|
|
||||||
- Added the required column `partner_id` to the `consumers` table without a default value. This is not possible if the table is not empty.
|
|
||||||
|
|
||||||
*/
|
|
||||||
-- DropIndex
|
|
||||||
DROP INDEX `consumers_mobile_number_key` ON `consumers`;
|
|
||||||
|
|
||||||
-- AlterTable
|
|
||||||
ALTER TABLE `business_activities` ADD COLUMN `economic_code` VARCHAR(191) NOT NULL;
|
|
||||||
|
|
||||||
-- AlterTable
|
|
||||||
ALTER TABLE `complexes` DROP COLUMN `tax_id`;
|
|
||||||
|
|
||||||
-- AlterTable
|
|
||||||
ALTER TABLE `consumers` ADD COLUMN `national_code` VARCHAR(191) NOT NULL,
|
|
||||||
ADD COLUMN `partner_id` VARCHAR(191) NOT NULL;
|
|
||||||
|
|
||||||
-- AlterTable
|
|
||||||
ALTER TABLE `licenses` ADD COLUMN `accounts_limit` INTEGER NOT NULL DEFAULT 3;
|
|
||||||
|
|
||||||
-- CreateIndex
|
|
||||||
CREATE UNIQUE INDEX `business_activities_economic_code_key` ON `business_activities`(`economic_code`);
|
|
||||||
|
|
||||||
-- CreateIndex
|
|
||||||
CREATE UNIQUE INDEX `consumers_mobile_number_national_code_partner_id_key` ON `consumers`(`mobile_number`, `national_code`, `partner_id`);
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `consumers` ADD CONSTRAINT `consumers_partner_id_fkey` FOREIGN KEY (`partner_id`) REFERENCES `partners`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
/*
|
|
||||||
Warnings:
|
|
||||||
|
|
||||||
- Added the required column `branch_code` to the `complexes` table without a default value. This is not possible if the table is not empty.
|
|
||||||
|
|
||||||
*/
|
|
||||||
-- AlterTable
|
|
||||||
ALTER TABLE `complexes` ADD COLUMN `branch_code` VARCHAR(191) NOT NULL;
|
|
||||||
@@ -1,151 +0,0 @@
|
|||||||
/*
|
|
||||||
Warnings:
|
|
||||||
|
|
||||||
- You are about to drop the column `charged_license_transaction_id` on the `licenses` table. All the data in the column will be lost.
|
|
||||||
- You are about to drop the `activated_licenses` table. If the table is not empty, all the data it contains will be lost.
|
|
||||||
- You are about to drop the `charged_license_transactions` table. If the table is not empty, all the data it contains will be lost.
|
|
||||||
- A unique constraint covering the columns `[mobile_number,partner_id]` on the table `consumers` will be added. If there are existing duplicate values, this will fail.
|
|
||||||
- A unique constraint covering the columns `[national_code,partner_id]` on the table `consumers` will be added. If there are existing duplicate values, this will fail.
|
|
||||||
- Added the required column `charge_transaction_id` to the `licenses` table without a default value. This is not possible if the table is not empty.
|
|
||||||
|
|
||||||
*/
|
|
||||||
-- DropForeignKey
|
|
||||||
ALTER TABLE `activated_licenses` DROP FOREIGN KEY `activated_licenses_consumer_id_fkey`;
|
|
||||||
|
|
||||||
-- DropForeignKey
|
|
||||||
ALTER TABLE `activated_licenses` DROP FOREIGN KEY `activated_licenses_license_id_fkey`;
|
|
||||||
|
|
||||||
-- DropForeignKey
|
|
||||||
ALTER TABLE `charged_license_transactions` DROP FOREIGN KEY `charged_license_transactions_partner_id_fkey`;
|
|
||||||
|
|
||||||
-- DropForeignKey
|
|
||||||
ALTER TABLE `licenses` DROP FOREIGN KEY `licenses_charged_license_transaction_id_fkey`;
|
|
||||||
|
|
||||||
-- DropIndex
|
|
||||||
DROP INDEX `consumers_mobile_number_national_code_partner_id_key` ON `consumers`;
|
|
||||||
|
|
||||||
-- DropIndex
|
|
||||||
DROP INDEX `licenses_charged_license_transaction_id_fkey` ON `licenses`;
|
|
||||||
|
|
||||||
-- AlterTable
|
|
||||||
ALTER TABLE `licenses` DROP COLUMN `charged_license_transaction_id`,
|
|
||||||
ADD COLUMN `charge_transaction_id` VARCHAR(191) NOT NULL;
|
|
||||||
|
|
||||||
-- DropTable
|
|
||||||
DROP TABLE `activated_licenses`;
|
|
||||||
|
|
||||||
-- DropTable
|
|
||||||
DROP TABLE `charged_license_transactions`;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `licenses_activated` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`starts_at` DATETIME(3) NOT NULL,
|
|
||||||
`expires_at` DATETIME(3) NOT NULL,
|
|
||||||
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`updated_at` TIMESTAMP(0) NOT NULL,
|
|
||||||
`license_id` VARCHAR(191) NOT NULL,
|
|
||||||
`business_activity_id` VARCHAR(191) NOT NULL,
|
|
||||||
|
|
||||||
UNIQUE INDEX `licenses_activated_id_key`(`id`),
|
|
||||||
UNIQUE INDEX `licenses_activated_license_id_key`(`license_id`),
|
|
||||||
UNIQUE INDEX `licenses_activated_business_activity_id_key`(`business_activity_id`),
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `license_charged_transactions` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`activation_expires_at` DATETIME(3) NOT NULL,
|
|
||||||
`tracking_code` VARCHAR(191) NOT NULL,
|
|
||||||
`purchased_count` INTEGER NOT NULL,
|
|
||||||
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`updated_at` TIMESTAMP(0) NOT NULL,
|
|
||||||
`partner_id` VARCHAR(191) NOT NULL,
|
|
||||||
|
|
||||||
UNIQUE INDEX `license_charged_transactions_tracking_code_key`(`tracking_code`),
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `license_renew` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`updated_at` TIMESTAMP(0) NOT NULL,
|
|
||||||
`charge_transaction_id` VARCHAR(191) NOT NULL,
|
|
||||||
`activation_id` VARCHAR(191) NOT NULL,
|
|
||||||
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `license_renew_charge_transaction` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`activation_expires_at` DATETIME(3) NOT NULL,
|
|
||||||
`tracking_code` VARCHAR(191) NOT NULL,
|
|
||||||
`purchased_count` INTEGER NOT NULL,
|
|
||||||
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`updated_at` TIMESTAMP(0) NOT NULL,
|
|
||||||
`partner_id` VARCHAR(191) NOT NULL,
|
|
||||||
|
|
||||||
UNIQUE INDEX `license_renew_charge_transaction_tracking_code_key`(`tracking_code`),
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `partner_account_quota_charge_transaction` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`purchased_count` INTEGER NOT NULL,
|
|
||||||
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`updated_at` TIMESTAMP(0) NOT NULL,
|
|
||||||
`partner_id` VARCHAR(191) NOT NULL,
|
|
||||||
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `partner_account_quota_allocation` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`updated_at` TIMESTAMP(0) NOT NULL,
|
|
||||||
`charge_transaction_id` VARCHAR(191) NOT NULL,
|
|
||||||
`license_id` VARCHAR(191) NULL,
|
|
||||||
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateIndex
|
|
||||||
CREATE UNIQUE INDEX `consumers_mobile_number_partner_id_key` ON `consumers`(`mobile_number`, `partner_id`);
|
|
||||||
|
|
||||||
-- CreateIndex
|
|
||||||
CREATE UNIQUE INDEX `consumers_national_code_partner_id_key` ON `consumers`(`national_code`, `partner_id`);
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `licenses` ADD CONSTRAINT `licenses_charge_transaction_id_fkey` FOREIGN KEY (`charge_transaction_id`) REFERENCES `license_charged_transactions`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `licenses_activated` ADD CONSTRAINT `licenses_activated_license_id_fkey` FOREIGN KEY (`license_id`) REFERENCES `licenses`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `licenses_activated` ADD CONSTRAINT `licenses_activated_business_activity_id_fkey` FOREIGN KEY (`business_activity_id`) REFERENCES `business_activities`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `license_charged_transactions` ADD CONSTRAINT `license_charged_transactions_partner_id_fkey` FOREIGN KEY (`partner_id`) REFERENCES `partners`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `license_renew` ADD CONSTRAINT `license_renew_charge_transaction_id_fkey` FOREIGN KEY (`charge_transaction_id`) REFERENCES `license_renew_charge_transaction`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `license_renew` ADD CONSTRAINT `license_renew_activation_id_fkey` FOREIGN KEY (`activation_id`) REFERENCES `licenses_activated`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `license_renew_charge_transaction` ADD CONSTRAINT `license_renew_charge_transaction_partner_id_fkey` FOREIGN KEY (`partner_id`) REFERENCES `partners`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `partner_account_quota_charge_transaction` ADD CONSTRAINT `partner_account_quota_charge_transaction_partner_id_fkey` FOREIGN KEY (`partner_id`) REFERENCES `partners`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `partner_account_quota_allocation` ADD CONSTRAINT `partner_account_quota_allocation_charge_transaction_id_fkey` FOREIGN KEY (`charge_transaction_id`) REFERENCES `partner_account_quota_charge_transaction`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `partner_account_quota_allocation` ADD CONSTRAINT `partner_account_quota_allocation_license_id_fkey` FOREIGN KEY (`license_id`) REFERENCES `licenses`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
/*
|
|
||||||
Warnings:
|
|
||||||
|
|
||||||
- A unique constraint covering the columns `[tracking_code]` on the table `partner_account_quota_charge_transaction` will be added. If there are existing duplicate values, this will fail.
|
|
||||||
- Added the required column `expires_at` to the `license_renew` table without a default value. This is not possible if the table is not empty.
|
|
||||||
- Added the required column `activation_expires_at` to the `partner_account_quota_charge_transaction` table without a default value. This is not possible if the table is not empty.
|
|
||||||
- Added the required column `tracking_code` to the `partner_account_quota_charge_transaction` table without a default value. This is not possible if the table is not empty.
|
|
||||||
|
|
||||||
*/
|
|
||||||
-- AlterTable
|
|
||||||
ALTER TABLE `license_renew` ADD COLUMN `expires_at` DATETIME(3) NOT NULL;
|
|
||||||
|
|
||||||
-- AlterTable
|
|
||||||
ALTER TABLE `partner_account_quota_charge_transaction` ADD COLUMN `activation_expires_at` DATETIME(3) NOT NULL,
|
|
||||||
ADD COLUMN `tracking_code` VARCHAR(191) NOT NULL;
|
|
||||||
|
|
||||||
-- CreateIndex
|
|
||||||
CREATE UNIQUE INDEX `partner_account_quota_charge_transaction_tracking_code_key` ON `partner_account_quota_charge_transaction`(`tracking_code`);
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
/*
|
|
||||||
Warnings:
|
|
||||||
|
|
||||||
- You are about to drop the column `serial` on the `poses` table. All the data in the column will be lost.
|
|
||||||
- A unique constraint covering the columns `[serial_number]` on the table `poses` will be added. If there are existing duplicate values, this will fail.
|
|
||||||
|
|
||||||
*/
|
|
||||||
-- DropIndex
|
|
||||||
DROP INDEX `poses_serial_key` ON `poses`;
|
|
||||||
|
|
||||||
-- AlterTable
|
|
||||||
ALTER TABLE `poses` DROP COLUMN `serial`,
|
|
||||||
ADD COLUMN `serial_number` VARCHAR(191) NULL;
|
|
||||||
|
|
||||||
-- CreateIndex
|
|
||||||
CREATE UNIQUE INDEX `poses_serial_number_key` ON `poses`(`serial_number`);
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
/*
|
|
||||||
Warnings:
|
|
||||||
|
|
||||||
- A unique constraint covering the columns `[account_id]` on the table `poses` will be added. If there are existing duplicate values, this will fail.
|
|
||||||
|
|
||||||
*/
|
|
||||||
-- AlterTable
|
|
||||||
ALTER TABLE `licenses` MODIFY `accounts_limit` INTEGER NOT NULL DEFAULT 2;
|
|
||||||
|
|
||||||
-- AlterTable
|
|
||||||
ALTER TABLE `partners` ADD COLUMN `logo_url` VARCHAR(191) NULL;
|
|
||||||
|
|
||||||
-- AlterTable
|
|
||||||
ALTER TABLE `poses` ADD COLUMN `account_id` VARCHAR(191) NULL;
|
|
||||||
|
|
||||||
-- CreateIndex
|
|
||||||
CREATE UNIQUE INDEX `poses_account_id_key` ON `poses`(`account_id`);
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `poses` ADD CONSTRAINT `poses_account_id_fkey` FOREIGN KEY (`account_id`) REFERENCES `consumer_accounts`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
/*
|
|
||||||
Warnings:
|
|
||||||
|
|
||||||
- You are about to drop the `partner_account_quota_allocation` table. If the table is not empty, all the data it contains will be lost.
|
|
||||||
|
|
||||||
*/
|
|
||||||
-- DropForeignKey
|
|
||||||
ALTER TABLE `partner_account_quota_allocation` DROP FOREIGN KEY `partner_account_quota_allocation_charge_transaction_id_fkey`;
|
|
||||||
|
|
||||||
-- DropForeignKey
|
|
||||||
ALTER TABLE `partner_account_quota_allocation` DROP FOREIGN KEY `partner_account_quota_allocation_license_id_fkey`;
|
|
||||||
|
|
||||||
-- DropTable
|
|
||||||
DROP TABLE `partner_account_quota_allocation`;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `partner_account_quota_credit` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`updated_at` TIMESTAMP(0) NOT NULL,
|
|
||||||
`charge_transaction_id` VARCHAR(191) NOT NULL,
|
|
||||||
`allocation_id` VARCHAR(191) NULL,
|
|
||||||
|
|
||||||
UNIQUE INDEX `partner_account_quota_credit_allocation_id_key`(`allocation_id`),
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE `license_account_allocation` (
|
|
||||||
`id` VARCHAR(191) NOT NULL,
|
|
||||||
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
|
|
||||||
`updated_at` TIMESTAMP(0) NOT NULL,
|
|
||||||
`license_activation_id` VARCHAR(191) NOT NULL,
|
|
||||||
`account_id` VARCHAR(191) NOT NULL,
|
|
||||||
|
|
||||||
UNIQUE INDEX `license_account_allocation_account_id_key`(`account_id`),
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `partner_account_quota_credit` ADD CONSTRAINT `partner_account_quota_credit_charge_transaction_id_fkey` FOREIGN KEY (`charge_transaction_id`) REFERENCES `partner_account_quota_charge_transaction`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `partner_account_quota_credit` ADD CONSTRAINT `partner_account_quota_credit_allocation_id_fkey` FOREIGN KEY (`allocation_id`) REFERENCES `license_account_allocation`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `license_account_allocation` ADD CONSTRAINT `license_account_allocation_license_activation_id_fkey` FOREIGN KEY (`license_activation_id`) REFERENCES `licenses_activated`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `license_account_allocation` ADD CONSTRAINT `license_account_allocation_account_id_fkey` FOREIGN KEY (`account_id`) REFERENCES `consumer_accounts`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
-- DropForeignKey
|
|
||||||
ALTER TABLE `license_account_allocation` DROP FOREIGN KEY `license_account_allocation_account_id_fkey`;
|
|
||||||
|
|
||||||
-- DropForeignKey
|
|
||||||
ALTER TABLE `license_account_allocation` DROP FOREIGN KEY `license_account_allocation_license_activation_id_fkey`;
|
|
||||||
|
|
||||||
-- DropForeignKey
|
|
||||||
ALTER TABLE `partner_account_quota_credit` DROP FOREIGN KEY `partner_account_quota_credit_charge_transaction_id_fkey`;
|
|
||||||
|
|
||||||
-- DropIndex
|
|
||||||
DROP INDEX `license_account_allocation_license_activation_id_fkey` ON `license_account_allocation`;
|
|
||||||
|
|
||||||
-- DropIndex
|
|
||||||
DROP INDEX `partner_account_quota_credit_charge_transaction_id_fkey` ON `partner_account_quota_credit`;
|
|
||||||
|
|
||||||
-- AlterTable
|
|
||||||
ALTER TABLE `license_account_allocation` MODIFY `license_activation_id` VARCHAR(191) NULL,
|
|
||||||
MODIFY `account_id` VARCHAR(191) NULL;
|
|
||||||
|
|
||||||
-- AlterTable
|
|
||||||
ALTER TABLE `partner_account_quota_credit` MODIFY `charge_transaction_id` VARCHAR(191) NULL;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `partner_account_quota_credit` ADD CONSTRAINT `partner_account_quota_credit_charge_transaction_id_fkey` FOREIGN KEY (`charge_transaction_id`) REFERENCES `partner_account_quota_charge_transaction`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `license_account_allocation` ADD CONSTRAINT `license_account_allocation_license_activation_id_fkey` FOREIGN KEY (`license_activation_id`) REFERENCES `licenses_activated`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `license_account_allocation` ADD CONSTRAINT `license_account_allocation_account_id_fkey` FOREIGN KEY (`account_id`) REFERENCES `consumer_accounts`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
/*
|
|
||||||
Warnings:
|
|
||||||
|
|
||||||
- You are about to drop the column `allocation_id` on the `partner_account_quota_credit` table. All the data in the column will be lost.
|
|
||||||
- A unique constraint covering the columns `[economic_code,consumer_id]` on the table `business_activities` will be added. If there are existing duplicate values, this will fail.
|
|
||||||
- A unique constraint covering the columns `[credit_id]` on the table `license_account_allocation` will be added. If there are existing duplicate values, this will fail.
|
|
||||||
- Made the column `account_id` on table `poses` required. This step will fail if there are existing NULL values in that column.
|
|
||||||
|
|
||||||
*/
|
|
||||||
-- DropForeignKey
|
|
||||||
ALTER TABLE `license_renew` DROP FOREIGN KEY `license_renew_activation_id_fkey`;
|
|
||||||
|
|
||||||
-- DropForeignKey
|
|
||||||
ALTER TABLE `partner_account_quota_credit` DROP FOREIGN KEY `partner_account_quota_credit_allocation_id_fkey`;
|
|
||||||
|
|
||||||
-- DropForeignKey
|
|
||||||
ALTER TABLE `poses` DROP FOREIGN KEY `poses_account_id_fkey`;
|
|
||||||
|
|
||||||
-- DropIndex
|
|
||||||
DROP INDEX `business_activities_economic_code_key` ON `business_activities`;
|
|
||||||
|
|
||||||
-- DropIndex
|
|
||||||
DROP INDEX `license_renew_activation_id_fkey` ON `license_renew`;
|
|
||||||
|
|
||||||
-- DropIndex
|
|
||||||
DROP INDEX `partner_account_quota_credit_allocation_id_key` ON `partner_account_quota_credit`;
|
|
||||||
|
|
||||||
-- AlterTable
|
|
||||||
ALTER TABLE `license_account_allocation` ADD COLUMN `credit_id` VARCHAR(191) NULL;
|
|
||||||
|
|
||||||
-- AlterTable
|
|
||||||
ALTER TABLE `license_renew` MODIFY `activation_id` VARCHAR(191) NULL;
|
|
||||||
|
|
||||||
-- AlterTable
|
|
||||||
ALTER TABLE `partner_account_quota_credit` DROP COLUMN `allocation_id`;
|
|
||||||
|
|
||||||
-- AlterTable
|
|
||||||
ALTER TABLE `poses` MODIFY `account_id` VARCHAR(191) NOT NULL;
|
|
||||||
|
|
||||||
-- CreateIndex
|
|
||||||
CREATE UNIQUE INDEX `business_activities_economic_code_consumer_id_key` ON `business_activities`(`economic_code`, `consumer_id`);
|
|
||||||
|
|
||||||
-- CreateIndex
|
|
||||||
CREATE UNIQUE INDEX `license_account_allocation_credit_id_key` ON `license_account_allocation`(`credit_id`);
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `poses` ADD CONSTRAINT `poses_account_id_fkey` FOREIGN KEY (`account_id`) REFERENCES `consumer_accounts`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `license_renew` ADD CONSTRAINT `license_renew_activation_id_fkey` FOREIGN KEY (`activation_id`) REFERENCES `licenses_activated`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE `license_account_allocation` ADD CONSTRAINT `license_account_allocation_credit_id_fkey` FOREIGN KEY (`credit_id`) REFERENCES `partner_account_quota_credit`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
Warnings:
|
||||||
|
|
||||||
|
- A unique constraint covering the columns `[business_activity_id,postal_code,national_id]` on the table `customer_individuals` will be added. If there are existing duplicate values, this will fail.
|
||||||
|
- A unique constraint covering the columns `[business_activity_id,postal_code,registration_number]` on the table `customer_legal` will be added. If there are existing duplicate values, this will fail.
|
||||||
|
|
||||||
|
*/
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE `customer_individuals` MODIFY `first_name` VARCHAR(255) NULL,
|
||||||
|
MODIFY `last_name` VARCHAR(255) NULL,
|
||||||
|
MODIFY `national_id` CHAR(10) NULL,
|
||||||
|
MODIFY `mobile_number` CHAR(15) NULL,
|
||||||
|
MODIFY `postal_code` CHAR(10) NULL,
|
||||||
|
MODIFY `economic_code` CHAR(14) NULL;
|
||||||
|
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE `customer_legal` MODIFY `name` VARCHAR(255) NULL,
|
||||||
|
MODIFY `economic_code` CHAR(11) NULL,
|
||||||
|
MODIFY `postal_code` CHAR(10) NULL;
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX `customer_individuals_business_activity_id_postal_code_nation_key` ON `customer_individuals`(`business_activity_id`, `postal_code`, `national_id`);
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX `customer_legal_business_activity_id_postal_code_registration_key` ON `customer_legal`(`business_activity_id`, `postal_code`, `registration_number`);
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
-- ALTER TABLE
|
||||||
|
ALTER TABLE `sales_invoices`
|
||||||
|
ADD COLUMN `last_attempt_no` INT NULL,
|
||||||
|
ADD COLUMN `last_tsp_status` ENUM(
|
||||||
|
'NOT_SEND',
|
||||||
|
'QUEUED',
|
||||||
|
'FISCAL_QUEUED',
|
||||||
|
'SEND_FAILURE',
|
||||||
|
'SUCCESS',
|
||||||
|
'FAILURE'
|
||||||
|
) NULL;
|
||||||
|
|
||||||
|
-- INDEX
|
||||||
|
CREATE INDEX `sales_invoices_pos_id_invoice_date_idx`
|
||||||
|
ON `sales_invoices` (`pos_id`, `invoice_date`);
|
||||||
|
|
||||||
|
-- BACKFILL LAST ATTEMPT
|
||||||
|
UPDATE sales_invoices si
|
||||||
|
JOIN (
|
||||||
|
SELECT invoice_id, attempt_no, status
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
invoice_id,
|
||||||
|
attempt_no,
|
||||||
|
status,
|
||||||
|
ROW_NUMBER() OVER (
|
||||||
|
PARTITION BY invoice_id
|
||||||
|
ORDER BY created_at DESC
|
||||||
|
) rn
|
||||||
|
FROM sale_invoice_tsp_attempts
|
||||||
|
) t
|
||||||
|
WHERE rn = 1
|
||||||
|
) la ON la.invoice_id = si.id
|
||||||
|
SET
|
||||||
|
si.last_attempt_no = la.attempt_no,
|
||||||
|
si.last_tsp_status = la.status;
|
||||||
|
|
||||||
|
-- SET NOT_SEND FOR NO ATTEMPTS
|
||||||
|
UPDATE sales_invoices si
|
||||||
|
LEFT JOIN sale_invoice_tsp_attempts att
|
||||||
|
ON att.invoice_id = si.id
|
||||||
|
SET
|
||||||
|
si.last_attempt_no = NULL,
|
||||||
|
si.last_tsp_status = 'NOT_SEND'
|
||||||
|
WHERE att.invoice_id IS NULL;
|
||||||
|
|
||||||
|
-- SAFETY FILL
|
||||||
|
UPDATE sales_invoices
|
||||||
|
SET last_tsp_status = 'NOT_SEND'
|
||||||
|
WHERE last_tsp_status IS NULL;
|
||||||
@@ -1,53 +1,25 @@
|
|||||||
model AdminAccount {
|
model AdminAccount {
|
||||||
id String @id @default(ulid())
|
id String @id @default(ulid())
|
||||||
|
|
||||||
created_at DateTime @default(now()) @db.Timestamp(0)
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
updated_at DateTime @updatedAt() @db.Timestamp(0)
|
updated_at DateTime @updatedAt @db.Timestamp(0)
|
||||||
|
|
||||||
admin_id String
|
admin_id String
|
||||||
|
account_id String @unique
|
||||||
|
account Account @relation(fields: [account_id], references: [id], onDelete: Cascade)
|
||||||
admin Admin @relation(fields: [admin_id], references: [id])
|
admin Admin @relation(fields: [admin_id], references: [id])
|
||||||
|
|
||||||
account_id String @unique
|
@@index([admin_id], map: "admin_accounts_admin_id_fkey")
|
||||||
account Account @relation(fields: [account_id], references: [id])
|
|
||||||
|
|
||||||
@@map("admin_accounts")
|
@@map("admin_accounts")
|
||||||
}
|
}
|
||||||
|
|
||||||
model Admin {
|
model Admin {
|
||||||
id String @id @default(ulid())
|
id String @id @default(ulid())
|
||||||
mobile_number String @unique()
|
mobile_number String @unique
|
||||||
national_code String? @unique()
|
national_code String? @unique
|
||||||
first_name String
|
first_name String
|
||||||
last_name String
|
last_name String
|
||||||
|
|
||||||
created_at DateTime @default(now()) @db.Timestamp(0)
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
updated_at DateTime @updatedAt() @db.Timestamp(0)
|
updated_at DateTime @updatedAt @db.Timestamp(0)
|
||||||
|
accounts AdminAccount[]
|
||||||
adminAccounts AdminAccount[]
|
|
||||||
|
|
||||||
@@map("admins")
|
@@map("admins")
|
||||||
}
|
}
|
||||||
|
|
||||||
// model LegalProfile {
|
|
||||||
// user_id String @id
|
|
||||||
// company_name String
|
|
||||||
// register_no String @unique()
|
|
||||||
// representative_name String?
|
|
||||||
// representative_national_id String?
|
|
||||||
|
|
||||||
// // user User @relation(fields: [user_id], references: [id])
|
|
||||||
|
|
||||||
// @@map("legal_profiles")
|
|
||||||
// }
|
|
||||||
|
|
||||||
// model IndividualProfile {
|
|
||||||
// user_id String @id
|
|
||||||
// national_code String @unique()
|
|
||||||
// first_name String
|
|
||||||
// last_name String
|
|
||||||
// birth_date DateTime?
|
|
||||||
// mobile_number String
|
|
||||||
// // user User @relation(fields: [user_id], references: [id])
|
|
||||||
|
|
||||||
// @@map("individual_profiles")
|
|
||||||
// }
|
|
||||||
|
|||||||
@@ -1,44 +1,13 @@
|
|||||||
model Account {
|
model Account {
|
||||||
id String @id @default(ulid())
|
id String @id @default(ulid())
|
||||||
username String @unique()
|
username String @unique
|
||||||
password String
|
password String
|
||||||
status AccountStatus
|
status AccountStatus
|
||||||
type AccountType
|
type AccountType
|
||||||
|
|
||||||
admin_account AdminAccount?
|
admin_account AdminAccount?
|
||||||
provider_account ProviderAccount?
|
|
||||||
partner_account PartnerAccount?
|
|
||||||
consumer_account ConsumerAccount?
|
consumer_account ConsumerAccount?
|
||||||
|
partner_account PartnerAccount?
|
||||||
// tokens Token[]
|
provider_account ProviderAccount?
|
||||||
// refresh_tokens RefreshToken[]
|
|
||||||
|
|
||||||
@@map("accounts")
|
@@map("accounts")
|
||||||
}
|
}
|
||||||
|
|
||||||
// model Token {
|
|
||||||
// id String @id @d @uniqueefault(ulid())
|
|
||||||
// token String @unique
|
|
||||||
// type TokenType
|
|
||||||
// created_at DateTime @default(now())
|
|
||||||
// expires_at DateTime
|
|
||||||
|
|
||||||
// account_id String
|
|
||||||
// account Account @relation(fields: [account_id], references: [id])
|
|
||||||
|
|
||||||
// @@unique([type, account_id])
|
|
||||||
// @@map("tokens")
|
|
||||||
// }
|
|
||||||
|
|
||||||
// model VerificationCode {
|
|
||||||
// id String @id @default(ulid())
|
|
||||||
// code String
|
|
||||||
// is_used Boolean @default(false)
|
|
||||||
// created_at DateTime @default(now())
|
|
||||||
// expires_at DateTime
|
|
||||||
|
|
||||||
// account_id String
|
|
||||||
// account Account @relation(fields: [account_id], references: [id])
|
|
||||||
|
|
||||||
// @@map("verification_codes")
|
|
||||||
// }
|
|
||||||
|
|||||||
@@ -1,117 +0,0 @@
|
|||||||
model ConsumerAccount {
|
|
||||||
id String @id @default(ulid())
|
|
||||||
role ConsumerRole
|
|
||||||
|
|
||||||
created_at DateTime @default(now()) @db.Timestamp(0)
|
|
||||||
updated_at DateTime @updatedAt() @db.Timestamp(0)
|
|
||||||
|
|
||||||
consumer_id String
|
|
||||||
consumer Consumer @relation(fields: [consumer_id], references: [id])
|
|
||||||
|
|
||||||
account_id String @unique()
|
|
||||||
account Account @relation(fields: [account_id], references: [id])
|
|
||||||
|
|
||||||
pos Pos?
|
|
||||||
permission PermissionConsumer?
|
|
||||||
account_allocation LicenseAccountAllocation?
|
|
||||||
sales_invoices SalesInvoice[]
|
|
||||||
|
|
||||||
@@map("consumer_accounts")
|
|
||||||
}
|
|
||||||
|
|
||||||
model Consumer {
|
|
||||||
id String @id @default(ulid())
|
|
||||||
mobile_number String
|
|
||||||
national_code String
|
|
||||||
first_name String
|
|
||||||
last_name String
|
|
||||||
status ConsumerStatus @default(ACTIVE)
|
|
||||||
|
|
||||||
created_at DateTime @default(now()) @db.Timestamp(0)
|
|
||||||
updated_at DateTime @updatedAt() @db.Timestamp(0)
|
|
||||||
|
|
||||||
partner_id String
|
|
||||||
partner Partner @relation(fields: [partner_id], references: [id])
|
|
||||||
|
|
||||||
consumer_accounts ConsumerAccount[]
|
|
||||||
business_activities BusinessActivity[]
|
|
||||||
consumer_devices ConsumerDevices[]
|
|
||||||
|
|
||||||
@@unique([mobile_number, partner_id])
|
|
||||||
@@unique([national_code, partner_id])
|
|
||||||
@@map("consumers")
|
|
||||||
}
|
|
||||||
|
|
||||||
model BusinessActivity {
|
|
||||||
id String @id @default(ulid())
|
|
||||||
economic_code String
|
|
||||||
name String
|
|
||||||
|
|
||||||
created_at DateTime @default(now()) @db.Timestamp(0)
|
|
||||||
updated_at DateTime @updatedAt() @db.Timestamp(0)
|
|
||||||
|
|
||||||
guild_id String
|
|
||||||
guild Guild @relation(fields: [guild_id], references: [id])
|
|
||||||
|
|
||||||
consumer_id String
|
|
||||||
consumer Consumer @relation(fields: [consumer_id], references: [id])
|
|
||||||
|
|
||||||
complexes Complex[]
|
|
||||||
permission_businesses PermissionBusiness[]
|
|
||||||
license_activation LicenseActivation?
|
|
||||||
|
|
||||||
@@unique([economic_code, consumer_id])
|
|
||||||
@@map("business_activities")
|
|
||||||
}
|
|
||||||
|
|
||||||
model Complex {
|
|
||||||
id String @id @default(ulid())
|
|
||||||
name String
|
|
||||||
branch_code String
|
|
||||||
address String?
|
|
||||||
|
|
||||||
created_at DateTime @default(now()) @db.Timestamp(0)
|
|
||||||
updated_at DateTime @updatedAt() @db.Timestamp(0)
|
|
||||||
|
|
||||||
business_activity_id String
|
|
||||||
|
|
||||||
business_activity BusinessActivity @relation(fields: [business_activity_id], references: [id])
|
|
||||||
|
|
||||||
pos_list Pos[]
|
|
||||||
goods Good[]
|
|
||||||
good_categories GoodCategory[]
|
|
||||||
permission_complexes PermissionComplex[]
|
|
||||||
customer_individuals CustomerIndividual[]
|
|
||||||
customer_legals CustomerLegal[]
|
|
||||||
|
|
||||||
@@map("complexes")
|
|
||||||
}
|
|
||||||
|
|
||||||
model Pos {
|
|
||||||
id String @id @default(ulid())
|
|
||||||
name String
|
|
||||||
model String?
|
|
||||||
serial_number String? @unique()
|
|
||||||
status POSStatus @default(ACTIVE)
|
|
||||||
pos_type POSType
|
|
||||||
|
|
||||||
created_at DateTime @default(now()) @db.Timestamp(0)
|
|
||||||
updated_at DateTime @updatedAt() @db.Timestamp(0)
|
|
||||||
|
|
||||||
complex_id String
|
|
||||||
complex Complex @relation(fields: [complex_id], references: [id])
|
|
||||||
|
|
||||||
device_id String?
|
|
||||||
device Device? @relation(fields: [device_id], references: [id])
|
|
||||||
|
|
||||||
provider_id String?
|
|
||||||
provider Provider? @relation(fields: [provider_id], references: [id])
|
|
||||||
|
|
||||||
account_id String @unique
|
|
||||||
account ConsumerAccount @relation(fields: [account_id], references: [id])
|
|
||||||
|
|
||||||
permission_pos PermissionPos[]
|
|
||||||
sales_invoices SalesInvoice[]
|
|
||||||
|
|
||||||
@@map("poses")
|
|
||||||
}
|
|
||||||
@@ -1,10 +1,8 @@
|
|||||||
model DeviceBrand {
|
model DeviceBrand {
|
||||||
id String @id @default(ulid())
|
id String @id @default(ulid())
|
||||||
name String
|
name String
|
||||||
|
|
||||||
created_at DateTime @default(now()) @db.Timestamp(0)
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
updated_at DateTime @updatedAt() @db.Timestamp(0)
|
updated_at DateTime @updatedAt @db.Timestamp(0)
|
||||||
|
|
||||||
devices Device[]
|
devices Device[]
|
||||||
|
|
||||||
@@map("device_brands")
|
@@map("device_brands")
|
||||||
@@ -14,14 +12,12 @@ model Device {
|
|||||||
id String @id @default(ulid())
|
id String @id @default(ulid())
|
||||||
name String
|
name String
|
||||||
os_version String?
|
os_version String?
|
||||||
|
|
||||||
created_at DateTime @default(now()) @db.Timestamp(0)
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
updated_at DateTime @updatedAt() @db.Timestamp(0)
|
updated_at DateTime @updatedAt @db.Timestamp(0)
|
||||||
|
|
||||||
brand_id String
|
brand_id String
|
||||||
|
|
||||||
brand DeviceBrand @relation(fields: [brand_id], references: [id])
|
brand DeviceBrand @relation(fields: [brand_id], references: [id])
|
||||||
poses Pos[]
|
poses Pos[]
|
||||||
|
|
||||||
|
@@index([brand_id])
|
||||||
@@map("devices")
|
@@map("devices")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,51 +1,43 @@
|
|||||||
model LicenseChargeTransaction {
|
model LicenseChargeTransaction {
|
||||||
id String @id @default(ulid())
|
id String @id @default(ulid())
|
||||||
activation_expires_at DateTime
|
activation_expires_at DateTime
|
||||||
tracking_code String @unique()
|
tracking_code String @unique
|
||||||
purchased_count Int
|
purchased_count Int
|
||||||
|
|
||||||
created_at DateTime @default(now()) @db.Timestamp(0)
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
updated_at DateTime @updatedAt() @db.Timestamp(0)
|
updated_at DateTime @updatedAt @db.Timestamp(0)
|
||||||
|
|
||||||
partner_id String
|
partner_id String
|
||||||
partner Partner @relation(fields: [partner_id], references: [id])
|
partner Partner @relation(fields: [partner_id], references: [id])
|
||||||
|
|
||||||
licenses License[]
|
licenses License[]
|
||||||
|
|
||||||
|
@@index([partner_id])
|
||||||
@@map("license_charged_transactions")
|
@@map("license_charged_transactions")
|
||||||
}
|
}
|
||||||
|
|
||||||
model License {
|
model License {
|
||||||
id String @id @default(ulid())
|
id String @id @default(ulid())
|
||||||
accounts_limit Int @default(2)
|
accounts_limit Int @default(2)
|
||||||
|
|
||||||
created_at DateTime @default(now()) @db.Timestamp(0)
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
updated_at DateTime @updatedAt() @db.Timestamp(0)
|
updated_at DateTime @updatedAt @db.Timestamp(0)
|
||||||
|
|
||||||
charge_transaction_id String
|
charge_transaction_id String
|
||||||
charge_transaction LicenseChargeTransaction @relation(fields: [charge_transaction_id], references: [id])
|
charge_transaction LicenseChargeTransaction @relation(fields: [charge_transaction_id], references: [id])
|
||||||
|
|
||||||
activation LicenseActivation?
|
activation LicenseActivation?
|
||||||
|
|
||||||
|
@@index([charge_transaction_id])
|
||||||
@@map("licenses")
|
@@map("licenses")
|
||||||
}
|
}
|
||||||
|
|
||||||
model LicenseActivation {
|
model LicenseActivation {
|
||||||
id String @id @unique() @default(ulid())
|
id String @id @unique @default(ulid())
|
||||||
starts_at DateTime
|
starts_at DateTime
|
||||||
expires_at DateTime
|
expires_at DateTime
|
||||||
|
|
||||||
created_at DateTime @default(now()) @db.Timestamp(0)
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
updated_at DateTime @updatedAt() @db.Timestamp(0)
|
updated_at DateTime @updatedAt @db.Timestamp(0)
|
||||||
|
|
||||||
license_id String @unique
|
license_id String @unique
|
||||||
license License @relation(fields: [license_id], references: [id])
|
|
||||||
|
|
||||||
business_activity_id String @unique
|
business_activity_id String @unique
|
||||||
business_activity BusinessActivity @relation(fields: [business_activity_id], references: [id])
|
|
||||||
|
|
||||||
license_renews LicenseRenew[]
|
|
||||||
account_allocations LicenseAccountAllocation[]
|
account_allocations LicenseAccountAllocation[]
|
||||||
|
license_renews LicenseRenew[]
|
||||||
|
business_activity BusinessActivity @relation(fields: [business_activity_id], references: [id])
|
||||||
|
license License @relation(fields: [license_id], references: [id])
|
||||||
|
|
||||||
@@map("licenses_activated")
|
@@map("licenses_activated")
|
||||||
}
|
}
|
||||||
@@ -53,81 +45,71 @@ model LicenseActivation {
|
|||||||
model LicenseRenewChargeTransaction {
|
model LicenseRenewChargeTransaction {
|
||||||
id String @id @default(ulid())
|
id String @id @default(ulid())
|
||||||
activation_expires_at DateTime
|
activation_expires_at DateTime
|
||||||
tracking_code String @unique()
|
tracking_code String @unique
|
||||||
purchased_count Int
|
purchased_count Int
|
||||||
|
|
||||||
created_at DateTime @default(now()) @db.Timestamp(0)
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
updated_at DateTime @updatedAt() @db.Timestamp(0)
|
updated_at DateTime @updatedAt @db.Timestamp(0)
|
||||||
|
|
||||||
partner_id String
|
partner_id String
|
||||||
|
license_renews LicenseRenew[]
|
||||||
partner Partner @relation(fields: [partner_id], references: [id])
|
partner Partner @relation(fields: [partner_id], references: [id])
|
||||||
|
|
||||||
license_renews LicenseRenew[]
|
@@index([partner_id])
|
||||||
|
|
||||||
@@map("license_renew_charge_transaction")
|
@@map("license_renew_charge_transaction")
|
||||||
}
|
}
|
||||||
|
|
||||||
model LicenseRenew {
|
model LicenseRenew {
|
||||||
id String @id @default(ulid())
|
id String @id @default(ulid())
|
||||||
expires_at DateTime
|
expires_at DateTime
|
||||||
|
|
||||||
created_at DateTime @default(now()) @db.Timestamp(0)
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
updated_at DateTime @updatedAt() @db.Timestamp(0)
|
updated_at DateTime @updatedAt @db.Timestamp(0)
|
||||||
|
|
||||||
charge_transaction_id String
|
charge_transaction_id String
|
||||||
charge_transaction LicenseRenewChargeTransaction @relation(fields: [charge_transaction_id], references: [id])
|
|
||||||
|
|
||||||
activation_id String?
|
activation_id String?
|
||||||
activation LicenseActivation? @relation(fields: [activation_id], references: [id])
|
activation LicenseActivation? @relation(fields: [activation_id], references: [id])
|
||||||
|
charge_transaction LicenseRenewChargeTransaction @relation(fields: [charge_transaction_id], references: [id])
|
||||||
|
|
||||||
|
@@index([activation_id])
|
||||||
|
@@index([charge_transaction_id])
|
||||||
@@map("license_renew")
|
@@map("license_renew")
|
||||||
}
|
}
|
||||||
|
|
||||||
model PartnerAccountQuotaChargeTransaction {
|
model PartnerAccountQuotaChargeTransaction {
|
||||||
id String @id @default(ulid())
|
id String @id @default(ulid())
|
||||||
activation_expires_at DateTime
|
activation_expires_at DateTime
|
||||||
tracking_code String @unique()
|
tracking_code String @unique
|
||||||
purchased_count Int
|
purchased_count Int
|
||||||
|
|
||||||
created_at DateTime @default(now()) @db.Timestamp(0)
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
updated_at DateTime @updatedAt() @db.Timestamp(0)
|
updated_at DateTime @updatedAt @db.Timestamp(0)
|
||||||
|
|
||||||
partner_id String
|
partner_id String
|
||||||
partner Partner @relation(fields: [partner_id], references: [id])
|
partner Partner @relation(fields: [partner_id], references: [id])
|
||||||
|
|
||||||
credits PartnerAccountQuotaCredit[]
|
credits PartnerAccountQuotaCredit[]
|
||||||
|
|
||||||
|
@@index([partner_id])
|
||||||
@@map("partner_account_quota_charge_transaction")
|
@@map("partner_account_quota_charge_transaction")
|
||||||
}
|
}
|
||||||
|
|
||||||
model PartnerAccountQuotaCredit {
|
model PartnerAccountQuotaCredit {
|
||||||
id String @id @default(ulid())
|
id String @id @default(ulid())
|
||||||
|
|
||||||
created_at DateTime @default(now()) @db.Timestamp(0)
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
updated_at DateTime @updatedAt() @db.Timestamp(0)
|
updated_at DateTime @updatedAt @db.Timestamp(0)
|
||||||
|
|
||||||
charge_transaction_id String?
|
charge_transaction_id String?
|
||||||
|
allocation LicenseAccountAllocation?
|
||||||
charge_transaction PartnerAccountQuotaChargeTransaction? @relation(fields: [charge_transaction_id], references: [id])
|
charge_transaction PartnerAccountQuotaChargeTransaction? @relation(fields: [charge_transaction_id], references: [id])
|
||||||
|
|
||||||
allocation LicenseAccountAllocation?
|
@@index([charge_transaction_id])
|
||||||
|
|
||||||
@@map("partner_account_quota_credit")
|
@@map("partner_account_quota_credit")
|
||||||
}
|
}
|
||||||
|
|
||||||
model LicenseAccountAllocation {
|
model LicenseAccountAllocation {
|
||||||
id String @id @default(ulid())
|
id String @id @default(ulid())
|
||||||
|
|
||||||
created_at DateTime @default(now()) @db.Timestamp(0)
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
updated_at DateTime @updatedAt() @db.Timestamp(0)
|
updated_at DateTime @updatedAt @db.Timestamp(0)
|
||||||
|
|
||||||
license_activation_id String?
|
license_activation_id String?
|
||||||
|
account_id String? @unique
|
||||||
|
credit_id String? @unique
|
||||||
|
account ConsumerAccount? @relation(fields: [account_id], references: [id])
|
||||||
|
credit PartnerAccountQuotaCredit? @relation(fields: [credit_id], references: [id])
|
||||||
license_activation LicenseActivation? @relation(fields: [license_activation_id], references: [id])
|
license_activation LicenseActivation? @relation(fields: [license_activation_id], references: [id])
|
||||||
|
|
||||||
account_id String? @unique
|
@@index([license_activation_id])
|
||||||
account ConsumerAccount? @relation(fields: [account_id], references: [id])
|
|
||||||
|
|
||||||
credit_id String? @unique
|
|
||||||
credit PartnerAccountQuotaCredit? @relation(fields: [credit_id], references: [id])
|
|
||||||
|
|
||||||
@@map("license_account_allocation")
|
@@map("license_account_allocation")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,34 +1,32 @@
|
|||||||
model PartnerAccount {
|
model PartnerAccount {
|
||||||
id String @id @default(ulid())
|
id String @id @default(ulid())
|
||||||
role PartnerRole
|
role PartnerRole
|
||||||
|
|
||||||
created_at DateTime @default(now()) @db.Timestamp(0)
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
updated_at DateTime @default(now()) @updatedAt @db.Timestamp(0)
|
updated_at DateTime @default(now()) @updatedAt @db.Timestamp(0)
|
||||||
|
|
||||||
partner_id String
|
partner_id String
|
||||||
|
account_id String @unique
|
||||||
|
account Account @relation(fields: [account_id], references: [id], onDelete: Cascade)
|
||||||
partner Partner @relation(fields: [partner_id], references: [id])
|
partner Partner @relation(fields: [partner_id], references: [id])
|
||||||
|
|
||||||
account_id String @unique
|
@@index([partner_id], map: "partner_accounts_partner_id_fkey")
|
||||||
account Account @relation(fields: [account_id], references: [id])
|
|
||||||
|
|
||||||
@@map("partner_accounts")
|
@@map("partner_accounts")
|
||||||
}
|
}
|
||||||
|
|
||||||
model Partner {
|
model Partner {
|
||||||
id String @id @default(ulid())
|
id String @id @default(ulid())
|
||||||
name String
|
name String
|
||||||
code String @unique()
|
code String @unique
|
||||||
status PartnerStatus @default(ACTIVE)
|
status PartnerStatus @default(ACTIVE)
|
||||||
logo_url String?
|
logo_url String?
|
||||||
|
|
||||||
created_at DateTime @default(now()) @db.Timestamp(0)
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
updated_at DateTime @default(now()) @updatedAt @db.Timestamp(0)
|
updated_at DateTime @default(now()) @updatedAt @db.Timestamp(0)
|
||||||
|
tsp_provider TspProviderType @default(NAMA)
|
||||||
consumers Consumer[]
|
consumers_individual ConsumerIndividual[]
|
||||||
partner_accounts PartnerAccount[]
|
consumers_legal ConsumerLegal[]
|
||||||
license_charge_transactions LicenseChargeTransaction[]
|
license_charge_transactions LicenseChargeTransaction[]
|
||||||
account_quota_charge_transactions PartnerAccountQuotaChargeTransaction[]
|
|
||||||
license_renew_charge_transactions LicenseRenewChargeTransaction[]
|
license_renew_charge_transactions LicenseRenewChargeTransaction[]
|
||||||
|
account_quota_charge_transactions PartnerAccountQuotaChargeTransaction[]
|
||||||
|
accounts PartnerAccount[]
|
||||||
|
|
||||||
@@map("partners")
|
@@map("partners")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
model PermissionConsumer {
|
model PermissionConsumer {
|
||||||
id String @id @default(ulid())
|
id String @id @default(ulid())
|
||||||
|
|
||||||
consumer_account_id String @unique
|
consumer_account_id String @unique
|
||||||
consumer_account ConsumerAccount @relation(fields: [consumer_account_id], references: [id], onDelete: Cascade)
|
|
||||||
|
|
||||||
pos_permissions PermissionPos[]
|
|
||||||
complex_permissions PermissionComplex[]
|
|
||||||
business_permissions PermissionBusiness[]
|
business_permissions PermissionBusiness[]
|
||||||
|
complex_permissions PermissionComplex[]
|
||||||
|
consumer_account ConsumerAccount @relation(fields: [consumer_account_id], references: [id], onDelete: Cascade)
|
||||||
|
pos_permissions PermissionPos[]
|
||||||
|
|
||||||
@@map("permission_consumers")
|
@@map("permission_consumers")
|
||||||
}
|
}
|
||||||
@@ -14,41 +12,38 @@ model PermissionConsumer {
|
|||||||
model PermissionPos {
|
model PermissionPos {
|
||||||
id String @id @default(ulid())
|
id String @id @default(ulid())
|
||||||
role POSRole
|
role POSRole
|
||||||
|
|
||||||
pos_id String
|
pos_id String
|
||||||
permission_id String
|
permission_id String
|
||||||
|
|
||||||
pos Pos @relation(fields: [pos_id], references: [id], onDelete: Cascade)
|
|
||||||
permission PermissionConsumer @relation(fields: [permission_id], references: [id], onDelete: Cascade)
|
permission PermissionConsumer @relation(fields: [permission_id], references: [id], onDelete: Cascade)
|
||||||
|
pos Pos @relation(fields: [pos_id], references: [id], onDelete: Cascade)
|
||||||
|
|
||||||
@@unique([permission_id, pos_id])
|
@@unique([permission_id, pos_id])
|
||||||
|
@@index([pos_id], map: "permission_poses_pos_id_fkey")
|
||||||
@@map("permission_poses")
|
@@map("permission_poses")
|
||||||
}
|
}
|
||||||
|
|
||||||
model PermissionComplex {
|
model PermissionComplex {
|
||||||
id String @id @default(ulid())
|
id String @id @default(ulid())
|
||||||
role ComplexRole
|
role ComplexRole
|
||||||
|
|
||||||
complex_id String
|
complex_id String
|
||||||
permission_id String
|
permission_id String
|
||||||
|
|
||||||
complex Complex @relation(fields: [complex_id], references: [id], onDelete: Cascade)
|
complex Complex @relation(fields: [complex_id], references: [id], onDelete: Cascade)
|
||||||
permission PermissionConsumer @relation(fields: [permission_id], references: [id], onDelete: Cascade)
|
permission PermissionConsumer @relation(fields: [permission_id], references: [id], onDelete: Cascade)
|
||||||
|
|
||||||
@@unique([permission_id, complex_id])
|
@@unique([permission_id, complex_id])
|
||||||
|
@@index([complex_id], map: "permission_complexes_complex_id_fkey")
|
||||||
@@map("permission_complexes")
|
@@map("permission_complexes")
|
||||||
}
|
}
|
||||||
|
|
||||||
model PermissionBusiness {
|
model PermissionBusiness {
|
||||||
id String @id @default(ulid())
|
id String @id @default(ulid())
|
||||||
role BusinessRole
|
role BusinessRole
|
||||||
|
|
||||||
business_id String
|
business_id String
|
||||||
permission_id String
|
permission_id String
|
||||||
|
|
||||||
business BusinessActivity @relation(fields: [business_id], references: [id], onDelete: Cascade)
|
business BusinessActivity @relation(fields: [business_id], references: [id], onDelete: Cascade)
|
||||||
permission PermissionConsumer @relation(fields: [permission_id], references: [id], onDelete: Cascade)
|
permission PermissionConsumer @relation(fields: [permission_id], references: [id], onDelete: Cascade)
|
||||||
|
|
||||||
@@unique([permission_id, business_id])
|
@@unique([permission_id, business_id])
|
||||||
|
@@index([business_id], map: "permission_business_activities_business_id_fkey")
|
||||||
@@map("permission_business_activities")
|
@@map("permission_business_activities")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,30 +1,26 @@
|
|||||||
model ProviderAccount {
|
model ProviderAccount {
|
||||||
id String @id @default(ulid())
|
id String @id @default(ulid())
|
||||||
role ProviderRole
|
role ProviderRole
|
||||||
|
|
||||||
created_at DateTime @default(now()) @db.Timestamp(0)
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
updated_at DateTime @updatedAt() @db.Timestamp(0)
|
updated_at DateTime @updatedAt @db.Timestamp(0)
|
||||||
|
|
||||||
provider_id String
|
provider_id String
|
||||||
|
account_id String @unique
|
||||||
|
account Account @relation(fields: [account_id], references: [id], onDelete: Cascade)
|
||||||
provider Provider @relation(fields: [provider_id], references: [id])
|
provider Provider @relation(fields: [provider_id], references: [id])
|
||||||
|
|
||||||
account_id String @unique
|
@@index([provider_id], map: "provider_accounts_provider_id_fkey")
|
||||||
account Account @relation(fields: [account_id], references: [id])
|
|
||||||
|
|
||||||
@@map("provider_accounts")
|
@@map("provider_accounts")
|
||||||
}
|
}
|
||||||
|
|
||||||
model Provider {
|
model Provider {
|
||||||
id String @id @default(ulid())
|
id String @id @default(ulid())
|
||||||
code String @unique()
|
code String @unique
|
||||||
status PartnerStatus @default(ACTIVE)
|
status PartnerStatus @default(ACTIVE)
|
||||||
name String
|
name String
|
||||||
|
|
||||||
created_at DateTime @default(now()) @db.Timestamp(0)
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
updated_at DateTime @updatedAt @db.Timestamp(0)
|
updated_at DateTime @updatedAt @db.Timestamp(0)
|
||||||
|
|
||||||
pos_list Pos[]
|
pos_list Pos[]
|
||||||
provider_accounts ProviderAccount[]
|
accounts ProviderAccount[]
|
||||||
|
|
||||||
@@map("providers")
|
@@map("providers")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
model ConsumerAccountDevice {
|
||||||
|
id String @id @default(ulid())
|
||||||
|
device_id String @unique
|
||||||
|
device_name String?
|
||||||
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
|
updated_at DateTime @updatedAt @db.Timestamp(0)
|
||||||
|
consumer_account_id String @unique
|
||||||
|
consumer_account ConsumerAccount @relation(fields: [consumer_account_id], references: [id])
|
||||||
|
|
||||||
|
@@index([consumer_account_id])
|
||||||
|
@@map("consumer_account_device")
|
||||||
|
}
|
||||||
@@ -1,24 +1 @@
|
|||||||
model ConsumerDevices {
|
|
||||||
uuid String @id @unique() @db.VarChar(255)
|
|
||||||
app_version String @db.VarChar(20)
|
|
||||||
build_number String @db.VarChar(20)
|
|
||||||
platform String @db.VarChar(100)
|
|
||||||
brand String @db.VarChar(100)
|
|
||||||
model String @db.VarChar(100)
|
|
||||||
device String @db.VarChar(100)
|
|
||||||
publisher ApplicationPublisher
|
|
||||||
os_version String @db.VarChar(20)
|
|
||||||
sdk_version String @db.VarChar(20)
|
|
||||||
release_number String @db.VarChar(20)
|
|
||||||
user_agent String? @db.VarChar(100)
|
|
||||||
browser_name String? @db.VarChar(100)
|
|
||||||
fcm_token String? @db.VarChar(100)
|
|
||||||
|
|
||||||
created_at DateTime @default(now()) @db.Timestamp(0)
|
|
||||||
updated_at DateTime @updatedAt() @db.Timestamp(0)
|
|
||||||
|
|
||||||
consumer_id String
|
|
||||||
consumer Consumer @relation(fields: [consumer_id], references: [id])
|
|
||||||
|
|
||||||
@@map("consumer_devices")
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -6,11 +6,9 @@ model ApplicationReleasedInfo {
|
|||||||
release_type ApplicationReleaseType
|
release_type ApplicationReleaseType
|
||||||
platform ApplicationPlatform
|
platform ApplicationPlatform
|
||||||
notes Json?
|
notes Json?
|
||||||
|
|
||||||
release_date DateTime @default(now()) @db.Timestamp(0)
|
release_date DateTime @default(now()) @db.Timestamp(0)
|
||||||
|
|
||||||
created_at DateTime @default(now()) @db.Timestamp(0)
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
updated_at DateTime @updatedAt() @db.Timestamp(0)
|
updated_at DateTime @updatedAt @db.Timestamp(0)
|
||||||
|
|
||||||
@@map("application_released_info")
|
@@map("application_released_info")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,146 @@
|
|||||||
|
model ConsumerAccount {
|
||||||
|
id String @id @default(ulid())
|
||||||
|
role ConsumerRole
|
||||||
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
|
updated_at DateTime @updatedAt @db.Timestamp(0)
|
||||||
|
consumer_id String
|
||||||
|
account_id String @unique
|
||||||
|
account_device ConsumerAccountDevice?
|
||||||
|
consumer_account_good_favorites ConsumerAccountGoodFavorite[]
|
||||||
|
account Account @relation(fields: [account_id], references: [id])
|
||||||
|
consumer Consumer @relation(fields: [consumer_id], references: [id])
|
||||||
|
account_allocation LicenseAccountAllocation?
|
||||||
|
permission PermissionConsumer?
|
||||||
|
pos Pos?
|
||||||
|
sales_invoices SalesInvoice[]
|
||||||
|
|
||||||
|
@@index([consumer_id], map: "consumer_accounts_consumer_id_fkey")
|
||||||
|
@@map("consumer_accounts")
|
||||||
|
}
|
||||||
|
|
||||||
|
model Consumer {
|
||||||
|
id String @id @default(ulid())
|
||||||
|
type ConsumerType
|
||||||
|
status ConsumerStatus @default(ACTIVE)
|
||||||
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
|
updated_at DateTime @updatedAt @db.Timestamp(0)
|
||||||
|
business_activities BusinessActivity[]
|
||||||
|
accounts ConsumerAccount[]
|
||||||
|
individual ConsumerIndividual?
|
||||||
|
legal ConsumerLegal?
|
||||||
|
|
||||||
|
@@map("consumers")
|
||||||
|
}
|
||||||
|
|
||||||
|
model ConsumerIndividual {
|
||||||
|
first_name String
|
||||||
|
last_name String
|
||||||
|
mobile_number String
|
||||||
|
national_code String
|
||||||
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
|
updated_at DateTime @updatedAt @db.Timestamp(0)
|
||||||
|
partner_id String
|
||||||
|
consumer_id String @id
|
||||||
|
consumer Consumer @relation(fields: [consumer_id], references: [id], onDelete: Cascade)
|
||||||
|
partner Partner @relation(fields: [partner_id], references: [id])
|
||||||
|
|
||||||
|
@@unique([mobile_number, consumer_id])
|
||||||
|
@@unique([partner_id, national_code])
|
||||||
|
@@map("consumers_individual")
|
||||||
|
}
|
||||||
|
|
||||||
|
model ConsumerLegal {
|
||||||
|
name String
|
||||||
|
registration_code String
|
||||||
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
|
updated_at DateTime @updatedAt @db.Timestamp(0)
|
||||||
|
partner_id String
|
||||||
|
consumer_id String @id
|
||||||
|
consumer Consumer @relation(fields: [consumer_id], references: [id], onDelete: Cascade)
|
||||||
|
partner Partner @relation(fields: [partner_id], references: [id])
|
||||||
|
|
||||||
|
@@unique([partner_id, registration_code])
|
||||||
|
@@map("consumers_legal")
|
||||||
|
}
|
||||||
|
|
||||||
|
model BusinessActivity {
|
||||||
|
id String @id @default(ulid())
|
||||||
|
economic_code String
|
||||||
|
name String
|
||||||
|
fiscal_id String
|
||||||
|
partner_token String
|
||||||
|
invoice_number_sequence Decimal @default(1) @db.Decimal(20, 0)
|
||||||
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
|
updated_at DateTime @updatedAt @db.Timestamp(0)
|
||||||
|
guild_id String
|
||||||
|
consumer_id String
|
||||||
|
consumer Consumer @relation(fields: [consumer_id], references: [id])
|
||||||
|
guild Guild @relation(fields: [guild_id], references: [id])
|
||||||
|
complexes Complex[]
|
||||||
|
customer_individuals CustomerIndividual[]
|
||||||
|
customer_legals CustomerLegal[]
|
||||||
|
goods Good[]
|
||||||
|
license_activation LicenseActivation?
|
||||||
|
permission_businesses PermissionBusiness[]
|
||||||
|
|
||||||
|
@@unique([economic_code, consumer_id])
|
||||||
|
@@index([consumer_id], map: "business_activities_consumer_id_fkey")
|
||||||
|
@@index([guild_id], map: "business_activities_guild_id_fkey")
|
||||||
|
@@map("business_activities")
|
||||||
|
}
|
||||||
|
|
||||||
|
model Complex {
|
||||||
|
id String @id @default(ulid())
|
||||||
|
name String
|
||||||
|
branch_code String
|
||||||
|
address String?
|
||||||
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
|
updated_at DateTime @updatedAt @db.Timestamp(0)
|
||||||
|
business_activity_id String
|
||||||
|
business_activity BusinessActivity @relation(fields: [business_activity_id], references: [id])
|
||||||
|
good_categories GoodCategory[]
|
||||||
|
permission_complexes PermissionComplex[]
|
||||||
|
pos_list Pos[]
|
||||||
|
|
||||||
|
@@index([business_activity_id], map: "complexes_business_activity_id_fkey")
|
||||||
|
@@map("complexes")
|
||||||
|
}
|
||||||
|
|
||||||
|
model Pos {
|
||||||
|
id String @id @default(ulid())
|
||||||
|
name String
|
||||||
|
model String?
|
||||||
|
serial_number String? @unique
|
||||||
|
status POSStatus @default(ACTIVE)
|
||||||
|
pos_type POSType
|
||||||
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
|
updated_at DateTime @updatedAt @db.Timestamp(0)
|
||||||
|
complex_id String
|
||||||
|
device_id String?
|
||||||
|
provider_id String?
|
||||||
|
account_id String @unique
|
||||||
|
permission_pos PermissionPos[]
|
||||||
|
account ConsumerAccount @relation(fields: [account_id], references: [id])
|
||||||
|
complex Complex @relation(fields: [complex_id], references: [id])
|
||||||
|
device Device? @relation(fields: [device_id], references: [id])
|
||||||
|
provider Provider? @relation(fields: [provider_id], references: [id])
|
||||||
|
sales_invoices SalesInvoice[]
|
||||||
|
|
||||||
|
@@index([complex_id], map: "poses_complex_id_fkey")
|
||||||
|
@@index([device_id], map: "poses_device_id_fkey")
|
||||||
|
@@index([provider_id], map: "poses_provider_id_fkey")
|
||||||
|
@@map("poses")
|
||||||
|
}
|
||||||
|
|
||||||
|
model ConsumerAccountGoodFavorite {
|
||||||
|
created_at DateTime @default(now())
|
||||||
|
consumer_account_id String
|
||||||
|
good_id String
|
||||||
|
consumer_account ConsumerAccount @relation(fields: [consumer_account_id], references: [id], onDelete: Cascade)
|
||||||
|
good Good @relation(fields: [good_id], references: [id], onDelete: Cascade)
|
||||||
|
|
||||||
|
@@id([consumer_account_id, good_id])
|
||||||
|
@@index([good_id])
|
||||||
|
@@index([consumer_account_id])
|
||||||
|
@@map("consumer_account_good_favorites")
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
model Good {
|
||||||
|
id String @id @default(ulid())
|
||||||
|
name String @db.VarChar(255)
|
||||||
|
is_default_guild_good Boolean @default(false)
|
||||||
|
pricing_model GoodPricingModel
|
||||||
|
description String? @db.Text
|
||||||
|
local_sku String? @unique @db.VarChar(100)
|
||||||
|
barcode String? @unique @db.VarChar(100)
|
||||||
|
base_sale_price Decimal? @default(0) @db.Decimal(15, 0)
|
||||||
|
image_url String? @db.VarChar(255)
|
||||||
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
|
updated_at DateTime @updatedAt @db.Timestamp(0)
|
||||||
|
deleted_at DateTime? @db.Timestamp(0)
|
||||||
|
sku_id String
|
||||||
|
measure_unit_id String
|
||||||
|
category_id String?
|
||||||
|
business_activity_id String?
|
||||||
|
consumer_account_good_favorites ConsumerAccountGoodFavorite[]
|
||||||
|
business_activity BusinessActivity? @relation(fields: [business_activity_id], references: [id])
|
||||||
|
category GoodCategory? @relation(fields: [category_id], references: [id])
|
||||||
|
measure_unit MeasureUnits @relation(fields: [measure_unit_id], references: [id])
|
||||||
|
sku StockKeepingUnits @relation(fields: [sku_id], references: [id])
|
||||||
|
sales_invoice_items SalesInvoiceItem[]
|
||||||
|
|
||||||
|
@@index([category_id])
|
||||||
|
@@index([business_activity_id], map: "goods_business_activity_id_fkey")
|
||||||
|
@@index([measure_unit_id], map: "goods_measure_unit_id_fkey")
|
||||||
|
@@index([sku_id], map: "goods_sku_id_fkey")
|
||||||
|
@@map("goods")
|
||||||
|
}
|
||||||
|
|
||||||
|
model GoodCategory {
|
||||||
|
id String @id @default(ulid())
|
||||||
|
name String @db.VarChar(100)
|
||||||
|
description String? @db.Text
|
||||||
|
image_url String? @db.VarChar(255)
|
||||||
|
complex_id String?
|
||||||
|
is_default_guild_good Boolean @default(false)
|
||||||
|
guild_id String?
|
||||||
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
|
updated_at DateTime @updatedAt @db.Timestamp(0)
|
||||||
|
deleted_at DateTime? @db.Timestamp(0)
|
||||||
|
complex Complex? @relation(fields: [complex_id], references: [id])
|
||||||
|
guild Guild? @relation(fields: [guild_id], references: [id])
|
||||||
|
goods Good[]
|
||||||
|
|
||||||
|
@@index([complex_id], map: "good_categories_complex_id_fkey")
|
||||||
|
@@index([guild_id], map: "good_categories_guild_id_fkey")
|
||||||
|
@@map("good_categories")
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
model Guild {
|
||||||
|
id String @id @default(ulid())
|
||||||
|
name String
|
||||||
|
invoice_template InvoiceTemplateType
|
||||||
|
code String?
|
||||||
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
|
updated_at DateTime @updatedAt @db.Timestamp(0)
|
||||||
|
business_activities BusinessActivity[]
|
||||||
|
good_categories GoodCategory[]
|
||||||
|
stockKeepingUnits StockKeepingUnits[]
|
||||||
|
|
||||||
|
@@map("guilds")
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
model MeasureUnits {
|
||||||
|
id String @id @default(ulid())
|
||||||
|
code String @unique
|
||||||
|
name String
|
||||||
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
|
updated_at DateTime @default(now()) @updatedAt @db.Timestamp(0)
|
||||||
|
goods Good[]
|
||||||
|
|
||||||
|
@@map("measure_units")
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
model StockKeepingUnits {
|
||||||
|
id String @id @default(ulid())
|
||||||
|
code String @unique
|
||||||
|
name String
|
||||||
|
VAT Decimal @db.Decimal(5, 2)
|
||||||
|
is_public Boolean @default(true)
|
||||||
|
is_domestic Boolean @default(false)
|
||||||
|
guild_id String
|
||||||
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
|
updated_at DateTime @updatedAt @db.Timestamp(0)
|
||||||
|
goods Good[]
|
||||||
|
guild Guild @relation(fields: [guild_id], references: [id])
|
||||||
|
|
||||||
|
@@index([code])
|
||||||
|
@@index([guild_id], map: "stock_keeping_units_guild_id_fkey")
|
||||||
|
@@map("stock_keeping_units")
|
||||||
|
}
|
||||||
@@ -1,19 +1,8 @@
|
|||||||
// generator client {
|
|
||||||
// provider = "prisma-client-js"
|
|
||||||
// // output = "../../src/generated/prisma"
|
|
||||||
// // moduleFormat = "cjs"
|
|
||||||
// previewFeatures = ["views"]
|
|
||||||
// }
|
|
||||||
|
|
||||||
// datasource db {
|
|
||||||
// provider = "mysql"
|
|
||||||
// }
|
|
||||||
|
|
||||||
generator client {
|
generator client {
|
||||||
provider = "prisma-client"
|
provider = "prisma-client"
|
||||||
output = "../../src/generated/prisma"
|
output = "../../src/generated/prisma"
|
||||||
moduleFormat = "cjs"
|
|
||||||
previewFeatures = ["views"]
|
previewFeatures = ["views"]
|
||||||
|
moduleFormat = "cjs"
|
||||||
}
|
}
|
||||||
|
|
||||||
datasource db {
|
datasource db {
|
||||||
|
|||||||
@@ -1,51 +1,47 @@
|
|||||||
model Customer {
|
model Customer {
|
||||||
id String @id @default(ulid())
|
id String @id @default(ulid())
|
||||||
is_favorite Boolean? @default(false)
|
is_favorite Boolean? @default(false)
|
||||||
|
type CustomerType
|
||||||
created_at DateTime @default(now()) @db.Timestamp(0)
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
updated_at DateTime @updatedAt @db.Timestamp(0)
|
updated_at DateTime @updatedAt @db.Timestamp(0)
|
||||||
deleted_at DateTime? @db.Timestamp(0)
|
deleted_at DateTime? @db.Timestamp(0)
|
||||||
|
individual CustomerIndividual?
|
||||||
type CustomerType
|
legal CustomerLegal?
|
||||||
unknown_customer Json?
|
|
||||||
customer_individual CustomerIndividual?
|
|
||||||
customer_legal CustomerLegal?
|
|
||||||
sales_invoices SalesInvoice[]
|
sales_invoices SalesInvoice[]
|
||||||
|
|
||||||
@@map("customers")
|
@@map("customers")
|
||||||
}
|
}
|
||||||
|
|
||||||
model CustomerIndividual {
|
model CustomerIndividual {
|
||||||
first_name String @db.VarChar(255)
|
first_name String? @db.VarChar(255)
|
||||||
last_name String @db.VarChar(255)
|
last_name String? @db.VarChar(255)
|
||||||
national_id String @db.Char(10)
|
national_id String? @db.Char(10)
|
||||||
postal_code String @db.Char(10)
|
mobile_number String? @db.Char(15)
|
||||||
economic_code String? @db.Char(10)
|
postal_code String? @db.Char(10)
|
||||||
|
economic_code String? @db.Char(14)
|
||||||
customer_id String @id
|
customer_id String @id
|
||||||
|
business_activity_id String
|
||||||
|
business_activity BusinessActivity @relation(fields: [business_activity_id], references: [id])
|
||||||
customer Customer @relation(fields: [customer_id], references: [id], onDelete: Cascade)
|
customer Customer @relation(fields: [customer_id], references: [id], onDelete: Cascade)
|
||||||
|
|
||||||
complex_id String
|
@@unique([business_activity_id, national_id])
|
||||||
complex Complex @relation(fields: [complex_id], references: [id])
|
@@unique([business_activity_id, postal_code, national_id])
|
||||||
|
@@index([business_activity_id])
|
||||||
@@unique([complex_id, national_id])
|
|
||||||
@@index([complex_id])
|
|
||||||
@@map("customer_individuals")
|
@@map("customer_individuals")
|
||||||
}
|
}
|
||||||
|
|
||||||
model CustomerLegal {
|
model CustomerLegal {
|
||||||
company_name String @db.VarChar(255)
|
name String? @db.VarChar(255)
|
||||||
economic_code String @db.Char(10)
|
economic_code String? @db.Char(11)
|
||||||
registration_number String @db.Char(20)
|
registration_number String? @db.Char(20)
|
||||||
postal_code String @db.Char(10)
|
postal_code String? @db.Char(10)
|
||||||
|
|
||||||
customer_id String @id
|
customer_id String @id
|
||||||
|
business_activity_id String
|
||||||
|
business_activity BusinessActivity @relation(fields: [business_activity_id], references: [id])
|
||||||
customer Customer @relation(fields: [customer_id], references: [id], onDelete: Cascade)
|
customer Customer @relation(fields: [customer_id], references: [id], onDelete: Cascade)
|
||||||
|
|
||||||
complex_id String
|
@@unique([business_activity_id, economic_code])
|
||||||
complex Complex @relation(fields: [complex_id], references: [id])
|
@@unique([business_activity_id, postal_code, registration_number])
|
||||||
|
@@index([business_activity_id])
|
||||||
@@unique([complex_id, registration_number])
|
|
||||||
@@index([complex_id])
|
|
||||||
@@map("customer_legal")
|
@@map("customer_legal")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,14 @@
|
|||||||
enum PaymentMethodType {
|
enum PaymentMethodType {
|
||||||
TERMINAL
|
CHEQUE
|
||||||
CASH
|
|
||||||
SET_OFF
|
SET_OFF
|
||||||
|
CASH
|
||||||
|
TERMINAL
|
||||||
|
PAYMENT_GATEWAY
|
||||||
CARD
|
CARD
|
||||||
BANK
|
BANK
|
||||||
CHECK
|
|
||||||
OTHER
|
OTHER
|
||||||
}
|
}
|
||||||
|
|
||||||
enum UnitType {
|
|
||||||
COUNT
|
|
||||||
GRAM
|
|
||||||
KILOGRAM
|
|
||||||
MILLILITER
|
|
||||||
LITER
|
|
||||||
METER
|
|
||||||
HOUR
|
|
||||||
}
|
|
||||||
|
|
||||||
enum GoodPricingModel {
|
enum GoodPricingModel {
|
||||||
STANDARD
|
STANDARD
|
||||||
GOLD
|
GOLD
|
||||||
@@ -49,18 +40,6 @@ enum BusinessRole {
|
|||||||
OPERATOR
|
OPERATOR
|
||||||
}
|
}
|
||||||
|
|
||||||
enum LicenseType {
|
|
||||||
BASIC
|
|
||||||
PRO
|
|
||||||
ENTERPRISE
|
|
||||||
}
|
|
||||||
|
|
||||||
enum LicenseStatus {
|
|
||||||
ACTIVE
|
|
||||||
EXPIRED
|
|
||||||
SUSPENDED
|
|
||||||
}
|
|
||||||
|
|
||||||
enum POSType {
|
enum POSType {
|
||||||
PSP
|
PSP
|
||||||
MOBILE
|
MOBILE
|
||||||
@@ -68,11 +47,6 @@ enum POSType {
|
|||||||
API
|
API
|
||||||
}
|
}
|
||||||
|
|
||||||
enum UserType {
|
|
||||||
LEGAL
|
|
||||||
INDIVIDUAL
|
|
||||||
}
|
|
||||||
|
|
||||||
enum AccountType {
|
enum AccountType {
|
||||||
ADMIN
|
ADMIN
|
||||||
PROVIDER
|
PROVIDER
|
||||||
@@ -80,17 +54,6 @@ enum AccountType {
|
|||||||
CONSUMER
|
CONSUMER
|
||||||
}
|
}
|
||||||
|
|
||||||
enum UserStatus {
|
|
||||||
ACTIVE
|
|
||||||
INACTIVE
|
|
||||||
}
|
|
||||||
|
|
||||||
enum AccountRole {
|
|
||||||
OWNER
|
|
||||||
OPERATOR
|
|
||||||
ACCOUNTANT
|
|
||||||
}
|
|
||||||
|
|
||||||
enum AccountStatus {
|
enum AccountStatus {
|
||||||
ACTIVE
|
ACTIVE
|
||||||
SUSPENDED
|
SUSPENDED
|
||||||
@@ -113,11 +76,6 @@ enum ProviderRole {
|
|||||||
OPERATOR
|
OPERATOR
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ProviderStatus {
|
|
||||||
ACTIVE
|
|
||||||
SUSPENDED
|
|
||||||
}
|
|
||||||
|
|
||||||
enum ConsumerRole {
|
enum ConsumerRole {
|
||||||
OWNER
|
OWNER
|
||||||
MANAGER
|
MANAGER
|
||||||
@@ -129,11 +87,6 @@ enum ConsumerStatus {
|
|||||||
SUSPENDED
|
SUSPENDED
|
||||||
}
|
}
|
||||||
|
|
||||||
enum TokenType {
|
|
||||||
ACCESS
|
|
||||||
REFRESH
|
|
||||||
}
|
|
||||||
|
|
||||||
enum ApplicationPlatform {
|
enum ApplicationPlatform {
|
||||||
ANDROID
|
ANDROID
|
||||||
IOS
|
IOS
|
||||||
@@ -145,8 +98,48 @@ enum ApplicationReleaseType {
|
|||||||
ALPHA
|
ALPHA
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ApplicationPublisher {
|
enum ConsumerType {
|
||||||
DIRECT
|
INDIVIDUAL
|
||||||
CAFE_BAZAR
|
LEGAL
|
||||||
MAYKET
|
}
|
||||||
|
|
||||||
|
enum InvoiceSettlementType {
|
||||||
|
CASH
|
||||||
|
CREDIT
|
||||||
|
MIXED
|
||||||
|
}
|
||||||
|
|
||||||
|
enum TspProviderType {
|
||||||
|
NAMA
|
||||||
|
SUN
|
||||||
|
}
|
||||||
|
|
||||||
|
enum TspProviderResponseStatus {
|
||||||
|
NOT_SEND
|
||||||
|
QUEUED
|
||||||
|
FISCAL_QUEUED
|
||||||
|
SEND_FAILURE
|
||||||
|
SUCCESS
|
||||||
|
FAILURE
|
||||||
|
}
|
||||||
|
|
||||||
|
enum TspProviderRequestType {
|
||||||
|
ORIGINAL
|
||||||
|
CORRECTION
|
||||||
|
REVOKE
|
||||||
|
RETURN
|
||||||
|
}
|
||||||
|
|
||||||
|
enum InvoiceTemplateType {
|
||||||
|
SALE
|
||||||
|
FX_SALE
|
||||||
|
GOLD_JEWELRY
|
||||||
|
CONTRACT
|
||||||
|
UTILITY
|
||||||
|
AIR_TICKET
|
||||||
|
EXPORT
|
||||||
|
BILL_OF_LADING
|
||||||
|
PETROCHEMICAL
|
||||||
|
COMMODITY_EXCHANGE
|
||||||
|
INSURANCE
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
model Good {
|
|
||||||
id String @id @default(ulid())
|
|
||||||
name String @db.VarChar(255)
|
|
||||||
is_default_guild_good Boolean @default(false)
|
|
||||||
sku String @db.VarChar(100)
|
|
||||||
unit_type UnitType
|
|
||||||
pricing_model GoodPricingModel
|
|
||||||
description String? @db.Text
|
|
||||||
local_sku String? @unique() @db.VarChar(100)
|
|
||||||
barcode String? @unique() @db.VarChar(100)
|
|
||||||
base_sale_price Decimal? @default(0.00) @db.Decimal(15, 0)
|
|
||||||
image_url String? @db.VarChar(255)
|
|
||||||
|
|
||||||
created_at DateTime @default(now()) @db.Timestamp(0)
|
|
||||||
updated_at DateTime @updatedAt @db.Timestamp(0)
|
|
||||||
deleted_at DateTime? @db.Timestamp(0)
|
|
||||||
|
|
||||||
complex_id String?
|
|
||||||
category_id String?
|
|
||||||
|
|
||||||
category GoodCategory? @relation(fields: [category_id], references: [id])
|
|
||||||
complex Complex? @relation(fields: [complex_id], references: [id])
|
|
||||||
sales_invoice_items SalesInvoiceItem[]
|
|
||||||
|
|
||||||
@@index([category_id])
|
|
||||||
@@map("goods")
|
|
||||||
}
|
|
||||||
|
|
||||||
model GoodCategory {
|
|
||||||
id String @id @default(ulid())
|
|
||||||
name String @db.VarChar(100)
|
|
||||||
description String? @db.Text
|
|
||||||
image_url String? @db.VarChar(255)
|
|
||||||
complex_id String?
|
|
||||||
is_default_guild_good Boolean @default(false)
|
|
||||||
guild_id String?
|
|
||||||
|
|
||||||
created_at DateTime @default(now()) @db.Timestamp(0)
|
|
||||||
updated_at DateTime @updatedAt @db.Timestamp(0)
|
|
||||||
deleted_at DateTime? @db.Timestamp(0)
|
|
||||||
|
|
||||||
goods Good[]
|
|
||||||
guild Guild? @relation(fields: [guild_id], references: [id])
|
|
||||||
complex Complex? @relation(fields: [complex_id], references: [id])
|
|
||||||
|
|
||||||
@@map("good_categories")
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
model Guild {
|
|
||||||
id String @id @default(ulid())
|
|
||||||
name String
|
|
||||||
code String?
|
|
||||||
|
|
||||||
created_at DateTime @default(now()) @db.Timestamp(0)
|
|
||||||
updated_at DateTime @updatedAt() @db.Timestamp(0)
|
|
||||||
|
|
||||||
business_activities BusinessActivity[]
|
|
||||||
good_categories GoodCategory[]
|
|
||||||
|
|
||||||
@@map("guilds")
|
|
||||||
}
|
|
||||||
@@ -1,60 +1,122 @@
|
|||||||
model SalesInvoice {
|
model SalesInvoice {
|
||||||
id String @id @default(ulid())
|
id String @id @default(uuid())
|
||||||
code String @unique @db.VarChar(100)
|
code String @unique @db.VarChar(100)
|
||||||
total_amount Decimal @db.Decimal(15, 2)
|
total_amount Decimal @db.Decimal(15, 2)
|
||||||
|
invoice_number Int
|
||||||
|
invoice_date DateTime @default(now()) @db.Timestamp(0)
|
||||||
|
type TspProviderRequestType
|
||||||
|
tax_id String? @unique @db.VarChar(32)
|
||||||
notes String? @db.Text
|
notes String? @db.Text
|
||||||
unknown_customer Json? @db.Json
|
unknown_customer Json?
|
||||||
invoice_date DateTime? @default(now()) @db.Timestamp(0)
|
|
||||||
created_at DateTime @default(now()) @db.Timestamp(0)
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
updated_at DateTime @updatedAt @db.Timestamp(0)
|
updated_at DateTime @updatedAt @db.Timestamp(0)
|
||||||
|
main_id String? @db.VarChar(50)
|
||||||
|
ref_id String? @unique @db.VarChar(50)
|
||||||
customer_id String?
|
customer_id String?
|
||||||
account_id String
|
consumer_account_id String
|
||||||
pos_id String
|
pos_id String
|
||||||
|
settlement_type InvoiceSettlementType
|
||||||
customer Customer? @relation(fields: [customer_id], references: [id])
|
discount_amount Decimal? @db.Decimal(15, 2)
|
||||||
pos Pos @relation(fields: [pos_id], references: [id])
|
tax_amount Decimal? @db.Decimal(15, 2)
|
||||||
consumer_account ConsumerAccount @relation(fields: [account_id], references: [id])
|
last_tsp_status TspProviderResponseStatus?
|
||||||
|
last_attempt_no Int?
|
||||||
|
tsp_attempts SaleInvoiceTspAttempts[]
|
||||||
items SalesInvoiceItem[]
|
items SalesInvoiceItem[]
|
||||||
payments SalesInvoicePayment[]
|
payments SalesInvoicePayment[]
|
||||||
|
consumer_account ConsumerAccount @relation(fields: [consumer_account_id], references: [id])
|
||||||
|
customer Customer? @relation(fields: [customer_id], references: [id])
|
||||||
|
pos Pos @relation(fields: [pos_id], references: [id])
|
||||||
|
reference_invoice SalesInvoice? @relation("SalesInvoiceReference", fields: [ref_id], references: [id])
|
||||||
|
referenced_by SalesInvoice? @relation("SalesInvoiceReference")
|
||||||
|
|
||||||
|
@@unique([invoice_number, pos_id])
|
||||||
|
@@index([pos_id, invoice_date])
|
||||||
|
@@index([ref_id])
|
||||||
|
@@index([tax_id])
|
||||||
|
@@index([consumer_account_id], map: "sales_invoices_consumer_account_id_fkey")
|
||||||
|
@@index([customer_id], map: "sales_invoices_customer_id_fkey")
|
||||||
@@map("sales_invoices")
|
@@map("sales_invoices")
|
||||||
}
|
}
|
||||||
|
|
||||||
model SalesInvoiceItem {
|
model SalesInvoiceItem {
|
||||||
id String @id @default(ulid())
|
id String @id @default(ulid())
|
||||||
quantity Decimal @db.Decimal(10, 0)
|
quantity Decimal @db.Decimal(10, 0)
|
||||||
unit_type UnitType
|
measure_unit_text String @db.VarChar(50)
|
||||||
|
measure_unit_code String @db.VarChar(50)
|
||||||
|
sku_code String @db.VarChar(50)
|
||||||
|
sku_vat Decimal @default(0.00) @db.Decimal(15, 2)
|
||||||
unit_price Decimal @default(0.00) @db.Decimal(15, 2)
|
unit_price Decimal @default(0.00) @db.Decimal(15, 2)
|
||||||
total_amount Decimal @default(0.00) @db.Decimal(15, 2)
|
total_amount Decimal @default(0.00) @db.Decimal(15, 2)
|
||||||
created_at DateTime @default(now()) @db.Timestamp(0)
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
discount Decimal @default(0.00) @db.Decimal(15, 2)
|
discount Decimal @default(0.00) @db.Decimal(15, 2)
|
||||||
notes String? @db.Text
|
notes String? @db.Text
|
||||||
|
|
||||||
invoice_id String
|
|
||||||
good_id String?
|
|
||||||
service_id String?
|
|
||||||
|
|
||||||
payload Json?
|
payload Json?
|
||||||
|
good_snapshot Json
|
||||||
|
invoice_id String
|
||||||
|
good_id String
|
||||||
|
service_id String?
|
||||||
|
discount_amount Decimal? @db.Decimal(15, 2)
|
||||||
|
tax_amount Decimal? @db.Decimal(15, 2)
|
||||||
|
|
||||||
|
good Good @relation(fields: [good_id], references: [id])
|
||||||
invoice SalesInvoice @relation(fields: [invoice_id], references: [id])
|
invoice SalesInvoice @relation(fields: [invoice_id], references: [id])
|
||||||
good Good? @relation(fields: [good_id], references: [id])
|
|
||||||
service Service? @relation(fields: [service_id], references: [id])
|
service Service? @relation(fields: [service_id], references: [id])
|
||||||
|
|
||||||
@@index([invoice_id, good_id])
|
@@index([invoice_id, good_id])
|
||||||
|
@@index([good_id], map: "sales_invoice_items_good_id_fkey")
|
||||||
|
@@index([service_id], map: "sales_invoice_items_service_id_fkey")
|
||||||
@@map("sales_invoice_items")
|
@@map("sales_invoice_items")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
model SaleInvoiceTspAttempts {
|
||||||
|
id String @id @default(ulid())
|
||||||
|
attempt_no Int
|
||||||
|
status TspProviderResponseStatus
|
||||||
|
message String @db.Text
|
||||||
|
sent_at DateTime? @db.Timestamp(0)
|
||||||
|
received_at DateTime? @db.Timestamp(0)
|
||||||
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
|
invoice_id String
|
||||||
|
provider_request_payload Json
|
||||||
|
raw_request_payload Json
|
||||||
|
error_message String? @db.Text
|
||||||
|
fiscal_warnings Json?
|
||||||
|
provider_response Json?
|
||||||
|
validation_errors Json?
|
||||||
|
invoice SalesInvoice @relation(fields: [invoice_id], references: [id], onDelete: Cascade)
|
||||||
|
|
||||||
|
@@unique([invoice_id, attempt_no])
|
||||||
|
@@index([status])
|
||||||
|
@@index([invoice_id])
|
||||||
|
@@map("sale_invoice_tsp_attempts")
|
||||||
|
}
|
||||||
|
|
||||||
model SalesInvoicePayment {
|
model SalesInvoicePayment {
|
||||||
id String @id @default(ulid())
|
id String @id @default(ulid())
|
||||||
invoice_id String
|
|
||||||
amount Decimal @db.Decimal(15, 2)
|
amount Decimal @db.Decimal(15, 2)
|
||||||
payment_method PaymentMethodType
|
payment_method PaymentMethodType
|
||||||
paid_at DateTime
|
paid_at DateTime @db.Timestamp(0)
|
||||||
created_at DateTime @default(now())
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
|
invoice_id String
|
||||||
|
terminal_info SalesInvoicePaymentTerminalInfo?
|
||||||
invoice SalesInvoice @relation(fields: [invoice_id], references: [id])
|
invoice SalesInvoice @relation(fields: [invoice_id], references: [id])
|
||||||
|
|
||||||
@@index([invoice_id])
|
@@index([invoice_id])
|
||||||
@@map("sales_invoice_payments")
|
@@map("sales_invoice_payments")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
model SalesInvoicePaymentTerminalInfo {
|
||||||
|
id String @id @default(ulid())
|
||||||
|
terminal_id String
|
||||||
|
stan String
|
||||||
|
rrn String
|
||||||
|
transaction_date_time DateTime
|
||||||
|
customer_card_no String?
|
||||||
|
description String?
|
||||||
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
|
payment_id String @unique
|
||||||
|
payment SalesInvoicePayment @relation(fields: [payment_id], references: [id])
|
||||||
|
|
||||||
|
@@unique([terminal_id, stan, rrn, payment_id])
|
||||||
|
@@map("sales_invoice_payment_terminal_info")
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,19 +2,18 @@ model Service {
|
|||||||
id String @id @default(ulid())
|
id String @id @default(ulid())
|
||||||
name String @db.VarChar(255)
|
name String @db.VarChar(255)
|
||||||
description String? @db.Text
|
description String? @db.Text
|
||||||
sku String @unique() @db.VarChar(100)
|
sku String @unique @db.VarChar(100)
|
||||||
local_sku String? @unique() @db.VarChar(100)
|
local_sku String? @unique @db.VarChar(100)
|
||||||
barcode String? @unique() @db.VarChar(100)
|
barcode String? @unique @db.VarChar(100)
|
||||||
created_at DateTime @default(now()) @db.Timestamp(0)
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
updated_at DateTime @updatedAt @db.Timestamp(0)
|
updated_at DateTime @updatedAt @db.Timestamp(0)
|
||||||
deleted_at DateTime? @db.Timestamp(0)
|
deleted_at DateTime? @db.Timestamp(0)
|
||||||
category_id String?
|
category_id String?
|
||||||
base_sale_price Decimal @default(0.00) @db.Decimal(15, 0)
|
base_sale_price Decimal @default(0) @db.Decimal(15, 0)
|
||||||
account_id String
|
account_id String
|
||||||
complex_id String
|
complex_id String
|
||||||
|
|
||||||
category ServiceCategory? @relation(fields: [category_id], references: [id])
|
|
||||||
sales_invoice_items SalesInvoiceItem[]
|
sales_invoice_items SalesInvoiceItem[]
|
||||||
|
category ServiceCategory? @relation(fields: [category_id], references: [id])
|
||||||
|
|
||||||
@@index([category_id])
|
@@index([category_id])
|
||||||
@@map("services")
|
@@map("services")
|
||||||
@@ -30,7 +29,6 @@ model ServiceCategory {
|
|||||||
created_at DateTime @default(now()) @db.Timestamp(0)
|
created_at DateTime @default(now()) @db.Timestamp(0)
|
||||||
updated_at DateTime @updatedAt @db.Timestamp(0)
|
updated_at DateTime @updatedAt @db.Timestamp(0)
|
||||||
deleted_at DateTime? @db.Timestamp(0)
|
deleted_at DateTime? @db.Timestamp(0)
|
||||||
|
|
||||||
services Service[]
|
services Service[]
|
||||||
|
|
||||||
@@map("service_categories")
|
@@map("service_categories")
|
||||||
|
|||||||
+454
-291
@@ -1,12 +1,15 @@
|
|||||||
import { PasswordUtil } from '@/common/utils/password.util'
|
import { PasswordUtil } from '@/common/utils/password.util'
|
||||||
import { generateTrackingCode } from '@/common/utils/tracking-code-generator.util'
|
import { GoodPricingModel } from '@/generated/prisma/enums'
|
||||||
import { GoodPricingModel, UnitType } from '@/generated/prisma/enums'
|
import { GoodCreateManyInput } from '@/generated/prisma/models'
|
||||||
import { GoodCreateInput, GoodCreateManyInput } from '@/generated/prisma/models'
|
import { PrismaClient } from '../src/generated/prisma/client'
|
||||||
import { prisma } from '../src/lib/prisma'
|
import { prismaAdapter } from '../src/lib/prisma'
|
||||||
|
|
||||||
|
const prisma = new PrismaClient({ adapter: prismaAdapter })
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const password = await PasswordUtil.hash('123456')
|
const password = await PasswordUtil.hash('123456')
|
||||||
const adminUser = await prisma.admin.upsert({
|
await prisma.$transaction(async tx => {
|
||||||
|
const adminUser = await tx.admin.upsert({
|
||||||
where: {
|
where: {
|
||||||
mobile_number: '09120258156',
|
mobile_number: '09120258156',
|
||||||
},
|
},
|
||||||
@@ -16,7 +19,7 @@ async function main() {
|
|||||||
last_name: 'حسنی',
|
last_name: 'حسنی',
|
||||||
national_code: '0016022289',
|
national_code: '0016022289',
|
||||||
mobile_number: '09120258156',
|
mobile_number: '09120258156',
|
||||||
adminAccounts: {
|
accounts: {
|
||||||
create: {
|
create: {
|
||||||
account: {
|
account: {
|
||||||
create: {
|
create: {
|
||||||
@@ -31,33 +34,128 @@ async function main() {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const measureUnits = await tx.measureUnits.createMany({
|
||||||
|
data: [
|
||||||
|
{ code: '1', name: 'لنگه' },
|
||||||
|
{ code: '2', name: 'ثوب' },
|
||||||
|
{ code: '3', name: 'عدل' },
|
||||||
|
{ code: '4', name: 'نیم دوجین' },
|
||||||
|
{ code: '5', name: 'جعبه' },
|
||||||
|
{ code: '6', name: 'قرقره' },
|
||||||
|
{ code: '7', name: 'توپ' },
|
||||||
|
{ code: '8', name: 'کیلوگرم' },
|
||||||
|
{ code: '9', name: 'ست' },
|
||||||
|
{ code: '10', name: 'بطری' },
|
||||||
|
{ code: '11', name: 'دست' },
|
||||||
|
{ code: '12', name: 'برگ' },
|
||||||
|
{ code: '13', name: 'کارتن' },
|
||||||
|
{ code: '14', name: 'سطل' },
|
||||||
|
{ code: '15', name: 'عدد' },
|
||||||
|
{ code: '16', name: 'ورق' },
|
||||||
|
{ code: '17', name: 'بسته' },
|
||||||
|
{ code: '18', name: 'شاخه' },
|
||||||
|
{ code: '19', name: 'پاکت' },
|
||||||
|
{ code: '20', name: 'قوطی' },
|
||||||
|
{ code: '21', name: 'دستگاه' },
|
||||||
|
{ code: '22', name: 'جلد' },
|
||||||
|
{ code: '23', name: 'تخته' },
|
||||||
|
{ code: '24', name: 'تیوب' },
|
||||||
|
{ code: '25', name: 'رول' },
|
||||||
|
{ code: '26', name: 'متر' },
|
||||||
|
{ code: '27', name: 'طاقه' },
|
||||||
|
{ code: '28', name: 'کلاف' },
|
||||||
|
{ code: '29', name: 'جفت' },
|
||||||
|
{ code: '30', name: 'کیسه' },
|
||||||
|
{ code: '31', name: 'متر مربع' },
|
||||||
|
{ code: '32', name: 'طغرا' },
|
||||||
|
{ code: '33', name: 'پالت' },
|
||||||
|
{ code: '34', name: 'بشکه' },
|
||||||
|
{ code: '35', name: 'دوجین' },
|
||||||
|
{ code: '36', name: 'گالن' },
|
||||||
|
{ code: '37', name: '(رینگ)حلقه' },
|
||||||
|
{ code: '38', name: 'فاقد بسته بندی' },
|
||||||
|
{ code: '39', name: 'قراص' },
|
||||||
|
{ code: '40', name: 'کارتن' },
|
||||||
|
{ code: '41', name: 'قراصه' },
|
||||||
|
{ code: '42', name: 'صفحه' },
|
||||||
|
{ code: '43', name: 'لیتر' },
|
||||||
|
{ code: '44', name: 'مخزن' },
|
||||||
|
{ code: '45', name: 'ساشه' },
|
||||||
|
{ code: '46', name: 'تانکر' },
|
||||||
|
{ code: '47', name: 'کپسول' },
|
||||||
|
{ code: '48', name: 'دبه' },
|
||||||
|
{ code: '49', name: 'بندیل' },
|
||||||
|
{ code: '50', name: 'سبد' },
|
||||||
|
{ code: '51', name: '(رول)حلقه' },
|
||||||
|
{ code: '52', name: 'تن' },
|
||||||
|
{ code: '53', name: 'قالب' },
|
||||||
|
{ code: '54', name: 'بانکه' },
|
||||||
|
{ code: '55', name: 'شانه' },
|
||||||
|
{ code: '56', name: 'سیلندر' },
|
||||||
|
{ code: '57', name: 'متر مکعب' },
|
||||||
|
{ code: '58', name: 'فوت مربع' },
|
||||||
|
{ code: '59', name: 'حلب' },
|
||||||
|
{ code: '60', name: 'شیت' },
|
||||||
|
{ code: '61', name: 'چلیک' },
|
||||||
|
{ code: '62', name: 'جام' },
|
||||||
|
{ code: '63', name: 'گرم' },
|
||||||
|
{ code: '64', name: 'نخ' },
|
||||||
|
{ code: '65', name: 'شعله' },
|
||||||
|
{ code: '66', name: 'قیراط' },
|
||||||
|
{ code: '67', name: 'میلی لیتر' },
|
||||||
|
{ code: '68', name: 'میلی متر' },
|
||||||
|
{ code: '69', name: 'میلی گرم' },
|
||||||
|
{ code: '70', name: 'ساعت' },
|
||||||
|
{ code: '71', name: 'روز' },
|
||||||
|
{ code: '72', name: 'تن کیلومتر' },
|
||||||
|
{ code: '73', name: 'کیلووات ساعت' },
|
||||||
|
{ code: '74', name: 'نفر' },
|
||||||
|
{ code: '75', name: 'ثانیه' },
|
||||||
|
{ code: '76', name: 'دقیقه' },
|
||||||
|
{ code: '77', name: 'ماه' },
|
||||||
|
{ code: '78', name: 'سال' },
|
||||||
|
{ code: '79', name: 'قطعه' },
|
||||||
|
{ code: '80', name: 'سانتی متر' },
|
||||||
|
{ code: '81', name: 'سانتی متر مربع' },
|
||||||
|
{ code: '82', name: 'فروند' },
|
||||||
|
{ code: '83', name: 'واحد' },
|
||||||
|
{ code: '84', name: 'لیوان' },
|
||||||
|
{ code: '85', name: 'نوبت)`,' },
|
||||||
|
],
|
||||||
|
skipDuplicates: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
const geramMeasureUnit = await tx.measureUnits.findFirst({
|
||||||
|
where: {
|
||||||
|
code: '63',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
// ****************** GUILD Start ****************** //
|
// ****************** GUILD Start ****************** //
|
||||||
const guilds = await prisma.guild.findMany()
|
let guilds = await tx.guild.findMany()
|
||||||
if (!guilds.length) {
|
if (!guilds.length) {
|
||||||
await prisma.guild.createMany({
|
await tx.guild.createMany({
|
||||||
data: [
|
data: [
|
||||||
{
|
{
|
||||||
name: 'طلا',
|
name: 'طلا',
|
||||||
code: 'Gold',
|
code: 'Gold',
|
||||||
},
|
invoice_template: 'GOLD_JEWELRY',
|
||||||
{
|
|
||||||
name: 'میوه و ترهبار',
|
|
||||||
code: 'Fruit',
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
guilds = await tx.guild.findMany()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ****************** GUILD Good Categories Start ****************** //
|
// ****************** GUILD Good Categories Start ****************** //
|
||||||
|
|
||||||
const goldGuild = await prisma.guild.findFirst({
|
const goldGuild = await tx.guild.findFirst({
|
||||||
where: {
|
where: {
|
||||||
name: 'طلا',
|
code: 'Gold',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const goldGuildId = goldGuild?.id
|
const goldGuildId = goldGuild?.id
|
||||||
const goldGuildGoodCategories = await prisma.goodCategory.findMany({
|
const goldGuildGoodCategories = await tx.goodCategory.findMany({
|
||||||
where: {
|
where: {
|
||||||
guild_id: goldGuildId,
|
guild_id: goldGuildId,
|
||||||
is_default_guild_good: true,
|
is_default_guild_good: true,
|
||||||
@@ -71,40 +169,59 @@ async function main() {
|
|||||||
is_default_guild_good: true,
|
is_default_guild_good: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
await prisma.goodCategory.createMany({
|
await tx.goodCategory.createMany({
|
||||||
data: [
|
data: [
|
||||||
categoryFactory('زیورآلات'),
|
categoryFactory('زیورآلات'),
|
||||||
categoryFactory('طلا'),
|
// categoryFactory('طلا'),
|
||||||
categoryFactory('سایر'),
|
// categoryFactory('سایر'),
|
||||||
categoryFactory('سکه'),
|
// categoryFactory('سکه'),
|
||||||
categoryFactory('شمش'),
|
// categoryFactory('شمش'),
|
||||||
categoryFactory('شمش'),
|
// categoryFactory('شمش'),
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const measureUnit = await tx.measureUnits.findFirst({
|
||||||
|
where: {
|
||||||
|
code: '63',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if (measureUnit) {
|
||||||
// ****************** GUILD Good Start ****************** //
|
// ****************** GUILD Good Start ****************** //
|
||||||
const goodFactory = (
|
async function goodFactory(
|
||||||
name: string,
|
name: string,
|
||||||
categoryId: string,
|
categoryId: string,
|
||||||
pricingModel: GoodPricingModel,
|
pricingModel: GoodPricingModel,
|
||||||
unitType: UnitType,
|
sku_code: string,
|
||||||
): GoodCreateManyInput => ({
|
measure_unit_code: string,
|
||||||
|
): Promise<GoodCreateManyInput | null> {
|
||||||
|
const sku = await tx.stockKeepingUnits.findUnique({
|
||||||
|
where: {
|
||||||
|
code: sku_code,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if (sku) {
|
||||||
|
return {
|
||||||
name,
|
name,
|
||||||
category_id: categoryId,
|
category_id: categoryId,
|
||||||
pricing_model: pricingModel,
|
pricing_model: pricingModel,
|
||||||
sku: '',
|
sku_id: sku.id,
|
||||||
unit_type: unitType,
|
measure_unit_id: measureUnit!.id,
|
||||||
is_default_guild_good: true,
|
is_default_guild_good: true,
|
||||||
})
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
const zivarCategory = await prisma.goodCategory.findFirst({
|
const zivarCategory = await tx.goodCategory.findFirst({
|
||||||
where: {
|
where: {
|
||||||
name: 'زیورآلات',
|
name: 'زیورآلات',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
if (zivarCategory) {
|
if (zivarCategory) {
|
||||||
const zivarGoods = await prisma.good.count({
|
const zivarGoods = await tx.good.count({
|
||||||
where: {
|
where: {
|
||||||
category_id: zivarCategory?.id,
|
category_id: zivarCategory?.id,
|
||||||
},
|
},
|
||||||
@@ -112,311 +229,356 @@ async function main() {
|
|||||||
if (!zivarGoods) {
|
if (!zivarGoods) {
|
||||||
const goodItems: GoodCreateManyInput[] = []
|
const goodItems: GoodCreateManyInput[] = []
|
||||||
|
|
||||||
goodItems.push(
|
const preparedGoodItems = [
|
||||||
...[
|
await goodFactory(
|
||||||
goodFactory(
|
|
||||||
'آویز گردنبند طلا',
|
'آویز گردنبند طلا',
|
||||||
zivarCategory.id,
|
zivarCategory.id,
|
||||||
GoodPricingModel.GOLD,
|
GoodPricingModel.GOLD,
|
||||||
UnitType.GRAM,
|
'2720000044696',
|
||||||
|
geramMeasureUnit!.id,
|
||||||
),
|
),
|
||||||
goodFactory('النگو', zivarCategory.id, GoodPricingModel.GOLD, UnitType.GRAM),
|
await goodFactory(
|
||||||
goodFactory('انگشتر', zivarCategory.id, GoodPricingModel.GOLD, UnitType.GRAM),
|
'النگو',
|
||||||
goodFactory('دستبند', zivarCategory.id, GoodPricingModel.GOLD, UnitType.GRAM),
|
zivarCategory.id,
|
||||||
goodFactory('زنجیر', zivarCategory.id, GoodPricingModel.GOLD, UnitType.GRAM),
|
|
||||||
goodFactory('سرویس', zivarCategory.id, GoodPricingModel.GOLD, UnitType.GRAM),
|
|
||||||
goodFactory('گوشواره', zivarCategory.id, GoodPricingModel.GOLD, UnitType.GRAM),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
await prisma.good.createMany({ data: goodItems })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const goldCategory = await prisma.goodCategory.findFirst({
|
|
||||||
where: {
|
|
||||||
name: 'طلا',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
if (goldCategory) {
|
|
||||||
const goldGoods = await prisma.good.count({
|
|
||||||
where: {
|
|
||||||
category_id: goldCategory?.id,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
if (!goldGoods) {
|
|
||||||
const goodItems: GoodCreateInput[] = []
|
|
||||||
goodItems.push(
|
|
||||||
...[
|
|
||||||
goodFactory(
|
|
||||||
'طلای آب شده',
|
|
||||||
goldCategory.id,
|
|
||||||
GoodPricingModel.GOLD,
|
GoodPricingModel.GOLD,
|
||||||
UnitType.GRAM,
|
'2720000044665',
|
||||||
|
geramMeasureUnit!.id,
|
||||||
),
|
),
|
||||||
goodFactory(
|
await goodFactory(
|
||||||
'طلای شکسته',
|
'انگشتر',
|
||||||
goldCategory.id,
|
zivarCategory.id,
|
||||||
GoodPricingModel.GOLD,
|
GoodPricingModel.GOLD,
|
||||||
UnitType.GRAM,
|
'2720000044672',
|
||||||
|
geramMeasureUnit!.id,
|
||||||
),
|
),
|
||||||
goodFactory(
|
await goodFactory(
|
||||||
'طلای مستعمل',
|
'دستبند',
|
||||||
goldCategory.id,
|
zivarCategory.id,
|
||||||
GoodPricingModel.GOLD,
|
GoodPricingModel.GOLD,
|
||||||
UnitType.GRAM,
|
'2720000044689',
|
||||||
|
geramMeasureUnit!.id,
|
||||||
),
|
),
|
||||||
],
|
await goodFactory(
|
||||||
)
|
'زنجیر',
|
||||||
await prisma.good.createMany({ data: goodItems })
|
zivarCategory.id,
|
||||||
|
GoodPricingModel.GOLD,
|
||||||
|
'2720000044702',
|
||||||
|
geramMeasureUnit!.id,
|
||||||
|
),
|
||||||
|
await goodFactory(
|
||||||
|
'سرویس',
|
||||||
|
zivarCategory.id,
|
||||||
|
GoodPricingModel.GOLD,
|
||||||
|
'2720000044733',
|
||||||
|
geramMeasureUnit!.id,
|
||||||
|
),
|
||||||
|
await goodFactory(
|
||||||
|
'گوشواره',
|
||||||
|
zivarCategory.id,
|
||||||
|
GoodPricingModel.GOLD,
|
||||||
|
'2720000044726',
|
||||||
|
geramMeasureUnit!.id,
|
||||||
|
),
|
||||||
|
].filter((item): item is GoodCreateManyInput => item !== null)
|
||||||
|
goodItems.push(...preparedGoodItems)
|
||||||
|
|
||||||
|
await tx.good.createMany({ data: goodItems })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const coinCategory = await prisma.goodCategory.findFirst({
|
// const goldCategory = await tx.goodCategory.findFirst({
|
||||||
where: {
|
// where: {
|
||||||
name: 'سکه',
|
// name: 'طلا',
|
||||||
},
|
// },
|
||||||
})
|
// })
|
||||||
if (coinCategory) {
|
// if (goldCategory) {
|
||||||
const coinGoods = await prisma.good.count({
|
// const goldGoods = await tx.good.count({
|
||||||
where: {
|
// where: {
|
||||||
category_id: coinCategory?.id,
|
// category_id: goldCategory?.id,
|
||||||
},
|
// },
|
||||||
})
|
// })
|
||||||
if (!coinGoods) {
|
// if (!goldGoods) {
|
||||||
const goodItems: GoodCreateInput[] = []
|
// const goodItems: GoodCreateInput[] = []
|
||||||
goodItems.push(
|
// goodItems.push(
|
||||||
...[
|
// ...[
|
||||||
goodFactory(
|
// goodFactory(
|
||||||
'مسکوکات خارجی',
|
// 'طلای آب شده',
|
||||||
coinCategory.id,
|
// goldCategory.id,
|
||||||
GoodPricingModel.STANDARD,
|
// GoodPricingModel.GOLD,
|
||||||
UnitType.COUNT,
|
// UnitType.GRAM,
|
||||||
),
|
// ),
|
||||||
goodFactory(
|
// goodFactory(
|
||||||
'مسکوکات داخلی (پارسیان)',
|
// 'طلای شکسته',
|
||||||
coinCategory.id,
|
// goldCategory.id,
|
||||||
GoodPricingModel.STANDARD,
|
// GoodPricingModel.GOLD,
|
||||||
UnitType.COUNT,
|
// UnitType.GRAM,
|
||||||
),
|
// ),
|
||||||
goodFactory(
|
// goodFactory(
|
||||||
'تمام بهار آزادی (طرح جدید)',
|
// 'طلای مستعمل',
|
||||||
coinCategory.id,
|
// goldCategory.id,
|
||||||
GoodPricingModel.STANDARD,
|
// GoodPricingModel.GOLD,
|
||||||
UnitType.COUNT,
|
// UnitType.GRAM,
|
||||||
),
|
// ),
|
||||||
goodFactory(
|
// ],
|
||||||
'تمام بهار آزادی (طرح قدیم)',
|
// )
|
||||||
coinCategory.id,
|
// await tx.good.createMany({ data: goodItems })
|
||||||
GoodPricingModel.STANDARD,
|
// }
|
||||||
UnitType.COUNT,
|
// }
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
await prisma.good.createMany({ data: goodItems })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const shemshCategory = await prisma.goodCategory.findFirst({
|
// const coinCategory = await tx.goodCategory.findFirst({
|
||||||
where: {
|
// where: {
|
||||||
name: 'شمش',
|
// name: 'سکه',
|
||||||
},
|
// },
|
||||||
})
|
// })
|
||||||
|
// if (coinCategory) {
|
||||||
|
// const coinGoods = await tx.good.count({
|
||||||
|
// where: {
|
||||||
|
// category_id: coinCategory?.id,
|
||||||
|
// },
|
||||||
|
// })
|
||||||
|
// if (!coinGoods) {
|
||||||
|
// const goodItems: GoodCreateInput[] = []
|
||||||
|
// goodItems.push(
|
||||||
|
// ...[
|
||||||
|
// goodFactory(
|
||||||
|
// 'مسکوکات خارجی',
|
||||||
|
// coinCategory.id,
|
||||||
|
// GoodPricingModel.STANDARD,
|
||||||
|
// UnitType.COUNT,
|
||||||
|
// ),
|
||||||
|
// goodFactory(
|
||||||
|
// 'مسکوکات داخلی (پارسیان)',
|
||||||
|
// coinCategory.id,
|
||||||
|
// GoodPricingModel.STANDARD,
|
||||||
|
// UnitType.COUNT,
|
||||||
|
// ),
|
||||||
|
// goodFactory(
|
||||||
|
// 'تمام بهار آزادی (طرح جدید)',
|
||||||
|
// coinCategory.id,
|
||||||
|
// GoodPricingModel.STANDARD,
|
||||||
|
// UnitType.COUNT,
|
||||||
|
// ),
|
||||||
|
// goodFactory(
|
||||||
|
// 'تمام بهار آزادی (طرح قدیم)',
|
||||||
|
// coinCategory.id,
|
||||||
|
// GoodPricingModel.STANDARD,
|
||||||
|
// UnitType.COUNT,
|
||||||
|
// ),
|
||||||
|
// ],
|
||||||
|
// )
|
||||||
|
// await tx.good.createMany({ data: goodItems })
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
if (shemshCategory) {
|
// const shemshCategory = await tx.goodCategory.findFirst({
|
||||||
const shemshGoods = await prisma.good.count({
|
// where: {
|
||||||
where: {
|
// name: 'شمش',
|
||||||
category_id: shemshCategory?.id,
|
// },
|
||||||
},
|
// })
|
||||||
})
|
|
||||||
if (!shemshGoods) {
|
// if (shemshCategory) {
|
||||||
await prisma.good.create({
|
// const shemshGoods = await tx.good.count({
|
||||||
data: goodFactory(
|
// where: {
|
||||||
'شمش استاندارد',
|
// category_id: shemshCategory?.id,
|
||||||
shemshCategory.id,
|
// },
|
||||||
GoodPricingModel.GOLD,
|
// })
|
||||||
UnitType.GRAM,
|
// if (!shemshGoods) {
|
||||||
),
|
// await tx.good.create({
|
||||||
})
|
// data: goodFactory(
|
||||||
}
|
// 'شمش استاندارد',
|
||||||
|
// shemshCategory.id,
|
||||||
|
// GoodPricingModel.GOLD,
|
||||||
|
// UnitType.GRAM,
|
||||||
|
// ),
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
// ****************** partner Start ****************** //
|
// ****************** partner Start ****************** //
|
||||||
let partner = await prisma.partner.findFirst()
|
// let partner = await tx.partner.findFirst()
|
||||||
let license = await prisma.license.findFirst()
|
// let license = await tx.license.findFirst()
|
||||||
if (!partner) {
|
// if (!partner) {
|
||||||
partner = await prisma.partner.create({
|
// partner = await tx.partner.create({
|
||||||
data: {
|
// data: {
|
||||||
name: 'تیس',
|
// name: 'تیس',
|
||||||
code: 'TIS',
|
// code: 'TIS',
|
||||||
status: 'ACTIVE',
|
// status: 'ACTIVE',
|
||||||
partner_accounts: {
|
// tsp_provider: TspProviderType.NAMA,
|
||||||
create: {
|
// accounts: {
|
||||||
role: 'OWNER',
|
// create: {
|
||||||
account: {
|
// role: 'OWNER',
|
||||||
create: {
|
// account: {
|
||||||
username: 'tis',
|
// create: {
|
||||||
password: await PasswordUtil.hash('123456'),
|
// username: 'tis',
|
||||||
status: 'ACTIVE',
|
// password: await PasswordUtil.hash('123456'),
|
||||||
type: 'PARTNER',
|
// status: 'ACTIVE',
|
||||||
},
|
// type: 'PARTNER',
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
})
|
// },
|
||||||
}
|
// })
|
||||||
if (partner && !license) {
|
// }
|
||||||
await prisma.$transaction(async tx => {
|
// if (partner && !license) {
|
||||||
const startOfToday = new Date()
|
// await tx.$transaction(async tx => {
|
||||||
startOfToday.setHours(0, 0, 0, 0)
|
// const startOfToday = new Date()
|
||||||
|
// startOfToday.setHours(0, 0, 0, 0)
|
||||||
|
|
||||||
const month = startOfToday.getMonth()
|
// const month = startOfToday.getMonth()
|
||||||
let year = startOfToday.getFullYear()
|
// let year = startOfToday.getFullYear()
|
||||||
let expMonth = month + 3
|
// let expMonth = month + 3
|
||||||
if (expMonth > 11) {
|
|
||||||
expMonth = expMonth - 11
|
|
||||||
year = year + 1
|
|
||||||
}
|
|
||||||
|
|
||||||
startOfToday.setFullYear(year)
|
|
||||||
startOfToday.setMonth(expMonth)
|
|
||||||
|
|
||||||
const transaction = await tx.licenseChargeTransaction.create({
|
|
||||||
data: {
|
|
||||||
activation_expires_at: startOfToday,
|
|
||||||
purchased_count: 1,
|
|
||||||
tracking_code: generateTrackingCode('LIC', 6),
|
|
||||||
partner: {
|
|
||||||
connect: {
|
|
||||||
id: partner.id,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
if (transaction)
|
|
||||||
license = await tx.license.create({
|
|
||||||
data: {
|
|
||||||
charge_transaction: {
|
|
||||||
connect: {
|
|
||||||
id: transaction.id,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// ****************** BA Start ****************** //
|
|
||||||
const ba = await prisma.businessActivity.count()
|
|
||||||
|
|
||||||
if (!ba && license) {
|
|
||||||
const startOfToday = new Date()
|
|
||||||
startOfToday.setHours(0, 0, 0, 0)
|
|
||||||
|
|
||||||
let year = startOfToday.getFullYear()
|
|
||||||
let expYear = year + 1
|
|
||||||
// if (expMonth > 11) {
|
// if (expMonth > 11) {
|
||||||
// expMonth = expMonth - 11
|
// expMonth = expMonth - 11
|
||||||
// year = year + 1
|
// year = year + 1
|
||||||
// }
|
// }
|
||||||
|
|
||||||
startOfToday.setFullYear(expYear)
|
// startOfToday.setFullYear(year)
|
||||||
|
// startOfToday.setMonth(expMonth)
|
||||||
await prisma.businessActivity.create({
|
|
||||||
data: {
|
|
||||||
name: 'طلا فروشی',
|
|
||||||
economic_code: '0111111111',
|
|
||||||
license_activation: {
|
|
||||||
create: {
|
|
||||||
expires_at: startOfToday,
|
|
||||||
starts_at: new Date(),
|
|
||||||
license: {
|
|
||||||
connect: {
|
|
||||||
id: license.id,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
consumer: {
|
|
||||||
create: {
|
|
||||||
first_name: 'محمد',
|
|
||||||
last_name: 'زرگر',
|
|
||||||
mobile_number: '09120258155',
|
|
||||||
national_code: '1234567890',
|
|
||||||
consumer_accounts: {
|
|
||||||
create: {
|
|
||||||
role: 'OWNER',
|
|
||||||
account: {
|
|
||||||
create: {
|
|
||||||
username: 'zargar',
|
|
||||||
password: await PasswordUtil.hash('123456'),
|
|
||||||
status: 'ACTIVE',
|
|
||||||
type: 'CONSUMER',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
partner: {
|
|
||||||
connect: {
|
|
||||||
id: partner.id,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
guild: {
|
|
||||||
connect: {
|
|
||||||
id: guilds[0].id,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
complexes: {
|
|
||||||
create: {
|
|
||||||
name: 'فروشگاه طلای مرکزی',
|
|
||||||
address: 'تهران، خیابان جمهوری',
|
|
||||||
branch_code: '12332',
|
|
||||||
|
|
||||||
// pos_list: {
|
|
||||||
// create: {
|
|
||||||
// name: 'لاین ۱',
|
|
||||||
// pos_type: POSType.WEB,
|
|
||||||
// status: 'ACTIVE',
|
|
||||||
// account: {
|
|
||||||
// create: {
|
|
||||||
// role: 'OPERATOR',
|
|
||||||
// account_allocation: {
|
|
||||||
|
|
||||||
|
// const transaction = await tx.licenseChargeTransaction.create({
|
||||||
|
// data: {
|
||||||
|
// activation_expires_at: startOfToday,
|
||||||
|
// purchased_count: 1,
|
||||||
|
// tracking_code: generateTrackingCode('LIC', 6),
|
||||||
|
// partner: {
|
||||||
|
// connect: {
|
||||||
|
// id: partner.id,
|
||||||
// },
|
// },
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// select: {
|
||||||
|
// id: true,
|
||||||
|
// },
|
||||||
|
// })
|
||||||
|
// if (transaction)
|
||||||
|
// license = await tx.license.create({
|
||||||
|
// data: {
|
||||||
|
// charge_transaction: {
|
||||||
|
// connect: {
|
||||||
|
// id: transaction.id,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // ****************** BA Start ****************** //
|
||||||
|
// const ba = await tx.businessActivity.count()
|
||||||
|
|
||||||
|
// if (!ba && license) {
|
||||||
|
// const startOfToday = new Date()
|
||||||
|
// startOfToday.setHours(0, 0, 0, 0)
|
||||||
|
|
||||||
|
// let year = startOfToday.getFullYear()
|
||||||
|
// let expYear = year + 1
|
||||||
|
// // if (expMonth > 11) {
|
||||||
|
// // expMonth = expMonth - 11
|
||||||
|
// // year = year + 1
|
||||||
|
// // }
|
||||||
|
|
||||||
|
// startOfToday.setFullYear(expYear)
|
||||||
|
|
||||||
|
// await tx.businessActivity.create({
|
||||||
|
// data: {
|
||||||
|
// name: 'طلا فروشی',
|
||||||
|
// economic_code: '0111111111',
|
||||||
|
// fiscal_id: '0111111111',
|
||||||
|
// partner_token: 'TIS-BA-001',
|
||||||
|
// license_activation: {
|
||||||
|
// create: {
|
||||||
|
// expires_at: startOfToday,
|
||||||
|
// starts_at: new Date(),
|
||||||
|
// license: {
|
||||||
|
// connect: {
|
||||||
|
// id: license.id,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// consumer: {
|
||||||
|
// create: {
|
||||||
|
// type: ConsumerType.INDIVIDUAL,
|
||||||
|
// individual: {
|
||||||
|
// create: {
|
||||||
|
// first_name: 'محمد',
|
||||||
|
// last_name: 'زرگر',
|
||||||
|
// mobile_number: '09120258155',
|
||||||
|
// national_code: '1234567890',
|
||||||
|
// partner: {
|
||||||
|
// connect: {
|
||||||
|
// id: partner.id,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// accounts: {
|
||||||
|
// create: {
|
||||||
|
// role: 'OWNER',
|
||||||
// account: {
|
// account: {
|
||||||
// create: {
|
// create: {
|
||||||
// username: 'line1',
|
// username: 'zargar',
|
||||||
// password: await PasswordUtil.hash('123456'),
|
// password: await PasswordUtil.hash('123456'),
|
||||||
// status: 'ACTIVE',
|
// status: 'ACTIVE',
|
||||||
// type: 'CONSUMER',
|
// type: 'CONSUMER',
|
||||||
// },
|
// },
|
||||||
// },
|
// },
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// },
|
// },
|
||||||
// },
|
// },
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
},
|
// guild: {
|
||||||
})
|
// connect: {
|
||||||
}
|
// id: guilds[0].id,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// complexes: {
|
||||||
|
// create: {
|
||||||
|
// name: 'فروشگاه طلای مرکزی',
|
||||||
|
// address: 'تهران، خیابان جمهوری',
|
||||||
|
// branch_code: '12332',
|
||||||
|
|
||||||
|
// // pos_list: {
|
||||||
|
// // create: {
|
||||||
|
// // name: 'لاین ۱',
|
||||||
|
// // pos_type: POSType.WEB,
|
||||||
|
// // status: 'ACTIVE',
|
||||||
|
// // account: {
|
||||||
|
// // create: {
|
||||||
|
// // role: 'OPERATOR',
|
||||||
|
// // account_allocation: {
|
||||||
|
|
||||||
|
// // },
|
||||||
|
// // account: {
|
||||||
|
// // create: {
|
||||||
|
// // username: 'line1',
|
||||||
|
// // password: await PasswordUtil.hash('123456'),
|
||||||
|
// // status: 'ACTIVE',
|
||||||
|
// // type: 'CONSUMER',
|
||||||
|
// // },
|
||||||
|
// // },
|
||||||
|
// // }
|
||||||
|
// // }
|
||||||
|
// // },
|
||||||
|
// // },
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// })
|
||||||
|
// }
|
||||||
// ****************** BA Start ****************** //
|
// ****************** BA Start ****************** //
|
||||||
|
|
||||||
// ****************** provider Start ****************** //
|
// ****************** provider Start ****************** //
|
||||||
const provider = await prisma.provider.count()
|
const provider = await tx.provider.count()
|
||||||
if (!provider) {
|
if (!provider) {
|
||||||
await prisma.provider.create({
|
await tx.provider.create({
|
||||||
data: {
|
data: {
|
||||||
name: 'توسن',
|
name: 'توسن',
|
||||||
code: 'Tosan',
|
code: 'Tosan',
|
||||||
status: 'ACTIVE',
|
status: 'ACTIVE',
|
||||||
provider_accounts: {
|
accounts: {
|
||||||
create: {
|
create: {
|
||||||
role: 'OWNER',
|
role: 'OWNER',
|
||||||
account: {
|
account: {
|
||||||
@@ -432,6 +594,7 @@ async function main() {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
main()
|
main()
|
||||||
|
|||||||
@@ -1,548 +0,0 @@
|
|||||||
-- AUTO-GENERATED MYSQL TRIGGER DUMP
|
|
||||||
-- Generated at: 2026-01-06T16:09:38.959Z
|
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- index: 1
|
|
||||||
-- Trigger: trg_bank_account_transaction_after_delete
|
|
||||||
-- Event: DELETE
|
|
||||||
-- Table: Bank_Account_Transactions
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_bank_account_transaction_after_delete`;
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_bank_account_transaction_after_delete` AFTER DELETE ON `Bank_Account_Transactions` FOR EACH ROW BEGIN
|
|
||||||
UPDATE `Bank_Account_Balance` SET balance = balance - OLD.amount WHERE `bankAccountId` = OLD.bankAccountId;
|
|
||||||
END;
|
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- index: 2
|
|
||||||
-- Trigger: trg_transfer_item_after_insert
|
|
||||||
-- Event: INSERT
|
|
||||||
-- Table: Inventory_Transfer_Items
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_transfer_item_after_insert`;
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_transfer_item_after_insert` AFTER INSERT ON `Inventory_Transfer_Items` FOR EACH ROW begin
|
|
||||||
|
|
||||||
DECLARE fromInv INT;
|
|
||||||
DECLARE toInv INT;
|
|
||||||
DECLARE _avgCost DECIMAL(10,2);
|
|
||||||
DECLARE latestQuantityInOrigin DECIMAL(10,2);
|
|
||||||
DECLARE latestQuantityInDestination DECIMAL(10,2);
|
|
||||||
|
|
||||||
SELECT fromInventoryId, toInventoryId INTO fromInv, toInv
|
|
||||||
FROM Inventory_Transfers WHERE id = NEW.transferId;
|
|
||||||
|
|
||||||
SELECT COALESCE(avgCost, 0), COALESCE(quantity, 0) INTO _avgCost, latestQuantityInOrigin FROM Stock_Balance
|
|
||||||
WHERE ProductId = NEW.productId AND inventoryId = fromInv LIMIT 1;
|
|
||||||
|
|
||||||
SELECT COALESCE(quantity, 0) INTO latestQuantityInDestination FROM Stock_Balance
|
|
||||||
WHERE ProductId = NEW.productId AND inventoryId = toInv LIMIT 1;
|
|
||||||
|
|
||||||
|
|
||||||
-- OUT from source
|
|
||||||
INSERT INTO Stock_Movements
|
|
||||||
(type, quantity, unitPrice, totalCost, avgCost, referenceType, referenceId, productId, inventoryId, counterInventoryId, createdAt, remainedInStock)
|
|
||||||
VALUES
|
|
||||||
('OUT', NEW.count, _avgCost, _avgCost*NEW.count, _avgCost, 'INVENTORY_TRANSFER', NEW.transferId, NEW.productId, fromInv, toInv, NOW(), latestQuantityInOrigin-NEW.count);
|
|
||||||
|
|
||||||
-- IN to destination
|
|
||||||
INSERT INTO Stock_Movements
|
|
||||||
(type, quantity, unitPrice, totalCost, avgCost, referenceType, referenceId, productId, inventoryId, counterInventoryId, createdAt, remainedInStock)
|
|
||||||
VALUES
|
|
||||||
('IN', NEW.count,_avgCost, _avgCost*NEW.count,_avgCost, 'INVENTORY_TRANSFER', NEW.transferId, NEW.productId, toInv, fromInv, NOW(), latestQuantityInOrigin-NEW.count);
|
|
||||||
end;
|
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- index: 3
|
|
||||||
-- Trigger: trg_order_item_after_update
|
|
||||||
-- Event: UPDATE
|
|
||||||
-- Table: Order_Items
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_order_item_after_update`;
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_order_item_after_update` AFTER UPDATE ON `Order_Items` FOR EACH ROW BEGIN
|
|
||||||
|
|
||||||
UPDATE Stock_Reservations
|
|
||||||
SET quantity = quantity - OLD.quantity + NEW.quantity
|
|
||||||
WHERE orderId = NEW.orderId AND productId = NEW.productId;
|
|
||||||
|
|
||||||
END;
|
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- index: 4
|
|
||||||
-- Trigger: trg_order_item_after_delete
|
|
||||||
-- Event: DELETE
|
|
||||||
-- Table: Order_Items
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_order_item_after_delete`;
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_order_item_after_delete` AFTER DELETE ON `Order_Items` FOR EACH ROW BEGIN
|
|
||||||
|
|
||||||
DELETE From Stock_Reservations
|
|
||||||
WHERE orderId = OLD.orderId AND productId = OLD.productId;
|
|
||||||
|
|
||||||
END;
|
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- index: 5
|
|
||||||
-- Trigger: trg_order_after_cancel
|
|
||||||
-- Event: UPDATE
|
|
||||||
-- Table: Orders
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_order_after_cancel`;
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_order_after_cancel` AFTER UPDATE ON `Orders` FOR EACH ROW BEGIN
|
|
||||||
IF NEW.status = 'CANCELED' OR NEW.status = 'REJECTED' OR NEW.status = 'DONE' THEN
|
|
||||||
UPDATE Stock_Reservations sr SET quantity = 0
|
|
||||||
WHERE sr.orderId = NEW.id;
|
|
||||||
END IF;
|
|
||||||
END;
|
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- index: 6
|
|
||||||
-- Trigger: trg_purchase_receipt_item_after_insert
|
|
||||||
-- Event: INSERT
|
|
||||||
-- Table: Purchase_Receipt_Items
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_purchase_receipt_item_after_insert`;
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_purchase_receipt_item_after_insert` AFTER INSERT ON `Purchase_Receipt_Items` FOR EACH ROW BEGIN DECLARE latestQuantity DECIMAL(10, 2) DEFAULT 0;
|
|
||||||
|
|
||||||
DECLARE invId INT;
|
|
||||||
DECLARE suppId INT;
|
|
||||||
|
|
||||||
-- Get inventory & supplier from
|
|
||||||
SELECT inventoryId, supplierId
|
|
||||||
INTO invId, suppId
|
|
||||||
FROM Purchase_Receipts
|
|
||||||
WHERE id = NEW.receiptId;
|
|
||||||
|
|
||||||
-- Get current stock quantity (if exists)
|
|
||||||
SELECT COALESCE(quantity, 0)
|
|
||||||
INTO latestQuantity
|
|
||||||
FROM Stock_Balance sb
|
|
||||||
WHERE sb.inventoryId = invId
|
|
||||||
AND sb.productId = NEW.productId
|
|
||||||
LIMIT 1;
|
|
||||||
|
|
||||||
-- Insert stock movement
|
|
||||||
INSERT INTO Stock_Movements (
|
|
||||||
type,
|
|
||||||
quantity,
|
|
||||||
unitPrice,
|
|
||||||
totalCost,
|
|
||||||
referenceType,
|
|
||||||
referenceId,
|
|
||||||
productId,
|
|
||||||
inventoryId,
|
|
||||||
avgCost,
|
|
||||||
supplierId,
|
|
||||||
remainedInStock,
|
|
||||||
createdAt
|
|
||||||
)
|
|
||||||
VALUES (
|
|
||||||
'IN',
|
|
||||||
NEW.count,
|
|
||||||
NEW.unitPrice,
|
|
||||||
NEW.totalAmount,
|
|
||||||
'PURCHASE',
|
|
||||||
NEW.receiptId,
|
|
||||||
NEW.productId,
|
|
||||||
invId,
|
|
||||||
CASE
|
|
||||||
WHEN NEW.count = 0 THEN 0
|
|
||||||
ELSE NEW.totalAmount / NEW.count
|
|
||||||
END
|
|
||||||
|
|
||||||
,
|
|
||||||
suppId,
|
|
||||||
latestQuantity + NEW.count,
|
|
||||||
NOW()
|
|
||||||
);
|
|
||||||
|
|
||||||
END;
|
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- index: 7
|
|
||||||
-- Trigger: trg_pr_payment_after_delete
|
|
||||||
-- Event: DELETE
|
|
||||||
-- Table: Purchase_Receipt_Payments
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_pr_payment_after_delete`;
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_pr_payment_after_delete` AFTER DELETE ON `Purchase_Receipt_Payments` FOR EACH ROW BEGIN
|
|
||||||
DECLARE receiptTotal DECIMAL(14,2);
|
|
||||||
DECLARE newPaid DECIMAL(14,2);
|
|
||||||
|
|
||||||
SELECT totalAmount, paidAmount
|
|
||||||
INTO receiptTotal, newPaid
|
|
||||||
FROM Purchase_Receipts
|
|
||||||
WHERE id = OLD.receiptId
|
|
||||||
FOR UPDATE;
|
|
||||||
|
|
||||||
IF OLD.type = 'PAYMENT' THEN
|
|
||||||
SET newPaid = newPaid - OLD.amount;
|
|
||||||
ELSE
|
|
||||||
SET newPaid = newPaid + OLD.amount;
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
UPDATE Purchase_Receipts
|
|
||||||
SET
|
|
||||||
paidAmount = newPaid,
|
|
||||||
status =
|
|
||||||
CASE
|
|
||||||
WHEN newPaid = 0 THEN 'UNPAID'
|
|
||||||
WHEN newPaid < receiptTotal THEN 'PARTIALLY_PAID'
|
|
||||||
ELSE 'PAID'
|
|
||||||
END
|
|
||||||
WHERE id = OLD.receiptId;
|
|
||||||
END;
|
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- index: 8
|
|
||||||
-- Trigger: trg_sales_invoice_items_before_insert
|
|
||||||
-- Event: INSERT
|
|
||||||
-- Table: Sales_Invoice_Items
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_sales_invoice_items_before_insert`;
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_sales_invoice_items_before_insert` BEFORE INSERT ON `Sales_Invoice_Items` FOR EACH ROW BEGIN
|
|
||||||
|
|
||||||
DECLARE current_stock DECIMAL(10, 2);
|
|
||||||
DECLARE inventory_id INT;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SELECT pa.inventoryId INTO inventory_id
|
|
||||||
FROM Pos_Accounts pa
|
|
||||||
INNER JOIN Sales_Invoices si ON pa.id = si.posAccountId
|
|
||||||
WHERE si.id = NEW.invoiceId;
|
|
||||||
|
|
||||||
|
|
||||||
SELECT COALESCE(sav.availableQuantity, 0) INTO current_stock
|
|
||||||
FROM Stock_Available_View sav
|
|
||||||
WHERE productId = NEW.productId AND sav.inventoryId = inventory_id;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
IF NEW.count > current_stock THEN
|
|
||||||
SIGNAL SQLSTATE '45000'
|
|
||||||
SET MESSAGE_TEXT = 'موجودی کالا در انبار کافی نیست.';
|
|
||||||
END IF;
|
|
||||||
end;
|
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- index: 9
|
|
||||||
-- Trigger: trg_sales_invoice_items_after_insert
|
|
||||||
-- Event: INSERT
|
|
||||||
-- Table: Sales_Invoice_Items
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_sales_invoice_items_after_insert`;
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_sales_invoice_items_after_insert` AFTER INSERT ON `Sales_Invoice_Items` FOR EACH ROW begin DECLARE current_stock DECIMAL(10, 2);
|
|
||||||
|
|
||||||
DECLARE inventory_id INT;
|
|
||||||
DECLARE customer_id INT;
|
|
||||||
DECLARE pos_id INT;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SELECT posAccountId, customerId INTO pos_id, customer_id
|
|
||||||
FROM Sales_Invoices si
|
|
||||||
WHERE si.id = NEW.invoiceId
|
|
||||||
LIMIT 1;
|
|
||||||
INSERT INTO Trigger_Logs (name , message) VALUES ('pos_id', pos_id);
|
|
||||||
INSERT INTO Trigger_Logs (name , message) VALUES ('customer_id', customer_id);
|
|
||||||
|
|
||||||
|
|
||||||
SELECT pa.inventoryId INTO inventory_id
|
|
||||||
FROM Pos_Accounts pa
|
|
||||||
INNER JOIN Sales_Invoices si ON pa.id = si.posAccountId
|
|
||||||
WHERE si.id = NEW.invoiceId;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SELECT COALESCE(quantity, 0) INTO current_stock
|
|
||||||
FROM Stock_Balance sb
|
|
||||||
WHERE productId = NEW.productId AND sb.inventoryId = inventory_id
|
|
||||||
LIMIT 1;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
INSERT INTO Stock_Movements (
|
|
||||||
type,
|
|
||||||
quantity,
|
|
||||||
unitPrice,
|
|
||||||
totalCost,
|
|
||||||
referenceType,
|
|
||||||
referenceId,
|
|
||||||
productId,
|
|
||||||
inventoryId,
|
|
||||||
avgCost,
|
|
||||||
remainedInStock,
|
|
||||||
customerId,
|
|
||||||
createdAt
|
|
||||||
)
|
|
||||||
VALUES (
|
|
||||||
'OUT',
|
|
||||||
NEW.count,
|
|
||||||
NEW.unitPrice,
|
|
||||||
NEW.totalAmount,
|
|
||||||
'SALES',
|
|
||||||
NEW.invoiceId,
|
|
||||||
NEW.productId,
|
|
||||||
inventory_id,
|
|
||||||
|
|
||||||
CASE
|
|
||||||
WHEN NEW.count = 0 THEN 0
|
|
||||||
ELSE NEW.totalAmount / NEW.count
|
|
||||||
END,
|
|
||||||
current_stock - NEW.count,
|
|
||||||
customer_id,
|
|
||||||
NOW()
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
END;
|
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- index: 10
|
|
||||||
-- Trigger: trg_pos_account_payment_after_insert
|
|
||||||
-- Event: INSERT
|
|
||||||
-- Table: Sales_Invoice_Payments
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_pos_account_payment_after_insert`;
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_pos_account_payment_after_insert` AFTER INSERT ON `Sales_Invoice_Payments` FOR EACH ROW BEGIN
|
|
||||||
|
|
||||||
DECLARE _bankAccountId INT;
|
|
||||||
|
|
||||||
IF(NEW.paymentMethod != 'CASH') THEN
|
|
||||||
SELECT cashBankAccountId INTO _bankAccountId
|
|
||||||
FROM Pos_Accounts pa
|
|
||||||
INNER JOIN Sales_Invoices si ON pa.id = si.posAccountId
|
|
||||||
WHERE si.id = NEW.invoiceId;
|
|
||||||
End IF;
|
|
||||||
|
|
||||||
INSERT INTO Bank_Account_Transactions (
|
|
||||||
bankAccountId,
|
|
||||||
type,
|
|
||||||
amount,
|
|
||||||
balanceAfter,
|
|
||||||
referenceType,
|
|
||||||
referenceId
|
|
||||||
)
|
|
||||||
VALUES(
|
|
||||||
_bankAccountId,
|
|
||||||
'DEPOSIT',
|
|
||||||
NEW.amount,
|
|
||||||
0,
|
|
||||||
'POS_SALE',
|
|
||||||
NEW.id
|
|
||||||
);
|
|
||||||
END;
|
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- index: 11
|
|
||||||
-- Trigger: trg_sales_invoice_payment_after_insert
|
|
||||||
-- Event: INSERT
|
|
||||||
-- Table: Sales_Invoice_Payments
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_sales_invoice_payment_after_insert`;
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_sales_invoice_payment_after_insert` AFTER INSERT ON `Sales_Invoice_Payments` FOR EACH ROW BEGIN
|
|
||||||
DECLARE currentBalance DECIMAL(15,2);
|
|
||||||
DECLARE bankAccountId INT;
|
|
||||||
|
|
||||||
SELECT pa.bankAccountId INTO bankAccountId
|
|
||||||
FROM Pos_Accounts pa
|
|
||||||
INNER JOIN Sales_Invoices si ON pa.id = si.posAccountId
|
|
||||||
WHERE si.id = NEW.invoiceId;
|
|
||||||
|
|
||||||
SELECT balance INTO currentBalance
|
|
||||||
FROM Bank_Account_Balance
|
|
||||||
WHERE bankAccountId = bankAccountId
|
|
||||||
FOR UPDATE;
|
|
||||||
|
|
||||||
IF currentBalance IS NULL THEN
|
|
||||||
SET currentBalance = 0;
|
|
||||||
INSERT INTO Bank_Account_Balance (bankAccountId, balance)
|
|
||||||
VALUES (bankAccountId, 0);
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
SET currentBalance = currentBalance + NEW.amount;
|
|
||||||
|
|
||||||
INSERT INTO Bank_Account_Transactions
|
|
||||||
(bankAccountId, type, amount, balanceAfter, referenceType, referenceId)
|
|
||||||
VALUES
|
|
||||||
(bankAccountId, 'DEPOSIT', NEW.amount, currentBalance, 'POS_SALE', NEW.id);
|
|
||||||
|
|
||||||
UPDATE Bank_Account_Balance
|
|
||||||
SET balance = currentBalance
|
|
||||||
WHERE bankAccountId = bankAccountId;
|
|
||||||
END;
|
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- index: 12
|
|
||||||
-- Trigger: trg_stock_sale_insert
|
|
||||||
-- Event: INSERT
|
|
||||||
-- Table: Stock_Movements
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_stock_sale_insert`;
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_stock_sale_insert` AFTER INSERT ON `Stock_Movements` FOR EACH ROW BEGIN IF NEW.referenceType = 'SALES' THEN
|
|
||||||
|
|
||||||
INSERT INTO
|
|
||||||
Stock_Balance (
|
|
||||||
productId,
|
|
||||||
quantity,
|
|
||||||
avgCost,
|
|
||||||
totalCost,
|
|
||||||
inventoryId,
|
|
||||||
updatedAt
|
|
||||||
)
|
|
||||||
VALUES (
|
|
||||||
NEW.productId,
|
|
||||||
NEW.quantity,
|
|
||||||
NEW.unitPrice,
|
|
||||||
NEW.totalCost,
|
|
||||||
NEW.inventoryId,
|
|
||||||
NOW()
|
|
||||||
)
|
|
||||||
ON DUPLICATE KEY UPDATE
|
|
||||||
quantity = quantity - NEW.quantity,
|
|
||||||
totalCost = totalCost - NEW.totalCost,
|
|
||||||
avgCost = totalCost / quantity;
|
|
||||||
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
END;
|
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- index: 13
|
|
||||||
-- Trigger: trg_stock_purchase_insert
|
|
||||||
-- Event: INSERT
|
|
||||||
-- Table: Stock_Movements
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_stock_purchase_insert`;
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_stock_purchase_insert` AFTER INSERT ON `Stock_Movements` FOR EACH ROW BEGIN IF NEW.referenceType = 'PURCHASE' THEN
|
|
||||||
|
|
||||||
INSERT INTO
|
|
||||||
Stock_Balance (
|
|
||||||
productId,
|
|
||||||
quantity,
|
|
||||||
avgCost,
|
|
||||||
totalCost,
|
|
||||||
inventoryId,
|
|
||||||
updatedAt
|
|
||||||
)
|
|
||||||
VALUES (
|
|
||||||
NEW.productId,
|
|
||||||
NEW.quantity,
|
|
||||||
NEW.unitPrice,
|
|
||||||
NEW.totalCost,
|
|
||||||
NEW.inventoryId,
|
|
||||||
NOW()
|
|
||||||
)
|
|
||||||
ON DUPLICATE KEY UPDATE
|
|
||||||
quantity = quantity + NEW.quantity,
|
|
||||||
totalCost = totalCost + NEW.totalCost,
|
|
||||||
avgCost = totalCost / quantity;
|
|
||||||
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
END;
|
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- index: 14
|
|
||||||
-- Trigger: trg_stock_transfer
|
|
||||||
-- Event: INSERT
|
|
||||||
-- Table: Stock_Movements
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_stock_transfer`;
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_stock_transfer` AFTER INSERT ON `Stock_Movements` FOR EACH ROW BEGIN IF NEW.referenceType = 'INVENTORY_TRANSFER' THEN IF NEW.type = 'IN' THEN
|
|
||||||
INSERT INTO
|
|
||||||
Stock_Balance (
|
|
||||||
productId,
|
|
||||||
inventoryId,
|
|
||||||
quantity,
|
|
||||||
totalCost,
|
|
||||||
avgCost,
|
|
||||||
updatedAt
|
|
||||||
)
|
|
||||||
VALUES (
|
|
||||||
NEW.productId,
|
|
||||||
NEW.inventoryId,
|
|
||||||
NEW.quantity,
|
|
||||||
NEW.totalCost,
|
|
||||||
CASE
|
|
||||||
WHEN NEW.quantity = 0 THEN 0
|
|
||||||
ELSE NEW.totalCost / NEW.quantity
|
|
||||||
END,
|
|
||||||
NOW()
|
|
||||||
)
|
|
||||||
ON DUPLICATE KEY UPDATE
|
|
||||||
quantity = quantity + NEW.quantity,
|
|
||||||
totalCost = totalCost + NEW.totalCost,
|
|
||||||
avgCost = CASE
|
|
||||||
WHEN (quantity + NEW.quantity) = 0 THEN 0
|
|
||||||
ELSE (totalCost + NEW.totalCost) / (quantity + NEW.quantity)
|
|
||||||
END,
|
|
||||||
updatedAt = NOW();
|
|
||||||
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
IF NEW.type = 'OUT' THEN IF EXISTS (
|
|
||||||
SELECT 1
|
|
||||||
FROM Stock_Balance sb
|
|
||||||
WHERE
|
|
||||||
sb.productId = NEW.productId
|
|
||||||
AND sb.inventoryId = NEW.inventoryId
|
|
||||||
) THEN
|
|
||||||
|
|
||||||
UPDATE Stock_Balance sb
|
|
||||||
SET
|
|
||||||
sb.quantity = sb.quantity - NEW.quantity,
|
|
||||||
sb.totalCost = sb.totalCost - (sb.avgCost * NEW.quantity),
|
|
||||||
sb.updatedAt = NOW()
|
|
||||||
WHERE
|
|
||||||
sb.productId = NEW.productId
|
|
||||||
AND sb.inventoryId = NEW.inventoryId;
|
|
||||||
|
|
||||||
ELSE
|
|
||||||
INSERT INTO
|
|
||||||
Stock_Balance (
|
|
||||||
productId,
|
|
||||||
inventoryId,
|
|
||||||
quantity,
|
|
||||||
totalCost,
|
|
||||||
avgCost,
|
|
||||||
updatedAt
|
|
||||||
)
|
|
||||||
VALUES (
|
|
||||||
NEW.productId,
|
|
||||||
NEW.inventoryId,
|
|
||||||
- NEW.quantity,
|
|
||||||
- COALESCE(NEW.unitPrice, 0) * NEW.quantity,
|
|
||||||
COALESCE(NEW.unitPrice, 0),
|
|
||||||
NOW()
|
|
||||||
);
|
|
||||||
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
END;
|
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- index: 15
|
|
||||||
-- Trigger: trg_no_negative_available_stock
|
|
||||||
-- Event: INSERT
|
|
||||||
-- Table: Stock_Reservations
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_no_negative_available_stock`;
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_no_negative_available_stock` BEFORE INSERT ON `Stock_Reservations` FOR EACH ROW BEGIN
|
|
||||||
DECLARE available DECIMAL(14,3);
|
|
||||||
|
|
||||||
SELECT availableQuantity
|
|
||||||
INTO available
|
|
||||||
FROM Stock_Available_View
|
|
||||||
WHERE productId = NEW.productId
|
|
||||||
AND inventoryId = NEW.inventoryId;
|
|
||||||
|
|
||||||
IF available < NEW.quantity THEN
|
|
||||||
SIGNAL SQLSTATE '45000'
|
|
||||||
SET MESSAGE_TEXT = 'موجودی کافی نیست';
|
|
||||||
END IF;
|
|
||||||
END;
|
|
||||||
|
|
||||||
@@ -1,825 +0,0 @@
|
|||||||
-- AUTO-GENERATED MYSQL TRIGGER DUMP
|
|
||||||
-- Generated at: 2026-01-04T09:46:30.365Z
|
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- index: 1
|
|
||||||
-- Trigger: trg_bank_account_transaction_after_insert
|
|
||||||
-- Event: INSERT
|
|
||||||
-- Table: Bank_Account_Transactions
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_bank_account_transaction_after_insert`;
|
|
||||||
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_bank_account_transaction_after_insert` AFTER INSERT ON `Bank_Account_Transactions` FOR EACH ROW BEGIN
|
|
||||||
IF NEW.type = 'DEPOSIT' THEN
|
|
||||||
UPDATE Bank_Account_Balance SET balance = balance + NEW.amount WHERE bankAccountId = NEW.bankAccountId;
|
|
||||||
ELSEIF NEW.type = 'WITHDRAWAL' THEN
|
|
||||||
UPDATE Bank_Account_Balance SET balance = balance - NEW.amount WHERE bankAccountId = NEW.bankAccountId;
|
|
||||||
END IF;
|
|
||||||
END;
|
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- index: 2
|
|
||||||
-- Trigger: trg_bank_account_transaction_after_delete
|
|
||||||
-- Event: DELETE
|
|
||||||
-- Table: Bank_Account_Transactions
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_bank_account_transaction_after_delete`;
|
|
||||||
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_bank_account_transaction_after_delete` AFTER DELETE ON `Bank_Account_Transactions` FOR EACH ROW BEGIN
|
|
||||||
UPDATE Bank_Accounts SET balance = balance - OLD.amount;
|
|
||||||
END;
|
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- index: 3
|
|
||||||
-- Trigger: trg_transfer_item_after_insert
|
|
||||||
-- Event: INSERT
|
|
||||||
-- Table: Inventory_Transfer_Items
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_transfer_item_after_insert`;
|
|
||||||
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_transfer_item_after_insert` AFTER INSERT ON `Inventory_Transfer_Items` FOR EACH ROW begin
|
|
||||||
|
|
||||||
DECLARE fromInv INT;
|
|
||||||
DECLARE toInv INT;
|
|
||||||
DECLARE _avgCost DECIMAL(10,2);
|
|
||||||
DECLARE latestQuantityInOrigin DECIMAL(10,2);
|
|
||||||
DECLARE latestQuantityInDestination DECIMAL(10,2);
|
|
||||||
|
|
||||||
SELECT fromInventoryId, toInventoryId INTO fromInv, toInv
|
|
||||||
FROM Inventory_Transfers WHERE id = NEW.transferId;
|
|
||||||
|
|
||||||
SELECT COALESCE(avgCost, 0), COALESCE(quantity, 0) INTO _avgCost, latestQuantityInOrigin FROM Stock_Balance
|
|
||||||
WHERE ProductId = NEW.productId AND inventoryId = fromInv LIMIT 1;
|
|
||||||
|
|
||||||
SELECT COALESCE(quantity, 0) INTO latestQuantityInDestination FROM Stock_Balance
|
|
||||||
WHERE ProductId = NEW.productId AND inventoryId = toInv LIMIT 1;
|
|
||||||
|
|
||||||
|
|
||||||
-- OUT from source
|
|
||||||
INSERT INTO Stock_Movements
|
|
||||||
(type, quantity, unitPrice, totalCost, avgCost, referenceType, referenceId, productId, inventoryId, counterInventoryId, createdAt, remainedInStock)
|
|
||||||
VALUES
|
|
||||||
('OUT', NEW.count, _avgCost, _avgCost*NEW.count, _avgCost, 'INVENTORY_TRANSFER', NEW.transferId, NEW.productId, fromInv, toInv, NOW(), latestQuantityInOrigin-NEW.count);
|
|
||||||
|
|
||||||
-- IN to destination
|
|
||||||
INSERT INTO Stock_Movements
|
|
||||||
(type, quantity, unitPrice, totalCost, avgCost, referenceType, referenceId, productId, inventoryId, counterInventoryId, createdAt, remainedInStock)
|
|
||||||
VALUES
|
|
||||||
('IN', NEW.count,_avgCost, _avgCost*NEW.count,_avgCost, 'INVENTORY_TRANSFER', NEW.transferId, NEW.productId, toInv, fromInv, NOW(), latestQuantityInOrigin-NEW.count);
|
|
||||||
end;
|
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- index: 4
|
|
||||||
-- Trigger: trg_order_item_after_insert
|
|
||||||
-- Event: INSERT
|
|
||||||
-- Table: Order_Items
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_order_item_after_insert`;
|
|
||||||
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_order_item_after_insert` AFTER INSERT ON `Order_Items` FOR EACH ROW BEGIN
|
|
||||||
UPDATE Stock_Reservations SET quantity = quantity + NEW.quantity
|
|
||||||
WHERE orderId = NEW.orderId AND productId = NEW.productId;
|
|
||||||
END;
|
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- index: 5
|
|
||||||
-- Trigger: trg_order_item_after_update
|
|
||||||
-- Event: UPDATE
|
|
||||||
-- Table: Order_Items
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_order_item_after_update`;
|
|
||||||
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_order_item_after_update` AFTER UPDATE ON `Order_Items` FOR EACH ROW BEGIN
|
|
||||||
UPDATE Stock_Reservations
|
|
||||||
SET quantity = quantity - OLD.quantity + NEW.quantity
|
|
||||||
WHERE orderId = NEW.orderId AND productId = NEW.productId;
|
|
||||||
END;
|
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- index: 6
|
|
||||||
-- Trigger: trg_order_item_after_delete
|
|
||||||
-- Event: DELETE
|
|
||||||
-- Table: Order_Items
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_order_item_after_delete`;
|
|
||||||
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_order_item_after_delete` AFTER DELETE ON `Order_Items` FOR EACH ROW BEGIN
|
|
||||||
UPDATE Stock_Reservations SET quantity = quantity - OLD.quantity
|
|
||||||
WHERE orderId = OLD.orderId AND productId = OLD.productId;
|
|
||||||
|
|
||||||
END;
|
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- index: 7
|
|
||||||
-- Trigger: trg_order_after_cancel
|
|
||||||
-- Event: UPDATE
|
|
||||||
-- Table: Orders
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_order_after_cancel`;
|
|
||||||
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_order_after_cancel` AFTER UPDATE ON `Orders` FOR EACH ROW BEGIN
|
|
||||||
IF NEW.status = 'CANCELED' OR NEW.status = 'REJECTED' OR NEW.status = 'DONE' THEN
|
|
||||||
UPDATE Stock_Reservations sr SET quantity = 0
|
|
||||||
WHERE sr.orderId = NEW.id;
|
|
||||||
END IF;
|
|
||||||
END;
|
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- index: 8
|
|
||||||
-- Trigger: trg_purchase_receipt_item_after_insert
|
|
||||||
-- Event: INSERT
|
|
||||||
-- Table: Purchase_Receipt_Items
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_purchase_receipt_item_after_insert`;
|
|
||||||
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_purchase_receipt_item_after_insert` AFTER INSERT ON `Purchase_Receipt_Items` FOR EACH ROW BEGIN DECLARE latestQuantity DECIMAL(10, 2) DEFAULT 0;
|
|
||||||
|
|
||||||
DECLARE invId INT;
|
|
||||||
DECLARE suppId INT;
|
|
||||||
|
|
||||||
-- Get inventory & supplier from
|
|
||||||
SELECT inventoryId, supplierId
|
|
||||||
INTO invId, suppId
|
|
||||||
FROM Purchase_Receipts
|
|
||||||
WHERE id = NEW.receiptId;
|
|
||||||
|
|
||||||
-- Get current stock quantity (if exists)
|
|
||||||
SELECT COALESCE(quantity, 0)
|
|
||||||
INTO latestQuantity
|
|
||||||
FROM Stock_Balance sb
|
|
||||||
WHERE sb.inventoryId = invId
|
|
||||||
AND sb.productId = NEW.productId
|
|
||||||
LIMIT 1;
|
|
||||||
|
|
||||||
-- Insert stock movement
|
|
||||||
INSERT INTO Stock_Movements (
|
|
||||||
type,
|
|
||||||
quantity,
|
|
||||||
unitPrice,
|
|
||||||
totalCost,
|
|
||||||
referenceType,
|
|
||||||
referenceId,
|
|
||||||
productId,
|
|
||||||
inventoryId,
|
|
||||||
avgCost,
|
|
||||||
supplierId,
|
|
||||||
remainedInStock,
|
|
||||||
createdAt
|
|
||||||
)
|
|
||||||
VALUES (
|
|
||||||
'IN',
|
|
||||||
NEW.count,
|
|
||||||
NEW.unitPrice,
|
|
||||||
NEW.totalAmount,
|
|
||||||
'PURCHASE',
|
|
||||||
NEW.receiptId,
|
|
||||||
NEW.productId,
|
|
||||||
invId,
|
|
||||||
CASE
|
|
||||||
WHEN NEW.count = 0 THEN 0
|
|
||||||
ELSE NEW.totalAmount / NEW.count
|
|
||||||
END
|
|
||||||
|
|
||||||
,
|
|
||||||
suppId,
|
|
||||||
latestQuantity + NEW.count,
|
|
||||||
NOW()
|
|
||||||
);
|
|
||||||
|
|
||||||
END;
|
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- index: 9
|
|
||||||
-- Trigger: trg_pr_payment_before_insert
|
|
||||||
-- Event: INSERT
|
|
||||||
-- Table: Purchase_Receipt_Payments
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_pr_payment_before_insert`;
|
|
||||||
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_pr_payment_before_insert` BEFORE INSERT ON `Purchase_Receipt_Payments` FOR EACH ROW BEGIN
|
|
||||||
|
|
||||||
|
|
||||||
DECLARE receiptTotal DECIMAL(14,2);
|
|
||||||
DECLARE paid DECIMAL(14,2);
|
|
||||||
|
|
||||||
|
|
||||||
SELECT totalAmount, paidAmount
|
|
||||||
INTO receiptTotal, paid
|
|
||||||
FROM Purchase_Receipts
|
|
||||||
WHERE id = NEW.receiptId
|
|
||||||
FOR UPDATE;
|
|
||||||
|
|
||||||
IF NEW.type = 'PAYMENT' AND paid + NEW.amount > receiptTotal THEN
|
|
||||||
SIGNAL SQLSTATE '45000'
|
|
||||||
SET MESSAGE_TEXT = 'مجموع مبلغ پرداختی بیشتر از مبلغ فاکتور است.';
|
|
||||||
END IF;
|
|
||||||
END;
|
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- index: 10
|
|
||||||
-- Trigger: trg_purchase_payment_update_receipt
|
|
||||||
-- Event: INSERT
|
|
||||||
-- Table: Purchase_Receipt_Payments
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_purchase_payment_update_receipt`;
|
|
||||||
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_purchase_payment_update_receipt` AFTER INSERT ON `Purchase_Receipt_Payments` FOR EACH ROW BEGIN
|
|
||||||
DECLARE paid DECIMAL(15,2);
|
|
||||||
DECLARE total DECIMAL(15,2);
|
|
||||||
|
|
||||||
SELECT
|
|
||||||
COALESCE(SUM(
|
|
||||||
CASE WHEN type = 'PAYMENT' THEN amount ELSE -amount END
|
|
||||||
),0)
|
|
||||||
INTO paid
|
|
||||||
FROM Purchase_Receipt_Payments
|
|
||||||
WHERE receiptId = NEW.receiptId;
|
|
||||||
|
|
||||||
SELECT totalAmount INTO total
|
|
||||||
FROM Purchase_Receipts
|
|
||||||
WHERE id = NEW.receiptId;
|
|
||||||
|
|
||||||
UPDATE Purchase_Receipts
|
|
||||||
SET
|
|
||||||
paidAmount = paid,
|
|
||||||
status = CASE
|
|
||||||
WHEN paid = 0 THEN 'UNPAID'
|
|
||||||
WHEN paid < total THEN 'PARTIALLY_PAID'
|
|
||||||
ELSE 'PAID'
|
|
||||||
END
|
|
||||||
WHERE id = NEW.receiptId;
|
|
||||||
END;
|
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- index: 11
|
|
||||||
-- Trigger: trg_purchase_payment_after_insert
|
|
||||||
-- Event: INSERT
|
|
||||||
-- Table: Purchase_Receipt_Payments
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_purchase_payment_after_insert`;
|
|
||||||
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_purchase_payment_after_insert` AFTER INSERT ON `Purchase_Receipt_Payments` FOR EACH ROW BEGIN
|
|
||||||
|
|
||||||
DECLARE currentBalance DECIMAL(15, 2);
|
|
||||||
|
|
||||||
|
|
||||||
SELECT balance INTO currentBalance
|
|
||||||
FROM Bank_Account_Balance
|
|
||||||
WHERE
|
|
||||||
bankAccountId = NEW.bankAccountId FOR
|
|
||||||
UPDATE;
|
|
||||||
|
|
||||||
|
|
||||||
IF currentBalance IS NULL THEN SET currentBalance = 0;
|
|
||||||
|
|
||||||
|
|
||||||
INSERT INTO
|
|
||||||
Bank_Account_Balance (bankAccountId, balance, updatedAt)
|
|
||||||
VALUES (NEW.bankAccountId, 0, NOW());
|
|
||||||
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
IF NEW.type = 'PAYMENT' THEN
|
|
||||||
SET
|
|
||||||
currentBalance = currentBalance - NEW.amount;
|
|
||||||
|
|
||||||
INSERT INTO
|
|
||||||
Bank_Account_Transactions (
|
|
||||||
bankAccountId,
|
|
||||||
type,
|
|
||||||
amount,
|
|
||||||
balanceAfter,
|
|
||||||
referenceType,
|
|
||||||
referenceId
|
|
||||||
)
|
|
||||||
VALUES (
|
|
||||||
NEW.bankAccountId,
|
|
||||||
'WITHDRAWAL',
|
|
||||||
NEW.amount,
|
|
||||||
currentBalance,
|
|
||||||
'PURCHASE_PAYMENT',
|
|
||||||
NEW.id
|
|
||||||
);
|
|
||||||
|
|
||||||
ELSE SET currentBalance = currentBalance + NEW.amount;
|
|
||||||
|
|
||||||
INSERT INTO
|
|
||||||
Bank_Account_Transactions (
|
|
||||||
bankAccountId,
|
|
||||||
type,
|
|
||||||
amount,
|
|
||||||
balanceAfter,
|
|
||||||
referenceType,
|
|
||||||
referenceId
|
|
||||||
)
|
|
||||||
VALUES (
|
|
||||||
NEW.bankAccountId,
|
|
||||||
'DEPOSIT',
|
|
||||||
NEW.amount,
|
|
||||||
currentBalance,
|
|
||||||
'PURCHASE_REFUND',
|
|
||||||
NEW.id
|
|
||||||
);
|
|
||||||
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
UPDATE Bank_Account_Balance
|
|
||||||
SET
|
|
||||||
balance = currentBalance
|
|
||||||
WHERE
|
|
||||||
bankAccountId = NEW.bankAccountId;
|
|
||||||
|
|
||||||
END;
|
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- index: 12
|
|
||||||
-- Trigger: trg_pr_payment_after_insert
|
|
||||||
-- Event: INSERT
|
|
||||||
-- Table: Purchase_Receipt_Payments
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_pr_payment_after_insert`;
|
|
||||||
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_pr_payment_after_insert` AFTER INSERT ON `Purchase_Receipt_Payments` FOR EACH ROW BEGIN
|
|
||||||
DECLARE receiptTotal DECIMAL(14,2) Default 0;
|
|
||||||
DECLARE newPaid DECIMAL(14,2) Default 0;
|
|
||||||
DECLARE _supplierId INT;
|
|
||||||
DECLARE lastBalance DECIMAL(14,2) Default 0;
|
|
||||||
|
|
||||||
|
|
||||||
-- Lock receipt row
|
|
||||||
SELECT COALESCE(totalAmount, 0), COALESCE(paidAmount, 0), supplierId
|
|
||||||
INTO receiptTotal, newPaid, _supplierId
|
|
||||||
FROM Purchase_Receipts
|
|
||||||
WHERE id = NEW.receiptId
|
|
||||||
FOR UPDATE;
|
|
||||||
|
|
||||||
-- Apply payment or refund
|
|
||||||
IF NEW.type = 'PAYMENT' THEN
|
|
||||||
SET newPaid = newPaid + NEW.amount;
|
|
||||||
ELSE
|
|
||||||
SET newPaid = newPaid - NEW.amount;
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
-- Update receipt
|
|
||||||
UPDATE Purchase_Receipts
|
|
||||||
SET
|
|
||||||
paidAmount = newPaid,
|
|
||||||
status =
|
|
||||||
CASE
|
|
||||||
WHEN newPaid = 0 THEN 'UNPAID'
|
|
||||||
WHEN newPaid < receiptTotal THEN 'PARTIALLY_PAID'
|
|
||||||
ELSE 'PAID'
|
|
||||||
END
|
|
||||||
WHERE id = NEW.receiptId;
|
|
||||||
|
|
||||||
-- Get last supplier balance
|
|
||||||
SELECT IFNULL(balance, 0)
|
|
||||||
INTO lastBalance
|
|
||||||
FROM Supplier_Ledger
|
|
||||||
WHERE supplierId = _supplierId
|
|
||||||
ORDER BY id DESC
|
|
||||||
LIMIT 1;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- Insert supplier ledger
|
|
||||||
INSERT INTO Supplier_Ledger
|
|
||||||
(
|
|
||||||
supplierId,
|
|
||||||
debit,
|
|
||||||
credit,
|
|
||||||
balance,
|
|
||||||
sourceType,
|
|
||||||
sourceId,
|
|
||||||
createdAt
|
|
||||||
)
|
|
||||||
VALUES
|
|
||||||
(
|
|
||||||
_supplierId,
|
|
||||||
IF(NEW.type = 'REFUND', NEW.amount, 0),
|
|
||||||
IF(NEW.type = 'PAYMENT', NEW.amount, 0),
|
|
||||||
lastBalance
|
|
||||||
+ IF(NEW.type = 'PAYMENT', NEW.amount, 0)
|
|
||||||
- IF(NEW.type = 'REFUND', NEW.amount, 0),
|
|
||||||
'PAYMENT',
|
|
||||||
NEW.id,
|
|
||||||
NOW()
|
|
||||||
);
|
|
||||||
END;
|
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- index: 13
|
|
||||||
-- Trigger: trg_pr_payment_after_delete
|
|
||||||
-- Event: DELETE
|
|
||||||
-- Table: Purchase_Receipt_Payments
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_pr_payment_after_delete`;
|
|
||||||
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_pr_payment_after_delete` AFTER DELETE ON `Purchase_Receipt_Payments` FOR EACH ROW BEGIN
|
|
||||||
DECLARE receiptTotal DECIMAL(14,2);
|
|
||||||
DECLARE newPaid DECIMAL(14,2);
|
|
||||||
|
|
||||||
SELECT totalAmount, paidAmount
|
|
||||||
INTO receiptTotal, newPaid
|
|
||||||
FROM Purchase_Receipts
|
|
||||||
WHERE id = OLD.receiptId
|
|
||||||
FOR UPDATE;
|
|
||||||
|
|
||||||
IF OLD.type = 'PAYMENT' THEN
|
|
||||||
SET newPaid = newPaid - OLD.amount;
|
|
||||||
ELSE
|
|
||||||
SET newPaid = newPaid + OLD.amount;
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
UPDATE Purchase_Receipts
|
|
||||||
SET
|
|
||||||
paidAmount = newPaid,
|
|
||||||
status =
|
|
||||||
CASE
|
|
||||||
WHEN newPaid = 0 THEN 'UNPAID'
|
|
||||||
WHEN newPaid < receiptTotal THEN 'PARTIALLY_PAID'
|
|
||||||
ELSE 'PAID'
|
|
||||||
END
|
|
||||||
WHERE id = OLD.receiptId;
|
|
||||||
END;
|
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- index: 14
|
|
||||||
-- Trigger: trg_purchase_receipt_after_insert
|
|
||||||
-- Event: INSERT
|
|
||||||
-- Table: Purchase_Receipts
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_purchase_receipt_after_insert`;
|
|
||||||
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_purchase_receipt_after_insert` AFTER INSERT ON `Purchase_Receipts` FOR EACH ROW BEGIN
|
|
||||||
DECLARE lastBalance DECIMAL(14,2) DEFAULT 0;
|
|
||||||
|
|
||||||
SELECT COALESCE(balance, 0)
|
|
||||||
INTO lastBalance
|
|
||||||
FROM Supplier_Ledger
|
|
||||||
WHERE supplierId = NEW.supplierId
|
|
||||||
ORDER BY id DESC
|
|
||||||
LIMIT 1;
|
|
||||||
|
|
||||||
INSERT INTO Supplier_Ledger
|
|
||||||
(
|
|
||||||
supplierId,
|
|
||||||
debit,
|
|
||||||
credit,
|
|
||||||
balance,
|
|
||||||
sourceType,
|
|
||||||
sourceId,
|
|
||||||
createdAt
|
|
||||||
)
|
|
||||||
VALUES
|
|
||||||
(
|
|
||||||
NEW.supplierId,
|
|
||||||
NEW.totalAmount,
|
|
||||||
0,
|
|
||||||
lastBalance - NEW.totalAmount,
|
|
||||||
'PURCHASE',
|
|
||||||
NEW.id,
|
|
||||||
NOW()
|
|
||||||
);
|
|
||||||
END;
|
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- index: 15
|
|
||||||
-- Trigger: trg_sales_invoice_items_before_insert
|
|
||||||
-- Event: INSERT
|
|
||||||
-- Table: Sales_Invoice_Items
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_sales_invoice_items_before_insert`;
|
|
||||||
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_sales_invoice_items_before_insert` BEFORE INSERT ON `Sales_Invoice_Items` FOR EACH ROW BEGIN
|
|
||||||
|
|
||||||
DECLARE current_stock DECIMAL(10, 2);
|
|
||||||
DECLARE inventory_id INT;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SELECT pa.inventoryId INTO inventory_id
|
|
||||||
FROM Pos_Accounts pa
|
|
||||||
INNER JOIN Sales_Invoices si ON pa.id = si.posAccountId
|
|
||||||
WHERE si.id = NEW.invoiceId;
|
|
||||||
|
|
||||||
|
|
||||||
SELECT COALESCE(quantity, 0) INTO current_stock
|
|
||||||
FROM Stock_Balance sb
|
|
||||||
WHERE productId = NEW.productId AND sb.inventoryId = inventory_id
|
|
||||||
LIMIT 1;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
IF NEW.count > current_stock THEN
|
|
||||||
SIGNAL SQLSTATE '45000'
|
|
||||||
SET MESSAGE_TEXT = 'موجودی کالا در انبار کافی نیست.';
|
|
||||||
END IF;
|
|
||||||
end;
|
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- index: 16
|
|
||||||
-- Trigger: trg_sales_invoice_items_after_insert
|
|
||||||
-- Event: INSERT
|
|
||||||
-- Table: Sales_Invoice_Items
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_sales_invoice_items_after_insert`;
|
|
||||||
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_sales_invoice_items_after_insert` AFTER INSERT ON `Sales_Invoice_Items` FOR EACH ROW begin DECLARE current_stock DECIMAL(10, 2);
|
|
||||||
|
|
||||||
DECLARE inventory_id INT;
|
|
||||||
DECLARE customer_id INT;
|
|
||||||
DECLARE pos_id INT;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SELECT posAccountId, customerId INTO pos_id, customer_id
|
|
||||||
FROM Sales_Invoices si
|
|
||||||
WHERE si.id = NEW.invoiceId
|
|
||||||
LIMIT 1;
|
|
||||||
INSERT INTO Trigger_Logs (name , message) VALUES ('pos_id', pos_id);
|
|
||||||
INSERT INTO Trigger_Logs (name , message) VALUES ('customer_id', customer_id);
|
|
||||||
|
|
||||||
|
|
||||||
SELECT pa.inventoryId INTO inventory_id
|
|
||||||
FROM Pos_Accounts pa
|
|
||||||
INNER JOIN Sales_Invoices si ON pa.id = si.posAccountId
|
|
||||||
WHERE si.id = NEW.invoiceId;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SELECT COALESCE(quantity, 0) INTO current_stock
|
|
||||||
FROM Stock_Balance sb
|
|
||||||
WHERE productId = NEW.productId AND sb.inventoryId = inventory_id
|
|
||||||
LIMIT 1;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
INSERT INTO Stock_Movements (
|
|
||||||
type,
|
|
||||||
quantity,
|
|
||||||
unitPrice,
|
|
||||||
totalCost,
|
|
||||||
referenceType,
|
|
||||||
referenceId,
|
|
||||||
productId,
|
|
||||||
inventoryId,
|
|
||||||
avgCost,
|
|
||||||
remainedInStock,
|
|
||||||
customerId,
|
|
||||||
createdAt
|
|
||||||
)
|
|
||||||
VALUES (
|
|
||||||
'OUT',
|
|
||||||
NEW.count,
|
|
||||||
NEW.unitPrice,
|
|
||||||
NEW.totalAmount,
|
|
||||||
'SALES',
|
|
||||||
NEW.invoiceId,
|
|
||||||
NEW.productId,
|
|
||||||
inventory_id,
|
|
||||||
|
|
||||||
CASE
|
|
||||||
WHEN NEW.count = 0 THEN 0
|
|
||||||
ELSE NEW.totalAmount / NEW.count
|
|
||||||
END,
|
|
||||||
current_stock - NEW.count,
|
|
||||||
customer_id,
|
|
||||||
NOW()
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
END;
|
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- index: 17
|
|
||||||
-- Trigger: trg_sales_invoice_payment_after_insert
|
|
||||||
-- Event: INSERT
|
|
||||||
-- Table: Sales_Invoice_Payments
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_sales_invoice_payment_after_insert`;
|
|
||||||
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_sales_invoice_payment_after_insert` AFTER INSERT ON `Sales_Invoice_Payments` FOR EACH ROW BEGIN
|
|
||||||
DECLARE currentBalance DECIMAL(15,2);
|
|
||||||
DECLARE bankAccountId INT;
|
|
||||||
|
|
||||||
SELECT pa.bankAccountId INTO bankAccountId
|
|
||||||
FROM Pos_Accounts pa
|
|
||||||
INNER JOIN Sales_Invoices si ON pa.id = si.posAccountId
|
|
||||||
WHERE si.id = NEW.invoiceId;
|
|
||||||
|
|
||||||
SELECT balance INTO currentBalance
|
|
||||||
FROM Bank_Account_Balance
|
|
||||||
WHERE bankAccountId = bankAccountId
|
|
||||||
FOR UPDATE;
|
|
||||||
|
|
||||||
IF currentBalance IS NULL THEN
|
|
||||||
SET currentBalance = 0;
|
|
||||||
INSERT INTO Bank_Account_Balance (bankAccountId, balance)
|
|
||||||
VALUES (bankAccountId, 0);
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
SET currentBalance = currentBalance + NEW.amount;
|
|
||||||
|
|
||||||
INSERT INTO Bank_Account_Transactions
|
|
||||||
(bankAccountId, type, amount, balanceAfter, referenceType, referenceId)
|
|
||||||
VALUES
|
|
||||||
(bankAccountId, 'DEPOSIT', NEW.amount, currentBalance, 'POS_SALE', NEW.id);
|
|
||||||
|
|
||||||
UPDATE Bank_Account_Balance
|
|
||||||
SET balance = currentBalance
|
|
||||||
WHERE bankAccountId = bankAccountId;
|
|
||||||
END;
|
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- index: 18
|
|
||||||
-- Trigger: trg_pos_account_payment_after_insert
|
|
||||||
-- Event: INSERT
|
|
||||||
-- Table: Sales_Invoice_Payments
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_pos_account_payment_after_insert`;
|
|
||||||
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_pos_account_payment_after_insert` AFTER INSERT ON `Sales_Invoice_Payments` FOR EACH ROW BEGIN
|
|
||||||
|
|
||||||
DECLARE _bankAccountId INT;
|
|
||||||
|
|
||||||
IF(NEW.paymentMethod != 'CASH') THEN
|
|
||||||
SELECT cashBankAccountId INTO _bankAccountId
|
|
||||||
FROM Pos_Accounts pa
|
|
||||||
INNER JOIN Sales_Invoices si ON pa.id = si.posAccountId
|
|
||||||
WHERE si.id = NEW.invoiceId;
|
|
||||||
End IF;
|
|
||||||
|
|
||||||
INSERT INTO Bank_Account_Transactions (
|
|
||||||
bankAccountId,
|
|
||||||
type,
|
|
||||||
amount,
|
|
||||||
balanceAfter,
|
|
||||||
referenceType,
|
|
||||||
referenceId
|
|
||||||
)
|
|
||||||
VALUES(
|
|
||||||
_bankAccountId,
|
|
||||||
'DEPOSIT',
|
|
||||||
NEW.amount,
|
|
||||||
0,
|
|
||||||
'POS_SALE',
|
|
||||||
NEW.id
|
|
||||||
);
|
|
||||||
END;
|
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- index: 19
|
|
||||||
-- Trigger: trg_stock_transfer
|
|
||||||
-- Event: INSERT
|
|
||||||
-- Table: Stock_Movements
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_stock_transfer`;
|
|
||||||
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_stock_transfer` AFTER INSERT ON `Stock_Movements` FOR EACH ROW BEGIN IF NEW.referenceType = 'INVENTORY_TRANSFER' THEN IF NEW.type = 'IN' THEN
|
|
||||||
INSERT INTO
|
|
||||||
Stock_Balance (
|
|
||||||
productId,
|
|
||||||
inventoryId,
|
|
||||||
quantity,
|
|
||||||
totalCost,
|
|
||||||
avgCost,
|
|
||||||
updatedAt
|
|
||||||
)
|
|
||||||
VALUES (
|
|
||||||
NEW.productId,
|
|
||||||
NEW.inventoryId,
|
|
||||||
NEW.quantity,
|
|
||||||
NEW.totalCost,
|
|
||||||
CASE
|
|
||||||
WHEN NEW.quantity = 0 THEN 0
|
|
||||||
ELSE NEW.totalCost / NEW.quantity
|
|
||||||
END,
|
|
||||||
NOW()
|
|
||||||
)
|
|
||||||
ON DUPLICATE KEY UPDATE
|
|
||||||
quantity = quantity + NEW.quantity,
|
|
||||||
totalCost = totalCost + NEW.totalCost,
|
|
||||||
avgCost = CASE
|
|
||||||
WHEN (quantity + NEW.quantity) = 0 THEN 0
|
|
||||||
ELSE (totalCost + NEW.totalCost) / (quantity + NEW.quantity)
|
|
||||||
END,
|
|
||||||
updatedAt = NOW();
|
|
||||||
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
IF NEW.type = 'OUT' THEN IF EXISTS (
|
|
||||||
SELECT 1
|
|
||||||
FROM Stock_Balance sb
|
|
||||||
WHERE
|
|
||||||
sb.productId = NEW.productId
|
|
||||||
AND sb.inventoryId = NEW.inventoryId
|
|
||||||
) THEN
|
|
||||||
|
|
||||||
UPDATE Stock_Balance sb
|
|
||||||
SET
|
|
||||||
sb.quantity = sb.quantity - NEW.quantity,
|
|
||||||
sb.totalCost = sb.totalCost - (sb.avgCost * NEW.quantity),
|
|
||||||
sb.updatedAt = NOW()
|
|
||||||
WHERE
|
|
||||||
sb.productId = NEW.productId
|
|
||||||
AND sb.inventoryId = NEW.inventoryId;
|
|
||||||
|
|
||||||
ELSE
|
|
||||||
INSERT INTO
|
|
||||||
Stock_Balance (
|
|
||||||
productId,
|
|
||||||
inventoryId,
|
|
||||||
quantity,
|
|
||||||
totalCost,
|
|
||||||
avgCost,
|
|
||||||
updatedAt
|
|
||||||
)
|
|
||||||
VALUES (
|
|
||||||
NEW.productId,
|
|
||||||
NEW.inventoryId,
|
|
||||||
- NEW.quantity,
|
|
||||||
- COALESCE(NEW.unitPrice, 0) * NEW.quantity,
|
|
||||||
COALESCE(NEW.unitPrice, 0),
|
|
||||||
NOW()
|
|
||||||
);
|
|
||||||
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
END;
|
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- index: 20
|
|
||||||
-- Trigger: trg_stock_purchase_insert
|
|
||||||
-- Event: INSERT
|
|
||||||
-- Table: Stock_Movements
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_stock_purchase_insert`;
|
|
||||||
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_stock_purchase_insert` AFTER INSERT ON `Stock_Movements` FOR EACH ROW BEGIN IF NEW.referenceType = 'PURCHASE' THEN
|
|
||||||
|
|
||||||
INSERT INTO
|
|
||||||
Stock_Balance (
|
|
||||||
productId,
|
|
||||||
quantity,
|
|
||||||
avgCost,
|
|
||||||
totalCost,
|
|
||||||
inventoryId,
|
|
||||||
updatedAt
|
|
||||||
)
|
|
||||||
VALUES (
|
|
||||||
NEW.productId,
|
|
||||||
NEW.quantity,
|
|
||||||
NEW.unitPrice,
|
|
||||||
NEW.totalCost,
|
|
||||||
NEW.inventoryId,
|
|
||||||
NOW()
|
|
||||||
)
|
|
||||||
ON DUPLICATE KEY UPDATE
|
|
||||||
quantity = quantity + NEW.quantity,
|
|
||||||
totalCost = totalCost + NEW.totalCost,
|
|
||||||
avgCost = totalCost / quantity;
|
|
||||||
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
END;
|
|
||||||
|
|
||||||
-- ------------------------------------------
|
|
||||||
-- index: 21
|
|
||||||
-- Trigger: trg_stock_sale_insert
|
|
||||||
-- Event: INSERT
|
|
||||||
-- Table: Stock_Movements
|
|
||||||
-- ------------------------------------------
|
|
||||||
DROP TRIGGER IF EXISTS `trg_stock_sale_insert`;
|
|
||||||
|
|
||||||
CREATE DEFINER=`pos`@`%` TRIGGER `trg_stock_sale_insert` AFTER INSERT ON `Stock_Movements` FOR EACH ROW BEGIN IF NEW.referenceType = 'SALES' THEN
|
|
||||||
|
|
||||||
INSERT INTO
|
|
||||||
Stock_Balance (
|
|
||||||
productId,
|
|
||||||
quantity,
|
|
||||||
avgCost,
|
|
||||||
totalCost,
|
|
||||||
inventoryId,
|
|
||||||
updatedAt
|
|
||||||
)
|
|
||||||
VALUES (
|
|
||||||
NEW.productId,
|
|
||||||
NEW.quantity,
|
|
||||||
NEW.unitPrice,
|
|
||||||
NEW.totalCost,
|
|
||||||
NEW.inventoryId,
|
|
||||||
NOW()
|
|
||||||
)
|
|
||||||
ON DUPLICATE KEY UPDATE
|
|
||||||
quantity = quantity - NEW.quantity,
|
|
||||||
totalCost = totalCost - NEW.totalCost,
|
|
||||||
avgCost = totalCost / quantity;
|
|
||||||
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
END;
|
|
||||||
@@ -1,657 +0,0 @@
|
|||||||
-- Stored Procedures equivalent to triggers
|
|
||||||
|
|
||||||
DELIMITER / /
|
|
||||||
|
|
||||||
-- Procedure for trg_bank_account_transaction_after_insert
|
|
||||||
CREATE PROCEDURE update_bank_balance(IN p_bankAccountId INT, IN p_type VARCHAR(20), IN p_amount DECIMAL(15,2))
|
|
||||||
BEGIN
|
|
||||||
START TRANSACTION;
|
|
||||||
IF p_type = 'DEPOSIT' THEN
|
|
||||||
UPDATE Bank_Account_Balance SET balance = balance + p_amount WHERE bankAccountId = p_bankAccountId;
|
|
||||||
ELSEIF p_type = 'WITHDRAWAL' THEN
|
|
||||||
UPDATE Bank_Account_Balance SET balance = balance - p_amount WHERE bankAccountId = p_bankAccountId;
|
|
||||||
END IF;
|
|
||||||
COMMIT;
|
|
||||||
END //
|
|
||||||
|
|
||||||
-- Procedure for trg_bank_account_transaction_after_delete
|
|
||||||
CREATE PROCEDURE update_bank_balance_on_delete(IN p_bankAccountId INT, IN p_amount DECIMAL(15,2))
|
|
||||||
BEGIN
|
|
||||||
START TRANSACTION;
|
|
||||||
UPDATE Bank_Accounts SET balance = balance - p_amount WHERE id = p_bankAccountId;
|
|
||||||
COMMIT;
|
|
||||||
END //
|
|
||||||
|
|
||||||
-- Procedure for trg_transfer_item_after_insert
|
|
||||||
CREATE PROCEDURE process_transfer_item(IN p_transferId INT, IN p_productId INT, IN p_count DECIMAL(10,2))
|
|
||||||
BEGIN
|
|
||||||
START TRANSACTION;
|
|
||||||
DECLARE fromInv INT;
|
|
||||||
DECLARE toInv INT;
|
|
||||||
DECLARE _avgCost DECIMAL(10,2);
|
|
||||||
DECLARE latestQuantityInOrigin DECIMAL(10,2);
|
|
||||||
DECLARE latestQuantityInDestination DECIMAL(10,2);
|
|
||||||
|
|
||||||
SELECT fromInventoryId, toInventoryId INTO fromInv, toInv
|
|
||||||
FROM Inventory_Transfers WHERE id = p_transferId;
|
|
||||||
|
|
||||||
SELECT COALESCE(avgCost, 0), COALESCE(quantity, 0) INTO _avgCost, latestQuantityInOrigin FROM Stock_Balance
|
|
||||||
WHERE ProductId = p_productId AND inventoryId = fromInv LIMIT 1;
|
|
||||||
|
|
||||||
SELECT COALESCE(quantity, 0) INTO latestQuantityInDestination FROM Stock_Balance
|
|
||||||
WHERE ProductId = p_productId AND inventoryId = toInv LIMIT 1;
|
|
||||||
|
|
||||||
-- OUT from source
|
|
||||||
INSERT INTO Stock_Movements
|
|
||||||
(type, quantity, unitPrice, totalCost, avgCost, referenceType, referenceId, productId, inventoryId, counterInventoryId, createdAt, remainedInStock)
|
|
||||||
VALUES
|
|
||||||
('OUT', p_count, _avgCost, _avgCost*p_count, _avgCost, 'INVENTORY_TRANSFER', p_transferId, p_productId, fromInv, toInv, NOW(), latestQuantityInOrigin-p_count);
|
|
||||||
|
|
||||||
-- IN to destination
|
|
||||||
INSERT INTO Stock_Movements
|
|
||||||
(type, quantity, unitPrice, totalCost, avgCost, referenceType, referenceId, productId, inventoryId, counterInventoryId, createdAt, remainedInStock)
|
|
||||||
VALUES
|
|
||||||
('IN', p_count, _avgCost, _avgCost*p_count, _avgCost, 'INVENTORY_TRANSFER', p_transferId, p_productId, toInv, fromInv, NOW(), latestQuantityInOrigin-p_count);
|
|
||||||
COMMIT;
|
|
||||||
END //
|
|
||||||
|
|
||||||
-- Procedure for trg_order_item_after_insert
|
|
||||||
CREATE PROCEDURE update_stock_reservation_insert(IN p_orderId INT, IN p_productId INT, IN p_quantity DECIMAL(10,2))
|
|
||||||
BEGIN
|
|
||||||
START TRANSACTION;
|
|
||||||
UPDATE Stock_Reservations SET quantity = quantity + p_quantity
|
|
||||||
WHERE orderId = p_orderId AND productId = p_productId;
|
|
||||||
COMMIT;
|
|
||||||
END //
|
|
||||||
|
|
||||||
-- Procedure for trg_order_item_after_update
|
|
||||||
CREATE PROCEDURE update_stock_reservation_update(IN p_orderId INT, IN p_productId INT, IN p_old_quantity DECIMAL(10,2), IN p_new_quantity DECIMAL(10,2))
|
|
||||||
BEGIN
|
|
||||||
START TRANSACTION;
|
|
||||||
UPDATE Stock_Reservations
|
|
||||||
SET quantity = quantity - p_old_quantity + p_new_quantity
|
|
||||||
WHERE orderId = p_orderId AND productId = p_productId;
|
|
||||||
COMMIT;
|
|
||||||
END //
|
|
||||||
|
|
||||||
-- Procedure for trg_order_item_after_delete
|
|
||||||
CREATE PROCEDURE update_stock_reservation_delete(IN p_orderId INT, IN p_productId INT, IN p_quantity DECIMAL(10,2))
|
|
||||||
BEGIN
|
|
||||||
START TRANSACTION;
|
|
||||||
UPDATE Stock_Reservations SET quantity = quantity - p_quantity
|
|
||||||
WHERE orderId = p_orderId AND productId = p_productId;
|
|
||||||
COMMIT;
|
|
||||||
END //
|
|
||||||
|
|
||||||
-- Procedure for trg_order_after_cancel
|
|
||||||
CREATE PROCEDURE cancel_order_stock(IN p_orderId INT, IN p_status VARCHAR(20))
|
|
||||||
BEGIN
|
|
||||||
START TRANSACTION;
|
|
||||||
IF p_status = 'CANCELED' OR p_status = 'REJECTED' OR p_status = 'DONE' THEN
|
|
||||||
UPDATE Stock_Reservations sr SET quantity = 0
|
|
||||||
WHERE sr.orderId = p_orderId;
|
|
||||||
END IF;
|
|
||||||
COMMIT;
|
|
||||||
END //
|
|
||||||
|
|
||||||
-- Procedure for trg_purchase_receipt_item_after_insert
|
|
||||||
CREATE PROCEDURE process_purchase_item(IN p_receiptId INT, IN p_productId INT, IN p_count DECIMAL(10,2), IN p_unitPrice DECIMAL(15,2), IN p_totalAmount DECIMAL(15,2))
|
|
||||||
BEGIN
|
|
||||||
START TRANSACTION;
|
|
||||||
DECLARE latestQuantity DECIMAL(10, 2) DEFAULT 0;
|
|
||||||
DECLARE invId INT;
|
|
||||||
DECLARE suppId INT;
|
|
||||||
|
|
||||||
-- Get inventory & supplier from
|
|
||||||
SELECT inventoryId, supplierId
|
|
||||||
INTO invId, suppId
|
|
||||||
FROM Purchase_Receipts
|
|
||||||
WHERE id = p_receiptId;
|
|
||||||
|
|
||||||
-- Get current stock quantity (if exists)
|
|
||||||
SELECT COALESCE(quantity, 0)
|
|
||||||
INTO latestQuantity
|
|
||||||
FROM Stock_Balance sb
|
|
||||||
WHERE sb.inventoryId = invId
|
|
||||||
AND sb.productId = p_productId
|
|
||||||
LIMIT 1;
|
|
||||||
|
|
||||||
-- Insert stock movement
|
|
||||||
INSERT INTO Stock_Movements (
|
|
||||||
type,
|
|
||||||
quantity,
|
|
||||||
unitPrice,
|
|
||||||
totalCost,
|
|
||||||
referenceType,
|
|
||||||
referenceId,
|
|
||||||
productId,
|
|
||||||
inventoryId,
|
|
||||||
avgCost,
|
|
||||||
supplierId,
|
|
||||||
remainedInStock,
|
|
||||||
createdAt
|
|
||||||
)
|
|
||||||
VALUES (
|
|
||||||
'IN',
|
|
||||||
p_count,
|
|
||||||
p_unitPrice,
|
|
||||||
p_totalAmount,
|
|
||||||
'PURCHASE',
|
|
||||||
p_receiptId,
|
|
||||||
p_productId,
|
|
||||||
invId,
|
|
||||||
CASE
|
|
||||||
WHEN p_count = 0 THEN 0
|
|
||||||
ELSE p_totalAmount / p_count
|
|
||||||
END,
|
|
||||||
suppId,
|
|
||||||
latestQuantity + p_count,
|
|
||||||
NOW()
|
|
||||||
);
|
|
||||||
COMMIT;
|
|
||||||
END //
|
|
||||||
|
|
||||||
-- Procedure for trg_pr_payment_before_insert
|
|
||||||
CREATE PROCEDURE validate_payment_before_insert(IN p_receiptId INT, IN p_type VARCHAR(20), IN p_amount DECIMAL(15,2))
|
|
||||||
BEGIN
|
|
||||||
START TRANSACTION;
|
|
||||||
DECLARE receiptTotal DECIMAL(14,2);
|
|
||||||
DECLARE paid DECIMAL(14,2);
|
|
||||||
|
|
||||||
SELECT totalAmount, paidAmount
|
|
||||||
INTO receiptTotal, paid
|
|
||||||
FROM Purchase_Receipts
|
|
||||||
WHERE id = p_receiptId
|
|
||||||
FOR UPDATE;
|
|
||||||
|
|
||||||
IF p_type = 'PAYMENT' AND paid + p_amount > receiptTotal THEN
|
|
||||||
SIGNAL SQLSTATE '45000'
|
|
||||||
SET MESSAGE_TEXT = 'مجموع مبلغ پرداختی بیشتر از مبلغ فاکتور است.';
|
|
||||||
END IF;
|
|
||||||
COMMIT;
|
|
||||||
END //
|
|
||||||
|
|
||||||
-- Procedure for trg_purchase_payment_update_receipt
|
|
||||||
CREATE PROCEDURE update_receipt_payment(IN p_receiptId INT)
|
|
||||||
BEGIN
|
|
||||||
START TRANSACTION;
|
|
||||||
DECLARE paid DECIMAL(15,2);
|
|
||||||
DECLARE total DECIMAL(15,2);
|
|
||||||
|
|
||||||
SELECT
|
|
||||||
COALESCE(SUM(
|
|
||||||
CASE WHEN type = 'PAYMENT' THEN amount ELSE -amount END
|
|
||||||
),0)
|
|
||||||
INTO paid
|
|
||||||
FROM Purchase_Receipt_Payments
|
|
||||||
WHERE receiptId = p_receiptId;
|
|
||||||
|
|
||||||
SELECT totalAmount INTO total
|
|
||||||
FROM Purchase_Receipts
|
|
||||||
WHERE id = p_receiptId;
|
|
||||||
|
|
||||||
UPDATE Purchase_Receipts
|
|
||||||
SET
|
|
||||||
paidAmount = paid,
|
|
||||||
status = CASE
|
|
||||||
WHEN paid = 0 THEN 'UNPAID'
|
|
||||||
WHEN paid < total THEN 'PARTIALLY_PAID'
|
|
||||||
ELSE 'PAID'
|
|
||||||
END
|
|
||||||
WHERE id = p_receiptId;
|
|
||||||
COMMIT;
|
|
||||||
END //
|
|
||||||
|
|
||||||
-- Procedure for trg_purchase_payment_after_insert
|
|
||||||
CREATE PROCEDURE process_purchase_payment(IN p_bankAccountId INT, IN p_type VARCHAR(20), IN p_amount DECIMAL(15,2), IN p_id INT)
|
|
||||||
BEGIN
|
|
||||||
START TRANSACTION;
|
|
||||||
DECLARE currentBalance DECIMAL(15, 2);
|
|
||||||
|
|
||||||
SELECT balance INTO currentBalance
|
|
||||||
FROM Bank_Account_Balance
|
|
||||||
WHERE bankAccountId = p_bankAccountId FOR UPDATE;
|
|
||||||
|
|
||||||
IF currentBalance IS NULL THEN SET currentBalance = 0;
|
|
||||||
INSERT INTO Bank_Account_Balance (bankAccountId, balance, updatedAt)
|
|
||||||
VALUES (p_bankAccountId, 0, NOW());
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
IF p_type = 'PAYMENT' THEN
|
|
||||||
SET currentBalance = currentBalance - p_amount;
|
|
||||||
INSERT INTO Bank_Account_Transactions (
|
|
||||||
bankAccountId,
|
|
||||||
type,
|
|
||||||
amount,
|
|
||||||
balanceAfter,
|
|
||||||
referenceType,
|
|
||||||
referenceId
|
|
||||||
)
|
|
||||||
VALUES (
|
|
||||||
p_bankAccountId,
|
|
||||||
'WITHDRAWAL',
|
|
||||||
p_amount,
|
|
||||||
currentBalance,
|
|
||||||
'PURCHASE_PAYMENT',
|
|
||||||
p_id
|
|
||||||
);
|
|
||||||
ELSE
|
|
||||||
SET currentBalance = currentBalance + p_amount;
|
|
||||||
INSERT INTO Bank_Account_Transactions (
|
|
||||||
bankAccountId,
|
|
||||||
type,
|
|
||||||
amount,
|
|
||||||
balanceAfter,
|
|
||||||
referenceType,
|
|
||||||
referenceId
|
|
||||||
)
|
|
||||||
VALUES (
|
|
||||||
p_bankAccountId,
|
|
||||||
'DEPOSIT',
|
|
||||||
p_amount,
|
|
||||||
currentBalance,
|
|
||||||
'PURCHASE_REFUND',
|
|
||||||
p_id
|
|
||||||
);
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
UPDATE Bank_Account_Balance
|
|
||||||
SET balance = currentBalance
|
|
||||||
WHERE bankAccountId = p_bankAccountId;
|
|
||||||
COMMIT;
|
|
||||||
END //
|
|
||||||
|
|
||||||
-- Procedure for trg_pr_payment_after_insert
|
|
||||||
CREATE PROCEDURE update_supplier_ledger(IN p_receiptId INT, IN p_type VARCHAR(20), IN p_amount DECIMAL(15,2), IN p_id INT)
|
|
||||||
BEGIN
|
|
||||||
START TRANSACTION;
|
|
||||||
DECLARE receiptTotal DECIMAL(14,2) DEFAULT 0;
|
|
||||||
DECLARE newPaid DECIMAL(14,2) DEFAULT 0;
|
|
||||||
DECLARE _supplierId INT;
|
|
||||||
DECLARE lastBalance DECIMAL(14,2) DEFAULT 0;
|
|
||||||
|
|
||||||
-- Lock receipt row
|
|
||||||
SELECT COALESCE(totalAmount, 0), COALESCE(paidAmount, 0), supplierId
|
|
||||||
INTO receiptTotal, newPaid, _supplierId
|
|
||||||
FROM Purchase_Receipts
|
|
||||||
WHERE id = p_receiptId
|
|
||||||
FOR UPDATE;
|
|
||||||
|
|
||||||
-- Apply payment or refund
|
|
||||||
IF p_type = 'PAYMENT' THEN
|
|
||||||
SET newPaid = newPaid + p_amount;
|
|
||||||
ELSE
|
|
||||||
SET newPaid = newPaid - p_amount;
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
-- Update receipt
|
|
||||||
UPDATE Purchase_Receipts
|
|
||||||
SET
|
|
||||||
paidAmount = newPaid,
|
|
||||||
status =
|
|
||||||
CASE
|
|
||||||
WHEN newPaid = 0 THEN 'UNPAID'
|
|
||||||
WHEN newPaid < receiptTotal THEN 'PARTIALLY_PAID'
|
|
||||||
ELSE 'PAID'
|
|
||||||
END
|
|
||||||
WHERE id = p_receiptId;
|
|
||||||
|
|
||||||
-- Get last supplier balance
|
|
||||||
SELECT IFNULL(balance, 0)
|
|
||||||
INTO lastBalance
|
|
||||||
FROM Supplier_Ledger
|
|
||||||
WHERE supplierId = _supplierId
|
|
||||||
ORDER BY id DESC
|
|
||||||
LIMIT 1;
|
|
||||||
|
|
||||||
-- Insert supplier ledger
|
|
||||||
INSERT INTO Supplier_Ledger
|
|
||||||
(
|
|
||||||
supplierId,
|
|
||||||
debit,
|
|
||||||
credit,
|
|
||||||
balance,
|
|
||||||
sourceType,
|
|
||||||
sourceId,
|
|
||||||
createdAt
|
|
||||||
)
|
|
||||||
VALUES
|
|
||||||
(
|
|
||||||
_supplierId,
|
|
||||||
IF(p_type = 'REFUND', p_amount, 0),
|
|
||||||
IF(p_type = 'PAYMENT', p_amount, 0),
|
|
||||||
lastBalance
|
|
||||||
+ IF(p_type = 'PAYMENT', p_amount, 0)
|
|
||||||
- IF(p_type = 'REFUND', p_amount, 0),
|
|
||||||
'PAYMENT',
|
|
||||||
p_id,
|
|
||||||
NOW()
|
|
||||||
);
|
|
||||||
COMMIT;
|
|
||||||
END //
|
|
||||||
|
|
||||||
-- Procedure for trg_pr_payment_after_delete
|
|
||||||
CREATE PROCEDURE update_receipt_on_payment_delete(IN p_receiptId INT, IN p_type VARCHAR(20), IN p_amount DECIMAL(15,2))
|
|
||||||
BEGIN
|
|
||||||
DECLARE receiptTotal DECIMAL(14,2);
|
|
||||||
DECLARE newPaid DECIMAL(14,2);
|
|
||||||
|
|
||||||
SELECT totalAmount, paidAmount
|
|
||||||
INTO receiptTotal, newPaid
|
|
||||||
FROM Purchase_Receipts
|
|
||||||
WHERE id = p_receiptId
|
|
||||||
FOR UPDATE;
|
|
||||||
|
|
||||||
IF p_type = 'PAYMENT' THEN
|
|
||||||
SET newPaid = newPaid - p_amount;
|
|
||||||
ELSE
|
|
||||||
SET newPaid = newPaid + p_amount;
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
UPDATE Purchase_Receipts
|
|
||||||
SET
|
|
||||||
paidAmount = newPaid,
|
|
||||||
status =
|
|
||||||
CASE
|
|
||||||
WHEN newPaid = 0 THEN 'UNPAID'
|
|
||||||
WHEN newPaid < receiptTotal THEN 'PARTIALLY_PAID'
|
|
||||||
ELSE 'PAID'
|
|
||||||
END
|
|
||||||
WHERE id = p_receiptId;
|
|
||||||
END //
|
|
||||||
|
|
||||||
-- Procedure for trg_purchase_receipt_after_insert
|
|
||||||
CREATE PROCEDURE insert_supplier_ledger_purchase(IN p_supplierId INT, IN p_totalAmount DECIMAL(15,2), IN p_id INT)
|
|
||||||
BEGIN
|
|
||||||
DECLARE lastBalance DECIMAL(14,2) DEFAULT 0;
|
|
||||||
|
|
||||||
SELECT COALESCE(balance, 0)
|
|
||||||
INTO lastBalance
|
|
||||||
FROM Supplier_Ledger
|
|
||||||
WHERE supplierId = p_supplierId
|
|
||||||
ORDER BY id DESC
|
|
||||||
LIMIT 1;
|
|
||||||
|
|
||||||
INSERT INTO Supplier_Ledger
|
|
||||||
(
|
|
||||||
supplierId,
|
|
||||||
debit,
|
|
||||||
credit,
|
|
||||||
balance,
|
|
||||||
sourceType,
|
|
||||||
sourceId,
|
|
||||||
createdAt
|
|
||||||
)
|
|
||||||
VALUES
|
|
||||||
(
|
|
||||||
p_supplierId,
|
|
||||||
p_totalAmount,
|
|
||||||
0,
|
|
||||||
lastBalance - p_totalAmount,
|
|
||||||
'PURCHASE',
|
|
||||||
p_id,
|
|
||||||
NOW()
|
|
||||||
);
|
|
||||||
END //
|
|
||||||
|
|
||||||
-- Procedure for trg_sales_invoice_items_before_insert
|
|
||||||
CREATE PROCEDURE validate_stock_before_sale(IN p_invoiceId INT, IN p_productId INT, IN p_count DECIMAL(10,2))
|
|
||||||
BEGIN
|
|
||||||
DECLARE current_stock DECIMAL(10, 2);
|
|
||||||
DECLARE inventory_id INT;
|
|
||||||
|
|
||||||
SELECT pa.inventoryId INTO inventory_id
|
|
||||||
FROM Pos_Accounts pa
|
|
||||||
INNER JOIN Sales_Invoices si ON pa.id = si.posAccountId
|
|
||||||
WHERE si.id = p_invoiceId;
|
|
||||||
|
|
||||||
SELECT COALESCE(quantity, 0) INTO current_stock
|
|
||||||
FROM Stock_Balance sb
|
|
||||||
WHERE productId = p_productId AND sb.inventoryId = inventory_id
|
|
||||||
LIMIT 1;
|
|
||||||
|
|
||||||
IF p_count > current_stock THEN
|
|
||||||
SIGNAL SQLSTATE '45000'
|
|
||||||
SET MESSAGE_TEXT = 'موجودی کالا در انبار کافی نیست.';
|
|
||||||
END IF;
|
|
||||||
END //
|
|
||||||
|
|
||||||
-- Procedure for trg_sales_invoice_items_after_insert
|
|
||||||
CREATE PROCEDURE process_sale_item(IN p_invoiceId INT, IN p_productId INT, IN p_count DECIMAL(10,2), IN p_unitPrice DECIMAL(15,2), IN p_totalAmount DECIMAL(15,2))
|
|
||||||
BEGIN
|
|
||||||
DECLARE current_stock DECIMAL(10, 2);
|
|
||||||
DECLARE inventory_id INT;
|
|
||||||
DECLARE customer_id INT;
|
|
||||||
DECLARE pos_id INT;
|
|
||||||
|
|
||||||
SELECT posAccountId, customerId INTO pos_id, customer_id
|
|
||||||
FROM Sales_Invoices si
|
|
||||||
WHERE si.id = p_invoiceId
|
|
||||||
LIMIT 1;
|
|
||||||
|
|
||||||
SELECT pa.inventoryId INTO inventory_id
|
|
||||||
FROM Pos_Accounts pa
|
|
||||||
INNER JOIN Sales_Invoices si ON pa.id = si.posAccountId
|
|
||||||
WHERE si.id = p_invoiceId;
|
|
||||||
|
|
||||||
SELECT COALESCE(quantity, 0) INTO current_stock
|
|
||||||
FROM Stock_Balance sb
|
|
||||||
WHERE productId = p_productId AND sb.inventoryId = inventory_id
|
|
||||||
LIMIT 1;
|
|
||||||
|
|
||||||
INSERT INTO Stock_Movements (
|
|
||||||
type,
|
|
||||||
quantity,
|
|
||||||
unitPrice,
|
|
||||||
totalCost,
|
|
||||||
referenceType,
|
|
||||||
referenceId,
|
|
||||||
productId,
|
|
||||||
inventoryId,
|
|
||||||
avgCost,
|
|
||||||
remainedInStock,
|
|
||||||
customerId,
|
|
||||||
createdAt
|
|
||||||
)
|
|
||||||
VALUES (
|
|
||||||
'OUT',
|
|
||||||
p_count,
|
|
||||||
p_unitPrice,
|
|
||||||
p_totalAmount,
|
|
||||||
'SALES',
|
|
||||||
p_invoiceId,
|
|
||||||
p_productId,
|
|
||||||
inventory_id,
|
|
||||||
CASE
|
|
||||||
WHEN p_count = 0 THEN 0
|
|
||||||
ELSE p_totalAmount / p_count
|
|
||||||
END,
|
|
||||||
current_stock - p_count,
|
|
||||||
customer_id,
|
|
||||||
NOW()
|
|
||||||
);
|
|
||||||
END //
|
|
||||||
|
|
||||||
-- Procedure for trg_sales_invoice_payment_after_insert
|
|
||||||
CREATE PROCEDURE process_sale_payment(IN p_invoiceId INT, IN p_amount DECIMAL(15,2), IN p_id INT)
|
|
||||||
BEGIN
|
|
||||||
DECLARE currentBalance DECIMAL(15,2);
|
|
||||||
DECLARE bankAccountId INT;
|
|
||||||
|
|
||||||
SELECT pa.bankAccountId INTO bankAccountId
|
|
||||||
FROM Pos_Accounts pa
|
|
||||||
INNER JOIN Sales_Invoices si ON pa.id = si.posAccountId
|
|
||||||
WHERE si.id = p_invoiceId;
|
|
||||||
|
|
||||||
SELECT balance INTO currentBalance
|
|
||||||
FROM Bank_Account_Balance
|
|
||||||
WHERE bankAccountId = bankAccountId
|
|
||||||
FOR UPDATE;
|
|
||||||
|
|
||||||
IF currentBalance IS NULL THEN
|
|
||||||
SET currentBalance = 0;
|
|
||||||
INSERT INTO Bank_Account_Balance (bankAccountId, balance, updatedAt)
|
|
||||||
VALUES (bankAccountId, 0, NOW());
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
SET currentBalance = currentBalance + p_amount;
|
|
||||||
|
|
||||||
INSERT INTO Bank_Account_Transactions
|
|
||||||
(bankAccountId, type, amount, balanceAfter, referenceType, referenceId)
|
|
||||||
VALUES
|
|
||||||
(bankAccountId, 'DEPOSIT', p_amount, currentBalance, 'POS_SALE', p_id);
|
|
||||||
|
|
||||||
UPDATE Bank_Account_Balance
|
|
||||||
SET balance = currentBalance
|
|
||||||
WHERE bankAccountId = bankAccountId;
|
|
||||||
END //
|
|
||||||
|
|
||||||
-- Procedure for trg_pos_account_payment_after_insert
|
|
||||||
CREATE PROCEDURE process_pos_payment(IN p_invoiceId INT, IN p_paymentMethod VARCHAR(20), IN p_amount DECIMAL(15,2), IN p_id INT)
|
|
||||||
BEGIN
|
|
||||||
DECLARE _bankAccountId INT;
|
|
||||||
|
|
||||||
IF(p_paymentMethod != 'CASH') THEN
|
|
||||||
SELECT cashBankAccountId INTO _bankAccountId
|
|
||||||
FROM Pos_Accounts pa
|
|
||||||
INNER JOIN Sales_Invoices si ON pa.id = si.posAccountId
|
|
||||||
WHERE si.id = p_invoiceId;
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
INSERT INTO Bank_Account_Transactions (
|
|
||||||
bankAccountId,
|
|
||||||
type,
|
|
||||||
amount,
|
|
||||||
balanceAfter,
|
|
||||||
referenceType,
|
|
||||||
referenceId
|
|
||||||
)
|
|
||||||
VALUES(
|
|
||||||
_bankAccountId,
|
|
||||||
'DEPOSIT',
|
|
||||||
p_amount,
|
|
||||||
0,
|
|
||||||
'POS_SALE',
|
|
||||||
p_id
|
|
||||||
);
|
|
||||||
END //
|
|
||||||
|
|
||||||
-- Procedure for trg_stock_transfer
|
|
||||||
CREATE PROCEDURE update_stock_balance_transfer(IN p_productId INT, IN p_inventoryId INT, IN p_quantity DECIMAL(10,2), IN p_unitPrice DECIMAL(15,2), IN p_totalCost DECIMAL(15,2), IN p_type VARCHAR(10))
|
|
||||||
BEGIN
|
|
||||||
IF p_type = 'IN' THEN
|
|
||||||
INSERT INTO Stock_Balance (
|
|
||||||
productId,
|
|
||||||
inventoryId,
|
|
||||||
quantity,
|
|
||||||
totalCost,
|
|
||||||
avgCost,
|
|
||||||
updatedAt
|
|
||||||
)
|
|
||||||
VALUES (
|
|
||||||
p_productId,
|
|
||||||
p_inventoryId,
|
|
||||||
p_quantity,
|
|
||||||
p_totalCost,
|
|
||||||
CASE
|
|
||||||
WHEN p_quantity = 0 THEN 0
|
|
||||||
ELSE p_totalCost / p_quantity
|
|
||||||
END,
|
|
||||||
NOW()
|
|
||||||
)
|
|
||||||
ON DUPLICATE KEY UPDATE
|
|
||||||
quantity = quantity + p_quantity,
|
|
||||||
totalCost = totalCost + p_totalCost,
|
|
||||||
avgCost = CASE
|
|
||||||
WHEN (quantity + p_quantity) = 0 THEN 0
|
|
||||||
ELSE (totalCost + p_totalCost) / (quantity + p_quantity)
|
|
||||||
END,
|
|
||||||
updatedAt = NOW();
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
IF p_type = 'OUT' THEN
|
|
||||||
IF EXISTS (
|
|
||||||
SELECT 1
|
|
||||||
FROM Stock_Balance sb
|
|
||||||
WHERE sb.productId = p_productId AND sb.inventoryId = p_inventoryId
|
|
||||||
) THEN
|
|
||||||
UPDATE Stock_Balance sb
|
|
||||||
SET
|
|
||||||
sb.quantity = sb.quantity - p_quantity,
|
|
||||||
sb.totalCost = sb.totalCost - (sb.avgCost * p_quantity),
|
|
||||||
sb.updatedAt = NOW()
|
|
||||||
WHERE
|
|
||||||
sb.productId = p_productId
|
|
||||||
AND sb.inventoryId = p_inventoryId;
|
|
||||||
ELSE
|
|
||||||
INSERT INTO Stock_Balance (
|
|
||||||
productId,
|
|
||||||
inventoryId,
|
|
||||||
quantity,
|
|
||||||
totalCost,
|
|
||||||
avgCost,
|
|
||||||
updatedAt
|
|
||||||
)
|
|
||||||
VALUES (
|
|
||||||
p_productId,
|
|
||||||
p_inventoryId,
|
|
||||||
- p_quantity,
|
|
||||||
- COALESCE(p_unitPrice, 0) * p_quantity,
|
|
||||||
COALESCE(p_unitPrice, 0),
|
|
||||||
NOW()
|
|
||||||
);
|
|
||||||
END IF;
|
|
||||||
END IF;
|
|
||||||
END //
|
|
||||||
|
|
||||||
-- Procedure for trg_stock_purchase_insert
|
|
||||||
CREATE PROCEDURE update_stock_balance_purchase(IN p_productId INT, IN p_quantity DECIMAL(10,2), IN p_unitPrice DECIMAL(15,2), IN p_totalCost DECIMAL(15,2), IN p_inventoryId INT)
|
|
||||||
BEGIN
|
|
||||||
INSERT INTO Stock_Balance (
|
|
||||||
productId,
|
|
||||||
quantity,
|
|
||||||
avgCost,
|
|
||||||
totalCost,
|
|
||||||
inventoryId,
|
|
||||||
updatedAt
|
|
||||||
)
|
|
||||||
VALUES (
|
|
||||||
p_productId,
|
|
||||||
p_quantity,
|
|
||||||
p_unitPrice,
|
|
||||||
p_totalCost,
|
|
||||||
p_inventoryId,
|
|
||||||
NOW()
|
|
||||||
)
|
|
||||||
ON DUPLICATE KEY UPDATE
|
|
||||||
quantity = quantity + p_quantity,
|
|
||||||
totalCost = totalCost + p_totalCost,
|
|
||||||
avgCost = totalCost / quantity;
|
|
||||||
END //
|
|
||||||
|
|
||||||
-- Procedure for trg_stock_sale_insert
|
|
||||||
CREATE PROCEDURE update_stock_balance_sale(IN p_productId INT, IN p_quantity DECIMAL(10,2), IN p_unitPrice DECIMAL(15,2), IN p_totalCost DECIMAL(15,2), IN p_inventoryId INT)
|
|
||||||
BEGIN
|
|
||||||
INSERT INTO Stock_Balance (
|
|
||||||
productId,
|
|
||||||
quantity,
|
|
||||||
avgCost,
|
|
||||||
totalCost,
|
|
||||||
inventoryId,
|
|
||||||
updatedAt
|
|
||||||
)
|
|
||||||
VALUES (
|
|
||||||
p_productId,
|
|
||||||
p_quantity,
|
|
||||||
p_unitPrice,
|
|
||||||
p_totalCost,
|
|
||||||
p_inventoryId,
|
|
||||||
NOW()
|
|
||||||
)
|
|
||||||
ON DUPLICATE KEY UPDATE
|
|
||||||
quantity = quantity - p_quantity,
|
|
||||||
totalCost = totalCost - p_totalCost,
|
|
||||||
avgCost = totalCost / quantity;
|
|
||||||
END //
|
|
||||||
|
|
||||||
DELIMITER;
|
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
/// <reference types="multer" />
|
||||||
|
|
||||||
import { AccessTokenPayload, IConsumerPayload, IPosPayload } from '@/common/models'
|
import { AccessTokenPayload, IConsumerPayload, IPosPayload } from '@/common/models'
|
||||||
import { IPartnerPayload } from '@/common/models/partnerPayload.model'
|
import { IPartnerPayload } from '@/common/models/partnerPayload.model'
|
||||||
|
|
||||||
|
|||||||
@@ -1,66 +1,65 @@
|
|||||||
#!/usr/bin/env ts-node
|
// #!/usr/bin/env ts-node
|
||||||
import * as fs from 'fs'
|
// import * as fs from 'fs'
|
||||||
import * as path from 'path'
|
// import * as path from 'path'
|
||||||
import { prisma } from '../src/lib/prisma'
|
|
||||||
|
|
||||||
function findModules(dir: string): string[] {
|
// function findModules(dir: string): string[] {
|
||||||
const results: string[] = []
|
// const results: string[] = []
|
||||||
const entries = fs.readdirSync(dir, { withFileTypes: true })
|
// const entries = fs.readdirSync(dir, { withFileTypes: true })
|
||||||
for (const e of entries) {
|
// for (const e of entries) {
|
||||||
const full = path.join(dir, e.name)
|
// const full = path.join(dir, e.name)
|
||||||
if (e.isDirectory()) {
|
// if (e.isDirectory()) {
|
||||||
results.push(...findModules(full))
|
// results.push(...findModules(full))
|
||||||
} else if (e.isFile() && e.name.endsWith('.module.ts')) {
|
// } else if (e.isFile() && e.name.endsWith('.module.ts')) {
|
||||||
results.push(full)
|
// results.push(full)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
return results
|
// return results
|
||||||
}
|
// }
|
||||||
|
|
||||||
function moduleNameFromFile(filePath: string) {
|
// function moduleNameFromFile(filePath: string) {
|
||||||
const name = path.basename(filePath).replace('.module.ts', '')
|
// const name = path.basename(filePath).replace('.module.ts', '')
|
||||||
return name.replace(/-module$|\.module$/i, '')
|
// return name.replace(/-module$|\.module$/i, '')
|
||||||
}
|
// }
|
||||||
|
|
||||||
function makePermissionsFor(moduleName: string) {
|
// function makePermissionsFor(moduleName: string) {
|
||||||
const base = moduleName.replace(/\W+/g, '_').toLowerCase()
|
// const base = moduleName.replace(/\W+/g, '_').toLowerCase()
|
||||||
return [`${base}:create`, `${base}:read`, `${base}:update`, `${base}:delete`]
|
// return [`${base}:create`, `${base}:read`, `${base}:update`, `${base}:delete`]
|
||||||
}
|
// }
|
||||||
|
|
||||||
async function main() {
|
// async function main() {
|
||||||
// const srcDir = path.resolve(__dirname, '..', 'src')
|
// // const srcDir = path.resolve(__dirname, '..', 'src')
|
||||||
// const moduleFiles = findModules(srcDir)
|
// // const moduleFiles = findModules(srcDir)
|
||||||
// const modules = moduleFiles.map(moduleNameFromFile)
|
// // const modules = moduleFiles.map(moduleNameFromFile)
|
||||||
|
|
||||||
// const permsMap: Record<string, boolean> = {}
|
// // const permsMap: Record<string, boolean> = {}
|
||||||
// for (const m of modules) {
|
// // for (const m of modules) {
|
||||||
// for (const p of makePermissionsFor(m)) permsMap[p] = false
|
// // for (const p of makePermissionsFor(m)) permsMap[p] = false
|
||||||
// }
|
// // }
|
||||||
|
|
||||||
// // Upsert roles: ensure admin has full permissions, others get entries added
|
// // // Upsert roles: ensure admin has full permissions, others get entries added
|
||||||
// const roles = await prisma.role.findMany()
|
// // const roles = await prisma.role.findMany()
|
||||||
// for (const r of roles) {
|
// // for (const r of roles) {
|
||||||
// const current: Record<string, any> = (r.permissions as any) || {}
|
// // const current: Record<string, any> = (r.permissions as any) || {}
|
||||||
// const merged = { ...permsMap, ...current }
|
// // const merged = { ...permsMap, ...current }
|
||||||
|
|
||||||
// // If role name is admin (case-insensitive), set all permissions to true
|
// // // If role name is admin (case-insensitive), set all permissions to true
|
||||||
// if (r.name && r.name.toLowerCase() === 'admin') {
|
// // if (r.name && r.name.toLowerCase() === 'admin') {
|
||||||
// for (const key of Object.keys(merged)) merged[key] = true
|
// // for (const key of Object.keys(merged)) merged[key] = true
|
||||||
// } else {
|
// // } else {
|
||||||
// // keep existing truthy values, otherwise false
|
// // // keep existing truthy values, otherwise false
|
||||||
// for (const key of Object.keys(merged)) merged[key] = merged[key] || false
|
// // for (const key of Object.keys(merged)) merged[key] = merged[key] || false
|
||||||
// }
|
// // }
|
||||||
|
|
||||||
// await prisma.role.update({ where: { id: r.id }, data: { permissions: merged } })
|
// // await prisma.role.update({ where: { id: r.id }, data: { permissions: merged } })
|
||||||
// console.log(
|
// // console.log(
|
||||||
// `Updated role ${r.name} (id=${r.id}) with ${Object.keys(merged).length} permissions`,
|
// // `Updated role ${r.name} (id=${r.id}) with ${Object.keys(merged).length} permissions`,
|
||||||
// )
|
// // )
|
||||||
// }
|
// // }
|
||||||
|
|
||||||
await prisma.$disconnect()
|
// await prisma.$disconnect()
|
||||||
}
|
// }
|
||||||
|
|
||||||
main().catch(e => {
|
// main().catch(e => {
|
||||||
console.error(e)
|
// console.error(e)
|
||||||
process.exit(1)
|
// process.exit(1)
|
||||||
})
|
// })
|
||||||
|
|||||||
@@ -0,0 +1,143 @@
|
|||||||
|
// import fs from 'node:fs'
|
||||||
|
// import path from 'node:path'
|
||||||
|
|
||||||
|
// type CsvRow = {
|
||||||
|
// ID?: string
|
||||||
|
// DescriptionOfID?: string
|
||||||
|
// Vat?: string
|
||||||
|
// Type?: string
|
||||||
|
// }
|
||||||
|
|
||||||
|
// function parseCsvLine(line: string): string[] {
|
||||||
|
// const result: string[] = []
|
||||||
|
// let current = ''
|
||||||
|
// let inQuotes = false
|
||||||
|
|
||||||
|
// for (let index = 0; index < line.length; index++) {
|
||||||
|
// const char = line[index]
|
||||||
|
|
||||||
|
// if (char === '"') {
|
||||||
|
// if (inQuotes && line[index + 1] === '"') {
|
||||||
|
// current += '"'
|
||||||
|
// index++
|
||||||
|
// } else {
|
||||||
|
// inQuotes = !inQuotes
|
||||||
|
// }
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (char === ',' && !inQuotes) {
|
||||||
|
// result.push(current)
|
||||||
|
// current = ''
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
|
|
||||||
|
// current += char
|
||||||
|
// }
|
||||||
|
|
||||||
|
// result.push(current)
|
||||||
|
// return result.map(value => value.trim())
|
||||||
|
// }
|
||||||
|
|
||||||
|
// function parseCsv(content: string): CsvRow[] {
|
||||||
|
// const lines = content
|
||||||
|
// .split(/\r?\n/)
|
||||||
|
// .map(line => line.trim())
|
||||||
|
// .filter(Boolean)
|
||||||
|
|
||||||
|
// if (!lines.length) return []
|
||||||
|
|
||||||
|
// const headers = parseCsvLine(lines[0])
|
||||||
|
// return lines.slice(1).map(line => {
|
||||||
|
// const cols = parseCsvLine(line)
|
||||||
|
// const row: Record<string, string> = {}
|
||||||
|
// for (let index = 0; index < headers.length; index++) {
|
||||||
|
// row[headers[index]] = cols[index] || ''
|
||||||
|
// }
|
||||||
|
// return row
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
|
||||||
|
// function toBooleanFlags(typeValue: string) {
|
||||||
|
// const normalized = typeValue || ''
|
||||||
|
// const isPublic = normalized.includes('شناسه عمومی')
|
||||||
|
// const isImported = normalized.includes('وارداتی')
|
||||||
|
// const isDomestic = !isImported
|
||||||
|
|
||||||
|
// return { isPublic, isDomestic }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// function parseVat(vatValue: string) {
|
||||||
|
// const parsed = Number(vatValue || '0')
|
||||||
|
// if (!Number.isFinite(parsed)) return 0
|
||||||
|
// return parsed
|
||||||
|
// }
|
||||||
|
|
||||||
|
// async function main() {
|
||||||
|
// const defaultPath =
|
||||||
|
// '/Users/ahasani/Desktop/product_good_2026-05-01T11-35-57_part_1_28812448-0dd9-411c-99e1-334c28d781fe.csv'
|
||||||
|
// const csvPath = process.argv[2] || defaultPath
|
||||||
|
// const absolutePath = path.resolve(csvPath)
|
||||||
|
|
||||||
|
// if (!fs.existsSync(absolutePath)) {
|
||||||
|
// throw new Error(`CSV file not found: ${absolutePath}`)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const raw = fs.readFileSync(absolutePath, 'utf8').replace(/^\uFEFF/, '')
|
||||||
|
// const rows = parseCsv(raw)
|
||||||
|
|
||||||
|
// let upserted = 0
|
||||||
|
// let skipped = 0
|
||||||
|
|
||||||
|
// const guild = await prisma.guild.findFirst({})
|
||||||
|
|
||||||
|
// for (const row of rows) {
|
||||||
|
// const code = (row.ID || '').trim()
|
||||||
|
// const name = (row.DescriptionOfID || '').trim()
|
||||||
|
// const vat = parseVat((row.Vat || '').trim())
|
||||||
|
// const type = (row.Type || '').trim()
|
||||||
|
// const { isPublic, isDomestic } = toBooleanFlags(type)
|
||||||
|
|
||||||
|
// if (!code || !name) {
|
||||||
|
// skipped++
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
|
|
||||||
|
// await prisma.stockKeepingUnits.upsert({
|
||||||
|
// where: { code },
|
||||||
|
// create: {
|
||||||
|
// code,
|
||||||
|
// name,
|
||||||
|
// VAT: vat,
|
||||||
|
// guild: {
|
||||||
|
// connect: {
|
||||||
|
// id: guild?.id,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// is_public: isPublic,
|
||||||
|
// is_domestic: isDomestic,
|
||||||
|
// },
|
||||||
|
// update: {
|
||||||
|
// name,
|
||||||
|
// VAT: vat,
|
||||||
|
// guild: {
|
||||||
|
// connect: {
|
||||||
|
// id: guild?.id,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// is_public: isPublic,
|
||||||
|
// is_domestic: isDomestic,
|
||||||
|
// },
|
||||||
|
// })
|
||||||
|
// upserted++
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// main()
|
||||||
|
// .catch(error => {
|
||||||
|
// console.error(error)
|
||||||
|
// process.exit(1)
|
||||||
|
// })
|
||||||
|
// .finally(async () => {
|
||||||
|
// await prisma.$disconnect()
|
||||||
|
// })
|
||||||
+5
-7
@@ -7,27 +7,25 @@ import { AuthModule } from './modules/auth/auth.module'
|
|||||||
import { CatalogModule } from './modules/catalog/catalog.module'
|
import { CatalogModule } from './modules/catalog/catalog.module'
|
||||||
import { ConsumerModule } from './modules/consumer/consumer.module'
|
import { ConsumerModule } from './modules/consumer/consumer.module'
|
||||||
import { EnumsModule } from './modules/enums/enums.module'
|
import { EnumsModule } from './modules/enums/enums.module'
|
||||||
|
import { PublicInvoicesModule } from './modules/invoices/invoices.module'
|
||||||
import { PartnerModule } from './modules/partners/partners.module'
|
import { PartnerModule } from './modules/partners/partners.module'
|
||||||
import { PosModule } from './modules/pos/pos.module'
|
import { PosModule } from './modules/pos/pos.module'
|
||||||
import { SalesInvoiceItemsModule } from './modules/pos/sales-invoices/sales-invoice-items/sales-invoice-items.module'
|
|
||||||
import { SalesInvoicePaymentsModule } from './modules/pos/sales-invoices/sales-invoice-payments/sales-invoice-payments.module'
|
|
||||||
import { TriggerLogsModule } from './modules/trigger-logs/trigger-logs.module'
|
|
||||||
import { UploaderModule } from './modules/uploader/uploader.module'
|
import { UploaderModule } from './modules/uploader/uploader.module'
|
||||||
import { PrismaModule } from './prisma/prisma.module'
|
import { PrismaModule } from './prisma/prisma.module'
|
||||||
|
import { RedisModule } from './redis/redis.module'
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
PrismaModule,
|
PrismaModule,
|
||||||
|
RedisModule,
|
||||||
EnumsModule,
|
EnumsModule,
|
||||||
AdminModule,
|
AdminModule,
|
||||||
|
AuthModule,
|
||||||
CatalogModule,
|
CatalogModule,
|
||||||
ConsumerModule,
|
ConsumerModule,
|
||||||
PosModule,
|
PosModule,
|
||||||
PartnerModule,
|
PartnerModule,
|
||||||
AuthModule,
|
PublicInvoicesModule,
|
||||||
SalesInvoiceItemsModule,
|
|
||||||
SalesInvoicePaymentsModule,
|
|
||||||
TriggerLogsModule,
|
|
||||||
UploaderModule,
|
UploaderModule,
|
||||||
ApplicationModule,
|
ApplicationModule,
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,14 +1,187 @@
|
|||||||
|
import {
|
||||||
|
InvoiceSettlementType,
|
||||||
|
TspProviderRequestType,
|
||||||
|
TspProviderResponseStatus,
|
||||||
|
} from '@/generated/prisma/enums'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
PaymentMethodType: {
|
||||||
|
TERMINAL: 'ترمینال',
|
||||||
|
CASH: 'نقدی',
|
||||||
|
SET_OFF: 'تهاتر',
|
||||||
|
CARD: 'کارت',
|
||||||
|
BANK: 'بانکی',
|
||||||
|
CHECK: 'چک',
|
||||||
|
OTHER: 'سایر',
|
||||||
|
},
|
||||||
|
UnitType: {
|
||||||
COUNT: 'تعداد',
|
COUNT: 'تعداد',
|
||||||
GRAM: 'گرم',
|
GRAM: 'گرم',
|
||||||
KILO_GRAM: 'کیلوگرم',
|
KILOGRAM: 'کیلوگرم',
|
||||||
LITER: 'لیتر',
|
LITER: 'لیتر',
|
||||||
MILLILITER: 'میلیلیتر',
|
MILLILITER: 'میلیلیتر',
|
||||||
STANDARD: 'استاندارد',
|
METER: 'متر',
|
||||||
|
HOUR: 'ساعت',
|
||||||
|
},
|
||||||
|
GoodPricingModel: {
|
||||||
|
STANDARD: 'عمومی',
|
||||||
GOLD: 'طلا',
|
GOLD: 'طلا',
|
||||||
|
},
|
||||||
|
CustomerType: {
|
||||||
|
INDIVIDUAL: 'حقیقی',
|
||||||
|
LEGAL: 'حقوقی',
|
||||||
|
UNKNOWN: 'نامشخص',
|
||||||
|
},
|
||||||
|
POSStatus: {
|
||||||
|
ACTIVE: 'فعال',
|
||||||
|
DISABLED: 'غیرفعال',
|
||||||
|
},
|
||||||
|
POSRole: {
|
||||||
|
MANAGER: 'مدیریت',
|
||||||
|
OPERATOR: 'اپراتور',
|
||||||
|
},
|
||||||
|
LicenseType: {
|
||||||
|
BASIC: 'پایه',
|
||||||
|
PRO: 'حرفهای',
|
||||||
|
ENTERPRISE: 'سازمانی',
|
||||||
|
},
|
||||||
|
LicenseStatus: {
|
||||||
|
ACTIVE: 'فعال',
|
||||||
|
EXPIRED: 'منقضی',
|
||||||
|
SUSPENDED: 'غیرفعال',
|
||||||
|
},
|
||||||
|
POSType: {
|
||||||
|
PSP: 'PSP',
|
||||||
|
MOBILE: 'موبایل',
|
||||||
|
WEB: 'وب',
|
||||||
|
API: 'API',
|
||||||
|
},
|
||||||
|
UserType: {
|
||||||
|
LEGAL: 'حقوقی',
|
||||||
|
INDIVIDUAL: 'حقیقی',
|
||||||
|
},
|
||||||
|
AccountType: {
|
||||||
|
ADMIN: 'مدیر سیستم',
|
||||||
|
PROVIDER: 'ارائهدهنده خدمات',
|
||||||
|
PARTNER: 'شریک تجاری',
|
||||||
|
CONSUMER: 'مصرفکننده',
|
||||||
|
},
|
||||||
|
UserStatus: {
|
||||||
|
ACTIVE: 'فعال',
|
||||||
|
INACTIVE: 'غیرفعال',
|
||||||
|
},
|
||||||
|
AccountRole: {
|
||||||
|
OWNER: 'مدیر اصلی',
|
||||||
|
OPERATOR: 'اپراتور',
|
||||||
|
ACCOUNTANT: 'حسابدار',
|
||||||
|
},
|
||||||
|
AccountStatus: {
|
||||||
ACTIVE: 'فعال',
|
ACTIVE: 'فعال',
|
||||||
SUSPENDED: 'غیرفعال',
|
SUSPENDED: 'غیرفعال',
|
||||||
|
},
|
||||||
|
PartnerRole: {
|
||||||
OWNER: 'مدیر اصلی',
|
OWNER: 'مدیر اصلی',
|
||||||
MANAGER: 'مدیریت',
|
MANAGER: 'مدیریت',
|
||||||
OPERATOR: 'اپراتور',
|
OPERATOR: 'اپراتور',
|
||||||
|
},
|
||||||
|
PartnerStatus: {
|
||||||
|
ACTIVE: 'فعال',
|
||||||
|
SUSPENDED: 'غیرفعال',
|
||||||
|
},
|
||||||
|
ProviderRole: {
|
||||||
|
OWNER: 'مدیر اصلی',
|
||||||
|
MANAGER: 'مدیریت',
|
||||||
|
OPERATOR: 'اپراتور',
|
||||||
|
},
|
||||||
|
ProviderStatus: {
|
||||||
|
ACTIVE: 'فعال',
|
||||||
|
SUSPENDED: 'غیرفعال',
|
||||||
|
},
|
||||||
|
BusinessRole: {
|
||||||
|
MANAGER: 'مدیریت',
|
||||||
|
OPERATOR: 'اپراتور',
|
||||||
|
},
|
||||||
|
ComplexRole: {
|
||||||
|
MANAGER: 'مدیریت',
|
||||||
|
OPERATOR: 'اپراتور',
|
||||||
|
},
|
||||||
|
ConsumerRole: {
|
||||||
|
OWNER: 'مدیر اصلی',
|
||||||
|
MANAGER: 'مدیریت',
|
||||||
|
OPERATOR: 'اپراتور',
|
||||||
|
},
|
||||||
|
ConsumerStatus: {
|
||||||
|
ACTIVE: 'فعال',
|
||||||
|
SUSPENDED: 'غیرفعال',
|
||||||
|
},
|
||||||
|
ConsumerType: {
|
||||||
|
INDIVIDUAL: 'حقیقی',
|
||||||
|
LEGAL: 'حقوقی',
|
||||||
|
},
|
||||||
|
TokenType: {
|
||||||
|
ACCESS: 'دسترسی',
|
||||||
|
REFRESH: 'نوسازی',
|
||||||
|
},
|
||||||
|
ApplicationPlatform: {
|
||||||
|
ANDROID: 'اندروید',
|
||||||
|
IOS: 'iOS',
|
||||||
|
},
|
||||||
|
ApplicationReleaseType: {
|
||||||
|
STABLE: 'پایدار',
|
||||||
|
BETA: 'بتا',
|
||||||
|
ALPHA: 'آلفا',
|
||||||
|
},
|
||||||
|
ApplicationPublisher: {
|
||||||
|
DIRECT: 'مستقیم',
|
||||||
|
CAFE_BAZAR: 'کافه بازار',
|
||||||
|
MAYKET: 'مایکت',
|
||||||
|
},
|
||||||
|
TspProviderType: {
|
||||||
|
NAMA: 'نما',
|
||||||
|
SUN: 'سان',
|
||||||
|
},
|
||||||
|
TspProviderResponseStatus: {
|
||||||
|
[TspProviderResponseStatus.SUCCESS]: 'تایید شده',
|
||||||
|
[TspProviderResponseStatus.FAILURE]: 'ناموفق',
|
||||||
|
[TspProviderResponseStatus.NOT_SEND]: 'ارسال نشده',
|
||||||
|
[TspProviderResponseStatus.QUEUED]: 'در صف ارسال',
|
||||||
|
[TspProviderResponseStatus.FISCAL_QUEUED]: 'در انتظار تایید سازمان',
|
||||||
|
[TspProviderResponseStatus.SEND_FAILURE]: 'خطا در ارسال',
|
||||||
|
},
|
||||||
|
InvoiceSettlementType: {
|
||||||
|
[InvoiceSettlementType.CASH]: 'نقدی',
|
||||||
|
[InvoiceSettlementType.CREDIT]: 'نسیه',
|
||||||
|
[InvoiceSettlementType.MIXED]: 'نقدی / نسیه',
|
||||||
|
},
|
||||||
|
TspProviderRequestType: {
|
||||||
|
[TspProviderRequestType.ORIGINAL]: 'اصلی',
|
||||||
|
[TspProviderRequestType.CORRECTION]: 'اصلاح',
|
||||||
|
[TspProviderRequestType.REVOKE]: 'ابطال',
|
||||||
|
[TspProviderRequestType.RETURN]: 'برگشت از فروش',
|
||||||
|
},
|
||||||
|
TspProviderCustomerType: {
|
||||||
|
Unknown: 'ناشناس',
|
||||||
|
Known: 'شناسایی شده',
|
||||||
|
},
|
||||||
|
SKUGuildType: {
|
||||||
|
GOLD: 'طلا',
|
||||||
|
},
|
||||||
|
GoldKarat: {
|
||||||
|
KARAT_18: '۱۸ عیار',
|
||||||
|
KARAT_21: '۲۱ عیار',
|
||||||
|
KARAT_24: '۲۴ عیار',
|
||||||
|
},
|
||||||
|
InvoiceTemplateType: {
|
||||||
|
SALE: 'فروش',
|
||||||
|
FX_SALE: 'فروش ارزی',
|
||||||
|
GOLD_JEWELRY: 'طلا و جواهر',
|
||||||
|
CONTRACT: 'پیمانکاری',
|
||||||
|
UTILITY: 'قبوض خدماتی',
|
||||||
|
AIR_TICKET: 'بلیط هواپیما',
|
||||||
|
EXPORT: 'صادرات',
|
||||||
|
BILL_OF_LADING: 'بارنامه',
|
||||||
|
PETROCHEMICAL: 'پتروشیمی',
|
||||||
|
COMMODITY_EXCHANGE: 'بورس کالا',
|
||||||
|
INSURANCE: 'بیمه',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
+28
-19
@@ -1,25 +1,34 @@
|
|||||||
export enum TokenType {
|
|
||||||
ACCESS = 'ACCESS',
|
|
||||||
REFRESH = 'REFRESH',
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum AccountType {
|
|
||||||
PARTNER = 'PARTNER',
|
|
||||||
BUSINESS = 'BUSINESS',
|
|
||||||
ADMIN = 'ADMIN',
|
|
||||||
PROVIDER = 'PROVIDER',
|
|
||||||
POS = 'POS',
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum GoldKarat {
|
export enum GoldKarat {
|
||||||
KARAT_18 = '18',
|
KARAT_18 = 'KARAT_18',
|
||||||
KARAT_21 = '21',
|
KARAT_21 = 'KARAT_21',
|
||||||
KARAT_24 = '24',
|
KARAT_24 = 'KARAT_24',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum TspProviderRequestType {
|
||||||
|
ORIGINAL = 'ORIGINAL',
|
||||||
|
CORRECTION = 'CORRECTION',
|
||||||
|
REVOKE = 'REVOKE',
|
||||||
|
REMOVE = 'REMOVE',
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SKUGuildType = {
|
||||||
|
GOLD: 'GOLD',
|
||||||
|
} as const
|
||||||
|
|
||||||
|
export type SKUGuildType = (typeof SKUGuildType)[keyof typeof SKUGuildType]
|
||||||
|
|
||||||
export const UploadedFileTypes = {
|
export const UploadedFileTypes = {
|
||||||
GOOD: 'good',
|
GOOD: 'GOOD',
|
||||||
SERVICE: 'service',
|
SERVICE: 'SERVICE',
|
||||||
PROFILE_AVATAR: 'profile_avatar',
|
PROFILE_AVATAR: 'PROFILE_AVATAR',
|
||||||
|
PARTNER_LOGO: 'PARTNER_LOGO',
|
||||||
}
|
}
|
||||||
export type UploadedFileTypes = (typeof UploadedFileTypes)[keyof typeof UploadedFileTypes]
|
export type UploadedFileTypes = (typeof UploadedFileTypes)[keyof typeof UploadedFileTypes]
|
||||||
|
|
||||||
|
export const TspProviderCustomerType = {
|
||||||
|
UNKNOWN: 'UNKNOWN',
|
||||||
|
KNOWN: 'KNOWN',
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TspProviderCustomerType =
|
||||||
|
(typeof TspProviderCustomerType)[keyof typeof TspProviderCustomerType]
|
||||||
|
|||||||
@@ -27,14 +27,14 @@ export class ConsumerGuard {
|
|||||||
|
|
||||||
const consumer = await this.prisma.consumer.findFirst({
|
const consumer = await this.prisma.consumer.findFirst({
|
||||||
where: {
|
where: {
|
||||||
consumer_accounts: {
|
accounts: {
|
||||||
some: {
|
some: {
|
||||||
id: tokenPayload.account_id,
|
id: tokenPayload.account_id,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
select: {
|
select: {
|
||||||
consumer_accounts: {
|
accounts: {
|
||||||
select: {
|
select: {
|
||||||
role: true,
|
role: true,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -23,14 +23,14 @@ export class PartnerGuard {
|
|||||||
|
|
||||||
const partner = await this.prisma.partner.findFirst({
|
const partner = await this.prisma.partner.findFirst({
|
||||||
where: {
|
where: {
|
||||||
partner_accounts: {
|
accounts: {
|
||||||
some: {
|
some: {
|
||||||
id: tokenPayload.account_id,
|
id: tokenPayload.account_id,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
select: {
|
select: {
|
||||||
partner_accounts: {
|
accounts: {
|
||||||
select: {
|
select: {
|
||||||
role: true,
|
role: true,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { ITokenPayload } from '@/modules/auth/auth.utils'
|
|||||||
import { PrismaService } from '@/prisma/prisma.service'
|
import { PrismaService } from '@/prisma/prisma.service'
|
||||||
import { ExecutionContext, ForbiddenException, Injectable } from '@nestjs/common'
|
import { ExecutionContext, ForbiddenException, Injectable } from '@nestjs/common'
|
||||||
import { Request as ExpressRequest } from 'express'
|
import { Request as ExpressRequest } from 'express'
|
||||||
|
import { QUERY_CONSTANTS } from '../queryConstants'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PosGuard {
|
export class PosGuard {
|
||||||
@@ -18,7 +19,6 @@ export class PosGuard {
|
|||||||
throw new ForbiddenException('شما دسترسی لازم را ندارید.')
|
throw new ForbiddenException('شما دسترسی لازم را ندارید.')
|
||||||
}
|
}
|
||||||
|
|
||||||
const now = new Date()
|
|
||||||
const cookie = req.cookies
|
const cookie = req.cookies
|
||||||
const { posId } = cookie
|
const { posId } = cookie
|
||||||
|
|
||||||
@@ -40,22 +40,7 @@ export class PosGuard {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
license_activation: {
|
license_activation: {
|
||||||
OR: [
|
...QUERY_CONSTANTS.LICENSE_ACTIVATION.activeOnDate(),
|
||||||
{
|
|
||||||
expires_at: {
|
|
||||||
gte: now,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
license_renews: {
|
|
||||||
some: {
|
|
||||||
expires_at: {
|
|
||||||
gte: now,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -67,85 +52,5 @@ export class PosGuard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
// const pos = await this.prisma.pos.findUnique({
|
|
||||||
// where: {
|
|
||||||
// id: posId,
|
|
||||||
// account_id: tokenPayload.account_id,
|
|
||||||
// },
|
|
||||||
// select: {
|
|
||||||
// complex: {
|
|
||||||
// select: {
|
|
||||||
// id: true,
|
|
||||||
// business_activity: {
|
|
||||||
// select: {
|
|
||||||
// id: true,
|
|
||||||
// license_activation: {
|
|
||||||
// select: {
|
|
||||||
// expires_at: true,
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// })
|
|
||||||
|
|
||||||
// if (!pos) {
|
|
||||||
// throw new ForbiddenException('شما دسترسی لازم را ندارید.')
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (req.method !== 'GET') {
|
|
||||||
// if (!pos.complex.business_activity.license_activation) {
|
|
||||||
// throw new ForbiddenException('برای کاربر شما لایسنس ایجاد نشده است.')
|
|
||||||
// }
|
|
||||||
// if (
|
|
||||||
// pos.complex.business_activity.license_activation.expires_at &&
|
|
||||||
// new Date().getTime() >
|
|
||||||
// new Date(pos.complex.business_activity.license_activation.expires_at).getTime()
|
|
||||||
// ) {
|
|
||||||
// throw new ForbiddenException('لایسنس شما منقضی شده است.')
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const foundedAccount = await this.prisma.consumerAccount.findUnique({
|
|
||||||
// where: {
|
|
||||||
// id: tokenPayload.account_id,
|
|
||||||
// },
|
|
||||||
// select: {
|
|
||||||
// role: true,
|
|
||||||
// },
|
|
||||||
// })
|
|
||||||
|
|
||||||
// if (foundedAccount?.role === 'OWNER') {
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const accountPermissions = await this.prisma.permissionConsumer.findUnique({
|
|
||||||
// where: {
|
|
||||||
// consumer_account_id: tokenPayload.account_id,
|
|
||||||
// },
|
|
||||||
// select: {
|
|
||||||
// pos_permissions: true,
|
|
||||||
// business_permissions: true,
|
|
||||||
// complex_permissions: true,
|
|
||||||
// },
|
|
||||||
// })
|
|
||||||
|
|
||||||
// if (accountPermissions?.pos_permissions.some(p => p.pos_id === posId)) {
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
// if (
|
|
||||||
// accountPermissions?.complex_permissions.some(p => p.complex_id === pos.complex.id)
|
|
||||||
// ) {
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
// if (
|
|
||||||
// accountPermissions?.business_permissions.some(
|
|
||||||
// p => p.business_id === pos.complex.business_activity.id,
|
|
||||||
// )
|
|
||||||
// ) {
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
export interface FetchRequestContext {
|
||||||
|
url: string
|
||||||
|
init: RequestInit
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FetchRequestInterceptor {
|
||||||
|
onRequest?(
|
||||||
|
context: FetchRequestContext,
|
||||||
|
): Promise<FetchRequestContext> | FetchRequestContext
|
||||||
|
onResponse?(
|
||||||
|
context: FetchRequestContext,
|
||||||
|
response: Response,
|
||||||
|
): Promise<Response> | Response
|
||||||
|
onError?(context: FetchRequestContext, error: unknown): Promise<void> | void
|
||||||
|
}
|
||||||
|
|
||||||
|
function mergeHeaders(
|
||||||
|
currentHeaders: HeadersInit | undefined,
|
||||||
|
newHeaders: HeadersInit,
|
||||||
|
): Headers {
|
||||||
|
const mergedHeaders = new Headers(currentHeaders)
|
||||||
|
const incomingHeaders = new Headers(newHeaders)
|
||||||
|
|
||||||
|
incomingHeaders.forEach((value, key) => {
|
||||||
|
mergedHeaders.set(key, value)
|
||||||
|
})
|
||||||
|
|
||||||
|
return mergedHeaders
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createHeaderRequestInterceptor(
|
||||||
|
headers: HeadersInit,
|
||||||
|
): FetchRequestInterceptor {
|
||||||
|
return {
|
||||||
|
onRequest(context) {
|
||||||
|
return {
|
||||||
|
...context,
|
||||||
|
init: {
|
||||||
|
...context.init,
|
||||||
|
headers: mergeHeaders(context.init.headers, headers),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createEnsureSuccessResponseInterceptor(): FetchRequestInterceptor {
|
||||||
|
return {
|
||||||
|
async onResponse(_, response) {
|
||||||
|
if (response.ok) {
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
const errorBody = await response.text().catch(() => '')
|
||||||
|
const normalizedBody = errorBody
|
||||||
|
return Promise.reject({
|
||||||
|
status: response.status,
|
||||||
|
statusText: response.statusText,
|
||||||
|
body: normalizedBody,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -85,7 +85,6 @@ export class ResponseMappingInterceptor implements NestInterceptor {
|
|||||||
break
|
break
|
||||||
case 'paginate': {
|
case 'paginate': {
|
||||||
const { items: a, ...rest } = wrapped
|
const { items: a, ...rest } = wrapped
|
||||||
console.log(rest)
|
|
||||||
|
|
||||||
const items = Array.isArray(wrapped.items) ? wrapped.items : []
|
const items = Array.isArray(wrapped.items) ? wrapped.items : []
|
||||||
const total =
|
const total =
|
||||||
@@ -96,7 +95,7 @@ export class ResponseMappingInterceptor implements NestInterceptor {
|
|||||||
meta = {
|
meta = {
|
||||||
totalRecords: total,
|
totalRecords: total,
|
||||||
totalPages: Math.max(1, Math.ceil(total / perPage)),
|
totalPages: Math.max(1, Math.ceil(total / perPage)),
|
||||||
page,
|
page: parseInt(page),
|
||||||
perPage,
|
perPage,
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
@@ -189,7 +188,7 @@ export class ResponseMappingInterceptor implements NestInterceptor {
|
|||||||
meta = {
|
meta = {
|
||||||
totalRecords: total,
|
totalRecords: total,
|
||||||
totalPages: Math.max(1, Math.ceil(total / perPage)),
|
totalPages: Math.max(1, Math.ceil(total / perPage)),
|
||||||
page,
|
page: parseInt(page),
|
||||||
perPage,
|
perPage,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ export interface SaleInvoiceGoldTypePayload {
|
|||||||
karat: keyof typeof GoldKarat
|
karat: keyof typeof GoldKarat
|
||||||
wages: number
|
wages: number
|
||||||
profit: number
|
profit: number
|
||||||
|
commission: number
|
||||||
}
|
}
|
||||||
export interface SaleInvoiceStandardPayload {}
|
export interface SaleInvoiceStandardPayload {}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
import { BusinessActivitySelect } from '@/generated/prisma/models'
|
||||||
|
|
||||||
|
export const summarySelect: BusinessActivitySelect = {
|
||||||
|
id: true,
|
||||||
|
name: true,
|
||||||
|
economic_code: true,
|
||||||
|
created_at: true,
|
||||||
|
fiscal_id: true,
|
||||||
|
invoice_number_sequence: true,
|
||||||
|
partner_token: true,
|
||||||
|
guild: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
code: true,
|
||||||
|
name: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
license_activation: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
starts_at: true,
|
||||||
|
expires_at: true,
|
||||||
|
license: {
|
||||||
|
select: {
|
||||||
|
activation: {
|
||||||
|
select: {
|
||||||
|
account_allocations: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
account_id: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export const select: BusinessActivitySelect = {
|
||||||
|
...summarySelect,
|
||||||
|
}
|
||||||
|
|
||||||
|
export const mappedData = (businessActivity: any) => {
|
||||||
|
const { license_activation, ...rest } = businessActivity
|
||||||
|
const { license, ...license_activation_rest } = license_activation
|
||||||
|
const { account_allocations } = license.activation
|
||||||
|
|
||||||
|
console.log('license_activation', license_activation)
|
||||||
|
|
||||||
|
return {
|
||||||
|
...rest,
|
||||||
|
license_info: {
|
||||||
|
...license_activation_rest,
|
||||||
|
accounts_limit: account_allocations.length,
|
||||||
|
allocated_account_count: account_allocations.filter(
|
||||||
|
allocation => allocation.account_id,
|
||||||
|
).length,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
import { ConsumerSelect, ConsumerWhereInput } from '@/generated/prisma/models'
|
||||||
|
|
||||||
|
const now = new Date()
|
||||||
|
|
||||||
|
export const infoSelect: ConsumerSelect = {
|
||||||
|
type: true,
|
||||||
|
legal: {
|
||||||
|
select: {
|
||||||
|
name: true,
|
||||||
|
registration_code: true,
|
||||||
|
partner: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
name: true,
|
||||||
|
code: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
individual: {
|
||||||
|
select: {
|
||||||
|
first_name: true,
|
||||||
|
last_name: true,
|
||||||
|
mobile_number: true,
|
||||||
|
national_code: true,
|
||||||
|
partner: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
name: true,
|
||||||
|
code: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export const activeBusinessCount: ConsumerSelect = {
|
||||||
|
_count: {
|
||||||
|
select: {
|
||||||
|
business_activities: {
|
||||||
|
where: {
|
||||||
|
license_activation: {
|
||||||
|
OR: [
|
||||||
|
{
|
||||||
|
expires_at: {
|
||||||
|
gt: now,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
license_renews: {
|
||||||
|
some: {
|
||||||
|
expires_at: {
|
||||||
|
gt: now,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export const consumerRelatedPartner = (partner_id: string): ConsumerWhereInput => ({
|
||||||
|
OR: [
|
||||||
|
{
|
||||||
|
legal: {
|
||||||
|
is: {
|
||||||
|
partner_id,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
individual: {
|
||||||
|
is: {
|
||||||
|
partner_id,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
@@ -1,5 +1,13 @@
|
|||||||
import * as pos from './pos'
|
import * as BUSINESS_ACTIVITIES from './businessActivities'
|
||||||
|
import * as CONSUMER from './consumer'
|
||||||
|
import * as LICENSE_ACTIVATION from './licenseActivation'
|
||||||
|
import * as POS from './pos'
|
||||||
|
import * as SALE_INVOICE from './saleInvoice'
|
||||||
|
|
||||||
export const QUERY_CONSTANTS = {
|
export const QUERY_CONSTANTS = {
|
||||||
pos,
|
POS,
|
||||||
|
CONSUMER,
|
||||||
|
LICENSE_ACTIVATION,
|
||||||
|
SALE_INVOICE,
|
||||||
|
BUSINESS_ACTIVITIES,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
export const activeOnDate = (expires_at: Date = new Date()) => ({
|
||||||
|
OR: [
|
||||||
|
{
|
||||||
|
expires_at: {
|
||||||
|
gte: expires_at,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
license_renews: {
|
||||||
|
some: {
|
||||||
|
expires_at: {
|
||||||
|
gte: expires_at,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
@@ -0,0 +1,134 @@
|
|||||||
|
import { SalesInvoiceSelect } from '@/generated/prisma/models'
|
||||||
|
|
||||||
|
export const summarySelect: SalesInvoiceSelect = {
|
||||||
|
id: true,
|
||||||
|
code: true,
|
||||||
|
invoice_date: true,
|
||||||
|
invoice_number: true,
|
||||||
|
main_id: true,
|
||||||
|
total_amount: true,
|
||||||
|
tax_id: true,
|
||||||
|
type: true,
|
||||||
|
notes: true,
|
||||||
|
created_at: true,
|
||||||
|
settlement_type: true,
|
||||||
|
unknown_customer: true,
|
||||||
|
last_attempt_no: true,
|
||||||
|
last_tsp_status: true,
|
||||||
|
customer: {
|
||||||
|
select: {
|
||||||
|
type: true,
|
||||||
|
individual: {
|
||||||
|
select: {
|
||||||
|
first_name: true,
|
||||||
|
last_name: true,
|
||||||
|
mobile_number: true,
|
||||||
|
national_id: true,
|
||||||
|
economic_code: true,
|
||||||
|
postal_code: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
legal: {
|
||||||
|
select: {
|
||||||
|
name: true,
|
||||||
|
economic_code: true,
|
||||||
|
registration_number: true,
|
||||||
|
postal_code: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
reference_invoice: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
invoice_number: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
referenced_by: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
invoice_number: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export const select: SalesInvoiceSelect = {
|
||||||
|
...summarySelect,
|
||||||
|
discount_amount: true,
|
||||||
|
tax_amount: true,
|
||||||
|
updated_at: true,
|
||||||
|
unknown_customer: true,
|
||||||
|
|
||||||
|
pos: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
name: true,
|
||||||
|
complex: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
name: true,
|
||||||
|
business_activity: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
name: true,
|
||||||
|
economic_code: true,
|
||||||
|
guild: {
|
||||||
|
select: {
|
||||||
|
name: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
consumer_account: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
role: true,
|
||||||
|
account: {
|
||||||
|
select: {
|
||||||
|
username: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
items: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
good_id: true,
|
||||||
|
service_id: true,
|
||||||
|
quantity: true,
|
||||||
|
measure_unit_code: true,
|
||||||
|
measure_unit_text: true,
|
||||||
|
sku_code: true,
|
||||||
|
unit_price: true,
|
||||||
|
discount_amount: true,
|
||||||
|
tax_amount: true,
|
||||||
|
total_amount: true,
|
||||||
|
notes: true,
|
||||||
|
payload: true,
|
||||||
|
good_snapshot: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
payments: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
amount: true,
|
||||||
|
payment_method: true,
|
||||||
|
paid_at: true,
|
||||||
|
created_at: true,
|
||||||
|
terminal_info: {
|
||||||
|
select: {
|
||||||
|
terminal_id: true,
|
||||||
|
stan: true,
|
||||||
|
rrn: true,
|
||||||
|
transaction_date_time: true,
|
||||||
|
customer_card_no: true,
|
||||||
|
description: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import { QUERY_CONSTANTS } from '@/common/queryConstants'
|
||||||
|
import { BusinessActivitySelect } from '@/generated/prisma/models'
|
||||||
|
import { PrismaService } from '@/prisma/prisma.service'
|
||||||
|
import { Injectable } from '@nestjs/common'
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class BusinessActivitiesQueryService {
|
||||||
|
constructor(private readonly prisma: PrismaService) {}
|
||||||
|
|
||||||
|
readonly baseSelect: BusinessActivitySelect = {
|
||||||
|
...QUERY_CONSTANTS.BUSINESS_ACTIVITIES.summarySelect,
|
||||||
|
}
|
||||||
|
|
||||||
|
async findAllByConsumer(consumer_id: string, select: BusinessActivitySelect) {
|
||||||
|
const businessActivities = await this.prisma.businessActivity.findMany({
|
||||||
|
where: { consumer_id },
|
||||||
|
select: this.baseSelect,
|
||||||
|
})
|
||||||
|
return businessActivities.map(QUERY_CONSTANTS.BUSINESS_ACTIVITIES.mappedData)
|
||||||
|
}
|
||||||
|
|
||||||
|
async findOneByConsumer(
|
||||||
|
consumer_id: string,
|
||||||
|
id: string,
|
||||||
|
select: BusinessActivitySelect,
|
||||||
|
orThrow = false,
|
||||||
|
) {
|
||||||
|
// if (orThrow) {
|
||||||
|
// return await this.prisma.businessActivity.findUniqueOrThrow({
|
||||||
|
// where: { consumer_id, id },
|
||||||
|
// select,
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
|
||||||
|
const businessActivity = await this.prisma.businessActivity.findUnique({
|
||||||
|
where: { consumer_id, id },
|
||||||
|
select: QUERY_CONSTANTS.BUSINESS_ACTIVITIES.select,
|
||||||
|
})
|
||||||
|
|
||||||
|
return QUERY_CONSTANTS.BUSINESS_ACTIVITIES.mappedData(businessActivity)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
import { UploadedFileTypes } from '@/common/enums/enums'
|
||||||
|
import { GoodPricingModel } from '@/generated/prisma/enums'
|
||||||
|
import { GoodSelect } from '@/generated/prisma/models'
|
||||||
|
import { UploaderService } from '@/modules/uploader/uploader.service'
|
||||||
|
import { Injectable } from '@nestjs/common'
|
||||||
|
|
||||||
|
export interface CreateGoodDto {
|
||||||
|
name: string
|
||||||
|
sku_id: string
|
||||||
|
category_id: string
|
||||||
|
measure_unit_id: string
|
||||||
|
pricing_model: GoodPricingModel
|
||||||
|
description?: string
|
||||||
|
is_default_guild_good?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdateGoodDto extends Partial<CreateGoodDto> {}
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class GoodsSharedService {
|
||||||
|
constructor(private readonly uploaderService: UploaderService) {}
|
||||||
|
|
||||||
|
readonly defaultSelect: GoodSelect = {
|
||||||
|
id: true,
|
||||||
|
name: true,
|
||||||
|
pricing_model: true,
|
||||||
|
image_url: true,
|
||||||
|
description: true,
|
||||||
|
sku: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
name: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
measure_unit: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
name: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
category: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
name: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
async prepareCreateData(data: CreateGoodDto, file?: Express.Multer.File) {
|
||||||
|
const { category_id, measure_unit_id, sku_id, ...rest } = data
|
||||||
|
|
||||||
|
let image_url = ''
|
||||||
|
if (file) {
|
||||||
|
const uploadedUrl = await this.uploaderService.uploadFile(
|
||||||
|
file,
|
||||||
|
UploadedFileTypes.GOOD,
|
||||||
|
)
|
||||||
|
image_url = uploadedUrl || ''
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...rest,
|
||||||
|
image_url,
|
||||||
|
sku: {
|
||||||
|
connect: {
|
||||||
|
id: sku_id,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
measure_unit: {
|
||||||
|
connect: {
|
||||||
|
id: measure_unit_id,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
category: {
|
||||||
|
connect: {
|
||||||
|
id: category_id,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async prepareUpdateData(id: string, data: UpdateGoodDto, file?: Express.Multer.File) {
|
||||||
|
const { category_id, measure_unit_id, sku_id, ...rest } = data
|
||||||
|
|
||||||
|
let image_url = ''
|
||||||
|
if (file) {
|
||||||
|
const uploadedUrl = await this.uploaderService.uploadFile(
|
||||||
|
file,
|
||||||
|
UploadedFileTypes.GOOD,
|
||||||
|
)
|
||||||
|
image_url = uploadedUrl || ''
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateData: any = {
|
||||||
|
...rest,
|
||||||
|
image_url,
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sku_id) {
|
||||||
|
updateData.sku = { connect: { id: sku_id } }
|
||||||
|
}
|
||||||
|
if (measure_unit_id) {
|
||||||
|
updateData.measure_unit = { connect: { id: measure_unit_id } }
|
||||||
|
}
|
||||||
|
if (category_id) {
|
||||||
|
updateData.category = { connect: { id: category_id } }
|
||||||
|
}
|
||||||
|
|
||||||
|
return updateData
|
||||||
|
}
|
||||||
|
|
||||||
|
async handleImageUpdate(id: string, prisma: any, image_url: string) {
|
||||||
|
if (image_url) {
|
||||||
|
const prevImage = await prisma.good.findUnique({
|
||||||
|
where: { id },
|
||||||
|
select: { image_url: true },
|
||||||
|
})
|
||||||
|
|
||||||
|
if (prevImage?.image_url) {
|
||||||
|
this.uploaderService.deleteFile(prevImage.image_url, UploadedFileTypes.GOOD)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { PrismaService } from '@/prisma/prisma.service'
|
||||||
|
import { BadRequestException, Injectable } from '@nestjs/common'
|
||||||
|
import { ConsumerRole } from 'generated/prisma/enums'
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class SharedSaleInvoiceAccessService {
|
||||||
|
constructor(private readonly prisma: PrismaService) {}
|
||||||
|
|
||||||
|
async getConsumerIdWithPosAccess(
|
||||||
|
consumerAccountId: string,
|
||||||
|
posId: string,
|
||||||
|
): Promise<string> {
|
||||||
|
const consumer = await this.prisma.consumerAccount.findUnique({
|
||||||
|
where: {
|
||||||
|
id: consumerAccountId,
|
||||||
|
OR: [{ pos: { id: posId } }, { role: ConsumerRole.OWNER }],
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
consumer_id: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!consumer) {
|
||||||
|
throw new BadRequestException('شما دسترسی لازم برای ارسال صورتحساب را ندارید.')
|
||||||
|
}
|
||||||
|
|
||||||
|
return consumer.consumer_id
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,547 @@
|
|||||||
|
import { SharedSaleInvoiceAccessService } from '@/common/services/saleInvoices/sale-invoice-access.service'
|
||||||
|
import {
|
||||||
|
PosCorrectionSalesInvoiceDto,
|
||||||
|
PosReturnSalesInvoiceDto,
|
||||||
|
} from '@/modules/pos/sales-invoices/dto/create-sales-invoice.dto'
|
||||||
|
import { SalesInvoiceTspService } from '@/modules/tspProviders/sales-invoice-tsp.service'
|
||||||
|
import { PrismaService } from '@/prisma/prisma.service'
|
||||||
|
import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common'
|
||||||
|
import {
|
||||||
|
CustomerType,
|
||||||
|
TspProviderRequestType,
|
||||||
|
TspProviderResponseStatus,
|
||||||
|
} from 'generated/prisma/enums'
|
||||||
|
import { SharedSaleInvoiceCreateService } from './sale-invoice-create.service'
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class SharedSaleInvoiceActionsService {
|
||||||
|
constructor(
|
||||||
|
private prisma: PrismaService,
|
||||||
|
private readonly salesInvoiceTspService: SalesInvoiceTspService,
|
||||||
|
private readonly saleInvoiceAccessService: SharedSaleInvoiceAccessService,
|
||||||
|
private sharedSaleInvoiceCreateService: SharedSaleInvoiceCreateService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
async send(consumerAccountId: string, posId: string, invoiceId: string) {
|
||||||
|
await this.saleInvoiceAccessService.getConsumerIdWithPosAccess(
|
||||||
|
consumerAccountId,
|
||||||
|
posId,
|
||||||
|
)
|
||||||
|
return this.salesInvoiceTspService.originalSend(posId, invoiceId)
|
||||||
|
}
|
||||||
|
|
||||||
|
async retry(consumerAccountId: string, posId: string, invoiceId: string) {
|
||||||
|
await this.saleInvoiceAccessService.getConsumerIdWithPosAccess(
|
||||||
|
consumerAccountId,
|
||||||
|
posId,
|
||||||
|
)
|
||||||
|
return this.salesInvoiceTspService.originalSend(posId, invoiceId)
|
||||||
|
}
|
||||||
|
|
||||||
|
async revoke(
|
||||||
|
consumerAccountId: string,
|
||||||
|
posId: string,
|
||||||
|
complexId: string,
|
||||||
|
businessId: string,
|
||||||
|
invoiceId: string,
|
||||||
|
) {
|
||||||
|
await this.saleInvoiceAccessService.getConsumerIdWithPosAccess(
|
||||||
|
consumerAccountId,
|
||||||
|
posId,
|
||||||
|
)
|
||||||
|
return this.salesInvoiceTspService.revoke(
|
||||||
|
consumerAccountId,
|
||||||
|
posId,
|
||||||
|
complexId,
|
||||||
|
businessId,
|
||||||
|
invoiceId,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
async correction(
|
||||||
|
data: PosCorrectionSalesInvoiceDto,
|
||||||
|
consumerAccountId: string,
|
||||||
|
posId: string,
|
||||||
|
complexId: string,
|
||||||
|
businessId: string,
|
||||||
|
invoiceId: string,
|
||||||
|
) {
|
||||||
|
await this.saleInvoiceAccessService.getConsumerIdWithPosAccess(
|
||||||
|
consumerAccountId,
|
||||||
|
posId,
|
||||||
|
)
|
||||||
|
|
||||||
|
const newInvoice = await this.prisma.$transaction(async tx => {
|
||||||
|
const relatedInvoice = await tx.salesInvoice.findUnique({
|
||||||
|
where: {
|
||||||
|
id: invoiceId,
|
||||||
|
pos_id: posId,
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
invoice_date: true,
|
||||||
|
settlement_type: true,
|
||||||
|
customer_id: true,
|
||||||
|
main_id: true,
|
||||||
|
last_tsp_status: true,
|
||||||
|
referenced_by: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
customer: {
|
||||||
|
select: {
|
||||||
|
type: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
total_amount: true,
|
||||||
|
items: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
good_id: true,
|
||||||
|
service_id: true,
|
||||||
|
quantity: true,
|
||||||
|
unit_price: true,
|
||||||
|
total_amount: true,
|
||||||
|
discount_amount: true,
|
||||||
|
tax_amount: true,
|
||||||
|
payload: true,
|
||||||
|
notes: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!relatedInvoice) {
|
||||||
|
throw new NotFoundException('صورتحساب مورد نظر شما یافت نشد.')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (relatedInvoice.last_tsp_status !== TspProviderResponseStatus.SUCCESS) {
|
||||||
|
throw new BadRequestException('امکان اصلاح این صورتحساب وجود ندارد.')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (relatedInvoice.referenced_by) {
|
||||||
|
throw new BadRequestException(
|
||||||
|
'این صورتحساب قبلا با یک صورتحساب دیگر جایگزین شده است.',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const normalizedInvoiceDate = this.normalizeInvoiceDate(data.invoice_date)
|
||||||
|
const originalInvoiceDate = this.normalizeInvoiceDate(relatedInvoice.invoice_date)
|
||||||
|
|
||||||
|
const originalItemsByKey = new Map(
|
||||||
|
relatedInvoice.items.map(item => [this.getItemKey(item), item]),
|
||||||
|
)
|
||||||
|
|
||||||
|
const usedItemKeys = new Set<string>()
|
||||||
|
const normalizedItems = data.items.map(item => {
|
||||||
|
const itemKey = this.getItemKey(item)
|
||||||
|
|
||||||
|
if (!itemKey) {
|
||||||
|
throw new BadRequestException('هر قلم باید شناسه کالا یا خدمت داشته باشد.')
|
||||||
|
}
|
||||||
|
|
||||||
|
usedItemKeys.add(itemKey)
|
||||||
|
|
||||||
|
const originalItem = originalItemsByKey.get(itemKey)
|
||||||
|
|
||||||
|
if (!originalItem) {
|
||||||
|
throw new BadRequestException(
|
||||||
|
'فقط اقلام موجود در صورتحساب اصلی قابل اصلاح هستند.',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const originalQuantity = Number(originalItem.quantity)
|
||||||
|
const requestedQuantity = Number(item.quantity)
|
||||||
|
const originalUnitPrice = Number(originalItem.unit_price)
|
||||||
|
const requestedUnitPrice = Number(item.unit_price)
|
||||||
|
const originalTotalAmount = this.roundAmount(Number(originalItem.total_amount))
|
||||||
|
const requestedTotalAmount = this.roundAmount(Number(item.total_amount))
|
||||||
|
|
||||||
|
if (requestedQuantity <= 0) {
|
||||||
|
throw new BadRequestException(
|
||||||
|
'تعداد/مقدار اقلام اصلاحی باید بیشتر از صفر باشد.',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (requestedUnitPrice < originalUnitPrice) {
|
||||||
|
// throw new BadRequestException(
|
||||||
|
// 'مبلغ واحد اقلام اصلاحی نمیتواند کمتر از صورتحساب اصلی باشد.',
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
|
||||||
|
return {
|
||||||
|
invoice_id: originalItem.id,
|
||||||
|
good_id: originalItem.good_id,
|
||||||
|
service_id: originalItem.service_id || undefined,
|
||||||
|
quantity: requestedQuantity,
|
||||||
|
unit_price: requestedUnitPrice,
|
||||||
|
total_amount: requestedTotalAmount,
|
||||||
|
discount_amount: this.roundAmount(Number(item.discount_amount || 0)),
|
||||||
|
tax_amount: this.roundAmount(Number(item.tax_amount || 0)),
|
||||||
|
payload: item.payload ? JSON.parse(JSON.stringify(item.payload)) : undefined,
|
||||||
|
notes: item.notes || undefined,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (usedItemKeys.size !== relatedInvoice.items.length) {
|
||||||
|
throw new BadRequestException(
|
||||||
|
'فقط اقلام موجود در صورتحساب اصلی قابل اصلاح هستند.',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasChangedQuantity = normalizedItems.some(item => {
|
||||||
|
const originalItem = relatedInvoice.items.find(
|
||||||
|
relatedItem => this.getItemKey(relatedItem) === this.getItemKey(item),
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!originalItem) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return Number(originalItem.quantity) !== Number(item.quantity)
|
||||||
|
})
|
||||||
|
const hasChangedAmount = normalizedItems.some(item => {
|
||||||
|
const originalItem = relatedInvoice.items.find(
|
||||||
|
relatedItem => this.getItemKey(relatedItem) === this.getItemKey(item),
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!originalItem) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
this.roundAmount(Number(originalItem.total_amount)) !==
|
||||||
|
this.roundAmount(Number(item.total_amount))
|
||||||
|
)
|
||||||
|
})
|
||||||
|
const hasChangedInvoiceDate = normalizedInvoiceDate !== originalInvoiceDate
|
||||||
|
|
||||||
|
if (!hasChangedQuantity && !hasChangedAmount && !hasChangedInvoiceDate) {
|
||||||
|
throw new BadRequestException('مقداری تغییر نکرده است.')
|
||||||
|
}
|
||||||
|
|
||||||
|
const requestedTotalAmount = this.roundAmount(Number(data.total_amount))
|
||||||
|
const originalTotalAmount = this.roundAmount(Number(relatedInvoice.total_amount))
|
||||||
|
const totalDiff = this.roundAmount(requestedTotalAmount - originalTotalAmount)
|
||||||
|
const paymentsAmount = this.roundAmount(this.getPaymentsAmount(data.payments))
|
||||||
|
|
||||||
|
if (totalDiff > 0 && paymentsAmount !== totalDiff) {
|
||||||
|
throw new BadRequestException(
|
||||||
|
'جمع پرداختی باید برابر با اختلاف مبلغ صورتحساب اصلاحی و صورتحساب مرجع باشد.',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (totalDiff === 0 && paymentsAmount !== 0) {
|
||||||
|
throw new BadRequestException('در صورت عدم افزایش مبلغ، پرداختی نباید ثبت شود.')
|
||||||
|
}
|
||||||
|
|
||||||
|
const newInvoice = await this.sharedSaleInvoiceCreateService.create({
|
||||||
|
tx,
|
||||||
|
data: {
|
||||||
|
invoice_date: new Date(normalizedInvoiceDate),
|
||||||
|
items: normalizedItems as any,
|
||||||
|
total_amount: requestedTotalAmount,
|
||||||
|
discount_amount: this.roundAmount(Number(data.discount_amount)),
|
||||||
|
tax_amount: this.roundAmount(Number(data.tax_amount)),
|
||||||
|
customer_id: relatedInvoice.customer_id || undefined,
|
||||||
|
customer_type: relatedInvoice.customer?.type || CustomerType.UNKNOWN,
|
||||||
|
settlement_type: relatedInvoice.settlement_type,
|
||||||
|
payments: data.payments,
|
||||||
|
} as any,
|
||||||
|
businessId,
|
||||||
|
complexId,
|
||||||
|
posId,
|
||||||
|
consumerAccountId,
|
||||||
|
main_invoice_id: relatedInvoice.main_id || relatedInvoice.id,
|
||||||
|
ref_invoice_id: relatedInvoice.id,
|
||||||
|
type: TspProviderRequestType.CORRECTION,
|
||||||
|
})
|
||||||
|
|
||||||
|
await tx.salesInvoice.update({
|
||||||
|
where: {
|
||||||
|
id: relatedInvoice.id,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
referenced_by: {
|
||||||
|
connect: {
|
||||||
|
id: newInvoice.id,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return newInvoice
|
||||||
|
})
|
||||||
|
|
||||||
|
return this.salesInvoiceTspService.correctionSend(posId, newInvoice.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
async return(
|
||||||
|
data: PosReturnSalesInvoiceDto,
|
||||||
|
consumerAccountId: string,
|
||||||
|
pos_id: string,
|
||||||
|
complex_id: string,
|
||||||
|
business_id: string,
|
||||||
|
invoiceId: string,
|
||||||
|
) {
|
||||||
|
await this.saleInvoiceAccessService.getConsumerIdWithPosAccess(
|
||||||
|
consumerAccountId,
|
||||||
|
pos_id,
|
||||||
|
)
|
||||||
|
|
||||||
|
const newInvoice = await this.prisma.$transaction(async tx => {
|
||||||
|
const relatedInvoice = await tx.salesInvoice.findUnique({
|
||||||
|
where: {
|
||||||
|
id: invoiceId,
|
||||||
|
pos_id,
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
type: true,
|
||||||
|
invoice_date: true,
|
||||||
|
settlement_type: true,
|
||||||
|
customer_id: true,
|
||||||
|
main_id: true,
|
||||||
|
last_tsp_status: true,
|
||||||
|
referenced_by: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
customer: {
|
||||||
|
select: {
|
||||||
|
type: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
items: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
good_id: true,
|
||||||
|
service_id: true,
|
||||||
|
quantity: true,
|
||||||
|
unit_price: true,
|
||||||
|
total_amount: true,
|
||||||
|
discount_amount: true,
|
||||||
|
tax_amount: true,
|
||||||
|
payload: true,
|
||||||
|
notes: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!relatedInvoice) {
|
||||||
|
throw new NotFoundException('صورتحساب مورد نظر شما یافت نشد.')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (relatedInvoice.last_tsp_status !== TspProviderResponseStatus.SUCCESS) {
|
||||||
|
throw new BadRequestException('امکان برگشت از خرید روی این صورتحساب وجود ندارد.')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (relatedInvoice.referenced_by) {
|
||||||
|
throw new BadRequestException(
|
||||||
|
'این صورتحساب قبلا با یک صورتحساب دیگر جایگزین شده است.',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const normalizedInvoiceDate = this.normalizeInvoiceDate(data.invoice_date)
|
||||||
|
const originalInvoiceDate = this.normalizeInvoiceDate(relatedInvoice.invoice_date)
|
||||||
|
|
||||||
|
const originalItemsByKey = new Map(
|
||||||
|
relatedInvoice.items.map(item => [this.getReturnItemKey(item), item]),
|
||||||
|
)
|
||||||
|
|
||||||
|
const usedItemKeys = new Set<string>()
|
||||||
|
const normalizedItems = data.items.map(item => {
|
||||||
|
const itemKey = this.getReturnItemKey(item)
|
||||||
|
|
||||||
|
if (!itemKey) {
|
||||||
|
throw new BadRequestException('هر قلم باید شناسه کالا یا خدمت داشته باشد.')
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (usedItemKeys.has(itemKey)) {
|
||||||
|
// throw new BadRequestException('اقلام تکراری در صورتحساب بازگشتی مجاز نیستند.')
|
||||||
|
// }
|
||||||
|
|
||||||
|
usedItemKeys.add(itemKey)
|
||||||
|
|
||||||
|
const originalItem = originalItemsByKey.get(itemKey)
|
||||||
|
|
||||||
|
if (!originalItem) {
|
||||||
|
throw new BadRequestException(
|
||||||
|
'فقط اقلام موجود در صورتحساب اصلی قابل بازگشت هستند.',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const originalQuantity = Number(originalItem.quantity)
|
||||||
|
const requestedQuantity = Number(item.quantity)
|
||||||
|
|
||||||
|
if (requestedQuantity <= 0) {
|
||||||
|
throw new BadRequestException(
|
||||||
|
'تعداد/مقدار اقلام بازگشتی باید بیشتر از صفر باشد.',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (requestedQuantity > originalQuantity) {
|
||||||
|
throw new BadRequestException(
|
||||||
|
'تعداد/مقدار اقلام بازگشتی نمیتواند از مقدار صورتحساب اصلی بیشتر باشد.',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const quantityRatio = requestedQuantity / originalQuantity
|
||||||
|
|
||||||
|
return {
|
||||||
|
invoice_id: originalItem.id,
|
||||||
|
good_id: originalItem.good_id,
|
||||||
|
service_id: originalItem.service_id || undefined,
|
||||||
|
quantity: requestedQuantity,
|
||||||
|
unit_price: Number(originalItem.unit_price),
|
||||||
|
total_amount: this.roundAmount(
|
||||||
|
Number(originalItem.total_amount) * quantityRatio,
|
||||||
|
),
|
||||||
|
discount_amount: this.roundAmount(
|
||||||
|
Number(originalItem.discount_amount || 0) * quantityRatio,
|
||||||
|
),
|
||||||
|
tax_amount: this.roundAmount(
|
||||||
|
Number(originalItem.tax_amount || 0) * quantityRatio,
|
||||||
|
),
|
||||||
|
payload: originalItem.payload
|
||||||
|
? JSON.parse(JSON.stringify(originalItem.payload))
|
||||||
|
: undefined,
|
||||||
|
notes: originalItem.notes || undefined,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!normalizedItems.length) {
|
||||||
|
throw new BadRequestException(
|
||||||
|
'حداقل یک قلم باید در صورتحساب بازگشتی باقی بماند.',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasRemovedItem = relatedInvoice.items.some(
|
||||||
|
item => !usedItemKeys.has(this.getReturnItemKey(item)),
|
||||||
|
)
|
||||||
|
const hasChangedQuantity = normalizedItems.some(item => {
|
||||||
|
const originalItem = relatedInvoice.items.find(
|
||||||
|
relatedItem =>
|
||||||
|
this.getReturnItemKey(relatedItem) === this.getReturnItemKey(item),
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!originalItem) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return Number(originalItem.quantity) !== Number(item.quantity)
|
||||||
|
})
|
||||||
|
const hasChangedInvoiceDate = normalizedInvoiceDate !== originalInvoiceDate
|
||||||
|
|
||||||
|
if (!hasRemovedItem && !hasChangedQuantity && !hasChangedInvoiceDate) {
|
||||||
|
throw new BadRequestException('مقداری تغییر نکرده است.')
|
||||||
|
}
|
||||||
|
|
||||||
|
const totalAmount = normalizedItems.reduce(
|
||||||
|
(sum, item) => sum + Number(item.total_amount),
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
const discountAmount = normalizedItems.reduce(
|
||||||
|
(sum, item) => sum + Number(item.discount_amount || 0),
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
const taxAmount = normalizedItems.reduce(
|
||||||
|
(sum, item) => sum + Number(item.tax_amount || 0),
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
|
||||||
|
const newInvoice = await this.sharedSaleInvoiceCreateService.create({
|
||||||
|
tx,
|
||||||
|
data: {
|
||||||
|
invoice_date: new Date(normalizedInvoiceDate),
|
||||||
|
items: normalizedItems as any,
|
||||||
|
total_amount: totalAmount,
|
||||||
|
discount_amount: discountAmount,
|
||||||
|
tax_amount: taxAmount,
|
||||||
|
customer_id: relatedInvoice.customer_id || undefined,
|
||||||
|
customer_type: relatedInvoice.customer?.type || CustomerType.UNKNOWN,
|
||||||
|
settlement_type: relatedInvoice.settlement_type,
|
||||||
|
payments: undefined,
|
||||||
|
} as any,
|
||||||
|
businessId: business_id,
|
||||||
|
complexId: complex_id,
|
||||||
|
posId: pos_id,
|
||||||
|
consumerAccountId,
|
||||||
|
main_invoice_id: relatedInvoice.main_id || relatedInvoice.id,
|
||||||
|
ref_invoice_id: relatedInvoice.id,
|
||||||
|
type: TspProviderRequestType.RETURN,
|
||||||
|
})
|
||||||
|
|
||||||
|
await tx.salesInvoice.update({
|
||||||
|
where: {
|
||||||
|
id: relatedInvoice.id,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
referenced_by: {
|
||||||
|
connect: {
|
||||||
|
id: newInvoice.id,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return newInvoice
|
||||||
|
})
|
||||||
|
|
||||||
|
return this.salesInvoiceTspService.returnFromSaleSend(
|
||||||
|
pos_id,
|
||||||
|
business_id,
|
||||||
|
newInvoice.id,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private normalizeInvoiceDate(invoiceDate: Date | string) {
|
||||||
|
return new Date(invoiceDate).toISOString()
|
||||||
|
}
|
||||||
|
|
||||||
|
private getItemKey(item: { good_id?: string | null; service_id?: string | null }) {
|
||||||
|
return item.good_id || item.service_id || ''
|
||||||
|
}
|
||||||
|
|
||||||
|
private getPaymentsAmount(payments?: {
|
||||||
|
terminals?: { amount?: number }
|
||||||
|
cash?: number
|
||||||
|
set_off?: number
|
||||||
|
card?: number
|
||||||
|
bank?: number
|
||||||
|
check?: number
|
||||||
|
other?: number
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
Number(payments?.terminals?.amount || 0) +
|
||||||
|
Number(payments?.cash || 0) +
|
||||||
|
Number(payments?.set_off || 0) +
|
||||||
|
Number(payments?.card || 0) +
|
||||||
|
Number(payments?.bank || 0) +
|
||||||
|
Number(payments?.check || 0) +
|
||||||
|
Number(payments?.other || 0)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private roundAmount(amount: number) {
|
||||||
|
return Number(amount.toFixed(2))
|
||||||
|
}
|
||||||
|
|
||||||
|
async inquiry(consumerAccountId: string, posId: string, invoiceId: string) {
|
||||||
|
const consumerId = await this.saleInvoiceAccessService.getConsumerIdWithPosAccess(
|
||||||
|
consumerAccountId,
|
||||||
|
posId,
|
||||||
|
)
|
||||||
|
return this.salesInvoiceTspService.get(invoiceId, posId, consumerId)
|
||||||
|
}
|
||||||
|
|
||||||
|
private getReturnItemKey(item: {
|
||||||
|
good_id?: string | null
|
||||||
|
service_id?: string | null
|
||||||
|
}) {
|
||||||
|
return item.good_id || item.service_id || ''
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,247 @@
|
|||||||
|
import type { SaleInvoiceType } from '@/common/interfaces/sale-invoice-payload'
|
||||||
|
import { ApiProperty, OmitType } from '@nestjs/swagger'
|
||||||
|
import { Type } from 'class-transformer'
|
||||||
|
import {
|
||||||
|
ArrayMinSize,
|
||||||
|
IsBoolean,
|
||||||
|
IsDate,
|
||||||
|
IsDateString,
|
||||||
|
IsEnum,
|
||||||
|
IsNotEmpty,
|
||||||
|
IsNumber,
|
||||||
|
IsObject,
|
||||||
|
IsOptional,
|
||||||
|
IsString,
|
||||||
|
Min,
|
||||||
|
ValidateNested,
|
||||||
|
} from 'class-validator'
|
||||||
|
import {
|
||||||
|
CustomerIndividual,
|
||||||
|
CustomerLegal,
|
||||||
|
InvoiceSettlementType,
|
||||||
|
} from 'generated/prisma/client'
|
||||||
|
import { CustomerType } from 'generated/prisma/enums'
|
||||||
|
|
||||||
|
export class SharedCreateSalesInvoiceItemDto {
|
||||||
|
@IsNumber()
|
||||||
|
@ApiProperty({ required: true })
|
||||||
|
unit_price: number
|
||||||
|
|
||||||
|
@IsNumber()
|
||||||
|
@ApiProperty({ required: true, default: 1 })
|
||||||
|
quantity: number
|
||||||
|
|
||||||
|
@IsNumber()
|
||||||
|
@ApiProperty({ required: true })
|
||||||
|
discount_amount: number
|
||||||
|
|
||||||
|
@IsNumber()
|
||||||
|
@ApiProperty({ required: true })
|
||||||
|
tax_amount: number
|
||||||
|
|
||||||
|
@IsNumber()
|
||||||
|
@ApiProperty({ required: true })
|
||||||
|
total_amount: number
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@ApiProperty({ required: true })
|
||||||
|
invoice_id: string
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
@ApiProperty({ required: false })
|
||||||
|
good_id?: string
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
@ApiProperty({ required: false })
|
||||||
|
service_id?: string
|
||||||
|
|
||||||
|
// @IsEnum(SalesInvoiceItemPricingModel)
|
||||||
|
// @ApiProperty({ enum: Object.values(SalesInvoiceItemPricingModel) })
|
||||||
|
// @IsOptional()
|
||||||
|
// pricingModel: SalesInvoiceItemPricingModel
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsObject()
|
||||||
|
@ApiProperty({ required: false, default: {} })
|
||||||
|
payload: SaleInvoiceType
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
@ApiProperty({ required: false, default: '' })
|
||||||
|
notes: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SharedCreateTerminalPayment {
|
||||||
|
@IsOptional()
|
||||||
|
@IsNumber()
|
||||||
|
@Min(0)
|
||||||
|
@ApiProperty({ required: false, default: 0 })
|
||||||
|
amount?: number
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
@ApiProperty({ required: true })
|
||||||
|
terminal_id: string
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
@ApiProperty({ required: true })
|
||||||
|
stan: string
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsNotEmpty()
|
||||||
|
@ApiProperty({ required: true })
|
||||||
|
rrn: string
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
@ApiProperty({ required: true })
|
||||||
|
response_code?: string
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
@ApiProperty({ required: true })
|
||||||
|
customer_card_no?: string
|
||||||
|
|
||||||
|
@Type(() => Date)
|
||||||
|
@IsDate()
|
||||||
|
@ApiProperty({ required: true })
|
||||||
|
transaction_date_time: Date
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
@ApiProperty({ required: false })
|
||||||
|
description?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SharedCreateSalesInvoicePaymentsDto {
|
||||||
|
@IsOptional()
|
||||||
|
@ValidateNested()
|
||||||
|
@Type(() => SharedCreateTerminalPayment)
|
||||||
|
@ApiProperty({ required: false, type: () => SharedCreateTerminalPayment })
|
||||||
|
terminals?: SharedCreateTerminalPayment
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsNumber()
|
||||||
|
@Min(0)
|
||||||
|
@ApiProperty({ required: false, default: 0 })
|
||||||
|
cash?: number
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsNumber()
|
||||||
|
@Min(0)
|
||||||
|
@ApiProperty({ required: false, default: 0 })
|
||||||
|
set_off?: number
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsNumber()
|
||||||
|
@Min(0)
|
||||||
|
@ApiProperty({ required: false, default: 0 })
|
||||||
|
card?: number
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsNumber()
|
||||||
|
@Min(0)
|
||||||
|
@ApiProperty({ required: false, default: 0 })
|
||||||
|
bank?: number
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsNumber()
|
||||||
|
@Min(0)
|
||||||
|
@ApiProperty({ required: false, default: 0 })
|
||||||
|
check?: number
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsNumber()
|
||||||
|
@Min(0)
|
||||||
|
@ApiProperty({ required: false, default: 0 })
|
||||||
|
other?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SharedCreateSalesInvoiceDto {
|
||||||
|
// @TODO: totalAmount must calculated instead of get from api
|
||||||
|
@IsNumber()
|
||||||
|
@ApiProperty({ required: true, default: 0 })
|
||||||
|
total_amount: number
|
||||||
|
|
||||||
|
@IsNumber()
|
||||||
|
@ApiProperty({ required: true, default: 0 })
|
||||||
|
discount_amount: number
|
||||||
|
|
||||||
|
@IsNumber()
|
||||||
|
@ApiProperty({ required: true, default: 0 })
|
||||||
|
tax_amount: number
|
||||||
|
|
||||||
|
@ApiProperty({ required: true })
|
||||||
|
@IsDateString(
|
||||||
|
{ strict: true },
|
||||||
|
{ message: 'invoice_date must be a valid ISO-8601 string' },
|
||||||
|
)
|
||||||
|
invoice_date: Date
|
||||||
|
|
||||||
|
@ApiProperty({ required: true, enum: InvoiceSettlementType })
|
||||||
|
@IsEnum(InvoiceSettlementType)
|
||||||
|
settlement_type: InvoiceSettlementType
|
||||||
|
|
||||||
|
@ApiProperty({ required: true })
|
||||||
|
@IsObject()
|
||||||
|
@ValidateNested({ each: true })
|
||||||
|
@Type(() => SharedCreateSalesInvoicePaymentsDto)
|
||||||
|
payments: SharedCreateSalesInvoicePaymentsDto
|
||||||
|
|
||||||
|
@ApiProperty()
|
||||||
|
@ArrayMinSize(1)
|
||||||
|
@ValidateNested({ each: true })
|
||||||
|
items: SharedCreateSalesInvoiceItemDto[]
|
||||||
|
|
||||||
|
@ApiProperty({ required: false })
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
ref_invoice_id?: string
|
||||||
|
|
||||||
|
@ApiProperty({ required: false })
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
notes?: string
|
||||||
|
|
||||||
|
@ApiProperty({ required: false, default: false })
|
||||||
|
@IsOptional()
|
||||||
|
@IsBoolean()
|
||||||
|
send_to_tsp?: boolean
|
||||||
|
|
||||||
|
@ApiProperty({ required: true, default: CustomerType.UNKNOWN })
|
||||||
|
@IsEnum(CustomerType)
|
||||||
|
customer_type: CustomerType
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
@ApiProperty({ required: false })
|
||||||
|
customer_id?: string
|
||||||
|
|
||||||
|
@ApiProperty({ required: false })
|
||||||
|
@IsOptional()
|
||||||
|
@IsObject()
|
||||||
|
customer?: {
|
||||||
|
customer_individual?: Omit<CustomerIndividual, 'business_activity_id' | 'customer_id'>
|
||||||
|
customer_legal?: Omit<CustomerLegal, 'business_activity_id' | 'customer_id'>
|
||||||
|
customer_unknown?: {
|
||||||
|
first_name: string
|
||||||
|
last_name: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SharedCorrectionSalesInvoiceDto extends OmitType(
|
||||||
|
SharedCreateSalesInvoiceDto,
|
||||||
|
['customer', 'customer_id', 'customer_type', 'settlement_type'],
|
||||||
|
) {}
|
||||||
|
|
||||||
|
export class SharedReturnSalesInvoiceDto extends OmitType(SharedCreateSalesInvoiceDto, [
|
||||||
|
'customer',
|
||||||
|
'customer_id',
|
||||||
|
'customer_type',
|
||||||
|
'settlement_type',
|
||||||
|
'payments',
|
||||||
|
]) {}
|
||||||
@@ -0,0 +1,574 @@
|
|||||||
|
import { QUERY_CONSTANTS } from '@/common/queryConstants'
|
||||||
|
import { SalesInvoiceCreateInput } from '@/generated/prisma/models'
|
||||||
|
import { PrismaService } from '@/prisma/prisma.service'
|
||||||
|
import { BadRequestException, Injectable } from '@nestjs/common'
|
||||||
|
import { Prisma } from 'generated/prisma/client'
|
||||||
|
import {
|
||||||
|
CustomerType,
|
||||||
|
PaymentMethodType,
|
||||||
|
TspProviderRequestType,
|
||||||
|
} from 'generated/prisma/enums'
|
||||||
|
import { SharedCreateSalesInvoiceDto } from './sale-invoice-create.dto'
|
||||||
|
|
||||||
|
interface TerminalPaymentInfo {
|
||||||
|
terminal_id: string
|
||||||
|
stan: string
|
||||||
|
rrn: string
|
||||||
|
transaction_date_time: string | Date
|
||||||
|
customer_card_no: string
|
||||||
|
description?: string
|
||||||
|
amount: number
|
||||||
|
}
|
||||||
|
|
||||||
|
interface NormalizedPayment {
|
||||||
|
method: PaymentMethodType
|
||||||
|
amount: number
|
||||||
|
terminalInfo?: TerminalPaymentInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CreateSharedSaleInvoiceInput {
|
||||||
|
tx?: Prisma.TransactionClient
|
||||||
|
data: SharedCreateSalesInvoiceDto
|
||||||
|
businessId: string
|
||||||
|
complexId: string
|
||||||
|
posId: string
|
||||||
|
consumerAccountId: string
|
||||||
|
type: TspProviderRequestType
|
||||||
|
main_invoice_id?: string
|
||||||
|
ref_invoice_id?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class SharedSaleInvoiceCreateService {
|
||||||
|
private readonly createInvoiceRetries = 3
|
||||||
|
|
||||||
|
constructor(private prisma: PrismaService) {}
|
||||||
|
|
||||||
|
async create(input: CreateSharedSaleInvoiceInput) {
|
||||||
|
const {
|
||||||
|
tx = this.prisma,
|
||||||
|
data,
|
||||||
|
businessId,
|
||||||
|
complexId,
|
||||||
|
posId,
|
||||||
|
consumerAccountId,
|
||||||
|
type,
|
||||||
|
main_invoice_id,
|
||||||
|
ref_invoice_id,
|
||||||
|
} = input
|
||||||
|
|
||||||
|
const normalizedInvoiceDate = this.normalizeInvoiceDate(data.invoice_date)
|
||||||
|
const payments =
|
||||||
|
type === TspProviderRequestType.ORIGINAL || data.payments
|
||||||
|
? this.buildPaymentsData(data.payments, data.total_amount)
|
||||||
|
: []
|
||||||
|
|
||||||
|
for (let attempt = 1; attempt <= this.createInvoiceRetries; attempt++) {
|
||||||
|
try {
|
||||||
|
return await tx.$transaction(async $tx => {
|
||||||
|
const invoiceNumber = await this.getNextInvoiceNumber($tx, businessId)
|
||||||
|
const customerId = await this.resolveCustomerId($tx, data, businessId)
|
||||||
|
const goodsById = await this.getGoodsById($tx, data)
|
||||||
|
const salesInvoiceData = this.buildSalesInvoiceData({
|
||||||
|
data,
|
||||||
|
normalizedInvoiceDate,
|
||||||
|
invoiceNumber,
|
||||||
|
consumerAccountId,
|
||||||
|
businessId,
|
||||||
|
complexId,
|
||||||
|
posId,
|
||||||
|
goodsById,
|
||||||
|
customerId,
|
||||||
|
type,
|
||||||
|
main_invoice_id,
|
||||||
|
ref_invoice_id,
|
||||||
|
})
|
||||||
|
|
||||||
|
const salesInvoice = await $tx.salesInvoice.create({
|
||||||
|
data: salesInvoiceData,
|
||||||
|
select: { ...QUERY_CONSTANTS.SALE_INVOICE.select },
|
||||||
|
})
|
||||||
|
|
||||||
|
if (payments.length) {
|
||||||
|
await this.createPayments(
|
||||||
|
$tx,
|
||||||
|
salesInvoice.id,
|
||||||
|
payments,
|
||||||
|
normalizedInvoiceDate,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return salesInvoice
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
if (
|
||||||
|
this.isRetryableInvoiceConflict(error) &&
|
||||||
|
attempt < this.createInvoiceRetries
|
||||||
|
) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new BadRequestException('ایجاد صورتحساب با خطا مواجه شد.')
|
||||||
|
}
|
||||||
|
|
||||||
|
private isRetryableInvoiceConflict(error: unknown) {
|
||||||
|
if (!(error instanceof Prisma.PrismaClientKnownRequestError)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error.code !== 'P2002') {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
const target = (error.meta?.target as string[]) || []
|
||||||
|
return (
|
||||||
|
target.includes('invoice_number') ||
|
||||||
|
target.includes('sales_invoices_invoice_number_pos_id_key')
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private normalizeInvoiceDate(invoiceDate: Date | string) {
|
||||||
|
return new Date(invoiceDate).toISOString() as any
|
||||||
|
}
|
||||||
|
|
||||||
|
private buildPaymentsData(
|
||||||
|
paymentsData: SharedCreateSalesInvoiceDto['payments'],
|
||||||
|
totalAmount: number,
|
||||||
|
) {
|
||||||
|
const paymentMethodMap: Record<string, PaymentMethodType> = {
|
||||||
|
cash: PaymentMethodType.CASH,
|
||||||
|
set_off: PaymentMethodType.SET_OFF,
|
||||||
|
card: PaymentMethodType.CARD,
|
||||||
|
payment_gateway: PaymentMethodType.PAYMENT_GATEWAY,
|
||||||
|
bank: PaymentMethodType.BANK,
|
||||||
|
check: PaymentMethodType.CHEQUE,
|
||||||
|
other: PaymentMethodType.OTHER,
|
||||||
|
terminal: PaymentMethodType.TERMINAL,
|
||||||
|
}
|
||||||
|
|
||||||
|
const rawPayments = (paymentsData || {}) as Record<string, unknown>
|
||||||
|
const terminalPayments = rawPayments.terminals as TerminalPaymentInfo[] | undefined
|
||||||
|
|
||||||
|
const payments: NormalizedPayment[] = Object.entries(rawPayments)
|
||||||
|
.filter(([key, value]) => key !== 'terminals' && value && Number(value) > 0)
|
||||||
|
.map(([key, value]) => ({
|
||||||
|
method: paymentMethodMap[key.toLowerCase()],
|
||||||
|
amount: typeof value === 'number' ? value : Number(value || 0),
|
||||||
|
}))
|
||||||
|
.filter(payment => payment.method && payment.amount > 0) as NormalizedPayment[]
|
||||||
|
|
||||||
|
const hasTerminalPayment = terminalPayments && terminalPayments.length
|
||||||
|
|
||||||
|
if (hasTerminalPayment) {
|
||||||
|
for (const terminal of terminalPayments) {
|
||||||
|
payments.push({
|
||||||
|
method: PaymentMethodType.TERMINAL,
|
||||||
|
amount: terminal.amount,
|
||||||
|
terminalInfo: terminal,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: for correction i need to validate payments with diff of total amount and original invoice amount
|
||||||
|
// this.validatePayments(payments, totalAmount)
|
||||||
|
|
||||||
|
return payments
|
||||||
|
}
|
||||||
|
|
||||||
|
private validatePayments(payments: NormalizedPayment[], totalAmount: number) {
|
||||||
|
const totalPayments = payments.reduce((sum, payment) => sum + payment.amount, 0)
|
||||||
|
const roundedTotalPayments = Number(totalPayments.toFixed(2))
|
||||||
|
const roundedTotalAmount = Number(Number(totalAmount).toFixed(2))
|
||||||
|
|
||||||
|
if (roundedTotalPayments !== roundedTotalAmount) {
|
||||||
|
throw new BadRequestException('مبلغ پرداختی باید برابر با مبلغ کل صورتحساب باشد.')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async resolveCustomerId(
|
||||||
|
tx: Prisma.TransactionClient,
|
||||||
|
data: SharedCreateSalesInvoiceDto,
|
||||||
|
businessId: string,
|
||||||
|
) {
|
||||||
|
const { customer_id, customer_type, customer } = data
|
||||||
|
|
||||||
|
if (customer_id) {
|
||||||
|
return customer_id
|
||||||
|
}
|
||||||
|
|
||||||
|
if (customer_type === CustomerType.INDIVIDUAL && customer?.customer_individual) {
|
||||||
|
const { national_id, postal_code, economic_code, ...rest } =
|
||||||
|
customer.customer_individual
|
||||||
|
|
||||||
|
const foundedCustomer = await tx.customerIndividual.findFirst({
|
||||||
|
where: {
|
||||||
|
business_activity_id: businessId,
|
||||||
|
OR: [
|
||||||
|
{
|
||||||
|
economic_code,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
postal_code,
|
||||||
|
national_id,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
customer_id: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
let customerIndividualId: string | undefined = foundedCustomer?.customer_id
|
||||||
|
|
||||||
|
if (foundedCustomer) {
|
||||||
|
await tx.customerIndividual.update({
|
||||||
|
where: {
|
||||||
|
customer_id: foundedCustomer.customer_id,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
...customer.customer_individual,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
const createdCustomer = await tx.customerIndividual.create({
|
||||||
|
data: {
|
||||||
|
...customer.customer_individual,
|
||||||
|
customer: {
|
||||||
|
create: {
|
||||||
|
type: CustomerType.INDIVIDUAL,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
business_activity: {
|
||||||
|
connect: {
|
||||||
|
id: businessId,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
customerIndividualId = createdCustomer.customer_id
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!customerIndividualId) {
|
||||||
|
throw new BadRequestException('متاسفانه مشکلی در اطلاعات مشتری وجود دارد.')
|
||||||
|
}
|
||||||
|
|
||||||
|
return customerIndividualId
|
||||||
|
} else if (customer_type === CustomerType.LEGAL && customer?.customer_legal) {
|
||||||
|
const { registration_number, economic_code, postal_code } = customer.customer_legal
|
||||||
|
const foundedCustomer = await tx.customerLegal.findFirst({
|
||||||
|
where: {
|
||||||
|
business_activity_id: businessId,
|
||||||
|
OR: [
|
||||||
|
{
|
||||||
|
economic_code,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
postal_code,
|
||||||
|
registration_number,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
customer_id: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
let customerLegalId: string | undefined = foundedCustomer?.customer_id
|
||||||
|
|
||||||
|
if (foundedCustomer) {
|
||||||
|
await tx.customerLegal.update({
|
||||||
|
where: {
|
||||||
|
customer_id: foundedCustomer.customer_id,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
...customer.customer_legal,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
const createdCustomer = await tx.customerLegal.create({
|
||||||
|
data: {
|
||||||
|
...customer.customer_legal,
|
||||||
|
customer: {
|
||||||
|
create: {
|
||||||
|
type: CustomerType.LEGAL,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
business_activity: {
|
||||||
|
connect: {
|
||||||
|
id: businessId,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
customerLegalId = createdCustomer.customer_id
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!customerLegalId) {
|
||||||
|
throw new BadRequestException('متاسفانه مشکلی در اطلاعات مشتری وجود دارد.')
|
||||||
|
}
|
||||||
|
|
||||||
|
return customerLegalId
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getGoodsById(
|
||||||
|
tx: Prisma.TransactionClient,
|
||||||
|
data: SharedCreateSalesInvoiceDto,
|
||||||
|
) {
|
||||||
|
const itemGoodIds = data.items
|
||||||
|
.map(item => item.good_id)
|
||||||
|
.filter((goodId): goodId is string => Boolean(goodId))
|
||||||
|
|
||||||
|
const goods = itemGoodIds.length
|
||||||
|
? await tx.good.findMany({
|
||||||
|
where: {
|
||||||
|
id: {
|
||||||
|
in: itemGoodIds,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
name: true,
|
||||||
|
sku: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
name: true,
|
||||||
|
code: true,
|
||||||
|
VAT: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
local_sku: true,
|
||||||
|
barcode: true,
|
||||||
|
pricing_model: true,
|
||||||
|
measure_unit: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
name: true,
|
||||||
|
code: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
base_sale_price: true,
|
||||||
|
image_url: true,
|
||||||
|
category: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
name: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
: []
|
||||||
|
|
||||||
|
return new Map(goods.map(good => [good.id, good]))
|
||||||
|
}
|
||||||
|
|
||||||
|
private buildSalesInvoiceData(params: {
|
||||||
|
data: SharedCreateSalesInvoiceDto
|
||||||
|
normalizedInvoiceDate: Date
|
||||||
|
invoiceNumber: number
|
||||||
|
consumerAccountId: string
|
||||||
|
businessId: string
|
||||||
|
complexId: string
|
||||||
|
posId: string
|
||||||
|
goodsById: Map<string, any>
|
||||||
|
customerId: string | null
|
||||||
|
type: TspProviderRequestType
|
||||||
|
main_invoice_id?: string
|
||||||
|
ref_invoice_id?: string
|
||||||
|
}) {
|
||||||
|
const {
|
||||||
|
data,
|
||||||
|
normalizedInvoiceDate,
|
||||||
|
invoiceNumber,
|
||||||
|
consumerAccountId,
|
||||||
|
posId,
|
||||||
|
goodsById,
|
||||||
|
customerId,
|
||||||
|
businessId,
|
||||||
|
complexId,
|
||||||
|
type,
|
||||||
|
main_invoice_id,
|
||||||
|
ref_invoice_id,
|
||||||
|
} = params
|
||||||
|
const {
|
||||||
|
customer_id,
|
||||||
|
customer_type,
|
||||||
|
customer,
|
||||||
|
payments,
|
||||||
|
settlement_type,
|
||||||
|
send_to_tsp,
|
||||||
|
...invoiceData
|
||||||
|
} = data
|
||||||
|
|
||||||
|
if (
|
||||||
|
type !== TspProviderRequestType.ORIGINAL &&
|
||||||
|
!(main_invoice_id || ref_invoice_id)
|
||||||
|
) {
|
||||||
|
throw new BadRequestException('متاسفانه مشکلی در اطلاعات صورتحساب وجود دارد.')
|
||||||
|
}
|
||||||
|
|
||||||
|
const salesInvoiceData: SalesInvoiceCreateInput = {
|
||||||
|
...invoiceData,
|
||||||
|
invoice_date: normalizedInvoiceDate,
|
||||||
|
invoice_number: invoiceNumber,
|
||||||
|
total_amount: data.total_amount,
|
||||||
|
discount_amount: data.items.reduce(
|
||||||
|
(prev, curr) => (prev += curr.discount_amount),
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
tax_amount: data.items.reduce((prev, curr) => (prev += curr.tax_amount), 0),
|
||||||
|
code: this.generateInvoiceCode(businessId, complexId, posId, invoiceNumber),
|
||||||
|
type,
|
||||||
|
settlement_type,
|
||||||
|
items: {
|
||||||
|
createMany: {
|
||||||
|
data: data.items.map(item => ({
|
||||||
|
good_id: item.good_id!,
|
||||||
|
quantity: item.quantity,
|
||||||
|
unit_price: item.unit_price,
|
||||||
|
total_amount: item.total_amount,
|
||||||
|
discount_amount: item.discount_amount,
|
||||||
|
tax_amount: item.tax_amount,
|
||||||
|
measure_unit_text: goodsById.get(item.good_id!)?.measure_unit.name || null,
|
||||||
|
measure_unit_code: goodsById.get(item.good_id!)?.measure_unit.code || null,
|
||||||
|
sku_code: goodsById.get(item.good_id!)?.sku.code || null,
|
||||||
|
sku_vat: goodsById.get(item.good_id!)?.sku.VAT || null,
|
||||||
|
payload: item.payload ? JSON.parse(JSON.stringify(item.payload)) : undefined,
|
||||||
|
good_snapshot: item.good_id
|
||||||
|
? JSON.parse(JSON.stringify(goodsById.get(item.good_id) || null))
|
||||||
|
: undefined,
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
unknown_customer: {},
|
||||||
|
consumer_account: {
|
||||||
|
connect: {
|
||||||
|
id: consumerAccountId,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
pos: {
|
||||||
|
connect: {
|
||||||
|
id: posId,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if (customerId) {
|
||||||
|
salesInvoiceData.customer = {
|
||||||
|
connect: {
|
||||||
|
id: customerId,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else if (data.customer?.customer_unknown) {
|
||||||
|
salesInvoiceData.unknown_customer = data.customer.customer_unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type !== TspProviderRequestType.ORIGINAL) {
|
||||||
|
salesInvoiceData.main_id = main_invoice_id
|
||||||
|
salesInvoiceData.reference_invoice = {
|
||||||
|
connect: {
|
||||||
|
id: ref_invoice_id,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return salesInvoiceData
|
||||||
|
}
|
||||||
|
|
||||||
|
async getNextInvoiceNumber(tx: Prisma.TransactionClient, businessId: string) {
|
||||||
|
const latestInvoice = await tx.salesInvoice.findFirst({
|
||||||
|
where: {
|
||||||
|
pos: {
|
||||||
|
complex: {
|
||||||
|
business_activity_id: businessId,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
orderBy: {
|
||||||
|
invoice_number: 'desc',
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
invoice_number: true,
|
||||||
|
pos: {
|
||||||
|
select: {
|
||||||
|
complex: {
|
||||||
|
select: {
|
||||||
|
business_activity: {
|
||||||
|
select: {
|
||||||
|
invoice_number_sequence: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const latestSequence =
|
||||||
|
latestInvoice?.pos?.complex?.business_activity?.invoice_number_sequence.toNumber() ||
|
||||||
|
0
|
||||||
|
|
||||||
|
return Math.max(latestInvoice?.invoice_number || 0, latestSequence) + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
private async createPayments(
|
||||||
|
tx: Prisma.TransactionClient,
|
||||||
|
invoiceId: string,
|
||||||
|
payments: NormalizedPayment[],
|
||||||
|
paidAt: Date,
|
||||||
|
) {
|
||||||
|
for (const payment of payments) {
|
||||||
|
if (payment.amount <= 0) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const createdPayment = await tx.salesInvoicePayment.create({
|
||||||
|
data: {
|
||||||
|
invoice_id: invoiceId,
|
||||||
|
amount: payment.amount,
|
||||||
|
payment_method: payment.method,
|
||||||
|
paid_at: paidAt,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if (payment.method === PaymentMethodType.TERMINAL && payment.terminalInfo) {
|
||||||
|
const {
|
||||||
|
terminal_id,
|
||||||
|
stan,
|
||||||
|
rrn,
|
||||||
|
transaction_date_time,
|
||||||
|
customer_card_no,
|
||||||
|
description,
|
||||||
|
} = payment.terminalInfo
|
||||||
|
await tx.salesInvoicePaymentTerminalInfo.create({
|
||||||
|
data: {
|
||||||
|
payment_id: createdPayment.id,
|
||||||
|
terminal_id,
|
||||||
|
stan: stan,
|
||||||
|
rrn: rrn,
|
||||||
|
transaction_date_time: transaction_date_time
|
||||||
|
? new Date(transaction_date_time)
|
||||||
|
: new Date(),
|
||||||
|
customer_card_no: '1234567890123456',
|
||||||
|
// customer_card_no: customer_card_no || null,
|
||||||
|
description: description || null,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private generateInvoiceCode(
|
||||||
|
businessId: string,
|
||||||
|
complexId: string,
|
||||||
|
posId: string,
|
||||||
|
invoiceNumber: number,
|
||||||
|
) {
|
||||||
|
return `${businessId.substring(businessId.length - 2, businessId.length)}${complexId.substring(complexId.length - 2, complexId.length)}${posId.substring(posId.length - 2, posId.length)}${invoiceNumber.toString()}`
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
import { ApiPropertyOptional } from '@nestjs/swagger'
|
||||||
|
import { Type } from 'class-transformer'
|
||||||
|
import {
|
||||||
|
IsDateString,
|
||||||
|
IsEnum,
|
||||||
|
IsNumber,
|
||||||
|
IsOptional,
|
||||||
|
IsString,
|
||||||
|
Min,
|
||||||
|
} from 'class-validator'
|
||||||
|
import { TspProviderResponseStatus } from 'generated/prisma/enums'
|
||||||
|
|
||||||
|
export class SharedSaleInvoicesFilterDto {
|
||||||
|
@ApiPropertyOptional({ default: 1 })
|
||||||
|
@IsOptional()
|
||||||
|
@Type(() => Number)
|
||||||
|
@IsNumber()
|
||||||
|
@Min(1)
|
||||||
|
page?: number
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ default: 10 })
|
||||||
|
@IsOptional()
|
||||||
|
@Type(() => Number)
|
||||||
|
@IsNumber()
|
||||||
|
@Min(1)
|
||||||
|
perPage?: number
|
||||||
|
|
||||||
|
@ApiPropertyOptional()
|
||||||
|
@IsOptional()
|
||||||
|
@IsDateString()
|
||||||
|
invoice_date_from?: string
|
||||||
|
|
||||||
|
@ApiPropertyOptional()
|
||||||
|
@IsOptional()
|
||||||
|
@IsDateString()
|
||||||
|
invoice_date_to?: string
|
||||||
|
|
||||||
|
@ApiPropertyOptional()
|
||||||
|
@IsOptional()
|
||||||
|
@IsDateString()
|
||||||
|
created_at_from?: string
|
||||||
|
|
||||||
|
@ApiPropertyOptional()
|
||||||
|
@IsOptional()
|
||||||
|
@IsDateString()
|
||||||
|
created_at_to?: string
|
||||||
|
|
||||||
|
@ApiPropertyOptional()
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
customer_name?: string
|
||||||
|
|
||||||
|
@ApiPropertyOptional()
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
customer_mobile?: string
|
||||||
|
|
||||||
|
@ApiPropertyOptional()
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
customer_national_id?: string
|
||||||
|
|
||||||
|
@ApiPropertyOptional()
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
customer_economic_code?: string
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ enum: TspProviderResponseStatus })
|
||||||
|
@IsOptional()
|
||||||
|
@IsEnum(TspProviderResponseStatus)
|
||||||
|
status?: TspProviderResponseStatus
|
||||||
|
|
||||||
|
@ApiPropertyOptional()
|
||||||
|
@IsOptional()
|
||||||
|
@Type(() => Number)
|
||||||
|
@IsNumber()
|
||||||
|
total_amount?: number
|
||||||
|
|
||||||
|
@ApiPropertyOptional()
|
||||||
|
@IsOptional()
|
||||||
|
@Type(() => Number)
|
||||||
|
@IsNumber()
|
||||||
|
total_amount_from?: number
|
||||||
|
|
||||||
|
@ApiPropertyOptional()
|
||||||
|
@IsOptional()
|
||||||
|
@Type(() => Number)
|
||||||
|
@IsNumber()
|
||||||
|
total_amount_to?: number
|
||||||
|
}
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
import { TspProviderResponseStatus } from '@/generated/prisma/enums'
|
||||||
|
import { SalesInvoiceWhereInput } from '@/generated/prisma/models'
|
||||||
|
import { Injectable } from '@nestjs/common'
|
||||||
|
import { SharedSaleInvoicesFilterDto } from './sale-invoice-filter.dto'
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class SharedSaleInvoiceFilterService {
|
||||||
|
buildWhere(filter: SharedSaleInvoicesFilterDto): SalesInvoiceWhereInput {
|
||||||
|
const where: SalesInvoiceWhereInput = {}
|
||||||
|
|
||||||
|
if (filter.invoice_date_from || filter.invoice_date_to) {
|
||||||
|
where.invoice_date = {
|
||||||
|
...(filter.invoice_date_from ? { gte: new Date(filter.invoice_date_from) } : {}),
|
||||||
|
...(filter.invoice_date_to ? { lte: new Date(filter.invoice_date_to) } : {}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter.created_at_from || filter.created_at_to) {
|
||||||
|
where.created_at = {
|
||||||
|
...(filter.created_at_from ? { gte: new Date(filter.created_at_from) } : {}),
|
||||||
|
...(filter.created_at_to ? { lte: new Date(filter.created_at_to) } : {}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
filter.total_amount !== undefined ||
|
||||||
|
filter.total_amount_from !== undefined ||
|
||||||
|
filter.total_amount_to !== undefined
|
||||||
|
) {
|
||||||
|
where.total_amount = {
|
||||||
|
...(filter.total_amount !== undefined ? { equals: filter.total_amount } : {}),
|
||||||
|
...(filter.total_amount_from !== undefined
|
||||||
|
? { gte: filter.total_amount_from }
|
||||||
|
: {}),
|
||||||
|
...(filter.total_amount_to !== undefined ? { lte: filter.total_amount_to } : {}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
filter.customer_name?.trim() ||
|
||||||
|
filter.customer_mobile?.trim() ||
|
||||||
|
filter.customer_national_id?.trim() ||
|
||||||
|
filter.customer_economic_code?.trim()
|
||||||
|
) {
|
||||||
|
where.customer = {
|
||||||
|
is: {
|
||||||
|
OR: [
|
||||||
|
...(filter.customer_name?.trim()
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
individual: {
|
||||||
|
is: {
|
||||||
|
OR: [
|
||||||
|
{ first_name: { contains: filter.customer_name.trim() } },
|
||||||
|
{ last_name: { contains: filter.customer_name.trim() } },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
legal: {
|
||||||
|
is: {
|
||||||
|
name: {
|
||||||
|
contains: filter.customer_name.trim(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: []),
|
||||||
|
...(filter.customer_mobile?.trim()
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
individual: {
|
||||||
|
is: {
|
||||||
|
mobile_number: { contains: filter.customer_mobile.trim() },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: []),
|
||||||
|
...(filter.customer_national_id?.trim()
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
individual: {
|
||||||
|
is: {
|
||||||
|
national_id: { contains: filter.customer_national_id.trim() },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: []),
|
||||||
|
...(filter.customer_economic_code?.trim()
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
legal: {
|
||||||
|
is: {
|
||||||
|
OR: [
|
||||||
|
{
|
||||||
|
economic_code: {
|
||||||
|
contains: filter.customer_economic_code.trim(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
registration_number: {
|
||||||
|
contains: filter.customer_economic_code.trim(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: []),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter.status) {
|
||||||
|
if (filter.status === TspProviderResponseStatus.NOT_SEND) {
|
||||||
|
where.OR = [
|
||||||
|
{
|
||||||
|
last_tsp_status: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
last_tsp_status: TspProviderResponseStatus.NOT_SEND,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
} else {
|
||||||
|
where.last_tsp_status = filter.status
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return where
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { Injectable } from '@nestjs/common'
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class SharedSaleInvoicePaginationService {
|
||||||
|
normalize(
|
||||||
|
page: number = 1,
|
||||||
|
perPage: number = 10,
|
||||||
|
defaultPerPage: number = 10,
|
||||||
|
maxPerPage: number = 50,
|
||||||
|
) {
|
||||||
|
const normalizedPageValue = Number(page ?? 1)
|
||||||
|
const normalizedPage = Number.isFinite(normalizedPageValue)
|
||||||
|
? Math.max(1, Math.floor(normalizedPageValue))
|
||||||
|
: 1
|
||||||
|
|
||||||
|
const requestedPerPageValue = Number(perPage ?? defaultPerPage)
|
||||||
|
const requestedPerPage = Number.isFinite(requestedPerPageValue)
|
||||||
|
? Math.max(1, Math.floor(requestedPerPageValue))
|
||||||
|
: defaultPerPage
|
||||||
|
const normalizedPerPage = Math.min(requestedPerPage, maxPerPage)
|
||||||
|
|
||||||
|
return {
|
||||||
|
page: normalizedPage,
|
||||||
|
perPage: normalizedPerPage,
|
||||||
|
skip: (normalizedPage - 1) * normalizedPerPage,
|
||||||
|
take: normalizedPerPage,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
import dayjs, { Dayjs } from 'dayjs'
|
||||||
|
import 'dayjs/locale/fa'
|
||||||
|
import relativeTime from 'dayjs/plugin/relativeTime'
|
||||||
|
import jalaliPlugin from 'jalaliday/dayjs'
|
||||||
|
|
||||||
|
dayjs.extend(jalaliPlugin)
|
||||||
|
dayjs.extend(relativeTime)
|
||||||
|
|
||||||
|
export function toJalali(date: string | number | Date | Dayjs): Date {
|
||||||
|
return dayjs(date).calendar('jalali').toDate()
|
||||||
|
}
|
||||||
|
|
||||||
|
export function toGregorian(date: string | number | Date | Dayjs): Date {
|
||||||
|
return dayjs(date).calendar('gregory').toDate()
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCurrentJalaliSeasonStart(
|
||||||
|
baseDate: string | number | Date | Dayjs = dayjs(),
|
||||||
|
): Date {
|
||||||
|
const date = dayjs(baseDate).calendar('jalali')
|
||||||
|
const month = date.month() + 1
|
||||||
|
const seasonStartMonth = Math.floor((month - 1) / 3) * 3 + 1
|
||||||
|
return date
|
||||||
|
.month(seasonStartMonth - 1)
|
||||||
|
.startOf('month')
|
||||||
|
.startOf('day')
|
||||||
|
.toDate()
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCurrentJalaliSeasonEnd(
|
||||||
|
baseDate: string | number | Date | Dayjs = dayjs(),
|
||||||
|
): Date {
|
||||||
|
return dayjs(getCurrentJalaliSeasonStart(baseDate))
|
||||||
|
.add(3, 'month')
|
||||||
|
.endOf('month')
|
||||||
|
.endOf('day')
|
||||||
|
.toDate()
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCurrentGregorianSeasonStart(
|
||||||
|
baseDate: string | number | Date | Dayjs = dayjs(),
|
||||||
|
): Date {
|
||||||
|
const date = dayjs(baseDate).calendar('gregory')
|
||||||
|
const month = date.month() + 1
|
||||||
|
const seasonStartMonth = Math.floor((month - 1) / 3) * 3 + 1
|
||||||
|
return date
|
||||||
|
.month(seasonStartMonth - 1)
|
||||||
|
.startOf('month')
|
||||||
|
.startOf('day')
|
||||||
|
.toDate()
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCurrentGregorianSeasonEnd(
|
||||||
|
baseDate: string | number | Date | Dayjs = dayjs(),
|
||||||
|
): Date {
|
||||||
|
return dayjs(getCurrentGregorianSeasonStart(baseDate))
|
||||||
|
.add(2, 'month')
|
||||||
|
.endOf('month')
|
||||||
|
.endOf('day')
|
||||||
|
.toDate()
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCurrentJalaliSeasonRange(
|
||||||
|
baseDate: string | number | Date | Dayjs = dayjs(),
|
||||||
|
): { start: Date; end: Date } {
|
||||||
|
return {
|
||||||
|
start: getCurrentJalaliSeasonStart(baseDate),
|
||||||
|
end: getCurrentJalaliSeasonEnd(baseDate),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCurrentGregorianSeasonRange(
|
||||||
|
baseDate: string | number | Date | Dayjs = dayjs(),
|
||||||
|
): { start: Date; end: Date } {
|
||||||
|
return {
|
||||||
|
start: getCurrentGregorianSeasonStart(baseDate),
|
||||||
|
end: getCurrentGregorianSeasonEnd(baseDate),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
toJalali,
|
||||||
|
toGregorian,
|
||||||
|
getCurrentJalaliSeasonStart,
|
||||||
|
getCurrentJalaliSeasonEnd,
|
||||||
|
getCurrentGregorianSeasonStart,
|
||||||
|
getCurrentGregorianSeasonEnd,
|
||||||
|
getCurrentJalaliSeasonRange,
|
||||||
|
getCurrentGregorianSeasonRange,
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import translates from '@/common/constants/translates/translates'
|
||||||
|
|
||||||
|
type EnumTranslateMap = Record<string, string>
|
||||||
|
type EnumsRegistry = Record<string, EnumTranslateMap>
|
||||||
|
|
||||||
|
export interface EnumTranslatedValue {
|
||||||
|
value: string | null | undefined
|
||||||
|
translate: string | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export function translateEnumValue(
|
||||||
|
enumKey: keyof typeof translates.enums,
|
||||||
|
value: string | null | undefined,
|
||||||
|
): EnumTranslatedValue {
|
||||||
|
const enumsRegistry = translates.enums as EnumsRegistry
|
||||||
|
const enumMap = enumsRegistry[String(enumKey)]
|
||||||
|
|
||||||
|
if (!value) {
|
||||||
|
return {
|
||||||
|
value,
|
||||||
|
translate: null,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
value,
|
||||||
|
translate: enumMap?.[value] ?? null,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import { Matches, MinLength } from 'class-validator'
|
||||||
|
|
||||||
|
const MIN_LENGTH = 6
|
||||||
|
const REGEX = /^[a-zA-Z0-9]*$/
|
||||||
|
|
||||||
|
export const FiscalIdFieldValidator = () =>
|
||||||
|
function (target: object, propertyKey: string) {
|
||||||
|
MinLength(MIN_LENGTH, {
|
||||||
|
message: `شناسه یکتا باید حداقل ${MIN_LENGTH} کاراکتر باشد`,
|
||||||
|
})(target, propertyKey)
|
||||||
|
Matches(REGEX, {
|
||||||
|
message: 'شناسه یکتا فقط میتواند شامل حروف و اعداد باشد',
|
||||||
|
})(target, propertyKey)
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
export { FiscalIdFieldValidator } from './fiscalId-validator'
|
||||||
|
export { PasswordFieldValidator, PASSWORD_MIN_LENGTH } from './password'
|
||||||
|
export { UsernameFieldValidator } from './username'
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import { MinLength } from 'class-validator'
|
||||||
|
|
||||||
|
export const PASSWORD_MIN_LENGTH = 6
|
||||||
|
|
||||||
|
export const PasswordFieldValidator = () =>
|
||||||
|
function (target: object, propertyKey: string) {
|
||||||
|
MinLength(PASSWORD_MIN_LENGTH, {
|
||||||
|
message: `رمز عبور باید حداقل ${PASSWORD_MIN_LENGTH} کاراکتر باشد`,
|
||||||
|
})(target, propertyKey)
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import { Matches, MinLength } from 'class-validator'
|
||||||
|
|
||||||
|
const USERNAME_REGEX = /^[a-zA-Z0-9_-]*$/
|
||||||
|
const USERNAME_MIN_LENGTH = 6
|
||||||
|
|
||||||
|
export const UsernameFieldValidator = () =>
|
||||||
|
function (target: object, propertyKey: string) {
|
||||||
|
MinLength(USERNAME_MIN_LENGTH, {
|
||||||
|
message: `نام کاربری باید حداقل ${USERNAME_MIN_LENGTH} کاراکتر باشد`,
|
||||||
|
})(target, propertyKey)
|
||||||
|
Matches(USERNAME_REGEX, {
|
||||||
|
message: 'نام کاربری فقط میتواند شامل حروف، اعداد، زیرخط و خط تیره باشد',
|
||||||
|
})(target, propertyKey)
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
import {
|
||||||
|
FetchRequestContext,
|
||||||
|
FetchRequestInterceptor,
|
||||||
|
} from '@/common/interceptors/fetch-request.interceptor'
|
||||||
|
import { Injectable } from '@nestjs/common'
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class HttpClientUtil {
|
||||||
|
async request(
|
||||||
|
url: string,
|
||||||
|
init: RequestInit = {},
|
||||||
|
interceptors: FetchRequestInterceptor[] = [],
|
||||||
|
): Promise<Response> {
|
||||||
|
let context: FetchRequestContext = { url, init }
|
||||||
|
|
||||||
|
for (const interceptor of interceptors) {
|
||||||
|
if (!interceptor.onRequest) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
context = await interceptor.onRequest(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
let response = await fetch(context.url, context.init)
|
||||||
|
|
||||||
|
for (const interceptor of interceptors) {
|
||||||
|
if (!interceptor.onResponse) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
response = await interceptor.onResponse(context, response)
|
||||||
|
}
|
||||||
|
|
||||||
|
return response
|
||||||
|
} catch (error: any) {
|
||||||
|
for (const interceptor of interceptors) {
|
||||||
|
if (!interceptor.onError) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
await interceptor.onError(context, error)
|
||||||
|
}
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
export * from './date-formatter.utils'
|
||||||
|
export * from './enum-translator.util'
|
||||||
|
export * from './field-validator.util'
|
||||||
|
export * from './http-client.util'
|
||||||
|
export * from './jwt-user.util'
|
||||||
|
export * from './mappers/consumer_mappers.util'
|
||||||
|
export * from './password.util'
|
||||||
|
export * from './redisKeyMaker'
|
||||||
|
export * from './tracking-code-generator.util'
|
||||||
@@ -18,13 +18,13 @@ export function checkAndDecodeJwtToken(
|
|||||||
token = authHeader.slice(7)
|
token = authHeader.slice(7)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!token) throw new UnauthorizedException('Missing accessToken cookie')
|
if (!token) throw new UnauthorizedException('توکن احراز هویت ارسال نشده است')
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const payload = jwtService.decode(token) as AccessTokenPayload
|
const payload = jwtService.decode(token) as AccessTokenPayload
|
||||||
|
|
||||||
return payload as ITokenPayload
|
return payload as ITokenPayload
|
||||||
} catch {
|
} catch {
|
||||||
return null
|
throw new UnauthorizedException('توکن احراز هویت نامعتبر است')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
import { translateEnumValue } from '../enum-translator.util'
|
||||||
|
|
||||||
|
export default (consumer: any) => {
|
||||||
|
const { legal, individual, activation, type, status, _count, ...rest } = consumer
|
||||||
|
|
||||||
|
const { business_activities: business_counts } = _count || { business_activities: 0 }
|
||||||
|
const partner = legal?.partner || individual?.partner
|
||||||
|
delete legal?.partner
|
||||||
|
delete individual?.partner
|
||||||
|
|
||||||
|
const returnData = {
|
||||||
|
...rest,
|
||||||
|
partner,
|
||||||
|
type: translateEnumValue('ConsumerType', type),
|
||||||
|
status: translateEnumValue('ConsumerStatus', consumer.status),
|
||||||
|
legal: legal ? { ...legal } : null,
|
||||||
|
individual: individual
|
||||||
|
? { ...individual, fullname: `${individual?.first_name} ${individual?.last_name}` }
|
||||||
|
: null,
|
||||||
|
name: legal ? legal.name : `${individual?.first_name} ${individual?.last_name}`,
|
||||||
|
}
|
||||||
|
|
||||||
|
if (business_counts !== undefined) {
|
||||||
|
returnData['business_counts'] = business_counts
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnData
|
||||||
|
}
|
||||||
|
|
||||||
|
function prepareLicenseInfo(latestLicense: any) {
|
||||||
|
if (!latestLicense) return null
|
||||||
|
const { license, ...rest } = latestLicense
|
||||||
|
|
||||||
|
return {
|
||||||
|
...rest,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
import { BadRequestException, ConflictException } from '@nestjs/common'
|
||||||
|
import { Prisma } from 'generated/prisma/client'
|
||||||
|
|
||||||
|
type UniqueMessageMap = Record<string, string>
|
||||||
|
|
||||||
|
export class PrismaErrorUtil {
|
||||||
|
static isKnownError(error: unknown): error is Prisma.PrismaClientKnownRequestError {
|
||||||
|
return error instanceof Prisma.PrismaClientKnownRequestError
|
||||||
|
}
|
||||||
|
|
||||||
|
static isCode(error: unknown, code: string): boolean {
|
||||||
|
return this.isKnownError(error) && error.code === code
|
||||||
|
}
|
||||||
|
|
||||||
|
static hasTarget(error: unknown, targetKey: string): boolean {
|
||||||
|
if (!this.isKnownError(error)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const target = error.meta?.target as string[] | string | undefined
|
||||||
|
if (Array.isArray(target)) {
|
||||||
|
return target.includes(targetKey)
|
||||||
|
}
|
||||||
|
if (typeof target === 'string') {
|
||||||
|
return target.includes(targetKey)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
static throwIfKnown(error: unknown, uniqueMap: UniqueMessageMap = {}) {
|
||||||
|
if (!(error instanceof Prisma.PrismaClientKnownRequestError)) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error.code === 'P2002') {
|
||||||
|
const target = (error.meta?.target as string[]) || []
|
||||||
|
for (const key of Object.keys(uniqueMap)) {
|
||||||
|
if (target.includes(key)) {
|
||||||
|
throw new BadRequestException(uniqueMap[key])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new ConflictException('رکورد تکراری است.')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error.code === 'P2003') {
|
||||||
|
throw new BadRequestException('ارتباط دادهای نامعتبر است.')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error.code === 'P2025') {
|
||||||
|
throw new BadRequestException('رکورد مورد نظر یافت نشد.')
|
||||||
|
}
|
||||||
|
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
export class ConsumerKeyMaker {
|
||||||
|
static middleware(token: string): string {
|
||||||
|
return `consumer:middleware:${token}`
|
||||||
|
}
|
||||||
|
|
||||||
|
static consumerInfo(consumerId: string): string {
|
||||||
|
return `consumers:${consumerId}:info`
|
||||||
|
}
|
||||||
|
|
||||||
|
static consumerBusinessActivitiesList(consumerId: string): string {
|
||||||
|
return `consumers:${consumerId}:business-activities:list`
|
||||||
|
}
|
||||||
|
|
||||||
|
static consumerBusinessActivityInfo(
|
||||||
|
consumerId: string,
|
||||||
|
businessActivityId: string,
|
||||||
|
): string {
|
||||||
|
return `consumers:${consumerId}:business-activities:${businessActivityId}:info`
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
export class EnumKeyMaker {
|
||||||
|
static enumsAll(buildVersion: string): string {
|
||||||
|
return `enums:${buildVersion}:all`
|
||||||
|
}
|
||||||
|
|
||||||
|
static enumsValues(buildVersion: string, enumName: string): string {
|
||||||
|
return `enums:${buildVersion}:values:${enumName}`
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user