Skip to content

Tài liệu Developer

BANA (BANA) là hệ thống Point of Sale (POS) cấp doanh nghiệp được thiết kế cho môi trường bán vé sự kiện đa merchant, bán lẻ và dịch vụ lưu trú. Được xây dựng dưới dạng Bun monorepo, nền tảng tận dụng IGNIS Framework cho các microservice dựa trên dependency injection, Tauri cho ứng dụng desktop đa nền tảng và stack React hiện đại cho giao diện web.

Tài liệu này cung cấp tham khảo kỹ thuật toàn diện cho các developer xây dựng, mở rộng hoặc tích hợp với nền tảng BANA.

Hướng dẫn cho Developer

Mới bắt đầu? Hãy bắt đầu với những hướng dẫn này:

Hướng dẫnBạn sẽ học được gì
Getting StartedClone, cài đặt, build, chạy service đầu tiên của bạn
Build SystemMakefile targets, dependency graph, Docker builds
Environment ReferenceMọi biến môi trường trên tất cả các service
Git WorkflowBranching, commits, MRs, code review, glab CLI
IGNIS PatternsApplication hierarchy, DI, controller factory, model patterns

Kiến trúc & Tham khảo

Hướng dẫnNội dung bao gồm
System ArchitectureService registry, dependency chain, ánh xạ database schema, component matrix
Event ArchitectureKafka topics, CDC pipeline, WebSocket topics, webhook events
Database Guide11 PostgreSQL schemas, Drizzle ORM, quy trình migration, column enrichers
Testing GuideBun test runner, preload mocking, Object.create pattern, mock factories
Frontend PatternsShared stack, app dependency graph, thư viện component, i18n

Technology Stack

Phân loạiCông nghệPhiên bảnMô tả
RuntimeBun>=1.3.8Runtime JavaScript all-in-one nhanh với hỗ trợ TypeScript native
FrameworkIGNIS0.0.7-7Framework DI TypeScript-first (@venizia/ignis)
Web ServerHono4.11.3Framework web siêu nhanh với routing type-safe
API SchemaZod4.1.13Thư viện validate schema TypeScript-first
API DocsHono Zod OpenAPI1.2.0Sinh spec OpenAPI 3.1 từ Zod schemas
ORMDrizzle ORM0.45.1Bộ công cụ SQL type-safe cho PostgreSQL
ORM MigrationsDrizzle Kit0.31.8Công cụ migrate schema cho Drizzle
ValidationDrizzle Zod0.8.3Sinh Zod schema từ Drizzle tables
DatabasePostgreSQL14+Cơ sở dữ liệu quan hệ đa schema (7 schemas, 55+ models)
Cache/QueueRedis6+Kho dữ liệu trong bộ nhớ (5 logical databases)
Job QueueBullMQLatestHàng đợi công việc phân tán dựa trên Redis (24 queues, 3 partitions mỗi queue)
SearchTypesenseLatestSearch engine nhanh, chịu lỗi chính tả với đồng bộ CDC real-time
StorageMinioLatestObject storage tương thích S3 cho tài sản media
API ReferenceScalar Hono0.9.28UI tài liệu API hiện đại cho Hono
Password Hashingbcrypt6.0.0Hàm băm adaptive cho credentials
Date/TimeDay.js1.11.19Thư viện xử lý ngày giờ nhẹ
PostgreSQL Clientnode-postgres8.16.3Client PostgreSQL non-blocking cho Node.js
TypeScriptTypeScript~5.9.3Superset có kiểu của JavaScript
HelpersIGNIS Helpers0.0.6-7Thư viện tiện ích framework IGNIS (@venizia/ignis-helpers)
DesktopTauri2.xFramework desktop nhẹ, an toàn (Rust + WebView)
FrontendReact19.xThư viện UI khai báo cho web và desktop apps
Build ToolVite7.xCông cụ build frontend thế hệ mới với HMR
StylingTailwindCSS4.xFramework CSS utility-first
UI ComponentsRadix UI + shadcnLatestComponent primitive accessible, composable

Tổng quan Kiến trúc

📱
Frontend Applications
React 19 + Vite 7 + TailwindCSS 4 + shadcn/ui
🌐
client
Admin Dashboard
🖥️
sale-renderer
POS Desktop UI
sale-main
Tauri Backend (Rust)
🏢
bo
Back Office
shared
🧩
admin-ui-kit
UI Component Library
shared
🔧
core
App Constants, Hooks
▼ HTTP REST / WebSocket / Tauri IPC
⚙️
Backend Microservices
IGNIS Framework (Bun + Hono + Drizzle + Zod)
🔐
identity
Auth, Users, RBAC
🏪
commerce
Products, Pricing
🛒
sale
Orders, Checkout
📦
inventory
Stock, PO, Tracking
🔍
search
Typesense + CDC
📁
asset
Media, Minio S3
🧾
invoice
E-Invoice, PDF
💰
finance
Wallets, Transactions
💳
payment
Orchestration Layer
📡
signal
WebSocket, E2E ECDH
shared
🔧
core
Base Classes, Utils
▼ IGNIS Components (Dependency Injection)
🔌
Third-Party Integrations
External service connectors and adapters
💳
mq-pay
Multi-Provider Payments
🧾
iiapi
VNPAY E-Invoice API
📊
t-van
Tax VAN / CQT
▼ HTTPS / REST API
☁️
External Services
Third-party providers and government authorities
🏦
VNPAY
Payment Gateway
🧾
VNPAY Invoice
E-Invoice Provider
🏛️
CQT
General Tax Dept
📄
T-VAN Providers
Viettel, VNPT

