.. | ||
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.
┌─────────────┐
│ Customer │
└──────┬──────┘
│
▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Currency │◄────┤ Product │◄────┤ │ │ │
└─────────────┘ └─────────────┘ │ │ │ │
▲ │ SaleItem │◄────┤ Sale │
│ │ │ │ │
┌─────┴──────────┐ │ │ │ │
│ProductComponent│ └─────────────┘ └──────┬──────┘
└────────────────┘ ▲ │
/ │
┌─────────────┐ ┌─────────────┐ / │
│ Currency │◄────┤ Service │◄────────/ │
└─────────────┘ └─────────────┘ │
│
│
▼
┌─────────────┐ ┌─────────────┐
│ 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
- Contains SaleItems that can be linked to either Products or Services
- SaleItem: Represents an item within a sale
- Can be linked to either a Product or a Service (via product_id or service_id)
- 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
: Option - ID of the product sold (if this is a product sale)service_id
: Option - ID of the service sold (if this is a service sale)name
: String - Product/service 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
A SaleItem can be directly linked to a Service via the service_id
field. This allows for selling existing services or creating new services as part of a sale:
// Create a SaleItem linked to a service
let sale_item = SaleItemBuilder::new()
.id(1)
.sale_id(1)
.service_id(Some(42)) // Link to service with ID 42
.product_id(None) // No product link since this is a service
.name("Premium Support")
.quantity(1)
.unit_price(unit_price)
.tax_rate(20.0)
.active_till(now + Duration::days(30))
.build()
.expect("Failed to build sale item");
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);