Database Design

Wallet Module
WALLET
Version1.0
SystemHR Management System
ModuleWALLET - Electronic Wallet
Databasewallet_db
Date2026-08-05
AuthorNam Nguyen
StatusDraft

Table of Contents

1. Introduction

1.1 Purpose

This document defines the database schema for the Wallet module. It includes table definitions, relationships, indexes, and migration scripts.

1.2 Database Overview

AspectValue
Databasewallet_db
EnginePostgreSQL 15+
ORMDrizzle ORM
Tables5 tables

2. Entity Relationship Diagram

ERD Diagram
Figure 1: Wallet Database ERD

3. Table Definitions

3.1 wallet_wallets

ColumnTypeConstraintsDescription
idBIGSERIALPRIMARY KEYUnique wallet identifier
user_idBIGINTUNIQUE, NOT NULLReference to auth_users.id
currencyVARCHAR(3)NOT NULL, DEFAULT 'VND'Currency code (ISO 4217)
balanceDECIMAL(15,2)NOT NULL, DEFAULT 0Current wallet balance
frozen_amountDECIMAL(15,2)NOT NULL, DEFAULT 0Amount frozen for pending withdrawals
statusVARCHAR(20)NOT NULL, DEFAULT 'active'active, frozen, closed
pin_hashVARCHAR(255)Hashed 6-digit PIN
daily_limitDECIMAL(15,2)NOT NULL, DEFAULT 50000000Daily transaction limit (VND)
monthly_limitDECIMAL(15,2)NOT NULL, DEFAULT 500000000Monthly transaction limit (VND)
versionINTEGERNOT NULL, DEFAULT 1Optimistic locking version
created_atTIMESTAMPNOT NULL, DEFAULT NOW()Record creation timestamp
updated_atTIMESTAMPNOT NULL, DEFAULT NOW()Last update timestamp

3.2 wallet_transactions

ColumnTypeConstraintsDescription
idBIGSERIALPRIMARY KEYUnique transaction identifier
wallet_idBIGINTNOT NULL, FK -> wallet_wallets.idAssociated wallet
typeVARCHAR(20)NOT NULLdeposit, withdrawal, payment, refund, transfer_in, transfer_out
amountDECIMAL(15,2)NOT NULLTransaction amount
currencyVARCHAR(3)NOT NULLCurrency code
balance_beforeDECIMAL(15,2)NOT NULLBalance before transaction
balance_afterDECIMAL(15,2)NOT NULLBalance after transaction
statusVARCHAR(20)NOT NULLpending, processing, completed, failed, cancelled
reference_typeVARCHAR(50)Related entity type
reference_idBIGINTRelated entity ID
descriptionTEXTTransaction description
metadataJSONBAdditional context data
failure_reasonTEXTReason for failed transaction
created_atTIMESTAMPNOT NULL, DEFAULT NOW()Transaction timestamp
updated_atTIMESTAMPNOT NULL, DEFAULT NOW()Last update timestamp

3.3 wallet_payment_methods

ColumnTypeConstraintsDescription
idBIGSERIALPRIMARY KEYUnique payment method identifier
wallet_idBIGINTNOT NULL, FK -> wallet_wallets.idAssociated wallet
typeVARCHAR(20)NOT NULLbank_account, credit_card, debit_card, e_wallet
providerVARCHAR(50)NOT NULLBank or card provider name
account_numberVARCHAR(100)NOT NULLEncrypted account/card number
account_nameVARCHAR(100)NOT NULLAccount holder name
is_defaultBOOLEANNOT NULL, DEFAULT falseDefault payment method
is_verifiedBOOLEANNOT NULL, DEFAULT falseVerification status
metadataJSONBAdditional provider data
created_atTIMESTAMPNOT NULL, DEFAULT NOW()Record creation timestamp
updated_atTIMESTAMPNOT NULL, DEFAULT NOW()Last update timestamp

3.4 wallet_payment_orders

ColumnTypeConstraintsDescription
idBIGSERIALPRIMARY KEYUnique order identifier
wallet_idBIGINTNOT NULL, FK -> wallet_wallets.idAssociated wallet
order_typeVARCHAR(30)NOT NULLjob_posting, featured_job, premium_subscription, recruitment_service
amountDECIMAL(15,2)NOT NULLOrder amount
currencyVARCHAR(3)NOT NULLCurrency code
statusVARCHAR(20)NOT NULLpending, paid, refunded, cancelled
related_moduleVARCHAR(20)Related module code (RECR)
related_idBIGINTRelated entity ID in external module
descriptionTEXTOrder description
paid_atTIMESTAMPPayment completion timestamp
created_atTIMESTAMPNOT NULL, DEFAULT NOW()Record creation timestamp
updated_atTIMESTAMPNOT NULL, DEFAULT NOW()Last update timestamp

3.5 wallet_payout_requests

ColumnTypeConstraintsDescription
idBIGSERIALPRIMARY KEYUnique request identifier
wallet_idBIGINTNOT NULL, FK -> wallet_wallets.idAssociated wallet
payment_method_idBIGINTNOT NULL, FK -> wallet_payment_methods.idTarget payment method
amountDECIMAL(15,2)NOT NULLWithdrawal amount
statusVARCHAR(20)NOT NULLpending, approved, processing, completed, rejected
admin_notesTEXTAdmin comments
processed_byBIGINTAdmin user ID who processed
processed_atTIMESTAMPProcessing completion timestamp
created_atTIMESTAMPNOT NULL, DEFAULT NOW()Request creation timestamp
updated_atTIMESTAMPNOT NULL, DEFAULT NOW()Last update timestamp

