@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix eubat: <https://ref.openepcis.io/extensions/eu/battery/> .
@prefix oec: <https://ref.openepcis.io/extensions/common/core/> .
@prefix gs1: <https://ref.gs1.org/voc/> .
@prefix schema: <https://schema.org/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix dcterms: <http://purl.org/dc/terms/> .

<https://ref.openepcis.io/extensions/eu/battery/shapes/>
    a sh:ShapesGraph ;
    dcterms:title "OpenEPCIS Battery SHACL Shapes"@en ;
    dcterms:description "SHACL validation shapes for Battery Digital Product Passport vocabulary, aligned with BatteryPass-Ready Data Attribute Longlist v1.3 (March 2026)."@en ;
    dcterms:created "2025-02-02"^^xsd:date ;
    dcterms:modified "2026-06-07"^^xsd:date .

# =============================================================================
# OpenEPCIS Battery Vocabulary SHACL Shapes v0.9.6
# Basic validation shapes for Battery Digital Product Passport data
# =============================================================================

# -----------------------------------------------------------------------------
# Battery Shape
# -----------------------------------------------------------------------------
eubat:BatteryShape a sh:NodeShape ;
    sh:targetClass eubat:Battery ;
    rdfs:label "Battery Shape" ;
    rdfs:comment "Validation shape for Battery instances as defined by EU Battery Regulation 2023/1542." ;
    sh:property [
        sh:path schema:category ;
        sh:name "Battery Category" ;
        sh:description "The regulatory category of the battery (LMT, EV, Industrial, Stationary)." ;
        sh:maxCount 1 ;
        sh:class eubat:BatteryCategory
    ] ;
    sh:property [
        sh:path schema:status ;
        sh:name "Battery Status" ;
        sh:description "Current lifecycle status of the battery." ;
        sh:maxCount 1 ;
        sh:class eubat:BatteryStatus
    ] ;
    sh:property [
        sh:path eubat:batteryChemistry ;
        sh:name "Battery Chemistry" ;
        sh:class eubat:BatteryChemistry
    ] ;
    sh:property [
        sh:path eubat:technicalSpecifications ;
        sh:name "Technical Specifications" ;
        sh:class eubat:TechnicalSpecification
    ] ;
    sh:property [
        sh:path eubat:materialComposition ;
        sh:name "Material Composition" ;
        sh:class eubat:BatteryMaterial
    ] ;
    sh:property [
        sh:path eubat:recycledContent ;
        sh:name "Recycled Content" ;
        sh:class eubat:RecycledContent
    ] ;
    sh:property [
        sh:path eubat:endOfLifeInfo ;
        sh:name "End of Life Information" ;
        sh:class eubat:EndOfLifeInfo
    ] ;
    sh:property [
        sh:path eubat:hazardousSubstances ;
        sh:name "Hazardous Substances" ;
        sh:class eubat:HazardousSubstance
    ] ;
    sh:property [
        sh:path eubat:operatorInformation ;
        sh:name "Operator Information" ;
        sh:class eubat:OperatorInformation
    ] ;
    sh:property [
        sh:path eubat:supplyChainDueDiligence ;
        sh:name "Supply Chain Due Diligence" ;
        sh:class eubat:SupplyChainDueDiligence
    ] ;
    # BatteryPass-Ready v1.3 mandatory identifier attributes (#7, #8, #11)
    sh:property [
        sh:path eubat:batteryModelIdentifier ;
        sh:name "Battery Model Identifier" ;
        sh:description "Mandatory per BatteryPass-Ready v1.3 (#7). Manufacturer-assigned model ID; referenced by the carbon footprint declaration." ;
        sh:datatype xsd:string ;
        sh:minCount 1 ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path gs1:hasSerialNumber ;
        sh:name "Battery Serial Number" ;
        sh:description "Mandatory per BatteryPass-Ready v1.3 (#8). Required on the Declaration of Conformity." ;
        sh:datatype xsd:string ;
        sh:minCount 1 ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eubat:facilityIdentifier ;
        sh:name "Facility Identifier" ;
        sh:description "Mandatory per BatteryPass-Ready v1.3 (#11). Recommend GLN of the gs1:Place referenced by eubat:manufacturingPlace." ;
        sh:datatype xsd:string ;
        sh:minCount 1
    ] ;
    sh:property [
        sh:path eubat:operatorIdentifier ;
        sh:name "Economic Operator Identifier" ;
        sh:description "Mandatory per BatteryPass-Ready v1.3 (#9). Access-restricted (AuthorizedOnly)." ;
        sh:datatype xsd:string ;
        sh:minCount 1
    ] ;
    sh:property [
        sh:path eubat:manufacturerIdentifier ;
        sh:name "Manufacturer Identifier" ;
        sh:description "Mandatory per BatteryPass-Ready v1.3 (#10). Access-restricted (AuthorizedOnly)." ;
        sh:datatype xsd:string ;
        sh:minCount 1
    ] ;
    sh:property [
        sh:path gs1:manufacturer ;
        sh:name "Manufacturer Information" ;
        sh:description "Mandatory per BatteryPass-Ready v1.3 (#13)." ;
        sh:class oec:OperatorInformation ;
        sh:minCount 1
    ] ;
    # BatteryPass-Ready v1.3 cross-cutting DPP information (#1-#4)
    sh:property [
        sh:path schema:schemaVersion ;
        sh:name "DPP Schema Version" ;
        sh:description "Mandatory per BatteryPass-Ready v1.3 (#1). Identifies the schema version this DPP instance follows (e.g. \"1.3\")." ;
        sh:datatype xsd:string ;
        sh:minCount 1 ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path oec:passportStatus ;
        sh:name "DPP Status" ;
        sh:description "Mandatory per BatteryPass-Ready v1.3 (#2). EN 18223 dppStatus." ;
        sh:datatype xsd:string ;
        sh:in ( "active" "inactive" "archived" "invalid" "draft" "withdrawn" "suspended" ) ;
        sh:minCount 1 ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path oec:reportingGranularity ;
        sh:name "DPP Reporting Granularity" ;
        sh:description "Mandatory per BatteryPass-Ready v1.3 (#3)." ;
        sh:class oec:DPPGranularity ;
        sh:minCount 1 ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path oec:lastUpdated ;
        sh:name "Date-time of latest update" ;
        sh:description "Mandatory per BatteryPass-Ready v1.3 (#4). Updated whenever any passport attribute changes." ;
        sh:datatype xsd:dateTime ;
        sh:minCount 1 ;
        sh:maxCount 1
    ] .

