Files
lti-api/internal/utils/recording/util.recording_test.go
T
2026-06-07 18:55:24 +07:00

176 lines
6.0 KiB
Go

package recording
import (
"context"
"testing"
"time"
"github.com/glebarez/sqlite"
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/production/recordings/validations"
"gitlab.com/mbugroup/lti-api.git/internal/utils"
"gorm.io/gorm"
)
func TestMapDepletionsKeepsSourceWarehouseRoutes(t *testing.T) {
sourceA := uint(11)
sourceB := uint(12)
got := MapDepletions(99, []validation.Depletion{
{ProductWarehouseId: 21, SourceProductWarehouseId: &sourceA, Qty: 3},
{ProductWarehouseId: 21, SourceProductWarehouseId: &sourceA, Qty: 2},
{ProductWarehouseId: 21, SourceProductWarehouseId: &sourceB, Qty: 4},
})
if len(got) != 2 {
t.Fatalf("expected 2 depletion routes, got %d", len(got))
}
routeQty := DepletionTotalsByRoute(got, func(item entity.RecordingDepletion) (uint, *uint, float64) {
return item.ProductWarehouseId, item.SourceProductWarehouseId, item.Qty
})
if routeQty[DepletionRoute{ProductWarehouseId: 21, SourceProductWarehouseId: sourceA}] != 5 {
t.Fatalf("expected source A qty 5, got %.2f", routeQty[DepletionRoute{ProductWarehouseId: 21, SourceProductWarehouseId: sourceA}])
}
if routeQty[DepletionRoute{ProductWarehouseId: 21, SourceProductWarehouseId: sourceB}] != 4 {
t.Fatalf("expected source B qty 4, got %.2f", routeQty[DepletionRoute{ProductWarehouseId: 21, SourceProductWarehouseId: sourceB}])
}
}
func TestMapEggsSetsProjectFlockKandangID(t *testing.T) {
got := MapEggs(77, 44, 9, []validation.Egg{
{ProductWarehouseId: 88, Qty: 10},
})
if len(got) != 1 {
t.Fatalf("expected 1 egg row, got %d", len(got))
}
if got[0].ProjectFlockKandangId == nil || *got[0].ProjectFlockKandangId != 44 {
t.Fatalf("expected project flock kandang id 44, got %+v", got[0].ProjectFlockKandangId)
}
}
func TestAttachProductionStandardsClampsLayingPreStandardWeek(t *testing.T) {
db := setupAttachProductionStandardTestDB(t)
day := 91
recordDate := time.Date(2026, 4, 2, 0, 0, 0, 0, time.UTC)
chickInDate := time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC)
recording := &entity.Recording{
Id: 501,
ProjectFlockKandangId: 103,
RecordDatetime: recordDate,
Day: &day,
ProjectFlockKandang: &entity.ProjectFlockKandang{
Id: 103,
ProjectFlock: entity.ProjectFlock{
Id: 52,
Category: string(utils.ProjectFlockCategoryLaying),
ProductionStandardId: 1,
ProductionStandard: entity.ProductionStandard{
Id: 1,
Name: "STD Laying",
},
},
},
}
actualWeek := computeTransferAwareWeek(recording, map[uint]time.Time{103: chickInDate})
if actualWeek != 13 {
t.Fatalf("expected actual transfer-aware week 13, got %d", actualWeek)
}
if err := AttachProductionStandards(context.Background(), db, false, nil, recording); err != nil {
t.Fatalf("expected attach standard to succeed, got %v", err)
}
if recording.Day == nil || *recording.Day != 91 {
t.Fatalf("expected actual recording day to remain 91, got %+v", recording.Day)
}
if recording.StandardWeek == nil || *recording.StandardWeek != 18 {
t.Fatalf("expected effective standard week 18, got %+v", recording.StandardWeek)
}
if recording.StandardFeedIntake == nil || *recording.StandardFeedIntake != 120 {
t.Fatalf("expected feed intake std from week 18, got %+v", recording.StandardFeedIntake)
}
if recording.StandardHenDay == nil || *recording.StandardHenDay != 80 {
t.Fatalf("expected hen day std from week 18, got %+v", recording.StandardHenDay)
}
if recording.StandardFcr == nil || *recording.StandardFcr != 2.1 {
t.Fatalf("expected fcr std from week 18, got %+v", recording.StandardFcr)
}
}
func setupAttachProductionStandardTestDB(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 production_standard_details (
id INTEGER PRIMARY KEY,
production_standard_id INTEGER NOT NULL,
week INTEGER NOT NULL,
target_hen_day_production NUMERIC NULL,
target_hen_house_production NUMERIC NULL,
target_egg_weight NUMERIC NULL,
target_egg_mass NUMERIC NULL,
standard_fcr NUMERIC NULL,
created_at TIMESTAMP NULL,
updated_at TIMESTAMP NULL
)`,
`CREATE TABLE standard_growth_details (
id INTEGER PRIMARY KEY,
production_standard_id INTEGER NOT NULL,
target_mean_bw NUMERIC NULL,
max_depletion NUMERIC NULL,
min_uniformity NUMERIC NOT NULL,
week INTEGER NOT NULL,
feed_intake NUMERIC NULL,
created_at TIMESTAMP NULL,
created_by INTEGER NOT NULL
)`,
`CREATE TABLE laying_transfer_targets (
id INTEGER PRIMARY KEY,
laying_transfer_id INTEGER NOT NULL,
target_project_flock_kandang_id INTEGER NOT NULL,
deleted_at TIMESTAMP NULL
)`,
`CREATE TABLE laying_transfers (
id INTEGER PRIMARY KEY,
source_project_flock_kandang_id INTEGER NULL,
deleted_at TIMESTAMP NULL
)`,
`CREATE TABLE project_chickins (
id INTEGER PRIMARY KEY,
project_flock_kandang_id INTEGER NOT NULL,
chick_in_date TIMESTAMP NOT NULL,
deleted_at TIMESTAMP NULL
)`,
`INSERT INTO production_standard_details
(id, production_standard_id, week, target_hen_day_production, target_hen_house_production, target_egg_weight, target_egg_mass, standard_fcr)
VALUES (1, 1, 18, 80, 70, 55, 44, 2.1)`,
`INSERT INTO standard_growth_details
(id, production_standard_id, week, feed_intake, max_depletion, min_uniformity, created_by)
VALUES (1, 1, 18, 120, 1.5, 80, 1)`,
`INSERT INTO laying_transfers (id, source_project_flock_kandang_id, deleted_at) VALUES
(77, 83, NULL)`,
`INSERT INTO laying_transfer_targets (id, laying_transfer_id, target_project_flock_kandang_id, deleted_at) VALUES
(88, 77, 103, NULL)`,
`INSERT INTO project_chickins (id, project_flock_kandang_id, chick_in_date, deleted_at) VALUES
(99, 83, '2026-01-01 00:00:00', NULL)`,
}
for _, stmt := range statements {
if err := db.Exec(stmt).Error; err != nil {
t.Fatalf("failed preparing schema: %v", err)
}
}
return db
}