Kiến trúc Hệ thống

Package Dependency Graph

Frontend Applications

Ứng dụngPackageStackMô tả
client@nx-app/clientReact 19.2.1, Vite 7.1.7, TailwindCSS 4.1.16, Redux Toolkit, TanStack Query/TableAdmin dashboard chính với 28 screen module: categories, products, sale orders, inventory, finance (wallets, transactions, categories), purchase orders, users, roles, merchants, organizers, devices, terminals, reports, settings
bo@nx-app/boReact 19, Vite 7, TailwindCSS 4Back Office cho nhân viên merchant/organizer với giao diện admin đơn giản (5 screens: home, merchant, organizer, sign-in, errors)
sale-renderer@nx-app/sale-rendererReact 19.2.0, Vite 7.2.4, TailwindCSS 4.1.18, Tauri 2.9.1, Socket.IO ClientPOS desktop app WebView: tạo đơn hàng, quét barcode, in hóa đơn, tích hợp thanh toán, cập nhật real-time qua WebSocket
sale-main@nx-app/sale-mainTauri 2.x, Rust, SQLite (Sea-ORM)Backend POS desktop (Tauri main process): xử lý thiết bị ngoại vi USB (scanner, printer, card reader), local database, custom plugins (USB, Payment, External Display, Machine UID)
admin-ui-kit@nx-app/admin-ui-kitRadix UI, shadcn/ui, lucide-react, TailwindCSS 4Thư viện component UI dùng chung: 38 shadcn components + custom core/icon components. Được dùng bởi clientbo
core@nx-app/coreReact 19Module app core dùng chung: constants, hooks, locales (i18n), utilities. Peer dependency: ra-core, @minimaltech/ra-core-infra

Backend Packages

PackageTên PackagePortTính năng chínhDependenciesTrạng thái
core@nx/coreN/AFoundation dùng chung: DefaultApplication, SoftDeletableRepository, 7 PostgreSQL schemas (55 models), Snowflake ID generator, xác thực cross-service, CryptoUtility (AES-256-GCM), bootstrap helpers (bootstrapApplication, bootstrapMigration, createAppConfig, createMigrationProcessLoader)N/AProduction
identity@nx/identity3001Xác thực & phân quyền: chiến lược JWT/Basic auth, CRUD user với tạo atomic (user + identifiers + profile + roles), quản lý employee với mapping organizer/merchant, xác minh email (mã 6 chữ số, hết hạn 10 phút, giới hạn tần suất), băm mật khẩu (bcrypt), RBAC với 5 vai trò mặc định (SUPER_ADMIN 999, ADMIN 998, OPERATOR 997, ORGANIZER_OWNER 899, EMPLOYEE 898)@nx/coreProduction
commerce@nx/commerce3002Product catalog & pricing engine: product aggregates (info, identifiers, variants), định giá động với đánh giá dựa trên rule (OVERRIDE/DISCOUNT/MARKUP operators: EQ, NE, GT, GTE, LT, LTE, IN, NIN), hỗ trợ đa merchant, categories, sale channels, lọc truy cập dựa trên role@nx/core, @nx/asset, @nx/inventory, @nx/search, @nx/t-vanProduction
sale@nx/sale3003Quản lý đơn hàng & checkout: vòng đời đơn hàng (DRAFT → PROCESSING → PARTIAL → COMPLETED/CANCELLED), quản lý item với tự động merge cho duplicate, validate checkout (giỏ không rỗng, item hợp lệ), xử lý sự kiện MQ-Pay cho cập nhật trạng thái thanh toán, ràng buộc tối đa (9999 qty/item, 100 items/order)@nx/core, @nx/mq-payProduction
inventory@nx/inventoryN/AQuản lý tồn kho & purchase orders: theo dõi tồn kho đa địa điểm (quantityOnHand, quantityAvailable, quantityReserved), vòng đời PO (DRAFT → PROCESSING → CONFIRMED → COMPLETED), 20+ tracking type định nghĩa sẵn (STOCK_IN, SALE, TRANSFER, RETURN, ADJUSTMENT, v.v.), tra cứu tracking type được cache bằng Redis@nx/coreProduction
search@nx/searchN/ATích hợp search Typesense: đồng bộ real-time qua Debezium CDC (PostgreSQL → Typesense), chuyển đổi filter IGNIS sang Typesense query (eq, neq, gt, gte, lt, lte, between, inq, nin, and, or), 6 collections (products, organizers, merchants, categories, devices, sale-channels), endpoint chẩn đoán@nx/coreProduction
asset@nx/assetN/ALưu trữ file & media: dual storage (Minio S3-compatible + local disk), entity MetaLink cho theo dõi metadata (bucketName, objectName, link, mimetype, size, etag, storageType, principalId, principalType), sinh presigned URL@nx/coreProduction
invoice@nx/invoiceN/ASinh E-Invoice (tuân thủ Việt Nam): các loại hóa đơn (VAT, Bán hàng, POS, phiếu xuất kho, biên lai, chứng từ PIT), định dạng XML, chữ ký số, sinh PDF, đánh số tuần tự@nx/core, @nx/iiapi, @nx/t-vanProduction
finance@nx/financeN/AQuản lý tài chính & kế toán: ví (CASH, BANK, EWALLET, CREDIT_CARD) với số dư ban đầu/hiện tại, theo dõi giao dịch thu/chi, 20 category đã seed, xử lý theo sự kiện (commerce initialized → tạo ví mặc định, payment success → ghi nhận thu, PO received → ghi nhận chi) qua Redis Pub/Sub + BullMQ@nx/coreProduction
payment@nx/paymentN/ALớp orchestration thanh toán: quản lý cấu hình webhook (đăng ký endpoint, loại sự kiện, metadata retry), tải/giải mã payment credential từ bảng Configuration (AES-256-GCM), dispatch webhook với retry exponential backoff, khởi tạo MQ-Pay component với credential getter động@nx/core, @nx/mq-payProduction
signal@nx/signalN/AGiao tiếp WebSocket real-time: trao đổi khóa ECDH P-256 bắt buộc + thông điệp mã hóa AES-256-GCM, xác thực JWT khi handshake, REST API cho broadcast/room/client messaging, state backed bởi Redis cho cross-instance delivery (chế độ single hoặc cluster), stateless (không database, không migrations)@nx/coreProduction
gateway@nx/gatewayN/AAPI Gateway: routing, cân bằng tải, circuit breaker, rate limiting@nx/corePlanned

