.. | ||
rhai | ||
contract.rs | ||
currency.rs | ||
customer.rs | ||
exchange_rate.rs | ||
invoice.rs | ||
lib.rs | ||
mod.rs | ||
product.rs | ||
README.md | ||
sale.rs | ||
service.rs |
Business Models
This directory contains the core business models used throughout the application for representing essential business objects like products, sales, and currency.
Overview
The business models are implemented as Rust structs and enums with serialization/deserialization support via Serde. These models implement the SledModel
and Storable
traits for persistence in the application's database layer.
Model Relationships
┌─────────────┐
│ Customer │
└──────┬──────┘
│
▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Currency │◄────┤ Product │◄────┤ SaleItem │◄────┤ Sale │
└─────────────┘ └─────────────┘ └─────────────┘ └──────┬──────┘
▲ │
│ │
┌─────┴──────────┐ │
│ProductComponent│ │
└────────────────┘ │
│
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ Currency │◄────┤ Service │◄────┤ ServiceItem │◄───────────┘
└─────────────┘ └─────────────┘ └─────────────┘
│
│
▼
┌─────────────┐ ┌─────────────┐
│ InvoiceItem │◄────┤ Invoice │
└─────────────┘ └─────────────┘
Business Logic Relationships
- Customer: The entity purchasing products or services
- Product/Service: Defines what is being sold, including its base price
- Can be marked as a template (
is_template=true
) to create copies for actual sales
- Can be marked as a template (
- Sale: Represents the transaction of selling products/services to customers, including tax calculations
- Can be linked to a Service when the sale creates an ongoing service
- Service: Represents an ongoing service provided to a customer
- Created from a Product template when the product type is Service
- Invoice: Represents the billing document for a sale, with payment tracking
- Created from a Sale object to handle billing and payment tracking
Root Objects
- Root objects are the ones stored directly in the DB
- Root Objects are:
- Customer
- Currency
- Product
- Sale
- Service
- Invoice
Models
Currency (Root Object)
Represents a monetary value with an amount and currency code.
Properties:
amount
: f64 - The monetary amountcurrency_code
: String - The currency code (e.g., "USD", "EUR")
Builder:
CurrencyBuilder
- Provides a fluent interface for creating Currency instances
Customer (Root Object)
Represents a customer who can purchase products or services.
Properties:
id
: u32 - Unique identifiername
: String - Customer namedescription
: String - Customer descriptionpubkey
: String - Customer's public keycontact_ids
: Vec - List of contact IDscreated_at
: DateTime - Creation timestampupdated_at
: DateTime - Last update timestamp
Methods:
add_contact()
- Adds a contact ID to the customerremove_contact()
- Removes a contact ID from the customer
Product
ProductType Enum
Categorizes products:
Product
- Physical productService
- Non-physical service
ProductStatus Enum
Tracks product availability:
Available
- Product can be purchasedUnavailable
- Product cannot be purchased
ProductComponent
Represents a component part of a product.
Properties:
id
: u32 - Unique identifiername
: String - Component namedescription
: String - Component descriptionquantity
: i32 - Number of this componentcreated_at
: DateTime - Creation timestampupdated_at
: DateTime - Last update timestamp
Builder:
ProductComponentBuilder
- Provides a fluent interface for creating ProductComponent instances
Product (Root Object)
Represents a product or service offered.
Properties:
id
: i64 - Unique identifiername
: String - Product namedescription
: String - Product descriptionprice
: Currency - Product pricetype_
: ProductType - Product or Servicecategory
: String - Product categorystatus
: ProductStatus - Available or Unavailablecreated_at
: DateTime - Creation timestampupdated_at
: DateTime - Last update timestampmax_amount
: i64 - Maximum quantity availablepurchase_till
: DateTime - Deadline for purchasingactive_till
: DateTime - When product/service expirescomponents
: Vec - List of product componentsis_template
: bool - Whether this is a template product (to be added)
Methods:
add_component()
- Adds a component to this productset_purchase_period()
- Updates purchase availability timeframeset_active_period()
- Updates active timeframeis_purchasable()
- Checks if product is available for purchaseis_active()
- Checks if product is still active
Builder:
ProductBuilder
- Provides a fluent interface for creating Product instances
Database Implementation:
- Implements
Storable
trait for serialization - Implements
SledModel
trait with:get_id()
- Returns the ID as a stringdb_prefix()
- Returns "product" as the database prefix
Service (Root Object)
BillingFrequency Enum
Defines how often a service is billed:
Hourly
- Billed by the hourDaily
- Billed dailyWeekly
- Billed weeklyMonthly
- Billed monthlyYearly
- Billed yearly
ServiceStatus Enum
Tracks the status of a service:
Active
- Service is currently activePaused
- Service is temporarily pausedCancelled
- Service has been cancelledCompleted
- Service has been completed
ServiceItem
Represents an item within a service.
Properties:
id
: u32 - Unique identifierservice_id
: u32 - Parent service IDproduct_id
: u32 - ID of the product this service is based onname
: String - Service namedescription
: String - Detailed description of the service itemcomments
: String - Additional notes or comments about the service itemquantity
: i32 - Number of unitsunit_price
: Currency - Price per unitsubtotal
: Currency - Total price before taxtax_rate
: f64 - Tax rate as a percentagetax_amount
: Currency - Calculated tax amountis_taxable
: bool - Whether this item is taxableactive_till
: DateTime - When service expires
Service
Represents an ongoing service provided to a customer.
Properties:
id
: u32 - Unique identifiercustomer_id
: u32 - ID of the customer receiving the servicetotal_amount
: Currency - Total service amount including taxstatus
: ServiceStatus - Current service statusbilling_frequency
: BillingFrequency - How often the service is billedservice_date
: DateTime - When service startedcreated_at
: DateTime - Creation timestampupdated_at
: DateTime - Last update timestampitems
: Vec - List of items in the serviceis_template
: bool - Whether this is a template service (to be added)
Methods:
add_item()
- Adds an item to the service and updates totalcalculate_total()
- Recalculates the total amountupdate_status()
- Updates the status of the service
Sale
SaleStatus Enum
Tracks the status of a sale:
Pending
- Sale is in progressCompleted
- Sale has been finalizedCancelled
- Sale has been cancelled
SaleItem
Represents an item within a sale.
Properties:
id
: u32 - Unique identifiersale_id
: u32 - Parent sale IDproduct_id
: u32 - ID of the product soldname
: String - Product name at time of saledescription
: String - Detailed description of the itemcomments
: String - Additional notes or comments about the itemquantity
: i32 - Number of items purchasedunit_price
: Currency - Price per unitsubtotal
: Currency - Total price for this item before tax (calculated)tax_rate
: f64 - Tax rate as a percentage (e.g., 20.0 for 20%)tax_amount
: Currency - Calculated tax amount for this itemactive_till
: DateTime - When item/service expires
Methods:
total_with_tax()
- Returns the total amount including tax
Builder:
SaleItemBuilder
- Provides a fluent interface for creating SaleItem instances
Sale (Root Object)
Represents a complete sale transaction.
Properties:
id
: u32 - Unique identifiercompany_id
: u32 - ID of the company making the salecustomer_id
: u32 - ID of the customer making the purchase (to be added)buyer_name
: String - Name of the buyerbuyer_email
: String - Email of the buyersubtotal_amount
: Currency - Total sale amount before taxtax_amount
: Currency - Total tax amount for the saletotal_amount
: Currency - Total sale amount including taxstatus
: SaleStatus - Current sale statusservice_id
: Option - ID of the service created from this sale (to be added)sale_date
: DateTime - When sale occurredcreated_at
: DateTime - Creation timestampupdated_at
: DateTime - Last update timestampitems
: Vec - List of items in the sale
Methods:
add_item()
- Adds an item to the sale and updates totalsupdate_status()
- Updates the status of the salerecalculate_totals()
- Recalculates all totals based on itemscreate_service()
- Creates a service from this sale (to be added)
Builder:
SaleBuilder
- Provides a fluent interface for creating Sale instances
Database Implementation:
- Implements
Storable
trait for serialization - Implements
SledModel
trait with:get_id()
- Returns the ID as a stringdb_prefix()
- Returns "sale" as the database prefix
Usage Examples
Creating a Currency
let price = CurrencyBuilder::new()
.amount(29.99)
.currency_code("USD")
.build()
.expect("Failed to build currency");
Creating a Product
// Create a currency using the builder
let price = CurrencyBuilder::new()
.amount(29.99)
.currency_code("USD")
.build()
.expect("Failed to build currency");
// Create a component using the builder
let component = ProductComponentBuilder::new()
.id(1)
.name("Basic Support")
.description("24/7 email support")
.quantity(1)
.build()
.expect("Failed to build product component");
// Create a product using the builder
let product = ProductBuilder::new()
.id(1)
.name("Premium Service")
.description("Our premium service offering")
.price(price)
.type_(ProductType::Service)
.category("Services")
.status(ProductStatus::Available)
.max_amount(100)
.validity_days(30)
.add_component(component)
.build()
.expect("Failed to build product");
Creating a Sale
let now = Utc::now();
// Create a currency using the builder
let unit_price = CurrencyBuilder::new()
.amount(29.99)
.currency_code("USD")
.build()
.expect("Failed to build currency");
// Create a sale item using the builder
let item = SaleItemBuilder::new()
.id(1)
.sale_id(1)
.product_id(1)
.name("Premium Service")
.quantity(1)
.unit_price(unit_price)
.tax_rate(20.0) // 20% tax rate
.active_till(now + Duration::days(30))
.build()
.expect("Failed to build sale item");
// Create a sale using the builder
let mut sale = SaleBuilder::new()
.id(1)
.company_id(101)
.buyer_name("John Doe")
.buyer_email("john.doe@example.com")
.currency_code("USD")
.status(SaleStatus::Pending)
.add_item(item)
.build()
.expect("Failed to build sale");
// Update the sale status
sale.update_status(SaleStatus::Completed);
// The sale now contains:
// - subtotal_amount: The sum of all items before tax
// - tax_amount: The sum of all tax amounts
// - total_amount: The total including tax
Relationship Between Sale and Invoice
The Sale model represents what is sold to a customer (products or services), including tax calculations. The Invoice model represents the billing document for that sale.
An InvoiceItem can be linked to a Sale via the sale_id
field, establishing a connection between what was sold and how it's billed.
// Create an invoice item linked to a sale
let invoice_item = InvoiceItemBuilder::new()
.id(1)
.invoice_id(1)
.description("Premium Service")
.amount(sale.total_amount.clone()) // Use the total amount from the sale
.sale_id(sale.id) // Link to the sale
.build()
.expect("Failed to build invoice item");
Database Operations
The library provides model-specific convenience methods for common database operations:
// Insert a product
db.insert_product(&product).expect("Failed to insert product");
// Retrieve a product by ID
let retrieved_product = db.get_product(1).expect("Failed to retrieve product");
// List all products
let all_products = db.list_products().expect("Failed to list products");
// Delete a product
db.delete_product(1).expect("Failed to delete product");
These methods are available for all root objects:
insert_product
,get_product
,delete_product
,list_products
for Productinsert_currency
,get_currency
,delete_currency
,list_currencies
for Currencyinsert_sale
,get_sale
,delete_sale
,list_sales
for Saleinsert_service
,get_service
,delete_service
,list_services
for Serviceinsert_invoice
,get_invoice
,delete_invoice
,list_invoices
for Invoiceinsert_customer
,get_customer
,delete_customer
,list_customers
for Customer
Invoice (Root Object)
InvoiceStatus Enum
Tracks the status of an invoice:
Draft
- Invoice is in draft stateSent
- Invoice has been sent to the customerPaid
- Invoice has been paidOverdue
- Invoice is past due dateCancelled
- Invoice has been cancelled
PaymentStatus Enum
Tracks the payment status of an invoice:
Unpaid
- Invoice has not been paidPartiallyPaid
- Invoice has been partially paidPaid
- Invoice has been fully paid
Payment
Represents a payment made against an invoice.
Properties:
amount
: Currency - Payment amountdate
: DateTime - Payment datemethod
: String - Payment methodcomment
: String - Payment comment
InvoiceItem
Represents an item in an invoice.
Properties:
id
: u32 - Unique identifierinvoice_id
: u32 - Parent invoice IDdescription
: String - Item descriptionamount
: Currency - Item amountservice_id
: Option - ID of the service this item is forsale_id
: Option - ID of the sale this item is for
Methods:
link_to_service()
- Links the invoice item to a servicelink_to_sale()
- Links the invoice item to a sale
Invoice
Represents an invoice sent to a customer.
Properties:
id
: u32 - Unique identifiercustomer_id
: u32 - ID of the customer being invoicedtotal_amount
: Currency - Total invoice amountbalance_due
: Currency - Amount still duestatus
: InvoiceStatus - Current invoice statuspayment_status
: PaymentStatus - Current payment statusissue_date
: DateTime - When invoice was issueddue_date
: DateTime - When payment is duecreated_at
: DateTime - Creation timestampupdated_at
: DateTime - Last update timestampitems
: Vec - List of items in the invoicepayments
: Vec - List of payments made
Methods:
add_item()
- Adds an item to the invoicecalculate_total()
- Calculates the total amountadd_payment()
- Adds a payment to the invoicecalculate_balance()
- Calculates the balance dueupdate_payment_status()
- Updates the payment statusupdate_status()
- Updates the status of the invoiceis_overdue()
- Checks if the invoice is overduecheck_if_overdue()
- Marks the invoice as overdue if past due date
Relationships Between Models
Product/Service Templates and Instances
Products and Services can be marked as templates (is_template=true
). When a customer purchases a product or service, a copy is created from the template with the specific details of what was sold.
Sale to Service Relationship
When a product of type Service
is sold, a Service instance can be created from the Sale:
// Create a service from a sale
let service = sale.create_service(
service_id,
ServiceStatus::Active,
BillingFrequency::Monthly
);
Sale to Invoice Relationship
An Invoice is created from a Sale to handle billing and payment tracking:
// Create an invoice from a sale
let invoice = Invoice::from_sale(
invoice_id,
sale,
due_date
);
Customer-Centric View
The models allow tracking all customer interactions:
- What products/services they've purchased (via Sale records)
- What ongoing services they have (via Service records)
- What they've been invoiced for (via Invoice records)
- What they've paid (via Payment records in Invoices)
// Get all sales for a customer
let customer_sales = db.list_sales_by_customer(customer_id);
// Get all services for a customer
let customer_services = db.list_services_by_customer(customer_id);
// Get all invoices for a customer
let customer_invoices = db.list_invoices_by_customer(customer_id);