mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-24 08:39:49 +00:00
Compare commits
12 Commits
feature/20
...
20260129-2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6193358cc3 | ||
|
|
518abcd30d | ||
|
|
7874b9f765 | ||
|
|
02cc7e0c96 | ||
|
|
57cc513873 | ||
|
|
f5bfdede30 | ||
|
|
488556bb59 | ||
|
|
0fc5a66e95 | ||
|
|
d9ae51027e | ||
|
|
a92d6112d9 | ||
|
|
889b0cec4b | ||
|
|
1c4c41ebba |
93
.dockerignore
Normal file
93
.dockerignore
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
# Dependencies
|
||||||
|
node_modules/
|
||||||
|
**/node_modules/
|
||||||
|
.pnpm-store/
|
||||||
|
|
||||||
|
# Build outputs
|
||||||
|
dist/
|
||||||
|
build/
|
||||||
|
**/dist/
|
||||||
|
**/build/
|
||||||
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
# Development files
|
||||||
|
.git/
|
||||||
|
.gitignore
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*~
|
||||||
|
|
||||||
|
# Test files
|
||||||
|
test/
|
||||||
|
**/test/
|
||||||
|
**/*.spec.ts
|
||||||
|
**/*.test.ts
|
||||||
|
**/*.e2e-spec.ts
|
||||||
|
coverage/
|
||||||
|
.nyc_output/
|
||||||
|
test-results/
|
||||||
|
playwright-report/
|
||||||
|
|
||||||
|
# Documentation
|
||||||
|
*.md
|
||||||
|
!README.md
|
||||||
|
docs/
|
||||||
|
CHANGELOG.md
|
||||||
|
CONTRIBUTING.md
|
||||||
|
DISCLAIMER
|
||||||
|
LICENSE
|
||||||
|
|
||||||
|
# CI/CD
|
||||||
|
.github/
|
||||||
|
.gitpod.yml
|
||||||
|
|
||||||
|
# Environment files
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
!.env.example
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
*.log
|
||||||
|
logs/
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
|
||||||
|
# OS files
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Docker files (don't copy Dockerfiles into themselves)
|
||||||
|
docker-compose*.yml
|
||||||
|
Dockerfile*
|
||||||
|
.dockerignore
|
||||||
|
|
||||||
|
# Misc
|
||||||
|
.cache/
|
||||||
|
.temp/
|
||||||
|
tmp/
|
||||||
|
*.tmp
|
||||||
|
.qodo/
|
||||||
|
e2e/
|
||||||
|
playwright.config.ts
|
||||||
|
|
||||||
|
# Source maps (not needed in production)
|
||||||
|
*.map
|
||||||
|
|
||||||
|
# TypeScript configs (not needed at runtime)
|
||||||
|
tsconfig*.json
|
||||||
|
!tsconfig.json
|
||||||
|
|
||||||
|
# Linting/formatting
|
||||||
|
.eslintrc*
|
||||||
|
.prettierrc*
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Package manager locks (we copy them explicitly)
|
||||||
|
# pnpm-lock.yaml
|
||||||
@@ -58,6 +58,12 @@ services:
|
|||||||
# System database
|
# System database
|
||||||
- SYSTEM_DB_NAME=${SYSTEM_DB_NAME}
|
- SYSTEM_DB_NAME=${SYSTEM_DB_NAME}
|
||||||
|
|
||||||
|
# Redis
|
||||||
|
- REDIS_HOST=redis
|
||||||
|
- REDIS_PORT=6379
|
||||||
|
- QUEUE_HOST=redis
|
||||||
|
- QUEUE_PORT=6379
|
||||||
|
|
||||||
# Tenants databases
|
# Tenants databases
|
||||||
- TENANT_DB_NAME_PERFIX=${TENANT_DB_NAME_PERFIX}
|
- TENANT_DB_NAME_PERFIX=${TENANT_DB_NAME_PERFIX}
|
||||||
|
|
||||||
|
|||||||
@@ -35,4 +35,4 @@ WORKDIR /app/packages/server
|
|||||||
RUN git clone https://github.com/vishnubob/wait-for-it.git
|
RUN git clone https://github.com/vishnubob/wait-for-it.git
|
||||||
|
|
||||||
# Once we listen the mysql port run the migration task.
|
# Once we listen the mysql port run the migration task.
|
||||||
CMD ./wait-for-it/wait-for-it.sh mysql:3306 -- sh -c "node ./build/commands.js system:migrate:latest && node ./build/commands.js tenants:migrate:latest"
|
CMD ./wait-for-it/wait-for-it.sh mysql:3306 -- sh -c "pnpm run system:migrate:latest && pnpm run tenants:migrate:latest"
|
||||||
|
|||||||
@@ -1,100 +1,99 @@
|
|||||||
FROM node:18.16.0-alpine as build
|
# Stage 1: Build
|
||||||
|
FROM node:18.16.0-alpine AS builder
|
||||||
|
|
||||||
USER root
|
|
||||||
|
|
||||||
ARG MAIL_HOST= \
|
|
||||||
MAIL_USERNAME= \
|
|
||||||
MAIL_PASSWORD= \
|
|
||||||
MAIL_PORT= \
|
|
||||||
MAIL_SECURE= \
|
|
||||||
MAIL_FROM_NAME= \
|
|
||||||
MAIL_FROM_ADDRESS= \
|
|
||||||
# Database
|
|
||||||
DB_HOST= \
|
|
||||||
DB_USER= \
|
|
||||||
DB_PASSWORD= \
|
|
||||||
DB_CHARSET= \
|
|
||||||
# System database.
|
|
||||||
SYSTEM_DB_NAME= \
|
|
||||||
SYSTEM_DB_PASSWORD= \
|
|
||||||
SYSTEM_DB_USER= \
|
|
||||||
SYSTEM_DB_HOST= \
|
|
||||||
SYSTEM_DB_CHARSET= \
|
|
||||||
# Tenant databases.
|
|
||||||
TENANT_DB_USER= \
|
|
||||||
TENANT_DB_PASSWORD= \
|
|
||||||
TENANT_DB_HOST= \
|
|
||||||
TENANT_DB_NAME_PERFIX= \
|
|
||||||
TENANT_DB_CHARSET= \
|
|
||||||
# Authentication
|
|
||||||
JWT_SECRET= \
|
|
||||||
# Application
|
|
||||||
BASE_URL= \
|
|
||||||
# Sign-up restriction
|
|
||||||
SIGNUP_DISABLED= \
|
|
||||||
SIGNUP_ALLOWED_DOMAINS= \
|
|
||||||
SIGNUP_ALLOWED_EMAILS=
|
|
||||||
|
|
||||||
ENV MAIL_HOST=$MAIL_HOST \
|
|
||||||
MAIL_USERNAME=$MAIL_USERNAME \
|
|
||||||
MAIL_PASSWORD=$MAIL_PASSWORD \
|
|
||||||
MAIL_PORT=$MAIL_PORT \
|
|
||||||
MAIL_SECURE=$MAIL_SECURE \
|
|
||||||
MAIL_FROM_NAME=$MAIL_FROM_NAME \
|
|
||||||
MAIL_FROM_ADDRESS=$MAIL_FROM_ADDRESS \
|
|
||||||
# Database
|
|
||||||
DB_HOST=$DB_HOST \
|
|
||||||
DB_USER=$DB_USER \
|
|
||||||
DB_PASSWORD=$DB_PASSWORD \
|
|
||||||
DB_CHARSET=$DB_CHARSET \
|
|
||||||
# System database.
|
|
||||||
SYSTEM_DB_HOST=$SYSTEM_DB_HOST \
|
|
||||||
SYSTEM_DB_USER=$SYSTEM_DB_USER \
|
|
||||||
SYSTEM_DB_PASSWORD=$SYSTEM_DB_PASSWORD \
|
|
||||||
SYSTEM_DB_NAME=$SYSTEM_DB_NAME \
|
|
||||||
SYSTEM_DB_CHARSET=$SYSTEM_DB_CHARSET \
|
|
||||||
# Tenant databases.
|
|
||||||
TENANT_DB_NAME_PERFIX=$TENANT_DB_NAME_PERFIX \
|
|
||||||
TENANT_DB_HOST=$TENANT_DB_HOST \
|
|
||||||
TENANT_DB_PASSWORD=$TENANT_DB_PASSWORD \
|
|
||||||
TENANT_DB_USER=$TENANT_DB_USER \
|
|
||||||
TENANT_DB_CHARSET=$TENANT_DB_CHARSET \
|
|
||||||
# Authentication
|
|
||||||
JWT_SECRET=$JWT_SECRET \
|
|
||||||
# Application
|
|
||||||
BASE_URL=$BASE_URL \
|
|
||||||
# Sign-up restriction
|
|
||||||
SIGNUP_DISABLED=$SIGNUP_DISABLED \
|
|
||||||
SIGNUP_ALLOWED_DOMAINS=$SIGNUP_ALLOWED_DOMAINS \
|
|
||||||
SIGNUP_ALLOWED_EMAILS=$SIGNUP_ALLOWED_EMAILS
|
|
||||||
|
|
||||||
# New Relic config file.
|
|
||||||
ENV NEW_RELIC_NO_CONFIG_FILE=true
|
|
||||||
|
|
||||||
# Create app directory.
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
RUN chown node:node /
|
|
||||||
|
|
||||||
# Install pnpm
|
# Install pnpm
|
||||||
RUN npm install -g pnpm
|
RUN npm install -g pnpm@8.10.2
|
||||||
|
|
||||||
# Copy application dependency manifests to the container image.
|
# Install build dependencies
|
||||||
COPY --chown=node:node ./ ./
|
RUN apk add --no-cache python3 build-base chromium
|
||||||
|
|
||||||
# Install application dependencies
|
# Set Python environment
|
||||||
RUN apk update
|
|
||||||
RUN apk add python3 build-base chromium
|
|
||||||
|
|
||||||
# Set PYHTON env
|
|
||||||
ENV PYTHON=/usr/bin/python3
|
ENV PYTHON=/usr/bin/python3
|
||||||
|
|
||||||
# Install packages dependencies for production.
|
# Copy package files for dependency installation
|
||||||
RUN pnpm install
|
COPY --chown=node:node package.json pnpm-lock.yaml pnpm-workspace.yaml lerna.json ./
|
||||||
|
COPY --chown=node:node packages/server/package.json ./packages/server/
|
||||||
|
COPY --chown=node:node shared/bigcapital-utils/package.json ./shared/bigcapital-utils/
|
||||||
|
COPY --chown=node:node shared/pdf-templates/package.json ./shared/pdf-templates/
|
||||||
|
COPY --chown=node:node shared/email-components/package.json ./shared/email-components/
|
||||||
|
|
||||||
|
# Install all dependencies (including devDependencies for build)
|
||||||
|
RUN pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
# Copy source code
|
||||||
COPY --chown=node:node ./packages/server ./packages/server
|
COPY --chown=node:node ./packages/server ./packages/server
|
||||||
|
COPY --chown=node:node ./shared/bigcapital-utils ./shared/bigcapital-utils
|
||||||
|
COPY --chown=node:node ./shared/pdf-templates ./shared/pdf-templates
|
||||||
|
COPY --chown=node:node ./shared/email-components ./shared/email-components
|
||||||
|
|
||||||
# # Creates a "dist" folder with the production build
|
# Build NestJS application
|
||||||
RUN pnpm run build:server --skip-nx-cache
|
RUN pnpm run build:server --skip-nx-cache
|
||||||
|
|
||||||
CMD [ "node", "./packages/server/build/index.js" ]
|
# Stage 2: Production
|
||||||
|
FROM node:18.16.0-alpine AS production
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Install pnpm for production
|
||||||
|
RUN npm install -g pnpm@8.10.2
|
||||||
|
|
||||||
|
# Create non-root user
|
||||||
|
RUN addgroup -g 1001 -S nodejs && \
|
||||||
|
adduser -S nodejs -u 1001
|
||||||
|
|
||||||
|
# Install build dependencies for native modules (bcrypt, etc.)
|
||||||
|
RUN apk add --no-cache python3 build-base
|
||||||
|
|
||||||
|
# Set Python environment
|
||||||
|
ENV PYTHON=/usr/bin/python3
|
||||||
|
|
||||||
|
# Copy package files for production dependency installation
|
||||||
|
COPY --chown=nodejs:nodejs package.json pnpm-lock.yaml pnpm-workspace.yaml ./
|
||||||
|
COPY --chown=nodejs:nodejs packages/server/package.json ./packages/server/
|
||||||
|
COPY --chown=nodejs:nodejs shared/bigcapital-utils/package.json ./shared/bigcapital-utils/
|
||||||
|
COPY --chown=nodejs:nodejs shared/pdf-templates/package.json ./shared/pdf-templates/
|
||||||
|
COPY --chown=nodejs:nodejs shared/email-components/package.json ./shared/email-components/
|
||||||
|
|
||||||
|
# Copy .husky directory (needed for husky install command)
|
||||||
|
COPY --chown=nodejs:nodejs .husky ./.husky
|
||||||
|
|
||||||
|
# Install only production dependencies
|
||||||
|
# Install husky temporarily so prepare script can run, then remove it
|
||||||
|
RUN pnpm add -D -w husky && \
|
||||||
|
pnpm install --prod --frozen-lockfile && \
|
||||||
|
pnpm remove -w husky && \
|
||||||
|
# Remove build dependencies to reduce image size
|
||||||
|
apk del python3 build-base
|
||||||
|
|
||||||
|
# Copy built application from builder stage
|
||||||
|
COPY --from=builder --chown=nodejs:nodejs /app/packages/server/dist ./packages/server/dist
|
||||||
|
|
||||||
|
# Copy static assets (i18n, public, static directories)
|
||||||
|
COPY --from=builder --chown=nodejs:nodejs /app/packages/server/src/i18n ./packages/server/dist/i18n
|
||||||
|
COPY --from=builder --chown=nodejs:nodejs /app/packages/server/public ./packages/server/public
|
||||||
|
COPY --from=builder --chown=nodejs:nodejs /app/packages/server/static ./packages/server/static
|
||||||
|
|
||||||
|
# Copy built shared packages (dist folders and package.json for module resolution)
|
||||||
|
COPY --from=builder --chown=nodejs:nodejs /app/shared/bigcapital-utils/dist ./shared/bigcapital-utils/dist
|
||||||
|
COPY --from=builder --chown=nodejs:nodejs /app/shared/pdf-templates/dist ./shared/pdf-templates/dist
|
||||||
|
COPY --from=builder --chown=nodejs:nodejs /app/shared/email-components/dist ./shared/email-components/dist
|
||||||
|
|
||||||
|
# Set runtime environment variables (these should be provided at runtime via docker-compose or k8s)
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
ENV NEW_RELIC_NO_CONFIG_FILE=true
|
||||||
|
ENV PORT=3000
|
||||||
|
|
||||||
|
# Switch to non-root user
|
||||||
|
USER nodejs
|
||||||
|
|
||||||
|
# Expose port
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
# Health check - uses /api/system_db ping endpoint
|
||||||
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
|
||||||
|
CMD node -e "require('http').get('http://localhost:3000/api/system_db', (r) => {process.exit(r.statusCode >= 200 && r.statusCode < 300 ? 0 : 1)}).on('error', () => process.exit(1))"
|
||||||
|
|
||||||
|
# Start the application
|
||||||
|
CMD [ "node", "packages/server/dist/main.js" ]
|
||||||
|
|||||||
@@ -40,6 +40,9 @@
|
|||||||
"@lemonsqueezy/lemonsqueezy.js": "^2.2.0",
|
"@lemonsqueezy/lemonsqueezy.js": "^2.2.0",
|
||||||
"@liaoliaots/nestjs-redis": "^10.0.0",
|
"@liaoliaots/nestjs-redis": "^10.0.0",
|
||||||
"@nest-lab/throttler-storage-redis": "^1.1.0",
|
"@nest-lab/throttler-storage-redis": "^1.1.0",
|
||||||
|
"@bull-board/api": "^5.22.0",
|
||||||
|
"@bull-board/express": "^5.22.0",
|
||||||
|
"@bull-board/nestjs": "^5.22.0",
|
||||||
"@nestjs/bull": "^10.2.1",
|
"@nestjs/bull": "^10.2.1",
|
||||||
"@nestjs/bullmq": "^10.2.2",
|
"@nestjs/bullmq": "^10.2.2",
|
||||||
"@nestjs/cache-manager": "^2.2.2",
|
"@nestjs/cache-manager": "^2.2.2",
|
||||||
|
|||||||
8
packages/server/src/common/config/bull-board.ts
Normal file
8
packages/server/src/common/config/bull-board.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { registerAs } from '@nestjs/config';
|
||||||
|
import { parseBoolean } from '@/utils/parse-boolean';
|
||||||
|
|
||||||
|
export default registerAs('bullBoard', () => ({
|
||||||
|
enabled: parseBoolean<boolean>(process.env.BULL_BOARD_ENABLED, false),
|
||||||
|
username: process.env.BULL_BOARD_USERNAME,
|
||||||
|
password: process.env.BULL_BOARD_PASSWORD,
|
||||||
|
}));
|
||||||
@@ -17,6 +17,9 @@ import loops from './loops';
|
|||||||
import bankfeed from './bankfeed';
|
import bankfeed from './bankfeed';
|
||||||
import throttle from './throttle';
|
import throttle from './throttle';
|
||||||
import cloud from './cloud';
|
import cloud from './cloud';
|
||||||
|
import redis from './redis';
|
||||||
|
import queue from './queue';
|
||||||
|
import bullBoard from './bull-board';
|
||||||
|
|
||||||
export const config = [
|
export const config = [
|
||||||
app,
|
app,
|
||||||
@@ -38,4 +41,7 @@ export const config = [
|
|||||||
loops,
|
loops,
|
||||||
bankfeed,
|
bankfeed,
|
||||||
throttle,
|
throttle,
|
||||||
|
redis,
|
||||||
|
queue,
|
||||||
|
bullBoard,
|
||||||
];
|
];
|
||||||
|
|||||||
6
packages/server/src/common/config/queue.ts
Normal file
6
packages/server/src/common/config/queue.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { registerAs } from '@nestjs/config';
|
||||||
|
|
||||||
|
export default registerAs('queue', () => ({
|
||||||
|
host: process.env.QUEUE_HOST || 'localhost',
|
||||||
|
port: parseInt(process.env.QUEUE_PORT, 10) || 6379,
|
||||||
|
}));
|
||||||
59
packages/server/src/middleware/bull-board-auth.middleware.ts
Normal file
59
packages/server/src/middleware/bull-board-auth.middleware.ts
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
import { Request, Response, NextFunction } from 'express';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates Express middleware for the Bull Board UI:
|
||||||
|
* - When disabled: responds with 404.
|
||||||
|
* - When enabled and username/password are set: enforces HTTP Basic Auth (401 if invalid).
|
||||||
|
* - When enabled and credentials are not set: allows access (no auth).
|
||||||
|
*/
|
||||||
|
export function createBullBoardAuthMiddleware(
|
||||||
|
enabled: boolean,
|
||||||
|
username: string | undefined,
|
||||||
|
password: string | undefined,
|
||||||
|
): (req: Request, res: Response, next: NextFunction) => void {
|
||||||
|
return (req: Request, res: Response, next: NextFunction) => {
|
||||||
|
if (!enabled) {
|
||||||
|
res.status(404).send('Not Found');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!username || !password) {
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
|
||||||
|
const authHeader = req.headers.authorization;
|
||||||
|
if (!authHeader || !authHeader.startsWith('Basic ')) {
|
||||||
|
res.setHeader('WWW-Authenticate', 'Basic realm="Bull Board"');
|
||||||
|
res.status(401).send('Authentication required');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const base64Credentials = authHeader.slice(6);
|
||||||
|
let decoded: string;
|
||||||
|
try {
|
||||||
|
decoded = Buffer.from(base64Credentials, 'base64').toString('utf8');
|
||||||
|
} catch {
|
||||||
|
res.setHeader('WWW-Authenticate', 'Basic realm="Bull Board"');
|
||||||
|
res.status(401).send('Invalid credentials');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const colonIndex = decoded.indexOf(':');
|
||||||
|
if (colonIndex === -1) {
|
||||||
|
res.setHeader('WWW-Authenticate', 'Basic realm="Bull Board"');
|
||||||
|
res.status(401).send('Invalid credentials');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const reqUsername = decoded.slice(0, colonIndex);
|
||||||
|
const reqPassword = decoded.slice(colonIndex + 1);
|
||||||
|
|
||||||
|
if (reqUsername !== username || reqPassword !== password) {
|
||||||
|
res.setHeader('WWW-Authenticate', 'Basic realm="Bull Board"');
|
||||||
|
res.status(401).send('Invalid credentials');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
next();
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -33,6 +33,7 @@ export class AccountTransaction extends BaseModel {
|
|||||||
public readonly userId!: number;
|
public readonly userId!: number;
|
||||||
public readonly itemId!: number;
|
public readonly itemId!: number;
|
||||||
public readonly projectId!: number;
|
public readonly projectId!: number;
|
||||||
|
public readonly costable!: boolean;
|
||||||
public readonly account: Account;
|
public readonly account: Account;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ import {
|
|||||||
I18nModule,
|
I18nModule,
|
||||||
QueryResolver,
|
QueryResolver,
|
||||||
} from 'nestjs-i18n';
|
} from 'nestjs-i18n';
|
||||||
|
import { BullBoardModule } from '@bull-board/nestjs';
|
||||||
|
import { ExpressAdapter } from '@bull-board/express';
|
||||||
|
import { createBullBoardAuthMiddleware } from '@/middleware/bull-board-auth.middleware';
|
||||||
import { BullModule } from '@nestjs/bullmq';
|
import { BullModule } from '@nestjs/bullmq';
|
||||||
import { ScheduleModule } from '@nestjs/schedule';
|
import { ScheduleModule } from '@nestjs/schedule';
|
||||||
import { PassportModule } from '@nestjs/passport';
|
import { PassportModule } from '@nestjs/passport';
|
||||||
@@ -137,12 +140,30 @@ import { AppThrottleModule } from './AppThrottle.module';
|
|||||||
imports: [ConfigModule],
|
imports: [ConfigModule],
|
||||||
useFactory: async (configService: ConfigService) => ({
|
useFactory: async (configService: ConfigService) => ({
|
||||||
connection: {
|
connection: {
|
||||||
host: configService.get('QUEUE_HOST'),
|
host: configService.get('queue.host'),
|
||||||
port: configService.get('QUEUE_PORT'),
|
port: configService.get('queue.port'),
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
inject: [ConfigService],
|
inject: [ConfigService],
|
||||||
}),
|
}),
|
||||||
|
BullBoardModule.forRootAsync({
|
||||||
|
imports: [ConfigModule],
|
||||||
|
useFactory: (configService: ConfigService) => {
|
||||||
|
const enabled = configService.get<boolean>('bullBoard.enabled');
|
||||||
|
const username = configService.get<string>('bullBoard.username');
|
||||||
|
const password = configService.get<string>('bullBoard.password');
|
||||||
|
return {
|
||||||
|
route: '/queues',
|
||||||
|
adapter: ExpressAdapter,
|
||||||
|
middleware: createBullBoardAuthMiddleware(
|
||||||
|
enabled,
|
||||||
|
username,
|
||||||
|
password,
|
||||||
|
),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
inject: [ConfigService],
|
||||||
|
}),
|
||||||
ClsModule.forRoot({
|
ClsModule.forRoot({
|
||||||
global: true,
|
global: true,
|
||||||
middleware: {
|
middleware: {
|
||||||
@@ -158,8 +179,8 @@ import { AppThrottleModule } from './AppThrottle.module';
|
|||||||
imports: [ConfigModule],
|
imports: [ConfigModule],
|
||||||
useFactory: (configService: ConfigService) => ({
|
useFactory: (configService: ConfigService) => ({
|
||||||
config: {
|
config: {
|
||||||
host: configService.get('redis.host') || 'localhost',
|
host: configService.get('redis.host'),
|
||||||
port: configService.get('redis.port') || 6379,
|
port: configService.get('redis.port'),
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
inject: [ConfigService],
|
inject: [ConfigService],
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ import { PassportModule } from '@nestjs/passport';
|
|||||||
import { APP_GUARD } from '@nestjs/core';
|
import { APP_GUARD } from '@nestjs/core';
|
||||||
import { JwtAuthGuard } from './guards/jwt.guard';
|
import { JwtAuthGuard } from './guards/jwt.guard';
|
||||||
import { AuthMailSubscriber } from './subscribers/AuthMail.subscriber';
|
import { AuthMailSubscriber } from './subscribers/AuthMail.subscriber';
|
||||||
|
import { BullBoardModule } from '@bull-board/nestjs';
|
||||||
|
import { BullMQAdapter } from '@bull-board/api/bullMQAdapter';
|
||||||
import { BullModule } from '@nestjs/bullmq';
|
import { BullModule } from '@nestjs/bullmq';
|
||||||
import {
|
import {
|
||||||
SendResetPasswordMailQueue,
|
SendResetPasswordMailQueue,
|
||||||
@@ -63,6 +65,14 @@ const models = [
|
|||||||
TenancyModule,
|
TenancyModule,
|
||||||
BullModule.registerQueue({ name: SendResetPasswordMailQueue }),
|
BullModule.registerQueue({ name: SendResetPasswordMailQueue }),
|
||||||
BullModule.registerQueue({ name: SendSignupVerificationMailQueue }),
|
BullModule.registerQueue({ name: SendSignupVerificationMailQueue }),
|
||||||
|
BullBoardModule.forFeature({
|
||||||
|
name: SendResetPasswordMailQueue,
|
||||||
|
adapter: BullMQAdapter,
|
||||||
|
}),
|
||||||
|
BullBoardModule.forFeature({
|
||||||
|
name: SendSignupVerificationMailQueue,
|
||||||
|
adapter: BullMQAdapter,
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
exports: [...models],
|
exports: [...models],
|
||||||
providers: [
|
providers: [
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { BullBoardModule } from '@bull-board/nestjs';
|
||||||
|
import { BullMQAdapter } from '@bull-board/api/bullMQAdapter';
|
||||||
import { BullModule } from '@nestjs/bullmq';
|
import { BullModule } from '@nestjs/bullmq';
|
||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { SocketModule } from '../Socket/Socket.module';
|
import { SocketModule } from '../Socket/Socket.module';
|
||||||
@@ -33,6 +35,10 @@ const models = [RegisterTenancyModel(PlaidItem)];
|
|||||||
BankingCategorizeModule,
|
BankingCategorizeModule,
|
||||||
BankingTransactionsModule,
|
BankingTransactionsModule,
|
||||||
BullModule.registerQueue({ name: UpdateBankingPlaidTransitionsQueueJob }),
|
BullModule.registerQueue({ name: UpdateBankingPlaidTransitionsQueueJob }),
|
||||||
|
BullBoardModule.forFeature({
|
||||||
|
name: UpdateBankingPlaidTransitionsQueueJob,
|
||||||
|
adapter: BullMQAdapter,
|
||||||
|
}),
|
||||||
...models,
|
...models,
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import { BankingRecognizedTransactionsController } from './BankingRecognizedTran
|
|||||||
import { RecognizedTransactionsApplication } from './RecognizedTransactions.application';
|
import { RecognizedTransactionsApplication } from './RecognizedTransactions.application';
|
||||||
import { GetRecognizedTransactionsService } from './GetRecongizedTransactions';
|
import { GetRecognizedTransactionsService } from './GetRecongizedTransactions';
|
||||||
import { GetRecognizedTransactionService } from './queries/GetRecognizedTransaction.service';
|
import { GetRecognizedTransactionService } from './queries/GetRecognizedTransaction.service';
|
||||||
|
import { BullBoardModule } from '@bull-board/nestjs';
|
||||||
|
import { BullMQAdapter } from '@bull-board/api/bullMQAdapter';
|
||||||
import { BullModule } from '@nestjs/bullmq';
|
import { BullModule } from '@nestjs/bullmq';
|
||||||
import { RecognizeUncategorizedTransactionsQueue } from './_types';
|
import { RecognizeUncategorizedTransactionsQueue } from './_types';
|
||||||
import { RegonizeTransactionsPrcessor } from './jobs/RecognizeTransactionsJob';
|
import { RegonizeTransactionsPrcessor } from './jobs/RecognizeTransactionsJob';
|
||||||
@@ -25,6 +27,10 @@ const models = [RegisterTenancyModel(RecognizedBankTransaction)];
|
|||||||
BullModule.registerQueue({
|
BullModule.registerQueue({
|
||||||
name: RecognizeUncategorizedTransactionsQueue,
|
name: RecognizeUncategorizedTransactionsQueue,
|
||||||
}),
|
}),
|
||||||
|
BullBoardModule.forFeature({
|
||||||
|
name: RecognizeUncategorizedTransactionsQueue,
|
||||||
|
adapter: BullMQAdapter,
|
||||||
|
}),
|
||||||
...models,
|
...models,
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ import {
|
|||||||
ComputeItemCostQueue,
|
ComputeItemCostQueue,
|
||||||
WriteInventoryTransactionsGLEntriesQueue,
|
WriteInventoryTransactionsGLEntriesQueue,
|
||||||
} from './types/InventoryCost.types';
|
} from './types/InventoryCost.types';
|
||||||
|
import { BullBoardModule } from '@bull-board/nestjs';
|
||||||
|
import { BullMQAdapter } from '@bull-board/api/bullMQAdapter';
|
||||||
import { BullModule } from '@nestjs/bullmq';
|
import { BullModule } from '@nestjs/bullmq';
|
||||||
import { InventoryAverageCostMethodService } from './commands/InventoryAverageCostMethod.service';
|
import { InventoryAverageCostMethodService } from './commands/InventoryAverageCostMethod.service';
|
||||||
import { InventoryItemCostService } from './commands/InventoryCosts.service';
|
import { InventoryItemCostService } from './commands/InventoryCosts.service';
|
||||||
@@ -39,6 +41,14 @@ const models = [
|
|||||||
BullModule.registerQueue({
|
BullModule.registerQueue({
|
||||||
name: WriteInventoryTransactionsGLEntriesQueue,
|
name: WriteInventoryTransactionsGLEntriesQueue,
|
||||||
}),
|
}),
|
||||||
|
BullBoardModule.forFeature({
|
||||||
|
name: ComputeItemCostQueue,
|
||||||
|
adapter: BullMQAdapter,
|
||||||
|
}),
|
||||||
|
BullBoardModule.forFeature({
|
||||||
|
name: WriteInventoryTransactionsGLEntriesQueue,
|
||||||
|
adapter: BullMQAdapter,
|
||||||
|
}),
|
||||||
forwardRef(() => SaleInvoicesModule),
|
forwardRef(() => SaleInvoicesModule),
|
||||||
ImportModule,
|
ImportModule,
|
||||||
],
|
],
|
||||||
@@ -56,7 +66,7 @@ const models = [
|
|||||||
InventoryItemCostService,
|
InventoryItemCostService,
|
||||||
InventoryItemOpeningAvgCostService,
|
InventoryItemOpeningAvgCostService,
|
||||||
InventoryCostSubscriber,
|
InventoryCostSubscriber,
|
||||||
GetItemsInventoryValuationListService
|
GetItemsInventoryValuationListService,
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
...models,
|
...models,
|
||||||
@@ -64,6 +74,6 @@ const models = [
|
|||||||
InventoryItemCostService,
|
InventoryItemCostService,
|
||||||
InventoryComputeCostService,
|
InventoryComputeCostService,
|
||||||
],
|
],
|
||||||
controllers: [InventoryCostController]
|
controllers: [InventoryCostController],
|
||||||
})
|
})
|
||||||
export class InventoryCostModule {}
|
export class InventoryCostModule {}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export const transformLedgerEntryToTransaction = (
|
|||||||
itemId: entry.itemId,
|
itemId: entry.itemId,
|
||||||
projectId: entry.projectId,
|
projectId: entry.projectId,
|
||||||
|
|
||||||
// costable: entry.costable,
|
costable: entry.costable,
|
||||||
|
|
||||||
taxRateId: entry.taxRateId,
|
taxRateId: entry.taxRateId,
|
||||||
taxRate: entry.taxRate,
|
taxRate: entry.taxRate,
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import { GetCurrentOrganizationService } from './queries/GetCurrentOrganization.
|
|||||||
import { BuildOrganizationService } from './commands/BuildOrganization.service';
|
import { BuildOrganizationService } from './commands/BuildOrganization.service';
|
||||||
import { UpdateOrganizationService } from './commands/UpdateOrganization.service';
|
import { UpdateOrganizationService } from './commands/UpdateOrganization.service';
|
||||||
import { OrganizationController } from './Organization.controller';
|
import { OrganizationController } from './Organization.controller';
|
||||||
|
import { BullBoardModule } from '@bull-board/nestjs';
|
||||||
|
import { BullMQAdapter } from '@bull-board/api/bullMQAdapter';
|
||||||
import { BullModule } from '@nestjs/bullmq';
|
import { BullModule } from '@nestjs/bullmq';
|
||||||
import { OrganizationBuildQueue } from './Organization.types';
|
import { OrganizationBuildQueue } from './Organization.types';
|
||||||
import { OrganizationBuildProcessor } from './processors/OrganizationBuild.processor';
|
import { OrganizationBuildProcessor } from './processors/OrganizationBuild.processor';
|
||||||
@@ -25,10 +27,14 @@ import { GetBuildOrganizationBuildJob } from './commands/GetBuildOrganizationJob
|
|||||||
OrganizationBaseCurrencyLocking,
|
OrganizationBaseCurrencyLocking,
|
||||||
SyncSystemUserToTenantService,
|
SyncSystemUserToTenantService,
|
||||||
SyncSystemUserToTenantSubscriber,
|
SyncSystemUserToTenantSubscriber,
|
||||||
GetBuildOrganizationBuildJob
|
GetBuildOrganizationBuildJob,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BullModule.registerQueue({ name: OrganizationBuildQueue }),
|
BullModule.registerQueue({ name: OrganizationBuildQueue }),
|
||||||
|
BullBoardModule.forFeature({
|
||||||
|
name: OrganizationBuildQueue,
|
||||||
|
adapter: BullMQAdapter,
|
||||||
|
}),
|
||||||
TenantDBManagerModule,
|
TenantDBManagerModule,
|
||||||
],
|
],
|
||||||
controllers: [OrganizationController],
|
controllers: [OrganizationController],
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
|
import { BullBoardModule } from '@bull-board/nestjs';
|
||||||
|
import { BullAdapter } from '@bull-board/api/bullAdapter';
|
||||||
import { BullModule } from '@nestjs/bull';
|
import { BullModule } from '@nestjs/bull';
|
||||||
import { PaymentReceivesController } from './PaymentsReceived.controller';
|
import { PaymentReceivesController } from './PaymentsReceived.controller';
|
||||||
import { PaymentReceivesApplication } from './PaymentReceived.application';
|
import { PaymentReceivesApplication } from './PaymentReceived.application';
|
||||||
@@ -95,6 +97,10 @@ import { ValidateBulkDeletePaymentReceivedService } from './ValidateBulkDeletePa
|
|||||||
DynamicListModule,
|
DynamicListModule,
|
||||||
MailModule,
|
MailModule,
|
||||||
BullModule.registerQueue({ name: SEND_PAYMENT_RECEIVED_MAIL_QUEUE }),
|
BullModule.registerQueue({ name: SEND_PAYMENT_RECEIVED_MAIL_QUEUE }),
|
||||||
|
BullBoardModule.forFeature({
|
||||||
|
name: SEND_PAYMENT_RECEIVED_MAIL_QUEUE,
|
||||||
|
adapter: BullAdapter,
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class PaymentsReceivedModule {}
|
export class PaymentsReceivedModule {}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
|
import { BullBoardModule } from '@bull-board/nestjs';
|
||||||
|
import { BullAdapter } from '@bull-board/api/bullAdapter';
|
||||||
import { BullModule } from '@nestjs/bull';
|
import { BullModule } from '@nestjs/bull';
|
||||||
import { TenancyContext } from '../Tenancy/TenancyContext.service';
|
import { TenancyContext } from '../Tenancy/TenancyContext.service';
|
||||||
import { TenancyDatabaseModule } from '../Tenancy/TenancyDB/TenancyDB.module';
|
import { TenancyDatabaseModule } from '../Tenancy/TenancyDB/TenancyDB.module';
|
||||||
@@ -54,6 +56,10 @@ import { SendSaleEstimateMailProcess } from './processes/SendSaleEstimateMail.pr
|
|||||||
TemplateInjectableModule,
|
TemplateInjectableModule,
|
||||||
PdfTemplatesModule,
|
PdfTemplatesModule,
|
||||||
BullModule.registerQueue({ name: SendSaleEstimateMailQueue }),
|
BullModule.registerQueue({ name: SendSaleEstimateMailQueue }),
|
||||||
|
BullBoardModule.forFeature({
|
||||||
|
name: SendSaleEstimateMailQueue,
|
||||||
|
adapter: BullAdapter,
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
controllers: [SaleEstimatesController],
|
controllers: [SaleEstimatesController],
|
||||||
providers: [
|
providers: [
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ import { SendSaleInvoiceMailCommon } from './commands/SendInvoiceInvoiceMailComm
|
|||||||
import { DynamicListModule } from '../DynamicListing/DynamicList.module';
|
import { DynamicListModule } from '../DynamicListing/DynamicList.module';
|
||||||
import { MailNotificationModule } from '../MailNotification/MailNotification.module';
|
import { MailNotificationModule } from '../MailNotification/MailNotification.module';
|
||||||
import { SendSaleInvoiceMailProcessor } from './processors/SendSaleInvoiceMail.processor';
|
import { SendSaleInvoiceMailProcessor } from './processors/SendSaleInvoiceMail.processor';
|
||||||
|
import { BullBoardModule } from '@bull-board/nestjs';
|
||||||
|
import { BullAdapter } from '@bull-board/api/bullAdapter';
|
||||||
import { BullModule } from '@nestjs/bull';
|
import { BullModule } from '@nestjs/bull';
|
||||||
import { SendSaleInvoiceQueue } from './constants';
|
import { SendSaleInvoiceQueue } from './constants';
|
||||||
import { InvoicePaymentIntegrationSubscriber } from './subscribers/InvoicePaymentIntegrationSubscriber';
|
import { InvoicePaymentIntegrationSubscriber } from './subscribers/InvoicePaymentIntegrationSubscriber';
|
||||||
@@ -81,6 +83,10 @@ import { ValidateBulkDeleteSaleInvoicesService } from './ValidateBulkDeleteSaleI
|
|||||||
forwardRef(() => PaymentLinksModule),
|
forwardRef(() => PaymentLinksModule),
|
||||||
DynamicListModule,
|
DynamicListModule,
|
||||||
BullModule.registerQueue({ name: SendSaleInvoiceQueue }),
|
BullModule.registerQueue({ name: SendSaleInvoiceQueue }),
|
||||||
|
BullBoardModule.forFeature({
|
||||||
|
name: SendSaleInvoiceQueue,
|
||||||
|
adapter: BullAdapter,
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
controllers: [SaleInvoicesController],
|
controllers: [SaleInvoicesController],
|
||||||
providers: [
|
providers: [
|
||||||
|
|||||||
@@ -0,0 +1,143 @@
|
|||||||
|
import * as R from 'ramda';
|
||||||
|
import { Knex } from 'knex';
|
||||||
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
|
import { TenantModelProxy } from '../System/models/TenantBaseModel';
|
||||||
|
import { InventoryCostLotTracker } from '../InventoryCost/models/InventoryCostLotTracker';
|
||||||
|
import { LedgerStorageService } from '../Ledger/LedgerStorage.service';
|
||||||
|
import { groupInventoryTransactionsByTypeId } from '../InventoryCost/utils';
|
||||||
|
import { Ledger } from '../Ledger/Ledger';
|
||||||
|
import { AccountNormal } from '@/interfaces/Account';
|
||||||
|
import { ILedgerEntry } from '../Ledger/types/Ledger.types';
|
||||||
|
import { increment } from '@/utils/increment';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class SaleReceiptCostGLEntries {
|
||||||
|
constructor(
|
||||||
|
private readonly ledgerStorage: LedgerStorageService,
|
||||||
|
|
||||||
|
@Inject(InventoryCostLotTracker.name)
|
||||||
|
private readonly inventoryCostLotTracker: TenantModelProxy<
|
||||||
|
typeof InventoryCostLotTracker
|
||||||
|
>,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes journal entries from sales receipts.
|
||||||
|
* @param {Date} startingDate - Starting date.
|
||||||
|
* @param {Knex.Transaction} trx - Transaction.
|
||||||
|
*/
|
||||||
|
public writeInventoryCostJournalEntries = async (
|
||||||
|
startingDate: Date,
|
||||||
|
trx?: Knex.Transaction,
|
||||||
|
): Promise<void> => {
|
||||||
|
const inventoryCostLotTrans = await this.inventoryCostLotTracker()
|
||||||
|
.query()
|
||||||
|
.where('direction', 'OUT')
|
||||||
|
.where('transaction_type', 'SaleReceipt')
|
||||||
|
.where('cost', '>', 0)
|
||||||
|
.modify('filterDateRange', startingDate)
|
||||||
|
.orderBy('date', 'ASC')
|
||||||
|
.withGraphFetched('receipt')
|
||||||
|
.withGraphFetched('item')
|
||||||
|
.withGraphFetched('itemEntry');
|
||||||
|
|
||||||
|
const ledger = this.getInventoryCostLotsLedger(inventoryCostLotTrans);
|
||||||
|
|
||||||
|
await this.ledgerStorage.commit(ledger, trx);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the inventory cost lots ledger.
|
||||||
|
*/
|
||||||
|
private getInventoryCostLotsLedger = (
|
||||||
|
inventoryCostLots: InventoryCostLotTracker[],
|
||||||
|
) => {
|
||||||
|
const inventoryTransactions =
|
||||||
|
groupInventoryTransactionsByTypeId(inventoryCostLots);
|
||||||
|
|
||||||
|
const entries = inventoryTransactions
|
||||||
|
.map(this.getSaleReceiptCostGLEntries)
|
||||||
|
.flat();
|
||||||
|
return new Ledger(entries);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the common GL entry fields for a sale receipt cost.
|
||||||
|
*/
|
||||||
|
private getReceiptCostGLCommonEntry = (
|
||||||
|
inventoryCostLot: InventoryCostLotTracker,
|
||||||
|
) => {
|
||||||
|
return {
|
||||||
|
currencyCode: inventoryCostLot.receipt.currencyCode,
|
||||||
|
exchangeRate: inventoryCostLot.receipt.exchangeRate,
|
||||||
|
|
||||||
|
transactionType: inventoryCostLot.transactionType,
|
||||||
|
transactionId: inventoryCostLot.transactionId,
|
||||||
|
|
||||||
|
transactionNumber: inventoryCostLot.receipt.receiptNumber,
|
||||||
|
referenceNumber: inventoryCostLot.receipt.referenceNo,
|
||||||
|
|
||||||
|
date: inventoryCostLot.date,
|
||||||
|
indexGroup: 20,
|
||||||
|
costable: true,
|
||||||
|
createdAt: inventoryCostLot.createdAt,
|
||||||
|
|
||||||
|
debit: 0,
|
||||||
|
credit: 0,
|
||||||
|
|
||||||
|
branchId: inventoryCostLot.receipt.branchId,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the inventory cost GL entry for a single lot.
|
||||||
|
*/
|
||||||
|
private getInventoryCostGLEntry = R.curry(
|
||||||
|
(
|
||||||
|
getIndexIncrement: () => number,
|
||||||
|
inventoryCostLot: InventoryCostLotTracker,
|
||||||
|
): ILedgerEntry[] => {
|
||||||
|
const commonEntry = this.getReceiptCostGLCommonEntry(inventoryCostLot);
|
||||||
|
const costAccountId =
|
||||||
|
inventoryCostLot.costAccountId || inventoryCostLot.item.costAccountId;
|
||||||
|
|
||||||
|
const description = inventoryCostLot.itemEntry?.description || null;
|
||||||
|
|
||||||
|
const costEntry = {
|
||||||
|
...commonEntry,
|
||||||
|
debit: inventoryCostLot.cost,
|
||||||
|
accountId: costAccountId,
|
||||||
|
accountNormal: AccountNormal.DEBIT,
|
||||||
|
itemId: inventoryCostLot.itemId,
|
||||||
|
note: description,
|
||||||
|
index: getIndexIncrement(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const inventoryEntry = {
|
||||||
|
...commonEntry,
|
||||||
|
credit: inventoryCostLot.cost,
|
||||||
|
accountId: inventoryCostLot.item.inventoryAccountId,
|
||||||
|
accountNormal: AccountNormal.DEBIT,
|
||||||
|
itemId: inventoryCostLot.itemId,
|
||||||
|
note: description,
|
||||||
|
index: getIndexIncrement(),
|
||||||
|
};
|
||||||
|
return [costEntry, inventoryEntry];
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds GL entries for a group of sale receipt cost lots.
|
||||||
|
* - Cost of goods sold -> Debit
|
||||||
|
* - Inventory assets -> Credit
|
||||||
|
*/
|
||||||
|
public getSaleReceiptCostGLEntries = (
|
||||||
|
inventoryCostLots: InventoryCostLotTracker[],
|
||||||
|
): ILedgerEntry[] => {
|
||||||
|
const getIndexIncrement = increment(0);
|
||||||
|
const getInventoryLotEntry =
|
||||||
|
this.getInventoryCostGLEntry(getIndexIncrement);
|
||||||
|
|
||||||
|
return inventoryCostLots.map((t) => getInventoryLotEntry(t)).flat();
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
|
import { BullBoardModule } from '@bull-board/nestjs';
|
||||||
|
import { BullAdapter } from '@bull-board/api/bullAdapter';
|
||||||
import { BullModule } from '@nestjs/bull';
|
import { BullModule } from '@nestjs/bull';
|
||||||
import { SaleReceiptApplication } from './SaleReceiptApplication.service';
|
import { SaleReceiptApplication } from './SaleReceiptApplication.service';
|
||||||
import { CreateSaleReceipt } from './commands/CreateSaleReceipt.service';
|
import { CreateSaleReceipt } from './commands/CreateSaleReceipt.service';
|
||||||
@@ -40,6 +42,8 @@ import { SaleReceiptsImportable } from './commands/SaleReceiptsImportable';
|
|||||||
import { GetSaleReceiptMailStateService } from './queries/GetSaleReceiptMailState.service';
|
import { GetSaleReceiptMailStateService } from './queries/GetSaleReceiptMailState.service';
|
||||||
import { GetSaleReceiptMailTemplateService } from './queries/GetSaleReceiptMailTemplate.service';
|
import { GetSaleReceiptMailTemplateService } from './queries/GetSaleReceiptMailTemplate.service';
|
||||||
import { SaleReceiptAutoIncrementSubscriber } from './subscribers/SaleReceiptAutoIncrementSubscriber';
|
import { SaleReceiptAutoIncrementSubscriber } from './subscribers/SaleReceiptAutoIncrementSubscriber';
|
||||||
|
import { SaleReceiptCostGLEntriesSubscriber } from './subscribers/SaleReceiptCostGLEntriesSubscriber';
|
||||||
|
import { SaleReceiptCostGLEntries } from './SaleReceiptCostGLEntries';
|
||||||
import { BulkDeleteSaleReceiptsService } from './BulkDeleteSaleReceipts.service';
|
import { BulkDeleteSaleReceiptsService } from './BulkDeleteSaleReceipts.service';
|
||||||
import { ValidateBulkDeleteSaleReceiptsService } from './ValidateBulkDeleteSaleReceipts.service';
|
import { ValidateBulkDeleteSaleReceiptsService } from './ValidateBulkDeleteSaleReceipts.service';
|
||||||
|
|
||||||
@@ -60,6 +64,10 @@ import { ValidateBulkDeleteSaleReceiptsService } from './ValidateBulkDeleteSaleR
|
|||||||
MailModule,
|
MailModule,
|
||||||
MailNotificationModule,
|
MailNotificationModule,
|
||||||
BullModule.registerQueue({ name: SendSaleReceiptMailQueue }),
|
BullModule.registerQueue({ name: SendSaleReceiptMailQueue }),
|
||||||
|
BullBoardModule.forFeature({
|
||||||
|
name: SendSaleReceiptMailQueue,
|
||||||
|
adapter: BullAdapter,
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
TenancyContext,
|
TenancyContext,
|
||||||
@@ -87,6 +95,8 @@ import { ValidateBulkDeleteSaleReceiptsService } from './ValidateBulkDeleteSaleR
|
|||||||
GetSaleReceiptMailStateService,
|
GetSaleReceiptMailStateService,
|
||||||
GetSaleReceiptMailTemplateService,
|
GetSaleReceiptMailTemplateService,
|
||||||
SaleReceiptAutoIncrementSubscriber,
|
SaleReceiptAutoIncrementSubscriber,
|
||||||
|
SaleReceiptCostGLEntries,
|
||||||
|
SaleReceiptCostGLEntriesSubscriber,
|
||||||
BulkDeleteSaleReceiptsService,
|
BulkDeleteSaleReceiptsService,
|
||||||
ValidateBulkDeleteSaleReceiptsService,
|
ValidateBulkDeleteSaleReceiptsService,
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,148 +0,0 @@
|
|||||||
// import { Service, Inject } from 'typedi';
|
|
||||||
// import * as R from 'ramda';
|
|
||||||
// import { Knex } from 'knex';
|
|
||||||
// import { AccountNormal, IInventoryLotCost, ILedgerEntry } from '@/interfaces';
|
|
||||||
// import { increment } from 'utils';
|
|
||||||
// import HasTenancyService from '@/services/Tenancy/TenancyService';
|
|
||||||
// import Ledger from '@/services/Accounting/Ledger';
|
|
||||||
// import LedgerStorageService from '@/services/Accounting/LedgerStorageService';
|
|
||||||
// import { groupInventoryTransactionsByTypeId } from '../../Inventory/utils';
|
|
||||||
|
|
||||||
// @Service()
|
|
||||||
// export class SaleReceiptCostGLEntries {
|
|
||||||
// @Inject()
|
|
||||||
// private tenancy: HasTenancyService;
|
|
||||||
|
|
||||||
// @Inject()
|
|
||||||
// private ledgerStorage: LedgerStorageService;
|
|
||||||
|
|
||||||
// /**
|
|
||||||
// * Writes journal entries from sales invoices.
|
|
||||||
// * @param {number} tenantId - The tenant id.
|
|
||||||
// * @param {Date} startingDate - Starting date.
|
|
||||||
// * @param {boolean} override
|
|
||||||
// */
|
|
||||||
// public writeInventoryCostJournalEntries = async (
|
|
||||||
// tenantId: number,
|
|
||||||
// startingDate: Date,
|
|
||||||
// trx?: Knex.Transaction
|
|
||||||
// ): Promise<void> => {
|
|
||||||
// const { InventoryCostLotTracker } = this.tenancy.models(tenantId);
|
|
||||||
|
|
||||||
// const inventoryCostLotTrans = await InventoryCostLotTracker.query()
|
|
||||||
// .where('direction', 'OUT')
|
|
||||||
// .where('transaction_type', 'SaleReceipt')
|
|
||||||
// .where('cost', '>', 0)
|
|
||||||
// .modify('filterDateRange', startingDate)
|
|
||||||
// .orderBy('date', 'ASC')
|
|
||||||
// .withGraphFetched('receipt')
|
|
||||||
// .withGraphFetched('item');
|
|
||||||
|
|
||||||
// const ledger = this.getInventoryCostLotsLedger(inventoryCostLotTrans);
|
|
||||||
|
|
||||||
// // Commit the ledger to the storage.
|
|
||||||
// await this.ledgerStorage.commit(tenantId, ledger, trx);
|
|
||||||
// };
|
|
||||||
|
|
||||||
// /**
|
|
||||||
// * Retrieves the inventory cost lots ledger.
|
|
||||||
// * @param {} inventoryCostLots
|
|
||||||
// * @returns {Ledger}
|
|
||||||
// */
|
|
||||||
// private getInventoryCostLotsLedger = (
|
|
||||||
// inventoryCostLots: IInventoryLotCost[]
|
|
||||||
// ) => {
|
|
||||||
// // Groups the inventory cost lots transactions.
|
|
||||||
// const inventoryTransactions =
|
|
||||||
// groupInventoryTransactionsByTypeId(inventoryCostLots);
|
|
||||||
|
|
||||||
// //
|
|
||||||
// const entries = inventoryTransactions
|
|
||||||
// .map(this.getSaleInvoiceCostGLEntries)
|
|
||||||
// .flat();
|
|
||||||
|
|
||||||
// return new Ledger(entries);
|
|
||||||
// };
|
|
||||||
|
|
||||||
// /**
|
|
||||||
// *
|
|
||||||
// * @param {IInventoryLotCost} inventoryCostLot
|
|
||||||
// * @returns {}
|
|
||||||
// */
|
|
||||||
// private getInvoiceCostGLCommonEntry = (
|
|
||||||
// inventoryCostLot: IInventoryLotCost
|
|
||||||
// ) => {
|
|
||||||
// return {
|
|
||||||
// currencyCode: inventoryCostLot.receipt.currencyCode,
|
|
||||||
// exchangeRate: inventoryCostLot.receipt.exchangeRate,
|
|
||||||
|
|
||||||
// transactionType: inventoryCostLot.transactionType,
|
|
||||||
// transactionId: inventoryCostLot.transactionId,
|
|
||||||
|
|
||||||
// date: inventoryCostLot.date,
|
|
||||||
// indexGroup: 20,
|
|
||||||
// costable: true,
|
|
||||||
// createdAt: inventoryCostLot.createdAt,
|
|
||||||
|
|
||||||
// debit: 0,
|
|
||||||
// credit: 0,
|
|
||||||
|
|
||||||
// branchId: inventoryCostLot.receipt.branchId,
|
|
||||||
// };
|
|
||||||
// };
|
|
||||||
|
|
||||||
// /**
|
|
||||||
// * Retrieves the inventory cost GL entry.
|
|
||||||
// * @param {IInventoryLotCost} inventoryLotCost
|
|
||||||
// * @returns {ILedgerEntry[]}
|
|
||||||
// */
|
|
||||||
// private getInventoryCostGLEntry = R.curry(
|
|
||||||
// (
|
|
||||||
// getIndexIncrement,
|
|
||||||
// inventoryCostLot: IInventoryLotCost
|
|
||||||
// ): ILedgerEntry[] => {
|
|
||||||
// const commonEntry = this.getInvoiceCostGLCommonEntry(inventoryCostLot);
|
|
||||||
// const costAccountId =
|
|
||||||
// inventoryCostLot.costAccountId || inventoryCostLot.item.costAccountId;
|
|
||||||
|
|
||||||
// // XXX Debit - Cost account.
|
|
||||||
// const costEntry = {
|
|
||||||
// ...commonEntry,
|
|
||||||
// debit: inventoryCostLot.cost,
|
|
||||||
// accountId: costAccountId,
|
|
||||||
// accountNormal: AccountNormal.DEBIT,
|
|
||||||
// itemId: inventoryCostLot.itemId,
|
|
||||||
// index: getIndexIncrement(),
|
|
||||||
// };
|
|
||||||
// // XXX Credit - Inventory account.
|
|
||||||
// const inventoryEntry = {
|
|
||||||
// ...commonEntry,
|
|
||||||
// credit: inventoryCostLot.cost,
|
|
||||||
// accountId: inventoryCostLot.item.inventoryAccountId,
|
|
||||||
// accountNormal: AccountNormal.DEBIT,
|
|
||||||
// itemId: inventoryCostLot.itemId,
|
|
||||||
// index: getIndexIncrement(),
|
|
||||||
// };
|
|
||||||
// return [costEntry, inventoryEntry];
|
|
||||||
// }
|
|
||||||
// );
|
|
||||||
|
|
||||||
// /**
|
|
||||||
// * Writes journal entries for given sale invoice.
|
|
||||||
// * -------
|
|
||||||
// * - Cost of goods sold -> Debit -> YYYY
|
|
||||||
// * - Inventory assets -> Credit -> YYYY
|
|
||||||
// * --------
|
|
||||||
// * @param {ISaleInvoice} saleInvoice
|
|
||||||
// * @param {JournalPoster} journal
|
|
||||||
// */
|
|
||||||
// public getSaleInvoiceCostGLEntries = (
|
|
||||||
// inventoryCostLots: IInventoryLotCost[]
|
|
||||||
// ): ILedgerEntry[] => {
|
|
||||||
// const getIndexIncrement = increment(0);
|
|
||||||
// const getInventoryLotEntry =
|
|
||||||
// this.getInventoryCostGLEntry(getIndexIncrement);
|
|
||||||
|
|
||||||
// return inventoryCostLots.map(getInventoryLotEntry).flat();
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
@@ -1,36 +1,26 @@
|
|||||||
// import { Inject, Service } from 'typedi';
|
import { Injectable } from '@nestjs/common';
|
||||||
// import events from '@/subscribers/events';
|
import { OnEvent } from '@nestjs/event-emitter';
|
||||||
// import { IInventoryCostLotsGLEntriesWriteEvent } from '@/interfaces';
|
import { events } from '@/common/events/events';
|
||||||
// import { SaleReceiptCostGLEntries } from '../SaleReceiptCostGLEntries';
|
import { IInventoryCostLotsGLEntriesWriteEvent } from '@/modules/InventoryCost/types/InventoryCost.types';
|
||||||
|
import { SaleReceiptCostGLEntries } from '../SaleReceiptCostGLEntries';
|
||||||
|
|
||||||
// @Service()
|
@Injectable()
|
||||||
// export class SaleReceiptCostGLEntriesSubscriber {
|
export class SaleReceiptCostGLEntriesSubscriber {
|
||||||
// @Inject()
|
constructor(
|
||||||
// private saleReceiptCostEntries: SaleReceiptCostGLEntries;
|
private readonly saleReceiptCostEntries: SaleReceiptCostGLEntries,
|
||||||
|
) {}
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * Attaches events.
|
* Writes the receipts cost GL entries once the inventory cost lots are written.
|
||||||
// */
|
*/
|
||||||
// public attach(bus) {
|
@OnEvent(events.inventory.onCostLotsGLEntriesWrite)
|
||||||
// bus.subscribe(
|
async writeReceiptsCostEntriesOnCostLotsWritten({
|
||||||
// events.inventory.onCostLotsGLEntriesWrite,
|
trx,
|
||||||
// this.writeJournalEntriesOnceWriteoffCreate
|
startingDate,
|
||||||
// );
|
}: IInventoryCostLotsGLEntriesWriteEvent) {
|
||||||
// }
|
await this.saleReceiptCostEntries.writeInventoryCostJournalEntries(
|
||||||
|
startingDate,
|
||||||
// /**
|
trx,
|
||||||
// * Writes the receipts cost GL entries once the inventory cost lots be written.
|
);
|
||||||
// * @param {IInventoryCostLotsGLEntriesWriteEvent}
|
}
|
||||||
// */
|
}
|
||||||
// private writeJournalEntriesOnceWriteoffCreate = async ({
|
|
||||||
// trx,
|
|
||||||
// startingDate,
|
|
||||||
// tenantId,
|
|
||||||
// }: IInventoryCostLotsGLEntriesWriteEvent) => {
|
|
||||||
// await this.saleReceiptCostEntries.writeInventoryCostJournalEntries(
|
|
||||||
// tenantId,
|
|
||||||
// startingDate,
|
|
||||||
// trx
|
|
||||||
// );
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|||||||
@@ -1,27 +1,47 @@
|
|||||||
FROM node:18.16.0-alpine as build
|
# Stage 1: Build
|
||||||
|
FROM node:18.16.0-alpine AS builder
|
||||||
USER root
|
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Copy application dependency manifests to the container image.
|
# Install pnpm
|
||||||
COPY . .
|
RUN npm install -g pnpm@8.10.2
|
||||||
|
|
||||||
# Install application dependencies
|
# Install build dependencies
|
||||||
RUN apk update
|
RUN apk add --no-cache python3 build-base chromium
|
||||||
RUN apk add python3 build-base chromium
|
|
||||||
|
|
||||||
# Set PYHTON env
|
# Set Python environment
|
||||||
ENV PYTHON=/usr/bin/python3
|
ENV PYTHON=/usr/bin/python3
|
||||||
|
|
||||||
# Install pnpm packages dependencies
|
# Copy package files for dependency installation
|
||||||
RUN npm install -g pnpm
|
COPY --chown=node:node package.json pnpm-lock.yaml pnpm-workspace.yaml lerna.json ./
|
||||||
|
COPY --chown=node:node packages/webapp/package.json ./packages/webapp/
|
||||||
|
COPY --chown=node:node shared/bigcapital-utils/package.json ./shared/bigcapital-utils/
|
||||||
|
COPY --chown=node:node shared/pdf-templates/package.json ./shared/pdf-templates/
|
||||||
|
COPY --chown=node:node shared/email-components/package.json ./shared/email-components/
|
||||||
|
|
||||||
|
# Install all dependencies (including devDependencies for build)
|
||||||
RUN pnpm install
|
RUN pnpm install
|
||||||
|
|
||||||
|
# Copy source code for webapp and dependencies
|
||||||
|
COPY --chown=node:node ./packages/webapp ./packages/webapp
|
||||||
|
COPY --chown=node:node ./shared/bigcapital-utils ./shared/bigcapital-utils
|
||||||
|
COPY --chown=node:node ./shared/pdf-templates ./shared/pdf-templates
|
||||||
|
COPY --chown=node:node ./shared/email-components ./shared/email-components
|
||||||
|
|
||||||
# Build webapp package
|
# Build webapp package
|
||||||
RUN pnpm run build:webapp
|
RUN pnpm run build:webapp
|
||||||
|
|
||||||
FROM nginx
|
# Stage 2: Nginx
|
||||||
|
FROM nginx:alpine
|
||||||
|
|
||||||
COPY ./packages/webapp/nginx/sites/default.conf /etc/nginx/conf.d/default.conf
|
# Copy nginx configuration
|
||||||
COPY --from=build /app/packages/webapp/dist /usr/share/nginx/html
|
COPY --chown=root:root ./packages/webapp/nginx/sites/default.conf /etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
|
# Copy built webapp assets from builder stage
|
||||||
|
COPY --from=builder --chown=nginx:nginx /app/packages/webapp/dist /usr/share/nginx/html
|
||||||
|
|
||||||
|
# Expose port
|
||||||
|
EXPOSE 80
|
||||||
|
|
||||||
|
# Nginx runs as nginx user by default, which is good for security
|
||||||
|
# No CMD needed as nginx base image already has it
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
"@blueprintjs/colors": "4.1.19",
|
"@blueprintjs/colors": "4.1.19",
|
||||||
"@blueprintjs/core": "^4.20.2",
|
"@blueprintjs/core": "^4.20.2",
|
||||||
"@blueprintjs/datetime": "^4.4.37",
|
"@blueprintjs/datetime": "^4.4.37",
|
||||||
"@blueprintjs/datetime2": "^3.0.10",
|
"@blueprintjs/datetime2": "^0.9.0",
|
||||||
"@blueprintjs/popover2": "^1.14.11",
|
"@blueprintjs/popover2": "^1.14.11",
|
||||||
"@blueprintjs/select": "^4.9.24",
|
"@blueprintjs/select": "^4.9.24",
|
||||||
"@blueprintjs/table": "^4.10.12",
|
"@blueprintjs/table": "^4.10.12",
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import intl from 'react-intl-universal';
|
import intl from 'react-intl-universal';
|
||||||
import { Intent, Alert } from '@blueprintjs/core';
|
import { Intent, Alert } from '@blueprintjs/core';
|
||||||
import { queryCache } from 'react-query';
|
import { useQueryClient } from 'react-query';
|
||||||
import { FormattedMessage as T, AppToaster } from '@/components';
|
import { FormattedMessage as T, AppToaster } from '@/components';
|
||||||
|
|
||||||
import { withAlertStoreConnect } from '@/containers/Alert/withAlertStoreConnect';
|
import { withAlertStoreConnect } from '@/containers/Alert/withAlertStoreConnect';
|
||||||
@@ -22,6 +22,7 @@ function AccountBulkActivateAlert({
|
|||||||
requestBulkActivateAccounts,
|
requestBulkActivateAccounts,
|
||||||
}) {
|
}) {
|
||||||
const [isLoading, setLoading] = useState(false);
|
const [isLoading, setLoading] = useState(false);
|
||||||
|
const queryClient = useQueryClient();
|
||||||
const selectedRowsCount = 0;
|
const selectedRowsCount = 0;
|
||||||
|
|
||||||
// Handle alert cancel.
|
// Handle alert cancel.
|
||||||
@@ -38,7 +39,7 @@ function AccountBulkActivateAlert({
|
|||||||
message: intl.get('the_accounts_has_been_successfully_activated'),
|
message: intl.get('the_accounts_has_been_successfully_activated'),
|
||||||
intent: Intent.SUCCESS,
|
intent: Intent.SUCCESS,
|
||||||
});
|
});
|
||||||
queryCache.invalidateQueries('accounts-table');
|
queryClient.invalidateQueries('accounts-table');
|
||||||
})
|
})
|
||||||
.catch((errors) => {})
|
.catch((errors) => {})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import React, { useState } from 'react';
|
|||||||
import { FormattedMessage as T } from '@/components';
|
import { FormattedMessage as T } from '@/components';
|
||||||
import intl from 'react-intl-universal';
|
import intl from 'react-intl-universal';
|
||||||
import { Intent, Alert } from '@blueprintjs/core';
|
import { Intent, Alert } from '@blueprintjs/core';
|
||||||
import { queryCache } from 'react-query';
|
import { useQueryClient } from 'react-query';
|
||||||
import { AppToaster } from '@/components';
|
import { AppToaster } from '@/components';
|
||||||
|
|
||||||
// import { withAccountsActions } from '@/containers/Accounts/withAccountsTableActions';
|
// import { withAccountsActions } from '@/containers/Accounts/withAccountsTableActions';
|
||||||
@@ -22,8 +22,8 @@ function AccountBulkInactivateAlert({
|
|||||||
|
|
||||||
closeAlert,
|
closeAlert,
|
||||||
}) {
|
}) {
|
||||||
|
|
||||||
const [isLoading, setLoading] = useState(false);
|
const [isLoading, setLoading] = useState(false);
|
||||||
|
const queryClient = useQueryClient();
|
||||||
const selectedRowsCount = 0;
|
const selectedRowsCount = 0;
|
||||||
|
|
||||||
// Handle alert cancel.
|
// Handle alert cancel.
|
||||||
@@ -39,7 +39,7 @@ function AccountBulkInactivateAlert({
|
|||||||
message: intl.get('the_accounts_have_been_successfully_inactivated'),
|
message: intl.get('the_accounts_have_been_successfully_inactivated'),
|
||||||
intent: Intent.SUCCESS,
|
intent: Intent.SUCCESS,
|
||||||
});
|
});
|
||||||
queryCache.invalidateQueries('accounts-table');
|
queryClient.invalidateQueries('accounts-table');
|
||||||
})
|
})
|
||||||
.catch((errors) => {})
|
.catch((errors) => {})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import React, { useCallback } from 'react';
|
|||||||
import intl from 'react-intl-universal';
|
import intl from 'react-intl-universal';
|
||||||
import { AppToaster, FormattedMessage as T } from '@/components';
|
import { AppToaster, FormattedMessage as T } from '@/components';
|
||||||
import { Intent, Alert } from '@blueprintjs/core';
|
import { Intent, Alert } from '@blueprintjs/core';
|
||||||
import { queryCache } from 'react-query';
|
import { useQueryClient } from 'react-query';
|
||||||
|
|
||||||
import { useApproveEstimate } from '@/hooks/query';
|
import { useApproveEstimate } from '@/hooks/query';
|
||||||
|
|
||||||
@@ -25,6 +25,7 @@ function EstimateApproveAlert({
|
|||||||
// #withAlertActions
|
// #withAlertActions
|
||||||
closeAlert,
|
closeAlert,
|
||||||
}) {
|
}) {
|
||||||
|
const queryClient = useQueryClient();
|
||||||
const { mutateAsync: deliverEstimateMutate, isLoading } =
|
const { mutateAsync: deliverEstimateMutate, isLoading } =
|
||||||
useApproveEstimate();
|
useApproveEstimate();
|
||||||
|
|
||||||
@@ -40,7 +41,7 @@ function EstimateApproveAlert({
|
|||||||
message: intl.get('the_estimate_has_been_approved_successfully'),
|
message: intl.get('the_estimate_has_been_approved_successfully'),
|
||||||
intent: Intent.SUCCESS,
|
intent: Intent.SUCCESS,
|
||||||
});
|
});
|
||||||
queryCache.invalidateQueries('estimates-table');
|
queryClient.invalidateQueries('estimates-table');
|
||||||
})
|
})
|
||||||
.catch((error) => {})
|
.catch((error) => {})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { DialogContent } from '@/components';
|
import { DialogContent } from '@/components';
|
||||||
import { useQuery, queryCache } from 'react-query';
|
import { useQuery, useQueryClient } from 'react-query';
|
||||||
|
|
||||||
import ReferenceNumberForm from '@/containers/JournalNumber/ReferenceNumberForm';
|
import ReferenceNumberForm from '@/containers/JournalNumber/ReferenceNumberForm';
|
||||||
|
|
||||||
@@ -31,6 +31,7 @@ function BillNumberDialogContent({
|
|||||||
// #withBillsActions
|
// #withBillsActions
|
||||||
setBillNumberChanged,
|
setBillNumberChanged,
|
||||||
}) {
|
}) {
|
||||||
|
const queryClient = useQueryClient();
|
||||||
const fetchSettings = useQuery(['settings'], () => requestFetchOptions({}));
|
const fetchSettings = useQuery(['settings'], () => requestFetchOptions({}));
|
||||||
|
|
||||||
const handleSubmitForm = (values, { setSubmitting }) => {
|
const handleSubmitForm = (values, { setSubmitting }) => {
|
||||||
@@ -45,7 +46,7 @@ function BillNumberDialogContent({
|
|||||||
setBillNumberChanged(true);
|
setBillNumberChanged(true);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
queryCache.invalidateQueries('settings');
|
queryClient.invalidateQueries('settings');
|
||||||
}, 250);
|
}, 250);
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import {
|
|||||||
FeatureCan,
|
FeatureCan,
|
||||||
InputPrependText,
|
InputPrependText,
|
||||||
} from '@/components';
|
} from '@/components';
|
||||||
import { FMoneyInputGroup, FFormGroup } from '@/components/Forms';
|
import { FMoneyInputGroup, FFormGroup, FDateInput } from '@/components/Forms';
|
||||||
|
|
||||||
import { useCustomerOpeningBalanceContext } from './CustomerOpeningBalanceFormProvider';
|
import { useCustomerOpeningBalanceContext } from './CustomerOpeningBalanceFormProvider';
|
||||||
import { useSetPrimaryBranchToForm } from './utils';
|
import { useSetPrimaryBranchToForm } from './utils';
|
||||||
@@ -59,28 +59,24 @@ function CustomerOpeningBalanceFields({
|
|||||||
</FFormGroup>
|
</FFormGroup>
|
||||||
|
|
||||||
{/*------------ Opening balance at -----------*/}
|
{/*------------ Opening balance at -----------*/}
|
||||||
<FastField name={'opening_balance_at'}>
|
<FFormGroup
|
||||||
{({ form, field: { value } }) => (
|
name={'opening_balance_at'}
|
||||||
<FormGroup
|
label={<T id={'customer_opening_balance.label.opening_balance_at'} />}
|
||||||
label={
|
fill
|
||||||
<T id={'customer_opening_balance.label.opening_balance_at'} />
|
fastField
|
||||||
}
|
|
||||||
className={Classes.FILL}
|
|
||||||
>
|
>
|
||||||
<DateInput
|
<FDateInput
|
||||||
{...momentFormatter('YYYY/MM/DD')}
|
name={'opening_balance_at'}
|
||||||
onChange={handleDateChange((formattedDate) => {
|
formatDate={(date) => date.toLocaleDateString()}
|
||||||
form.setFieldValue('opening_balance_at', formattedDate);
|
parseDate={(str) => new Date(str)}
|
||||||
})}
|
|
||||||
value={tansformDateValue(value)}
|
|
||||||
popoverProps={{ position: Position.BOTTOM, minimal: true }}
|
popoverProps={{ position: Position.BOTTOM, minimal: true }}
|
||||||
inputProps={{
|
inputProps={{
|
||||||
leftIcon: <Icon icon={'date-range'} />,
|
leftIcon: <Icon icon={'date-range'} />,
|
||||||
}}
|
}}
|
||||||
|
fill
|
||||||
|
fastField
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FFormGroup>
|
||||||
)}
|
|
||||||
</FastField>
|
|
||||||
|
|
||||||
<If condition={!isEqual(base_currency, customer.currency_code)}>
|
<If condition={!isEqual(base_currency, customer.currency_code)}>
|
||||||
{/*------------ Opening balance exchange rate -----------*/}
|
{/*------------ Opening balance exchange rate -----------*/}
|
||||||
@@ -99,12 +95,15 @@ function CustomerOpeningBalanceFields({
|
|||||||
<FFormGroup
|
<FFormGroup
|
||||||
label={<T id={'branch'} />}
|
label={<T id={'branch'} />}
|
||||||
name={'opening_balance_branch_id'}
|
name={'opening_balance_branch_id'}
|
||||||
className={classNames('form-group--select-list', Classes.FILL)}
|
fill
|
||||||
|
fastField
|
||||||
>
|
>
|
||||||
<BranchSelect
|
<BranchSelect
|
||||||
name={'opening_balance_branch_id'}
|
name={'opening_balance_branch_id'}
|
||||||
branches={branches}
|
branches={branches}
|
||||||
popoverProps={{ minimal: true }}
|
popoverProps={{ minimal: true }}
|
||||||
|
fastField
|
||||||
|
fill
|
||||||
/>
|
/>
|
||||||
</FFormGroup>
|
</FFormGroup>
|
||||||
</FeatureCan>
|
</FeatureCan>
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ function CustomerOpeningBalanceForm({
|
|||||||
const handleFormSubmit = (values, { setSubmitting, setErrors }) => {
|
const handleFormSubmit = (values, { setSubmitting, setErrors }) => {
|
||||||
const formValues = {
|
const formValues = {
|
||||||
...values,
|
...values,
|
||||||
|
opening_balance_at: moment(values.opening_balance_at).format('YYYY-MM-DD'),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle request response success.
|
// Handle request response success.
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ function VendorOpeningBalanceForm({
|
|||||||
const handleFormSubmit = (values, { setSubmitting, setErrors }) => {
|
const handleFormSubmit = (values, { setSubmitting, setErrors }) => {
|
||||||
const formValues = {
|
const formValues = {
|
||||||
...values,
|
...values,
|
||||||
|
opening_balance_at: moment(values.opening_balance_at).format('YYYY-MM-DD'),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle request response success.
|
// Handle request response success.
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import {
|
|||||||
FeatureCan,
|
FeatureCan,
|
||||||
InputPrependText,
|
InputPrependText,
|
||||||
} from '@/components';
|
} from '@/components';
|
||||||
import { FMoneyInputGroup, FFormGroup } from '@/components/Forms';
|
import { FMoneyInputGroup, FFormGroup, FDateInput } from '@/components/Forms';
|
||||||
|
|
||||||
import { useVendorOpeningBalanceContext } from './VendorOpeningBalanceFormProvider';
|
import { useVendorOpeningBalanceContext } from './VendorOpeningBalanceFormProvider';
|
||||||
import { useSetPrimaryBranchToForm } from './utils';
|
import { useSetPrimaryBranchToForm } from './utils';
|
||||||
@@ -59,26 +59,24 @@ function VendorOpeningBalanceFormFields({
|
|||||||
</FFormGroup>
|
</FFormGroup>
|
||||||
|
|
||||||
{/*------------ Opening balance at -----------*/}
|
{/*------------ Opening balance at -----------*/}
|
||||||
<FastField name={'opening_balance_at'}>
|
<FFormGroup
|
||||||
{({ form, field: { value } }) => (
|
name={'opening_balance_at'}
|
||||||
<FormGroup
|
|
||||||
label={<T id={'vendor_opening_balance.label.opening_balance_at'} />}
|
label={<T id={'vendor_opening_balance.label.opening_balance_at'} />}
|
||||||
className={Classes.FILL}
|
fill
|
||||||
|
fastField
|
||||||
>
|
>
|
||||||
<DateInput
|
<FDateInput
|
||||||
{...momentFormatter('YYYY/MM/DD')}
|
name={'opening_balance_at'}
|
||||||
onChange={handleDateChange((formattedDate) => {
|
formatDate={(date) => date.toLocaleDateString()}
|
||||||
form.setFieldValue('opening_balance_at', formattedDate);
|
parseDate={(str) => new Date(str)}
|
||||||
})}
|
|
||||||
value={tansformDateValue(value)}
|
|
||||||
popoverProps={{ position: Position.BOTTOM, minimal: true }}
|
popoverProps={{ position: Position.BOTTOM, minimal: true }}
|
||||||
inputProps={{
|
inputProps={{
|
||||||
leftIcon: <Icon icon={'date-range'} />,
|
leftIcon: <Icon icon={'date-range'} />,
|
||||||
}}
|
}}
|
||||||
|
fill
|
||||||
|
fastField
|
||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FFormGroup>
|
||||||
)}
|
|
||||||
</FastField>
|
|
||||||
|
|
||||||
<If condition={!isEqual(base_currency, vendor.currency_code)}>
|
<If condition={!isEqual(base_currency, vendor.currency_code)}>
|
||||||
{/*------------ Opening balance exchange rate -----------*/}
|
{/*------------ Opening balance exchange rate -----------*/}
|
||||||
@@ -97,7 +95,8 @@ function VendorOpeningBalanceFormFields({
|
|||||||
<FFormGroup
|
<FFormGroup
|
||||||
label={<T id={'branch'} />}
|
label={<T id={'branch'} />}
|
||||||
name={'opening_balance_branch_id'}
|
name={'opening_balance_branch_id'}
|
||||||
className={classNames('form-group--select-list', Classes.FILL)}
|
fill
|
||||||
|
fastField
|
||||||
>
|
>
|
||||||
<BranchSelect
|
<BranchSelect
|
||||||
name={'opening_balance_branch_id'}
|
name={'opening_balance_branch_id'}
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ export function useEditCustomerOpeningBalance(props) {
|
|||||||
|
|
||||||
return useMutation(
|
return useMutation(
|
||||||
([id, values]) =>
|
([id, values]) =>
|
||||||
apiRequest.post(`customers/${id}/opening_balance`, values),
|
apiRequest.put(`customers/${id}/opening-balance`, values),
|
||||||
{
|
{
|
||||||
onSuccess: (res, [id, values]) => {
|
onSuccess: (res, [id, values]) => {
|
||||||
// Invalidate specific customer.
|
// Invalidate specific customer.
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ export function useEditVendorOpeningBalance(props) {
|
|||||||
const apiRequest = useApiRequest();
|
const apiRequest = useApiRequest();
|
||||||
|
|
||||||
return useMutation(
|
return useMutation(
|
||||||
([id, values]) => apiRequest.post(`vendors/${id}/opening_balance`, values),
|
([id, values]) => apiRequest.put(`vendors/${id}/opening-balance`, values),
|
||||||
{
|
{
|
||||||
onSuccess: (res, [id, values]) => {
|
onSuccess: (res, [id, values]) => {
|
||||||
// Invalidate specific vendor.
|
// Invalidate specific vendor.
|
||||||
|
|||||||
213
pnpm-lock.yaml
generated
213
pnpm-lock.yaml
generated
@@ -54,6 +54,15 @@ importers:
|
|||||||
'@bigcapital/utils':
|
'@bigcapital/utils':
|
||||||
specifier: '*'
|
specifier: '*'
|
||||||
version: link:../../shared/bigcapital-utils
|
version: link:../../shared/bigcapital-utils
|
||||||
|
'@bull-board/api':
|
||||||
|
specifier: ^5.22.0
|
||||||
|
version: 5.23.0(@bull-board/ui@5.23.0)
|
||||||
|
'@bull-board/express':
|
||||||
|
specifier: ^5.22.0
|
||||||
|
version: 5.23.0
|
||||||
|
'@bull-board/nestjs':
|
||||||
|
specifier: ^5.22.0
|
||||||
|
version: 5.23.0(@bull-board/api@5.23.0)(@bull-board/express@5.23.0)(@nestjs/common@10.4.7)(@nestjs/core@10.4.7)(reflect-metadata@0.2.2)(rxjs@7.8.1)
|
||||||
'@casl/ability':
|
'@casl/ability':
|
||||||
specifier: ^5.4.3
|
specifier: ^5.4.3
|
||||||
version: 5.4.4
|
version: 5.4.4
|
||||||
@@ -411,7 +420,7 @@ importers:
|
|||||||
version: 0.3.7(@babel/core@7.28.5)(@blueprintjs/core@4.20.2)(@blueprintjs/select@4.9.24)(formik@2.4.6)(react-dom@18.3.1)(react-is@18.3.1)(react@18.3.1)
|
version: 0.3.7(@babel/core@7.28.5)(@blueprintjs/core@4.20.2)(@blueprintjs/select@4.9.24)(formik@2.4.6)(react-dom@18.3.1)(react-is@18.3.1)(react@18.3.1)
|
||||||
'@blueprintjs-formik/datetime':
|
'@blueprintjs-formik/datetime':
|
||||||
specifier: ^0.4.0
|
specifier: ^0.4.0
|
||||||
version: 0.4.0(@babel/core@7.28.5)(@blueprintjs-formik/core@0.3.7)(@blueprintjs/core@4.20.2)(@blueprintjs/datetime2@3.0.10)(@blueprintjs/datetime@4.4.37)(@blueprintjs/select@4.9.24)(formik@2.4.6)(react-dom@18.3.1)(react-is@18.3.1)(react@18.3.1)
|
version: 0.4.0(@babel/core@7.28.5)(@blueprintjs-formik/core@0.3.7)(@blueprintjs/core@4.20.2)(@blueprintjs/datetime2@0.9.37)(@blueprintjs/datetime@4.4.37)(@blueprintjs/select@4.9.24)(formik@2.4.6)(react-dom@18.3.1)(react-is@18.3.1)(react@18.3.1)
|
||||||
'@blueprintjs-formik/select':
|
'@blueprintjs-formik/select':
|
||||||
specifier: ^0.4.5
|
specifier: ^0.4.5
|
||||||
version: 0.4.5(@blueprintjs/core@4.20.2)(@blueprintjs/select@4.9.24)(formik@2.4.6)(react-dom@18.3.1)(react@18.3.1)
|
version: 0.4.5(@blueprintjs/core@4.20.2)(@blueprintjs/select@4.9.24)(formik@2.4.6)(react-dom@18.3.1)(react@18.3.1)
|
||||||
@@ -425,8 +434,8 @@ importers:
|
|||||||
specifier: ^4.4.37
|
specifier: ^4.4.37
|
||||||
version: 4.4.37(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1)
|
version: 4.4.37(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1)
|
||||||
'@blueprintjs/datetime2':
|
'@blueprintjs/datetime2':
|
||||||
specifier: ^3.0.10
|
specifier: ^0.9.0
|
||||||
version: 3.0.10(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1)
|
version: 0.9.37(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1)
|
||||||
'@blueprintjs/popover2':
|
'@blueprintjs/popover2':
|
||||||
specifier: ^1.14.11
|
specifier: ^1.14.11
|
||||||
version: 1.14.11(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1)
|
version: 1.14.11(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1)
|
||||||
@@ -4636,7 +4645,7 @@ packages:
|
|||||||
- react-is
|
- react-is
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@blueprintjs-formik/datetime@0.4.0(@babel/core@7.28.5)(@blueprintjs-formik/core@0.3.7)(@blueprintjs/core@4.20.2)(@blueprintjs/datetime2@3.0.10)(@blueprintjs/datetime@4.4.37)(@blueprintjs/select@4.9.24)(formik@2.4.6)(react-dom@18.3.1)(react-is@18.3.1)(react@18.3.1):
|
/@blueprintjs-formik/datetime@0.4.0(@babel/core@7.28.5)(@blueprintjs-formik/core@0.3.7)(@blueprintjs/core@4.20.2)(@blueprintjs/datetime2@0.9.37)(@blueprintjs/datetime@4.4.37)(@blueprintjs/select@4.9.24)(formik@2.4.6)(react-dom@18.3.1)(react-is@18.3.1)(react@18.3.1):
|
||||||
resolution: {integrity: sha512-51RW41DSM96seIgOGz2gw2DX1SfH8+Ydi9JBCNmLaFZRqyKZgRX+qpxmltgbS97lk2IOfCEyKSxoGGfz4XlnPg==}
|
resolution: {integrity: sha512-51RW41DSM96seIgOGz2gw2DX1SfH8+Ydi9JBCNmLaFZRqyKZgRX+qpxmltgbS97lk2IOfCEyKSxoGGfz4XlnPg==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@blueprintjs-formik/core': ^0.3.2 || 4 || 5
|
'@blueprintjs-formik/core': ^0.3.2 || 4 || 5
|
||||||
@@ -4651,7 +4660,7 @@ packages:
|
|||||||
'@blueprintjs-formik/core': 0.3.7(@babel/core@7.28.5)(@blueprintjs/core@4.20.2)(@blueprintjs/select@4.9.24)(formik@2.4.6)(react-dom@18.3.1)(react-is@18.3.1)(react@18.3.1)
|
'@blueprintjs-formik/core': 0.3.7(@babel/core@7.28.5)(@blueprintjs/core@4.20.2)(@blueprintjs/select@4.9.24)(formik@2.4.6)(react-dom@18.3.1)(react-is@18.3.1)(react@18.3.1)
|
||||||
'@blueprintjs/core': 4.20.2(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1)
|
'@blueprintjs/core': 4.20.2(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1)
|
||||||
'@blueprintjs/datetime': 4.4.37(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1)
|
'@blueprintjs/datetime': 4.4.37(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1)
|
||||||
'@blueprintjs/datetime2': 3.0.10(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1)
|
'@blueprintjs/datetime2': 0.9.37(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1)
|
||||||
'@blueprintjs/select': 4.9.24(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1)
|
'@blueprintjs/select': 4.9.24(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1)
|
||||||
formik: 2.4.6(react@18.3.1)
|
formik: 2.4.6(react@18.3.1)
|
||||||
lodash.get: 4.4.2
|
lodash.get: 4.4.2
|
||||||
@@ -4694,12 +4703,6 @@ packages:
|
|||||||
tslib: 2.5.3
|
tslib: 2.5.3
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@blueprintjs/colors@5.1.12:
|
|
||||||
resolution: {integrity: sha512-7GQWUQ82eLE1te++DC8fRO2B31bsSwia82NLamZfKgjHY9V4zxafMT1DK5gKlmmy0nCjpdcCc+df4aVZMHGLww==}
|
|
||||||
dependencies:
|
|
||||||
tslib: 2.6.2
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@blueprintjs/core@4.20.2(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1):
|
/@blueprintjs/core@4.20.2(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1):
|
||||||
resolution: {integrity: sha512-5v4Nr0jozfAjiOkjY4zvt1XSpt4ldnrSaxtwo506S2cxJYfwFeMTmDshXNPFcc8L1fjZMxi0IWI2WABXzZXS6w==}
|
resolution: {integrity: sha512-5v4Nr0jozfAjiOkjY4zvt1XSpt4ldnrSaxtwo506S2cxJYfwFeMTmDshXNPFcc8L1fjZMxi0IWI2WABXzZXS6w==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
@@ -4727,51 +4730,28 @@ packages:
|
|||||||
tslib: 2.5.3
|
tslib: 2.5.3
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@blueprintjs/core@6.4.1(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1):
|
/@blueprintjs/datetime2@0.9.37(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1):
|
||||||
resolution: {integrity: sha512-JSA8seGiZ2dpmugO7Cea4bh0XEkTioDyzM1Z/0piFsziVv4OeV3jrmMXMegtCdHqpwpWYj8reGuPzFKHGemXXw==}
|
resolution: {integrity: sha512-eCoQbQK1IO5uegmYugj/K5helj6oA7s/4ZkA7dweBHBHXQ3KmZLh2Zj+O0ESOq/qqvlvCfiNCfsObk309EIbKQ==}
|
||||||
hasBin: true
|
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@types/react': '18'
|
'@types/react': ^16.14.32 || 17
|
||||||
react: '18'
|
react: ^16.8 || 17
|
||||||
react-dom: '18'
|
react-dom: ^16.8 || 17
|
||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
'@types/react':
|
'@types/react':
|
||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
'@blueprintjs/colors': 5.1.12
|
'@blueprintjs/core': 4.20.2(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1)
|
||||||
'@blueprintjs/icons': 6.3.2(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1)
|
'@blueprintjs/datetime': 4.4.37(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1)
|
||||||
'@popperjs/core': 2.11.8
|
'@blueprintjs/popover2': 1.14.11(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1)
|
||||||
|
'@blueprintjs/select': 4.9.24(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1)
|
||||||
'@types/react': 18.3.4
|
'@types/react': 18.3.4
|
||||||
classnames: 2.5.1
|
classnames: 2.5.1
|
||||||
normalize.css: 8.0.1
|
|
||||||
react: 18.3.1
|
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
|
||||||
react-popper: 2.3.0(@popperjs/core@2.11.8)(react-dom@18.3.1)(react@18.3.1)
|
|
||||||
react-transition-group: 4.4.5(react-dom@18.3.1)(react@18.3.1)
|
|
||||||
tslib: 2.6.2
|
|
||||||
use-sync-external-store: 1.6.0(react@18.3.1)
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@blueprintjs/datetime2@3.0.10(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1):
|
|
||||||
resolution: {integrity: sha512-pli0hkv93aH2Ou3inZ2KIdNBLj5dYW8XVu21Rr3fSoh5b9aUsThAVDmb51LjlfNiPVi1i+y2omGuDRTKV+zUgw==}
|
|
||||||
peerDependencies:
|
|
||||||
'@types/react': '18'
|
|
||||||
react: '18'
|
|
||||||
react-dom: '18'
|
|
||||||
peerDependenciesMeta:
|
|
||||||
'@types/react':
|
|
||||||
optional: true
|
|
||||||
dependencies:
|
|
||||||
'@blueprintjs/colors': 5.1.12
|
|
||||||
'@blueprintjs/core': 6.4.1(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1)
|
|
||||||
'@blueprintjs/datetime': 6.0.10(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1)
|
|
||||||
'@blueprintjs/icons': 6.3.2(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1)
|
|
||||||
'@types/react': 18.3.4
|
|
||||||
date-fns: 2.30.0
|
date-fns: 2.30.0
|
||||||
|
date-fns-tz: 1.3.8(date-fns@2.30.0)
|
||||||
|
lodash: 4.17.21
|
||||||
react: 18.3.1
|
react: 18.3.1
|
||||||
react-day-picker: 8.10.1(date-fns@2.30.0)(react@18.3.1)
|
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
react-dom: 18.3.1(react@18.3.1)
|
||||||
tslib: 2.6.2
|
tslib: 2.5.3
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@blueprintjs/datetime@4.4.37(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1):
|
/@blueprintjs/datetime@4.4.37(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1):
|
||||||
@@ -4793,30 +4773,6 @@ packages:
|
|||||||
tslib: 2.5.3
|
tslib: 2.5.3
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@blueprintjs/datetime@6.0.10(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1):
|
|
||||||
resolution: {integrity: sha512-8i8P12OwCe0JGTkX20EtHvembEjwfqkf1pQcec3lMdPDDeEpPmV3vzPWxwCS+NSc6vUGl/2aAFs+Ro7qDW1msw==}
|
|
||||||
peerDependencies:
|
|
||||||
'@types/react': '18'
|
|
||||||
react: '18'
|
|
||||||
react-dom: '18'
|
|
||||||
peerDependenciesMeta:
|
|
||||||
'@types/react':
|
|
||||||
optional: true
|
|
||||||
dependencies:
|
|
||||||
'@blueprintjs/core': 6.4.1(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1)
|
|
||||||
'@blueprintjs/icons': 6.3.2(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1)
|
|
||||||
'@blueprintjs/select': 6.0.10(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1)
|
|
||||||
'@types/react': 18.3.4
|
|
||||||
classnames: 2.5.1
|
|
||||||
date-fns: 2.30.0
|
|
||||||
date-fns-tz: 2.0.1(date-fns@2.30.0)
|
|
||||||
react: 18.3.1
|
|
||||||
react-day-picker: 8.10.1(date-fns@2.30.0)(react@18.3.1)
|
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
|
||||||
react-innertext: 1.1.5(@types/react@18.3.4)(react@18.3.1)
|
|
||||||
tslib: 2.6.2
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@blueprintjs/icons@4.16.0:
|
/@blueprintjs/icons@4.16.0:
|
||||||
resolution: {integrity: sha512-cyfgjUZcZCtQrXWUV8FwqYTFEzduV4a0N7yhOU38jY+cBRCLu/sDrD0Osvfk4DGRvNe4YjY7pohVLFSxpg68Uw==}
|
resolution: {integrity: sha512-cyfgjUZcZCtQrXWUV8FwqYTFEzduV4a0N7yhOU38jY+cBRCLu/sDrD0Osvfk4DGRvNe4YjY7pohVLFSxpg68Uw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -4825,24 +4781,6 @@ packages:
|
|||||||
tslib: 2.5.3
|
tslib: 2.5.3
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@blueprintjs/icons@6.3.2(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1):
|
|
||||||
resolution: {integrity: sha512-rOdSg7yPmjtqy3e+wD66tXCrzt57M59htVOikwunTaCyQ61+bsF0PyqLfNlhsw1mXqZm8uxSINs1bhnwXhQCiw==}
|
|
||||||
peerDependencies:
|
|
||||||
'@types/react': '18'
|
|
||||||
react: '18'
|
|
||||||
react-dom: '18'
|
|
||||||
peerDependenciesMeta:
|
|
||||||
'@types/react':
|
|
||||||
optional: true
|
|
||||||
dependencies:
|
|
||||||
'@types/react': 18.3.4
|
|
||||||
change-case: 4.1.2
|
|
||||||
classnames: 2.5.1
|
|
||||||
react: 18.3.1
|
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
|
||||||
tslib: 2.6.2
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@blueprintjs/popover2@1.14.11(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1):
|
/@blueprintjs/popover2@1.14.11(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1):
|
||||||
resolution: {integrity: sha512-5XAjeb2mlWjYXC0pqrNDLzHSsX85Zaiv8jixxUN9abarMUUFKGATgGF8MRsWTLAW94Gli6CB1lzVkrYkRHHf6Q==}
|
resolution: {integrity: sha512-5XAjeb2mlWjYXC0pqrNDLzHSsX85Zaiv8jixxUN9abarMUUFKGATgGF8MRsWTLAW94Gli6CB1lzVkrYkRHHf6Q==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -4884,26 +4822,6 @@ packages:
|
|||||||
tslib: 2.5.3
|
tslib: 2.5.3
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@blueprintjs/select@6.0.10(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1):
|
|
||||||
resolution: {integrity: sha512-RjDuomn4KhluiN7tVofLLX6S+b+un0mLehvmOSETpqk1C8lHXCxReIXxFiWqTB+YiIgkqQ6aRNjQs35cJBbrfg==}
|
|
||||||
peerDependencies:
|
|
||||||
'@types/react': '18'
|
|
||||||
react: '18'
|
|
||||||
react-dom: '18'
|
|
||||||
peerDependenciesMeta:
|
|
||||||
'@types/react':
|
|
||||||
optional: true
|
|
||||||
dependencies:
|
|
||||||
'@blueprintjs/colors': 5.1.12
|
|
||||||
'@blueprintjs/core': 6.4.1(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1)
|
|
||||||
'@blueprintjs/icons': 6.3.2(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1)
|
|
||||||
'@types/react': 18.3.4
|
|
||||||
classnames: 2.5.1
|
|
||||||
react: 18.3.1
|
|
||||||
react-dom: 18.3.1(react@18.3.1)
|
|
||||||
tslib: 2.6.2
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/@blueprintjs/table@4.10.12(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1):
|
/@blueprintjs/table@4.10.12(@types/react@18.3.4)(react-dom@18.3.1)(react@18.3.1):
|
||||||
resolution: {integrity: sha512-f5NbjuHQ/1vb5hkT+WsCnjIU3Vp2OCWdyDUopVmgj4qHIgzgX38vP2sLS8aUFlbsEQr/xAU9mfkpp4FT+65mXA==}
|
resolution: {integrity: sha512-f5NbjuHQ/1vb5hkT+WsCnjIU3Vp2OCWdyDUopVmgj4qHIgzgX38vP2sLS8aUFlbsEQr/xAU9mfkpp4FT+65mXA==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -4946,6 +4864,51 @@ packages:
|
|||||||
tslib: 2.5.3
|
tslib: 2.5.3
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@bull-board/api@5.23.0(@bull-board/ui@5.23.0):
|
||||||
|
resolution: {integrity: sha512-ZZGsWJ+XBG49GAlNgAL9tTEV6Ms7gMkQnZDbzwUhjGChCKWy62RWuPoZSefNXau9QH9+QzlzHRUeFvt4xr5wiw==}
|
||||||
|
peerDependencies:
|
||||||
|
'@bull-board/ui': 5.23.0
|
||||||
|
dependencies:
|
||||||
|
'@bull-board/ui': 5.23.0
|
||||||
|
redis-info: 3.1.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@bull-board/express@5.23.0:
|
||||||
|
resolution: {integrity: sha512-t/mHzJMlZBtSKD8v81kbZoexOmtQxKVnHZfHJ0um5vrkHNJJuzKuwbR+n9nf1u89AGdyXoWxqDhBDslxv3zrrQ==}
|
||||||
|
dependencies:
|
||||||
|
'@bull-board/api': 5.23.0(@bull-board/ui@5.23.0)
|
||||||
|
'@bull-board/ui': 5.23.0
|
||||||
|
ejs: 3.1.10
|
||||||
|
express: 4.21.1
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@bull-board/nestjs@5.23.0(@bull-board/api@5.23.0)(@bull-board/express@5.23.0)(@nestjs/common@10.4.7)(@nestjs/core@10.4.7)(reflect-metadata@0.2.2)(rxjs@7.8.1):
|
||||||
|
resolution: {integrity: sha512-eRJCz6PqKzrlZfd7akc+6/1eXwNO7Fp468TmSo8avlPcKhStZH3fUmCF6xxfRQpm9kn/eDOp+H18CTnSafmwmw==}
|
||||||
|
peerDependencies:
|
||||||
|
'@bull-board/api': ^5.23.0
|
||||||
|
'@bull-board/express': ^5.23.0
|
||||||
|
'@nestjs/common': ^9.0.0 || ^10.0.0
|
||||||
|
'@nestjs/core': ^9.0.0 || ^10.0.0
|
||||||
|
reflect-metadata: ^0.1.13 || ^0.2.0
|
||||||
|
rxjs: ^7.8.1
|
||||||
|
dependencies:
|
||||||
|
'@bull-board/api': 5.23.0(@bull-board/ui@5.23.0)
|
||||||
|
'@bull-board/express': 5.23.0
|
||||||
|
'@nestjs/bull-shared': 10.2.2(@nestjs/common@10.4.7)(@nestjs/core@10.4.7)
|
||||||
|
'@nestjs/common': 10.4.7(class-transformer@0.5.1)(class-validator@0.14.1)(reflect-metadata@0.2.2)(rxjs@7.8.1)
|
||||||
|
'@nestjs/core': 10.4.7(@nestjs/common@10.4.7)(@nestjs/platform-express@10.4.7)(@nestjs/websockets@10.4.20)(reflect-metadata@0.2.2)(rxjs@7.8.1)
|
||||||
|
reflect-metadata: 0.2.2
|
||||||
|
rxjs: 7.8.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/@bull-board/ui@5.23.0:
|
||||||
|
resolution: {integrity: sha512-iI/Ssl8T5ZEn9s899Qz67m92M6RU8thf/aqD7cUHB2yHmkCjqbw7s7NaODTsyArAsnyu7DGJMWm7EhbfFXDNgQ==}
|
||||||
|
dependencies:
|
||||||
|
'@bull-board/api': 5.23.0(@bull-board/ui@5.23.0)
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@casl/ability@5.4.4:
|
/@casl/ability@5.4.4:
|
||||||
resolution: {integrity: sha512-7+GOnMUq6q4fqtDDesymBXTS9LSDVezYhFiSJ8Rn3f0aQLeRm7qHn66KWbej4niCOvm0XzNj9jzpkK0yz6hUww==}
|
resolution: {integrity: sha512-7+GOnMUq6q4fqtDDesymBXTS9LSDVezYhFiSJ8Rn3f0aQLeRm7qHn66KWbej4niCOvm0XzNj9jzpkK0yz6hUww==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -15031,10 +14994,10 @@ packages:
|
|||||||
is-data-view: 1.0.1
|
is-data-view: 1.0.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/date-fns-tz@2.0.1(date-fns@2.30.0):
|
/date-fns-tz@1.3.8(date-fns@2.30.0):
|
||||||
resolution: {integrity: sha512-fJCG3Pwx8HUoLhkepdsP7Z5RsucUi+ZBOxyM5d0ZZ6c4SdYustq0VMmOu6Wf7bli+yS/Jwp91TOCqn9jMcVrUA==}
|
resolution: {integrity: sha512-qwNXUFtMHTTU6CFSFjoJ80W8Fzzp24LntbjFFBgL/faqds4e5mo9mftoRLgr3Vi1trISsg4awSpYVsOQCRnapQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
date-fns: 2.x
|
date-fns: '>=2.0.0'
|
||||||
dependencies:
|
dependencies:
|
||||||
date-fns: 2.30.0
|
date-fns: 2.30.0
|
||||||
dev: false
|
dev: false
|
||||||
@@ -15557,7 +15520,6 @@ packages:
|
|||||||
hasBin: true
|
hasBin: true
|
||||||
dependencies:
|
dependencies:
|
||||||
jake: 10.9.1
|
jake: 10.9.1
|
||||||
dev: true
|
|
||||||
|
|
||||||
/electron-to-chromium@1.4.782:
|
/electron-to-chromium@1.4.782:
|
||||||
resolution: {integrity: sha512-JUfU61e8tr+i5Y1FKXcKs+Xe+rJ+CEqm4cgv1kMihPE2EvYHmYyVr3Im/+1+Z5B29Be2EEGCZCwAc6Tazdl1Yg==}
|
resolution: {integrity: sha512-JUfU61e8tr+i5Y1FKXcKs+Xe+rJ+CEqm4cgv1kMihPE2EvYHmYyVr3Im/+1+Z5B29Be2EEGCZCwAc6Tazdl1Yg==}
|
||||||
@@ -16832,7 +16794,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==}
|
resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==}
|
||||||
dependencies:
|
dependencies:
|
||||||
minimatch: 5.1.6
|
minimatch: 5.1.6
|
||||||
dev: true
|
|
||||||
|
|
||||||
/fill-range@7.1.1:
|
/fill-range@7.1.1:
|
||||||
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
|
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
|
||||||
@@ -18572,7 +18533,6 @@ packages:
|
|||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
filelist: 1.0.4
|
filelist: 1.0.4
|
||||||
minimatch: 3.1.2
|
minimatch: 3.1.2
|
||||||
dev: true
|
|
||||||
|
|
||||||
/javascript-natural-sort@0.7.1:
|
/javascript-natural-sort@0.7.1:
|
||||||
resolution: {integrity: sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==}
|
resolution: {integrity: sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==}
|
||||||
@@ -20133,7 +20093,6 @@ packages:
|
|||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
dependencies:
|
dependencies:
|
||||||
brace-expansion: 2.0.1
|
brace-expansion: 2.0.1
|
||||||
dev: true
|
|
||||||
|
|
||||||
/minimatch@8.0.4:
|
/minimatch@8.0.4:
|
||||||
resolution: {integrity: sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==}
|
resolution: {integrity: sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==}
|
||||||
@@ -22488,16 +22447,6 @@ packages:
|
|||||||
react: 18.3.1
|
react: 18.3.1
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/react-day-picker@8.10.1(date-fns@2.30.0)(react@18.3.1):
|
|
||||||
resolution: {integrity: sha512-TMx7fNbhLk15eqcMt+7Z7S2KF7mfTId/XJDjKE8f+IUcFn0l08/kI4FiYTL/0yuOLmEcbR4Fwe3GJf/NiiMnPA==}
|
|
||||||
peerDependencies:
|
|
||||||
date-fns: ^2.28.0 || ^3.0.0
|
|
||||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0
|
|
||||||
dependencies:
|
|
||||||
date-fns: 2.30.0
|
|
||||||
react: 18.3.1
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/react-docgen-typescript@2.2.2(typescript@5.6.3):
|
/react-docgen-typescript@2.2.2(typescript@5.6.3):
|
||||||
resolution: {integrity: sha512-tvg2ZtOpOi6QDwsb3GZhOjDkkX0h8Z2gipvTg6OVMUyoYoURhEiRNePT8NZItTVCDh39JJHnLdfCOkzoLbFnTg==}
|
resolution: {integrity: sha512-tvg2ZtOpOi6QDwsb3GZhOjDkkX0h8Z2gipvTg6OVMUyoYoURhEiRNePT8NZItTVCDh39JJHnLdfCOkzoLbFnTg==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -23273,6 +23222,12 @@ packages:
|
|||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/redis-info@3.1.0:
|
||||||
|
resolution: {integrity: sha512-ER4L9Sh/vm63DkIE0bkSjxluQlioBiBgf5w1UuldaW/3vPcecdljVDisZhmnCMvsxHNiARTTDDHGg9cGwTfrKg==}
|
||||||
|
dependencies:
|
||||||
|
lodash: 4.17.21
|
||||||
|
dev: false
|
||||||
|
|
||||||
/redis-parser@3.0.0:
|
/redis-parser@3.0.0:
|
||||||
resolution: {integrity: sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==}
|
resolution: {integrity: sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
@@ -25786,14 +25741,6 @@ packages:
|
|||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/use-sync-external-store@1.6.0(react@18.3.1):
|
|
||||||
resolution: {integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==}
|
|
||||||
peerDependencies:
|
|
||||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
|
||||||
dependencies:
|
|
||||||
react: 18.3.1
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/util-deprecate@1.0.2:
|
/util-deprecate@1.0.2:
|
||||||
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user