Third-Party Integrations

Tích hợpTên PackageMô tảTính năng chínhExternal Services
mq-pay@nx/mq-payHệ thống thanh toán đa providerProviders: SYSTEM (CASH, BANK_TRANSFER), VNPAY_QR_MMS, VNPAY_PHONE_POS, VNPAY_SMART_POS; Vòng đời giao dịch (NEW 100 → PARTIAL 300 → SETTLED 600 / CANCELLED 505 / BLOCKED 800 / CLOSED 900); Loại payment attempt (MAKE_PAYMENT 100, CANCEL_PAYMENT 200, REFUND_PAYMENT 300); BullMQ 3-partition queues (scheduler, confirmation) với 10 job đồng thời/partition; Event emitter với 11+ loại sự kiện; Mẫu singleton AppRegistry (không dùng được DI @inject())VNPAY
iiapi@nx/iiapiTích hợp VNPAY E-Invoice (viiAPI)Loại hóa đơn: VAT, Bán hàng, POS, phiếu xuất kho nội bộ, biên lai, chứng từ PIT; 15 services (VAT invoice, POS VAT invoice, POS sale invoice, invoice management, webhook, OTP); Multi-client registry với OAuth2 token tự động refresh (buffer 5 phút); Request/response qua VIIAPIRequestHelper; Test endpoint: https://invoice-api.vnpaytest.vn, Production: https://api.vnpayinvoice.vnVNPAY Invoice
t-van@nx/t-vanTích hợp Vietnam Tax VANTruy vấn hóa đơn điện tử từ Tax Authority (CQT); Tra cứu thông tin người nộp thuế theo tax code/ID (4 loại query: 00001 Citizen ID, 00003 Tax Code, 00130 ID Tax Payer, 00132 Personal Tax Code); Multi-client registry; Tự động chia batch cho query lớn (VNPAY tối đa 10 tax codes/request)CQT (qua providers Viettel, VNPT T-VAN)

Infrastructure

Data Stores

Dịch vụPortDatabase/IndexMục đíchGhi chú
PostgreSQL5432N/ACơ sở dữ liệu quan hệ7 schemas, 55 models
Redis6379DB0CacheCaching đa mục đích
Redis6379DB1BullMQ Queues24 queues (4 systems × 3 partitions × 2 types)
Redis6379DB2Pub/Sub SubscriberKênh subscribe sự kiện
Redis6379DB3Pub/Sub PublisherKênh publish sự kiện
Redis6379DB4WebSocket StateState cross-instance của dịch vụ Signal
Typesense8108N/ASearch engine6 collections: products, merchants, categories, organizers, devices, sale-channels
Minio9000N/AObject storageAPI tương thích S3, presigned URLs

PostgreSQL Database Schemas

