package seed import ( "errors" "fmt" "strings" "time" entity "gitlab.com/mbugroup/lti-api.git/internal/entities" "gitlab.com/mbugroup/lti-api.git/internal/utils" approvalutils "gitlab.com/mbugroup/lti-api.git/internal/utils/approvals" "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 } areas, err := seedAreas(tx, adminID) if err != nil { return err } locations, err := seedLocations(tx, adminID, areas) if err != nil { return err } productCategories, err := seedProductCategories(tx, adminID) if err != nil { return err } flocks, err := seedFlocks(tx, adminID) if err != nil { return err } fcrs, err := seedFcr(tx, adminID) if err != nil { return err } projectFlocks, err := seedProjectFlocks(tx, adminID, flocks, areas, fcrs, locations) if err != nil { return err } kandangs, err := seedKandangs(tx, adminID, locations, users, projectFlocks) if err != nil { return err } if err := seedWarehouses(tx, adminID, areas, locations, kandangs); err != nil { return err } suppliers, err := seedSuppliers(tx, adminID) if err != nil { return err } if err := seedCustomers(tx, adminID, users); err != nil { return err } if err := seedProducts(tx, adminID, uoms, productCategories, suppliers); err != nil { return err } if err := seedNonstocks(tx, adminID, uoms, suppliers); err != nil { return err } if err := seedBanks(tx, adminID); err != nil { return err } if err := seedProductWarehouse(tx, adminID); err != nil { return err } if err := seedTransferStock(tx, adminID); err != nil { return err } if err := seedChickin(tx, adminID); 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 seedAreas(tx *gorm.DB, createdBy uint) (map[string]uint, error) { names := []string{"Priangan", "Banten"} result := make(map[string]uint, len(names)) for _, name := range names { var area entity.Area err := tx.Where("name = ?", name).First(&area).Error if errors.Is(err, gorm.ErrRecordNotFound) { area = entity.Area{Name: name, CreatedBy: createdBy} if err := tx.Create(&area).Error; err != nil { return nil, err } } else if err != nil { return nil, err } result[name] = area.Id } return result, nil } func seedLocations(tx *gorm.DB, createdBy uint, areas map[string]uint) (map[string]uint, error) { seeds := []struct { Name string Address string Area string }{ {"Singaparna", "Tasik", "Priangan"}, {"Cikaum", "Cikaum", "Banten"}, } result := make(map[string]uint, len(seeds)) for _, seed := range seeds { areaID, ok := areas[seed.Area] if !ok { return nil, fmt.Errorf("area %s not seeded", seed.Area) } var loc entity.Location err := tx.Where("name = ?", seed.Name).First(&loc).Error if errors.Is(err, gorm.ErrRecordNotFound) { loc = entity.Location{ Name: seed.Name, Address: seed.Address, AreaId: areaID, CreatedBy: createdBy, } if err := tx.Create(&loc).Error; err != nil { return nil, err } } else if err != nil { return nil, err } result[seed.Name] = loc.Id } return result, nil } func seedFlocks(tx *gorm.DB, createdBy uint) (map[string]uint, error) { names := []string{"Flock Priangan", "Flock Banten"} result := make(map[string]uint, len(names)) for _, name := range names { var flock entity.Flock err := tx.Where("name = ?", name).First(&flock).Error if errors.Is(err, gorm.ErrRecordNotFound) { flock = entity.Flock{ Name: name, CreatedBy: createdBy, } if err := tx.Create(&flock).Error; err != nil { return nil, err } } else if err != nil { return nil, err } else { if err := tx.Model(&entity.Flock{}).Where("id = ?", flock.Id).Updates(map[string]any{ "created_by": createdBy, }).Error; err != nil { return nil, err } } result[name] = flock.Id } return result, nil } func seedProjectFlocks(tx *gorm.DB, createdBy uint, flocks, areas, fcrs, locations map[string]uint) (map[string]uint, error) { seeds := []struct { Key string Flock string Area string Category utils.ProjectFlockCategory Fcr string Location string Period int }{ { Key: "Singaparna Period 1", Flock: "Flock Priangan", Area: "Priangan", Category: utils.ProjectFlockCategoryGrowing, Fcr: "FCR Layer", Location: "Singaparna", Period: 1, }, { Key: "Cikaum Period 1", Flock: "Flock Banten", Area: "Banten", Category: utils.ProjectFlockCategoryGrowing, Fcr: "FCR Layer", Location: "Cikaum", Period: 1, }, } result := make(map[string]uint, len(seeds)) for _, seed := range seeds { flockID, ok := flocks[seed.Flock] if !ok { return nil, fmt.Errorf("floc %s not seeded", seed.Flock) } areaID, ok := areas[seed.Area] if !ok { return nil, fmt.Errorf("area %s not seeded", seed.Area) } fcrID, ok := fcrs[seed.Fcr] if !ok { return nil, fmt.Errorf("fcr %s not seeded", seed.Fcr) } locationID, ok := locations[seed.Location] if !ok { return nil, fmt.Errorf("location %s not seeded", seed.Location) } var projectFlock entity.ProjectFlock err := tx.Where("flock_id = ? AND area_id = ? AND category = ? AND fcr_id = ? AND location_id = ? AND period = ?", flockID, areaID, seed.Category, fcrID, locationID, seed.Period).First(&projectFlock).Error if errors.Is(err, gorm.ErrRecordNotFound) { projectFlock = entity.ProjectFlock{ FlockId: flockID, AreaId: areaID, Category: string(seed.Category), FcrId: fcrID, LocationId: locationID, Period: seed.Period, CreatedBy: createdBy, } if err := tx.Create(&projectFlock).Error; err != nil { return nil, err } } else if err != nil { return nil, err } else { if err := tx.Model(&entity.ProjectFlock{}).Where("id = ?", projectFlock.Id).Updates(map[string]any{ "flock_id": flockID, "area_id": areaID, "category": string(seed.Category), "fcr_id": fcrID, "location_id": locationID, "period": seed.Period, }).Error; err != nil { return nil, err } } if err := ensureProjectFlockApprovals(tx, projectFlock.Id, createdBy); err != nil { return nil, err } result[seed.Key] = projectFlock.Id } return result, nil } func ensureProjectFlockApprovals(tx *gorm.DB, projectFlockID uint, actorID uint) error { if projectFlockID == 0 || actorID == 0 { return nil } workflow := utils.ApprovalWorkflowProjectFlock.String() steps := []struct { step approvalutils.ApprovalStep action entity.ApprovalAction }{ {step: utils.ProjectFlockStepPengajuan, action: entity.ApprovalActionCreated}, {step: utils.ProjectFlockStepAktif, action: entity.ApprovalActionApproved}, } for _, cfg := range steps { var count int64 if err := tx.Model(&entity.Approval{}). Where("approvable_type = ? AND approvable_id = ? AND step_number = ?", workflow, projectFlockID, uint16(cfg.step)). Count(&count).Error; err != nil { return err } if count > 0 { continue } stepName, ok := utils.ProjectFlockApprovalSteps[cfg.step] if !ok || strings.TrimSpace(stepName) == "" { stepName = fmt.Sprintf("Step %d", cfg.step) } var actionPtr *entity.ApprovalAction action := cfg.action actionPtr = &action record := entity.Approval{ ApprovableType: workflow, ApprovableId: projectFlockID, StepNumber: uint16(cfg.step), StepName: stepName, Action: actionPtr, ActionBy: uintPtr(actorID), } if err := tx.Create(&record).Error; err != nil { return err } } return nil } func seedKandangs(tx *gorm.DB, createdBy uint, locations map[string]uint, users map[string]uint, projectFlocks map[string]uint) (map[string]uint, error) { seeds := []struct { Name string Status utils.KandangStatus Location string PicKey string ProjectFlockKey *string }{ {Name: "Singaparna 1", Status: utils.KandangStatusActive, Location: "Singaparna", PicKey: "admin", ProjectFlockKey: strPtr("Singaparna Period 1")}, {Name: "Singaparna 2", Status: utils.KandangStatusNonActive, Location: "Singaparna", PicKey: "admin", ProjectFlockKey: strPtr("Singaparna Period 1")}, {Name: "Cikaum 1", Status: utils.KandangStatusActive, Location: "Cikaum", PicKey: "admin", ProjectFlockKey: strPtr("Cikaum Period 1")}, {Name: "Cikaum 2", Status: utils.KandangStatusPengajuan, Location: "Cikaum", PicKey: "admin"}, } result := make(map[string]uint, len(seeds)) for _, seed := range seeds { locID, ok := locations[seed.Location] if !ok { return nil, fmt.Errorf("location %s not seeded", seed.Location) } picID, ok := users[seed.PicKey] if !ok { return nil, fmt.Errorf("user %s not seeded", seed.PicKey) } var projectFlockID *uint if seed.ProjectFlockKey != nil { pfID, ok := projectFlocks[*seed.ProjectFlockKey] if !ok { return nil, fmt.Errorf("project flock %s not seeded", *seed.ProjectFlockKey) } projectFlockID = uintPtr(pfID) } var kandang entity.Kandang err := tx.Where("name = ?", seed.Name).First(&kandang).Error if errors.Is(err, gorm.ErrRecordNotFound) { kandang = entity.Kandang{ Name: seed.Name, Status: string(seed.Status), LocationId: locID, PicId: picID, ProjectFlockId: projectFlockID, CreatedBy: createdBy, } if err := tx.Create(&kandang).Error; err != nil { return nil, err } if err := syncPivotRelation(tx, projectFlockID, kandang.Id); err != nil { return nil, err } } else if err != nil { return nil, err } else { updates := map[string]any{ "location_id": locID, "pic_id": picID, "status": string(seed.Status), } if projectFlockID != nil { updates["project_flock_id"] = *projectFlockID } else { updates["project_flock_id"] = nil } if err := tx.Model(&entity.Kandang{}).Where("id = ?", kandang.Id).Updates(updates).Error; err != nil { return nil, err } if err := syncPivotRelation(tx, projectFlockID, kandang.Id); err != nil { return nil, err } } result[seed.Name] = kandang.Id } return result, nil } func syncPivotRelation(tx *gorm.DB, projectFlockID *uint, kandangID uint) error { if err := detachActivePivot(tx, kandangID); err != nil { return err } if projectFlockID == nil { return nil } return ensureActivePivot(tx, *projectFlockID, kandangID) } func detachActivePivot(tx *gorm.DB, kandangID uint) error { return tx.Where("kandang_id = ?", kandangID). Delete(&entity.ProjectFlockKandang{}).Error } func ensureActivePivot(tx *gorm.DB, projectFlockID, kandangID uint) error { var pivot entity.ProjectFlockKandang err := tx.Where("project_flock_id = ? AND kandang_id = ?", projectFlockID, kandangID). First(&pivot).Error if err == nil { return nil } if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { return err } newRecord := entity.ProjectFlockKandang{ ProjectFlockId: projectFlockID, KandangId: kandangID, } return tx.Create(&newRecord).Error } func seedWarehouses(tx *gorm.DB, createdBy uint, areas map[string]uint, locations map[string]uint, kandangs map[string]uint) error { seeds := []struct { Name string Type string Area string Location *string Kandang *string }{ {Name: "Gudang Priangan", Type: string(utils.WarehouseTypeArea), Area: "Priangan"}, {Name: "Gudang Singaparna", Type: string(utils.WarehouseTypeLokasi), Area: "Priangan", Location: strPtr("Singaparna")}, {Name: "Gudang Singaparna 1", Type: string(utils.WarehouseTypeKandang), Area: "Priangan", Location: strPtr("Singaparna"), Kandang: strPtr("Singaparna 1")}, {Name: "Gudang Singaparna 2", Type: string(utils.WarehouseTypeKandang), Area: "Priangan", Location: strPtr("Singaparna"), Kandang: strPtr("Singaparna 2")}, {Name: "Gudang Banten", Type: string(utils.WarehouseTypeArea), Area: "Banten"}, {Name: "Gudang Cikaum", Type: string(utils.WarehouseTypeLokasi), Area: "Banten", Location: strPtr("Cikaum")}, {Name: "Gudang Cikaum 1", Type: string(utils.WarehouseTypeKandang), Area: "Banten", Location: strPtr("Cikaum"), Kandang: strPtr("Cikaum 1")}, {Name: "Gudang Cikaum 2", Type: string(utils.WarehouseTypeKandang), Area: "Banten", Location: strPtr("Cikaum"), Kandang: strPtr("Cikaum 2")}, } for _, seed := range seeds { areaID, ok := areas[seed.Area] if !ok { return fmt.Errorf("area %s not seeded", seed.Area) } var warehouse entity.Warehouse err := tx.Where("name = ?", seed.Name).First(&warehouse).Error if errors.Is(err, gorm.ErrRecordNotFound) { warehouse = entity.Warehouse{ Name: seed.Name, Type: seed.Type, AreaId: areaID, CreatedBy: createdBy, } } else if err != nil { return err } if seed.Location != nil { locID, ok := locations[*seed.Location] if !ok { return fmt.Errorf("location %s not seeded", *seed.Location) } warehouse.LocationId = uintPtr(locID) } if seed.Kandang != nil { kandangID, ok := kandangs[*seed.Kandang] if !ok { return fmt.Errorf("kandang %s not seeded", *seed.Kandang) } warehouse.KandangId = uintPtr(kandangID) } if warehouse.Id == 0 { if err := tx.Create(&warehouse).Error; err != nil { return err } } else { if err := tx.Model(&entity.Warehouse{}).Where("id = ?", warehouse.Id).Updates(map[string]any{ "type": warehouse.Type, "area_id": warehouse.AreaId, "location_id": warehouse.LocationId, "kandang_id": warehouse.KandangId, }).Error; err != nil { return err } } } return nil } func seedProductCategories(tx *gorm.DB, createdBy uint) (map[string]uint, error) { seeds := []struct { Name string Code string }{ {"Bahan Baku", "RAW"}, {"Day Old Chick", "DOC"}, } 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 seedCustomers(tx *gorm.DB, createdBy uint, users map[string]uint) error { seeds := []struct { Name string PicKey string Address string Phone string Email string }{ {"Abdul Azis", "admin", "Jl. Raya Utama 1, Bekasi", "082100000001", "abdul.azis@gmail.com"}, } for idx, seed := range seeds { picID, ok := users[seed.PicKey] if !ok { return fmt.Errorf("user %s not seeded", seed.PicKey) } var customer entity.Customer err := tx.Where("name = ?", seed.Name).First(&customer).Error if errors.Is(err, gorm.ErrRecordNotFound) { customer = entity.Customer{ Name: seed.Name, PicId: picID, Type: string(utils.CustomerSupplierTypeBisnis), Address: seed.Address, Phone: seed.Phone, Email: seed.Email, AccountNumber: *strPtr(fmt.Sprintf("%03d", idx+1)), CreatedBy: createdBy, } if err := tx.Create(&customer).Error; err != nil { return err } } else if err != nil { return err } } return nil } func seedFcr(tx *gorm.DB, createdBy uint) (map[string]uint, error) { seeds := []struct { Name string Standards []struct { Weight float64 FcrNumber float64 Mortality float64 } }{ { Name: "FCR Layer", Standards: []struct { Weight float64 FcrNumber float64 Mortality float64 }{ {Weight: 0.8, FcrNumber: 1.60, Mortality: 2.0}, {Weight: 1.5, FcrNumber: 1.75, Mortality: 3.5}, }, }, } result := make(map[string]uint, len(seeds)) for _, seed := range seeds { var fcr entity.Fcr err := tx.Where("name = ?", seed.Name).First(&fcr).Error if errors.Is(err, gorm.ErrRecordNotFound) { fcr = entity.Fcr{Name: seed.Name, CreatedBy: createdBy} if err := tx.Create(&fcr).Error; err != nil { return nil, err } } else if err != nil { return nil, err } result[seed.Name] = fcr.Id for _, std := range seed.Standards { var standard entity.FcrStandard err := tx.Where("fcr_id = ? AND weight = ?", fcr.Id, std.Weight).First(&standard).Error if errors.Is(err, gorm.ErrRecordNotFound) { standard = entity.FcrStandard{ FcrID: fcr.Id, Weight: std.Weight, FcrNumber: std.FcrNumber, Mortality: std.Mortality, } if err := tx.Create(&standard).Error; err != nil { return nil, err } } else if err != nil { return nil, err } else { if err := tx.Model(&entity.FcrStandard{}).Where("id = ?", standard.Id).Updates(map[string]any{ "fcr_number": std.FcrNumber, "mortality": std.Mortality, }).Error; err != nil { return nil, err } } } } 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 }{ { Name: "DOC Broiler", Brand: "MBU Broiler", Sku: "BRO0001", Uom: "Ekor", Category: "Day Old Chick", Price: 7500, Suppliers: []string{"PT CHAROEN POKPHAND INDONESIA Tbk"}, Flags: []utils.FlagType{utils.FlagDOC}, }, { Name: "281 SPECIAL STARTER", Brand: "281 STARTER", Sku: "281", Uom: "Kilogram", Category: "Bahan Baku", Price: 7850, Expiry: intPtr(60), Suppliers: []string{"PT CHAROEN POKPHAND INDONESIA Tbk"}, Flags: []utils.FlagType{utils.FlagPakan, utils.FlagStarter}, }, } 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, } 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: "Expedisi DOC", Uom: "Ekor", 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 seedBanks(tx *gorm.DB, createdBy uint) error { seeds := []struct { Name string Alias string Owner *string AccountNumber string }{ { Name: "Bank Central Asia", Alias: "BCA", AccountNumber: "1234567890", Owner: ptr("PT MBU Group"), }, { Name: "Bank Rakyat Indonesia", Alias: "BRI", AccountNumber: "9876543210", Owner: ptr("PT MBU Group"), }, { Name: "Bank Mandiri", Alias: "MAND", AccountNumber: "1122334455", Owner: ptr("PT MBU Group"), }, } for _, seed := range seeds { var bank entity.Bank err := tx.Where("name = ?", seed.Name).First(&bank).Error if errors.Is(err, gorm.ErrRecordNotFound) { bank = entity.Bank{ Name: seed.Name, Alias: seed.Alias, Owner: seed.Owner, AccountNumber: seed.AccountNumber, CreatedBy: createdBy, CreatedAt: time.Now(), UpdatedAt: time.Now(), } if err := tx.Create(&bank).Error; err != nil { return err } } else if err != nil { return err } else { // update data jika sudah ada if err := tx.Model(&entity.Bank{}).Where("id = ?", bank.Id).Updates(map[string]any{ "alias": seed.Alias, "owner": seed.Owner, "account_number": seed.AccountNumber, "updated_at": time.Now(), }).Error; err != nil { return err } } } return nil } func seedProductWarehouse(tx *gorm.DB, createdBy uint) error { seeds := []struct { ProductID uint WarehouseID uint Quantity float64 }{ {ProductID: 1, WarehouseID: 1, Quantity: 100}, {ProductID: 2, WarehouseID: 2, Quantity: 200}, {ProductID: 2, WarehouseID: 1, Quantity: 300}, {ProductID: 1, WarehouseID: 3, Quantity: 5000}, } for _, seed := range seeds { var productWarehouse entity.ProductWarehouse err := tx.Where("product_id = ? AND warehouse_id = ?", seed.ProductID, seed.WarehouseID).First(&productWarehouse).Error if errors.Is(err, gorm.ErrRecordNotFound) { productWarehouse = entity.ProductWarehouse{ ProductId: seed.ProductID, WarehouseId: seed.WarehouseID, Quantity: seed.Quantity, CreatedBy: createdBy, } if err := tx.Create(&productWarehouse).Error; err != nil { return err } } else if err != nil { return err } } return nil } func seedTransferStock(tx *gorm.DB, createdBy uint) error { transfer := entity.StockTransfer{ FromWarehouseId: 1, ToWarehouseId: 2, Reason: "Seed transfer stock", TransferDate: time.Now(), MovementNumber: "SEED-TRF-00001", CreatedBy: 1, } if err := tx.Create(&transfer).Error; err != nil { return err } details := []entity.StockTransferDetail{ { StockTransferId: transfer.Id, ProductId: 1, Quantity: 10, }, { StockTransferId: transfer.Id, ProductId: 2, Quantity: 5, }, } for i := range details { if err := tx.Create(&details[i]).Error; err != nil { return err } } deliveries := []entity.StockTransferDelivery{ { StockTransferId: transfer.Id, SupplierId: 1, VehiclePlate: "B 1234 XYZ", DriverName: "Driver Seed", DocumentPath: "seed.pdf", ShippingCostItem: 1000, ShippingCostTotal: 2000, }, } for i := range deliveries { if err := tx.Create(&deliveries[i]).Error; err != nil { return err } } detailMap := make(map[uint64]uint64) for _, d := range details { detailMap[d.ProductId] = d.Id } deliveryItems := []entity.StockTransferDeliveryItem{ { StockTransferDeliveryId: deliveries[0].Id, StockTransferDetailId: detailMap[1], Quantity: 50, }, { StockTransferDeliveryId: deliveries[0].Id, StockTransferDetailId: detailMap[2], Quantity: 30, }, } for i := range deliveryItems { if err := tx.Create(&deliveryItems[i]).Error; err != nil { return err } } return nil } func seedChickin(tx *gorm.DB, createdBy uint) error { seeds := []struct { ProjectFlockKandangId uint ChickInDate string Quantity float64 Note string }{ {ProjectFlockKandangId: 1, ChickInDate: "2025-10-20", Quantity: 100, Note: "Seeder chickin 1"}, {ProjectFlockKandangId: 2, ChickInDate: "2025-10-21", Quantity: 200, Note: "Seeder chickin 2"}, } for _, seed := range seeds { chickinDate, err := time.Parse("2006-01-02", seed.ChickInDate) if err != nil { return err } // Insert ProjectChickin jika belum ada var chickin entity.ProjectChickin err = tx.Where("project_flock_kandang_id = ? AND chick_in_date = ?", seed.ProjectFlockKandangId, chickinDate). First(&chickin).Error if errors.Is(err, gorm.ErrRecordNotFound) { chickin = entity.ProjectChickin{ ProjectFlockKandangId: seed.ProjectFlockKandangId, ChickInDate: chickinDate, Quantity: seed.Quantity, Note: seed.Note, CreatedBy: createdBy, } if err := tx.Create(&chickin).Error; err != nil { return err } } else if err != nil { return err } // Update/Insert ProjectFlockPopulation var population entity.ProjectFlockPopulation err = tx.Where("project_flock_kandang_id = ?", seed.ProjectFlockKandangId).First(&population).Error if errors.Is(err, gorm.ErrRecordNotFound) { population = entity.ProjectFlockPopulation{ ProjectFlockKandangId: seed.ProjectFlockKandangId, InitialQuantity: seed.Quantity, CurrentQuantity: seed.Quantity, ReservedQuantity: 0, CreatedBy: createdBy, } if err := tx.Create(&population).Error; err != nil { return err } } else if err != nil { return err } else { // Update population quantities if err := tx.Model(&entity.ProjectFlockPopulation{}). Where("id = ?", population.Id). Updates(map[string]any{ "initial_quantity": population.InitialQuantity + seed.Quantity, "current_quantity": population.CurrentQuantity + seed.Quantity, "reserved_quantity": 0, }).Error; err != nil { return err } } } return nil } func ptr[T any](v T) *T { return &v } func strPtr(s string) *string { return &s } func intPtr(v int) *int { return &v } func uintPtr(v uint) *uint { return &v }