# -----------------------------------------------------------------------------
# Carbon Footprint Declaration Shape
# Carbon footprint *label* (#23) is MANDATORY in v1.3 (was voluntary in v1.2).
# -----------------------------------------------------------------------------
eubat:CarbonFootprintDeclarationShape a sh:NodeShape ;
    sh:targetClass eubat:CarbonFootprintDeclaration ;
    rdfs:label "Carbon Footprint Declaration Shape" ;
    sh:property [
        sh:path eubat:carbonFootprintTotal ;
        sh:name "Battery Carbon Footprint per Functional Unit" ;
        sh:minCount 1
    ] ;
    sh:property [
        sh:path eubat:carbonFootprintPerformanceClass ;
        sh:name "Carbon Footprint Performance Class" ;
        sh:class eubat:CarbonFootprintClass ;
        sh:minCount 1
    ] ;
    sh:property [
        sh:path eubat:carbonFootprintStudyUrl ;
        sh:name "Web link to public carbon footprint study" ;
        sh:datatype xsd:anyURI ;
        sh:minCount 1
    ] .

# -----------------------------------------------------------------------------
# Battery Chemistry Shape
# -----------------------------------------------------------------------------
eubat:BatteryChemistryShape a sh:NodeShape ;
    sh:targetClass eubat:BatteryChemistry ;
    rdfs:label "Battery Chemistry Shape" ;
    sh:property [
        sh:path schema:name ;
        sh:name "Short Name" ;
        sh:description "Abbreviated chemistry name (e.g., LFP, NMC, NCA)." ;
        sh:datatype xsd:string ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path schema:name ;
        sh:name "Full Name" ;
        sh:description "Full chemical name of the battery chemistry." ;
        sh:datatype xsd:string ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path eubat:cathodeActiveMaterial ;
        sh:datatype xsd:string
    ] ;
    sh:property [
        sh:path eubat:anodeActiveMaterial ;
        sh:datatype xsd:string
    ] ;
    sh:property [
        sh:path eubat:electrolyteType ;
        sh:datatype xsd:string
    ] .

