package expiry import "testing" func TestService_CreateItemAndGetItems(t *testing.T) { db := newTestDB(t) repo := NewRepository(db) service := NewService(repo) productionDate := mustDate(t, "2030-01-01") shelfLife := 10 created, err := service.CreateItem(1, CreateItemRequest{ MiniProgramID: 1, Name: "测试牛奶", Category: CategoryFood, ProductionDate: &productionDate, ShelfLifeDays: &shelfLife, Quantity: 2, Location: "冰箱", Remark: "服务层测试", }) if err != nil { t.Fatalf("create item: %v", err) } if created.ExpiryDate.Format("2006-01-02") != "2030-01-11" { t.Fatalf("unexpected expiry date: %s", created.ExpiryDate.Format("2006-01-02")) } list, err := service.GetItems(1, ItemFilters{ Status: "all", Category: "all", Sort: "expiry_date", Page: 1, PageSize: 20, }) if err != nil { t.Fatalf("get items: %v", err) } if list.Total != 1 || len(list.Items) != 1 { t.Fatalf("expected 1 item, got total=%d len=%d", list.Total, len(list.Items)) } if list.Items[0].DaysLeft <= 0 { t.Fatalf("expected days_left > 0, got %d", list.Items[0].DaysLeft) } } func TestService_UpdateDeleteAndStatus(t *testing.T) { db := newTestDB(t) repo := NewRepository(db) service := NewService(repo) expiryDate := mustDate(t, "2030-02-01") created, err := service.CreateItem(2, CreateItemRequest{ MiniProgramID: 1, Name: "测试药品", Category: CategoryMedicine, ExpiryDate: &expiryDate, Quantity: 1, }) if err != nil { t.Fatalf("create item: %v", err) } newExpiry := mustDate(t, "2030-03-01") updated, err := service.UpdateItem(created.ID, 2, UpdateItemRequest{ MiniProgramID: 1, Name: "测试药品(更新)", Category: CategoryMedicine, ExpiryDate: &newExpiry, Quantity: 1, }) if err != nil { t.Fatalf("update item: %v", err) } if updated.Name != "测试药品(更新)" { t.Fatalf("unexpected updated name: %s", updated.Name) } if err := service.UpdateItemStatus(created.ID, 2, StatusUsed); err != nil { t.Fatalf("update item status: %v", err) } got, err := service.GetItem(created.ID, 2) if err != nil { t.Fatalf("get item: %v", err) } if got.Status != StatusUsed { t.Fatalf("expected used status, got %s", got.Status) } if err := service.DeleteItem(created.ID, 2); err != nil { t.Fatalf("delete item: %v", err) } _, err = service.GetItem(created.ID, 2) if err != ErrExpiryItemNotFound { t.Fatalf("expected not found, got %v", err) } } func TestService_Validation(t *testing.T) { db := newTestDB(t) repo := NewRepository(db) service := NewService(repo) expiryDate := mustDate(t, "2030-02-01") _, err := service.CreateItem(3, CreateItemRequest{ MiniProgramID: 1, Name: "", Category: CategoryFood, ExpiryDate: &expiryDate, Quantity: 1, }) if err != ErrExpiryNameInvalid { t.Fatalf("expected ErrExpiryNameInvalid, got %v", err) } _, err = service.GetItems(3, ItemFilters{Status: "invalid", Category: "all", Sort: "expiry_date", Page: 1, PageSize: 20}) if err != ErrExpiryFilterStatusInvalid { t.Fatalf("expected ErrExpiryFilterStatusInvalid, got %v", err) } err = service.UpdateItemStatus(1, 3, "unknown") if err != ErrExpiryStatusInvalid { t.Fatalf("expected ErrExpiryStatusInvalid, got %v", err) } } func TestService_Settings(t *testing.T) { db := newTestDB(t) repo := NewRepository(db) service := NewService(repo) defaults, err := service.GetSettings(10) if err != nil { t.Fatalf("get default settings: %v", err) } if len(defaults.RemindDays) != 3 { t.Fatalf("expected default remind_days len=3, got %d", len(defaults.RemindDays)) } _, err = service.UpdateSettings(10, []int{0, 31}) if err != ErrExpiryRemindDaysInvalid { t.Fatalf("expected ErrExpiryRemindDaysInvalid, got %v", err) } updated, err := service.UpdateSettings(10, []int{10, 10, 3, 1}) if err != nil { t.Fatalf("update settings: %v", err) } if len(updated.RemindDays) != 3 { t.Fatalf("expected deduped remind_days len=3, got %d", len(updated.RemindDays)) } }