CREATE TABLE accounts (
account_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
account_number VARCHAR(30) UNIQUE NOT NULL,
account_name VARCHAR(100) NOT NULL,
account_type VARCHAR(20) CHECK (account_type IN ('资产','负债','权益','收入','费用')),
balance NUMERIC(18,4) DEFAULT 0.0000,
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE TABLE transactions (
transaction_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
account_id UUID REFERENCES accounts(account_id),
transaction_date DATE NOT NULL,
amount NUMERIC(18,4) NOT NULL CHECK (amount != 0),
direction VARCHAR(10) CHECK (direction IN ('DEBIT','CREDIT')),
reference VARCHAR(50),
status VARCHAR(20) DEFAULT 'PENDING'::varchar,
CONSTRAINT valid_amount CHECK (amount > 0)
);
CREATE TABLE audit_logs (
log_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
table_name VARCHAR(50) NOT NULL,
record_id UUID NOT NULL,
changed_fields JSONB,
old_values JSONB,
new_values JSONB,
changed_by VARCHAR(50),
changed_at TIMESTAMPTZ DEFAULT NOW()
);
class AccountingSystem:
def __init__(self, db_conn):
self.conn = db_conn
def create_account(self, account_data):
"""创建新账户"""
with self.conn.cursor() as cur:
cur.execute("""
INSERT INTO accounts (account_number, account_name, account_type)
VALUES (%s, %s, %s)
RETURNING account_id
""", (account_data['number'], account_data['name'], account_data['type']))
return cur.fetchone()[0]
def record_transaction(self, tx_data):
"""记录交易流水"""
with self.conn.cursor() as cur:
cur.execute("BEGIN;")
balance_sql = "UPDATE accounts SET balance = balance + %s WHERE account_id = %s"
tx_sql = """
INSERT INTO transactions (account_id, transaction_date, amount, direction)
VALUES (%s, %s, %s, %s)
"""
try:
cur.execute(balance_sql, (tx_data['amount'], tx_data['account']))
cur.execute(tx_sql, (
tx_data['account'],
tx_data['date'],
tx_data['amount'],
'DEBIT' if tx_data['amount'] > 0 else 'CREDIT'
))
self.conn.commit()
return True
except Exception as e:
self.conn.rollback()
raise e
def generate_report(self, start_date, end_date):
"""生成财务报表"""
with self.conn.cursor() as cur:
cur.execute("""
SELECT a.account_type, SUM(t.amount)
FROM transactions t
JOIN accounts a ON t.account_id = a.account_id
WHERE t.transaction_date BETWEEN %s AND %s
GROUP BY a.account_type
""", (start_date, end_date))
return cur.fetchall();
DELIMITER $$
CREATE PROCEDURE sp_transfer_funds(
IN src_account BIGINT,
IN dest_account BIGINT,
IN transfer_amount DECIMAL(15,2)
)
BEGIN
START TRANSACTION;
UPDATE accounts
SET balance = balance - transfer_amount
WHERE account_id = src_account AND balance >= transfer_amount;
UPDATE accounts
SET balance = balance + transfer_amount
WHERE account_id = dest_account;
IF ROW_COUNT() = 2 THEN
COMMIT;
ELSE
ROLLBACK;
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Transfer failed - insufficient funds';
END IF;
END$$
DELIMITER ;