# -----------------------------------------------------------------------------
# Technical Specification Shape
# -----------------------------------------------------------------------------
eubat:TechnicalSpecificationShape a sh:NodeShape ;
    sh:targetClass eubat:TechnicalSpecification ;
    rdfs:label "Technical Specification Shape" ;
    sh:property [
        sh:path eubat:ratedCapacity ;
        sh:name "Rated Capacity" ;
        sh:class gs1:QuantitativeValue
    ] ;
    sh:property [
        sh:path eubat:ratedEnergy ;
        sh:name "Rated Energy" ;
        sh:class gs1:QuantitativeValue
    ] ;
    sh:property [
        sh:path eubat:nominalVoltage ;
        sh:name "Nominal Voltage" ;
        sh:class gs1:QuantitativeValue
    ] ;
    sh:property [
        sh:path eubat:expectedCycleLife ;
        sh:datatype xsd:integer
    ] ;
    sh:property [
        sh:path eubat:roundTripEfficiency ;
        sh:datatype xsd:decimal
    ] .

# -----------------------------------------------------------------------------
# Battery Material Shape
# -----------------------------------------------------------------------------
eubat:BatteryMaterialShape a sh:NodeShape ;
    sh:targetClass eubat:BatteryMaterial ;
    rdfs:label "Battery Material Shape" ;
    sh:property [
        sh:path schema:name ;
        sh:datatype xsd:string ;
        sh:minCount 1
    ] ;
    sh:property [
        sh:path eubat:casNumber ;
        sh:name "CAS Number" ;
        sh:datatype xsd:string
    ] ;
    sh:property [
        sh:path eubat:componentLocation ;
        sh:class eubat:ComponentLocation
    ] ;
    sh:property [
        sh:path schema:weightPercentage ;
        sh:datatype xsd:decimal
    ] ;
    sh:property [
        sh:path eubat:isCriticalRawMaterial ;
        sh:datatype xsd:boolean
    ] .

# -----------------------------------------------------------------------------
# Recycled Content Shape
# -----------------------------------------------------------------------------
eubat:RecycledContentShape a sh:NodeShape ;
    sh:targetClass eubat:RecycledContent ;
    rdfs:label "Recycled Content Shape" ;
    sh:property [
        sh:path eubat:lithiumRecycledShare ;
        sh:datatype xsd:decimal
    ] ;
    sh:property [
        sh:path eubat:cobaltRecycledShare ;
        sh:datatype xsd:decimal
    ] ;
    sh:property [
        sh:path eubat:nickelRecycledShare ;
        sh:datatype xsd:decimal
    ] ;
    sh:property [
        sh:path eubat:leadRecycledShare ;
        sh:datatype xsd:decimal
    ] .

# -----------------------------------------------------------------------------
# End of Life Info Shape
# -----------------------------------------------------------------------------
eubat:EndOfLifeInfoShape a sh:NodeShape ;
    sh:targetClass eubat:EndOfLifeInfo ;
    rdfs:label "End of Life Information Shape" ;
    sh:property [
        sh:path eubat:dismantlingInstructions ;
        sh:nodeKind sh:IRI
    ] ;
    sh:property [
        sh:path eubat:extinguishingAgent ;
        sh:datatype xsd:string
    ] .

