stateset_embedded/reviews.rs
1//! Product review operations for managing customer reviews and ratings
2//!
3//! # Example
4//!
5//! ```rust,ignore
6//! use stateset_embedded::{Commerce, CreateReview, ProductId, CustomerId};
7//!
8//! let commerce = Commerce::new("./store.db")?;
9//!
10//! let review = commerce.reviews().create(CreateReview {
11//! product_id: ProductId::new(),
12//! customer_id: CustomerId::new(),
13//! rating: 5,
14//! title: Some("Excellent product!".into()),
15//! body: Some("Works exactly as described.".into()),
16//! ..Default::default()
17//! })?;
18//!
19//! println!("Review created with rating: {}", review.rating);
20//! # Ok::<(), stateset_embedded::CommerceError>(())
21//! ```
22
23use stateset_core::{
24 CreateReview, ProductId, Result, Review, ReviewFilter, ReviewId, ReviewSummary, UpdateReview,
25};
26use stateset_db::{Database, DatabaseCapability};
27use std::sync::Arc;
28
29/// Product review operations.
30pub struct Reviews {
31 db: Arc<dyn Database>,
32}
33
34impl std::fmt::Debug for Reviews {
35 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36 f.debug_struct("Reviews").finish_non_exhaustive()
37 }
38}
39
40impl Reviews {
41 pub(crate) fn new(db: Arc<dyn Database>) -> Self {
42 Self { db }
43 }
44
45 /// Whether reviews are supported by the active backend.
46 #[must_use]
47 pub fn is_supported(&self) -> bool {
48 self.db.supports_capability(DatabaseCapability::Reviews)
49 }
50
51 fn ensure_supported(&self) -> Result<()> {
52 self.db.ensure_capability(DatabaseCapability::Reviews)
53 }
54
55 /// Create a new product review.
56 ///
57 /// # Example
58 ///
59 /// ```rust,ignore
60 /// use stateset_embedded::{Commerce, CreateReview, ProductId, CustomerId};
61 ///
62 /// let commerce = Commerce::new("./store.db")?;
63 ///
64 /// let review = commerce.reviews().create(CreateReview {
65 /// product_id: ProductId::new(),
66 /// customer_id: CustomerId::new(),
67 /// rating: 4,
68 /// title: Some("Good value".into()),
69 /// body: Some("Decent quality for the price.".into()),
70 /// ..Default::default()
71 /// })?;
72 /// # Ok::<(), stateset_embedded::CommerceError>(())
73 /// ```
74 pub fn create(&self, input: CreateReview) -> Result<Review> {
75 self.ensure_supported()?;
76 self.db.reviews().create(input)
77 }
78
79 /// Get a review by ID.
80 pub fn get(&self, id: ReviewId) -> Result<Option<Review>> {
81 self.ensure_supported()?;
82 self.db.reviews().get(id)
83 }
84
85 /// Update a review.
86 pub fn update(&self, id: ReviewId, input: UpdateReview) -> Result<Review> {
87 self.ensure_supported()?;
88 self.db.reviews().update(id, input)
89 }
90
91 /// List reviews with optional filtering.
92 pub fn list(&self, filter: ReviewFilter) -> Result<Vec<Review>> {
93 self.ensure_supported()?;
94 self.db.reviews().list(filter)
95 }
96
97 /// Delete a review.
98 pub fn delete(&self, id: ReviewId) -> Result<()> {
99 self.ensure_supported()?;
100 self.db.reviews().delete(id)
101 }
102
103 /// Get aggregate review summary for a product.
104 ///
105 /// Returns average rating, total count, and rating distribution.
106 pub fn get_summary(&self, product_id: ProductId) -> Result<ReviewSummary> {
107 self.ensure_supported()?;
108 self.db.reviews().get_summary(product_id)
109 }
110
111 /// Mark a review as helpful (increment helpful count).
112 pub fn mark_helpful(&self, id: ReviewId) -> Result<()> {
113 self.ensure_supported()?;
114 self.db.reviews().mark_helpful(id)
115 }
116
117 /// Mark a review as reported (increment reported count).
118 pub fn mark_reported(&self, id: ReviewId) -> Result<()> {
119 self.ensure_supported()?;
120 self.db.reviews().mark_reported(id)
121 }
122}