@@ -1156,6 +1156,12 @@ const CODEBOOK: &[(&str, u16)] = &[
11561156 // PR description for the queue.
11571157 ( "product" , 0x0207 ) ,
11581158 ( "accounting_account" , 0x0208 ) ,
1159+ // ProductCatalog cluster — closes 3 more of the 11-gap. All stay in 0x02XX
1160+ // (no new ConceptDomain needed). HR cluster (hr.*) remains queued; needs
1161+ // a new 0x0DXX concept domain (keystone-style §7 review).
1162+ ( "pricelist" , 0x0209 ) ,
1163+ ( "pricelist_rule" , 0x020A ) ,
1164+ ( "unit_of_measure" , 0x020B ) ,
11591165 // ── 0x09XX — Health domain (clinical / patient / care) ──
11601166 // medcare-rs Healthcare-namespace promotion (Northstar T9). The 7
11611167 // entities the OGIT `NTO/Healthcare/entities/` TTL ships, projected
@@ -1533,6 +1539,16 @@ pub mod class_ids {
15331539 /// SMBAccounting (0x62); this id is the OGAR-side identity that closes
15341540 /// the same axis.
15351541 pub const ACCOUNTING_ACCOUNT : u16 = 0x0208 ;
1542+ /// `pricelist` (`0x0209`) — price-specification base. OSB `Pricelist`,
1543+ /// Odoo `product.pricelist` (`schema:PriceSpecification`). Phase-3
1544+ /// ProductCatalog cluster.
1545+ pub const PRICELIST : u16 = 0x0209 ;
1546+ /// `pricelist_rule` (`0x020A`) — per-tier unit-price rule. OSB
1547+ /// `PricelistTier`, Odoo `product.pricelist.item`.
1548+ pub const PRICELIST_RULE : u16 = 0x020A ;
1549+ /// `unit_of_measure` (`0x020B`) — measurement unit. OSB `UoM`, Odoo
1550+ /// `uom.uom` (`qudt:Unit`).
1551+ pub const UNIT_OF_MEASURE : u16 = 0x020B ;
15361552
15371553 // ── 0x09XX — health domain (medcare-rs Healthcare namespace) ──
15381554
@@ -1670,6 +1686,9 @@ pub mod class_ids {
16701686 ( "currency_policy" , CURRENCY_POLICY ) ,
16711687 ( "product" , PRODUCT ) ,
16721688 ( "accounting_account" , ACCOUNTING_ACCOUNT ) ,
1689+ ( "pricelist" , PRICELIST ) ,
1690+ ( "pricelist_rule" , PRICELIST_RULE ) ,
1691+ ( "unit_of_measure" , UNIT_OF_MEASURE ) ,
16731692 // 0x09XX — health
16741693 ( "patient" , PATIENT ) ,
16751694 ( "diagnosis" , DIAGNOSIS ) ,
@@ -2538,6 +2557,9 @@ pub fn all_promoted_classes() -> Vec<Class> {
25382557 currency_policy( ) ,
25392558 product( ) ,
25402559 accounting_account( ) ,
2560+ pricelist( ) ,
2561+ pricelist_rule( ) ,
2562+ unit_of_measure( ) ,
25412563 // 0x09XX — health arm (7 OGIT Healthcare concepts), in
25422564 // class_ids::ALL order.
25432565 patient( ) ,
@@ -3418,6 +3440,58 @@ pub fn accounting_account() -> Class {
34183440 c
34193441}
34203442
3443+ /// `pricelist` (`0x0209`) — price-specification base.
3444+ pub fn pricelist ( ) -> Class {
3445+ let mut c = Class :: new ( "Pricelist" ) ;
3446+ c. language = Language :: Unknown ;
3447+ c. canonical_concept = Some ( "pricelist" . to_string ( ) ) ;
3448+ c. associations = Vec :: new ( ) ;
3449+ let mut name = Attribute :: new ( "name" ) ;
3450+ name. type_name = Some ( "string" . to_string ( ) ) ;
3451+ let mut currency = Attribute :: new ( "currency" ) ;
3452+ currency. type_name = Some ( "string" . to_string ( ) ) ;
3453+ let mut active = Attribute :: new ( "active" ) ;
3454+ active. type_name = Some ( "bool" . to_string ( ) ) ;
3455+ c. attributes = vec ! [ name, currency, active] ;
3456+ c
3457+ }
3458+
3459+ /// `pricelist_rule` (`0x020A`) — per-tier unit-price rule.
3460+ pub fn pricelist_rule ( ) -> Class {
3461+ let mut c = Class :: new ( "PricelistRule" ) ;
3462+ c. language = Language :: Unknown ;
3463+ c. canonical_concept = Some ( "pricelist_rule" . to_string ( ) ) ;
3464+ c. associations = Vec :: new ( ) ;
3465+ let mut price = Attribute :: new ( "price" ) ;
3466+ price. type_name = Some ( "decimal" . to_string ( ) ) ;
3467+ let mut min_quantity = Attribute :: new ( "min_quantity" ) ;
3468+ min_quantity. type_name = Some ( "decimal" . to_string ( ) ) ;
3469+ let mut max_quantity = Attribute :: new ( "max_quantity" ) ;
3470+ max_quantity. type_name = Some ( "decimal" . to_string ( ) ) ;
3471+ let mut pricelist_ref = Attribute :: new ( "pricelist_ref" ) ;
3472+ pricelist_ref. type_name = Some ( "string" . to_string ( ) ) ;
3473+ c. attributes = vec ! [ price, min_quantity, max_quantity, pricelist_ref] ;
3474+ c
3475+ }
3476+
3477+ /// `unit_of_measure` (`0x020B`) — measurement unit.
3478+ pub fn unit_of_measure ( ) -> Class {
3479+ let mut c = Class :: new ( "UnitOfMeasure" ) ;
3480+ c. language = Language :: Unknown ;
3481+ c. canonical_concept = Some ( "unit_of_measure" . to_string ( ) ) ;
3482+ c. associations = Vec :: new ( ) ;
3483+ let mut name = Attribute :: new ( "name" ) ;
3484+ name. type_name = Some ( "string" . to_string ( ) ) ;
3485+ let mut symbol = Attribute :: new ( "symbol" ) ;
3486+ symbol. type_name = Some ( "string" . to_string ( ) ) ;
3487+ let mut factor = Attribute :: new ( "factor" ) ;
3488+ factor. type_name = Some ( "decimal" . to_string ( ) ) ;
3489+ let mut uom_type = Attribute :: new ( "uom_type" ) ;
3490+ uom_type. type_name = Some ( "string" . to_string ( ) ) ;
3491+ c. attributes = vec ! [ name, symbol, factor, uom_type] ;
3492+ c
3493+ }
3494+
34213495// ─────────────────────────────────────────────────────────────────────
34223496// 0x09XX — Health domain (OGIT Healthcare). The reusable Active-Record
34233497// shape for the clinical concepts. `diagnosis` (0x0902) is the worked
@@ -4488,6 +4562,9 @@ mod tests {
44884562 "currency_policy" ,
44894563 "product" ,
44904564 "accounting_account" ,
4565+ "pricelist" ,
4566+ "pricelist_rule" ,
4567+ "unit_of_measure" ,
44914568 ] {
44924569 let id = canonical_concept_id ( commerce_concept)
44934570 . unwrap_or_else ( || panic ! ( "{commerce_concept} missing from codebook" ) ) ;
@@ -4633,7 +4710,7 @@ mod tests {
46334710 }
46344711 // Counts line up with the codebook blocks.
46354712 assert_eq ! ( concepts_in_domain( ConceptDomain :: Health ) . count( ) , 7 ) ;
4636- assert_eq ! ( concepts_in_domain( ConceptDomain :: Commerce ) . count( ) , 8 ) ;
4713+ assert_eq ! ( concepts_in_domain( ConceptDomain :: Commerce ) . count( ) , 11 ) ;
46374714 assert_eq ! ( concepts_in_domain( ConceptDomain :: ProjectMgmt ) . count( ) , 26 ) ;
46384715 assert_eq ! ( concepts_in_domain( ConceptDomain :: Anatomy ) . count( ) , 4 ) ;
46394716 assert_eq ! ( concepts_in_domain( ConceptDomain :: Auth ) . count( ) , 4 ) ;
0 commit comments