# -----------------------------------------------------------------------------
# Hazardous Substance Shape
# -----------------------------------------------------------------------------
eubat:HazardousSubstanceShape a sh:NodeShape ;
    sh:targetClass eubat:HazardousSubstance ;
    rdfs:label "Hazardous Substance Shape" ;
    sh:property [
        sh:path schema:name ;
        sh:datatype xsd:string ;
        sh:minCount 1
    ] ;
    sh:property [
        sh:path eubat:substanceCasNumber ;
        sh:datatype xsd:string
    ] ;
    sh:property [
        sh:path eubat:hazardClass ;
        sh:class eubat:HazardClass
    ] ;
    sh:property [
        sh:path eubat:concentration ;
        sh:datatype xsd:decimal
    ] .

# -----------------------------------------------------------------------------
# Operator Information Shape
# -----------------------------------------------------------------------------
eubat:OperatorInformationShape a sh:NodeShape ;
    sh:targetClass eubat:OperatorInformation ;
    rdfs:label "Operator Information Shape" ;
    sh:property [
        sh:path eubat:operatorRole ;
        sh:datatype xsd:string
    ] .

# -----------------------------------------------------------------------------
# Supply Chain Due Diligence Shape
# -----------------------------------------------------------------------------
eubat:SupplyChainDueDiligenceShape a sh:NodeShape ;
    sh:targetClass eubat:SupplyChainDueDiligence ;
    rdfs:label "Supply Chain Due Diligence Shape" ;
    sh:property [
        sh:path eubat:dueDiligenceReportUrl ;
        sh:datatype xsd:anyURI ;
        sh:minCount 1
    ] ;
    sh:property [
        sh:path eubat:thirdPartyAssurancesUrl ;
        sh:datatype xsd:anyURI
    ] .

# =============================================================================
# QuantitativeValue unitCode Shapes (GS1-idiomatic)
# =============================================================================
# Pin gs1:unitCode to the canonical UN/CEFACT Rec 20 code documented for each
# battery property. These complement dpp-sh:QuantitativeValueShape (which
# enforces value+unitCode presence); here we add the per-property hasValue
# check. Extend with more shapes as additional regulated properties are added.

eubat:RatedCapacityShape a sh:NodeShape ;
    sh:targetSubjectsOf eubat:ratedCapacity ;
    sh:property [
        sh:path ( eubat:ratedCapacity gs1:unitCode ) ;
        sh:hasValue "AMH" ;
        sh:message "eubat:ratedCapacity must use unitCode 'AMH' (ampere-hours)"@en
    ] .

eubat:RatedEnergyShape a sh:NodeShape ;
    sh:targetSubjectsOf eubat:ratedEnergy ;
    sh:property [
        sh:path ( eubat:ratedEnergy gs1:unitCode ) ;
        sh:hasValue "KWH" ;
        sh:message "eubat:ratedEnergy must use unitCode 'KWH' (kilowatt-hours)"@en
    ] .

eubat:NominalVoltageShape a sh:NodeShape ;
    sh:targetSubjectsOf eubat:nominalVoltage ;
    sh:property [
        sh:path ( eubat:nominalVoltage gs1:unitCode ) ;
        sh:hasValue "VLT" ;
        sh:message "eubat:nominalVoltage must use unitCode 'VLT' (volts)"@en
    ] .

eubat:RatedMaximumPowerShape a sh:NodeShape ;
    sh:targetSubjectsOf eubat:ratedMaximumPower ;
    sh:property [
        sh:path ( eubat:ratedMaximumPower gs1:unitCode ) ;
        sh:hasValue "KWT" ;
        sh:message "eubat:ratedMaximumPower must use unitCode 'KWT' (kilowatts)"@en
    ] .
