Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7793def268 |
+114
-60
@@ -67,31 +67,60 @@ ex:SD_10_01 a pr:SubDomain ;
|
|||||||
pr:belongsTo ex:DD_10 ;
|
pr:belongsTo ex:DD_10 ;
|
||||||
pr:hasStatus "PUBLISHED" ; pr:hasVersion "1.0" .
|
pr:hasStatus "PUBLISHED" ; pr:hasVersion "1.0" .
|
||||||
ex:SD_04_01 a pr:SubDomain ;
|
ex:SD_04_01 a pr:SubDomain ;
|
||||||
pr:hasIdentifier "SD-04.01" ; pr:hasName "Customer & Outlet" ;
|
pr:hasName "Customer Structure" ;
|
||||||
|
pr:hasIdentifier "SD-04.01" ;
|
||||||
pr:owningDomain ex:DD_04 ; pr:ownedBy ex:ST_DD_04 ;
|
pr:owningDomain ex:DD_04 ; pr:ownedBy ex:ST_DD_04 ;
|
||||||
pr:belongsTo ex:DD_04 ;
|
pr:belongsTo ex:DD_04 ;
|
||||||
pr:hasStatus "PUBLISHED" ; pr:hasVersion "1.0" .
|
pr:hasStatus "PUBLISHED" ; pr:hasVersion "1.0"
|
||||||
|
.
|
||||||
ex:SD_16_01 a pr:SubDomain ;
|
ex:SD_16_01 a pr:SubDomain ;
|
||||||
pr:hasIdentifier "SD-16.01" ; pr:hasName "Currency & Exchange Rates" ;
|
pr:hasName "Currency & Exchange Rate" ;
|
||||||
|
pr:hasIdentifier "SD-16.01" ;
|
||||||
pr:owningDomain ex:DD_16 ; pr:ownedBy ex:ST_DD_16 ;
|
pr:owningDomain ex:DD_16 ; pr:ownedBy ex:ST_DD_16 ;
|
||||||
pr:belongsTo ex:DD_16 ;
|
pr:belongsTo ex:DD_16 ;
|
||||||
pr:hasStatus "PUBLISHED" ; pr:hasVersion "1.0" .
|
pr:hasStatus "PUBLISHED" ; pr:hasVersion "1.0"
|
||||||
|
.
|
||||||
ex:SD_16_02 a pr:SubDomain ;
|
ex:SD_16_02 a pr:SubDomain ;
|
||||||
pr:hasIdentifier "SD-16.02" ; pr:hasName "Marketing Entity & Fiscal Calendar" ;
|
pr:hasName "Fiscal Calendar" ;
|
||||||
|
pr:hasIdentifier "SD-16.02" ;
|
||||||
pr:owningDomain ex:DD_16 ; pr:ownedBy ex:ST_DD_16 ;
|
pr:owningDomain ex:DD_16 ; pr:ownedBy ex:ST_DD_16 ;
|
||||||
pr:belongsTo ex:DD_16 ;
|
pr:belongsTo ex:DD_16 ;
|
||||||
pr:hasStatus "PUBLISHED" ; pr:hasVersion "1.0" .
|
pr:hasStatus "PUBLISHED" ; pr:hasVersion "1.0"
|
||||||
|
.
|
||||||
ex:SD_21_01 a pr:SubDomain ;
|
ex:SD_21_01 a pr:SubDomain ;
|
||||||
pr:hasIdentifier "SD-21.01" ; pr:hasName "Calendar" ;
|
pr:hasName "Standard Calendar" ;
|
||||||
|
pr:hasIdentifier "SD-21.01" ;
|
||||||
pr:owningDomain ex:DD_21 ; pr:ownedBy ex:ST_DD_21 ;
|
pr:owningDomain ex:DD_21 ; pr:ownedBy ex:ST_DD_21 ;
|
||||||
pr:belongsTo ex:DD_21 ;
|
pr:belongsTo ex:DD_21 ;
|
||||||
pr:hasStatus "PUBLISHED" ; pr:hasVersion "1.0" .
|
pr:hasStatus "PUBLISHED" ; pr:hasVersion "1.0"
|
||||||
|
.
|
||||||
ex:SD_05_01 a pr:SubDomain ;
|
ex:SD_05_01 a pr:SubDomain ;
|
||||||
pr:hasIdentifier "SD-05.01" ; pr:hasName "Promotion" ;
|
pr:hasIdentifier "SD-05.01" ; pr:hasName "Promotion" ;
|
||||||
pr:owningDomain ex:DD_05 ; pr:ownedBy ex:ST_DD_05 ;
|
pr:owningDomain ex:DD_05 ; pr:ownedBy ex:ST_DD_05 ;
|
||||||
pr:belongsTo ex:DD_05 ;
|
pr:belongsTo ex:DD_05 ;
|
||||||
pr:hasStatus "PUBLISHED" ; pr:hasVersion "1.0" .
|
pr:hasStatus "PUBLISHED" ; pr:hasVersion "1.0" .
|
||||||
|
|
||||||
|
|
||||||
|
# --- sub-domains from the v1.1 structure proposal --------------------
|
||||||
|
# 'Customer & Outlet' and 'Marketing Entity & Fiscal Calendar' had the
|
||||||
|
# same defect as the compound Business Objects: a name joined by '&'
|
||||||
|
# has no single subject. Same rule, one level up.
|
||||||
|
ex:SD_04_02 a pr:SubDomain ;
|
||||||
|
pr:hasIdentifier "SD-04.02" ; pr:hasName "Outlet & Points of Sale" ;
|
||||||
|
pr:belongsTo ex:DD_04 ; pr:owningDomain ex:DD_04 ;
|
||||||
|
pr:arbitrationStatus "TO_ARBITRATE" ;
|
||||||
|
pr:hasStatus "DRAFT" ; pr:hasVersion "1.1" ; pr:hasSource "DGO proposal, split of a compound sub-domain" .
|
||||||
|
ex:SD_04_03 a pr:SubDomain ;
|
||||||
|
pr:hasIdentifier "SD-04.03" ; pr:hasName "Geography" ;
|
||||||
|
pr:belongsTo ex:DD_04 ; pr:owningDomain ex:DD_04 ;
|
||||||
|
pr:arbitrationStatus "TO_ARBITRATE" ;
|
||||||
|
pr:hasStatus "DRAFT" ; pr:hasVersion "1.1" ; pr:hasSource "DGO proposal, split of a compound sub-domain" .
|
||||||
|
ex:SD_16_03 a pr:SubDomain ;
|
||||||
|
pr:hasIdentifier "SD-16.03" ; pr:hasName "Organisation Structure" ;
|
||||||
|
pr:belongsTo ex:DD_16 ; pr:owningDomain ex:DD_16 ;
|
||||||
|
pr:arbitrationStatus "TO_ARBITRATE" ;
|
||||||
|
pr:hasStatus "DRAFT" ; pr:hasVersion "1.1" ; pr:hasSource "DGO proposal, split of a compound sub-domain" .
|
||||||
|
|
||||||
ex:BC_06_01_001 a pr:BusinessConcept ;
|
ex:BC_06_01_001 a pr:BusinessConcept ;
|
||||||
pr:hasIdentifier "BC-06.01-001" ; pr:hasName "Sell Out" ;
|
pr:hasIdentifier "BC-06.01-001" ; pr:hasName "Sell Out" ;
|
||||||
pr:owningDomain ex:DD_06 ; pr:ownedBy ex:ST_DD_06 ;
|
pr:owningDomain ex:DD_06 ; pr:ownedBy ex:ST_DD_06 ;
|
||||||
@@ -168,20 +197,22 @@ ex:BC_21_01_001 a pr:BusinessConcept ;
|
|||||||
# --- concepts required by the meaning XOR ---------------------------
|
# --- concepts required by the meaning XOR ---------------------------
|
||||||
# Country, Marketing Entity and Fiscal Period had Data Elements but no
|
# Country, Marketing Entity and Fiscal Period had Data Elements but no
|
||||||
# notion behind them. The rule forced them to be named.
|
# notion behind them. The rule forced them to be named.
|
||||||
ex:BC_04_01_003 a pr:BusinessConcept ;
|
ex:BC_04_03_001 a pr:BusinessConcept ;
|
||||||
pr:hasIdentifier "BC-04.01-003" ; pr:hasName "Country" ;
|
pr:hasIdentifier "BC-04.03-001" ; pr:hasName "Country" ;
|
||||||
pr:owningDomain ex:DD_04 ; pr:ownedBy ex:ST_DD_04 ;
|
pr:owningDomain ex:DD_04 ; pr:ownedBy ex:ST_DD_04 ;
|
||||||
pr:hasBusinessDefinition "A sovereign territory used as the geographic frame for retail measurement, identified by its ISO 3166 code. Distinct from Customer and Outlet: it is where they operate, not what they are." ;
|
pr:hasBusinessDefinition "A sovereign territory used as the geographic frame for retail measurement, identified by its ISO 3166 code. Distinct from Customer and Outlet: it is where they operate, not what they are." ;
|
||||||
pr:arbitrationStatus "TO_ARBITRATE" ;
|
pr:arbitrationStatus "TO_ARBITRATE" ;
|
||||||
pr:hasStatus "DRAFT" ; pr:hasVersion "1.1" ; pr:hasSource "DGO proposal, pending ratification by the owning domain" .
|
pr:hasStatus "DRAFT" ; pr:hasVersion "1.1" ; pr:hasSource "DGO proposal, pending ratification by the owning domain" .
|
||||||
ex:BC_16_01_003 a pr:BusinessConcept ;
|
ex:BC_16_03_001 a pr:BusinessConcept ;
|
||||||
pr:hasIdentifier "BC-16.01-003" ; pr:hasName "Marketing Entity" ;
|
pr:hasBusinessRule "Named Marketing Entity, not Management Entity: the element is Marketing Entity Code and the column is MARKETING_ENTITY_CD. To be confirmed by DD-16." ;
|
||||||
|
pr:hasIdentifier "BC-16.03-001" ; pr:hasName "Marketing Entity" ;
|
||||||
pr:owningDomain ex:DD_16 ; pr:ownedBy ex:ST_DD_16 ;
|
pr:owningDomain ex:DD_16 ; pr:ownedBy ex:ST_DD_16 ;
|
||||||
pr:hasBusinessDefinition "An organisational unit of the group holding commercial responsibility for a market, and the level at which financial results are consolidated." ;
|
pr:hasBusinessDefinition "An organisational unit of the group holding commercial responsibility for a market, and the level at which financial results are consolidated." ;
|
||||||
pr:arbitrationStatus "TO_ARBITRATE" ;
|
pr:arbitrationStatus "TO_ARBITRATE" ;
|
||||||
pr:hasStatus "DRAFT" ; pr:hasVersion "1.1" ; pr:hasSource "DGO proposal, pending ratification by the owning domain" .
|
pr:hasStatus "DRAFT" ; pr:hasVersion "1.1" ; pr:hasSource "DGO proposal, pending ratification by the owning domain"
|
||||||
ex:BC_16_01_004 a pr:BusinessConcept ;
|
.
|
||||||
pr:hasIdentifier "BC-16.01-004" ; pr:hasName "Fiscal Period" ;
|
ex:BC_16_02_001 a pr:BusinessConcept ;
|
||||||
|
pr:hasIdentifier "BC-16.02-001" ; pr:hasName "Fiscal Period" ;
|
||||||
pr:owningDomain ex:DD_16 ; pr:ownedBy ex:ST_DD_16 ;
|
pr:owningDomain ex:DD_16 ; pr:ownedBy ex:ST_DD_16 ;
|
||||||
pr:hasBusinessDefinition "A reporting interval of the Pernod Ricard fiscal year, which runs July to June. Distinct from Calendar Date: the fiscal frame does not align with the Gregorian one." ;
|
pr:hasBusinessDefinition "A reporting interval of the Pernod Ricard fiscal year, which runs July to June. Distinct from Calendar Date: the fiscal frame does not align with the Gregorian one." ;
|
||||||
pr:arbitrationStatus "TO_ARBITRATE" ;
|
pr:arbitrationStatus "TO_ARBITRATE" ;
|
||||||
@@ -193,8 +224,6 @@ ex:BO_06_01_001 a pr:BusinessObject ;
|
|||||||
pr:belongsTo ex:SD_06_01 ; pr:monitoredBy ex:ST_DD_06 ;
|
pr:belongsTo ex:SD_06_01 ; pr:monitoredBy ex:ST_DD_06 ;
|
||||||
pr:aboutConcept ex:BC_06_01_001 ;
|
pr:aboutConcept ex:BC_06_01_001 ;
|
||||||
pr:usesConcept ex:BC_06_01_003 , ex:BC_05_01_001 ;
|
pr:usesConcept ex:BC_06_01_003 , ex:BC_05_01_001 ;
|
||||||
pr:aboutConcept ex:BC_06_01_001 ;
|
|
||||||
pr:usesConcept ex:BC_06_01_003 , ex:BC_05_01_001 ;
|
|
||||||
pr:hasMetric ex:M_06_01_001 ;
|
pr:hasMetric ex:M_06_01_001 ;
|
||||||
pr:hasStatus "DRAFT" ; pr:hasVersion "0.6" ; pr:hasSource "SODH Gold / F_SELL_OUT" .
|
pr:hasStatus "DRAFT" ; pr:hasVersion "0.6" ; pr:hasSource "SODH Gold / F_SELL_OUT" .
|
||||||
ex:BO_06_01_002 a pr:BusinessObject ;
|
ex:BO_06_01_002 a pr:BusinessObject ;
|
||||||
@@ -203,8 +232,6 @@ ex:BO_06_01_002 a pr:BusinessObject ;
|
|||||||
pr:belongsTo ex:SD_06_01 ; pr:monitoredBy ex:ST_DD_06 ;
|
pr:belongsTo ex:SD_06_01 ; pr:monitoredBy ex:ST_DD_06 ;
|
||||||
pr:aboutConcept ex:BC_06_01_001 ;
|
pr:aboutConcept ex:BC_06_01_001 ;
|
||||||
pr:usesConcept ex:BC_06_01_003 , ex:BC_05_01_001 , ex:BC_16_01_001 ;
|
pr:usesConcept ex:BC_06_01_003 , ex:BC_05_01_001 , ex:BC_16_01_001 ;
|
||||||
pr:aboutConcept ex:BC_06_01_001 ;
|
|
||||||
pr:usesConcept ex:BC_06_01_003 , ex:BC_05_01_001 , ex:BC_16_01_001 ;
|
|
||||||
pr:hasMetric ex:M_06_01_002 ;
|
pr:hasMetric ex:M_06_01_002 ;
|
||||||
pr:hasStatus "DRAFT" ; pr:hasVersion "0.6" ; pr:hasSource "SODH Gold / F_SELL_OUT" .
|
pr:hasStatus "DRAFT" ; pr:hasVersion "0.6" ; pr:hasSource "SODH Gold / F_SELL_OUT" .
|
||||||
ex:BO_06_01_003 a pr:BusinessObject ;
|
ex:BO_06_01_003 a pr:BusinessObject ;
|
||||||
@@ -213,8 +240,6 @@ ex:BO_06_01_003 a pr:BusinessObject ;
|
|||||||
pr:belongsTo ex:SD_06_01 ; pr:monitoredBy ex:ST_DD_06 ;
|
pr:belongsTo ex:SD_06_01 ; pr:monitoredBy ex:ST_DD_06 ;
|
||||||
pr:aboutConcept ex:BC_06_01_004 ;
|
pr:aboutConcept ex:BC_06_01_004 ;
|
||||||
pr:usesConcept ex:BC_06_01_003 ;
|
pr:usesConcept ex:BC_06_01_003 ;
|
||||||
pr:aboutConcept ex:BC_06_01_004 ;
|
|
||||||
pr:usesConcept ex:BC_06_01_003 ;
|
|
||||||
pr:hasMetric ex:M_06_01_003 , ex:M_06_01_004 , ex:M_06_01_005 ;
|
pr:hasMetric ex:M_06_01_003 , ex:M_06_01_004 , ex:M_06_01_005 ;
|
||||||
pr:hasStatus "DRAFT" ; pr:hasVersion "0.6" ; pr:hasSource "SODH Gold / F_SELL_OUT_DISTRIBUTION" .
|
pr:hasStatus "DRAFT" ; pr:hasVersion "0.6" ; pr:hasSource "SODH Gold / F_SELL_OUT_DISTRIBUTION" .
|
||||||
ex:BO_06_01_004 a pr:BusinessObject ;
|
ex:BO_06_01_004 a pr:BusinessObject ;
|
||||||
@@ -223,8 +248,6 @@ ex:BO_06_01_004 a pr:BusinessObject ;
|
|||||||
pr:belongsTo ex:SD_06_01 ; pr:monitoredBy ex:ST_DD_06 ;
|
pr:belongsTo ex:SD_06_01 ; pr:monitoredBy ex:ST_DD_06 ;
|
||||||
pr:aboutConcept ex:BC_06_01_002 ;
|
pr:aboutConcept ex:BC_06_01_002 ;
|
||||||
pr:usesConcept ex:BC_06_01_001 , ex:BC_06_01_003 ;
|
pr:usesConcept ex:BC_06_01_001 , ex:BC_06_01_003 ;
|
||||||
pr:aboutConcept ex:BC_06_01_002 ;
|
|
||||||
pr:usesConcept ex:BC_06_01_001 , ex:BC_06_01_003 ;
|
|
||||||
pr:hasMetric ex:M_06_01_006 , ex:M_06_01_007 , ex:M_06_01_008 ;
|
pr:hasMetric ex:M_06_01_006 , ex:M_06_01_007 , ex:M_06_01_008 ;
|
||||||
pr:hasStatus "DRAFT" ; pr:hasVersion "0.6" ; pr:hasSource "SODH Gold / F_SELL_OUT" .
|
pr:hasStatus "DRAFT" ; pr:hasVersion "0.6" ; pr:hasSource "SODH Gold / F_SELL_OUT" .
|
||||||
ex:BO_06_01_005 a pr:BusinessObject ;
|
ex:BO_06_01_005 a pr:BusinessObject ;
|
||||||
@@ -233,64 +256,95 @@ ex:BO_06_01_005 a pr:BusinessObject ;
|
|||||||
pr:belongsTo ex:SD_06_01 ; pr:monitoredBy ex:ST_DD_06 ;
|
pr:belongsTo ex:SD_06_01 ; pr:monitoredBy ex:ST_DD_06 ;
|
||||||
pr:aboutConcept ex:BC_06_01_005 ;
|
pr:aboutConcept ex:BC_06_01_005 ;
|
||||||
pr:usesConcept ex:BC_06_01_001 , ex:BC_05_01_001 ;
|
pr:usesConcept ex:BC_06_01_001 , ex:BC_05_01_001 ;
|
||||||
pr:aboutConcept ex:BC_06_01_005 ;
|
|
||||||
pr:usesConcept ex:BC_06_01_001 , ex:BC_05_01_001 ;
|
|
||||||
pr:hasMetric ex:M_06_01_009 , ex:M_06_01_010 ;
|
pr:hasMetric ex:M_06_01_009 , ex:M_06_01_010 ;
|
||||||
pr:hasStatus "DRAFT" ; pr:hasVersion "0.6" ; pr:hasSource "SODH Gold / F_SELL_OUT_BASELINE" .
|
pr:hasStatus "DRAFT" ; pr:hasVersion "0.6" ; pr:hasSource "SODH Gold / F_SELL_OUT_BASELINE" .
|
||||||
ex:BO_10_01_001 a pr:BusinessObject ;
|
ex:BO_10_01_001 a pr:BusinessObject ;
|
||||||
pr:hasIdentifier "BO-10.01-001" ; pr:hasName "Product Structure" ;
|
|
||||||
pr:owningDomain ex:DD_10 ; pr:ownedBy ex:ST_DD_10 ;
|
|
||||||
pr:belongsTo ex:SD_10_01 ; pr:monitoredBy ex:ST_DD_10 ;
|
|
||||||
pr:aboutConcept ex:BC_10_01_001 ;
|
pr:aboutConcept ex:BC_10_01_001 ;
|
||||||
pr:aboutConcept ex:BC_10_01_001 ;
|
pr:belongsTo ex:SD_10_01 ;
|
||||||
pr:hasStatus "DRAFT" ; pr:hasVersion "0.6" ; pr:hasSource "MDM Product -> SODH [concepts TBC by DD-10]" .
|
pr:hasName "Product Hierarchy" ;
|
||||||
|
pr:hasIdentifier "BO-10.01-001" ;
|
||||||
|
pr:owningDomain ex:DD_10 ; pr:ownedBy ex:ST_DD_10 ; pr:monitoredBy ex:ST_DD_10 ;
|
||||||
|
pr:hasStatus "DRAFT" ; pr:hasVersion "0.6" ; pr:hasSource "MDM Product -> SODH [concepts TBC by DD-10]"
|
||||||
|
.
|
||||||
ex:BO_04_01_001 a pr:BusinessObject ;
|
ex:BO_04_01_001 a pr:BusinessObject ;
|
||||||
pr:hasIdentifier "BO-04.01-001" ; pr:hasName "Customer" ;
|
|
||||||
pr:owningDomain ex:DD_04 ; pr:ownedBy ex:ST_DD_04 ;
|
|
||||||
pr:belongsTo ex:SD_04_01 ; pr:monitoredBy ex:ST_DD_04 ;
|
|
||||||
pr:aboutConcept ex:BC_04_01_001 ;
|
pr:aboutConcept ex:BC_04_01_001 ;
|
||||||
pr:aboutConcept ex:BC_04_01_001 ;
|
pr:belongsTo ex:SD_04_01 ;
|
||||||
pr:hasStatus "DRAFT" ; pr:hasVersion "0.6" ; pr:hasSource "MDM -> SODH [split proposed, subject arbitrated 2026-07-27]" .
|
pr:hasName "Customer Hierarchy" ;
|
||||||
|
pr:hasIdentifier "BO-04.01-001" ;
|
||||||
|
pr:owningDomain ex:DD_04 ; pr:ownedBy ex:ST_DD_04 ; pr:monitoredBy ex:ST_DD_04 ;
|
||||||
|
pr:hasStatus "DRAFT" ; pr:hasVersion "0.6" ; pr:hasSource "MDM -> SODH [split proposed, subject arbitrated 2026-07-27]"
|
||||||
|
.
|
||||||
ex:BO_16_01_001 a pr:BusinessObject ;
|
ex:BO_16_01_001 a pr:BusinessObject ;
|
||||||
|
pr:aboutConcept ex:BC_16_01_001 ;
|
||||||
|
pr:belongsTo ex:SD_16_01 ;
|
||||||
pr:hasIdentifier "BO-16.01-001" ; pr:hasName "Currency" ;
|
pr:hasIdentifier "BO-16.01-001" ; pr:hasName "Currency" ;
|
||||||
pr:owningDomain ex:DD_16 ; pr:ownedBy ex:ST_DD_16 ;
|
pr:owningDomain ex:DD_16 ; pr:ownedBy ex:ST_DD_16 ; pr:monitoredBy ex:ST_DD_16 ;
|
||||||
pr:belongsTo ex:SD_16_01 ; pr:monitoredBy ex:ST_DD_16 ;
|
pr:hasStatus "DRAFT" ; pr:hasVersion "0.6" ; pr:hasSource "MDM -> SODH [split proposed, subject arbitrated 2026-07-27]"
|
||||||
pr:aboutConcept ex:BC_16_01_001 ;
|
.
|
||||||
pr:aboutConcept ex:BC_16_01_001 ;
|
|
||||||
pr:hasStatus "DRAFT" ; pr:hasVersion "0.6" ; pr:hasSource "MDM -> SODH [split proposed, subject arbitrated 2026-07-27]" .
|
|
||||||
ex:BO_21_01_001 a pr:BusinessObject ;
|
ex:BO_21_01_001 a pr:BusinessObject ;
|
||||||
pr:hasIdentifier "BO-21.01-001" ; pr:hasName "Calendar" ;
|
|
||||||
pr:owningDomain ex:DD_21 ; pr:ownedBy ex:ST_DD_21 ;
|
|
||||||
pr:belongsTo ex:SD_21_01 ; pr:monitoredBy ex:ST_DD_21 ;
|
|
||||||
pr:aboutConcept ex:BC_21_01_001 ;
|
pr:aboutConcept ex:BC_21_01_001 ;
|
||||||
pr:aboutConcept ex:BC_21_01_001 ;
|
pr:belongsTo ex:SD_21_01 ;
|
||||||
pr:hasStatus "DRAFT" ; pr:hasVersion "0.6" ; pr:hasSource "Standard Calendar -> SODH [concepts TBC by DD-21]" .
|
pr:hasName "Analysis Period" ;
|
||||||
|
pr:hasIdentifier "BO-21.01-001" ;
|
||||||
|
pr:owningDomain ex:DD_21 ; pr:ownedBy ex:ST_DD_21 ; pr:monitoredBy ex:ST_DD_21 ;
|
||||||
|
pr:hasStatus "DRAFT" ; pr:hasVersion "0.6" ; pr:hasSource "Standard Calendar -> SODH [concepts TBC by DD-21]"
|
||||||
|
.
|
||||||
ex:BO_05_01_001 a pr:BusinessObject ;
|
ex:BO_05_01_001 a pr:BusinessObject ;
|
||||||
pr:hasIdentifier "BO-05.01-001" ; pr:hasName "Promotion Type" ;
|
pr:hasIdentifier "BO-05.01-001" ; pr:hasName "Promotion Type" ;
|
||||||
pr:owningDomain ex:DD_05 ; pr:ownedBy ex:ST_DD_05 ;
|
pr:owningDomain ex:DD_05 ; pr:ownedBy ex:ST_DD_05 ;
|
||||||
pr:belongsTo ex:SD_05_01 ; pr:monitoredBy ex:ST_DD_05 ;
|
pr:belongsTo ex:SD_05_01 ; pr:monitoredBy ex:ST_DD_05 ;
|
||||||
pr:aboutConcept ex:BC_05_01_001 ;
|
pr:aboutConcept ex:BC_05_01_001 ;
|
||||||
pr:aboutConcept ex:BC_05_01_001 ;
|
|
||||||
pr:hasStatus "DRAFT" ; pr:hasVersion "0.6" ; pr:hasSource "Sales Activation -> SODH [concepts TBC by DD-05]" .
|
pr:hasStatus "DRAFT" ; pr:hasVersion "0.6" ; pr:hasSource "Sales Activation -> SODH [concepts TBC by DD-05]" .
|
||||||
|
|
||||||
|
|
||||||
# --- Business Objects from the v1.1 splits ---------------------------
|
# --- Business Objects from the v1.1 splits ---------------------------
|
||||||
# 'Customer & Outlet' and 'Currency & Exchange Rates' had no single
|
# 'Customer & Outlet' and 'Currency & Exchange Rates' had no single
|
||||||
# subject. Split proposed to DD-04 and DD-16, hence TO_ARBITRATE.
|
# subject. Split proposed to DD-04 and DD-16, hence TO_ARBITRATE.
|
||||||
ex:BO_04_01_002 a pr:BusinessObject ;
|
ex:BO_04_02_001 a pr:BusinessObject ;
|
||||||
pr:hasIdentifier "BO-04.01-002" ; pr:hasName "Outlet" ;
|
|
||||||
pr:owningDomain ex:DD_04 ; pr:ownedBy ex:ST_DD_04 ;
|
|
||||||
pr:belongsTo ex:SD_04_01 ; pr:monitoredBy ex:ST_DD_04 ;
|
|
||||||
pr:aboutConcept ex:BC_04_01_002 ;
|
pr:aboutConcept ex:BC_04_01_002 ;
|
||||||
|
pr:belongsTo ex:SD_04_02 ;
|
||||||
|
pr:hasIdentifier "BO-04.02-001" ; pr:hasName "Outlet" ;
|
||||||
|
pr:owningDomain ex:DD_04 ; pr:ownedBy ex:ST_DD_04 ; pr:monitoredBy ex:ST_DD_04 ;
|
||||||
pr:arbitrationStatus "TO_ARBITRATE" ;
|
pr:arbitrationStatus "TO_ARBITRATE" ;
|
||||||
pr:hasStatus "DRAFT" ; pr:hasVersion "1.1" ; pr:hasSource "MDM Customer -> SODH [split from BO-04.01-001, proposed to DD-04]" .
|
pr:hasStatus "DRAFT" ; pr:hasVersion "1.1" ; pr:hasSource "MDM Customer -> SODH [split from BO-04.01-001, proposed to DD-04]"
|
||||||
|
.
|
||||||
ex:BO_16_01_002 a pr:BusinessObject ;
|
ex:BO_16_01_002 a pr:BusinessObject ;
|
||||||
pr:hasIdentifier "BO-16.01-002" ; pr:hasName "Exchange Rate" ;
|
|
||||||
pr:owningDomain ex:DD_16 ; pr:ownedBy ex:ST_DD_16 ;
|
|
||||||
pr:belongsTo ex:SD_16_01 ; pr:monitoredBy ex:ST_DD_16 ;
|
|
||||||
pr:aboutConcept ex:BC_16_01_002 ;
|
pr:aboutConcept ex:BC_16_01_002 ;
|
||||||
|
pr:belongsTo ex:SD_16_01 ;
|
||||||
|
pr:hasIdentifier "BO-16.01-002" ; pr:hasName "Exchange Rate" ;
|
||||||
|
pr:owningDomain ex:DD_16 ; pr:ownedBy ex:ST_DD_16 ; pr:monitoredBy ex:ST_DD_16 ;
|
||||||
pr:arbitrationStatus "TO_ARBITRATE" ;
|
pr:arbitrationStatus "TO_ARBITRATE" ;
|
||||||
pr:hasStatus "DRAFT" ; pr:hasVersion "1.1" ; pr:hasSource "Group Finance -> SODH [split from BO-16.01-001, proposed to DD-16]" .
|
pr:hasStatus "DRAFT" ; pr:hasVersion "1.1" ; pr:hasSource "Group Finance -> SODH [split from BO-16.01-001, proposed to DD-16]"
|
||||||
|
.
|
||||||
|
|
||||||
|
|
||||||
|
# --- business objects for the borrowed concepts -----------------------
|
||||||
|
# Country, Fiscal Period and Marketing Entity had a concept but nothing
|
||||||
|
# to hold it. Proposed to DD-04 and DD-16, hence TO_ARBITRATE.
|
||||||
|
ex:BO_04_03_001 a pr:BusinessObject ;
|
||||||
|
pr:aboutConcept ex:BC_04_03_001 ;
|
||||||
|
pr:belongsTo ex:SD_04_03 ;
|
||||||
|
pr:hasIdentifier "BO-04.03-001" ; pr:hasName "Country" ;
|
||||||
|
pr:owningDomain ex:DD_04 ; pr:ownedBy ex:ST_DD_04 ; pr:monitoredBy ex:ST_DD_04 ;
|
||||||
|
pr:arbitrationStatus "TO_ARBITRATE" ;
|
||||||
|
pr:hasStatus "DRAFT" ; pr:hasVersion "1.1" ; pr:hasSource "DGO proposal, pending ratification by the owning domain"
|
||||||
|
.
|
||||||
|
ex:BO_16_02_001 a pr:BusinessObject ;
|
||||||
|
pr:aboutConcept ex:BC_16_02_001 ;
|
||||||
|
pr:belongsTo ex:SD_16_02 ;
|
||||||
|
pr:hasIdentifier "BO-16.02-001" ; pr:hasName "Fiscal Period" ;
|
||||||
|
pr:owningDomain ex:DD_16 ; pr:ownedBy ex:ST_DD_16 ; pr:monitoredBy ex:ST_DD_16 ;
|
||||||
|
pr:arbitrationStatus "TO_ARBITRATE" ;
|
||||||
|
pr:hasStatus "DRAFT" ; pr:hasVersion "1.1" ; pr:hasSource "DGO proposal, pending ratification by the owning domain"
|
||||||
|
.
|
||||||
|
ex:BO_16_03_001 a pr:BusinessObject ;
|
||||||
|
pr:aboutConcept ex:BC_16_03_001 ;
|
||||||
|
pr:belongsTo ex:SD_16_03 ;
|
||||||
|
pr:hasIdentifier "BO-16.03-001" ; pr:hasName "Marketing Entity" ;
|
||||||
|
pr:owningDomain ex:DD_16 ; pr:ownedBy ex:ST_DD_16 ; pr:monitoredBy ex:ST_DD_16 ;
|
||||||
|
pr:arbitrationStatus "TO_ARBITRATE" ;
|
||||||
|
pr:hasStatus "DRAFT" ; pr:hasVersion "1.1" ; pr:hasSource "DGO proposal, pending ratification by the owning domain"
|
||||||
|
.
|
||||||
|
|
||||||
ex:DO_06_01_001 a pr:DataObject ;
|
ex:DO_06_01_001 a pr:DataObject ;
|
||||||
pr:hasIdentifier "DO-06.01-001" ; pr:hasName "Sell Out Volume Dataset" ;
|
pr:hasIdentifier "DO-06.01-001" ; pr:hasName "Sell Out Volume Dataset" ;
|
||||||
@@ -585,14 +639,14 @@ ex:DE_04_01_0008 a pr:DataElement ;
|
|||||||
pr:owningDomain ex:DD_04 ;
|
pr:owningDomain ex:DD_04 ;
|
||||||
pr:hasFormat "STRING(2)" ;
|
pr:hasFormat "STRING(2)" ;
|
||||||
pr:physicalName "COUNTRY_CD" ;
|
pr:physicalName "COUNTRY_CD" ;
|
||||||
pr:represents ex:BC_04_01_003 ;
|
pr:represents ex:BC_04_03_001 ;
|
||||||
pr:hasStatus "DRAFT" ; pr:hasVersion "1.1" ; pr:hasSource "MDM Customer" .
|
pr:hasStatus "DRAFT" ; pr:hasVersion "1.1" ; pr:hasSource "MDM Customer" .
|
||||||
ex:DE_04_01_0009 a pr:DataElement ;
|
ex:DE_04_01_0009 a pr:DataElement ;
|
||||||
pr:hasIdentifier "DE-04.01-0009" ; pr:hasName "Country Name" ;
|
pr:hasIdentifier "DE-04.01-0009" ; pr:hasName "Country Name" ;
|
||||||
pr:owningDomain ex:DD_04 ;
|
pr:owningDomain ex:DD_04 ;
|
||||||
pr:hasFormat "STRING(100)" ;
|
pr:hasFormat "STRING(100)" ;
|
||||||
pr:physicalName "COUNTRY_NM" ;
|
pr:physicalName "COUNTRY_NM" ;
|
||||||
pr:represents ex:BC_04_01_003 ;
|
pr:represents ex:BC_04_03_001 ;
|
||||||
pr:hasStatus "DRAFT" ; pr:hasVersion "1.1" ; pr:hasSource "MDM Customer" .
|
pr:hasStatus "DRAFT" ; pr:hasVersion "1.1" ; pr:hasSource "MDM Customer" .
|
||||||
ex:DE_04_01_0010 a pr:DataElement ;
|
ex:DE_04_01_0010 a pr:DataElement ;
|
||||||
pr:hasIdentifier "DE-04.01-0010" ; pr:hasName "Point of Sale Count (Count)" ;
|
pr:hasIdentifier "DE-04.01-0010" ; pr:hasName "Point of Sale Count (Count)" ;
|
||||||
@@ -630,21 +684,21 @@ ex:DE_16_02_0001 a pr:DataElement ;
|
|||||||
pr:owningDomain ex:DD_16 ;
|
pr:owningDomain ex:DD_16 ;
|
||||||
pr:hasFormat "STRING(10)" ;
|
pr:hasFormat "STRING(10)" ;
|
||||||
pr:physicalName "MARKETING_ENTITY_CD" ;
|
pr:physicalName "MARKETING_ENTITY_CD" ;
|
||||||
pr:represents ex:BC_16_01_003 ;
|
pr:represents ex:BC_16_03_001 ;
|
||||||
pr:hasStatus "DRAFT" ; pr:hasVersion "1.1" ; pr:hasSource "Group Finance" .
|
pr:hasStatus "DRAFT" ; pr:hasVersion "1.1" ; pr:hasSource "Group Finance" .
|
||||||
ex:DE_16_02_0002 a pr:DataElement ;
|
ex:DE_16_02_0002 a pr:DataElement ;
|
||||||
pr:hasIdentifier "DE-16.02-0002" ; pr:hasName "Fiscal Period Code" ;
|
pr:hasIdentifier "DE-16.02-0002" ; pr:hasName "Fiscal Period Code" ;
|
||||||
pr:owningDomain ex:DD_16 ;
|
pr:owningDomain ex:DD_16 ;
|
||||||
pr:hasFormat "STRING(10)" ;
|
pr:hasFormat "STRING(10)" ;
|
||||||
pr:physicalName "PR_FISCAL_PERIOD_CD" ;
|
pr:physicalName "PR_FISCAL_PERIOD_CD" ;
|
||||||
pr:represents ex:BC_16_01_004 ;
|
pr:represents ex:BC_16_02_001 ;
|
||||||
pr:hasStatus "DRAFT" ; pr:hasVersion "1.1" ; pr:hasSource "Group Finance" .
|
pr:hasStatus "DRAFT" ; pr:hasVersion "1.1" ; pr:hasSource "Group Finance" .
|
||||||
ex:DE_16_02_0003 a pr:DataElement ;
|
ex:DE_16_02_0003 a pr:DataElement ;
|
||||||
pr:hasIdentifier "DE-16.02-0003" ; pr:hasName "Fiscal Quarter Code" ;
|
pr:hasIdentifier "DE-16.02-0003" ; pr:hasName "Fiscal Quarter Code" ;
|
||||||
pr:owningDomain ex:DD_16 ;
|
pr:owningDomain ex:DD_16 ;
|
||||||
pr:hasFormat "STRING(10)" ;
|
pr:hasFormat "STRING(10)" ;
|
||||||
pr:physicalName "PR_FISCAL_QUARTER_CD" ;
|
pr:physicalName "PR_FISCAL_QUARTER_CD" ;
|
||||||
pr:represents ex:BC_16_01_004 ;
|
pr:represents ex:BC_16_02_001 ;
|
||||||
pr:hasStatus "DRAFT" ; pr:hasVersion "1.1" ; pr:hasSource "Group Finance" .
|
pr:hasStatus "DRAFT" ; pr:hasVersion "1.1" ; pr:hasSource "Group Finance" .
|
||||||
ex:DE_21_01_0001 a pr:DataElement ;
|
ex:DE_21_01_0001 a pr:DataElement ;
|
||||||
pr:hasIdentifier "DE-21.01-0001" ; pr:hasName "Calendar Date" ;
|
pr:hasIdentifier "DE-21.01-0001" ; pr:hasName "Calendar Date" ;
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ NEW_CONCEPTS = [
|
|||||||
|
|
||||||
# ------------------------------------------------------------------- new object
|
# ------------------------------------------------------------------- new object
|
||||||
NEW_OBJECTS = [
|
NEW_OBJECTS = [
|
||||||
("ex:BO_04_01_002", "BO-04.01-002", "Outlet", "ex:DD_04", "ex:ST_DD_04", "ex:SD_04_01",
|
("ex:BO_04_02_001", "BO-04.02-001", "Outlet", "ex:DD_04", "ex:ST_DD_04", "ex:SD_04_02",
|
||||||
"ex:BC_04_01_002", [], "MDM Customer -> SODH [split from BO-04.01-001, proposed to DD-04]"),
|
"ex:BC_04_01_002", [], "MDM Customer -> SODH [split from BO-04.01-001, proposed to DD-04]"),
|
||||||
("ex:BO_16_01_002", "BO-16.01-002", "Exchange Rate", "ex:DD_16", "ex:ST_DD_16", "ex:SD_16_01",
|
("ex:BO_16_01_002", "BO-16.01-002", "Exchange Rate", "ex:DD_16", "ex:ST_DD_16", "ex:SD_16_01",
|
||||||
"ex:BC_16_01_002", [], "Group Finance -> SODH [split from BO-16.01-001, proposed to DD-16]"),
|
"ex:BC_16_01_002", [], "Group Finance -> SODH [split from BO-16.01-001, proposed to DD-16]"),
|
||||||
@@ -176,7 +176,13 @@ def main():
|
|||||||
continue
|
continue
|
||||||
block = m.group(1)
|
block = m.group(1)
|
||||||
|
|
||||||
|
# strip what a previous run may have written, so re-running is a no-op.
|
||||||
|
# Duplicated clauses carrying the SAME value merge under RDF set
|
||||||
|
# semantics: the graph stays valid and SHACL sees nothing, while the
|
||||||
|
# file quietly grows a redundant line on every pass.
|
||||||
new_block = re.sub(r'[ \t]*pr:composedOf\s+[^";]*;[ \t]*\n', '', block)
|
new_block = re.sub(r'[ \t]*pr:composedOf\s+[^";]*;[ \t]*\n', '', block)
|
||||||
|
new_block = re.sub(r'[ \t]*pr:(aboutConcept|usesConcept)\s+[^";]*;[ \t]*\n',
|
||||||
|
'', new_block)
|
||||||
clause = ' pr:aboutConcept %s ;\n' % about
|
clause = ' pr:aboutConcept %s ;\n' % about
|
||||||
if uses:
|
if uses:
|
||||||
clause += ' pr:usesConcept %s ;\n' % " , ".join(uses)
|
clause += ' pr:usesConcept %s ;\n' % " , ".join(uses)
|
||||||
@@ -244,6 +250,13 @@ def main():
|
|||||||
for line in report:
|
for line in report:
|
||||||
print(" " + line)
|
print(" " + line)
|
||||||
print("=" * W)
|
print("=" * W)
|
||||||
|
doubled = []
|
||||||
|
for m in re.finditer(r'^(ex:\w+) a pr:\w+ ;(.*?)\.\s*\n', text, re.S | re.M):
|
||||||
|
for prop in ("pr:hasName", "pr:aboutConcept", "pr:belongsTo"):
|
||||||
|
if len(re.findall(r'(?<![\w:])%s\s' % re.escape(prop), m.group(2))) > 1:
|
||||||
|
doubled.append("%s/%s" % (m.group(1), prop))
|
||||||
|
print(" duplicated single-valued properties: %s"
|
||||||
|
% (", ".join(doubled) if doubled else "none"))
|
||||||
bo = len(re.findall(r'a pr:BusinessObject', text))
|
bo = len(re.findall(r'a pr:BusinessObject', text))
|
||||||
bc = len(re.findall(r'a pr:BusinessConcept', text))
|
bc = len(re.findall(r'a pr:BusinessConcept', text))
|
||||||
print(" Business Objects %d | Business Concepts %d | composedOf left %d"
|
print(" Business Objects %d | Business Concepts %d | composedOf left %d"
|
||||||
|
|||||||
@@ -71,14 +71,14 @@ DE_CONCEPT_EXACT = {
|
|||||||
"DE-04.01-0006": "ex:BC_04_01_002", # Outlet Type -> Outlet
|
"DE-04.01-0006": "ex:BC_04_01_002", # Outlet Type -> Outlet
|
||||||
"DE-04.01-0007": "ex:BC_04_01_002", # Channel -> Outlet
|
"DE-04.01-0007": "ex:BC_04_01_002", # Channel -> Outlet
|
||||||
"DE-04.01-0010": "ex:BC_04_01_002", # Point of Sale Count -> Outlet
|
"DE-04.01-0010": "ex:BC_04_01_002", # Point of Sale Count -> Outlet
|
||||||
"DE-04.01-0008": "ex:BC_04_01_003", # Country Code -> Country
|
"DE-04.01-0008": "ex:BC_04_03_001", # Country Code -> Country
|
||||||
"DE-04.01-0009": "ex:BC_04_01_003", # Country Name -> Country
|
"DE-04.01-0009": "ex:BC_04_03_001", # Country Name -> Country
|
||||||
"DE-16.01-0001": "ex:BC_16_01_001", # Currency Code -> Currency
|
"DE-16.01-0001": "ex:BC_16_01_001", # Currency Code -> Currency
|
||||||
"DE-16.01-0002": "ex:BC_16_01_002", # FX Rate to-Euro -> Exchange Rate
|
"DE-16.01-0002": "ex:BC_16_01_002", # FX Rate to-Euro -> Exchange Rate
|
||||||
"DE-16.01-0003": "ex:BC_16_01_002", # FX Rate to-USD -> Exchange Rate
|
"DE-16.01-0003": "ex:BC_16_01_002", # FX Rate to-USD -> Exchange Rate
|
||||||
"DE-16.02-0001": "ex:BC_16_01_003", # Marketing Entity -> Marketing Entity
|
"DE-16.02-0001": "ex:BC_16_03_001", # Marketing Entity -> Marketing Entity
|
||||||
"DE-16.02-0002": "ex:BC_16_01_004", # Fiscal Period Code -> Fiscal Period
|
"DE-16.02-0002": "ex:BC_16_02_001", # Fiscal Period Code -> Fiscal Period
|
||||||
"DE-16.02-0003": "ex:BC_16_01_004", # Fiscal Quarter Code -> Fiscal Period
|
"DE-16.02-0003": "ex:BC_16_02_001", # Fiscal Quarter Code -> Fiscal Period
|
||||||
}
|
}
|
||||||
DE_CONCEPT_PREFIX = [
|
DE_CONCEPT_PREFIX = [
|
||||||
("DE-10.01", "ex:BC_10_01_001"), # product hierarchy -> Product
|
("DE-10.01", "ex:BC_10_01_001"), # product hierarchy -> Product
|
||||||
@@ -89,14 +89,17 @@ DE_CONCEPT_PREFIX = [
|
|||||||
|
|
||||||
# ---- concepts the XOR forces us to name ------------------------------------
|
# ---- concepts the XOR forces us to name ------------------------------------
|
||||||
NEW_CONCEPTS = [
|
NEW_CONCEPTS = [
|
||||||
("ex:BC_04_01_003", "BC-04.01-003", "Country", "ex:DD_04", "ex:ST_DD_04",
|
# Final identifiers from the outset. Creating them under one id and
|
||||||
|
# renumbering them later broke idempotence: the second run no longer found
|
||||||
|
# the original id and recreated the concept alongside the renamed one.
|
||||||
|
("ex:BC_04_03_001", "BC-04.03-001", "Country", "ex:DD_04", "ex:ST_DD_04",
|
||||||
"A sovereign territory used as the geographic frame for retail measurement, "
|
"A sovereign territory used as the geographic frame for retail measurement, "
|
||||||
"identified by its ISO 3166 code. Distinct from Customer and Outlet: it is where "
|
"identified by its ISO 3166 code. Distinct from Customer and Outlet: it is where "
|
||||||
"they operate, not what they are."),
|
"they operate, not what they are."),
|
||||||
("ex:BC_16_01_003", "BC-16.01-003", "Marketing Entity", "ex:DD_16", "ex:ST_DD_16",
|
("ex:BC_16_03_001", "BC-16.03-001", "Marketing Entity", "ex:DD_16", "ex:ST_DD_16",
|
||||||
"An organisational unit of the group holding commercial responsibility for a market, "
|
"An organisational unit of the group holding commercial responsibility for a market, "
|
||||||
"and the level at which financial results are consolidated."),
|
"and the level at which financial results are consolidated."),
|
||||||
("ex:BC_16_01_004", "BC-16.01-004", "Fiscal Period", "ex:DD_16", "ex:ST_DD_16",
|
("ex:BC_16_02_001", "BC-16.02-001", "Fiscal Period", "ex:DD_16", "ex:ST_DD_16",
|
||||||
"A reporting interval of the Pernod Ricard fiscal year, which runs July to June. "
|
"A reporting interval of the Pernod Ricard fiscal year, which runs July to June. "
|
||||||
"Distinct from Calendar Date: the fiscal frame does not align with the Gregorian one."),
|
"Distinct from Calendar Date: the fiscal frame does not align with the Gregorian one."),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -0,0 +1,261 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
SODH - structure proposed for the borrowed domains
|
||||||
|
===================================================
|
||||||
|
Gives the nine TO_ARBITRATE concepts a home: a Business Object and a
|
||||||
|
Sub-Domain each, per the structure arbitrated with Bastien on 2026-07-27.
|
||||||
|
|
||||||
|
USAGE
|
||||||
|
python3 scripts/apply_structure_sodh.py # dry run
|
||||||
|
python3 scripts/apply_structure_sodh.py --apply # rewrite, .bak kept
|
||||||
|
|
||||||
|
STILL A PROPOSAL
|
||||||
|
Everything created here stays TO_ARBITRATE. DD-04, DD-10, DD-16 and DD-21
|
||||||
|
own these perimeters; the DGO is proposing a coherent structure, not
|
||||||
|
ratifying one. Replacing padding with an equally unilateral structure
|
||||||
|
would trade one problem for a tidier version of the same problem. The flag
|
||||||
|
comes off when Helene Puchot, Anas El Kesri and Gaelle Seret say so, and
|
||||||
|
OW-007 blocks publication until then.
|
||||||
|
|
||||||
|
IDENTIFIERS ARE FINAL FROM CREATION
|
||||||
|
Identifiers encode the sub-domain (BO-04.02-001 lives in SD-04.02), so the
|
||||||
|
upstream scripts now mint them correctly rather than having this one
|
||||||
|
renumber afterwards. Renaming after creation broke idempotence: the script
|
||||||
|
that created an object stopped recognising its own output and made a second
|
||||||
|
copy on the next run.
|
||||||
|
|
||||||
|
COMPOUND SUB-DOMAINS SPLIT TOO
|
||||||
|
'Customer & Outlet' and 'Marketing Entity & Fiscal Calendar' have the same
|
||||||
|
defect as the Business Objects that were split earlier: a name joined by
|
||||||
|
'&' has no single subject. Same rule, one level up.
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import shutil
|
||||||
|
import sys
|
||||||
|
|
||||||
|
REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
TTL = os.path.join(REPO, "instances", "sodh.ttl")
|
||||||
|
W = 78
|
||||||
|
|
||||||
|
# No IRI renaming here. Objects are created with their final identifiers by
|
||||||
|
# the upstream scripts: renumbering after the fact broke idempotence, because
|
||||||
|
# the creating script then no longer recognised its own output.
|
||||||
|
# ---- sub-domains ----------------------------------------------------------
|
||||||
|
SD_RENAME = {
|
||||||
|
"ex:SD_04_01": "Customer Structure",
|
||||||
|
"ex:SD_16_01": "Currency & Exchange Rate",
|
||||||
|
"ex:SD_16_02": "Fiscal Calendar",
|
||||||
|
"ex:SD_21_01": "Standard Calendar",
|
||||||
|
}
|
||||||
|
SD_NEW = [
|
||||||
|
("ex:SD_04_02", "SD-04.02", "Outlet & Points of Sale", "ex:DD_04"),
|
||||||
|
("ex:SD_04_03", "SD-04.03", "Geography", "ex:DD_04"),
|
||||||
|
("ex:SD_16_03", "SD-16.03", "Organisation Structure", "ex:DD_16"),
|
||||||
|
]
|
||||||
|
|
||||||
|
# ---- business objects -----------------------------------------------------
|
||||||
|
BO_RENAME = {
|
||||||
|
"ex:BO_10_01_001": "Product Hierarchy",
|
||||||
|
"ex:BO_04_01_001": "Customer Hierarchy",
|
||||||
|
"ex:BO_21_01_001": "Analysis Period",
|
||||||
|
}
|
||||||
|
BO_NEW = [
|
||||||
|
("ex:BO_04_03_001", "BO-04.03-001", "Country", "ex:DD_04", "ex:ST_DD_04",
|
||||||
|
"ex:SD_04_03", "ex:BC_04_03_001"),
|
||||||
|
("ex:BO_16_02_001", "BO-16.02-001", "Fiscal Period", "ex:DD_16", "ex:ST_DD_16",
|
||||||
|
"ex:SD_16_02", "ex:BC_16_02_001"),
|
||||||
|
("ex:BO_16_03_001", "BO-16.03-001", "Marketing Entity", "ex:DD_16", "ex:ST_DD_16",
|
||||||
|
"ex:SD_16_03", "ex:BC_16_03_001"),
|
||||||
|
]
|
||||||
|
|
||||||
|
# ---- where each object finally sits ---------------------------------------
|
||||||
|
BELONGS = {
|
||||||
|
"ex:BO_10_01_001": "ex:SD_10_01",
|
||||||
|
"ex:BO_04_01_001": "ex:SD_04_01",
|
||||||
|
"ex:BO_04_02_001": "ex:SD_04_02",
|
||||||
|
"ex:BO_04_03_001": "ex:SD_04_03",
|
||||||
|
"ex:BO_16_01_001": "ex:SD_16_01",
|
||||||
|
"ex:BO_16_01_002": "ex:SD_16_01",
|
||||||
|
"ex:BO_16_02_001": "ex:SD_16_02",
|
||||||
|
"ex:BO_16_03_001": "ex:SD_16_03",
|
||||||
|
"ex:BO_21_01_001": "ex:SD_21_01",
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---- subject of each borrowed object --------------------------------------
|
||||||
|
ABOUT = {
|
||||||
|
"ex:BO_10_01_001": "ex:BC_10_01_001", # Product Hierarchy -> Product
|
||||||
|
"ex:BO_04_01_001": "ex:BC_04_01_001", # Customer Hierarchy -> Customer
|
||||||
|
"ex:BO_04_02_001": "ex:BC_04_01_002", # Outlet -> Outlet
|
||||||
|
"ex:BO_04_03_001": "ex:BC_04_03_001", # Country -> Country
|
||||||
|
"ex:BO_16_01_001": "ex:BC_16_01_001", # Currency -> Currency
|
||||||
|
"ex:BO_16_01_002": "ex:BC_16_01_002", # Exchange Rate -> Exchange Rate
|
||||||
|
"ex:BO_16_02_001": "ex:BC_16_02_001", # Fiscal Period -> Fiscal Period
|
||||||
|
"ex:BO_16_03_001": "ex:BC_16_03_001", # Marketing Entity -> Marketing Entity
|
||||||
|
"ex:BO_21_01_001": "ex:BC_21_01_001", # Analysis Period -> Calendar Date
|
||||||
|
}
|
||||||
|
|
||||||
|
MARKETING_NOTE = ("Named Marketing Entity, not Management Entity: the element is "
|
||||||
|
"Marketing Entity Code and the column is MARKETING_ENTITY_CD. "
|
||||||
|
"To be confirmed by DD-16.")
|
||||||
|
|
||||||
|
|
||||||
|
def sd_block(i, ident, name, domain):
|
||||||
|
return ('%s a pr:SubDomain ;\n'
|
||||||
|
' pr:hasIdentifier "%s" ; pr:hasName "%s" ;\n'
|
||||||
|
' pr:belongsTo %s ; pr:owningDomain %s ;\n'
|
||||||
|
' pr:arbitrationStatus "TO_ARBITRATE" ;\n'
|
||||||
|
' pr:hasStatus "DRAFT" ; pr:hasVersion "1.1" ; '
|
||||||
|
'pr:hasSource "DGO proposal, split of a compound sub-domain" .'
|
||||||
|
% (i, ident, name, domain, domain))
|
||||||
|
|
||||||
|
|
||||||
|
def bo_block(i, ident, name, domain, steward, sd, bc):
|
||||||
|
return ('%s a pr:BusinessObject ;\n'
|
||||||
|
' pr:hasIdentifier "%s" ; pr:hasName "%s" ;\n'
|
||||||
|
' pr:owningDomain %s ; pr:ownedBy %s ;\n'
|
||||||
|
' pr:belongsTo %s ; pr:monitoredBy %s ;\n'
|
||||||
|
' pr:aboutConcept %s ;\n'
|
||||||
|
' pr:arbitrationStatus "TO_ARBITRATE" ;\n'
|
||||||
|
' pr:hasStatus "DRAFT" ; pr:hasVersion "1.1" ; '
|
||||||
|
'pr:hasSource "DGO proposal, pending ratification by the owning domain" .'
|
||||||
|
% (i, ident, name, domain, steward, sd, steward, bc))
|
||||||
|
|
||||||
|
|
||||||
|
def _split_clauses(body):
|
||||||
|
"""Split a Turtle predicate list on ';' that sit outside string literals."""
|
||||||
|
out, buf, i, n = [], [], 0, len(body)
|
||||||
|
while i < n:
|
||||||
|
c = body[i]
|
||||||
|
if c == '"':
|
||||||
|
j = i + 1
|
||||||
|
while j < n and body[j] != '"':
|
||||||
|
j += 2 if body[j] == "\\" else 1
|
||||||
|
j = min(j + 1, n)
|
||||||
|
buf.append(body[i:j]); i = j; continue
|
||||||
|
if c == ";":
|
||||||
|
out.append("".join(buf)); buf = []; i += 1; continue
|
||||||
|
buf.append(c); i += 1
|
||||||
|
out.append("".join(buf))
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def set_prop(text, subject, prop, value):
|
||||||
|
"""
|
||||||
|
Set or replace a single-valued property inside a subject block.
|
||||||
|
|
||||||
|
Clause-level, not regex-level: a property can sit mid-line
|
||||||
|
(pr:hasIdentifier "X" ; pr:hasName "Y" ;) and its value can contain a
|
||||||
|
semicolon inside the literal. A line-anchored pattern silently misses both
|
||||||
|
and APPENDS instead of replacing, which produces a second value and a
|
||||||
|
cardinality violation -- exactly what happened on the first run here.
|
||||||
|
"""
|
||||||
|
pat = re.compile(r'(^%s a pr:\w+ ;)(.*?)(\.\s*\n)' % re.escape(subject), re.S | re.M)
|
||||||
|
m = pat.search(text)
|
||||||
|
if not m:
|
||||||
|
return text, False
|
||||||
|
kept = [c for c in _split_clauses(m.group(2))
|
||||||
|
if c.strip() and not re.match(r'\s*%s\s' % re.escape(prop), c)]
|
||||||
|
kept.insert(0, "\n %s %s " % (prop, value))
|
||||||
|
body = " ;".join(kept)
|
||||||
|
if not body.endswith("\n"):
|
||||||
|
body = body.rstrip() + "\n "
|
||||||
|
return text[:m.start()] + m.group(1) + body + m.group(3) + text[m.end():], True
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
apply_changes = "--apply" in sys.argv
|
||||||
|
if not os.path.exists(TTL):
|
||||||
|
print("Not found: %s" % TTL)
|
||||||
|
sys.exit(2)
|
||||||
|
text = original = open(TTL, encoding="utf-8").read()
|
||||||
|
report = []
|
||||||
|
|
||||||
|
# 2. sub-domains
|
||||||
|
for sd, name in SD_RENAME.items():
|
||||||
|
text, ok = set_prop(text, sd, "pr:hasName", '"%s"' % name)
|
||||||
|
if ok:
|
||||||
|
report.append("renamed %s -> %s" % (sd.replace("ex:SD_", "SD-"), name))
|
||||||
|
|
||||||
|
todo_sd = [s for s in SD_NEW if not re.search(r'^%s a ' % re.escape(s[0]), text, re.M)]
|
||||||
|
if todo_sd:
|
||||||
|
anchor = re.search(r'\n(?=ex:BC_\w+ a pr:BusinessConcept ;|ex:BO_\w+ a pr:BusinessObject ;)',
|
||||||
|
text)
|
||||||
|
blocks = "\n".join(sd_block(*s) for s in todo_sd)
|
||||||
|
text = (text[:anchor.start()] + "\n\n"
|
||||||
|
+ "# --- sub-domains from the v1.1 structure proposal --------------------\n"
|
||||||
|
+ "# 'Customer & Outlet' and 'Marketing Entity & Fiscal Calendar' had the\n"
|
||||||
|
+ "# same defect as the compound Business Objects: a name joined by '&'\n"
|
||||||
|
+ "# has no single subject. Same rule, one level up.\n"
|
||||||
|
+ blocks + "\n" + text[anchor.start():])
|
||||||
|
report.append("created %d sub-domains%s"
|
||||||
|
% (len(todo_sd), "" if todo_sd else " (already present)"))
|
||||||
|
|
||||||
|
# 3. new business objects
|
||||||
|
todo_bo = [b for b in BO_NEW if not re.search(r'^%s a ' % re.escape(b[0]), text, re.M)]
|
||||||
|
if todo_bo:
|
||||||
|
anchor = re.search(r'\n(?=ex:DO_\w+ a pr:DataObject ;|ex:M_\w+ a pr:Metric ;)', text)
|
||||||
|
blocks = "\n".join(bo_block(*b) for b in todo_bo)
|
||||||
|
text = (text[:anchor.start()] + "\n\n"
|
||||||
|
+ "# --- business objects for the borrowed concepts -----------------------\n"
|
||||||
|
+ "# Country, Fiscal Period and Marketing Entity had a concept but nothing\n"
|
||||||
|
+ "# to hold it. Proposed to DD-04 and DD-16, hence TO_ARBITRATE.\n"
|
||||||
|
+ blocks + "\n" + text[anchor.start():])
|
||||||
|
report.append("created %d business objects%s"
|
||||||
|
% (len(todo_bo), "" if todo_bo else " (already present)"))
|
||||||
|
|
||||||
|
# 4. renames, placement, subject
|
||||||
|
for bo, name in BO_RENAME.items():
|
||||||
|
text, _ = set_prop(text, bo, "pr:hasName", '"%s"' % name)
|
||||||
|
report.append("renamed %d business objects to the agreed nomenclature" % len(BO_RENAME))
|
||||||
|
|
||||||
|
n_b = n_a = 0
|
||||||
|
for bo, sd in BELONGS.items():
|
||||||
|
text, ok = set_prop(text, bo, "pr:belongsTo", sd)
|
||||||
|
n_b += ok
|
||||||
|
for bo, bc in ABOUT.items():
|
||||||
|
text, ok = set_prop(text, bo, "pr:aboutConcept", bc)
|
||||||
|
n_a += ok
|
||||||
|
report.append("placed %d objects in their sub-domain, %d subjects confirmed" % (n_b, n_a))
|
||||||
|
|
||||||
|
# 5. the naming caveat, recorded on the object rather than in a side note
|
||||||
|
text, ok = set_prop(text, "ex:BC_16_03_001", "pr:hasBusinessRule", '"%s"' % MARKETING_NOTE)
|
||||||
|
if ok:
|
||||||
|
report.append("recorded the Marketing/Management naming caveat on the concept")
|
||||||
|
|
||||||
|
# ---- report
|
||||||
|
print()
|
||||||
|
print("SODH STRUCTURE PROPOSAL %s" % ("APPLY" if apply_changes else "DRY RUN"))
|
||||||
|
print("=" * W)
|
||||||
|
for line in report:
|
||||||
|
print(" " + line)
|
||||||
|
print("=" * W)
|
||||||
|
defined = set(re.findall(r'^(ex:\w+) a ', text, re.M))
|
||||||
|
dangling = sorted(set(re.findall(r'\bex:\w+', text)) - defined)
|
||||||
|
print(" dangling references: %s" % (", ".join(dangling) if dangling else "none"))
|
||||||
|
for cls in ("SubDomain", "BusinessObject", "BusinessConcept"):
|
||||||
|
ids = re.findall(r'^(ex:\w+) a pr:%s\b' % cls, text, re.M)
|
||||||
|
dup = [i for i in set(ids) if ids.count(i) > 1]
|
||||||
|
print(" %-16s %3d duplicates %d" % (cls, len(ids), len(dup)))
|
||||||
|
doubled = []
|
||||||
|
for m in re.finditer(r'^(ex:\w+) a pr:\w+ ;(.*?)\.\s*\n', text, re.S | re.M):
|
||||||
|
for prop in ("pr:hasName", "pr:hasIdentifier", "pr:belongsTo", "pr:aboutConcept"):
|
||||||
|
if len(re.findall(r'%s\s' % re.escape(prop), m.group(2))) > 1:
|
||||||
|
doubled.append("%s/%s" % (m.group(1), prop))
|
||||||
|
print(" duplicated single-valued properties: %s"
|
||||||
|
% (", ".join(doubled) if doubled else "none"))
|
||||||
|
arb = len(re.findall(r'pr:arbitrationStatus "TO_ARBITRATE"', text))
|
||||||
|
print(" TO_ARBITRATE %3d (nothing publishes until the domains ratify)" % arb)
|
||||||
|
print("=" * W)
|
||||||
|
|
||||||
|
if text != original and apply_changes:
|
||||||
|
shutil.copy2(TTL, TTL + ".bak")
|
||||||
|
open(TTL, "w", encoding="utf-8").write(text)
|
||||||
|
print(" written, backup at %s.bak" % os.path.basename(TTL))
|
||||||
|
elif text != original:
|
||||||
|
print(" dry run -- re-run with --apply to write")
|
||||||
|
print()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user