Skip to content

Commit 5089c1e

Browse files
authored
Merge pull request #126 from AdaWorldAPI/claude/odoo-aliases-pricelist-uom-productcatalog-mints
feat(vocab+class-view): mint PRICELIST + PRICELIST_RULE + UNIT_OF_MEASURE; extend ODOO_ALIASES (ProductCatalog cluster)
2 parents a3574bd + 2291f2f commit 5089c1e

3 files changed

Lines changed: 100 additions & 63 deletions

File tree

crates/ogar-class-view/src/lib.rs

Lines changed: 15 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -64,67 +64,19 @@ use lance_graph_contract::{
6464
ontology::{DisplayTemplate, FieldRef, ObjectView},
6565
};
6666
use ogar_vocab::{
67-
Class,
68-
accounting_account,
6967
// 0x0CXX — automation (HIRO MARS CMDB + DO-arm actuators)
70-
action_applicability,
71-
action_handler,
72-
anatomical_structure,
73-
auth_ory_keto,
74-
auth_store,
75-
auth_zanzibar,
76-
auth_zitadel,
77-
automation_trigger,
78-
billable_work_entry,
79-
billing_party,
80-
bone,
81-
canonical_concept_id,
82-
commercial_document,
83-
commercial_line_item,
84-
currency_policy,
85-
diagnosis,
86-
joint,
87-
knowledge_item,
88-
lab_value,
89-
mars_application,
90-
mars_machine,
91-
mars_node_template,
92-
mars_resource,
93-
mars_software,
94-
medication,
95-
patient,
96-
payment_record,
97-
priority,
98-
product,
99-
project,
100-
project_actor,
101-
project_attachment,
102-
project_changeset,
103-
project_comment,
104-
project_custom_field,
105-
project_custom_value,
106-
project_enabled_module,
107-
project_forum,
108-
project_journal,
109-
project_member_role,
110-
project_membership,
111-
project_message,
112-
project_news,
113-
project_query,
114-
project_relation,
115-
project_repository,
116-
project_role,
117-
project_status,
118-
project_type,
119-
project_version,
120-
project_watcher,
121-
project_wiki_page,
122-
project_work_item,
123-
skeleton,
124-
tax_policy,
125-
treatment,
126-
visit,
127-
vital_sign,
68+
action_applicability, Class,
69+
accounting_account, action_handler, anatomical_structure, auth_ory_keto, auth_store,
70+
auth_zanzibar, auth_zitadel, automation_trigger, billable_work_entry, billing_party, bone,
71+
canonical_concept_id, commercial_document, commercial_line_item, currency_policy, diagnosis,
72+
joint, knowledge_item, lab_value, mars_application, mars_machine, mars_node_template,
73+
mars_resource, mars_software, medication, patient, payment_record, pricelist, pricelist_rule,
74+
priority, product, project, project_actor, project_attachment, project_changeset,
75+
project_comment, project_custom_field, project_custom_value, project_enabled_module,
76+
project_forum, project_journal, project_member_role, project_membership, project_message,
77+
project_news, project_query, project_relation, project_repository, project_role,
78+
project_status, project_type, project_version, project_watcher, project_wiki_page,
79+
project_work_item, skeleton, tax_policy, treatment, unit_of_measure, visit, vital_sign,
12880
};
12981

13082
/// All promoted canonical concepts: `(canonical_concept_name, Class)`.
@@ -171,6 +123,9 @@ fn all_canonical_classes() -> Vec<(&'static str, Class)> {
171123
("currency_policy", currency_policy()),
172124
("product", product()),
173125
("accounting_account", accounting_account()),
126+
("pricelist", pricelist()),
127+
("pricelist_rule", pricelist_rule()),
128+
("unit_of_measure", unit_of_measure()),
174129
// ── 0x09XX — health (OGIT Healthcare) ──
175130
("patient", patient()),
176131
("diagnosis", diagnosis()),

crates/ogar-vocab/src/lib.rs

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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);

crates/ogar-vocab/src/ports.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,11 @@ pub const ODOO_ALIASES: &[(&str, u16)] = &[
496496
// same `accounting_account` id. Phase-3 mint per odoo-rs PR #14 + #16.
497497
("account.account", class_ids::ACCOUNTING_ACCOUNT),
498498
("account.account.template", class_ids::ACCOUNTING_ACCOUNT),
499+
// ProductCatalog cluster — pricing structure + UoM, Phase-3 per
500+
// odoo-rs PR #14.
501+
("product.pricelist", class_ids::PRICELIST),
502+
("product.pricelist.item", class_ids::PRICELIST_RULE),
503+
("uom.uom", class_ids::UNIT_OF_MEASURE),
499504
// Cross-arm bridge: the timesheet / cost line converges on the
500505
// project-arm `billable_work_entry` (0x0103) — the SAME id
501506
// OpenProject `TimeEntry` and Redmine `TimeEntry` resolve to.
@@ -1000,13 +1005,13 @@ mod tests {
10001005
// 9 Odoo model aliases = 8 commerce-arm (account.move,
10011006
// sale.order, account.move.line, sale.order.line, account.tax,
10021007
// res.partner, account.payment, res.currency) + 4 product/accounting
1003-
// master-record aliases (product.template, product.product,
1008+
// master-record aliases + 3 ProductCatalog cluster aliases (product.template, product.product,
10041009
// account.account, account.account.template — Phase-3 mints per
10051010
// odoo-rs PR #14 + #16) + 1 cross-arm bridge
10061011
// (account.analytic.line → billable_work_entry). Re-count on drift.
10071012
assert_eq!(
10081013
OdooPort::aliases().len(),
1009-
13,
1014+
16,
10101015
"Odoo alias count drift — re-count the ODOO_ALIASES table",
10111016
);
10121017
}

0 commit comments

Comments
 (0)