fix(BE): remove supplier price in master nonstock

This commit is contained in:
Hafizh A. Y
2026-01-15 15:49:15 +07:00
parent 2a884a8d09
commit fe002c9602
8 changed files with 38 additions and 54 deletions
@@ -0,0 +1,3 @@
-- Rollback: add price back to nonstock_suppliers
ALTER TABLE nonstock_suppliers
ADD COLUMN IF NOT EXISTS price NUMERIC(15, 3) NOT NULL DEFAULT 0;
@@ -0,0 +1,3 @@
-- Migration: remove price from nonstock_suppliers
ALTER TABLE nonstock_suppliers
DROP COLUMN IF EXISTS price;
-1
View File
@@ -5,7 +5,6 @@ import "time"
type NonstockSupplier struct { type NonstockSupplier struct {
NonstockId uint `gorm:"not null"` NonstockId uint `gorm:"not null"`
SupplierId uint `gorm:"not null"` SupplierId uint `gorm:"not null"`
Price float64 `gorm:"type:numeric(15,3);not null;default:0"`
CreatedAt time.Time `gorm:"autoCreateTime"` CreatedAt time.Time `gorm:"autoCreateTime"`
Nonstock Nonstock `gorm:"foreignKey:NonstockId;references:Id"` Nonstock Nonstock `gorm:"foreignKey:NonstockId;references:Id"`
@@ -37,7 +37,6 @@ type NonstockSupplierDTO struct {
Name string `json:"name"` Name string `json:"name"`
Alias string `json:"alias"` Alias string `json:"alias"`
Category string `json:"category"` Category string `json:"category"`
Price float64 `json:"price"`
} }
// === Mapper Functions === // === Mapper Functions ===
@@ -121,7 +120,6 @@ func toNonstockSupplierDTOs(relations []entity.NonstockSupplier) []NonstockSuppl
Name: relation.Supplier.Name, Name: relation.Supplier.Name,
Alias: relation.Supplier.Alias, Alias: relation.Supplier.Alias,
Category: relation.Supplier.Category, Category: relation.Supplier.Category,
Price: relation.Price,
}) })
} }
@@ -61,30 +61,20 @@ func (r *NonstockRepositoryImpl) SyncSuppliersDiff(ctx context.Context, tx *gorm
return err return err
} }
existingMap := make(map[uint]entity.NonstockSupplier, len(existing)) existingMap := make(map[uint]struct{}, len(existing))
for _, rel := range existing { for _, rel := range existing {
existingMap[rel.SupplierId] = rel existingMap[rel.SupplierId] = struct{}{}
} }
incomingMap := make(map[uint]struct{}, len(suppliers)) incomingMap := make(map[uint]struct{}, len(suppliers))
for _, rel := range suppliers { for _, rel := range suppliers {
incomingMap[rel.SupplierId] = struct{}{} incomingMap[rel.SupplierId] = struct{}{}
if existingRel, exists := existingMap[rel.SupplierId]; exists { if _, exists := existingMap[rel.SupplierId]; exists {
if existingRel.Price != rel.Price {
if err := db.WithContext(ctx).
Model(&entity.NonstockSupplier{}).
Where("nonstock_id = ? AND supplier_id = ?", nonstockID, rel.SupplierId).
Update("price", rel.Price).
Error; err != nil {
return err
}
}
continue continue
} }
record := entity.NonstockSupplier{ record := entity.NonstockSupplier{
NonstockId: nonstockID, NonstockId: nonstockID,
SupplierId: rel.SupplierId, SupplierId: rel.SupplierId,
Price: rel.Price,
} }
if err := db.WithContext(ctx).Create(&record).Error; err != nil { if err := db.WithContext(ctx).Create(&record).Error; err != nil {
return err return err
@@ -115,19 +115,18 @@ func (s *nonstockService) CreateOne(c *fiber.Ctx, req *validation.Create) (*enti
supplierLinks []entity.NonstockSupplier supplierLinks []entity.NonstockSupplier
supplierIDs []uint supplierIDs []uint
) )
if len(req.Suppliers) > 0 { if len(req.SupplierIDs) > 0 {
seen := make(map[uint]struct{}, len(req.Suppliers)) seen := make(map[uint]struct{}, len(req.SupplierIDs))
supplierLinks = make([]entity.NonstockSupplier, 0, len(req.Suppliers)) supplierLinks = make([]entity.NonstockSupplier, 0, len(req.SupplierIDs))
supplierIDs = make([]uint, 0, len(req.Suppliers)) supplierIDs = make([]uint, 0, len(req.SupplierIDs))
for _, supplier := range req.Suppliers { for _, supplierID := range req.SupplierIDs {
if _, exists := seen[supplier.SupplierID]; exists { if _, exists := seen[supplierID]; exists {
return nil, fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Duplicate supplier_id %d", supplier.SupplierID)) return nil, fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Duplicate supplier_id %d", supplierID))
} }
seen[supplier.SupplierID] = struct{}{} seen[supplierID] = struct{}{}
supplierIDs = append(supplierIDs, supplier.SupplierID) supplierIDs = append(supplierIDs, supplierID)
supplierLinks = append(supplierLinks, entity.NonstockSupplier{ supplierLinks = append(supplierLinks, entity.NonstockSupplier{
SupplierId: supplier.SupplierID, SupplierId: supplierID,
Price: supplier.Price,
}) })
} }
supplierList, supplierErr := s.Repository.GetSuppliersByIDs(ctx, supplierIDs) supplierList, supplierErr := s.Repository.GetSuppliersByIDs(ctx, supplierIDs)
@@ -212,21 +211,20 @@ func (s nonstockService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uint
var supplierLinks []entity.NonstockSupplier var supplierLinks []entity.NonstockSupplier
var supplierUpdate bool var supplierUpdate bool
if req.Suppliers != nil { if req.SupplierIDs != nil {
supplierUpdate = true supplierUpdate = true
if len(*req.Suppliers) > 0 { if len(*req.SupplierIDs) > 0 {
seen := make(map[uint]struct{}, len(*req.Suppliers)) seen := make(map[uint]struct{}, len(*req.SupplierIDs))
supplierLinks = make([]entity.NonstockSupplier, 0, len(*req.Suppliers)) supplierLinks = make([]entity.NonstockSupplier, 0, len(*req.SupplierIDs))
supplierIDs := make([]uint, 0, len(*req.Suppliers)) supplierIDs := make([]uint, 0, len(*req.SupplierIDs))
for _, supplier := range *req.Suppliers { for _, supplierID := range *req.SupplierIDs {
if _, exists := seen[supplier.SupplierID]; exists { if _, exists := seen[supplierID]; exists {
return nil, fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Duplicate supplier_id %d", supplier.SupplierID)) return nil, fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Duplicate supplier_id %d", supplierID))
} }
seen[supplier.SupplierID] = struct{}{} seen[supplierID] = struct{}{}
supplierIDs = append(supplierIDs, supplier.SupplierID) supplierIDs = append(supplierIDs, supplierID)
supplierLinks = append(supplierLinks, entity.NonstockSupplier{ supplierLinks = append(supplierLinks, entity.NonstockSupplier{
SupplierId: supplier.SupplierID, SupplierId: supplierID,
Price: supplier.Price,
}) })
} }
@@ -1,22 +1,17 @@
package validation package validation
type SupplierPrice struct {
SupplierID uint `json:"supplier_id" validate:"required,gt=0"`
Price float64 `json:"price" validate:"required,gte=0"`
}
type Create struct { type Create struct {
Name string `json:"name" validate:"required_strict,min=3,max=50"` Name string `json:"name" validate:"required_strict,min=3,max=50"`
UomID uint `json:"uom_id" validate:"required,gt=0"` UomID uint `json:"uom_id" validate:"required,gt=0"`
Suppliers []SupplierPrice `json:"suppliers,omitempty" validate:"omitempty,dive"` SupplierIDs []uint `json:"supplier_ids,omitempty" validate:"omitempty,dive,gt=0"`
Flags []string `json:"flags" validate:"dive,max=50"` Flags []string `json:"flags" validate:"dive,max=50"`
} }
type Update struct { type Update struct {
Name *string `json:"name,omitempty" validate:"omitempty,min=3,max=50"` Name *string `json:"name,omitempty" validate:"omitempty,min=3,max=50"`
UomID *uint `json:"uom_id,omitempty" validate:"omitempty,gt=0"` UomID *uint `json:"uom_id,omitempty" validate:"omitempty,gt=0"`
Suppliers *[]SupplierPrice `json:"suppliers,omitempty" validate:"omitempty,dive"` SupplierIDs *[]uint `json:"supplier_ids,omitempty" validate:"omitempty,dive,gt=0"`
Flags *[]string `json:"flags,omitempty" validate:"omitempty,dive,max=50"` Flags *[]string `json:"flags,omitempty" validate:"omitempty,dive,max=50"`
} }
type Query struct { type Query struct {
@@ -10,7 +10,6 @@ import (
type SupplierNonstockDTO struct { type SupplierNonstockDTO struct {
Id uint `json:"id"` Id uint `json:"id"`
Name string `json:"name"` Name string `json:"name"`
Price float64 `json:"price"`
Uom *uomDTO.UomRelationDTO `json:"uom,omitempty"` Uom *uomDTO.UomRelationDTO `json:"uom,omitempty"`
Flags []string `json:"flags"` Flags []string `json:"flags"`
} }
@@ -43,7 +42,6 @@ func toSupplierNonstockDTOs(relations []entity.NonstockSupplier) []SupplierNonst
result = append(result, SupplierNonstockDTO{ result = append(result, SupplierNonstockDTO{
Id: Nonstock.Id, Id: Nonstock.Id,
Name: Nonstock.Name, Name: Nonstock.Name,
Price: relation.Price,
Uom: uomRef, Uom: uomRef,
Flags: flags, Flags: flags,
}) })