package repositories import ( "context" "errors" "testing" "time" "github.com/glebarez/sqlite" entity "gitlab.com/mbugroup/lti-api.git/internal/entities" "gorm.io/gorm" ) func TestUpdateReceivingDetailsAllowsNoOpUpdatesOnExistingItem(t *testing.T) { db := setupPurchaseRepositoryTestDB(t) repo := NewPurchaseRepository(db) ctx := context.Background() receivedAt := time.Date(2026, 4, 1, 0, 0, 0, 0, time.UTC) travelNumber := "SJ-001" vehicleNumber := "B 1234 CD" if err := db.WithContext(ctx).Create(&entity.PurchaseItem{ Id: 10, PurchaseId: 1, ProductId: 2, WarehouseId: 3, SubQty: 10, TotalQty: 10, Price: 15000, TotalPrice: 150000, ReceivedDate: &receivedAt, TravelNumber: &travelNumber, VehicleNumber: &vehicleNumber, }).Error; err != nil { t.Fatalf("failed seeding purchase item: %v", err) } pwID := uint(99) if err := repo.UpdateReceivingDetails(ctx, 1, []PurchaseReceivingUpdate{ { ItemID: 10, ReceivedDate: &receivedAt, TravelNumber: &travelNumber, VehicleNumber: &vehicleNumber, ProductWarehouseID: &pwID, }, }); err != nil { t.Fatalf("expected no-op receive update to succeed, got %v", err) } } func TestUpdateReceivingDetailsReturnsNotFoundForMissingItem(t *testing.T) { db := setupPurchaseRepositoryTestDB(t) repo := NewPurchaseRepository(db) ctx := context.Background() receivedAt := time.Date(2026, 4, 1, 0, 0, 0, 0, time.UTC) err := repo.UpdateReceivingDetails(ctx, 1, []PurchaseReceivingUpdate{ { ItemID: 999, ReceivedDate: &receivedAt, }, }) if !errors.Is(err, gorm.ErrRecordNotFound) { t.Fatalf("expected gorm.ErrRecordNotFound, got %v", err) } } func TestUpdatePricingAllowsNoOpUpdatesOnExistingItem(t *testing.T) { db := setupPurchaseRepositoryTestDB(t) repo := NewPurchaseRepository(db) ctx := context.Background() if err := db.WithContext(ctx).Create(&entity.PurchaseItem{ Id: 20, PurchaseId: 2, ProductId: 5, WarehouseId: 6, SubQty: 5, TotalQty: 5, Price: 10000, TotalPrice: 50000, }).Error; err != nil { t.Fatalf("failed seeding purchase item: %v", err) } if err := repo.UpdatePricing(ctx, 2, []PurchasePricingUpdate{ { ItemID: 20, Price: 10000, TotalPrice: 50000, }, }); err != nil { t.Fatalf("expected no-op pricing update to succeed, got %v", err) } } func TestUpdatePricingReturnsNotFoundForMissingItem(t *testing.T) { db := setupPurchaseRepositoryTestDB(t) repo := NewPurchaseRepository(db) ctx := context.Background() err := repo.UpdatePricing(ctx, 2, []PurchasePricingUpdate{ { ItemID: 777, Price: 10000, TotalPrice: 50000, }, }) if !errors.Is(err, gorm.ErrRecordNotFound) { t.Fatalf("expected gorm.ErrRecordNotFound, got %v", err) } } func setupPurchaseRepositoryTestDB(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 purchase_items ( id INTEGER PRIMARY KEY, purchase_id INTEGER NOT NULL, product_id INTEGER NOT NULL, warehouse_id INTEGER NOT NULL, product_warehouse_id INTEGER NULL, project_flock_kandang_id INTEGER NULL, received_date TIMESTAMP NULL, travel_number TEXT NULL, travel_number_docs TEXT NULL, vehicle_number TEXT NULL, sub_qty NUMERIC(15,3) NOT NULL DEFAULT 0, total_qty NUMERIC(15,3) NOT NULL DEFAULT 0, total_used NUMERIC(15,3) NOT NULL DEFAULT 0, price NUMERIC(15,3) NOT NULL DEFAULT 0, total_price NUMERIC(15,3) NOT NULL DEFAULT 0, expense_nonstock_id INTEGER NULL )`, } for _, stmt := range statements { if err := db.Exec(stmt).Error; err != nil { t.Fatalf("failed preparing schema: %v", err) } } return db }