Skip to content

Hằng số

TrườngChi tiết
Tệp nguồnpackages/core/src/common/constants.ts (294 dòng)
Importimport { <ClassName> } from '@nx/core';
Mẫu thiết kếHằng số lớp tĩnh với xác thực dựa trên Set
Tổng số lớp14

Tổng quan

Tất cả hằng số toàn ứng dụng được tập trung trong một tệp duy nhất (src/common/constants.ts) bên trong gói @nx/core. Mọi gói khác import từ @nx/core thay vì tự định nghĩa các chuỗi cố định riêng.

Mỗi lớp hằng số tuân theo một mẫu nhất quán:

  1. Trường static readonly -- các giá trị hằng số thực tế.
  2. SCHEME_SET / TYPE_SET -- một Set chứa tất cả giá trị hợp lệ, dùng cho kiểm tra thành viên O(1).
  3. Phương thức isValid() -- phương thức tĩnh ủy quyền cho Set.
typescript
import { <ClassName> } from '@nx/core';

// Use a constant
const schema = PostgresSchemas.PUBLIC;

// Validate input
if (!PostgresSchemas.isValid(userInput)) {
  throw new Error('Invalid schema');
}

1. Hạ tầng

RedisModes

Bộ chọn chế độ kết nối Redis. Xác định ứng dụng kết nối đến một instance Redis đơn lẻ hay Redis Cluster.

TênGiá trịMô tả
SINGLE'single'Instance Redis đơn lẻ (standalone)
CLUSTER'cluster'Redis Cluster (đa node)

INFO

RedisModes không bao gồm SCHEME_SET hoặc phương thức isValid(). Việc xác thực được xử lý ở tầng cấu hình.

Cách sử dụng

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

const redisMode = applicationEnvironment.get<string>('APP_ENV_WEBSOCKET_REDIS_MODE')
  ?? RedisModes.SINGLE;

if (redisMode === RedisModes.CLUSTER) {
  // Initialize cluster connection
}

PostgresSchemas

Định danh cho bảy schema PostgreSQL được sử dụng trên toàn bộ cơ sở dữ liệu.

TênGiá trịMô tả
PUBLIC'public'Người dùng, vai trò, sản phẩm, merchant, organizer, cấu hình
PRICING'pricing'Giá vé, quy tắc giá, chi phí, thuế
ALLOCATION'allocation'Bố trí chỗ ngồi sự kiện và sơ đồ địa điểm
SALE'sale'Đơn hàng và mục đơn hàng
INVENTORY'inventory'Quản lý kho và tồn kho
FINANCE'finance'Ví, giao dịch, danh mục
PAYMENT'payment'Cấu hình webhook

Phương thức Hỗ trợ

Phương thứcChữ kýMô tả
isValidisValid(input: string): booleanTrả về true nếu input là thành viên của SCHEME_SET

Cách sử dụng

typescript
import { PostgresSchemas } from '@nx/core';
import { pgSchema } from 'drizzle-orm/pg-core';

// Define a table in the pricing schema
const pricingSchema = pgSchema(PostgresSchemas.PRICING);
const Fare = pricingSchema.table('Fare', { /* columns */ });

// Validate schema name
if (!PostgresSchemas.isValid(input)) {
  throw new Error(`Unknown schema: ${input}`);
}

// Use in migration config
const schemaFilter = [
  PostgresSchemas.PUBLIC,
  PostgresSchemas.ALLOCATION,
  PostgresSchemas.PRICING,
];

2. Bảng / Giao diện

TableConst

Giá trị mặc định cho các thành phần bảng dữ liệu và lưới được sử dụng bởi cả phân trang backend và giao diện frontend.

