move repos into monorepo

This commit is contained in:
Timur Gordon
2025-11-13 20:44:00 +01:00
commit 4b23e5eb7f
204 changed files with 33737 additions and 0 deletions

View File

@@ -0,0 +1,151 @@
/// Expense Object for Accounting
use crate::store::BaseData;
use serde::{Deserialize, Serialize};
/// Expense category
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum ExpenseCategory {
Registration,
Subscription,
Service,
Product,
Other,
}
impl Default for ExpenseCategory {
fn default() -> Self {
ExpenseCategory::Other
}
}
/// Expense status
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum ExpenseStatus {
Pending,
Approved,
Paid,
Rejected,
}
impl Default for ExpenseStatus {
fn default() -> Self {
ExpenseStatus::Pending
}
}
/// Expense record
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, crate::DeriveObject)]
pub struct Expense {
/// Base data for object storage
pub base_data: BaseData,
/// User/entity ID who incurred the expense
pub user_id: u32,
/// Amount
pub amount: f64,
/// Currency
pub currency: String,
/// Description
pub description: String,
/// Category
pub category: ExpenseCategory,
/// Status
pub status: ExpenseStatus,
/// Date incurred (unix timestamp)
pub expense_date: u64,
/// Related invoice ID (if any)
pub invoice_id: Option<u32>,
}
impl Expense {
/// Create a new expense
pub fn new(id: u32) -> Self {
let base_data = BaseData::with_id(id, String::new());
let now = time::OffsetDateTime::now_utc().unix_timestamp() as u64;
Self {
base_data,
user_id: 0,
amount: 0.0,
currency: String::from("USD"),
description: String::new(),
category: ExpenseCategory::default(),
status: ExpenseStatus::default(),
expense_date: now,
invoice_id: None,
}
}
/// Set user ID (fluent)
pub fn user_id(mut self, id: u32) -> Self {
self.user_id = id;
self
}
/// Set amount (fluent)
pub fn amount(mut self, amount: f64) -> Self {
self.amount = amount;
self
}
/// Set currency (fluent)
pub fn currency(mut self, currency: impl ToString) -> Self {
self.currency = currency.to_string();
self
}
/// Set description (fluent)
pub fn description(mut self, description: impl ToString) -> Self {
self.description = description.to_string();
self
}
/// Set category (fluent)
pub fn category(mut self, category: ExpenseCategory) -> Self {
self.category = category;
self
}
/// Set category from string (fluent)
pub fn category_str(mut self, category: &str) -> Self {
self.category = match category.to_lowercase().as_str() {
"registration" => ExpenseCategory::Registration,
"subscription" => ExpenseCategory::Subscription,
"service" => ExpenseCategory::Service,
"product" => ExpenseCategory::Product,
_ => ExpenseCategory::Other,
};
self
}
/// Set invoice ID (fluent)
pub fn invoice_id(mut self, id: u32) -> Self {
self.invoice_id = Some(id);
self
}
/// Approve expense
pub fn approve(mut self) -> Self {
self.status = ExpenseStatus::Approved;
self
}
/// Mark as paid
pub fn mark_paid(mut self) -> Self {
self.status = ExpenseStatus::Paid;
self
}
/// Reject expense
pub fn reject(mut self) -> Self {
self.status = ExpenseStatus::Rejected;
self
}
}

View File

@@ -0,0 +1,130 @@
/// Invoice Object for Accounting
use crate::store::BaseData;
use serde::{Deserialize, Serialize};
/// Invoice status
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum InvoiceStatus {
Draft,
Sent,
Paid,
Overdue,
Cancelled,
}
impl Default for InvoiceStatus {
fn default() -> Self {
InvoiceStatus::Draft
}
}
/// Invoice for billing
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, crate::DeriveObject)]
pub struct Invoice {
/// Base data for object storage
pub base_data: BaseData,
/// Invoice number
pub invoice_number: String,
/// Customer/payer ID
pub customer_id: u32,
/// Amount
pub amount: f64,
/// Currency
pub currency: String,
/// Description
pub description: String,
/// Status
pub status: InvoiceStatus,
/// Due date (unix timestamp)
pub due_date: Option<u64>,
/// Payment date (unix timestamp)
pub paid_date: Option<u64>,
}
impl Invoice {
/// Create a new invoice
pub fn new(id: u32) -> Self {
let base_data = BaseData::with_id(id, String::new());
Self {
base_data,
invoice_number: String::new(),
customer_id: 0,
amount: 0.0,
currency: String::from("USD"),
description: String::new(),
status: InvoiceStatus::default(),
due_date: None,
paid_date: None,
}
}
/// Set invoice number (fluent)
pub fn invoice_number(mut self, number: impl ToString) -> Self {
self.invoice_number = number.to_string();
self
}
/// Set customer ID (fluent)
pub fn customer_id(mut self, id: u32) -> Self {
self.customer_id = id;
self
}
/// Set amount (fluent)
pub fn amount(mut self, amount: f64) -> Self {
self.amount = amount;
self
}
/// Set currency (fluent)
pub fn currency(mut self, currency: impl ToString) -> Self {
self.currency = currency.to_string();
self
}
/// Set description (fluent)
pub fn description(mut self, description: impl ToString) -> Self {
self.description = description.to_string();
self
}
/// Set due date (fluent)
pub fn due_date(mut self, date: u64) -> Self {
self.due_date = Some(date);
self
}
/// Mark as sent
pub fn send(mut self) -> Self {
self.status = InvoiceStatus::Sent;
self
}
/// Mark as paid
pub fn mark_paid(mut self) -> Self {
self.status = InvoiceStatus::Paid;
self.paid_date = Some(time::OffsetDateTime::now_utc().unix_timestamp() as u64);
self
}
/// Mark as overdue
pub fn mark_overdue(mut self) -> Self {
self.status = InvoiceStatus::Overdue;
self
}
/// Cancel invoice
pub fn cancel(mut self) -> Self {
self.status = InvoiceStatus::Cancelled;
self
}
}

View File

@@ -0,0 +1,11 @@
/// Accounting Module
///
/// Provides Invoice and Expense objects for financial tracking
pub mod invoice;
pub mod expense;
pub mod rhai;
pub use invoice::{Invoice, InvoiceStatus};
pub use expense::{Expense, ExpenseCategory, ExpenseStatus};
// pub use rhai::register_accounting_modules; // TODO: Implement when needed