package service import ( "context" "fmt" beforeflightinspection "wucher/internal/domain/before_flight_inspection" "wucher/internal/shared/pkg/appctx" ) type BeforeFlightInspectionService struct { repo beforeflightinspection.Repository } func NewBeforeFlightInspectionService(repo beforeflightinspection.Repository) *BeforeFlightInspectionService { return &BeforeFlightInspectionService{repo: repo} } func (s *BeforeFlightInspectionService) Upsert(ctx context.Context, flightInspectionID []byte, req *beforeflightinspection.UpsertRequest) (*beforeflightinspection.BeforeFlightInspection, error) { if len(flightInspectionID) != 16 { return nil, &beforeflightinspection.ValidationError{Status: 400, Title: "Invalid flight_inspection_id", Detail: "flight_inspection_id must be a valid UUID"} } exists, err := s.repo.FlightInspectionExists(ctx, flightInspectionID) if err != nil { return nil, fmt.Errorf("failed to check flight inspection: %w", err) } if !exists { return nil, &beforeflightinspection.ValidationError{Status: 404, Title: "Flight inspection not found", Detail: "The specified flight inspection does not exist"} } caps, err := s.repo.GetHelicopterCapabilities(ctx, flightInspectionID) if err != nil { return nil, fmt.Errorf("failed to get helicopter capabilities: %w", err) } if err := s.validateRequest(req, caps); err != nil { return nil, err } row := &beforeflightinspection.BeforeFlightInspection{ FlightInspectionID: flightInspectionID, OilEngineNR1Checked: req.OilEngineNR1Checked, OilEngineNR2Checked: req.OilEngineNR2Checked, HydraulicLHChecked: req.HydraulicLHChecked, HydraulicRHChecked: req.HydraulicRHChecked, OilTransmissionMGBChecked: req.OilTransmissionMGBChecked, OilTransmissionIGBChecked: req.OilTransmissionIGBChecked, OilTransmissionTGBChecked: req.OilTransmissionTGBChecked, FuelAmount: req.FuelAmount, FuelUnit: s.normalizeFuelUnit(req.FuelUnit), FuelAddedAmount: req.FuelAddedAmount, } // Keep update idempotent on unique flight_inspection_id. // If a row already exists, update it instead of inserting a new one. existing, err := s.repo.GetByFlightInspectionID(ctx, flightInspectionID) if err != nil { return nil, fmt.Errorf("failed to get before flight inspection: %w", err) } if existing != nil { row.ID = append([]byte(nil), existing.ID...) row.CreatedBy = append([]byte(nil), existing.CreatedBy...) row.CreatedAt = existing.CreatedAt } userID := appctx.GetUserID(ctx) if userID != nil { if existing == nil { row.CreatedBy = userID } row.UpdatedBy = userID } if err := s.repo.Upsert(ctx, row); err != nil { return nil, fmt.Errorf("failed to upsert before flight inspection: %w", err) } return row, nil } func (s *BeforeFlightInspectionService) GetByFlightInspectionID(ctx context.Context, flightInspectionID []byte) (*beforeflightinspection.BeforeFlightInspection, error) { if len(flightInspectionID) != 16 { return nil, &beforeflightinspection.ValidationError{Status: 400, Title: "Invalid flight_inspection_id", Detail: "flight_inspection_id must be a valid UUID"} } exists, err := s.repo.FlightInspectionExists(ctx, flightInspectionID) if err != nil { return nil, fmt.Errorf("failed to check flight inspection: %w", err) } if !exists { return nil, &beforeflightinspection.ValidationError{Status: 404, Title: "Flight inspection not found", Detail: "The specified flight inspection does not exist"} } row, err := s.repo.GetByFlightInspectionID(ctx, flightInspectionID) if err != nil { return nil, fmt.Errorf("failed to get before flight inspection: %w", err) } return row, nil } func (s *BeforeFlightInspectionService) validateRequest(req *beforeflightinspection.UpsertRequest, caps *beforeflightinspection.HelicopterCapabilities) error { if req.FuelAmount != nil && *req.FuelAmount < 0 { return &beforeflightinspection.ValidationError{Status: 422, Title: "Invalid fuel_amount", Detail: "fuel_amount cannot be negative"} } if req.FuelAddedAmount != nil && *req.FuelAddedAmount < 0 { return &beforeflightinspection.ValidationError{Status: 422, Title: "Invalid fuel_added_amount", Detail: "fuel_added_amount cannot be negative"} } if req.FuelUnit != nil { if _, valid := beforeflightinspection.NormalizeFuelUnit(*req.FuelUnit); !valid { return &beforeflightinspection.ValidationError{Status: 422, Title: "Invalid fuel_unit", Detail: "fuel_unit must be one of: LT, KG, POUND"} } } // Capability=true means corresponding check must be explicitly true. if caps.NR1 && (req.OilEngineNR1Checked == nil || !*req.OilEngineNR1Checked) { return &beforeflightinspection.ValidationError{Status: 422, Title: "Invalid oil_engine_nr1_checked", Detail: "oil_engine_nr1_checked must be true for this helicopter"} } if caps.NR2 && (req.OilEngineNR2Checked == nil || !*req.OilEngineNR2Checked) { return &beforeflightinspection.ValidationError{Status: 422, Title: "Invalid oil_engine_nr2_checked", Detail: "oil_engine_nr2_checked must be true for this helicopter"} } if caps.LH && (req.HydraulicLHChecked == nil || !*req.HydraulicLHChecked) { return &beforeflightinspection.ValidationError{Status: 422, Title: "Invalid hydraulic_lh_checked", Detail: "hydraulic_lh_checked must be true for this helicopter"} } if caps.RH && (req.HydraulicRHChecked == nil || !*req.HydraulicRHChecked) { return &beforeflightinspection.ValidationError{Status: 422, Title: "Invalid hydraulic_rh_checked", Detail: "hydraulic_rh_checked must be true for this helicopter"} } if caps.MGB && (req.OilTransmissionMGBChecked == nil || !*req.OilTransmissionMGBChecked) { return &beforeflightinspection.ValidationError{Status: 422, Title: "Invalid oil_transmission_mgb_checked", Detail: "oil_transmission_mgb_checked must be true for this helicopter"} } if caps.IGB && (req.OilTransmissionIGBChecked == nil || !*req.OilTransmissionIGBChecked) { return &beforeflightinspection.ValidationError{Status: 422, Title: "Invalid oil_transmission_igb_checked", Detail: "oil_transmission_igb_checked must be true for this helicopter"} } if caps.TGB && (req.OilTransmissionTGBChecked == nil || !*req.OilTransmissionTGBChecked) { return &beforeflightinspection.ValidationError{Status: 422, Title: "Invalid oil_transmission_tgb_checked", Detail: "oil_transmission_tgb_checked must be true for this helicopter"} } return nil } func (s *BeforeFlightInspectionService) normalizeFuelUnit(unit *string) string { if unit == nil { return "" } normalized, _ := beforeflightinspection.NormalizeFuelUnit(*unit) return normalized }