package entities import ( "fmt" "strings" "time" "github.com/google/uuid" "gorm.io/gorm" ) type MProductEntity struct { ID uuid.UUID `gorm:"type:uuid;default:uuid_generate_v4()" json:"id"` Name string `gorm:"type:varchar(255);not null" json:"name"` RefNumber string `gorm:"type:varchar(100);not null;" json:"ref_number"` SKU string `gorm:"type:varchar(100);not null;" json:"sku"` Description string `gorm:"type:text" json:"description"` Status string `gorm:"type:varchar(50);not null" json:"status"` IsReturnable bool `gorm:"type:boolean;default:false" json:"is_returnable"` DimLength float64 `gorm:"type:decimal(10,2);" json:"dim_length"` DimWidth float64 `gorm:"type:decimal(10,2);" json:"dim_width"` DimHeight float64 `gorm:"type:decimal(10,2);" json:"dim_height"` Weight float64 `gorm:"type:decimal(10,2);" json:"weight"` Volume float64 `gorm:"type:decimal(10,2);" json:"volume"` MaxStackHeight int `gorm:"type:int;" json:"max_stack_height"` Temperature string `gorm:"type:varchar(50)" json:"temperature"` IsHazardous bool `gorm:"type:boolean;default:false" json:"is_hazardous"` MinStock int `gorm:"type:int;default:0" json:"min_stock"` MaxStock int `gorm:"type:int;default:0" json:"max_stock"` ReplenishType string `gorm:"type:varchar(50)" json:"replenish_type"` CycleCount string `gorm:"type:varchar(50);default:0" json:"cycle_count"` LotRules string `gorm:"type:varchar(100)" json:"lot_rules"` LeadTime int `gorm:"type:int;default:0" json:"lead_time"` MultiplyRate string `gorm:"type:varchar(50)" json:"multiply_rate"` DivideRate float64 `gorm:"type:decimal(10,2)" json:"divide_rate"` ClientID uuid.UUID `gorm:"type:uuid;index;" json:"client_id"` CategoryID *uuid.UUID `gorm:"type:uuid;index" json:"category_id"` UomID *uuid.UUID `gorm:"type:uuid;index" json:"uom_id"` DimUomID *uuid.UUID `gorm:"type:uuid;index" json:"dim_uom_id"` WeightUomID *uuid.UUID `gorm:"type:uuid;index" json:"weight_uom_id"` VolumeUomID *uuid.UUID `gorm:"type:uuid;index" json:"volume_uom_id"` MinStockUomID *uuid.UUID `gorm:"type:uuid;index" json:"min_stock_uom_id"` MaxStockUomID *uuid.UUID `gorm:"type:uuid;index" json:"max_stock_uom_id"` LeadTimeUomID *uuid.UUID `gorm:"type:uuid;index" json:"lead_time_uom_id"` UomToUomID *uuid.UUID `gorm:"type:uuid;index" json:"uom_to_uom_id"` Client M_Client `gorm:"foreignKey:ClientID;references:ID;constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"` Category MCategoryEntity `gorm:"foreignKey:CategoryID;references:ID"` Uom MUomEntity `gorm:"foreignKey:UomID;references:ID"` DimUom MUomEntity `gorm:"foreignKey:DimUomID;references:ID"` WeightUom MUomEntity `gorm:"foreignKey:WeightUomID;references:ID"` VolumeUom MUomEntity `gorm:"foreignKey:VolumeUomID;references:ID"` MinStockUom MUomEntity `gorm:"foreignKey:MinStockUomID;references:ID"` MaxStockUom MUomEntity `gorm:"foreignKey:MaxStockUomID;references:ID"` LeadTimeUom MUomEntity `gorm:"foreignKey:LeadTimeUomID;references:ID"` UomToUom MUomEntity `gorm:"foreignKey:UomToUomID;references:ID"` CrossReferences []MCrossReferenceEntity `gorm:"foreignKey:ProductID;references:ID"` InventoryTransactions []InventoryTransactionEntity `gorm:"foreignKey:ProductID;references:ID"` InventoryStorages []InventoryStorageEntity `gorm:"foreignKey:ProductID;references:ID"` FullAuditTrail } func (MProductEntity) TableName() string { return "m_products" } // GenerateRefNumberProduct generates a new reference number for a product func GenerateRefNumberProduct(db *gorm.DB, clientId string, categoryId string) (string, error) { prefix := "PRD" // Ambil nama client berdasarkan clientId var client struct { Name string } if err := db.Table("m_clients").Select("name").Where("id = ?", clientId).First(&client).Error; err != nil { return "", fmt.Errorf("client not found") } if client.Name == "" { return "", fmt.Errorf("client name is empty") } // Ambil search key kategori berdasarkan categoryId var category struct { SearchKey string } if err := db.Table("m_categories").Select("search_key").Where("id = ?", categoryId).First(&category).Error; err != nil { return "", fmt.Errorf("category not found") } if category.SearchKey == "" { return "", fmt.Errorf("category search key is empty") } categoryInitial := "" lettersOnly := "" for _, r := range category.SearchKey { if (r >= 'A' && r <= 'Z') || (r >= 'a' && r <= 'z') { lettersOnly += string(r) } } if len(lettersOnly) > 0 { categoryInitial = strings.ToUpper(lettersOnly) } // Ambil tahun dan bulan sekarang now := time.Now() period := now.Format("0601") // YYYYMM // Cari sequence terakhir untuk client dan kategori di periode ini var lastProduct MProductEntity prefixQuery := fmt.Sprintf("%s-%s-%s", prefix, categoryInitial, period) err := db. Where("client_id = ? AND category_id = ? AND LEFT(ref_number, ?) = ?", clientId, categoryId, len(prefixQuery), prefixQuery). Order("ref_number DESC"). First(&lastProduct).Error seq := 1 if err == nil && lastProduct.RefNumber != "" { parts := strings.Split(lastProduct.RefNumber, "-") if len(parts) == 4 { fmt.Sscanf(parts[3], "%d", &seq) seq++ } } refNum := fmt.Sprintf("%s-%s-%s-%04d", prefix, categoryInitial, period, seq) return refNum, nil }