3 changed files with 238 additions and 9 deletions
@ -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 |
||||
|
||||
@ -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; |
||||
Loading…
Reference in new issue