TênGiá trịMô tả
DEFAULT_NAME'System'Tên hiển thị mặc định của hệ thống
DEFAULT_PAGINATION{ pageIndex: 0, pageSize: 50 }Trang bắt đầu và kích thước trang
DEFAULT_ROWS_PER_PAGE_OPTIONS[25, 50, 75, 100]Các tùy chọn bộ chọn kích thước trang
DEFAULT_SORTING[{ id: 'createdAt', desc: true }]Sắp xếp mặc định: mới nhất trước
DEFAULT_FILTER{}Đối tượng bộ lọc rỗng
DEFAULT_SIZE180Chiều rộng cột mặc định theo pixel

INFO

TableConst không bao gồm SCHEME_SET hoặc phương thức isValid() vì nó chứa các đối tượng cấu hình mặc định, không phải giá trị liệt kê.

Cách sử dụng

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

async findAll(opts?: PaginationOptions) {
  const pagination = opts?.pagination ?? TableConst.DEFAULT_PAGINATION;
  const sorting = opts?.sorting ?? TableConst.DEFAULT_SORTING;

  return this.find({
    limit: pagination.pageSize,
    offset: pagination.pageIndex * pagination.pageSize,
    orderBy: sorting.map(s => ({ [s.id]: s.desc ? 'desc' : 'asc' })),
  });
}

TableConfigurations

Các khóa để lưu trữ cấu hình hiển thị bảng theo từng người dùng (hiển thị cột, thứ tự, kích thước). Mỗi khóa tương ứng với một bảng trên màn hình quản trị.

TênGiá trị
TABLE_ORGANIZER'TABLE_ORGANIZER'
TABLE_MERCHANT'TABLE_MERCHANT'
TABLE_CATEGORY'TABLE_CATEGORY'
TABLE_PRODUCT'TABLE_PRODUCT'
TABLE_USER'TABLE_USER'
TABLE_CATEGORY_TEMPLATE'TABLE_CATEGORY_TEMPLATE'
TABLE_MERCHANT_TYPE'TABLE_MERCHANT_TYPE'
TABLE_EMPLOYEE'TABLE_EMPLOYEE'
TABLE_SALE_CHANNEL'TABLE_SALE_CHANNEL'
TABLE_DEVICE'TABLE_DEVICE'
TABLE_ROLE'TABLE_ROLE'
TABLE_TRANSACTION'TABLE_TRANSACTION'
TABLE_REVENUE_REPORT'TABLE_REVENUE_REPORT'
TABLE_ORDER_REPORT'TABLE_ORDER_REPORT'
TABLE_CUSTOMER'TABLE_CUSTOMER'
TABLE_INVOICE'TABLE_INVOICE'
TABLE_TERMINAL'TABLE_TERMINAL'
TABLE_VENDOR'TABLE_VENDOR'
TABLE_INVENTORY_TRACKING'TABLE_INVENTORY_TRACKING'
TABLE_SALE_ORDER'TABLE_SALE_ORDER'
TABLE_INVENTORY'TABLE_INVENTORY'
TABLE_FINANCE_TRANSACTION'TABLE_FINANCE_TRANSACTION'
TABLE_FINANCE_CATEGORY'TABLE_FINANCE_CATEGORY'
TABLE_FINANCE_WALLET'TABLE_FINANCE_WALLET'
TABLE_PURCHASE_ORDER'TABLE_PURCHASE_ORDER'

Cách sử dụng

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

// Save user's table configuration
await configurationRepository.upsert({
  userId: currentUser.id,
  code: TableConfigurations.TABLE_PRODUCT,
  value: JSON.stringify({ columns: ['name', 'price', 'status'], pageSize: 25 }),
});

UserConfigurationCodes

Các khóa để lưu trữ dữ liệu tùy chọn cấp người dùng.

TênGiá trịMô tả
USER_PREFERENCES'PREFERENCES'Tùy chọn chung của người dùng (ngôn ngữ, giao diện, v.v.)

Cách sử dụng

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

const prefs = await configurationRepository.findOne({
  where: {
    userId: currentUser.id,
    code: UserConfigurationCodes.USER_PREFERENCES,
  },
});

3. Hệ thống