SchemaSố lượng ModelMô tảModel ví dụ
public30Core business entitiesUser, Role, Product, ProductInfo, ProductIdentifier, ProductVariant, Merchant, Organizer, Category, Device, Terminal, SaleChannel, Configuration, Employee, Vendor
pricing7Pricing engineFare, FareRule, Cost, Tax
allocation4Chỗ ngồi & venues sự kiệnVenue, Section, Seat, Allocation
inventory8Quản lý tồn khoInventory, PurchaseOrder, PurchaseOrderItem, InventoryTracking, InventoryTrackingType
sale2Đơn bán hàngSaleOrder, SaleOrderItem
finance3Bản ghi tài chínhFinanceWallet, FinanceCategory, FinanceTransaction
payment1Cấu hình thanh toánWebhookConfig
Tổng557 schemas

BullMQ Queue Systems

SystemQueue TypesPartitionsTổng QueuesMục đích
Commerce236Đồng bộ product, cập nhật catalog
Finance236Xử lý giao dịch, đối soát
Inventory236Cập nhật tồn, xử lý PO
Sale236Xử lý đơn hàng, cập nhật thanh toán
Tổng8324

Lưu ý: Mỗi queue type có 3 partitions (P01, P02, P03) để phân tải. Mặc định: 10 job đồng thời mỗi partition.

Kiến trúc theo Sự kiện

Redis Pub/Sub Channels

ChannelLoại sự kiệnPublisherSubscribersPayload
UserOnboardingEventChannels.COMMERCE_INITIALIZEDCommerce Initialized@nx/commerce@nx/finance{ merchantId: string, organizerId: string }
PaymentEventChannels.PAYMENT_SUCCESSPayment Success@nx/mq-pay@nx/sale, @nx/finance{ transactionId: string, amount: number, currency: string, referenceId: string, referenceType: string }
UserOnboardingEventChannels.SELLER_REGISTEREDSeller Registered@nx/identityN/A{ userId: string, email: string, roles: string[] }

MQ-Pay Event System

Loại sự kiệnTriggerPayloadSubscribers
mq-pay:transaction.createdGiao dịch được tạo{ transactionId, amount, currency, provider }@nx/sale
mq-pay:transaction.settledThanh toán đã settle{ transactionId, settlementDate }@nx/sale, @nx/finance
mq-pay:transaction.cancelledThanh toán bị huỷ{ transactionId, reason }@nx/sale
mq-pay:attempt.createdPayment attempt được tạo{ attemptId, transactionId, type }@nx/sale
mq-pay:attempt.sentPayment request đã gửi{ attemptId, provider, sentAt }@nx/sale
mq-pay:attempt.successThanh toán thành công{ attemptId, transactionId, paidAt }@nx/sale, @nx/finance
mq-pay:attempt.failedThanh toán thất bại{ attemptId, errorCode, errorMessage }@nx/sale
mq-pay:attempt.expiredThanh toán hết hạn{ attemptId, expiredAt }@nx/sale
mq-pay:refund.successHoàn tiền thành công{ refundId, transactionId, amount }@nx/sale, @nx/finance
mq-pay:refund.failedHoàn tiền thất bại{ refundId, errorCode }@nx/sale

Bảo mật

LớpCơ chếTriển khai
Xác thựcJWT + Basic AuthJWT token với expiry cấu hình được (mặc định: 3600s), Basic auth với băm mật khẩu bcrypt (cost factor: 6.0.0)
Phân quyềnRBAC5 vai trò mặc định: SUPER_ADMIN (999), ADMIN (998), OPERATOR (997), ORGANIZER_OWNER (899), EMPLOYEE (898). Middleware dựa trên role qua decorator @authenticate
WebSocket EncryptionECDH P-256 + AES-256-GCMTrao đổi khóa bắt buộc khi handshake, shared key mỗi client, envelope thông điệp mã hóa { event: 'encrypted', data: { iv, ct } }
Lưu trữ CredentialAES-256-GCM EncryptionPayment credentials được mã hóa trong bảng Configuration bằng CryptoUtility, giải mã on-the-fly qua PaymentConfigurationService
Băm mật khẩubcryptHàm băm adaptive với salt rounds (bcrypt 6.0.0)
CORSHono CORS MiddlewareCấu hình trong DefaultApplication với origin cho phép dựa trên môi trường
Rate LimitingXác minh EmailCooldown 60s, 5 lần gửi lại/ngày, khoá 15 phút sau 3 lần thử thất bại

Setup môi trường phát triển

Yêu cầu tiên quyết

Công cụPhiên bảnMục đích
Bun>=1.3.8Runtime, package manager, build tool
PostgreSQL14+Cơ sở dữ liệu chính
Redis6+Cache, queues, pub/sub, WebSocket state
TypesenseLatestSearch engine (tùy chọn cho tính năng search)
MinioLatestObject storage (tùy chọn cho tính năng asset)
Node.js18+Tauri tooling, một số công cụ build frontend
RustLatestBiên dịch Tauri backend (sale-main)

Quick Start

bash
# Clone repository
git clone https://git.nexpando.com/bana/bana.git
cd bana

# Install dependencies
make install           # or: bun install

