package service import ( "fmt" "testing" "time" "github.com/glebarez/sqlite" "github.com/stretchr/testify/require" "gorm.io/gorm" "wails-app/internal/dao" "wails-app/internal/global" "wails-app/internal/modules/digital-ticket/repository" ) func setupTicketServiceTest(t *testing.T) *TicketService { dsn := fmt.Sprintf("file:digital-ticket-service-%d?mode=memory&cache=shared", time.Now().UnixNano()) db, err := gorm.Open(sqlite.Open(dsn), &gorm.Config{}) require.NoError(t, err) sqlDB, err := db.DB() require.NoError(t, err) sqlDB.SetMaxOpenConns(16) t.Cleanup(func() { _ = sqlDB.Close() if global.GVA_DB == db { global.GVA_DB = nil } }) global.GVA_DB = db require.NoError(t, db.AutoMigrate(&dao.VehicleRecord{}, &dao.DigitalTicket{})) return NewTicketService() } func TestMarkPaidAndExitedUsesTheActualPaymentEntry(t *testing.T) { svc := setupTicketServiceTest(t) record := &dao.VehicleRecord{PlateNumber: "TEST001"} require.NoError(t, global.GVA_DB.Create(record).Error) _, err := svc.Create("TEST001", "manual", record.ID) require.NoError(t, err) require.NoError(t, svc.MarkPaidAndExitedTx(global.GVA_DB, record.ID, "central_payment_machine", "pos", "ORDER-001", 10, 10)) ticket, err := svc.repo.GetByVehicleRecordID(record.ID) require.NoError(t, err) require.Equal(t, StateExited, ticket.State) require.Equal(t, "central_payment_machine", ticket.PaymentEntry) require.Equal(t, "pos", ticket.PaymentMethod) require.Equal(t, "ORDER-001", ticket.PaymentOrderNo) } func TestMarkPaidAndExitedRequiresATicket(t *testing.T) { svc := setupTicketServiceTest(t) record := &dao.VehicleRecord{PlateNumber: "TEST002"} require.NoError(t, global.GVA_DB.Create(record).Error) require.EqualError(t, svc.MarkPaidAndExitedTx(global.GVA_DB, record.ID, "counter", "cash", "", 0, 0), "车辆对应的数字票不存在") } func TestSummaryCountsTheCompleteFilteredSet(t *testing.T) { svc := setupTicketServiceTest(t) states := []string{StateCreated, StatePendingPayment, StatePendingPayment, StatePaid, StateExited, StateExpired} for i, state := range states { record := &dao.VehicleRecord{PlateNumber: "SUMMARY"} require.NoError(t, global.GVA_DB.Create(record).Error) ticket := &dao.DigitalTicket{ TicketNo: fmt.Sprintf("SUMMARY-%d", i), PlateNumber: "SUMMARY", State: state, VehicleRecordID: record.ID, EntryTime: time.Now(), } require.NoError(t, global.GVA_DB.Create(ticket).Error) } summary, err := svc.Summary(repository.TicketListQuery{PlateNumber: "SUMMARY", State: StatePaid, Page: 2, PageSize: 1}) require.NoError(t, err) require.EqualValues(t, 6, summary.Total) require.EqualValues(t, 3, summary.Pending) require.EqualValues(t, 1, summary.Paid) require.EqualValues(t, 1, summary.Exited) require.EqualValues(t, 1, summary.Expired) list, total, err := svc.List(repository.TicketListQuery{PlateNumber: "SUMMARY", State: StatePendingPayment}) require.NoError(t, err) require.EqualValues(t, 3, total) require.Len(t, list, 3) legacyRecord := &dao.VehicleRecord{PlateNumber: "SUMMARY-LEGACY"} require.NoError(t, global.GVA_DB.Create(legacyRecord).Error) require.NoError(t, global.GVA_DB.Create(&dao.DigitalTicket{ TicketNo: "SUMMARY-LEGACY-001", State: StatePendingPayment, VehicleRecordID: legacyRecord.ID, EntryTime: time.Now(), }).Error) legacySummary, err := svc.Summary(repository.TicketListQuery{PlateNumber: "SUMMARY-LEGACY"}) require.NoError(t, err) require.EqualValues(t, 1, legacySummary.Total) require.EqualValues(t, 1, legacySummary.Pending) } func TestPendingTicketUsesCurrentFeeAndRecordPlate(t *testing.T) { db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{}) require.NoError(t, err) global.GVA_DB = db require.NoError(t, db.AutoMigrate( &dao.VehicleRecord{}, &dao.DigitalTicket{}, &dao.Vehicle{}, &dao.VehicleType{}, &dao.FeeConfig{}, )) vehicleType := &dao.VehicleType{Name: "临时车", IsSystem: true} require.NoError(t, db.Create(vehicleType).Error) require.NoError(t, db.Create(&dao.FeeConfig{ VehicleTypeID: vehicleType.ID, StartTime: 0, StartFee: 0, UnitTime: 60, UnitFee: 5, DailyMaxFee: 50, }).Error) require.NoError(t, db.Create(&dao.Vehicle{PlateNumber: "粤A12345", VehicleTypeID: vehicleType.ID}).Error) record := &dao.VehicleRecord{PlateNumber: "粤A12345", EntryTime: time.Now().Add(-61 * time.Minute)} require.NoError(t, db.Create(record).Error) require.NoError(t, db.Create(&dao.DigitalTicket{ TicketNo: "FEE-001", PlateNumber: "", State: StatePendingPayment, VehicleRecordID: record.ID, EntryTime: record.EntryTime, }).Error) ticket, err := NewTicketService().GetByTicketNo("FEE-001") require.NoError(t, err) require.Equal(t, "粤A12345", ticket.PlateNumber) require.InDelta(t, 10, ticket.Fee, 0.001) }