4. Indexes

TableIndexColumnsType
wallet_walletswallet_wallets_user_id_keyuser_idUNIQUE
wallet_walletswallet_wallets_status_idxstatusBTREE
wallet_transactionswallet_transactions_wallet_id_idxwallet_idBTREE
wallet_transactionswallet_transactions_type_idxtypeBTREE
wallet_transactionswallet_transactions_status_idxstatusBTREE
wallet_transactionswallet_transactions_created_at_idxcreated_atBTREE
wallet_payment_methodswallet_payment_methods_wallet_id_idxwallet_idBTREE
wallet_payment_orderswallet_payment_orders_wallet_id_idxwallet_idBTREE
wallet_payment_orderswallet_payment_orders_status_idxstatusBTREE
wallet_payout_requestswallet_payout_requests_wallet_id_idxwallet_idBTREE
wallet_payout_requestswallet_payout_requests_status_idxstatusBTREE

5. Migration Scripts

5.1 Initial Migration

CREATE TABLE wallet_wallets (
  id BIGSERIAL PRIMARY KEY,
  user_id BIGINT UNIQUE NOT NULL,
  currency VARCHAR(3) NOT NULL DEFAULT 'VND',
  balance DECIMAL(15,2) NOT NULL DEFAULT 0,
  frozen_amount DECIMAL(15,2) NOT NULL DEFAULT 0,
  status VARCHAR(20) NOT NULL DEFAULT 'active',
  pin_hash VARCHAR(255),
  daily_limit DECIMAL(15,2) NOT NULL DEFAULT 50000000,
  monthly_limit DECIMAL(15,2) NOT NULL DEFAULT 500000000,
  version INTEGER NOT NULL DEFAULT 1,
  created_at TIMESTAMP NOT NULL DEFAULT NOW(),
  updated_at TIMESTAMP NOT NULL DEFAULT NOW()
);

CREATE TABLE wallet_transactions (
  id BIGSERIAL PRIMARY KEY,
  wallet_id BIGINT NOT NULL REFERENCES wallet_wallets(id),
  type VARCHAR(20) NOT NULL,
  amount DECIMAL(15,2) NOT NULL,
  currency VARCHAR(3) NOT NULL,
  balance_before DECIMAL(15,2) NOT NULL,
  balance_after DECIMAL(15,2) NOT NULL,
  status VARCHAR(20) NOT NULL,
  reference_type VARCHAR(50),
  reference_id BIGINT,
  description TEXT,
  metadata JSONB,
  failure_reason TEXT,
  created_at TIMESTAMP NOT NULL DEFAULT NOW(),
  updated_at TIMESTAMP NOT NULL DEFAULT NOW()
);

CREATE TABLE wallet_payment_methods (
  id BIGSERIAL PRIMARY KEY,
  wallet_id BIGINT NOT NULL REFERENCES wallet_wallets(id),
  type VARCHAR(20) NOT NULL,
  provider VARCHAR(50) NOT NULL,
  account_number VARCHAR(100) NOT NULL,
  account_name VARCHAR(100) NOT NULL,
  is_default BOOLEAN NOT NULL DEFAULT false,
  is_verified BOOLEAN NOT NULL DEFAULT false,
  metadata JSONB,
  created_at TIMESTAMP NOT NULL DEFAULT NOW(),
  updated_at TIMESTAMP NOT NULL DEFAULT NOW()
);

CREATE TABLE wallet_payment_orders (
  id BIGSERIAL PRIMARY KEY,
  wallet_id BIGINT NOT NULL REFERENCES wallet_wallets(id),
  order_type VARCHAR(30) NOT NULL,
  amount DECIMAL(15,2) NOT NULL,
  currency VARCHAR(3) NOT NULL,
  status VARCHAR(20) NOT NULL,
  related_module VARCHAR(20),
  related_id BIGINT,
  description TEXT,
  paid_at TIMESTAMP,
  created_at TIMESTAMP NOT NULL DEFAULT NOW(),
  updated_at TIMESTAMP NOT NULL DEFAULT NOW()
);

CREATE TABLE wallet_payout_requests (
  id BIGSERIAL PRIMARY KEY,
  wallet_id BIGINT NOT NULL REFERENCES wallet_wallets(id),
  payment_method_id BIGINT NOT NULL REFERENCES wallet_payment_methods(id),
  amount DECIMAL(15,2) NOT NULL,
  status VARCHAR(20) NOT NULL,
  admin_notes TEXT,
  processed_by BIGINT,
  processed_at TIMESTAMP,
  created_at TIMESTAMP NOT NULL DEFAULT NOW(),
  updated_at TIMESTAMP NOT NULL DEFAULT NOW()
);

6. Data Requirements Traceability

Req ID Table Description Related FR
DR-001wallet_walletsUser wallet accounts with balance and limitsFR-001, FR-002
DR-002wallet_transactionsComplete transaction history with audit trailFR-004, FR-009
DR-003wallet_payment_methodsLinked bank accounts and payment cardsFR-005
DR-004wallet_payment_ordersPayment orders for servicesFR-011, FR-012, FR-013
DR-005wallet_payout_requestsWithdrawal requests for admin approvalFR-007, FR-015