init push
This commit is contained in:
95
internal/service/fleet_status_update_test.go
Normal file
95
internal/service/fleet_status_update_test.go
Normal file
@@ -0,0 +1,95 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
|
||||
filemanager "wucher/internal/domain/file_manager"
|
||||
fleetstatus "wucher/internal/domain/fleet_status"
|
||||
"wucher/internal/domain/helicopter"
|
||||
helicopterusage "wucher/internal/domain/helicopter_usage"
|
||||
"wucher/internal/repository/mysql"
|
||||
)
|
||||
|
||||
// TestFleetStatusUpdateAcceptsNegativeSummaryAndBareSchedule guards the full service path
|
||||
// behind PATCH /fleet-status/update/{id}: negative summary values + an A/F schedule with
|
||||
// empty type/due/ext must persist (incl. syncAutomaticAOG, which the repo-level test skips).
|
||||
func TestFleetStatusUpdateAcceptsNegativeSummaryAndBareSchedule(t *testing.T) {
|
||||
dsn := fmt.Sprintf("file:fleet_update_repro_%d?mode=memory&cache=shared", time.Now().UnixNano())
|
||||
db, err := gorm.Open(sqlite.Open(dsn), &gorm.Config{NowFunc: func() time.Time { return time.Now().UTC() }})
|
||||
if err != nil {
|
||||
t.Fatalf("open sqlite: %v", err)
|
||||
}
|
||||
if err := db.AutoMigrate(
|
||||
&filemanager.Folder{}, &filemanager.File{}, &filemanager.Attachment{},
|
||||
&helicopter.Helicopter{},
|
||||
&fleetstatus.FleetStatus{}, &fleetstatus.MaintenanceSchedule{}, &fleetstatus.FleetStatusFile{},
|
||||
&helicopterusage.HelicopterUsage{},
|
||||
); err != nil {
|
||||
t.Fatalf("migrate: %v", err)
|
||||
}
|
||||
ctx := context.Background()
|
||||
|
||||
heliRepo := mysql.NewHelicopterRepository(db)
|
||||
heli := &helicopter.Helicopter{Designation: "H1", Identifier: "PK-H1", Type: "Twin", NR1: true, NR2: true}
|
||||
if err := heliRepo.Create(ctx, heli); err != nil {
|
||||
t.Fatalf("create heli: %v", err)
|
||||
}
|
||||
fsRepo := mysql.NewFleetStatusRepository(db)
|
||||
fs := &fleetstatus.FleetStatus{HelicopterID: heli.ID, Status: fleetstatus.StatusActive}
|
||||
if err := fsRepo.Create(ctx, fs); err != nil {
|
||||
t.Fatalf("create fs: %v", err)
|
||||
}
|
||||
|
||||
usageSvc := NewHelicopterUsageService(mysql.NewHelicopterUsageRepository(db))
|
||||
svc := NewFleetStatusService(fsRepo, nil, NewHelicopterService(heliRepo), nil).WithUsage(usageSvc)
|
||||
|
||||
// Handler builds this row from the patch: full-replace schedules with one A/F entry.
|
||||
fs.MaintenanceSchedules = []fleetstatus.MaintenanceSchedule{
|
||||
{FleetStatusID: fs.ID, InspectionType: "A/F", Type: "", Due: "", Ext: ""},
|
||||
}
|
||||
fs.UpdatedBy = heli.ID // any actor
|
||||
if err := svc.Update(ctx, fs); err != nil {
|
||||
t.Fatalf("REPRO: FleetStatusService.Update FAILED: %v", err)
|
||||
}
|
||||
t.Log("FleetStatusService.Update OK (incl syncAutomaticAOG)")
|
||||
|
||||
f := func(v float64) *float64 { return &v }
|
||||
if err := svc.ReviseSummary(ctx, heli.ID, helicopterusage.ManualSummaryInput{
|
||||
AirframeHours: f(1234), AirframeCycles: f(-1),
|
||||
Engine1Hours: f(1234), Engine1GpcNgN1: f(23.23), Engine1PtcNfN2: f(23.59), Engine1Ccc: f(-8),
|
||||
Engine2Hours: f(234), Engine2GpcNgN1: f(123), Engine2PtcNfN2: f(1230), Engine2Ccc: f(123),
|
||||
Landing: f(1), FlightReport: f(1), HookRelease: f(1), RotorBrakeCycle: f(1),
|
||||
}, heli.ID); err != nil {
|
||||
t.Fatalf("REPRO: ReviseSummary FAILED: %v", err)
|
||||
}
|
||||
got, _ := usageSvc.GetByHelicopterID(ctx, heli.ID)
|
||||
t.Logf("ReviseSummary OK: cycles=%v ccc1=%v ccc2=%v", got.TotalAirframeCycles, got.TotalEngine1Ccc, got.TotalEngine2Ccc)
|
||||
|
||||
// The fleet GET reads the summary via GetSummaryByHelicopterID — verify it reflects the patch.
|
||||
summary, err := svc.GetSummaryByHelicopterID(ctx, heli.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("GetSummaryByHelicopterID: %v", err)
|
||||
}
|
||||
if summary.Airframe.Hours == nil || *summary.Airframe.Hours != 1234 {
|
||||
t.Fatalf("summary airframe hours = %v, want 1234 (patch not reflected)", summary.Airframe.Hours)
|
||||
}
|
||||
if summary.Engine1.Hours == nil || *summary.Engine1.Hours != 1234 {
|
||||
t.Fatalf("summary engine1 hours = %v, want 1234", summary.Engine1.Hours)
|
||||
}
|
||||
|
||||
// Second PATCH with a NEW value — the "ga terganti" (value doesn't change) scenario.
|
||||
if err := svc.ReviseSummary(ctx, heli.ID, helicopterusage.ManualSummaryInput{AirframeHours: f(9999)}, heli.ID); err != nil {
|
||||
t.Fatalf("second ReviseSummary: %v", err)
|
||||
}
|
||||
summary2, _ := svc.GetSummaryByHelicopterID(ctx, heli.ID)
|
||||
if summary2.Airframe.Hours == nil || *summary2.Airframe.Hours != 9999 {
|
||||
t.Fatalf("second patch: airframe hours = %v, want 9999 (VALUE DID NOT CHANGE)", summary2.Airframe.Hours)
|
||||
}
|
||||
t.Logf("both patches reflected in GET summary: first af.hours=1234, second=%v", *summary2.Airframe.Hours)
|
||||
}
|
||||
Reference in New Issue
Block a user