Templates: add capabilities on product level (#31588)

This commit is contained in:
andig 2026-07-09 12:43:27 +02:00 • committed by GitHub
parent 4f71e9675c
commit 023a48dd24
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 95 additions and 10 deletions

View file

@ -0,0 +1,45 @@
package templates
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestCapabilityPushdown(t *testing.T) {
tmpl, err := fromBytes([]byte(`
template: caps-demo
capabilities: ["1p3p"]
products:
- brand: Plain
- brand: Extra
capabilities: ["meter"]
params:
- name: host
required: true
render: |
type: demo
`))
require.NoError(t, err)
// template caps appended to product caps (product first)
require.Equal(t, []Capability{Capability1p3p}, tmpl.Products[0].Capabilities)
require.Equal(t, []Capability{CapabilityMeter, Capability1p3p}, tmpl.Products[1].Capabilities)
}
func TestCapabilityDuplicate(t *testing.T) {
// product repeats a template-level capability
_, err := fromBytes([]byte(`
template: caps-dup
capabilities: ["1p3p"]
products:
- brand: Dup
capabilities: ["1p3p"]
params:
- name: host
required: true
render: |
type: demo
`))
require.ErrorContains(t, err, "duplicate capability '1p3p'")
}

View file

@ -101,7 +101,7 @@ func (t *Template) RenderDocumentation(product Product, lang string) ([]byte, er
"ProductBrand": product.Brand,
"ProductDescription": product.Description.String(lang),
"ProductGroup": t.GroupTitle(lang),
"Capabilities": t.Capabilities,
"Capabilities": product.Capabilities,
"Countries": t.Countries,
"Requirements": t.Requirements.EVCC,
"RequirementDescription": t.Requirements.Description.String(lang),

View file

@ -79,6 +79,19 @@ func fromBytes(b []byte) (Template, error) {
}
}
// push down capabilities to products
for i := range tmpl.Products {
tmpl.Products[i].Capabilities = append(tmpl.Products[i].Capabilities, tmpl.Capabilities...)
seen := make(map[Capability]struct{}, len(tmpl.Products[i].Capabilities))
for _, c := range tmpl.Products[i].Capabilities {
if _, ok := seen[c]; ok {
return Template{}, fmt.Errorf("template '%s': duplicate capability '%s' for product '%s'", tmpl.Template, c, tmpl.Products[i].Identifier())
}
seen[c] = struct{}{}
}
}
return tmpl, nil
}

View file

@ -22,7 +22,7 @@ type Template struct {
Group string `json:",omitempty"` // the group this template belongs to, references groupList entries
Covers []string `json:",omitempty"` // list of covered outdated template names
Products []Product `json:",omitempty"` // list of products this template is compatible with
Capabilities []Capability `json:",omitempty"`
Capabilities []Capability `json:"-"`
Countries []CountryCode `json:",omitempty"` // list of countries supported by this template
Requirements Requirements `json:",omitempty"`
Caveats []Caveat `json:",omitempty"` // known device limitations

View file

@ -321,8 +321,9 @@ func (p Param) MarshalJSON() ([]byte, error) {
// Product contains naming information about a product a template supports
type Product struct {
Brand string // product brand
Description TextLanguage `json:",omitempty"` // product name
Brand string // product brand
Description TextLanguage `json:",omitempty"` // product name
Capabilities []Capability `json:",omitempty"` // appended to template-level capabilities
}
// Title returns the product title in the given language