diff --git a/VERSION b/VERSION index 8acdd82..4e379d2 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.0.1 +0.0.2 diff --git a/docs/design.md b/docs/design.md index 540f1a7..62b9cb8 100644 --- a/docs/design.md +++ b/docs/design.md @@ -1,12 +1,67 @@ -OTB Billing Design +# OTB Billing Design Notes -Purpose: -Track invoices and payments for OutsideTheBox services. +## Current Version +0.0.2 -Payment types: +## Purpose +OTB Billing is the billing and payment tracking component for OutsideTheBox. + +It is intended to: +- track clients +- track services +- issue invoices +- record payments +- support bookkeeping visibility +- integrate with outsidethedb while keeping billing records logically separate + +## Supported payment directions - Square -- Interac e-transfer -- crypto +- Interac e-Transfer +- Crypto + +## Multi-currency design +The schema supports multi-currency from day one. + +Current intended currencies: +- CAD +- ETHO +- EGAZ +- ALT + +### Rule +Store both: +- actual payment currency and amount +- CAD-equivalent snapshot when relevant + +Example: +- payment_currency = EGAZ +- payment_amount = 12.50000000 +- cad_value_at_payment = 47.82 + +This keeps both crypto-native records and bookkeeping-friendly reporting. + +## Core tables +- clients +- services +- invoices +- invoice_items +- payments +- audit_log + +## Relationship flow +client -> service -> invoice -> invoice_items -> payment + +## Notes +- services are linked to clients +- invoices are linked to clients and optionally to services +- invoice items can optionally reference services +- payments reference both invoice and client +- audit_log provides change history for future accountability and troubleshooting -Integration: -Will communicate with outsidethedb for service status. +## Planned future additions +- recurring invoice generation +- reminders / overdue handling +- dashboard counts +- service suspension workflow +- integration hooks to outsidethedb +- client verification records diff --git a/sql/schema_v0.0.2.sql b/sql/schema_v0.0.2.sql new file mode 100644 index 0000000..fcf6707 --- /dev/null +++ b/sql/schema_v0.0.2.sql @@ -0,0 +1,174 @@ +CREATE DATABASE IF NOT EXISTS otb_billing + CHARACTER SET utf8mb4 + COLLATE utf8mb4_unicode_ci; + +USE otb_billing; + +SET FOREIGN_KEY_CHECKS=0; + +DROP TABLE IF EXISTS audit_log; +DROP TABLE IF EXISTS payments; +DROP TABLE IF EXISTS invoice_items; +DROP TABLE IF EXISTS invoices; +DROP TABLE IF EXISTS services; +DROP TABLE IF EXISTS clients; + +SET FOREIGN_KEY_CHECKS=1; + +CREATE TABLE clients ( + id INT UNSIGNED NOT NULL AUTO_INCREMENT, + client_code VARCHAR(50) NOT NULL, + company_name VARCHAR(255) NOT NULL, + contact_name VARCHAR(255) DEFAULT NULL, + email VARCHAR(255) DEFAULT NULL, + phone VARCHAR(50) DEFAULT NULL, + status ENUM('lead','active','inactive','suspended') NOT NULL DEFAULT 'active', + notes TEXT DEFAULT NULL, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (id), + UNIQUE KEY uq_clients_client_code (client_code), + KEY idx_clients_company_name (company_name), + KEY idx_clients_status (status) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE services ( + id INT UNSIGNED NOT NULL AUTO_INCREMENT, + client_id INT UNSIGNED NOT NULL, + service_code VARCHAR(50) NOT NULL, + service_name VARCHAR(255) NOT NULL, + service_type ENUM('hosting','rpc','explorer','node','ipfs','consulting','other') NOT NULL DEFAULT 'other', + billing_cycle ENUM('one_time','monthly','quarterly','yearly','manual') NOT NULL DEFAULT 'monthly', + status ENUM('pending','active','suspended','cancelled') NOT NULL DEFAULT 'pending', + currency_code VARCHAR(16) NOT NULL DEFAULT 'CAD', + recurring_amount DECIMAL(18,8) NOT NULL DEFAULT 0.00000000, + start_date DATE DEFAULT NULL, + end_date DATE DEFAULT NULL, + description TEXT DEFAULT NULL, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (id), + UNIQUE KEY uq_services_service_code (service_code), + KEY idx_services_client_id (client_id), + KEY idx_services_status (status), + CONSTRAINT fk_services_client + FOREIGN KEY (client_id) REFERENCES clients(id) + ON DELETE RESTRICT + ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE invoices ( + id INT UNSIGNED NOT NULL AUTO_INCREMENT, + client_id INT UNSIGNED NOT NULL, + service_id INT UNSIGNED DEFAULT NULL, + invoice_number VARCHAR(50) NOT NULL, + currency_code VARCHAR(16) NOT NULL DEFAULT 'CAD', + subtotal_amount DECIMAL(18,8) NOT NULL DEFAULT 0.00000000, + tax_amount DECIMAL(18,8) NOT NULL DEFAULT 0.00000000, + total_amount DECIMAL(18,8) NOT NULL DEFAULT 0.00000000, + amount_paid DECIMAL(18,8) NOT NULL DEFAULT 0.00000000, + status ENUM('draft','pending','paid','partial','overdue','cancelled') NOT NULL DEFAULT 'draft', + issued_at DATETIME DEFAULT NULL, + due_at DATETIME DEFAULT NULL, + paid_at DATETIME DEFAULT NULL, + notes TEXT DEFAULT NULL, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (id), + UNIQUE KEY uq_invoices_invoice_number (invoice_number), + KEY idx_invoices_client_id (client_id), + KEY idx_invoices_service_id (service_id), + KEY idx_invoices_status (status), + KEY idx_invoices_due_at (due_at), + CONSTRAINT fk_invoices_client + FOREIGN KEY (client_id) REFERENCES clients(id) + ON DELETE RESTRICT + ON UPDATE CASCADE, + CONSTRAINT fk_invoices_service + FOREIGN KEY (service_id) REFERENCES services(id) + ON DELETE SET NULL + ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE invoice_items ( + id INT UNSIGNED NOT NULL AUTO_INCREMENT, + invoice_id INT UNSIGNED NOT NULL, + line_number INT UNSIGNED NOT NULL DEFAULT 1, + item_type ENUM('service','setup','credit','discount','manual','other') NOT NULL DEFAULT 'service', + description VARCHAR(255) NOT NULL, + quantity DECIMAL(18,4) NOT NULL DEFAULT 1.0000, + unit_amount DECIMAL(18,8) NOT NULL DEFAULT 0.00000000, + line_total DECIMAL(18,8) NOT NULL DEFAULT 0.00000000, + currency_code VARCHAR(16) NOT NULL DEFAULT 'CAD', + service_id INT UNSIGNED DEFAULT NULL, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (id), + KEY idx_invoice_items_invoice_id (invoice_id), + KEY idx_invoice_items_service_id (service_id), + CONSTRAINT fk_invoice_items_invoice + FOREIGN KEY (invoice_id) REFERENCES invoices(id) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT fk_invoice_items_service + FOREIGN KEY (service_id) REFERENCES services(id) + ON DELETE SET NULL + ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE payments ( + id INT UNSIGNED NOT NULL AUTO_INCREMENT, + invoice_id INT UNSIGNED NOT NULL, + client_id INT UNSIGNED NOT NULL, + payment_method ENUM( + 'square', + 'etransfer', + 'crypto_etho', + 'crypto_egaz', + 'crypto_alt', + 'cash', + 'other' + ) NOT NULL, + payment_currency VARCHAR(16) NOT NULL, + payment_amount DECIMAL(18,8) NOT NULL DEFAULT 0.00000000, + cad_value_at_payment DECIMAL(18,8) DEFAULT NULL, + exchange_rate_note VARCHAR(255) DEFAULT NULL, + reference VARCHAR(255) DEFAULT NULL, + sender_name VARCHAR(255) DEFAULT NULL, + txid VARCHAR(255) DEFAULT NULL, + wallet_address VARCHAR(255) DEFAULT NULL, + confirmations INT UNSIGNED DEFAULT NULL, + confirmation_required INT UNSIGNED DEFAULT NULL, + payment_status ENUM('pending','confirmed','failed','reversed') NOT NULL DEFAULT 'confirmed', + received_at DATETIME DEFAULT NULL, + notes TEXT DEFAULT NULL, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (id), + KEY idx_payments_invoice_id (invoice_id), + KEY idx_payments_client_id (client_id), + KEY idx_payments_method (payment_method), + KEY idx_payments_status (payment_status), + KEY idx_payments_txid (txid), + CONSTRAINT fk_payments_invoice + FOREIGN KEY (invoice_id) REFERENCES invoices(id) + ON DELETE RESTRICT + ON UPDATE CASCADE, + CONSTRAINT fk_payments_client + FOREIGN KEY (client_id) REFERENCES clients(id) + ON DELETE RESTRICT + ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE audit_log ( + id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, + entity_type ENUM('client','service','invoice','payment','system') NOT NULL, + entity_id INT UNSIGNED DEFAULT NULL, + action VARCHAR(100) NOT NULL, + actor VARCHAR(100) NOT NULL DEFAULT 'system', + details TEXT DEFAULT NULL, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (id), + KEY idx_audit_entity (entity_type, entity_id), + KEY idx_audit_action (action), + KEY idx_audit_created_at (created_at) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;