# Set up environment variables
cd packages/core       # or any package
cp .env.example .env.development

# Build all packages (respects dependency order)
make build             # Builds: core → asset,search,identity,inventory,finance,sale,signal → commerce → payment

# Run database migrations (from any package directory)
cd packages/identity
bun run migrate:dev

# Start development server (from package directory)
bun run server:dev     # Uses .env.development

Lệnh Build

bash
# Root-level build (respects dependency order)
make build                    # Build all: third-parties → packages
make build-packages           # Build only packages/*
make build-3rd                # Build only third-parties/*

# Individual package builds
make core                     # @nx/core (build first)
make identity                 # @nx/identity
make sale-order               # @nx/sale
make commerce                 # @nx/commerce (requires asset, search, inventory)
make inventory                # @nx/inventory
make finance                  # @nx/finance
make payment                  # @nx/payment (requires mq-pay)
make signal                   # @nx/signal
make mq-pay                   # @nx/mq-pay
make iiapi                    # @nx/iiapi
make t-van                    # @nx/t-van

# Per-package build (inside package directory)
cd packages/sale
bun run rebuild               # ALWAYS use this (clean + tsc + tsc-alias)
                              # NEVER run `tsc` directly (path aliases won't resolve)

Development Servers

bash
# Backend services
make dev-sale-order           # Start @nx/sale (http://localhost:3003)
make dev-commerce             # Start @nx/commerce (http://localhost:3002)
make dev-identity             # Start @nx/identity (http://localhost:3001)
make dev-finance              # Start @nx/finance
make dev-payment              # Start @nx/payment
make dev-signal               # Start @nx/signal (WebSocket)

# Frontend apps
make dev-client               # Start admin dashboard (Vite HMR)
make dev-bo                   # Start back office (Vite HMR)
make dev-wiki                 # Start VitePress docs (http://localhost:5173)

# Tauri desktop app
cd apps/sale-renderer
bunx tauri dev                # Start POS desktop app (hot reload)

Lint & Test

bash
# Linting (root level)
make lint                     # Lint everything
make lint-packages            # Lint all packages/*
make lint-3rd                 # Lint all third-parties/*
make lint-sale-order          # Lint @nx/sale
make lint-finance             # Lint @nx/finance
make lint-mq-pay              # Lint @nx/mq-pay

# Linting (per package)
cd packages/sale
bun run lint:fix              # ESLint + Prettier auto-fix

# Testing (per package)
cd packages/sale
bun run rebuild               # Build first
bun run test                  # Run all tests (requires .env.test)
bun run test:watch            # Watch mode

# Single test file
bun test --env-file=.env.test dist/__tests__/path/to/file.test.js

Git Hooks

bash
# Set up git hooks (run once)
make setup-tools              # Configure git to use .githooks directory

# Pre-commit hook runs automatically on `git commit`
make pre-commit               # Run manually: lints all packages

Cấu hình Môi trường

Chiến lược dotenv-flow

Mỗi package dùng dotenv-flow cho cấu hình theo môi trường:

FileMục đíchĐược Git tracking
.env.exampleTemplate với tất cả biến
.env.developmentCài đặt developmentKhông (copy từ example)
.env.testMôi trường testKhông (copy từ example)
.env.localOverride local (ưu tiên cao nhất)Không

Biến môi trường Core

bash
# Application
APP_ENV_NODE_ENV=development
APP_ENV_APPLICATION_SECRET=<secret-key-32-chars>
APP_ENV_JWT_SECRET=<jwt-secret-key>
APP_ENV_JWT_EXPIRES_IN=3600

# PostgreSQL
APP_ENV_POSTGRES_HOST=localhost
APP_ENV_POSTGRES_PORT=5432
APP_ENV_POSTGRES_DATABASE=bana
APP_ENV_POSTGRES_USERNAME=postgres
APP_ENV_POSTGRES_PASSWORD=password

# Redis - Cache (DB0)
APP_ENV_CACHE_REDIS_HOST=localhost
APP_ENV_CACHE_REDIS_PORT=6379
APP_ENV_CACHE_REDIS_DB=0
APP_ENV_CACHE_REDIS_PASSWORD=

# Redis - Queue (DB1)
APP_ENV_QUEUE_REDIS_HOST=localhost
APP_ENV_QUEUE_REDIS_PORT=6379
APP_ENV_QUEUE_REDIS_DB=1
APP_ENV_QUEUE_REDIS_PASSWORD=

# Redis - WebSocket (DB4)
APP_ENV_WEBSOCKET_REDIS_MODE=single                    # or: cluster
APP_ENV_WEBSOCKET_REDIS_HOST=localhost
APP_ENV_WEBSOCKET_REDIS_PORT=6379
APP_ENV_WEBSOCKET_REDIS_DB=4
APP_ENV_WEBSOCKET_REDIS_PASSWORD=
APP_ENV_WEBSOCKET_REDIS_MAX_RETRY=5
APP_ENV_WEBSOCKET_ECDH_INFO=<HKDF-info-string>

