Skip to main content

datasynth_core/models/
sales_quote.rs

1//! Sales quote models for the Quote-to-Cash process.
2//!
3//! These models represent sales quotations and their line items,
4//! supporting the full quote lifecycle from draft through win/loss.
5
6use chrono::NaiveDate;
7use rust_decimal::Decimal;
8use serde::{Deserialize, Serialize};
9
10/// Status of a sales quote through the quotation lifecycle.
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
12#[serde(rename_all = "snake_case")]
13pub enum QuoteStatus {
14    /// Initial draft, not yet sent to customer
15    #[default]
16    Draft,
17    /// Quote has been sent to the customer
18    Sent,
19    /// Quote is under active negotiation
20    Negotiating,
21    /// Customer accepted the quote
22    Won,
23    /// Customer rejected the quote
24    Lost,
25    /// Quote validity period has elapsed
26    Expired,
27    /// Quote was cancelled before resolution
28    Cancelled,
29}
30
31/// A sales quotation issued to a prospective or existing customer.
32#[derive(Debug, Clone, Serialize, Deserialize)]
33pub struct SalesQuote {
34    /// Unique quote identifier
35    pub quote_id: String,
36    /// Company code issuing the quote
37    pub company_code: String,
38    /// Customer identifier
39    pub customer_id: String,
40    /// Customer name
41    pub customer_name: String,
42    /// Date the quote was created
43    pub quote_date: NaiveDate,
44    /// Date the quote expires
45    pub valid_until: NaiveDate,
46    /// Current status of the quote
47    pub status: QuoteStatus,
48    /// Individual line items on the quote
49    pub line_items: Vec<QuoteLineItem>,
50    /// Total quoted amount before discount
51    #[serde(with = "rust_decimal::serde::str")]
52    pub total_amount: Decimal,
53    /// Currency code (e.g., USD, EUR)
54    pub currency: String,
55    /// Discount percentage applied (0.0 to 1.0)
56    pub discount_percent: f64,
57    /// Calculated discount amount
58    #[serde(with = "rust_decimal::serde::str")]
59    pub discount_amount: Decimal,
60    /// Sales representative responsible for the quote
61    pub sales_rep_id: Option<String>,
62    /// Linked sales order identifier (populated when status is Won)
63    pub sales_order_id: Option<String>,
64    /// Reason the quote was lost (populated when status is Lost)
65    pub lost_reason: Option<String>,
66    /// Free-text notes on the quote
67    pub notes: Option<String>,
68}
69
70/// An individual line item within a sales quote.
71#[derive(Debug, Clone, Serialize, Deserialize)]
72pub struct QuoteLineItem {
73    /// Sequential item number within the quote
74    pub item_number: u32,
75    /// Material or product identifier
76    pub material_id: String,
77    /// Description of the quoted item
78    pub description: String,
79    /// Quoted quantity
80    #[serde(with = "rust_decimal::serde::str")]
81    pub quantity: Decimal,
82    /// Unit price for the item
83    #[serde(with = "rust_decimal::serde::str")]
84    pub unit_price: Decimal,
85    /// Total line amount (quantity * unit_price)
86    #[serde(with = "rust_decimal::serde::str")]
87    pub line_amount: Decimal,
88}