refactor: Convert MoneyAmount to INTEGER cents storage and modularize currency types

- Refactor MoneyAmount to store as INTEGER cents instead of TEXT decimals
- Move CurrencyType to separate currency_type.rs module
- Rename money.rs to money_amount.rs for clarity
- Update database schema to use INTEGER for all monetary columns
- Remove complex CAST AS REAL workarounds from database queries
- Add comprehensive test coverage for cent-based arithmetic and storage
- Enable STRICT mode and foreign key constraints in SQLite
- Add rstest dependency for parameterized testing

Benefits:
- Faster INTEGER-based comparisons vs TEXT casting
- Exact financial precision without floating-point errors
- Simpler, cleaner SQL queries
- Better performance for auction bid operations
This commit is contained in:
Dylan Knutson
2025-08-27 23:19:13 +00:00
parent 348fa416e8
commit 32dca5f4de
13 changed files with 1966 additions and 27 deletions

View File

@@ -1,5 +1,8 @@
-- Initial database schema for Pawctioneer Bot
-- Supports all listing types: standard, multi_slot, fixed_price, blind
-- Supports all listing types: basic_auction, multi_slot_auction, fixed_price_listing, blind_auction
-- Enable foreign key constraints
PRAGMA foreign_keys = ON;
-- Core user tracking
CREATE TABLE users (
@@ -10,20 +13,20 @@ CREATE TABLE users (
is_banned BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
) STRICT;
-- Main listing table (handles all listing types)
CREATE TABLE listings (
id INTEGER PRIMARY KEY,
seller_id INTEGER NOT NULL,
listing_type TEXT NOT NULL, -- 'standard', 'multi_slot', 'fixed_price', 'blind'
listing_type TEXT NOT NULL, -- 'basic_auction', 'multi_slot_auction', 'fixed_price_listing', 'blind_auction'
title TEXT NOT NULL,
description TEXT,
-- Pricing
starting_bid DECIMAL(10,2),
buy_now_price DECIMAL(10,2),
min_increment DECIMAL(10,2) DEFAULT 1.00,
-- Pricing (stored as INTEGER cents for USD)
starting_bid INTEGER,
buy_now_price INTEGER,
min_increment INTEGER DEFAULT 100, -- 1.00 USD = 100 cents
-- Multi-slot/fixed price
slots_available INTEGER DEFAULT 1,
@@ -36,14 +39,14 @@ CREATE TABLE listings (
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (seller_id) REFERENCES users(id)
);
) STRICT;
-- Proxy bid strategies (NOT actual bids, but bidding strategies)
CREATE TABLE proxy_bids (
id INTEGER PRIMARY KEY,
listing_id INTEGER NOT NULL,
buyer_id INTEGER NOT NULL,
max_amount DECIMAL(10,2) NOT NULL,
max_amount INTEGER NOT NULL, -- stored as cents
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
@@ -52,14 +55,14 @@ CREATE TABLE proxy_bids (
FOREIGN KEY (listing_id) REFERENCES listings(id),
FOREIGN KEY (buyer_id) REFERENCES users(id),
UNIQUE(listing_id, buyer_id) -- One active proxy per user per listing
);
) STRICT;
-- Actual bids that happened (events)
CREATE TABLE bids (
id INTEGER PRIMARY KEY,
listing_id INTEGER NOT NULL,
buyer_id INTEGER NOT NULL,
bid_amount DECIMAL(10,2) NOT NULL,
bid_amount INTEGER NOT NULL, -- stored as cents
-- For blind listings
description TEXT,
@@ -76,7 +79,7 @@ CREATE TABLE bids (
FOREIGN KEY (listing_id) REFERENCES listings(id),
FOREIGN KEY (buyer_id) REFERENCES users(id),
FOREIGN KEY (proxy_bid_id) REFERENCES proxy_bids(id)
);
) STRICT;
-- Media attachments
CREATE TABLE listing_medias (
@@ -88,7 +91,7 @@ CREATE TABLE listing_medias (
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (listing_id) REFERENCES listings(id)
);
) STRICT;
-- User preferences
CREATE TABLE user_settings (
@@ -99,7 +102,7 @@ CREATE TABLE user_settings (
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id)
);
) STRICT;
-- Create indexes for better performance
CREATE INDEX idx_listings_seller_id ON listings(seller_id);