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",
"description": "Product groups for Simply CPQ",
"productGroups": [
@@ -10,6 +9,18 @@
{
"label": "Radio",
"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": [
{
"externalId": "Radio_RAD-001",
@@ -195,6 +206,18 @@
{
"label": "Kassette",
"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": [
{
"externalId": "Kassette_CAS-001",
@@ -381,6 +404,18 @@
{
"label": "Verstärker",
"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": [
{
"externalId": "Verstärker_AMP-001",
@@ -566,6 +601,18 @@
{
"label": "CD_Player",
"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": [
{
"externalId": "CD‑Player_CDP-001",
@@ -752,6 +799,18 @@
{
"label": "Machines",
"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": [
{
"externalId": "Waschmaschine_WAS-001",
@@ -1120,6 +1179,7 @@
{
"label": "components",
"description": "All components",
"properties": [],
"productGroups": []
}
]
@@ -12,27 +12,27 @@
},
{
"label": "Leistung (W)",
"description": "All kitchen products"
"description": "Leistung"
},
{
"label": "Eingangsimpedanz (Ω)",
"description": "All kitchen products"
"description": "Wiederstand der Eingangsimpedanz"
},
{
"label": "Frequenzbereich (Hz‑kHz)",
"description": "All kitchen products"
"description": "Frequenzbereich (Hz‑kHz)"
},
{
"label": "Signal‑Rausch‑Verhältnis (dB)",
"description": "All kitchen products"
"description": "Signal‑Rausch‑Verhältnis (dB)"
},
{
"label": "Anschlüsse",
"description": "All kitchen products"
"description": "Anschlüsse"
},
{
"label": "Ausgangsimpedanz (Ω)",
"description": "All machines products"
"description": "Ausgangsimpedanz (Ω)"
}
]
},
+13 -9
View File
@@ -15,9 +15,12 @@ type ImportPropertyType struct {
}
type ImportProperty struct {
ID int `json:"id,omitempty"`
Label string `json:"property"`
Value string `json:"value"`
ID int `json:"id,omitempty"`
PropertyTypeID int `json:"propertyTypeId,omitempty"`
ProductID int `json:"productId,omitempty"`
ProductGroupID int `json:"productGroupId,omitempty"`
Label string `json:"property"`
Value string `json:"value"`
}
type ImportProductGroup struct {
@@ -26,13 +29,14 @@ type ImportProductGroup struct {
Description string `json:"description"`
ProductGroups []ImportProductGroup `json:"productGroups,omitempty"`
Products []ImportProduct `json:"products,omitempty"`
Properties []ImportProperty `json:"properties,omitempty"`
}
type ImportProduct struct {
ID int `json:"id,omitempty"`
ExternalID string `json:"externalId"`
Label string `json:"label"`
Description string `json:"description"`
ProductGroupLabel string `json:"productGroupLabel,omitempty"`
Properties []ImportProperty `json:"properties,omitempty"`
ID int `json:"id,omitempty"`
ExternalID string `json:"externalId"`
Label string `json:"label"`
Description string `json:"description"`
ProductGroupID int `json:"productGroupId,omitempty"`
Properties []ImportProperty `json:"properties,omitempty"`
}
+139 -123
View File
@@ -2,6 +2,7 @@ package repositories
import (
"database/sql"
"log"
"simplycpq/models"
)
@@ -95,158 +96,173 @@ func (r *ImportRepository) ImportPropertyTypes(importData []models.ImportPropert
return nil
}
func (r *ImportRepository) ImportProductGroups(importData []models.ImportProductGroup, parentGroupId int) error {
// Implement the logic to import ProductGroups into the database
// Implement the logic to import PropertyTypeGroups into the database
// This is a placeholder implementation; you need to write the actual logic
for _, data := range importData {
if data.ID != 0 {
// Update existing record
query := "UPDATE productgroups SET label = $1, description = $2 WHERE id = $3"
_, err := r.db.Exec(query, data.Label, data.Description, data.ID)
// Implement the ImportProducts method
func (r *ImportRepository) ImportProductGroups(importData []models.ImportProductGroup, parentProductGroupID int) error {
// check if ProductGroup allready exists
for _, productGroup := range importData {
if productGroup.ID != 0 {
// Update existing ProductGroup
query := "UPDATE productGroups SET label = $1, description = $2, parentGroupId = $3 WHERE id = $4"
_, err := r.db.Exec(query, productGroup.Label, productGroup.Description, parentProductGroupID, productGroup.ID)
if err != nil {
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 {
// Insert new record
err := r.db.QueryRow("INSERT INTO productgroups (label, description, parentGroupId) VALUES ($1, $2, $3) RETURNING id", data.Label, data.Description, parentGroupId).Scan(&data.ID)
// Insert new ProductGroup
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 {
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
}
if data.ProductGroups != nil {
return r.ImportProductGroups(data.ProductGroups, data.ID)
log.Printf("Retrieved PropertyTypeID: %d for label: %s", ptid, property.Label)
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
}
func (r *ImportRepository) ImportProducts(importData []models.ImportProduct, productGroupID int) error {
// Implement the logic to import Products into the database
for _, product := range importData {
if product.ID != 0 {
// Update existing Product
query := "UPDATE products SET externalId = $1, label = $2, description = $3, productGroupId = $4 WHERE id = $5"
_, err := r.db.Exec(query, product.ExternalID, product.Label, product.Description, productGroupID, product.ID)
if err != nil {
return err
}
if product.Properties != nil {
if err := r.ImportProperties(product.Properties, product.ID, productGroupID); err != nil {
return err
}
}
} else {
// Insert new Product
query := "INSERT INTO products (externalId, label, description, productGroupId) VALUES ($1, $2, $3, $4) RETURNING id"
err := r.db.QueryRow(query, product.ExternalID, product.Label, product.Description, productGroupID).Scan(&product.ID)
if err != nil {
return err
}
if product.Properties != nil {
if err := r.ImportProperties(product.Properties, product.ID, productGroupID); err != nil {
return err
}
}
}
}
return nil
}
func (r *ImportRepository) ImportProperties(importData []models.ImportProperty, productID int, productGroupID int) error {
for _, property := range importData {
var propertyType models.ImportPropertyType
var propertyIDs []int
propertyType, err := r.findPropertyType(property.Label)
func (r *ImportRepository) ImportProduct(product models.ImportProduct) error {
if product.ID != 0 {
// Update existing Product
query := "UPDATE products SET label = $1, description = $2, productGroupId = $3 WHERE id = $4"
_, err := r.db.Exec(query, product.Label, product.Description, product.ProductGroupID, product.ID)
if err != nil {
return err
}
if property.ID != 0 {
if err := r.updateProperty(property, property.ID, productID, productGroupID, propertyType); err != nil {
return err
}
} else {
propertyIDs, err = r.insertProperty(property, productID, productGroupID, propertyType)
if err != nil {
return err
}
} else {
// Insert new Product
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)
if err != nil {
return err
}
for _, propertyId := range propertyIDs {
property.ID = propertyId
if err := r.upsertValue(property, property.Value, propertyType.ID); err != nil {
return err
}
}
// 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 nil
}
func (r *ImportRepository) ImportProperty(property models.ImportProperty) error {
if property.ID != 0 {
// 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
}
} else {
// 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 {
return err
}
}
// Import Property Value for the Property
if property.Value != "" {
err := r.ImportPropertyValue(property.Value, property)
if err != nil {
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
}
func (r *ImportRepository) findPropertyType(label string) (models.ImportPropertyType, error) {
var propertyType models.ImportPropertyType
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 {
func (r *ImportRepository) ImportPropertyValue(value string, property models.ImportProperty) 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, property.ID).Scan(&existingValueID)
if err != nil {
if err != sql.ErrNoRows {
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, value, property.ID)
if err != nil {
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 {
_, err = r.db.Exec("INSERT INTO values (label, description, propertyId) VALUES ($1, $2, $3)", value, property.Label, propertyTypeId)
return err
}
return err
} else {
_, err = r.db.Exec("UPDATE values SET label = $1, description = $2 WHERE id = $3", value, property.Label, existingValueID)
} else if err != nil {
return err
}
return nil
}
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
}
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) {
// Implement the logic to retrieve the propertyTypes by groupId from the database
query := `SELECT id, label, description, propertytypegroupid FROM propertytypes WHERE propertytypegroupid=$1`