SystemConfigurations

Xác định các mục cấu hình cấp hệ thống được lưu trong bảng Configuration của cơ sở dữ liệu. Hiện tại được dùng để lưu thông tin xác thực nhà cung cấp thanh toán.

TênGiá trịMô tả
VNPAY_QR_MMS'VNPAY_QR_MMS'Cấu hình nhà cung cấp VNPAY QR MMS
VNPAY_PHONE_POS'VNPAY_PHONE_POS'Cấu hình nhà cung cấp VNPAY PhonePOS

Phương thức Hỗ trợ

Phương thứcChữ kýMô tả
isValidisValid(input: string): booleanTrả về true nếu input là thành viên của SCHEME_SET

Cách sử dụng

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

// Load payment configuration from the database
const config = await configurationRepository.findOne({
  where: { code: SystemConfigurations.VNPAY_QR_MMS },
});

// Validate configuration code
if (!SystemConfigurations.isValid(configCode)) {
  throw new Error(`Unknown system configuration: ${configCode}`);
}

4. Nghiệp vụ

MerchantTypes

Phân loại loại hình kinh doanh quyết định bố cục giao diện POS và tập tính năng.

TênGiá trịMô tả
DEFAULT'000_DEFAULT'Merchant tiêu chuẩn / đa mục đích
TICKET'100_POS_UI_TICKET'POS bán vé (sự kiện, vận chuyển)
FNB'200_POS_UI_FNB'POS Thực phẩm & Đồ uống
THEATER'300_POS_UI_THEATER'POS Rạp chiếu phim/rạp hát với phân bổ chỗ ngồi

INFO

MerchantTypes không bao gồm SCHEME_SET hoặc phương thức isValid(). Việc xác thực được thực hiện ở tầng dịch vụ.

Cách sử dụng

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

// Create a merchant
await merchantRepository.create({
  data: {
    name: 'Cinema Central',
    type: MerchantTypes.THEATER,
    organizerId,
  },
});

// Conditional UI rendering (frontend)
switch (merchant.type) {
  case MerchantTypes.TICKET:
    return <TicketPOSUI />;
  case MerchantTypes.FNB:
    return <FnBPOSUI />;
  case MerchantTypes.THEATER:
    return <TheaterPOSUI />;
  default:
    return <DefaultPOSUI />;
}

FixedUserRoles

Định danh vai trò được định nghĩa trước với phân cấp ưu tiên số. Mã ưu tiên cao hơn cấp quyền truy cập rộng hơn.

Định danh Vai trò

TênGiá trịMô tả
SUPER_ADMIN'999-super-admin'Toàn quyền kiểm soát hệ thống
ADMIN'998-admin'Quyền quản trị
OPERATOR'997-operator'Quản lý vận hành
ORGANIZER_OWNER'899-organizer-owner'Chủ sở hữu thực thể organizer
EMPLOYEE'898-employee'Quyền cấp nhân viên

Mã Ưu tiên

KhóaCấp độ
SUPER_ADMIN999Hệ thống
ADMIN998Hệ thống
OPERATOR997Hệ thống
ORGANIZER_OWNER899Tổ chức
EMPLOYEE898Tổ chức

Tập hợp Đặc biệt

TênNội dungMô tả
ALWAYS_ALLOW_ROLESSUPER_ADMIN, ADMINCác vai trò bỏ qua kiểm tra quyền

Phân cấp Vai trò

Cách sử dụng

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

// Check admin bypass
if (FixedUserRoles.ALWAYS_ALLOW_ROLES.has(currentRole)) {
  return true; // Skip permission check
}

// Compare priority
const userPriority = FixedUserRoles.PRIORITY_CODE.ORGANIZER_OWNER; // 899
const requiredPriority = FixedUserRoles.PRIORITY_CODE.ADMIN;       // 998

if (userPriority < requiredPriority) {
  throw new ForbiddenError('Insufficient privileges');
}

CompanyRegistrationTypes

