package seed import ( "errors" "fmt" "strings" entity "gitlab.com/mbugroup/lti-api.git/internal/entities" "gitlab.com/mbugroup/lti-api.git/internal/utils" "gorm.io/gorm" ) func Run(db *gorm.DB) error { return db.Transaction(func(tx *gorm.DB) error { users, err := seedUsers(tx) if err != nil { return err } adminID := users["admin"] uoms, err := seedUoms(tx, adminID) if err != nil { return err } productCategories, err := seedProductCategories(tx, adminID) if err != nil { return err } suppliers, err := seedSuppliers(tx, adminID) if err != nil { return err } if err := seedProducts(tx, adminID, uoms, productCategories, suppliers); err != nil { return err } fmt.Println("✅ Master data seeding completed") return nil }) } func seedUsers(tx *gorm.DB) (map[string]uint, error) { seeds := []struct { Key string Data entity.User }{ { Key: "admin", Data: entity.User{Email: "admin@mbugroup.id", IdUser: 1, Name: "Super Admin"}, }, } result := make(map[string]uint, len(seeds)) for _, seed := range seeds { var user entity.User err := tx.Where("email = ?", seed.Data.Email).First(&user).Error if errors.Is(err, gorm.ErrRecordNotFound) { user = seed.Data if err := tx.Create(&user).Error; err != nil { return nil, err } } else if err != nil { return nil, err } result[seed.Key] = user.Id } return result, nil } func seedUoms(tx *gorm.DB, createdBy uint) (map[string]uint, error) { names := []string{"Kilogram", "Gram", "Liter", "Unit", "Ekor"} result := make(map[string]uint, len(names)) for _, name := range names { var uom entity.Uom err := tx.Where("name = ?", name).First(&uom).Error if errors.Is(err, gorm.ErrRecordNotFound) { uom = entity.Uom{Name: name, CreatedBy: createdBy} if err := tx.Create(&uom).Error; err != nil { return nil, err } } else if err != nil { return nil, err } result[name] = uom.Id } return result, nil } func seedProductCategories(tx *gorm.DB, createdBy uint) (map[string]uint, error) { seeds := []struct { Name string Code string }{ {"Pullet", "PLT"}, {"Bahan Baku", "RAW"}, {"Day Old Chick", "DOC"}, {"Telur", "EGG"}, } result := make(map[string]uint, len(seeds)) for _, seed := range seeds { var category entity.ProductCategory err := tx.Where("name = ?", seed.Name).First(&category).Error if errors.Is(err, gorm.ErrRecordNotFound) { category = entity.ProductCategory{Name: seed.Name, Code: seed.Code, CreatedBy: createdBy} if err := tx.Create(&category).Error; err != nil { return nil, err } } else if err != nil { return nil, err } else { if err := tx.Model(&entity.ProductCategory{}).Where("id = ?", category.Id).Updates(map[string]any{ "code": seed.Code, }).Error; err != nil { return nil, err } } result[seed.Name] = category.Id } return result, nil } func seedSuppliers(tx *gorm.DB, createdBy uint) (map[string]uint, error) { seeds := []struct { Name string Alias string Category string Email string Phone string Address string }{ {"PT CHAROEN POKPHAND INDONESIA Tbk", "CPI", string(utils.SupplierCategorySapronak), "cpi@gmail.com", "081200000001", "Jl. Pakan 1, Bekasi"}, {"BOP Vendor", "BOP", string(utils.SupplierCategoryBOP), "bop@gmail.com", "081200000002", "Jl. Veteriner 3, Bogor"}, {"Ekspedisi", "EKS", string(utils.SupplierCategoryBOP), "bop@gmail.com", "081200000002", "Jl. Veteriner 3, Bogor"}, } result := make(map[string]uint, len(seeds)) for idx, seed := range seeds { var supplier entity.Supplier err := tx.Where("name = ?", seed.Name).First(&supplier).Error if errors.Is(err, gorm.ErrRecordNotFound) { supplier = entity.Supplier{ Name: seed.Name, Alias: seed.Alias, Pic: "John Doe", Type: string(utils.CustomerSupplierTypeBisnis), Category: seed.Category, Phone: seed.Phone, Email: seed.Email, Address: seed.Address, DueDate: 30, CreatedBy: createdBy, AccountNumber: strPtr(fmt.Sprintf("%03d", idx+1)), } if err := tx.Create(&supplier).Error; err != nil { return nil, err } } else if err != nil { return nil, err } result[seed.Name] = supplier.Id } return result, nil } func seedProducts(tx *gorm.DB, createdBy uint, uoms map[string]uint, categories map[string]uint, suppliers map[string]uint) error { seeds := []struct { Name string Brand string Sku string Uom string Category string Price float64 Selling *float64 Tax *float64 Expiry *int Suppliers []string Flags []utils.FlagType IsVisible bool }{ { Name: "ISA Brown", Brand: "ISA Brown", Sku: "ISA0001", Uom: "Ekor", Category: "Day Old Chick", Price: 7500, Suppliers: []string{"PT CHAROEN POKPHAND INDONESIA Tbk"}, Flags: []utils.FlagType{utils.FlagDOC, utils.FlagPullet, utils.FlagLayer}, IsVisible: true, }, { Name: "Ayam Afkir", Brand: "-", Sku: "1", Uom: "Ekor", Category: "Day Old Chick", Price: 1, Flags: []utils.FlagType{utils.FlagAyamAfkir}, IsVisible: false, }, { Name: "Ayam Mati", Brand: "-", Sku: "2", Uom: "Ekor", Category: "Day Old Chick", Price: 1, Flags: []utils.FlagType{utils.FlagAyamMati}, IsVisible: false, }, { Name: "Ayam Culling", Brand: "-", Sku: "3", Uom: "Ekor", Category: "Day Old Chick", Price: 1, Flags: []utils.FlagType{utils.FlagAyamCulling}, IsVisible: false, }, { Name: "Telur Utuh", Brand: "-", Sku: "4", Uom: "Gram", Category: "Telur", Price: 1, Flags: []utils.FlagType{utils.FlagTelurUtuh}, IsVisible: false, }, { Name: "Telur Pecah", Brand: "-", Sku: "5", Uom: "Gram", Category: "Telur", Price: 1, Flags: []utils.FlagType{utils.FlagTelurPecah}, IsVisible: false, }, { Name: "Telur Putih", Brand: "-", Sku: "6", Uom: "Gram", Category: "Telur", Price: 1, Flags: []utils.FlagType{utils.FlagTelurPutih}, IsVisible: false, }, { Name: "Telur Retak", Brand: "-", Sku: "7", Uom: "Gram", Category: "Telur", Price: 1, Flags: []utils.FlagType{utils.FlagTelurRetak}, IsVisible: false, }, } for _, seed := range seeds { uomID, ok := uoms[seed.Uom] if !ok { return fmt.Errorf("uom %s not seeded", seed.Uom) } categoryID, ok := categories[seed.Category] if !ok { return fmt.Errorf("product category %s not seeded", seed.Category) } var product entity.Product err := tx.Where("name = ?", seed.Name).First(&product).Error if errors.Is(err, gorm.ErrRecordNotFound) { selling := seed.Selling tax := seed.Tax product = entity.Product{ Name: seed.Name, Brand: seed.Brand, Sku: &seed.Sku, UomId: uomID, ProductCategoryId: categoryID, ProductPrice: seed.Price, SellingPrice: selling, Tax: tax, ExpiryPeriod: seed.Expiry, CreatedBy: createdBy, IsVisible: seed.IsVisible, } if err := tx.Create(&product).Error; err != nil { return err } } else if err != nil { return err } else { updates := map[string]any{ "brand": seed.Brand, "uom_id": uomID, "product_category_id": categoryID, "product_price": seed.Price, "selling_price": seed.Selling, "tax": seed.Tax, "expiry_period": seed.Expiry, } if seed.Sku != "" { updates["sku"] = seed.Sku } if err := tx.Model(&entity.Product{}).Where("id = ?", product.Id).Updates(updates).Error; err != nil { return err } } for _, supplierName := range seed.Suppliers { supplierID, ok := suppliers[supplierName] if !ok { return fmt.Errorf("supplier %s not seeded", supplierName) } var existing entity.ProductSupplier err := tx.Where("product_id = ? AND supplier_id = ?", product.Id, supplierID).First(&existing).Error if errors.Is(err, gorm.ErrRecordNotFound) { link := entity.ProductSupplier{ProductId: product.Id, SupplierId: supplierID} if err := tx.Create(&link).Error; err != nil { return err } } else if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { return err } } if err := seedFlags(tx, product.Id, entity.FlagableTypeProduct, seed.Flags); err != nil { return err } } return nil } // func seedNonstocks(tx *gorm.DB, createdBy uint, uoms map[string]uint, suppliers map[string]uint) error { // seeds := []struct { // Name string // Uom string // Suppliers []string // Flags []utils.FlagType // }{ // { // Name: "LAJ", // Uom: "Unit", // Suppliers: []string{"Ekspedisi"}, // Flags: []utils.FlagType{utils.FlagEkspedisi}, // }, // { // Name: "Solar", // Uom: "Liter", // Suppliers: []string{"BOP Vendor"}, // Flags: []utils.FlagType{}, // }, // } // for _, seed := range seeds { // uomID, ok := uoms[seed.Uom] // if !ok { // return fmt.Errorf("uom %s not seeded", seed.Uom) // } // var nonstock entity.Nonstock // err := tx.Where("name = ?", seed.Name).First(&nonstock).Error // if errors.Is(err, gorm.ErrRecordNotFound) { // nonstock = entity.Nonstock{ // Name: seed.Name, // UomId: uomID, // CreatedBy: createdBy, // } // if err := tx.Create(&nonstock).Error; err != nil { // return err // } // } else if err != nil { // return err // } else { // if err := tx.Model(&entity.Nonstock{}).Where("id = ?", nonstock.Id).Updates(map[string]any{ // "uom_id": uomID, // }).Error; err != nil { // return err // } // } // for _, supplierName := range seed.Suppliers { // supplierID, ok := suppliers[supplierName] // if !ok { // return fmt.Errorf("supplier %s not seeded", supplierName) // } // var existing entity.NonstockSupplier // err := tx.Where("nonstock_id = ? AND supplier_id = ?", nonstock.Id, supplierID).First(&existing).Error // if errors.Is(err, gorm.ErrRecordNotFound) { // link := entity.NonstockSupplier{NonstockId: nonstock.Id, SupplierId: supplierID} // if err := tx.Create(&link).Error; err != nil { // return err // } // } else if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { // return err // } // } // if err := seedFlags(tx, nonstock.Id, entity.FlagableTypeNonstock, seed.Flags); err != nil { // return err // } // } // return nil // } // nanti saya isi func seedFlags(tx *gorm.DB, flagableID uint, flagableType string, flags []utils.FlagType) error { if len(flags) == 0 { return nil } for _, flag := range flags { name := strings.ToUpper(string(flag)) var existing entity.Flag err := tx.Where("name = ? AND flagable_id = ? AND flagable_type = ?", name, flagableID, flagableType).First(&existing).Error if errors.Is(err, gorm.ErrRecordNotFound) { record := entity.Flag{ Name: name, FlagableID: flagableID, FlagableType: flagableType, } if err := tx.Create(&record).Error; err != nil { return err } } else if err != nil { return err } } return nil } func strPtr(s string) *string { return &s }