@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix battery: <https://ref.openepcis.io/extensions/eu/battery/> .
@prefix dpp: <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-04-29"^^xsd:date .

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

# -----------------------------------------------------------------------------
# Battery Shape
# -----------------------------------------------------------------------------
battery:BatteryShape a sh:NodeShape ;
    sh:targetClass battery: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 battery:BatteryCategory
    ] ;
    sh:property [
        sh:path schema:status ;
        sh:name "Battery Status" ;
        sh:description "Current lifecycle status of the battery." ;
        sh:maxCount 1 ;
        sh:class battery:BatteryStatus
    ] ;
    sh:property [
        sh:path battery:batteryChemistry ;
        sh:name "Battery Chemistry" ;
        sh:class battery:BatteryChemistry
    ] ;
    sh:property [
        sh:path battery:technicalSpecifications ;
        sh:name "Technical Specifications" ;
        sh:class battery:TechnicalSpecification
    ] ;
    sh:property [
        sh:path battery:materialComposition ;
        sh:name "Material Composition" ;
        sh:class battery:BatteryMaterial
    ] ;
    sh:property [
        sh:path battery:recycledContent ;
        sh:name "Recycled Content" ;
        sh:class battery:RecycledContent
    ] ;
    sh:property [
        sh:path battery:endOfLifeInfo ;
        sh:name "End of Life Information" ;
        sh:class battery:EndOfLifeInfo
    ] ;
    sh:property [
        sh:path battery:hazardousSubstances ;
        sh:name "Hazardous Substances" ;
        sh:class battery:HazardousSubstance
    ] ;
    sh:property [
        sh:path battery:operatorInformation ;
        sh:name "Operator Information" ;
        sh:class battery:OperatorInformation
    ] ;
    sh:property [
        sh:path battery:supplyChainDueDiligence ;
        sh:name "Supply Chain Due Diligence" ;
        sh:class battery:SupplyChainDueDiligence
    ] ;
    # BatteryPass-Ready v1.3 mandatory identifier attributes (#7, #8, #11)
    sh:property [
        sh:path battery: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 battery:facilityIdentifier ;
        sh:name "Facility Identifier" ;
        sh:description "Mandatory per BatteryPass-Ready v1.3 (#11). Recommend GLN of the gs1:Place referenced by battery:manufacturingPlace." ;
        sh:datatype xsd:string ;
        sh:minCount 1
    ] ;
    sh:property [
        sh:path battery: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 battery: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 dpp: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 schema:status ;
        sh:name "DPP Status" ;
        sh:description "Mandatory per BatteryPass-Ready v1.3 (#2)." ;
        sh:class dpp:PassportStatus ;
        sh:minCount 1 ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path dpp:granularity ;
        sh:name "DPP Granularity" ;
        sh:description "Mandatory per BatteryPass-Ready v1.3 (#3)." ;
        sh:class dpp:DPPGranularity ;
        sh:minCount 1 ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path dpp:lastUpdate ;
        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).
# -----------------------------------------------------------------------------
battery:CarbonFootprintDeclarationShape a sh:NodeShape ;
    sh:targetClass battery:CarbonFootprintDeclaration ;
    rdfs:label "Carbon Footprint Declaration Shape" ;
    sh:property [
        sh:path battery:carbonFootprintTotal ;
        sh:name "Battery Carbon Footprint per Functional Unit" ;
        sh:minCount 1
    ] ;
    sh:property [
        sh:path battery:carbonFootprintPerformanceClass ;
        sh:name "Carbon Footprint Performance Class" ;
        sh:class battery:CarbonFootprintClass ;
        sh:minCount 1
    ] ;
    sh:property [
        sh:path battery:carbonFootprintStudyUrl ;
        sh:name "Web link to public carbon footprint study" ;
        sh:datatype xsd:anyURI ;
        sh:minCount 1
    ] .

# -----------------------------------------------------------------------------
# Battery Chemistry Shape
# -----------------------------------------------------------------------------
battery:BatteryChemistryShape a sh:NodeShape ;
    sh:targetClass battery: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 battery:cathodeActiveMaterial ;
        sh:datatype xsd:string
    ] ;
    sh:property [
        sh:path battery:anodeActiveMaterial ;
        sh:datatype xsd:string
    ] ;
    sh:property [
        sh:path battery:electrolyteType ;
        sh:datatype xsd:string
    ] .

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

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

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

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

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

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

# -----------------------------------------------------------------------------
# Supply Chain Due Diligence Shape
# -----------------------------------------------------------------------------
battery:SupplyChainDueDiligenceShape a sh:NodeShape ;
    sh:targetClass battery:SupplyChainDueDiligence ;
    rdfs:label "Supply Chain Due Diligence Shape" ;
    sh:property [
        sh:path battery:dueDiligenceReportUrl ;
        sh:datatype xsd:anyURI ;
        sh:minCount 1
    ] ;
    sh:property [
        sh:path battery: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.

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

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

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

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