Phân loại thực thể pháp lý cho đăng ký organizer. Hiện tại chỉ các loại dành riêng cho Việt Nam đang hoạt động; các loại quốc tế được định nghĩa trong mã nguồn nhưng đã bị comment để mở rộng trong tương lai.

Loại Đang Hoạt động (Việt Nam)

TênGiá trịTên Tiếng Việt
VN_HOUSEHOLD_BUSINESS'300_VN_HOUSEHOLD_BUSINESS'Ho kinh doanh
VN_PRIVATE_ENTERPRISE'301_VN_PRIVATE_ENTERPRISE'Doanh nghiep tu nhan
VN_LIMITED_LIABILITY_ONE'302_VN_LIMITED_LIABILITY_ONE'Cong ty TNHH mot thanh vien
VN_LIMITED_LIABILITY_TWO_PLUS'303_VN_LIMITED_LIABILITY_TWO_PLUS'Cong ty TNHH hai thanh vien tro len
VN_JOINT_STOCK'304_VN_JOINT_STOCK'Cong ty co phan

Loại Đã Comment (Sử dụng Trong Tương lai)

Tệp nguồn chứa các định nghĩa đã comment cho các loại quốc tế có thể được kích hoạt trong tương lai:

Danh mụcVí dụ
Cá nhân001, 002INDIVIDUAL, SOLE_PROPRIETORSHIP
Hợp danh100, 101GENERAL_PARTNERSHIP, LIMITED_PARTNERSHIP
Công ty200, 201, 202PRIVATE_LIMITED_COMPANY, PUBLIC_LIMITED_COMPANY, JOINT_STOCK_COMPANY
Phi lợi nhuận & Đặc biệt800, 801, 802, 999NON_PROFIT, COOPERATIVE, GOVERNMENT_ENTITY, OTHER

Phương thức Hỗ trợ

Phương thứcChữ kýMô tả
isValidisValid(type: string): booleanTrả về true nếu type là thành viên của TYPE_SET (chỉ các loại đang hoạt động)

Cách sử dụng

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

// Validate registration type
if (!CompanyRegistrationTypes.isValid(input.registrationType)) {
  throw new ValidationError('Invalid company registration type');
}

// Create organizer
await organizerRepository.create({
  data: {
    name: 'ABC Ltd.',
    registrationType: CompanyRegistrationTypes.VN_LIMITED_LIABILITY_ONE,
  },
});

DeviceTypes

Phân loại thiết bị POS và phần cứng được sử dụng cho đăng ký và quản lý thiết bị.

TênGiá trịDanh mụcMô tả
POS_TERMINAL'100_POS_TERMINAL'POS cố địnhPOS quầy truyền thống
POS_WORKSTATION'101_POS_WORKSTATION'POS cố địnhPOS máy tính để bàn với hệ điều hành đầy đủ
MOBILE_POS'200_MOBILE_POS'POS di độngỨng dụng POS trên điện thoại/máy tính bảng
TABLET'400_TABLET'Chuyên dụngThiết bị máy tính bảng chung
BARCODE_SCANNER'401_BARCODE_SCANNER'Chuyên dụngMáy quét mã vạch độc lập
OTHER'999_OTHER'KhácThiết bị chưa phân loại

Phương thức Hỗ trợ

Phương thứcChữ kýMô tả
isValidisValid(type: string): booleanTrả về true nếu type là thành viên của TYPE_SET

Cách sử dụng

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

// Validate device type
if (!DeviceTypes.isValid(input.deviceType)) {
  throw new ValidationError('Invalid device type');
}

// Create device
await deviceRepository.create({
  data: {
    name: 'Checkout Terminal 1',
    type: DeviceTypes.POS_TERMINAL,
    merchantId,
  },
});

5. Thanh toán

MQPayProviders

Định danh nhà cung cấp thanh toán được sử dụng bởi hệ thống con MQ-Pay. Bao gồm một nhà cung cấp nội bộ (SYSTEM) và sáu nhà cung cấp bên thứ ba.

