backbone-inventory 0.17.2

Inventory: stock ledger of record (SLE) + moving-average valuation; emits COGS/asset AccountingPost (Delivery/Receipt -> GL)
Documentation
//! Repository for StockReconciliationItem entities
//!
//! Originally generated by metaphor-schema; now **user-owned** — this exact path is declared under
//! `user_owned` in `metaphor.codegen.yaml`, so the generator skips it wholesale. The custom methods
//! below hold the hand-written StockReconciliationItem SQL
//! (4-layer rule: services orchestrate, repositories hold the SQL).
//!
//! Thin newtype over `backbone_orm::GenericCrudRepository<StockReconciliationItem, backbone_orm::SoftDelete>`.
//! All standard CRUD methods are available via `Deref`.

use anyhow::Result;
use rust_decimal::Decimal;
use sqlx::PgPool;
use uuid::Uuid;

use crate::domain::entity::StockReconciliationItem;

/// Table name for StockReconciliationItem entities
pub const TABLE_NAME: &str = "inventory.stock_reconciliation_items";

/// Repository for StockReconciliationItem entities.
///
/// All standard CRUD, soft-delete, pagination, and bulk methods are
/// provided automatically via `Deref` to `backbone_orm::GenericCrudRepository`.
pub struct StockReconciliationItemRepository(
    backbone_orm::GenericCrudRepository<StockReconciliationItem, backbone_orm::SoftDelete>,
);

impl std::ops::Deref for StockReconciliationItemRepository {
    type Target = backbone_orm::GenericCrudRepository<StockReconciliationItem, backbone_orm::SoftDelete>;
    fn deref(&self) -> &Self::Target { &self.0 }
}

impl StockReconciliationItemRepository {
    /// Create a new repository instance.
    pub fn new(pool: PgPool) -> Self {
        Self(backbone_orm::GenericCrudRepository::new(pool, TABLE_NAME))
    }
}

/// The exact row a counted reconciliation line insert writes.
///
/// `counted_rate` is stored as SUPPLIED (0 meaning "keep the current rate"), while the differences
/// are computed against the bin's locked balance — so the line records both what was counted and
/// what it moved.
pub struct NewReconciliationItemRow {
    pub id: Uuid,
    pub reconciliation_id: Uuid,
    pub item_id: Uuid,
    pub counted_qty: Decimal,
    pub counted_rate: Decimal,
    pub qty_difference: Decimal,
    pub value_difference: Decimal,
}

/// Hand-written StockReconciliationItem SQL. Lives here per the module's 4-layer rule.
impl StockReconciliationItemRepository {
    /// Insert one counted line. Takes the CALLER'S connection so it commits with the bin/SLE writes
    /// it describes; the caller has already relayed the ambient org scope onto it — don't re-bind
    /// here.
    pub async fn insert_item(
        &self,
        conn: &mut sqlx::PgConnection,
        l: &NewReconciliationItemRow,
    ) -> Result<(), sqlx::Error> {
        sqlx::query(
            r#"INSERT INTO inventory.stock_reconciliation_items
                (id, reconciliation_id, item_id, counted_qty, counted_rate, qty_difference, value_difference)
               VALUES ($1,$2,$3,$4,$5,$6,$7)"#,
        )
        .bind(l.id).bind(l.reconciliation_id).bind(l.item_id).bind(l.counted_qty)
        .bind(l.counted_rate).bind(l.qty_difference).bind(l.value_difference)
        .execute(conn)
        .await?;
        Ok(())
    }
}

backbone_core::impl_crud_repository!(StockReconciliationItemRepository, StockReconciliationItem, soft_delete);