# Typesense
APP_ENV_TYPESENSE_API_KEY=<api-key>
APP_ENV_TYPESENSE_NODES=http:localhost:8108            # format: protocol:host:port, comma-separated

# Minio
APP_ENV_MINIO_HOST=localhost
APP_ENV_MINIO_API_PORT=9000
APP_ENV_MINIO_CONSOLE_PORT=9001
APP_ENV_MINIO_ACCESS_KEY=minioadmin
APP_ENV_MINIO_SECRET_KEY=minioadmin
APP_ENV_MINIO_USE_SSL=false

# Snowflake ID Generator
APP_ENV_SNOWFLAKE_WORKER_ID=1
APP_ENV_SNOWFLAKE_EPOCH_CHECKPOINT=1704067200000       # 2024-01-01 00:00:00 UTC

# Cross-Service URLs
APP_ENV_IDENTITY_SERVICE_URL=http://localhost:3001
APP_ENV_COMMERCE_SERVICE_URL=http://localhost:3002
APP_ENV_SALE_SERVICE_URL=http://localhost:3003

# VNPAY (via mq-pay)
APP_ENV_VNPAY_TVAN_API_KEY=<api-key>

# Email (for identity email verification)
APP_ENV_SMTP_HOST=smtp.gmail.com
APP_ENV_SMTP_PORT=587
APP_ENV_SMTP_USER=<email@example.com>
APP_ENV_SMTP_PASSWORD=<app-password>

Cấu trúc Dự án

bana/
├── apps/                                # Frontend applications
│   ├── client/                          # Admin dashboard (React 19, Vite 7, TailwindCSS 4)
│   │   ├── src/screens/                 # 28 screen modules (products, orders, finance, users, etc.)
│   │   ├── src/layouts/                 # Layout components
│   │   └── package.json
│   ├── bo/                              # Back office (simplified admin)
│   │   ├── src/screens/                 # 5 screens (home, merchant, organizer, sign-in, errors)
│   │   └── package.json
│   ├── sale-renderer/                   # POS desktop UI (Tauri WebView)
│   │   ├── src/                         # React app
│   │   └── package.json
│   ├── sale-main/                       # POS desktop backend (Tauri Rust)
│   │   ├── src-tauri/                   # Rust source
│   │   ├── src-tauri/tauri-plugin-*/    # Custom plugins (USB, Payment, Display, Machine UID)
│   │   └── package.json
│   ├── admin-ui-kit/                    # Shared UI library (Radix UI + shadcn)
│   │   ├── components/shadcn/           # 38 shadcn components
│   │   ├── components/core/             # Custom core components
│   │   ├── components/icons/            # Icon components
│   │   └── package.json
│   └── core/                            # Shared app core (constants, hooks, locales, utilities)
│       └── package.json

├── packages/                            # Backend microservices (IGNIS-based)
│   ├── core/                            # Foundation package
│   │   ├── src/default-application.ts   # Base application class
│   │   ├── src/repositories/soft-deletable.repository.ts
│   │   ├── src/utilities/id-generator.utility.ts
│   │   ├── src/helpers/bootstraps/      # bootstrapApplication, bootstrapMigration
│   │   ├── src/models/schemas/          # 7 PostgreSQL schemas (55 models)
│   │   │   ├── public/                  # 30 models
│   │   │   ├── pricing/                 # 7 models
│   │   │   ├── allocation/              # 4 models
│   │   │   ├── inventory/               # 8 models
│   │   │   ├── sale/                    # 2 models
│   │   │   ├── finance/                 # 3 models
│   │   │   └── payment/                 # 1 model
│   │   └── package.json
│   ├── identity/                        # Auth, users, RBAC (port 3001)
│   │   ├── src/application.ts
│   │   ├── src/components/
│   │   ├── src/services/
│   │   └── package.json
│   ├── commerce/                        # Products, pricing (port 3002)
│   ├── sale/                            # Orders, checkout (port 3003)
│   ├── inventory/                       # Stock, purchase orders
│   ├── search/                          # Typesense integration
│   ├── asset/                           # Minio storage
│   ├── invoice/                         # E-Invoice generation
│   ├── finance/                         # Wallets, transactions
│   ├── payment/                         # Payment orchestration
│   └── signal/                          # WebSocket service

├── third-parties/                       # External integrations
│   ├── mq-pay/                          # Multi-provider payments
│   │   ├── src/component.ts             # MQPayComponent
│   │   ├── src/services/payment/        # Payment execution, cancellation, refund, verification
│   │   ├── src/helpers/app-registry.helper.ts  # Singleton registry
│   │   └── package.json
│   ├── iiapi/                           # VNPAY E-Invoice API
│   │   ├── src/iiapi.component.ts
│   │   └── package.json
│   └── t-van/                           # Tax VAN connector
│       ├── src/t-van.component.ts
│       └── package.json

├── docs/wiki/                           # VitePress documentation
│   ├── content/en/developer/            # English docs
│   └── content/vi/developer/            # Vietnamese docs