TênGiá trịDanh mụcMô tả
SYSTEM'SYSTEM'Nội bộThanh toán thủ công (tiền mặt, chuyển khoản)
VNPAY_QR_MMS'VNPAY_QR_MMS'VNPAYThanh toán mã QR động
VNPAY_PHONE_POS'VNPAY_PHONE_POS'VNPAYThanh toán thẻ NFC qua PhonePOS
VNPAY_SMART_POS'VNPAY_SMART_POS'VNPAYQR + thẻ kết hợp qua SmartPOS
MOMO'MOMO'Bên thứ baVí điện tử MoMo
ZALOPAY'ZALOPAY'Bên thứ baVí điện tử ZaloPay
VIETQR'VIETQR'Bên thứ baChuyển khoản ngân hàng VietQR

Tập hợp

TênNội dungMô tả
SCHEME_SETTất cả 7 nhà cung cấpTập hợp đầy đủ nhà cung cấp
THIRD_PARTY_SCHEME_SETTất cả trừ SYSTEMChỉ nhà cung cấp thanh toán bên ngoài

Phương thức Hỗ trợ

Phương thứcChữ kýMô tả
isValidisValid(scheme: string): booleanTrả về true nếu scheme là bất kỳ nhà cung cấp nào đã biết
isThirdPartyProviderisThirdPartyProvider(opts: { provider: string }): booleanTrả về true nếu opts.provider là nhà cung cấp bên thứ ba (không phải SYSTEM)

Cách sử dụng

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

// Check if provider requires external API calls
if (MQPayProviders.isThirdPartyProvider({ provider: paymentProvider })) {
  // Load credentials and call external payment gateway
} else {
  // Handle as manual/system payment
}

// Validate provider
if (!MQPayProviders.isValid(input.provider)) {
  throw new ValidationError('Unknown payment provider');
}

MQPayCredentialActions

Các hành động yêu cầu tập thông tin xác thực cụ thể khi giao tiếp với nhà cung cấp thanh toán. Mỗi hành động ánh xạ đến một thao tác API riêng biệt.

TênGiá trịMô tả
CREATE_PAYMENT'CREATE_PAYMENT'Khởi tạo giao dịch thanh toán mới
VERIFY_IPN'VERIFY_IPN'Xác minh Thông báo Thanh toán Tức thì (IPN)
CHECK_TRANSACTION'CHECK_TRANSACTION'Truy vấn trạng thái giao dịch từ nhà cung cấp
CANCEL_PAYMENT'CANCEL_PAYMENT'Hủy thanh toán đang xử lý
REFUND'REFUND'Hoàn tiền thanh toán đã thanh toán

Phương thức Hỗ trợ

Phương thứcChữ kýMô tả
isValidisValid(scheme: string): booleanTrả về true nếu scheme là thành viên của SCHEME_SET

Cách sử dụng

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

// Load credentials for a specific action
const credentials = await paymentConfigService.getCredentials({
  provider: MQPayProviders.VNPAY_QR_MMS,
  action: MQPayCredentialActions.CREATE_PAYMENT,
});

MQPayCredentialTypes

Phân loại dữ liệu thông tin xác thực theo hướng giao tiếp.

TênGiá trịMô tả
REQUEST'request'Thông tin xác thực cho yêu cầu gửi đi đến nhà cung cấp
RESPONSE'response'Thông tin xác thực để xác thực phản hồi từ nhà cung cấp
IPN'ipn'Thông tin xác thực để xác minh Thông báo Thanh toán Tức thì

Phương thức Hỗ trợ

Phương thứcChữ kýMô tả
isValidisValid(scheme: string): booleanTrả về true nếu scheme là thành viên của SCHEME_SET

Cách sử dụng

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

// Retrieve request-specific credentials
const requestCreds = credentials.filter(
  c => c.type === MQPayCredentialTypes.REQUEST
);

