package service import ( "context" "testing" "time" afterflightinspection "wucher/internal/domain/after_flight_inspection" ) type afterFlightInspectionRepoStub struct { exists bool caps *afterflightinspection.HelicopterCapabilities existing *afterflightinspection.AfterFlightInspection upserted *afterflightinspection.AfterFlightInspection upsertErr error existsErr error capErr error flightChecked int } func (r *afterFlightInspectionRepoStub) Upsert(_ context.Context, row *afterflightinspection.AfterFlightInspection) error { r.upserted = row return r.upsertErr } func (r *afterFlightInspectionRepoStub) GetByFlightInspectionID(context.Context, []byte) (*afterflightinspection.AfterFlightInspection, error) { return r.existing, nil } func (r *afterFlightInspectionRepoStub) DeleteByFlightInspectionID(context.Context, []byte) error { return nil } func (r *afterFlightInspectionRepoStub) FlightInspectionExists(context.Context, []byte) (bool, error) { if r.existsErr != nil { return false, r.existsErr } return r.exists, nil } func (r *afterFlightInspectionRepoStub) GetHelicopterCapabilities(context.Context, []byte) (*afterflightinspection.HelicopterCapabilities, error) { if r.capErr != nil { return nil, r.capErr } r.flightChecked++ return r.caps, nil } func TestAfterFlightInspectionServiceValidateRequestRequiresCapabilityChecks(t *testing.T) { svc := NewAfterFlightInspectionService(&afterFlightInspectionRepoStub{}) nr1 := "checked" nr2 := "checked" lh := "checked" rh := "checked" mgb := "checked" igb := "checked" tgb := "checked" req := &afterflightinspection.UpsertRequest{ OilEngineNR1Checked: &nr1, OilEngineNR2Checked: &nr2, HydraulicLHChecked: &lh, HydraulicRHChecked: &rh, OilTransmissionMGBChecked: &mgb, OilTransmissionIGBChecked: &igb, OilTransmissionTGBChecked: &tgb, } caps := &afterflightinspection.HelicopterCapabilities{ NR1: true, NR2: true, LH: true, RH: true, MGB: true, IGB: true, TGB: true, } if err := svc.validateRequest(req, caps); err != nil { t.Fatalf("expected request to be valid, got %v", err) } req.OilEngineNR2Checked = nil if err := svc.validateRequest(req, caps); err == nil { t.Fatal("expected missing required nr2 check to be rejected") } } func TestAfterFlightInspectionServiceUpsertUpdatesExistingRow(t *testing.T) { existingID := make([]byte, 16) for i := range existingID { existingID[i] = byte(i + 1) } createdBy := []byte("creator123456789") createdAt := time.Date(2026, 1, 1, 8, 0, 0, 0, time.UTC) repo := &afterFlightInspectionRepoStub{ exists: true, caps: &afterflightinspection.HelicopterCapabilities{NR1: true}, existing: &afterflightinspection.AfterFlightInspection{ ID: existingID, CreatedAt: createdAt, CreatedBy: createdBy, }, } svc := NewAfterFlightInspectionService(repo) flightInspectionID := make([]byte, 16) for i := range flightInspectionID { flightInspectionID[i] = byte(100 + i) } nr1 := "400" row, err := svc.Upsert(context.Background(), flightInspectionID, &afterflightinspection.UpsertRequest{ OilEngineNR1Checked: &nr1, }) if err != nil { t.Fatalf("Upsert returned error: %v", err) } // The saved row must reuse the existing identity so GORM performs an UPDATE // instead of inserting a duplicate flight_inspection_id (the original bug). if string(repo.upserted.ID) != string(existingID) { t.Fatalf("expected upsert to reuse existing ID %x, got %x", existingID, repo.upserted.ID) } if !repo.upserted.CreatedAt.Equal(createdAt) { t.Fatalf("expected created_at to be preserved, got %v", repo.upserted.CreatedAt) } if string(repo.upserted.CreatedBy) != string(createdBy) { t.Fatalf("expected created_by to be preserved, got %x", repo.upserted.CreatedBy) } if row == nil || string(row.ID) != string(existingID) { t.Fatal("expected returned row to carry existing ID") } } func TestAfterFlightInspectionServiceUpsertInsertsWhenAbsent(t *testing.T) { repo := &afterFlightInspectionRepoStub{ exists: true, caps: &afterflightinspection.HelicopterCapabilities{NR1: true}, } svc := NewAfterFlightInspectionService(repo) flightInspectionID := make([]byte, 16) for i := range flightInspectionID { flightInspectionID[i] = byte(50 + i) } nr1 := "400" if _, err := svc.Upsert(context.Background(), flightInspectionID, &afterflightinspection.UpsertRequest{ OilEngineNR1Checked: &nr1, }); err != nil { t.Fatalf("Upsert returned error: %v", err) } // No existing row: a new INSERT (empty ID, BeforeCreate mints a UUID). if len(repo.upserted.ID) != 0 { t.Fatalf("expected empty ID for new row, got %x", repo.upserted.ID) } if string(repo.upserted.FlightInspectionID) != string(flightInspectionID) { t.Fatal("expected flight_inspection_id to be set") } } func TestAfterFlightInspectionServiceValidateRequestRejectsUnsupportedChecks(t *testing.T) { svc := NewAfterFlightInspectionService(&afterFlightInspectionRepoStub{}) yes := "checked" req := &afterflightinspection.UpsertRequest{ OilEngineNR1Checked: &yes, } caps := &afterflightinspection.HelicopterCapabilities{} if err := svc.validateRequest(req, caps); err == nil { t.Fatal("expected unsupported nr1 check to be rejected") } }