This commit is contained in:
2026-08-22 20:09:28 +02:00
parent fa19852736
commit 8ed0919f67
5 changed files with 231 additions and 139 deletions
@@ -1,5 +1,4 @@
[{ [{
"id": 1000007,
"label": "Simply CPQ", "label": "Simply CPQ",
"description": "Product groups for Simply CPQ", "description": "Product groups for Simply CPQ",
"productGroups": [ "productGroups": [
@@ -10,6 +9,18 @@
{ {
"label": "Radio", "label": "Radio",
"description": "All HIFI products", "description": "All HIFI products",
"properties": [
{ "property": "Spannungsversorgung (V)"},
{ "property": "Leistung (W)"},
{ "property": "Ausgangsimpedanz (Ω)"},
{ "property": "Eingangsimpedanz (Ω)"},
{ "property": "Gewicht (kg)"},
{ "property": "Abmessungen (mm)"},
{ "property": "Frequenzbereich (Hz‑kHz)"},
{ "property": "Signal‑Rausch‑Verhältnis (dB)"},
{ "property": "Anschlüsse"},
{ "property": "Preis (USD)"}
],
"products": [ "products": [
{ {
"externalId": "Radio_RAD-001", "externalId": "Radio_RAD-001",
@@ -195,6 +206,18 @@
{ {
"label": "Kassette", "label": "Kassette",
"description": "All Kassette products", "description": "All Kassette products",
"properties": [
{ "property": "Spannungsversorgung (V)"},
{ "property": "Leistung (W)"},
{ "property": "Kapazität/Volumen (L)"},
{ "property": "Abmessungen (mm)"},
{ "property": "Gewicht (kg)"},
{ "property": "Energieeffizienzklasse"},
{ "property": "Bedienungsart"},
{ "property": "Material Innenraum"},
{ "property": "Zusatzfunktionen"},
{ "property": "Preis (USD)"}
],
"products": [ "products": [
{ {
"externalId": "Kassette_CAS-001", "externalId": "Kassette_CAS-001",
@@ -381,6 +404,18 @@
{ {
"label": "Verstärker", "label": "Verstärker",
"description": "All Verstärker products", "description": "All Verstärker products",
"properties": [
{ "property": "Spannungsversorgung (V)"},
{ "property": "Leistung (W)"},
{ "property": "Kapazität/Volumen (L)"},
{ "property": "Abmessungen (mm)"},
{ "property": "Gewicht (kg)"},
{ "property": "Energieeffizienzklasse"},
{ "property": "Bedienungsart"},
{ "property": "Material Innenraum"},
{ "property": "Zusatzfunktionen"},
{ "property": "Preis (USD)"}
],
"products": [ "products": [
{ {
"externalId": "Verstärker_AMP-001", "externalId": "Verstärker_AMP-001",
@@ -566,6 +601,18 @@
{ {
"label": "CD_Player", "label": "CD_Player",
"description": "All CD_Player products", "description": "All CD_Player products",
"properties": [
{ "property": "Spannungsversorgung (V)"},
{ "property": "Leistung (W)"},
{ "property": "Kapazität/Volumen (L)"},
{ "property": "Abmessungen (mm)"},
{ "property": "Gewicht (kg)"},
{ "property": "Energieeffizienzklasse"},
{ "property": "Bedienungsart"},
{ "property": "Material Innenraum"},
{ "property": "Zusatzfunktionen"},
{ "property": "Preis (USD)"}
],
"products": [ "products": [
{ {
"externalId": "CD‑Player_CDP-001", "externalId": "CD‑Player_CDP-001",
@@ -752,6 +799,18 @@
{ {
"label": "Machines", "label": "Machines",
"description": "All machines products", "description": "All machines products",
"properties": [
{ "property": "Spannungsversorgung (V)"},
{ "property": "Leistung (W)"},
{ "property": "Kapazität (kg)"},
{ "property": "Energieeffizienzklasse"},
{ "property": "Schleuderdrehzahl (U/min)"},
{ "property": "Programms/Features"},
{ "property": "Wasserverbrauch pro Zyklus (L)"},
{ "property": "Abmessungen (mm)"},
{ "property": "Gewicht (kg)"},
{ "property": "Preis (USD)"}
],
"products": [ "products": [
{ {
"externalId": "Waschmaschine_WAS-001", "externalId": "Waschmaschine_WAS-001",
@@ -1120,6 +1179,7 @@
{ {
"label": "components", "label": "components",
"description": "All components", "description": "All components",
"properties": [],
"productGroups": [] "productGroups": []
} }
] ]
@@ -12,27 +12,27 @@
}, },
{ {
"label": "Leistung (W)", "label": "Leistung (W)",
"description": "All kitchen products" "description": "Leistung"
}, },
{ {
"label": "Eingangsimpedanz (Ω)", "label": "Eingangsimpedanz (Ω)",
"description": "All kitchen products" "description": "Wiederstand der Eingangsimpedanz"
}, },
{ {
"label": "Frequenzbereich (Hz‑kHz)", "label": "Frequenzbereich (Hz‑kHz)",
"description": "All kitchen products" "description": "Frequenzbereich (Hz‑kHz)"
}, },
{ {
"label": "Signal‑Rausch‑Verhältnis (dB)", "label": "Signal‑Rausch‑Verhältnis (dB)",
"description": "All kitchen products" "description": "Signal‑Rausch‑Verhältnis (dB)"
}, },
{ {
"label": "Anschlüsse", "label": "Anschlüsse",
"description": "All kitchen products" "description": "Anschlüsse"
}, },
{ {
"label": "Ausgangsimpedanz (Ω)", "label": "Ausgangsimpedanz (Ω)",
"description": "All machines products" "description": "Ausgangsimpedanz (Ω)"
} }
] ]
}, },
+5 -1
View File
@@ -16,6 +16,9 @@ type ImportPropertyType struct {
type ImportProperty struct { type ImportProperty struct {
ID int `json:"id,omitempty"` ID int `json:"id,omitempty"`
PropertyTypeID int `json:"propertyTypeId,omitempty"`
ProductID int `json:"productId,omitempty"`
ProductGroupID int `json:"productGroupId,omitempty"`
Label string `json:"property"` Label string `json:"property"`
Value string `json:"value"` Value string `json:"value"`
} }
@@ -26,6 +29,7 @@ type ImportProductGroup struct {
Description string `json:"description"` Description string `json:"description"`
ProductGroups []ImportProductGroup `json:"productGroups,omitempty"` ProductGroups []ImportProductGroup `json:"productGroups,omitempty"`
Products []ImportProduct `json:"products,omitempty"` Products []ImportProduct `json:"products,omitempty"`
Properties []ImportProperty `json:"properties,omitempty"`
} }
type ImportProduct struct { type ImportProduct struct {
@@ -33,6 +37,6 @@ type ImportProduct struct {
ExternalID string `json:"externalId"` ExternalID string `json:"externalId"`
Label string `json:"label"` Label string `json:"label"`
Description string `json:"description"` Description string `json:"description"`
ProductGroupLabel string `json:"productGroupLabel,omitempty"` ProductGroupID int `json:"productGroupId,omitempty"`
Properties []ImportProperty `json:"properties,omitempty"` Properties []ImportProperty `json:"properties,omitempty"`
} }
+116 -100
View File
@@ -2,6 +2,7 @@ package repositories
import ( import (
"database/sql" "database/sql"
"log"
"simplycpq/models" "simplycpq/models"
) )
@@ -95,158 +96,173 @@ func (r *ImportRepository) ImportPropertyTypes(importData []models.ImportPropert
return nil return nil
} }
func (r *ImportRepository) ImportProductGroups(importData []models.ImportProductGroup, parentGroupId int) error { // Implement the ImportProducts method
// Implement the logic to import ProductGroups into the database func (r *ImportRepository) ImportProductGroups(importData []models.ImportProductGroup, parentProductGroupID int) error {
// Implement the logic to import PropertyTypeGroups into the database // check if ProductGroup allready exists
// This is a placeholder implementation; you need to write the actual logic for _, productGroup := range importData {
for _, data := range importData { if productGroup.ID != 0 {
if data.ID != 0 { // Update existing ProductGroup
// Update existing record query := "UPDATE productGroups SET label = $1, description = $2, parentGroupId = $3 WHERE id = $4"
query := "UPDATE productgroups SET label = $1, description = $2 WHERE id = $3" _, err := r.db.Exec(query, productGroup.Label, productGroup.Description, parentProductGroupID, productGroup.ID)
_, err := r.db.Exec(query, data.Label, data.Description, data.ID)
if err != nil { if err != nil {
return err return err
} }
//
if err := r.ImportProducts(data.Products, data.ID); err != nil {
return err
}
// update subgroups if they exist
if data.ProductGroups != nil {
return r.ImportProductGroups(data.ProductGroups, data.ID)
}
} else { } else {
// Insert new record // Insert new ProductGroup
err := r.db.QueryRow("INSERT INTO productgroups (label, description, parentGroupId) VALUES ($1, $2, $3) RETURNING id", data.Label, data.Description, parentGroupId).Scan(&data.ID) err := r.db.QueryRow("INSERT INTO productGroups (label, description, parentGroupId) VALUES ($1, $2, $3) RETURNING id", productGroup.Label, productGroup.Description, parentProductGroupID).Scan(&productGroup.ID)
if err != nil { if err != nil {
return err return err
} }
if err := r.ImportProducts(data.Products, data.ID); err != nil { }
// Import Properties for the ProductGroup
for _, property := range productGroup.Properties {
property.ProductGroupID = productGroup.ID
property.ProductID = 0 // Clear ProductID for ProductGroup properties
// get PropertyTypeID by label
log.Printf("Getting PropertyTypeID for label: %s", property.Label)
ptid, err := r.valueRepo.GetPropertyTypeIDByLabel(property.Label)
if err != nil {
return err return err
} }
if data.ProductGroups != nil { log.Printf("Retrieved PropertyTypeID: %d for label: %s", ptid, property.Label)
return r.ImportProductGroups(data.ProductGroups, data.ID) property.PropertyTypeID = ptid // Set PropertyTypeID to the retrieved ID for ProductGroup properties
err = r.ImportProperty(property)
if err != nil {
return err
}
}
// Import Products for the ProductGroup
for _, product := range productGroup.Products {
product.ProductGroupID = productGroup.ID // Set the ProductGroupID for the Product
err := r.ImportProduct(product)
if err != nil {
return err
}
}
// Import sub ProductGroups recursively
if productGroup.ProductGroups != nil {
err := r.ImportProductGroups(productGroup.ProductGroups, productGroup.ID)
if err != nil {
return err
} }
} }
} }
return nil return nil
} }
func (r *ImportRepository) ImportProducts(importData []models.ImportProduct, productGroupID int) error { func (r *ImportRepository) ImportProduct(product models.ImportProduct) error {
// Implement the logic to import Products into the database
for _, product := range importData {
if product.ID != 0 { if product.ID != 0 {
// Update existing Product // Update existing Product
query := "UPDATE products SET externalId = $1, label = $2, description = $3, productGroupId = $4 WHERE id = $5" query := "UPDATE products SET label = $1, description = $2, productGroupId = $3 WHERE id = $4"
_, err := r.db.Exec(query, product.ExternalID, product.Label, product.Description, productGroupID, product.ID) _, err := r.db.Exec(query, product.Label, product.Description, product.ProductGroupID, product.ID)
if err != nil { if err != nil {
return err return err
} }
if product.Properties != nil {
if err := r.ImportProperties(product.Properties, product.ID, productGroupID); err != nil {
return err
}
}
} else { } else {
// Insert new Product // Insert new Product
query := "INSERT INTO products (externalId, label, description, productGroupId) VALUES ($1, $2, $3, $4) RETURNING id" err := r.db.QueryRow("INSERT INTO products (label, description, productGroupId) VALUES ($1, $2, $3) RETURNING id", product.Label, product.Description, product.ProductGroupID).Scan(&product.ID)
err := r.db.QueryRow(query, product.ExternalID, product.Label, product.Description, productGroupID).Scan(&product.ID)
if err != nil { if err != nil {
return err return err
} }
if product.Properties != nil { }
if err := r.ImportProperties(product.Properties, product.ID, productGroupID); err != nil {
// Import Properties for the Product
for _, property := range product.Properties {
property.ProductID = product.ID // Set the ProductID for the Property
property.ProductGroupID = product.ProductGroupID // Clear ProductGroupID for Product properties
err := r.ImportProperty(property)
if err != nil {
return err return err
} }
} }
}
}
return nil return nil
} }
func (r *ImportRepository) ImportProperties(importData []models.ImportProperty, productID int, productGroupID int) error { func (r *ImportRepository) ImportProperty(property models.ImportProperty) error {
for _, property := range importData {
var propertyType models.ImportPropertyType
var propertyIDs []int
propertyType, err := r.findPropertyType(property.Label)
if err != nil {
return err
}
if property.ID != 0 { if property.ID != 0 {
if err := r.updateProperty(property, property.ID, productID, productGroupID, propertyType); err != nil { // Update existing Property
query := "UPDATE properties SET label = $1, description = $2, propertyTypeId = $3, productId = $4, productGroupId = $5 WHERE id = $6"
_, err := r.db.Exec(query, property.Label, property.Label, property.PropertyTypeID, property.ProductID, property.ProductGroupID, property.ID)
if err != nil {
return err return err
} }
} else { } else {
propertyIDs, err = r.insertProperty(property, productID, productGroupID, propertyType) // Insert new Property
query := "INSERT INTO properties (label, description, propertyTypeId, productId, productGroupId) VALUES ($1, $2, $3, $4, $5) RETURNING id"
err := r.db.QueryRow(query, property.Label, property.Label, property.PropertyTypeID, property.ProductID, property.ProductGroupID).Scan(&property.ID)
if err != nil { if err != nil {
return err return err
} }
} }
for _, propertyId := range propertyIDs { // Import Property Value for the Property
property.ID = propertyId if property.Value != "" {
if err := r.upsertValue(property, property.Value, propertyType.ID); err != nil { err := r.ImportPropertyValue(property.Value, property)
if err != nil {
return err return err
} }
err2 := r.ImportPropertyTypeValue(property.Value, property.PropertyTypeID, property.Label)
if err2 != nil {
return err2
}
err3 := r.ImportPropertyProductValue(property.Value, property.ProductID, property.Label)
if err3 != nil {
return err3
} }
} }
return nil return nil
} }
func (r *ImportRepository) findPropertyType(label string) (models.ImportPropertyType, error) { func (r *ImportRepository) ImportPropertyValue(value string, property models.ImportProperty) error {
var propertyType models.ImportPropertyType // Check if a value already exists for the property
err := r.db.QueryRow("SELECT id, label FROM propertyTypes WHERE label = $1", label).Scan(&propertyType.ID, &propertyType.Label)
if err != nil {
if err == sql.ErrNoRows {
return models.ImportPropertyType{}, nil
}
return models.ImportPropertyType{}, err
}
return propertyType, nil
}
func (r *ImportRepository) updateProperty(property models.ImportProperty, propertyID int, productID int, productGroupID int, propertyType models.ImportPropertyType) error {
query := "UPDATE properties SET label = $1, description = $2, propertyTypeId = $3, productId = $4, productGroupId = $5 WHERE id = $6"
_, err := r.db.Exec(query, property.Label, propertyType.Label, propertyType.ID, productID, productGroupID, propertyID)
return err
}
func (r *ImportRepository) insertProperty(property models.ImportProperty, productID int, productGroupID int, propertyType models.ImportPropertyType) ([]int, error) {
query := "INSERT INTO properties (label, description, productId, propertyTypeId, productGroupId) VALUES ($1, $2, $3, $4, $5) RETURNING id"
var propertyID int
var propertyID2 int
err := r.db.QueryRow(query, property.Label, propertyType.Label, productID, propertyType.ID, productGroupID).Scan(&propertyID)
if err != nil {
return nil, err
}
err2 := r.db.QueryRow(query, property.Label, propertyType.Label, 0, propertyType.ID, productGroupID).Scan(&propertyID2)
if err2 != nil {
return nil, err2
}
return []int{propertyID, propertyID2}, nil
}
func (r *ImportRepository) upsertValue(property models.ImportProperty, value string, propertyTypeId int) error {
var existingValueID int var existingValueID int
err := r.db.QueryRow("SELECT id FROM values WHERE label = $1 AND propertyId = $2", value, property.ID).Scan(&existingValueID) err := r.db.QueryRow("SELECT id FROM values WHERE label = $1 AND propertyId = $2", value, property.ID).Scan(&existingValueID)
if err != nil {
if err != sql.ErrNoRows {
return err
}
_, err = r.db.Exec("INSERT INTO values (label, description, propertyId) VALUES ($1, $2, $3)", value, property.Label, property.ID)
// check if value exists for propertyType, if not insert it, if yes update it
query3 := "SELECT id FROM values WHERE label = $1 AND propertyId = $2"
_, err = r.db.Exec(query3, value, propertyTypeId)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
_, err = r.db.Exec("INSERT INTO values (label, description, propertyId) VALUES ($1, $2, $3)", value, property.Label, propertyTypeId) // Insert new Property Value
query := "INSERT INTO values (label, description, propertyId) VALUES ($1, $2, $3)"
_, err := r.db.Exec(query, value, value, property.ID)
if err != nil {
return err return err
} }
} else if err != nil {
return err return err
} else { }
_, err = r.db.Exec("UPDATE values SET label = $1, description = $2 WHERE id = $3", value, property.Label, existingValueID) return nil
return err
} }
func (r *ImportRepository) ImportPropertyTypeValue(value string, propertyTypeID int, description string) error {
// Check if a value already exists for the property
var existingValueID int
err := r.db.QueryRow("SELECT id FROM values WHERE label = $1 AND propertyId = $2", value, propertyTypeID).Scan(&existingValueID)
if err == sql.ErrNoRows {
// Insert new Property Value
query := "INSERT INTO values (label, description, propertyId) VALUES ($1, $2, $3)"
_, err := r.db.Exec(query, value, description, propertyTypeID)
if err != nil {
return err
}
} else if err != nil {
return err
}
return nil
}
func (r *ImportRepository) ImportPropertyProductValue(value string, productID int, description string) error {
// Check if a value already exists for the property
var existingValueID int
err := r.db.QueryRow("SELECT id FROM values WHERE label = $1 AND propertyId = $2", value, productID).Scan(&existingValueID)
if err == sql.ErrNoRows {
// Insert new Property Value
query := "INSERT INTO values (label, description, propertyId) VALUES ($1, $2, $3)"
_, err := r.db.Exec(query, value, description, productID)
if err != nil {
return err
}
} else if err != nil {
return err
}
return nil
} }
@@ -143,6 +143,18 @@ func (vr *ValueRepository) GetPropertyType(id int) (*models.PropertyType, error)
return &propertyType, nil return &propertyType, nil
} }
func (vr *ValueRepository) GetPropertyTypeIDByLabel(label string) (int, error) {
// Implement the logic to retrieve the propertyType ID from the database by label
query := `SELECT id FROM propertytypes WHERE label=$1`
row := vr.db.QueryRow(query, label)
var id int
err := row.Scan(&id)
if err != nil {
return 0, err
}
return id, nil
}
func (vr *ValueRepository) GetPropertyTypesByGroupId(groupId int) ([]*models.PropertyType, error) { func (vr *ValueRepository) GetPropertyTypesByGroupId(groupId int) ([]*models.PropertyType, error) {
// Implement the logic to retrieve the propertyTypes by groupId from the database // Implement the logic to retrieve the propertyTypes by groupId from the database
query := `SELECT id, label, description, propertytypegroupid FROM propertytypes WHERE propertytypegroupid=$1` query := `SELECT id, label, description, propertytypegroupid FROM propertytypes WHERE propertytypegroupid=$1`