// Retrieve IPN verification credentials
const ipnCreds = credentials.filter(
  c => c.type === MQPayCredentialTypes.IPN
);

6. Trạng thái

WebhookConfigStatuses

Trạng thái vòng đời cho các mục cấu hình webhook. Các giá trị được tái xuất từ lớp Statuses của framework IGNIS.

TênHằng số NguồnGiá trịMô tả
ACTIVATEDStatuses.ACTIVATED'201_ACTIVATED'Webhook đang hoạt động và sẽ nhận sự kiện
DEACTIVATEDStatuses.DEACTIVATED'401_DEACTIVATED'Webhook tạm dừng, không gửi sự kiện
ARCHIVEDStatuses.ARCHIVED'405_ARCHIVED'Webhook được lưu trữ để lưu hồ sơ

Statuses của IGNIS

WebhookConfigStatuses ủy quyền cho Statuses từ @venizia/ignis. Để tham khảo đầy đủ mã trạng thái, xem tài liệu IGNIS Statuses.

Xuất Kiểu

typescript
export type TWebhookConfigStatus = TConstValue<typeof WebhookConfigStatuses>;
// Resolves to: '201_ACTIVATED' | '401_DEACTIVATED' | '405_ARCHIVED'

Phương thức Hỗ trợ

Phương thứcChữ kýMô tả
isValidisValid(status: string): booleanTrả về true nếu status là thành viên của SCHEME_SET

Cách sử dụng

typescript
import { WebhookConfigStatuses } from '@nx/core';
import type { TWebhookConfigStatus } from '@nx/core';

// Create a webhook config
await webhookConfigRepository.create({
  data: {
    name: 'Order Notifications',
    url: 'https://example.com/webhook',
    eventTypes: ['order.created', 'order.completed'],
    status: WebhookConfigStatuses.ACTIVATED,
  },
});

// Deactivate a webhook
await webhookConfigRepository.updateById({
  id: webhookId,
  data: { status: WebhookConfigStatuses.DEACTIVATED },
});

// Type-safe status parameter
function setWebhookStatus(id: string, status: TWebhookConfigStatus) {
  return webhookConfigRepository.updateById({ id, data: { status } });
}

Thực hành Tốt nhất

1. Luôn Sử dụng Hằng số -- Không Dùng Chuỗi Cố định

typescript
// Good -- type-safe and refactorable
if (device.type === DeviceTypes.POS_TERMINAL) { /* ... */ }

// Bad -- magic string, prone to typos
if (device.type === '100_POS_TERMINAL') { /* ... */ }

2. Xác thực Đầu vào với isValid()

typescript
// Good -- explicit validation using the Set
if (!DeviceTypes.isValid(input.type)) {
  throw new ValidationError('Invalid device type');
}

// Bad -- manual inline check
if (!['100_POS_TERMINAL', '101_POS_WORKSTATION'].includes(input.type)) { /* ... */ }

3. Ưu tiên SCHEME_SET / TYPE_SET cho Kiểm tra Hàng loạt

typescript
// Good -- O(1) lookup
if (MQPayProviders.THIRD_PARTY_SCHEME_SET.has(provider)) { /* ... */ }

// Bad -- O(n) array search
if (['VNPAY_QR_MMS', 'VNPAY_PHONE_POS', /* ... */].includes(provider)) { /* ... */ }

4. Mở rộng Hằng số trong Gói Downstream

Khi gói downstream cần thêm giá trị, hãy mở rộng lớp cơ sở thay vì sao chép:

typescript
export class ExtendedDeviceTypes extends DeviceTypes {
  static readonly SELF_CHECKOUT_KIOSK = '500_SELF_CHECKOUT_KIOSK';

  static override TYPE_SET = new Set([
    ...DeviceTypes.TYPE_SET,
    this.SELF_CHECKOUT_KIOSK,
  ]);
}

Tài liệu Liên quan

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