mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +00:00
codex/fix: store stocks on farm warehouse when recording egg
This commit is contained in:
+3
@@ -347,7 +347,10 @@ func (r *projectFlockKandangRepositoryImpl) GetByID(ctx context.Context, id uint
|
|||||||
func (r *projectFlockKandangRepositoryImpl) GetByIDLight(ctx context.Context, id uint) (*entity.ProjectFlockKandang, error) {
|
func (r *projectFlockKandangRepositoryImpl) GetByIDLight(ctx context.Context, id uint) (*entity.ProjectFlockKandang, error) {
|
||||||
record := new(entity.ProjectFlockKandang)
|
record := new(entity.ProjectFlockKandang)
|
||||||
if err := r.db.WithContext(ctx).
|
if err := r.db.WithContext(ctx).
|
||||||
|
Preload("Kandang").
|
||||||
|
Preload("Kandang.Location").
|
||||||
Preload("ProjectFlock").
|
Preload("ProjectFlock").
|
||||||
|
Preload("ProjectFlock.Location").
|
||||||
First(record, id).Error; err != nil {
|
First(record, id).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -355,6 +355,14 @@ func (s *recordingService) CreateOne(c *fiber.Ctx, req *validation.Create) (*ent
|
|||||||
return nil, fiber.NewError(fiber.StatusBadRequest, "Egg details permitted only for laying project flocks")
|
return nil, fiber.NewError(fiber.StatusBadRequest, "Egg details permitted only for laying project flocks")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
actorID, err := m.ActorIDFromContext(c)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if req.Eggs, err = s.resolveEggRequestsToFarmWarehouses(ctx, pfk, actorID, req.Eggs); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
if err := s.ensureProductWarehousesExist(c, req.Stocks, req.Depletions, req.Eggs); err != nil {
|
if err := s.ensureProductWarehousesExist(c, req.Stocks, req.Depletions, req.Eggs); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -379,10 +387,6 @@ func (s *recordingService) CreateOne(c *fiber.Ctx, req *validation.Create) (*ent
|
|||||||
if err := s.ensureProductWarehousesByFlags(ctx, eggIDs, []string{"TELUR-UTUH", "TELUR-PECAH", "TELUR-PUTIH", "TELUR-RETAK", "TELUR"}, "egg"); err != nil {
|
if err := s.ensureProductWarehousesByFlags(ctx, eggIDs, []string{"TELUR-UTUH", "TELUR-PECAH", "TELUR-PUTIH", "TELUR-RETAK", "TELUR"}, "egg"); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
actorID, err := m.ActorIDFromContext(c)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var createdRecording entity.Recording
|
var createdRecording entity.Recording
|
||||||
transactionErr := s.Repository.DB().WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
transactionErr := s.Repository.DB().WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||||
if s.ProductionStandardSvc != nil {
|
if s.ProductionStandardSvc != nil {
|
||||||
@@ -687,6 +691,15 @@ func (s recordingService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uin
|
|||||||
s.Log.Errorf("Failed to list existing eggs: %+v", err)
|
s.Log.Errorf("Failed to list existing eggs: %+v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
normalizeEggWarehouses, err := s.shouldNormalizeEggRequestsOnUpdate(ctx, existingEggs)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if normalizeEggWarehouses {
|
||||||
|
if req.Eggs, err = s.resolveEggRequestsToFarmWarehouses(ctx, pfkForRoute, actorID, req.Eggs); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
existingTotals := recordingutil.EggTotalsByWarehouse(existingEggs, func(egg entity.RecordingEgg) (uint, int, *float64) {
|
existingTotals := recordingutil.EggTotalsByWarehouse(existingEggs, func(egg entity.RecordingEgg) (uint, int, *float64) {
|
||||||
return egg.ProductWarehouseId, egg.Qty, egg.Weight
|
return egg.ProductWarehouseId, egg.Qty, egg.Weight
|
||||||
})
|
})
|
||||||
@@ -1492,6 +1505,194 @@ func boolPtr(value bool) *bool {
|
|||||||
return &v
|
return &v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *recordingService) resolveEggRequestsToFarmWarehouses(
|
||||||
|
ctx context.Context,
|
||||||
|
pfk *entity.ProjectFlockKandang,
|
||||||
|
actorID uint,
|
||||||
|
eggs []validation.Egg,
|
||||||
|
) ([]validation.Egg, error) {
|
||||||
|
if len(eggs) == 0 {
|
||||||
|
return eggs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
locationID, farmName := farmContextFromProjectFlockKandang(pfk)
|
||||||
|
if locationID == 0 {
|
||||||
|
return nil, fiber.NewError(fiber.StatusBadRequest, "Farm recording tidak valid")
|
||||||
|
}
|
||||||
|
|
||||||
|
farmWarehouse, err := s.findFirstFarmWarehouse(ctx, locationID)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
|
return nil, fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Farm %s belum memiliki gudang", farmName))
|
||||||
|
}
|
||||||
|
s.Log.Errorf("Failed to resolve farm warehouse for egg recording: %+v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
idSet := make(map[uint]struct{}, len(eggs))
|
||||||
|
for _, egg := range eggs {
|
||||||
|
if egg.ProductWarehouseId != 0 {
|
||||||
|
idSet[egg.ProductWarehouseId] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(idSet) == 0 {
|
||||||
|
return eggs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ids := make([]uint, 0, len(idSet))
|
||||||
|
for id := range idSet {
|
||||||
|
ids = append(ids, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
var sourceWarehouses []entity.ProductWarehouse
|
||||||
|
if err := s.ProductWarehouseRepo.DB().WithContext(ctx).
|
||||||
|
Preload("Warehouse").
|
||||||
|
Where("id IN ?", ids).
|
||||||
|
Find(&sourceWarehouses).Error; err != nil {
|
||||||
|
s.Log.Errorf("Failed to load egg source product warehouses: %+v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(sourceWarehouses) != len(ids) {
|
||||||
|
return nil, fiber.NewError(fiber.StatusBadRequest, "Product warehouse telur tidak ditemukan")
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceByID := make(map[uint]entity.ProductWarehouse, len(sourceWarehouses))
|
||||||
|
resolvedBySource := make(map[uint]uint, len(sourceWarehouses))
|
||||||
|
for _, source := range sourceWarehouses {
|
||||||
|
if err := ensureEggSourceMatchesRecordingScope(source, locationID, pfk.KandangId); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
sourceByID[source.Id] = source
|
||||||
|
}
|
||||||
|
|
||||||
|
normalized := make([]validation.Egg, len(eggs))
|
||||||
|
copy(normalized, eggs)
|
||||||
|
for i := range normalized {
|
||||||
|
source := sourceByID[normalized[i].ProductWarehouseId]
|
||||||
|
if resolvedID, ok := resolvedBySource[source.Id]; ok {
|
||||||
|
normalized[i].ProductWarehouseId = resolvedID
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
resolvedID, err := s.ProductWarehouseRepo.EnsureProductWarehouse(ctx, source.ProductId, farmWarehouse.Id, nil, actorID)
|
||||||
|
if err != nil {
|
||||||
|
s.Log.Errorf("Failed to ensure egg farm product warehouse: %+v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
resolvedBySource[source.Id] = resolvedID
|
||||||
|
normalized[i].ProductWarehouseId = resolvedID
|
||||||
|
}
|
||||||
|
|
||||||
|
return normalized, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func farmContextFromProjectFlockKandang(pfk *entity.ProjectFlockKandang) (uint, string) {
|
||||||
|
if pfk == nil {
|
||||||
|
return 0, "tidak diketahui"
|
||||||
|
}
|
||||||
|
|
||||||
|
if pfk.ProjectFlock.LocationId != 0 {
|
||||||
|
name := strings.TrimSpace(pfk.ProjectFlock.Location.Name)
|
||||||
|
if name == "" {
|
||||||
|
name = strings.TrimSpace(pfk.Kandang.Location.Name)
|
||||||
|
}
|
||||||
|
if name == "" {
|
||||||
|
name = fmt.Sprintf("#%d", pfk.ProjectFlock.LocationId)
|
||||||
|
}
|
||||||
|
return pfk.ProjectFlock.LocationId, name
|
||||||
|
}
|
||||||
|
|
||||||
|
if pfk.Kandang.LocationId != 0 {
|
||||||
|
name := strings.TrimSpace(pfk.Kandang.Location.Name)
|
||||||
|
if name == "" {
|
||||||
|
name = fmt.Sprintf("#%d", pfk.Kandang.LocationId)
|
||||||
|
}
|
||||||
|
return pfk.Kandang.LocationId, name
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0, "tidak diketahui"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *recordingService) findFirstFarmWarehouse(ctx context.Context, locationID uint) (*entity.Warehouse, error) {
|
||||||
|
var warehouse entity.Warehouse
|
||||||
|
if err := s.Repository.DB().WithContext(ctx).
|
||||||
|
Model(&entity.Warehouse{}).
|
||||||
|
Where("location_id = ? AND type = ?", locationID, utils.WarehouseTypeLokasi).
|
||||||
|
Order("id ASC").
|
||||||
|
First(&warehouse).Error; err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &warehouse, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ensureEggSourceMatchesRecordingScope(source entity.ProductWarehouse, locationID uint, kandangID uint) error {
|
||||||
|
if source.Id == 0 {
|
||||||
|
return fiber.NewError(fiber.StatusBadRequest, "Product warehouse telur tidak ditemukan")
|
||||||
|
}
|
||||||
|
if source.ProductId == 0 {
|
||||||
|
return fiber.NewError(fiber.StatusBadRequest, "Produk telur tidak valid")
|
||||||
|
}
|
||||||
|
if source.WarehouseId == 0 {
|
||||||
|
return fiber.NewError(fiber.StatusBadRequest, "Gudang telur tidak valid")
|
||||||
|
}
|
||||||
|
if source.Warehouse.LocationId == nil || *source.Warehouse.LocationId != locationID {
|
||||||
|
return fiber.NewError(fiber.StatusBadRequest, "Produk telur harus berasal dari farm yang sama")
|
||||||
|
}
|
||||||
|
|
||||||
|
switch strings.ToUpper(strings.TrimSpace(source.Warehouse.Type)) {
|
||||||
|
case string(utils.WarehouseTypeLokasi):
|
||||||
|
return nil
|
||||||
|
case string(utils.WarehouseTypeKandang):
|
||||||
|
if source.Warehouse.KandangId == nil || *source.Warehouse.KandangId != kandangID {
|
||||||
|
return fiber.NewError(fiber.StatusBadRequest, "Produk telur harus berasal dari kandang recording yang sama")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return fiber.NewError(fiber.StatusBadRequest, "Produk telur harus berasal dari gudang farm atau kandang recording")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *recordingService) shouldNormalizeEggRequestsOnUpdate(ctx context.Context, existingEggs []entity.RecordingEgg) (bool, error) {
|
||||||
|
if len(existingEggs) == 0 {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
idSet := make(map[uint]struct{}, len(existingEggs))
|
||||||
|
for _, egg := range existingEggs {
|
||||||
|
if egg.ProductWarehouseId != 0 {
|
||||||
|
idSet[egg.ProductWarehouseId] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(idSet) == 0 {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ids := make([]uint, 0, len(idSet))
|
||||||
|
for id := range idSet {
|
||||||
|
ids = append(ids, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
var productWarehouses []entity.ProductWarehouse
|
||||||
|
if err := s.ProductWarehouseRepo.DB().WithContext(ctx).
|
||||||
|
Preload("Warehouse").
|
||||||
|
Where("id IN ?", ids).
|
||||||
|
Find(&productWarehouses).Error; err != nil {
|
||||||
|
s.Log.Errorf("Failed to load existing egg product warehouses: %+v", err)
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if len(productWarehouses) != len(ids) {
|
||||||
|
return false, fiber.NewError(fiber.StatusBadRequest, "Product warehouse telur tidak ditemukan")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, productWarehouse := range productWarehouses {
|
||||||
|
if strings.EqualFold(strings.TrimSpace(productWarehouse.Warehouse.Type), string(utils.WarehouseTypeLokasi)) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *recordingService) ensureProductWarehousesExist(c *fiber.Ctx, stocks []validation.Stock, depletions []validation.Depletion, eggs []validation.Egg) error {
|
func (s *recordingService) ensureProductWarehousesExist(c *fiber.Ctx, stocks []validation.Stock, depletions []validation.Depletion, eggs []validation.Egg) error {
|
||||||
idSet := make(map[uint]struct{})
|
idSet := make(map[uint]struct{})
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,195 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/glebarez/sqlite"
|
||||||
|
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
||||||
|
rProductWarehouse "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/product-warehouses/repositories"
|
||||||
|
repository "gitlab.com/mbugroup/lti-api.git/internal/modules/production/recordings/repositories"
|
||||||
|
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/production/recordings/validations"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestResolveEggRequestsToFarmWarehousesChoosesFirstFarmWarehouse(t *testing.T) {
|
||||||
|
db := setupRecordingServiceTestDB(t)
|
||||||
|
repo := repository.NewRecordingRepository(db)
|
||||||
|
productWarehouseRepo := rProductWarehouse.NewProductWarehouseRepository(db)
|
||||||
|
svc := &recordingService{
|
||||||
|
Log: nil,
|
||||||
|
Repository: repo,
|
||||||
|
ProductWarehouseRepo: productWarehouseRepo,
|
||||||
|
}
|
||||||
|
|
||||||
|
pfk := &entity.ProjectFlockKandang{
|
||||||
|
Id: 10,
|
||||||
|
KandangId: 59,
|
||||||
|
ProjectFlock: entity.ProjectFlock{
|
||||||
|
LocationId: 16,
|
||||||
|
Location: entity.Location{Name: "Jamali"},
|
||||||
|
},
|
||||||
|
Kandang: entity.Kandang{
|
||||||
|
Id: 59,
|
||||||
|
LocationId: 16,
|
||||||
|
Location: entity.Location{Name: "Jamali"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
got, err := svc.resolveEggRequestsToFarmWarehouses(context.Background(), pfk, 9, []validation.Egg{
|
||||||
|
{ProductWarehouseId: 101, Qty: 120},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
if len(got) != 1 {
|
||||||
|
t.Fatalf("expected 1 egg row, got %d", len(got))
|
||||||
|
}
|
||||||
|
if got[0].ProductWarehouseId == 101 {
|
||||||
|
t.Fatalf("expected egg warehouse to be remapped to farm warehouse")
|
||||||
|
}
|
||||||
|
|
||||||
|
var resolved entity.ProductWarehouse
|
||||||
|
if err := db.WithContext(context.Background()).
|
||||||
|
Preload("Warehouse").
|
||||||
|
First(&resolved, got[0].ProductWarehouseId).Error; err != nil {
|
||||||
|
t.Fatalf("failed to load resolved product warehouse: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if resolved.ProductId != 8 {
|
||||||
|
t.Fatalf("expected product_id 8, got %d", resolved.ProductId)
|
||||||
|
}
|
||||||
|
if resolved.WarehouseId != 21 {
|
||||||
|
t.Fatalf("expected first farm warehouse id 21, got %d", resolved.WarehouseId)
|
||||||
|
}
|
||||||
|
if resolved.ProjectFlockKandangId != nil {
|
||||||
|
t.Fatalf("expected farm-level product warehouse to remain shared, got pfk %+v", resolved.ProjectFlockKandangId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestResolveEggRequestsToFarmWarehousesFailsWhenFarmHasNoWarehouse(t *testing.T) {
|
||||||
|
db := setupRecordingServiceTestDB(t)
|
||||||
|
if err := db.Exec("DELETE FROM warehouses WHERE type = 'LOKASI'").Error; err != nil {
|
||||||
|
t.Fatalf("failed to remove farm warehouses: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
repo := repository.NewRecordingRepository(db)
|
||||||
|
productWarehouseRepo := rProductWarehouse.NewProductWarehouseRepository(db)
|
||||||
|
svc := &recordingService{
|
||||||
|
Log: nil,
|
||||||
|
Repository: repo,
|
||||||
|
ProductWarehouseRepo: productWarehouseRepo,
|
||||||
|
}
|
||||||
|
|
||||||
|
pfk := &entity.ProjectFlockKandang{
|
||||||
|
Id: 10,
|
||||||
|
KandangId: 59,
|
||||||
|
ProjectFlock: entity.ProjectFlock{
|
||||||
|
LocationId: 16,
|
||||||
|
Location: entity.Location{Name: "Jamali"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := svc.resolveEggRequestsToFarmWarehouses(context.Background(), pfk, 9, []validation.Egg{
|
||||||
|
{ProductWarehouseId: 101, Qty: 120},
|
||||||
|
})
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected validation error when farm warehouse is missing")
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(), "Farm Jamali belum memiliki gudang") {
|
||||||
|
t.Fatalf("expected missing farm warehouse error, got %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestShouldNormalizeEggRequestsOnUpdatePreservesHistoricalKandangEggs(t *testing.T) {
|
||||||
|
db := setupRecordingServiceTestDB(t)
|
||||||
|
repo := repository.NewRecordingRepository(db)
|
||||||
|
productWarehouseRepo := rProductWarehouse.NewProductWarehouseRepository(db)
|
||||||
|
svc := &recordingService{
|
||||||
|
Log: nil,
|
||||||
|
Repository: repo,
|
||||||
|
ProductWarehouseRepo: productWarehouseRepo,
|
||||||
|
}
|
||||||
|
|
||||||
|
shouldNormalize, err := svc.shouldNormalizeEggRequestsOnUpdate(context.Background(), []entity.RecordingEgg{
|
||||||
|
{ProductWarehouseId: 101, Qty: 120},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
if shouldNormalize {
|
||||||
|
t.Fatal("expected historical kandang-level egg rows to remain kandang-level on update")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestShouldNormalizeEggRequestsOnUpdateNormalizesFarmLevelEggs(t *testing.T) {
|
||||||
|
db := setupRecordingServiceTestDB(t)
|
||||||
|
if err := db.Exec(`INSERT INTO product_warehouses (id, product_id, warehouse_id, project_flock_kandang_id, qty) VALUES (201, 8, 21, NULL, 300)`).Error; err != nil {
|
||||||
|
t.Fatalf("failed to insert farm-level egg warehouse: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
repo := repository.NewRecordingRepository(db)
|
||||||
|
productWarehouseRepo := rProductWarehouse.NewProductWarehouseRepository(db)
|
||||||
|
svc := &recordingService{
|
||||||
|
Log: nil,
|
||||||
|
Repository: repo,
|
||||||
|
ProductWarehouseRepo: productWarehouseRepo,
|
||||||
|
}
|
||||||
|
|
||||||
|
shouldNormalize, err := svc.shouldNormalizeEggRequestsOnUpdate(context.Background(), []entity.RecordingEgg{
|
||||||
|
{ProductWarehouseId: 201, Qty: 120},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("expected no error, got %v", err)
|
||||||
|
}
|
||||||
|
if !shouldNormalize {
|
||||||
|
t.Fatal("expected farm-level egg rows to keep using farm normalization on update")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupRecordingServiceTestDB(t *testing.T) *gorm.DB {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
db, err := gorm.Open(sqlite.Open("file:"+t.Name()+"?mode=memory&cache=private"), &gorm.Config{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed opening sqlite db: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
statements := []string{
|
||||||
|
`CREATE TABLE locations (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
name TEXT NOT NULL
|
||||||
|
)`,
|
||||||
|
`CREATE TABLE warehouses (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
type TEXT NOT NULL,
|
||||||
|
location_id INTEGER NULL,
|
||||||
|
kandang_id INTEGER NULL,
|
||||||
|
deleted_at TIMESTAMP NULL
|
||||||
|
)`,
|
||||||
|
`CREATE TABLE product_warehouses (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
product_id INTEGER NOT NULL,
|
||||||
|
warehouse_id INTEGER NOT NULL,
|
||||||
|
project_flock_kandang_id INTEGER NULL,
|
||||||
|
qty NUMERIC NULL
|
||||||
|
)`,
|
||||||
|
`INSERT INTO locations (id, name) VALUES (16, 'Jamali')`,
|
||||||
|
`INSERT INTO warehouses (id, name, type, location_id, kandang_id, deleted_at) VALUES
|
||||||
|
(21, 'Gudang Farm Jamali A', 'LOKASI', 16, NULL, NULL),
|
||||||
|
(25, 'Gudang Farm Jamali B', 'LOKASI', 16, NULL, NULL),
|
||||||
|
(46, 'Gudang Jamali 1', 'KANDANG', 16, 59, NULL)`,
|
||||||
|
`INSERT INTO product_warehouses (id, product_id, warehouse_id, project_flock_kandang_id, qty) VALUES
|
||||||
|
(101, 8, 46, 10, 500)`,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, stmt := range statements {
|
||||||
|
if err := db.Exec(stmt).Error; err != nil {
|
||||||
|
t.Fatalf("failed preparing schema: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return db
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user