Produkte und Properties im Server
This commit is contained in:
@@ -72,7 +72,7 @@ CREATE TABLE tabelle_a (
|
||||
|
||||
- updateValueFromValueId
|
||||
|
||||
- add
|
||||
- addValueToPropertyType
|
||||
|
||||
- Produkte haben zusätzlich zur ID, Label und Beschreibung noch eine externalId.
|
||||
|
||||
@@ -107,7 +107,7 @@ CREATE TABLE IF NOT EXISTS values (
|
||||
id BIGINT PRIMARY KEY DEFAULT nextval('global_id_seq'),
|
||||
Label TEXT,
|
||||
description TEXT,
|
||||
propertyId BIGINT
|
||||
propertyGroupId BIGINT
|
||||
);
|
||||
|
||||
-- Property Table
|
||||
@@ -163,11 +163,8 @@ CREATE TABLE IF NOT EXISTS media (
|
||||
mediaType TEXT,
|
||||
externalId BIGINT
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Open Aufsetzen des Source Codes:
|
||||
|
||||
````
|
||||
@@ -218,4 +215,47 @@ go get github.com/gin-contrib/cors
|
||||
|
||||
## Server API
|
||||
|
||||
Die Server-API baut auf HTTP und auf REST auf. Antworten werden im JSON Format gesendet,ebenso, wie neu anzulegende Daten oder zu aktualisierende Daten.
|
||||
Die Server-API baut auf HTTP und auf REST auf. Antworten werden im JSON Format gesendet,ebenso, wie neu anzulegende Daten oder zu aktualisierende Daten.
|
||||
|
||||
Generell werden Daten im JSON Format ausgetauscht. Z.B. wird ein *Value* Objekt in From von *application/json Daten* übergeben:
|
||||
|
||||
```gettext
|
||||
put: http://server:port/updatePropertyType
|
||||
```
|
||||
|
||||
benötigt folgende Struktur im Anfragekörper:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 1000003,
|
||||
"label": "Colour",
|
||||
"description": "System wide colors",
|
||||
"propertyTypeGroupId": 100002
|
||||
}
|
||||
```
|
||||
|
||||
und liefert als Ergebnis (wenn kein Fehler auftritt):
|
||||
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"id": 1000003,
|
||||
"label": "Colour",
|
||||
"description": "System wide colors",
|
||||
"propertyTypeGroupId": 100002
|
||||
},
|
||||
"message": "PropertyType updated"
|
||||
}
|
||||
```
|
||||
|
||||
Wenn Daten zurückkommen, so wie hier im Beispiel, dann werden sie im *"data"* Tag geschrieben. Meistens kommt auch noch eine Nachricht mit, die in *"message"* steht.
|
||||
|
||||
Im Falle eines Fehler kommt eine entsprechende Nachricht zurück (z.B. wenn es keinen PropertyType mit der entsprechenden *ID* gibt):
|
||||
|
||||
```json
|
||||
{
|
||||
"error": "sql: no rows in result set"
|
||||
}
|
||||
```
|
||||
|
||||
### Value und Property Funktionen
|
||||
@@ -0,0 +1,142 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"simplycpq/models"
|
||||
"simplycpq/services"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type ProductController struct {
|
||||
productService *services.ProductService
|
||||
productGroupService *services.ProductGroupService
|
||||
valueService *services.ValueService
|
||||
}
|
||||
|
||||
func NewProductController(productService *services.ProductService, productGroupService *services.ProductGroupService, valueService *services.ValueService) *ProductController {
|
||||
return &ProductController{
|
||||
productService: productService,
|
||||
productGroupService: productGroupService,
|
||||
valueService: valueService,
|
||||
}
|
||||
}
|
||||
|
||||
func (pc *ProductController) CreateProduct(c *gin.Context) {
|
||||
var product models.Product
|
||||
if err := c.ShouldBindJSON(&product); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
createdProduct, err := pc.productService.CreateProduct(&product)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"status": "product created successfully", "data": createdProduct})
|
||||
}
|
||||
|
||||
func (pc *ProductController) UpdateProduct(c *gin.Context) {
|
||||
var product models.Product
|
||||
if err := c.ShouldBindJSON(&product); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
if err := pc.productService.UpdateProduct(&product); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"status": "product updated successfully"})
|
||||
}
|
||||
|
||||
func (pc *ProductController) DeleteProduct(c *gin.Context) {
|
||||
id, err := strconv.Atoi(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid product id"})
|
||||
return
|
||||
}
|
||||
if err := pc.productService.DeleteProduct(id); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"status": "product deleted successfully"})
|
||||
}
|
||||
|
||||
func (pc *ProductController) GetProduct(c *gin.Context) {
|
||||
id, err := strconv.Atoi(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid product id"})
|
||||
return
|
||||
}
|
||||
product, err := pc.productService.GetProductById(id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"status": "product retrieved successfully", "product": product})
|
||||
}
|
||||
|
||||
func (pc *ProductController) GetProductsByGroupId(c *gin.Context) {
|
||||
groupId, err := strconv.Atoi(c.Param("groupId"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid group id"})
|
||||
return
|
||||
}
|
||||
products, err := pc.productService.GetProductsByGroupId(groupId)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"status": "products retrieved successfully", "groupId": groupId, "products": products})
|
||||
}
|
||||
|
||||
func (pc *ProductController) AddPropertyToProductId(c *gin.Context) {
|
||||
productId, err := strconv.Atoi(c.Param("productId"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid product id"})
|
||||
return
|
||||
}
|
||||
propertyId, err := strconv.Atoi(c.Param("propertyId"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid property id"})
|
||||
return
|
||||
}
|
||||
if err := pc.productService.AddPropertyToProduct(productId, propertyId); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"status": "property added to product successfully", "productId": productId, "propertyId": propertyId})
|
||||
}
|
||||
|
||||
func (pc *ProductController) DeletePropertyFromProductId(c *gin.Context) {
|
||||
productId, err := strconv.Atoi(c.Param("productId"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid product id"})
|
||||
return
|
||||
}
|
||||
propertyId, err := strconv.Atoi(c.Param("propertyId"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid property id"})
|
||||
return
|
||||
}
|
||||
if err := pc.productService.DeletePropertyFromProduct(productId, propertyId); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"status": "property deleted from product successfully", "productId": productId, "propertyId": propertyId})
|
||||
}
|
||||
|
||||
func (pc *ProductController) GetPropertiesFromProductId(c *gin.Context) {
|
||||
productId, err := strconv.Atoi(c.Param("productId"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid product id"})
|
||||
return
|
||||
}
|
||||
properties, err := pc.productService.GetPropertiesFromProduct(productId)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"status": "properties retrieved from product successfully", "productId": productId, "properties": properties})
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"simplycpq/models"
|
||||
"simplycpq/services"
|
||||
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type ProductGroupController struct {
|
||||
productGroupService *services.ProductGroupService
|
||||
valueService *services.ValueService
|
||||
}
|
||||
|
||||
func NewProductGroupController(productGroupService *services.ProductGroupService, valueService *services.ValueService) *ProductGroupController {
|
||||
return &ProductGroupController{
|
||||
productGroupService: productGroupService,
|
||||
valueService: valueService,
|
||||
}
|
||||
}
|
||||
|
||||
func (pgc *ProductGroupController) CreateProductGroup(c *gin.Context) {
|
||||
var productGroup models.ProductGroup
|
||||
if err := c.ShouldBindJSON(&productGroup); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
createdProductGroup, err := pgc.productGroupService.CreateProductGroup(&productGroup)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, createdProductGroup)
|
||||
}
|
||||
|
||||
func (pgc *ProductGroupController) UpdateProductGroup(c *gin.Context) {
|
||||
var productGroup models.ProductGroup
|
||||
if err := c.ShouldBindJSON(&productGroup); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
updatedProductGroup, err := pgc.productGroupService.UpdateProductGroup(&productGroup)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, updatedProductGroup)
|
||||
}
|
||||
|
||||
func (pgc *ProductGroupController) DeleteProductGroup(c *gin.Context) {
|
||||
id, err := strconv.Atoi(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"})
|
||||
return
|
||||
}
|
||||
err = pgc.productGroupService.DeleteProductGroup(id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"message": "ProductGroup deleted successfully"})
|
||||
}
|
||||
|
||||
func (pgc *ProductGroupController) GetProductGroup(c *gin.Context) {
|
||||
id, err := strconv.Atoi(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"})
|
||||
return
|
||||
}
|
||||
productGroup, err := pgc.productGroupService.GetProductGroup(id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, productGroup)
|
||||
}
|
||||
|
||||
func (pgc *ProductGroupController) GetProductGroupsByParentId(c *gin.Context) {
|
||||
parentId, err := strconv.Atoi(c.Param("parentId"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid parent ID"})
|
||||
return
|
||||
}
|
||||
productGroups, err := pgc.productGroupService.GetProductGroupsByParentId(parentId)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, productGroups)
|
||||
}
|
||||
|
||||
func (pgc *ProductGroupController) DeleteProductFromProductGroupId(c *gin.Context) {
|
||||
productId, err := strconv.Atoi(c.Param("productId"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid product ID"})
|
||||
return
|
||||
}
|
||||
err = pgc.productGroupService.DeleteProductFromProductGroupId(productId)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"message": "Product deleted from product group successfully"})
|
||||
}
|
||||
|
||||
func (pgc *ProductGroupController) GetPropertiesFromProductGroupId(c *gin.Context) {
|
||||
productGroupId, err := strconv.Atoi(c.Param("productGroupId"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid product group ID"})
|
||||
return
|
||||
}
|
||||
properties, err := pgc.productGroupService.GetPropertiesFromProductGroupId(productGroupId)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, properties)
|
||||
}
|
||||
|
||||
func (pgc *ProductGroupController) DeletePropertyFromProductGroupId(c *gin.Context) {
|
||||
propertyId, err := strconv.Atoi(c.Param("propertyId"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid property ID"})
|
||||
return
|
||||
}
|
||||
productGroupId, err := strconv.Atoi(c.Param("productGroupId"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid product group ID"})
|
||||
return
|
||||
}
|
||||
err = pgc.productGroupService.DeletePropertyFromProductGroup(productGroupId, propertyId)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"message": "Property deleted from product group successfully"})
|
||||
}
|
||||
|
||||
func (pgc *ProductGroupController) CreatePropertyToProductGroupId(c *gin.Context) {
|
||||
var property models.Property
|
||||
if err := c.ShouldBindJSON(&property); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
productGroupId, err := strconv.Atoi(c.Param("productGroupId"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid product group ID"})
|
||||
return
|
||||
}
|
||||
|
||||
property2, err := pgc.productGroupService.CreatePropertyToProductGroupId(productGroupId, &property)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, property2)
|
||||
}
|
||||
@@ -19,6 +19,8 @@ type Property struct {
|
||||
Label string `json:"label"`
|
||||
Description string `json:"description"`
|
||||
PropertyTypeID int `json:"propertyTypeId"`
|
||||
ProductID int `json:"productId"`
|
||||
ProductGroupID int `json:"productGroupId"`
|
||||
}
|
||||
|
||||
type Value struct {
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
package repositories
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"simplycpq/models"
|
||||
)
|
||||
|
||||
type ProductGroupRepository struct {
|
||||
db *sql.DB
|
||||
valueRepository *ValueRepository
|
||||
}
|
||||
|
||||
func NewProductGroupRepository(db *sql.DB, valueRepository *ValueRepository) *ProductGroupRepository {
|
||||
return &ProductGroupRepository{
|
||||
db: db,
|
||||
valueRepository: valueRepository,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *ProductGroupRepository) CreateProductGroup(productGroup *models.ProductGroup) (*models.ProductGroup, error) {
|
||||
// Insert the product group into the database
|
||||
query := "INSERT INTO product_groups (label, description, parentgroupid) VALUES($1,$2,$3) RETURNING id"
|
||||
err := r.db.QueryRow(query, productGroup.Label, productGroup.Description, productGroup.ParentGroupID).Scan(&productGroup.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// get all properties from parent group and copy them to the new group
|
||||
if productGroup.ParentGroupID != 0 {
|
||||
properties, err := r.GetPropertiesFromProductGroupId(productGroup.ParentGroupID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, prop := range properties {
|
||||
_, err := r.valueRepository.createPropertyFromProperty(productGroup.ID, 0, prop)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return productGroup, nil
|
||||
}
|
||||
|
||||
func (r *ProductGroupRepository) UpdateProductGroup(productGroup *models.ProductGroup) (*models.ProductGroup, error) {
|
||||
query := "UPDATE product_groups SET label=$1, description=$2, parentgroupid=$3 WHERE id=$4"
|
||||
_, err := r.db.Exec(query, productGroup.Label, productGroup.Description, productGroup.ParentGroupID, productGroup.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return productGroup, nil
|
||||
}
|
||||
|
||||
func (r *ProductGroupRepository) DeleteProductGroup(id int) error {
|
||||
query := "DELETE FROM product_groups WHERE id=$1"
|
||||
_, err := r.db.Exec(query, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *ProductGroupRepository) GetProductGroup(id int) (*models.ProductGroup, error) {
|
||||
query := "SELECT id, label, description, parentgroupid FROM product_groups WHERE id=$1"
|
||||
row := r.db.QueryRow(query, id)
|
||||
productGroup := &models.ProductGroup{}
|
||||
err := row.Scan(&productGroup.ID, &productGroup.Label, &productGroup.Description, &productGroup.ParentGroupID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return productGroup, nil
|
||||
}
|
||||
|
||||
func (r *ProductGroupRepository) GetProductGroupsByParentId(parentId int) ([]*models.ProductGroup, error) {
|
||||
query := "SELECT id, label, description, parentgroupid FROM product_groups WHERE parentgroupid=$1"
|
||||
rows, err := r.db.Query(query, parentId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var productGroups []*models.ProductGroup
|
||||
for rows.Next() {
|
||||
var productGroup models.ProductGroup
|
||||
err := rows.Scan(&productGroup.ID, &productGroup.Label, &productGroup.Description, &productGroup.ParentGroupID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
productGroups = append(productGroups, &productGroup)
|
||||
}
|
||||
if err = rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return productGroups, nil
|
||||
}
|
||||
|
||||
func (r *ProductGroupRepository) DeleteProductFromProductGroupId(productGroupId int) error {
|
||||
query := "DELETE FROM products WHERE productgroupid=$1"
|
||||
_, err := r.db.Exec(query, productGroupId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *ProductGroupRepository) GetPropertiesFromProductGroupId(productGroupId int) ([]*models.Property, error) {
|
||||
query := "SELECT id, label, description, propertytypeid, productid, productgroupid FROM properties WHERE productgroupid=$1"
|
||||
rows, err := r.db.Query(query, productGroupId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var properties []*models.Property
|
||||
for rows.Next() {
|
||||
var property models.Property
|
||||
err := rows.Scan(&property.ID, &property.Label, &property.Description, &property.PropertyTypeID, &property.ProductID, &property.ProductGroupID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
properties = append(properties, &property)
|
||||
}
|
||||
if err = rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return properties, nil
|
||||
}
|
||||
|
||||
func (r *ProductGroupRepository) DeletePropertyFromProductGroup(productGroupId int, propertyId int) error {
|
||||
query := "DELETE FROM properties WHERE productgroupid=$1 AND id=$2"
|
||||
_, err := r.db.Exec(query, productGroupId, propertyId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *ProductGroupRepository) CreatePropertyFromProductGroup(productGroupId int, property *models.Property) (*models.Property, error) {
|
||||
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.Description, property.PropertyTypeID, property.ProductID, productGroupId).Scan(&property.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// copy property values from parent group to new property
|
||||
if productGroupId != 0 {
|
||||
err := r.valueRepository.copyValuesFromPropertyTypeToProperty(property.ID, property.PropertyTypeID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return property, nil
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
package repositories
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"simplycpq/models"
|
||||
)
|
||||
|
||||
type ProductRepository struct {
|
||||
dbHandler *sql.DB
|
||||
productGroupRepository *ProductGroupRepository
|
||||
valueRepository *ValueRepository
|
||||
}
|
||||
|
||||
func NewProductRepository(dbHandler *sql.DB, productGroupRepository *ProductGroupRepository, valueRepository *ValueRepository) *ProductRepository {
|
||||
return &ProductRepository{
|
||||
dbHandler: dbHandler,
|
||||
productGroupRepository: productGroupRepository,
|
||||
valueRepository: valueRepository,
|
||||
}
|
||||
}
|
||||
|
||||
func (pr *ProductRepository) CreateProduct(product *models.Product) (*models.Product, error) {
|
||||
// Implement the logic to insert a new product into the database
|
||||
query := "INSERT INTO products (label, externalId, description, productGroupId) VALUES ($1, $2, $3, $4) RETURNING id"
|
||||
err := pr.dbHandler.QueryRow(query, product.Label, product.ExternalID, product.Description, product.ProductGroupID).Scan(&product.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// copy Properties from ProductGroup to Product
|
||||
properties, err := pr.productGroupRepository.GetPropertiesFromProductGroupId(product.ProductGroupID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, property := range properties {
|
||||
_, err := pr.valueRepository.createPropertyFromProperty(0, product.ID, property)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return product, nil
|
||||
}
|
||||
|
||||
func (pr *ProductRepository) GetProductById(id int) (*models.Product, error) {
|
||||
// Implement the logic to retrieve a product by its ID from the database
|
||||
query := "SELECT id, label, externalId, description, productGroupId FROM products WHERE id = $1"
|
||||
row := pr.dbHandler.QueryRow(query, id)
|
||||
product := &models.Product{}
|
||||
err := row.Scan(&product.ID, &product.Label, &product.ExternalID, &product.Description, &product.ProductGroupID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return product, nil
|
||||
}
|
||||
|
||||
func (pr *ProductRepository) UpdateProduct(product *models.Product) error {
|
||||
// Implement the logic to update an existing product in the database
|
||||
query := "UPDATE products SET label = $1, externalId = $2, description = $3, productGroupId = $4 WHERE id = $5"
|
||||
_, err := pr.dbHandler.Exec(query, product.Label, product.ExternalID, product.Description, product.ProductGroupID, product.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
func (pr *ProductRepository) DeleteProduct(id int) error {
|
||||
// Implement the logic to delete a product from the database
|
||||
query := "DELETE FROM products WHERE id = $1"
|
||||
_, err := pr.dbHandler.Exec(query, id)
|
||||
return err
|
||||
}
|
||||
|
||||
func (pr *ProductRepository) GetProductsByGroupId(groupId int) ([]*models.Product, error) {
|
||||
// Implement the logic to retrieve all products by their group ID from the database
|
||||
query := "SELECT id, label, externalId, description, productGroupId FROM products WHERE productGroupId = $1"
|
||||
rows, err := pr.dbHandler.Query(query, groupId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
products := []*models.Product{}
|
||||
for rows.Next() {
|
||||
product := &models.Product{}
|
||||
err := rows.Scan(&product.ID, &product.Label, &product.ExternalID, &product.Description, &product.ProductGroupID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
products = append(products, product)
|
||||
}
|
||||
return products, nil
|
||||
}
|
||||
|
||||
func (pr *ProductRepository) AddPropertyToProduct(productId int, propertyId int) error {
|
||||
// Implement the logic to add a property to a product in the database
|
||||
query := "INSERT INTO product_properties (productId, propertyId) VALUES ($1, $2)"
|
||||
_, err := pr.dbHandler.Exec(query, productId, propertyId)
|
||||
return err
|
||||
}
|
||||
|
||||
func (pr *ProductRepository) DeletePropertyFromProduct(productId int, propertyId int) error {
|
||||
// Implement the logic to delete a property from a product in the database
|
||||
query := "DELETE FROM product_properties WHERE productId = $1 AND propertyId = $2"
|
||||
_, err := pr.dbHandler.Exec(query, productId, propertyId)
|
||||
return err
|
||||
}
|
||||
|
||||
func (pr *ProductRepository) GetPropertiesFromProduct(productId int) ([]*models.Property, error) {
|
||||
// Implement the logic to retrieve all properties from a product in the database
|
||||
query := "SELECT id, label, description, propertyTypeId, productId, productGroupId FROM properties WHERE productId = $1"
|
||||
rows, err := pr.dbHandler.Query(query, productId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
properties := []*models.Property{}
|
||||
for rows.Next() {
|
||||
property := &models.Property{}
|
||||
err := rows.Scan(&property.ID, &property.Label, &property.Description, &property.PropertyTypeID, &property.ProductID, &property.ProductGroupID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
properties = append(properties, property)
|
||||
}
|
||||
return properties, nil
|
||||
}
|
||||
@@ -267,6 +267,48 @@ func (vr *ValueRepository) GetValue(id int) (*models.Value, error) {
|
||||
return &value, nil
|
||||
}
|
||||
|
||||
func (vr *ValueRepository) createPropertyFromPropertyType(productGroupId int, productId int, propertyType *models.PropertyType) (*models.Property, error) {
|
||||
query := `INSERT INTO properties (label, description, propertytypeid, productid, productgroupid) VALUES ($1, $2, $3, $4, $5) RETURNING id`
|
||||
var property models.Property
|
||||
err := vr.db.QueryRow(query, propertyType.Label, propertyType.Description, propertyType.ID, productId, productGroupId).Scan(&property.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
property.Label = propertyType.Label
|
||||
property.Description = propertyType.Description
|
||||
property.PropertyTypeID = propertyType.ID
|
||||
property.ProductID = productId
|
||||
property.ProductGroupID = productGroupId
|
||||
|
||||
// Copy values from property type to property
|
||||
err = vr.copyValuesFromPropertyTypeToProperty(propertyType.ID, property.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &property, nil
|
||||
}
|
||||
|
||||
func (vr *ValueRepository) createPropertyFromProperty(productGroupId int, productId int, property *models.Property) (*models.Property, error) {
|
||||
query := `INSERT INTO properties (label, description, propertytypeid, productid, productgroupid) VALUES ($1, $2, $3, $4, $5) RETURNING id`
|
||||
var newProperty models.Property
|
||||
err := vr.db.QueryRow(query, property.Label, property.Description, property.PropertyTypeID, productId, productGroupId).Scan(&newProperty.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newProperty.Label = property.Label
|
||||
newProperty.Description = property.Description
|
||||
newProperty.PropertyTypeID = property.PropertyTypeID
|
||||
newProperty.ProductID = productId
|
||||
newProperty.ProductGroupID = productGroupId
|
||||
|
||||
// Copy values from property type to property
|
||||
err = vr.copyValuesFromPropertyToProperty(property.ID, newProperty.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &newProperty, nil
|
||||
}
|
||||
|
||||
func (vr *ValueRepository) copyValuesFromPropertyTypeToProperty(propertyTypeId int, propertyId int) error {
|
||||
// Implement the logic to copy values from a property type to a property
|
||||
query := `INSERT INTO values (propertyId, label, description) SELECT $1, label, description FROM values WHERE propertytypeid=$2`
|
||||
|
||||
@@ -15,20 +15,30 @@ import (
|
||||
)
|
||||
|
||||
type HttpServer struct {
|
||||
config *viper.Viper
|
||||
router *gin.Engine
|
||||
dbHandler *sql.DB
|
||||
valueController *controller.ValueController
|
||||
config *viper.Viper
|
||||
router *gin.Engine
|
||||
dbHandler *sql.DB
|
||||
valueController *controller.ValueController
|
||||
productGroupController *controller.ProductGroupController
|
||||
productController *controller.ProductController
|
||||
}
|
||||
|
||||
func InitHttpServer(config *viper.Viper, dbHandler *sql.DB) HttpServer {
|
||||
|
||||
// repository initialisation:
|
||||
valueRepository := repositories.NewValueRepository(dbHandler)
|
||||
productGroupRepository := repositories.NewProductGroupRepository(dbHandler, valueRepository)
|
||||
productRepository := repositories.NewProductRepository(dbHandler, productGroupRepository, valueRepository)
|
||||
|
||||
// service initialisation:
|
||||
valueService := services.NewValueService(valueRepository)
|
||||
productGroupService := services.NewProductGroupService(productGroupRepository)
|
||||
productService := services.NewProductService(productRepository)
|
||||
|
||||
// controller initialisation:
|
||||
valueController := controller.NewValueController(valueService)
|
||||
productGroupController := controller.NewProductGroupController(productGroupService, valueService)
|
||||
productController := controller.NewProductController(productService, productGroupService, valueService)
|
||||
|
||||
// Service API
|
||||
router := gin.Default()
|
||||
@@ -55,13 +65,34 @@ func InitHttpServer(config *viper.Viper, dbHandler *sql.DB) HttpServer {
|
||||
router.GET("/getValue/:id", valueController.GetValue) // get Value by id
|
||||
|
||||
// Product centric routing
|
||||
// ProductGroup
|
||||
router.POST("/createProductGroup", productGroupController.CreateProductGroup) // create ProductGroup
|
||||
router.PUT("/updateProductGroup", productGroupController.UpdateProductGroup) // update ProductGroup
|
||||
router.DELETE("/deleteProductGroup/:id", productGroupController.DeleteProductGroup) // delete ProductGroup
|
||||
router.GET("/getProductGroup/:id", productGroupController.GetProductGroup) // get ProductGroup by id
|
||||
router.GET("/getProductGroupsByParentId/:parentId", productGroupController.GetProductGroupsByParentId) // get all ProductGroups by parent ID
|
||||
router.DELETE("/deleteProductFromProductGroupId/:productId", productGroupController.DeleteProductFromProductGroupId) // delete Product from ProductGroup by ID
|
||||
router.POST("/getPropertiesFromProductGroupId/:productGroupId", productGroupController.GetPropertiesFromProductGroupId) // get Properties from ProductGroup by ID
|
||||
router.DELETE("/deletePropertyFromProductGroupId/:propertyId/:productGroupId", productGroupController.DeletePropertyFromProductGroupId) // delete Property from ProductGroup by ID
|
||||
router.POST("/createPropertyToProductGroupId/:propertyTypeId/:productGroupId", productGroupController.CreatePropertyToProductGroupId) // add Property to ProductGroup by ID
|
||||
|
||||
// Product
|
||||
router.POST("/createProduct", productController.CreateProduct) // create Product
|
||||
router.PUT("/updateProduct", productController.UpdateProduct) // update Product
|
||||
router.DELETE("/deleteProduct/:id", productController.DeleteProduct) // delete Product
|
||||
router.GET("/getProduct/:id", productController.GetProduct) // get Product by id
|
||||
router.GET("/getProductsByGroupId/:groupId", productController.GetProductsByGroupId) // get all Products by group ID
|
||||
router.POST("/addPropertyToProductId/:productId", productController.AddPropertyToProductId) // add Property to Product by ID
|
||||
router.DELETE("/deletePropertyFromProductId/:productId", productController.DeletePropertyFromProductId) // delete Property from Product by ID
|
||||
|
||||
// server
|
||||
return HttpServer{
|
||||
config: config,
|
||||
router: router,
|
||||
dbHandler: dbHandler,
|
||||
valueController: valueController,
|
||||
config: config,
|
||||
router: router,
|
||||
dbHandler: dbHandler,
|
||||
valueController: valueController,
|
||||
productGroupController: productGroupController,
|
||||
productController: productController,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"simplycpq/models"
|
||||
"simplycpq/repositories"
|
||||
)
|
||||
|
||||
type ProductGroupService struct {
|
||||
productGroupRepository *repositories.ProductGroupRepository
|
||||
}
|
||||
|
||||
func NewProductGroupService(productGroupRepository *repositories.ProductGroupRepository) *ProductGroupService {
|
||||
return &ProductGroupService{
|
||||
productGroupRepository: productGroupRepository,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ProductGroupService) CreateProductGroup(productGroup *models.ProductGroup) (*models.ProductGroup, error) {
|
||||
return s.productGroupRepository.CreateProductGroup(productGroup)
|
||||
}
|
||||
|
||||
func (s *ProductGroupService) UpdateProductGroup(productGroup *models.ProductGroup) (*models.ProductGroup, error) {
|
||||
return s.productGroupRepository.UpdateProductGroup(productGroup)
|
||||
}
|
||||
|
||||
func (s *ProductGroupService) DeleteProductGroup(id int) error {
|
||||
return s.productGroupRepository.DeleteProductGroup(id)
|
||||
}
|
||||
|
||||
func (s *ProductGroupService) GetProductGroup(id int) (*models.ProductGroup, error) {
|
||||
return s.productGroupRepository.GetProductGroup(id)
|
||||
}
|
||||
|
||||
func (s *ProductGroupService) GetPropertiesFromProductGroupId(id int) ([]*models.Property, error) {
|
||||
return s.productGroupRepository.GetPropertiesFromProductGroupId(id)
|
||||
}
|
||||
|
||||
func (s *ProductGroupService) GetProductGroupsByParentId(parentId int) ([]*models.ProductGroup, error) {
|
||||
return s.productGroupRepository.GetProductGroupsByParentId(parentId)
|
||||
}
|
||||
|
||||
func (s *ProductGroupService) DeleteProductFromProductGroupId(productGroupId int) error {
|
||||
return s.productGroupRepository.DeleteProductFromProductGroupId(productGroupId)
|
||||
}
|
||||
|
||||
func (s *ProductGroupService) GetPropertiesFromProductGroup(productGroupId int) ([]*models.Property, error) {
|
||||
return s.productGroupRepository.GetPropertiesFromProductGroupId(productGroupId)
|
||||
}
|
||||
|
||||
func (s *ProductGroupService) DeletePropertyFromProductGroup(productGroupId int, propertyId int) error {
|
||||
return s.productGroupRepository.DeletePropertyFromProductGroup(productGroupId, propertyId)
|
||||
}
|
||||
|
||||
func (s *ProductGroupService) CreatePropertyToProductGroupId(productGroupId int, property *models.Property) (*models.Property, error) {
|
||||
return s.productGroupRepository.CreatePropertyFromProductGroup(productGroupId, property)
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"simplycpq/models"
|
||||
"simplycpq/repositories"
|
||||
)
|
||||
|
||||
type ProductService struct {
|
||||
productRepository *repositories.ProductRepository
|
||||
}
|
||||
|
||||
func NewProductService(productRepository *repositories.ProductRepository) *ProductService {
|
||||
return &ProductService{
|
||||
productRepository: productRepository,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ProductService) CreateProduct(product *models.Product) (*models.Product, error) {
|
||||
return s.productRepository.CreateProduct(product)
|
||||
}
|
||||
func (s *ProductService) UpdateProduct(product *models.Product) error {
|
||||
return s.productRepository.UpdateProduct(product)
|
||||
}
|
||||
|
||||
func (s *ProductService) DeleteProduct(id int) error {
|
||||
return s.productRepository.DeleteProduct(id)
|
||||
}
|
||||
|
||||
func (s *ProductService) GetProduct(id int) (*models.Product, error) {
|
||||
return s.productRepository.GetProductById(id)
|
||||
}
|
||||
|
||||
func (s *ProductService) GetProductById(id int) (*models.Product, error) {
|
||||
return s.productRepository.GetProductById(id)
|
||||
}
|
||||
|
||||
func (s *ProductService) GetProductsByGroupId(groupId int) ([]*models.Product, error) {
|
||||
return s.productRepository.GetProductsByGroupId(groupId)
|
||||
}
|
||||
|
||||
func (s *ProductService) AddPropertyToProduct(productId int, propertyId int) error {
|
||||
return s.productRepository.AddPropertyToProduct(productId, propertyId)
|
||||
}
|
||||
|
||||
func (s *ProductService) DeletePropertyFromProduct(productId int, propertyId int) error {
|
||||
return s.productRepository.DeletePropertyFromProduct(productId, propertyId)
|
||||
}
|
||||
|
||||
func (s *ProductService) GetPropertiesFromProduct(productId int) ([]*models.Property, error) {
|
||||
return s.productRepository.GetPropertiesFromProduct(productId)
|
||||
}
|
||||
Reference in New Issue
Block a user