├── infrastructure/                      # Infrastructure & deployment configs
│   └── deployments/
│       └── develop/                     # Docker Compose configs per service

├── Makefile                             # Build automation
├── package.json                         # Root package (workspaces, overrides)
├── tsconfig.json                        # TypeScript config
├── .githooks/                           # Git hooks (pre-commit)
└── AGENTS.md                            # AI agent instructions (project rules, architecture)

IGNIS Framework Patterns

Dependency Injection

typescript
import { inject, BaseService, BindingKeys, BindingNamespaces } from '@venizia/ignis';

export class MyService extends BaseService {
  constructor(
    // String key pattern
    @inject({ key: 'repositories.UserRepository' })
    private userRepository: UserRepository,

    // Or with BindingKeys helper
    @inject({ key: BindingKeys.build({ namespace: BindingNamespaces.REPOSITORY, key: 'ProductRepository' }) })
    private productRepository: ProductRepository,
  ) {
    super({ scope: MyService.name });
  }

  async findUser(id: string): Promise<User> {
    return this.userRepository.findById({ id });
  }
}

Cấu trúc Component

typescript
import { BaseComponent, inject, CoreBindings, BaseApplication } from '@venizia/ignis';

export class MyComponent extends BaseComponent {
  constructor(
    @inject({ key: CoreBindings.APPLICATION_INSTANCE })
    protected application: BaseApplication,
  ) {
    super({
      scope: MyComponent.name,
      initDefault: { enable: true, container: application },
      bindings: {},
    });
  }

  override async binding(): Promise<void> {
    // Register repositories, services, controllers in correct order
    this.application.repository(MyRepository);
    this.application.service(MyService);
    this.application.controller(MyController);
  }
}

Vòng đời Application

typescript
import { DefaultApplication } from '@nx/core';

export class Application extends DefaultApplication {
  override preConfigure(): void {
    // Execute BEFORE boot phase
    this.configureServices();
    this.configureComponents();
    this.configureSecurity();
  }

  override configureComponents(): void {
    super.configureComponents();  // Call parent to register core components
    this.component(MyComponent);   // Register custom components
  }

  override async postConfigure(): Promise<void> {
    // Execute AFTER all components are bound
    await this.initializeExternalServices();
  }
}

Bootstrap Helpers (từ @nx/core)

typescript
// packages/*/src/index.ts - Application entry point
import { bootstrapApplication } from '@nx/core';
import { Application } from './application.js';
import { appConfig } from './common/app-config.js';
import { resolve } from 'node:path';

bootstrapApplication({
  ApplicationClass: Application,
  config: appConfig,
  options: { bannerPath: resolve(__dirname, '../resources/banner.txt') },
});

// packages/*/src/migrate.ts - Migration entry point
import { bootstrapMigration } from '@nx/core';
import { Application } from './application.js';
import { getMigrationProcesses } from './migrations/processes/migration-process.js';

bootstrapMigration({
  ApplicationClass: Application,
  getMigrationProcesses,
});

// packages/*/src/common/app-config.ts - Centralized config
import { createAppConfig } from '@nx/core';
export const appConfig = createAppConfig();

// packages/*/src/migrations/processes/migration-process.ts
import { createMigrationProcessLoader } from '@nx/core';

export const getMigrationProcesses = createMigrationProcessLoader({
  seedPaths: ['my-package-0001-seed-data', 'my-package-0002-seed-roles'],
  importFn: path => import(`../processes/${path}.js`),
});

Controller Factory (Auto CRUD)

typescript
import { controller } from '@venizia/ignis';
import { ControllerFactory } from '@venizia/ignis';
import { inject } from '@venizia/ignis';
import { MyRepository } from '../repositories/my.repository.js';
import { MyEntity } from '../models/entities/my.entity.js';

@controller({ path: '/my-entities' })
export class MyController extends ControllerFactory.defineCrudController({
  repository: { name: MyRepository.name },
  authenticate: { strategies: ['jwt', 'basic'] },  // Optional: require auth
  controller: { name: 'MyController', basePath: '/my-entities' },
  entity: () => MyEntity,
}) {
  constructor(
    @inject({ key: 'repositories.MyRepository' })
    repository: MyRepository,
  ) {
    super(repository);
  }

  // Auto-generated routes:
  // GET    /my-entities         - List with pagination, filtering, sorting
  // GET    /my-entities/:id     - Get by ID
  // POST   /my-entities         - Create
  // PATCH  /my-entities/:id     - Update
  // DELETE /my-entities/:id     - Delete (soft-delete if using SoftDeletableRepository)

  // Override or add custom routes as needed
}

Drizzle ORM Patterns

typescript
// Schema definition
import { pgTable, uuid, text, timestamp, decimal, integer } from 'drizzle-orm/pg-core';

export const products = pgTable('products', {
  id: uuid('id').primaryKey().defaultRandom(),
  name: text('name').notNull(),
  price: decimal('price', { precision: 10, scale: 4 }).notNull(),
  quantity: integer('quantity').default(0),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow(),
  modifiedAt: timestamp('modified_at', { withTimezone: true }).defaultNow(),
  deletedAt: timestamp('deleted_at', { withTimezone: true }),  // For soft-delete
});

