Skip to main content

backbone_inventory/application/service/
inventory_masters.rs

1//! Warehouse + stock-item masters (hand-authored, user-owned).
2//!
3//! An `impl InventoryWriteService` chunk over the vocabulary in [`super::inventory_write_service`]:
4//! the two master-data creators. Both are simple inserts under the ambient org scope —
5//! no SLE, no Bin, no GL.
6//!
7//! Tenancy (ADR-0029): the module is tenant-agnostic. The inserts ride the ambient org scope
8//! the composing service set per request (the repositories run `org_scope::execute_scoped`);
9//! the composing decorator owns isolation.
10//!
11//! Per the module's 4-layer rule this file holds no SQL — the statements live on
12//! `WarehouseRepository` / `StockItemRepository`.
13
14use uuid::Uuid;
15
16use crate::infrastructure::persistence::{NewStockItemRow, NewWarehouseRow};
17
18use super::inventory_write_service::{is_dup, InventoryError, InventoryWriteService, NewStockItem, NewWarehouse};
19
20impl InventoryWriteService {
21    // ---- masters ------------------------------------------------------------
22
23    pub async fn create_warehouse(&self, w: NewWarehouse) -> Result<Uuid, InventoryError> {
24        let id = Uuid::new_v4();
25        let wt = w.warehouse_type.unwrap_or_else(|| "stock".into());
26        let r = self.warehouses.insert_warehouse(&self.rpool(), &NewWarehouseRow {
27            id,
28            code: &w.code,
29            name: &w.name,
30            warehouse_type: &wt,
31            parent_warehouse_id: w.parent_warehouse_id,
32            is_group: w.is_group,
33        }).await;
34        match r {
35            Ok(_) => Ok(id),
36            Err(e) if is_dup(&e) => Err(InventoryError::DuplicateNumber(w.code)),
37            Err(e) => Err(e.into()),
38        }
39    }
40
41    pub async fn create_stock_item(&self, s: NewStockItem) -> Result<Uuid, InventoryError> {
42        let id = Uuid::new_v4();
43        let vm = s.valuation_method.unwrap_or_else(|| "moving_average".into());
44        let r = self.stock_items.insert_stock_item(&self.rpool(), &NewStockItemRow {
45            id,
46            item_id: s.item_id,
47            stock_uom: &s.stock_uom,
48            valuation_method: &vm,
49            reorder_level: s.reorder_level,
50        }).await;
51        match r {
52            Ok(_) => Ok(id),
53            Err(e) if is_dup(&e) => Err(InventoryError::DuplicateNumber(s.item_id.to_string())),
54            Err(e) => Err(e.into()),
55        }
56    }
57}