// Repository with soft-delete
import { repository } from '@venizia/ignis';
import { SoftDeletableRepository } from '@nx/core';
import { PostgresCoreDataSource } from '@/datasources';
import { Product } from '../models/entities/product.entity.js';

@repository({ dataSource: PostgresCoreDataSource, model: Product })
export class ProductRepository extends SoftDeletableRepository<typeof products, Product, TProductPersist> {
  // Built-in methods:
  // - deleteById (sets deletedAt, not physical delete)
  // - restoreById (clears deletedAt)
  // - findById (excludes soft-deleted by default)
  // - find (excludes soft-deleted by default)
}

// Transactions
await this.productRepository.dataSource.withTransaction(async tx => {
  await this.productRepository.create({ data: productData, options: { transaction: tx } });
  await this.inventoryRepository.create({ data: inventoryData, options: { transaction: tx } });
  // Both succeed or both rollback
});

Zod Validation với Drizzle

typescript
import { createSelectSchema, createInsertSchema } from 'drizzle-zod';
import { products } from '../schemas/product.schema.js';

// Auto-generate Zod schemas from Drizzle tables
export const ProductSelectSchema = createSelectSchema(products);
export const ProductInsertSchema = createInsertSchema(products);

// Custom validation
import { z } from 'zod';

export const CreateProductSchema = ProductInsertSchema.omit({ id: true, createdAt: true, modifiedAt: true }).extend({
  name: z.string().min(2).max(255),
  price: z.number().positive().max(9999999.9999),
  quantity: z.number().int().nonnegative(),
});

export type CreateProductInput = z.infer<typeof CreateProductSchema>;

Liên kết nhanh

Backend Packages

PackageTài liệuMô tả
CoreTài liệuFoundation dùng chung: base classes, 7 DB schemas, utilities
IdentityTài liệuXác thực, RBAC, xác minh email
CommerceTài liệuProducts, pricing engine, merchants
SaleTài liệuĐơn hàng, checkout, tích hợp MQ-Pay
PaymentTài liệuOrchestration thanh toán, dispatch webhook
SignalTài liệuGiao tiếp WebSocket, mã hóa ECDH
AssetTài liệuLưu trữ file, Minio S3
InvoiceTài liệuSinh E-Invoice, PDF
GatewayTài liệuAPI Gateway (planned)

Third-Party Integrations

Tích hợpTài liệuMô tả
MQ-PayTài liệuHệ thống thanh toán đa provider (VNPAY, Cash)
IIAPITài liệuTích hợp VNPAY E-Invoice
T-VANTài liệuVietnam Tax VAN connector

Frontend Applications

Ứng dụngTài liệuMô tả
ClientTài liệuAdmin dashboard (28 screens)
POS DesktopRenderer / MainTauri desktop app
Admin UI KitTài liệuThư viện component dùng chung

Bước tiếp theo

Cho Developer mới

  1. Setup môi trường local: Cài đặt các yêu cầu (Bun, PostgreSQL, Redis)
  2. Build monorepo: Chạy make install && make build
  3. Khám phá package Core: Đọc Core Documentation để hiểu hạ tầng dùng chung
  4. Chạy một service: Khởi động dịch vụ Identity với make dev-identity, khám phá Swagger tại http://localhost:3001/docs
  5. Đọc IGNIS patterns: Nghiên cứu dependency injection, cấu trúc component, ví dụ controller factory ở trên

Cho Developer tích hợp

  1. Review tích hợp MQ-Pay: MQ-Pay Documentation cho luồng thanh toán
  2. Hiểu hệ thống sự kiện: Nghiên cứu Redis Pub/Sub channels và kiến trúc queue BullMQ
  3. Triển khai webhooks: Dùng dispatcher webhook @nx/payment với retry exponential backoff
  4. Test với sandbox: Dùng endpoint VNPAY test từ các tích hợp @nx/iiapi@nx/t-van

Cho Frontend Developer

  1. Setup client app: Chạy make dev-client và khám phá 28 screen module
  2. Dùng Admin UI Kit: Import component từ @nx-app/admin-ui-kit (38 shadcn components)
  3. Tích hợp với backend: Dùng TanStack Query cho API call, Redux Toolkit cho quản lý state
  4. Build POS desktop app: Khám phá kiến trúc Tauri trong sale-mainsale-renderer

Cho DevOps Engineer

  1. Review infrastructure: PostgreSQL 7 schemas, Redis 5 databases, Typesense, Minio
  2. Setup Docker Compose: Dùng infrastructure/deployments/develop/ cho stack local
  3. Cấu hình môi trường: Nghiên cứu các file .env.example trong các package
  4. Giám sát queues: Setup dashboard BullMQ để giám sát 24 queue
  5. Triển khai services: Mỗi package có Dockerfile, triển khai độc lập hoặc dạng monolith

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.