init push
This commit is contained in:
555
internal/service/reserve_ac_update_service.go
Normal file
555
internal/service/reserve_ac_update_service.go
Normal file
@@ -0,0 +1,555 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
beforeflightinspection "wucher/internal/domain/before_flight_inspection"
|
||||
"wucher/internal/domain/flight"
|
||||
flightinspection "wucher/internal/domain/flight_inspection"
|
||||
flightinspectionfilechecklist "wucher/internal/domain/flight_inspection_file_checklist"
|
||||
flightprepcheck "wucher/internal/domain/flight_prep_check"
|
||||
helicopterfile "wucher/internal/domain/helicopter_file"
|
||||
reserveac "wucher/internal/domain/reserve_ac"
|
||||
"wucher/internal/shared/pkg/uuidv7"
|
||||
requestdto "wucher/internal/transport/http/dto/request"
|
||||
)
|
||||
|
||||
// ReserveAcUpdateError carries structured validation/update failures from the
|
||||
// application service layer back to the HTTP handler.
|
||||
type ReserveAcUpdateError struct {
|
||||
Status int
|
||||
Title string
|
||||
Detail string
|
||||
Pointer string
|
||||
}
|
||||
|
||||
func (e *ReserveAcUpdateError) Error() string {
|
||||
if e == nil {
|
||||
return ""
|
||||
}
|
||||
return e.Detail
|
||||
}
|
||||
|
||||
type ReserveAcUpdateInput struct {
|
||||
ID []byte
|
||||
ActorUserID []byte
|
||||
AircraftID *string
|
||||
FlightID *string
|
||||
Inspection *requestdto.ReserveAcInspectionUpdateAttributes
|
||||
Flight reserveAcFlightService
|
||||
Inspect flightinspection.FlightInspectionService
|
||||
Before beforeflightinspection.Service
|
||||
Prep flightprepcheck.Service
|
||||
HeliFile helicopterfile.Service
|
||||
FileChecklist flightinspectionfilechecklist.Service
|
||||
}
|
||||
|
||||
type reserveAcFlightService interface {
|
||||
GetByID(ctx context.Context, id []byte) (*flight.Flight, error)
|
||||
GetByReserveAcID(ctx context.Context, reserveAcID []byte) (*flight.Flight, error)
|
||||
Update(ctx context.Context, row *flight.Flight) error
|
||||
}
|
||||
|
||||
type ReserveAcCreateInput struct {
|
||||
HelicopterID []byte
|
||||
FlightID []byte
|
||||
InspectionDate time.Time
|
||||
Before *requestdto.ReserveAcBeforeInspectionAttributes
|
||||
Prepare *requestdto.ReserveAcPrepareInspectionAttributes
|
||||
ActorUserID []byte
|
||||
Flight reserveAcFlightService
|
||||
Inspect flightinspection.FlightInspectionService
|
||||
BeforeSvc beforeflightinspection.Service
|
||||
Prep flightprepcheck.Service
|
||||
HeliFile helicopterfile.Service
|
||||
FileChecklist flightinspectionfilechecklist.Service
|
||||
}
|
||||
|
||||
func (s *ReserveAcService) UpdateDetailed(ctx context.Context, in ReserveAcUpdateInput) (*reserveac.ReserveAc, error) {
|
||||
if s == nil || s.repo == nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 500, Title: "Update failed", Detail: "reserve ac service is not configured"}
|
||||
}
|
||||
if len(in.ID) != 16 {
|
||||
return nil, &ReserveAcUpdateError{Status: 422, Title: "Validation error", Detail: "id is invalid UUID", Pointer: "/data/id"}
|
||||
}
|
||||
|
||||
existing, err := s.repo.GetByID(ctx, in.ID)
|
||||
if err != nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 400, Title: "Update failed", Detail: err.Error()}
|
||||
}
|
||||
if existing == nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 404, Title: "Not found", Detail: "reserve_ac not found"}
|
||||
}
|
||||
|
||||
if in.FlightID != nil {
|
||||
if in.Flight == nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 500, Title: "Update failed", Detail: "flight service is not configured"}
|
||||
}
|
||||
flightValue := strings.TrimSpace(*in.FlightID)
|
||||
flightID, parseErr := uuidv7.ParseString(flightValue)
|
||||
if parseErr != nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 422, Title: "Validation error", Detail: "flight_id is invalid UUID", Pointer: "/data/attributes/flight_id"}
|
||||
}
|
||||
|
||||
targetFlight, flightErr := in.Flight.GetByID(ctx, flightID)
|
||||
if flightErr != nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 400, Title: "Update failed", Detail: flightErr.Error()}
|
||||
}
|
||||
if targetFlight == nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 422, Title: "Validation error", Detail: "flight_id does not exist", Pointer: "/data/attributes/flight_id"}
|
||||
}
|
||||
if len(targetFlight.ReserveAcID) == 16 && !bytes.Equal(targetFlight.ReserveAcID, existing.ID) {
|
||||
return nil, &ReserveAcUpdateError{Status: 422, Title: "Validation error", Detail: "flight already has reserve_ac assigned", Pointer: "/data/attributes/flight_id"}
|
||||
}
|
||||
|
||||
currentFlight, currentErr := in.Flight.GetByReserveAcID(ctx, existing.ID)
|
||||
if currentErr != nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 400, Title: "Update failed", Detail: currentErr.Error()}
|
||||
}
|
||||
if currentFlight != nil && !bytes.Equal(currentFlight.ID, targetFlight.ID) {
|
||||
currentFlight.ReserveAcID = nil
|
||||
currentFlight.UpdatedBy = in.ActorUserID
|
||||
if updateErr := in.Flight.Update(ctx, currentFlight); updateErr != nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 400, Title: "Update failed", Detail: updateErr.Error()}
|
||||
}
|
||||
}
|
||||
|
||||
if len(targetFlight.ReserveAcID) != 16 || !bytes.Equal(targetFlight.ReserveAcID, existing.ID) {
|
||||
targetFlight.ReserveAcID = append([]byte(nil), existing.ID...)
|
||||
targetFlight.UpdatedBy = in.ActorUserID
|
||||
if updateErr := in.Flight.Update(ctx, targetFlight); updateErr != nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 400, Title: "Update failed", Detail: updateErr.Error()}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if in.AircraftID != nil && strings.TrimSpace(*in.AircraftID) != "" {
|
||||
helicopterValue := strings.TrimSpace(*in.AircraftID)
|
||||
helicopterID, parseErr := uuidv7.ParseString(helicopterValue)
|
||||
if parseErr != nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 422, Title: "Validation error", Detail: "helicopter_id is invalid UUID", Pointer: "/data/attributes/helicopter_id"}
|
||||
}
|
||||
exists, existsErr := s.repo.AircraftExists(ctx, helicopterID)
|
||||
if existsErr != nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 400, Title: "Update failed", Detail: existsErr.Error()}
|
||||
}
|
||||
if !exists {
|
||||
return nil, &ReserveAcUpdateError{Status: 422, Title: "Validation error", Detail: "helicopter_id does not exist", Pointer: "/data/attributes/helicopter_id"}
|
||||
}
|
||||
existing.AircraftID = helicopterID
|
||||
}
|
||||
|
||||
if in.Inspection != nil {
|
||||
if in.Inspect == nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 500, Title: "Update failed", Detail: "flight inspection service is not configured"}
|
||||
}
|
||||
if in.Before == nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 500, Title: "Update failed", Detail: "before flight inspection service is not configured"}
|
||||
}
|
||||
if in.Prep == nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 500, Title: "Update failed", Detail: "flight prep check service is not configured"}
|
||||
}
|
||||
if in.HeliFile == nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 500, Title: "Update failed", Detail: "helicopter file service is not configured"}
|
||||
}
|
||||
if in.FileChecklist == nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 500, Title: "Update failed", Detail: "flight inspection file checklist service is not configured"}
|
||||
}
|
||||
|
||||
inspectionRow, getErr := in.Inspect.GetByID(ctx, existing.InspectionID)
|
||||
if getErr != nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 400, Title: "Update failed", Detail: getErr.Error()}
|
||||
}
|
||||
if inspectionRow == nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 404, Title: "Not found", Detail: "flight inspection not found"}
|
||||
}
|
||||
|
||||
if in.Inspection.InspectionDate != nil {
|
||||
inspectionDate, parseErr := time.Parse("2006-01-02", strings.TrimSpace(*in.Inspection.InspectionDate))
|
||||
if parseErr != nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 422, Title: "Validation error", Detail: "inspection.inspection_date must be YYYY-MM-DD", Pointer: "/data/attributes/inspection/inspection_date"}
|
||||
}
|
||||
inspectionRow.InspectionDate = inspectionDate.UTC()
|
||||
inspectionRow.UpdatedBy = in.ActorUserID
|
||||
if updateErr := in.Inspect.Update(ctx, inspectionRow); updateErr != nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 400, Title: "Update failed", Detail: updateErr.Error()}
|
||||
}
|
||||
}
|
||||
|
||||
if in.Inspection.Before != nil {
|
||||
beforeReq := &beforeflightinspection.UpsertRequest{
|
||||
OilEngineNR1Checked: in.Inspection.Before.OilEngineNR1Checked,
|
||||
OilEngineNR2Checked: in.Inspection.Before.OilEngineNR2Checked,
|
||||
HydraulicLHChecked: in.Inspection.Before.HydraulicLHChecked,
|
||||
HydraulicRHChecked: in.Inspection.Before.HydraulicRHChecked,
|
||||
OilTransmissionMGBChecked: in.Inspection.Before.OilTransmissionMGBChecked,
|
||||
OilTransmissionIGBChecked: in.Inspection.Before.OilTransmissionIGBChecked,
|
||||
OilTransmissionTGBChecked: in.Inspection.Before.OilTransmissionTGBChecked,
|
||||
FuelAmount: in.Inspection.Before.FuelAmount,
|
||||
FuelUnit: in.Inspection.Before.FuelUnit,
|
||||
FuelAddedAmount: in.Inspection.Before.FuelAddedAmount,
|
||||
Note: in.Inspection.Before.Note,
|
||||
}
|
||||
if _, upsertErr := in.Before.Upsert(ctx, existing.InspectionID, beforeReq); upsertErr != nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 400, Title: "Update failed", Detail: upsertErr.Error()}
|
||||
}
|
||||
if in.Inspection.Before.FileChecklist != nil {
|
||||
if err := s.upsertInspectionFileChecklistSection(ctx, in, existing.InspectionID, existing.AircraftID, helicopterfile.SectionBeforeFirstFlightInspection, in.Inspection.Before.FileChecklist, "/data/attributes/inspection/before/file_checklist", existing.ID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if in.Inspection.Prepare != nil {
|
||||
if _, upsertErr := in.Prep.UpsertByFlightInspection(ctx, existing.InspectionID, &flightprepcheck.UpsertRequest{
|
||||
NOTAMBriefing: in.Inspection.Prepare.NotamBriefing,
|
||||
WeatherBriefing: in.Inspection.Prepare.WeatherBriefing,
|
||||
OperationalFlightPlan: in.Inspection.Prepare.OperationalFlightPlan,
|
||||
}); upsertErr != nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 400, Title: "Update failed", Detail: upsertErr.Error()}
|
||||
}
|
||||
if in.Inspection.Prepare.FileChecklist != nil {
|
||||
if err := s.upsertInspectionFileChecklistSection(ctx, in, existing.InspectionID, existing.AircraftID, helicopterfile.SectionFlightPreparationAndWB, in.Inspection.Prepare.FileChecklist, "/data/attributes/inspection/prepare/file_checklist", existing.ID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
existing.UpdatedBy = in.ActorUserID
|
||||
existing.Status = s.calculateReserveAcStatus(ctx, in, existing.InspectionID, existing.AircraftID)
|
||||
if err := s.Update(ctx, existing); err != nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 400, Title: "Update failed", Detail: err.Error()}
|
||||
}
|
||||
|
||||
return existing, nil
|
||||
}
|
||||
|
||||
func (s *ReserveAcService) CreateDetailed(ctx context.Context, in ReserveAcCreateInput) (*reserveac.ReserveAc, error) {
|
||||
if s == nil || s.repo == nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 500, Title: "Create failed", Detail: "reserve ac service is not configured"}
|
||||
}
|
||||
if len(in.HelicopterID) != 16 {
|
||||
return nil, &ReserveAcUpdateError{Status: 422, Title: "Validation error", Detail: "helicopter_id is invalid UUID", Pointer: "/data/attributes/helicopter_id"}
|
||||
}
|
||||
if len(in.FlightID) != 16 {
|
||||
return nil, &ReserveAcUpdateError{Status: 422, Title: "Validation error", Detail: "flight_id is invalid UUID", Pointer: "/data/attributes/flight_id"}
|
||||
}
|
||||
if in.Before == nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 422, Title: "Validation error", Detail: "inspection.before is required", Pointer: "/data/attributes/inspection/before"}
|
||||
}
|
||||
if in.Prepare == nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 422, Title: "Validation error", Detail: "inspection.prepare is required", Pointer: "/data/attributes/inspection/prepare"}
|
||||
}
|
||||
if in.Flight == nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 500, Title: "Create failed", Detail: "flight service is not configured"}
|
||||
}
|
||||
if in.Inspect == nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 500, Title: "Create failed", Detail: "flight inspection service is not configured"}
|
||||
}
|
||||
if in.BeforeSvc == nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 500, Title: "Create failed", Detail: "before flight inspection service is not configured"}
|
||||
}
|
||||
if in.Prep == nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 500, Title: "Create failed", Detail: "flight prep check service is not configured"}
|
||||
}
|
||||
if in.HeliFile == nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 500, Title: "Create failed", Detail: "helicopter file service is not configured"}
|
||||
}
|
||||
if in.FileChecklist == nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 500, Title: "Create failed", Detail: "flight inspection file checklist service is not configured"}
|
||||
}
|
||||
|
||||
flightRow, err := in.Flight.GetByID(ctx, in.FlightID)
|
||||
if err != nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 400, Title: "Create failed", Detail: err.Error()}
|
||||
}
|
||||
if flightRow == nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 422, Title: "Validation error", Detail: "flight_id does not exist", Pointer: "/data/attributes/flight_id"}
|
||||
}
|
||||
if len(flightRow.ReserveAcID) == 16 {
|
||||
return nil, &ReserveAcUpdateError{Status: 422, Title: "Validation error", Detail: "flight already has reserve_ac assigned", Pointer: "/data/attributes/flight_id"}
|
||||
}
|
||||
|
||||
exists, err := s.repo.AircraftExists(ctx, in.HelicopterID)
|
||||
if err != nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 400, Title: "Create failed", Detail: err.Error()}
|
||||
}
|
||||
if !exists {
|
||||
return nil, &ReserveAcUpdateError{Status: 422, Title: "Validation error", Detail: "helicopter_id does not exist", Pointer: "/data/attributes/helicopter_id"}
|
||||
}
|
||||
|
||||
inspection := &flightinspection.FlightInspection{
|
||||
InspectionDate: in.InspectionDate.UTC(),
|
||||
CreatedBy: in.ActorUserID,
|
||||
UpdatedBy: in.ActorUserID,
|
||||
}
|
||||
if err := in.Inspect.CreateDraft(ctx, inspection); err != nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 400, Title: "Create failed", Detail: err.Error()}
|
||||
}
|
||||
|
||||
row := &reserveac.ReserveAc{
|
||||
Status: reserveac.StatusPending,
|
||||
AircraftID: append([]byte(nil), in.HelicopterID...),
|
||||
InspectionID: append([]byte(nil), inspection.ID...),
|
||||
CreatedBy: in.ActorUserID,
|
||||
UpdatedBy: in.ActorUserID,
|
||||
}
|
||||
if err := s.Create(ctx, row); err != nil {
|
||||
return nil, &ReserveAcUpdateError{Status: 400, Title: "Create failed", Detail: err.Error()}
|
||||
}
|
||||
|
||||
beforeReq := &beforeflightinspection.UpsertRequest{
|
||||
OilEngineNR1Checked: in.Before.OilEngineNR1Checked,
|
||||
OilEngineNR2Checked: in.Before.OilEngineNR2Checked,
|
||||
HydraulicLHChecked: in.Before.HydraulicLHChecked,
|
||||
HydraulicRHChecked: in.Before.HydraulicRHChecked,
|
||||
OilTransmissionMGBChecked: in.Before.OilTransmissionMGBChecked,
|
||||
OilTransmissionIGBChecked: in.Before.OilTransmissionIGBChecked,
|
||||
OilTransmissionTGBChecked: in.Before.OilTransmissionTGBChecked,
|
||||
FuelAmount: in.Before.FuelAmount,
|
||||
FuelUnit: in.Before.FuelUnit,
|
||||
FuelAddedAmount: in.Before.FuelAddedAmount,
|
||||
Note: in.Before.Note,
|
||||
}
|
||||
if _, err := in.BeforeSvc.Upsert(ctx, inspection.ID, beforeReq); err != nil {
|
||||
_ = s.Delete(ctx, row.ID, in.ActorUserID)
|
||||
return nil, &ReserveAcUpdateError{Status: 400, Title: "Create failed", Detail: err.Error()}
|
||||
}
|
||||
if _, err := in.Prep.InitializeChecks(ctx, inspection.ID); err != nil {
|
||||
_ = s.Delete(ctx, row.ID, in.ActorUserID)
|
||||
return nil, &ReserveAcUpdateError{Status: 400, Title: "Create failed", Detail: err.Error()}
|
||||
}
|
||||
if _, err := in.Prep.UpsertByFlightInspection(ctx, inspection.ID, &flightprepcheck.UpsertRequest{
|
||||
NOTAMBriefing: in.Prepare.NotamBriefing,
|
||||
WeatherBriefing: in.Prepare.WeatherBriefing,
|
||||
OperationalFlightPlan: in.Prepare.OperationalFlightPlan,
|
||||
}); err != nil {
|
||||
_ = s.Delete(ctx, row.ID, in.ActorUserID)
|
||||
return nil, &ReserveAcUpdateError{Status: 400, Title: "Create failed", Detail: err.Error()}
|
||||
}
|
||||
if in.Before.FileChecklist != nil {
|
||||
if err := s.upsertInspectionFileChecklistSection(ctx, ReserveAcUpdateInput{
|
||||
ActorUserID: in.ActorUserID,
|
||||
HeliFile: in.HeliFile,
|
||||
FileChecklist: in.FileChecklist,
|
||||
}, inspection.ID, in.HelicopterID, helicopterfile.SectionBeforeFirstFlightInspection, in.Before.FileChecklist, "/data/attributes/inspection/before/file_checklist", row.ID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if in.Prepare.FileChecklist != nil {
|
||||
if err := s.upsertInspectionFileChecklistSection(ctx, ReserveAcUpdateInput{
|
||||
ActorUserID: in.ActorUserID,
|
||||
HeliFile: in.HeliFile,
|
||||
FileChecklist: in.FileChecklist,
|
||||
}, inspection.ID, in.HelicopterID, helicopterfile.SectionFlightPreparationAndWB, in.Prepare.FileChecklist, "/data/attributes/inspection/prepare/file_checklist", row.ID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
flightRow.ReserveAcID = append([]byte(nil), row.ID...)
|
||||
flightRow.UpdatedBy = in.ActorUserID
|
||||
if err := in.Flight.Update(ctx, flightRow); err != nil {
|
||||
_ = s.Delete(ctx, row.ID, in.ActorUserID)
|
||||
return nil, &ReserveAcUpdateError{Status: 400, Title: "Create failed", Detail: err.Error()}
|
||||
}
|
||||
|
||||
row.Status = s.calculateReserveAcStatus(ctx, ReserveAcUpdateInput{
|
||||
Inspect: in.Inspect,
|
||||
Before: in.BeforeSvc,
|
||||
Prep: in.Prep,
|
||||
HeliFile: in.HeliFile,
|
||||
FileChecklist: in.FileChecklist,
|
||||
}, inspection.ID, in.HelicopterID)
|
||||
if err := s.Update(ctx, row); err != nil {
|
||||
_ = s.Delete(ctx, row.ID, in.ActorUserID)
|
||||
return nil, &ReserveAcUpdateError{Status: 400, Title: "Create failed", Detail: err.Error()}
|
||||
}
|
||||
|
||||
return row, nil
|
||||
}
|
||||
|
||||
func (s *ReserveAcService) calculateReserveAcStatus(ctx context.Context, in ReserveAcUpdateInput, inspectionID []byte, helicopterID []byte) string {
|
||||
if len(inspectionID) != 16 || len(helicopterID) != 16 {
|
||||
return reserveac.StatusPending
|
||||
}
|
||||
if in.Inspect == nil || in.Before == nil || in.Prep == nil || in.HeliFile == nil || in.FileChecklist == nil {
|
||||
return reserveac.StatusPending
|
||||
}
|
||||
|
||||
inspectionRow, err := in.Inspect.GetByID(ctx, inspectionID)
|
||||
if err != nil || inspectionRow == nil {
|
||||
return reserveac.StatusPending
|
||||
}
|
||||
ckRows, err := in.FileChecklist.ListByInspectionID(ctx, inspectionID)
|
||||
if err != nil {
|
||||
return reserveac.StatusPending
|
||||
}
|
||||
isDoneByHeliFileID := make(map[string]bool, len(ckRows))
|
||||
for i := range ckRows {
|
||||
isDoneByHeliFileID[string(ckRows[i].HelicopterFileID)] = ckRows[i].IsDone
|
||||
}
|
||||
|
||||
beforeRows, err := in.HeliFile.ListByHelicopterAndSection(ctx, helicopterID, helicopterfile.SectionBeforeFirstFlightInspection)
|
||||
if err != nil {
|
||||
return reserveac.StatusPending
|
||||
}
|
||||
prepareRows, err := in.HeliFile.ListByHelicopterAndSection(ctx, helicopterID, helicopterfile.SectionFlightPreparationAndWB)
|
||||
if err != nil {
|
||||
return reserveac.StatusPending
|
||||
}
|
||||
beforeData, _ := in.Before.GetByFlightInspectionID(ctx, inspectionID)
|
||||
prepareData, _ := in.Prep.GetByFlightInspection(ctx, inspectionID)
|
||||
|
||||
beforeDone := countCompletedChecklist(beforeRows, isDoneByHeliFileID)
|
||||
prepareDone := countCompletedChecklist(prepareRows, isDoneByHeliFileID)
|
||||
totalChecklist := len(beforeRows) + len(prepareRows)
|
||||
doneChecklist := beforeDone + prepareDone
|
||||
if totalChecklist > 0 {
|
||||
if doneChecklist == 0 {
|
||||
return reserveac.StatusPending
|
||||
}
|
||||
if doneChecklist < totalChecklist {
|
||||
return reserveac.StatusOnProgress
|
||||
}
|
||||
return reserveac.StatusApproved
|
||||
}
|
||||
if beforeData != nil || prepareData != nil {
|
||||
return reserveac.StatusOnProgress
|
||||
}
|
||||
return reserveac.StatusPending
|
||||
}
|
||||
|
||||
func countCompletedChecklist(files []helicopterfile.HelicopterFile, doneByID map[string]bool) int {
|
||||
if len(files) == 0 {
|
||||
return 0
|
||||
}
|
||||
completed := 0
|
||||
for i := range files {
|
||||
if doneByID[string(files[i].ID)] {
|
||||
completed++
|
||||
}
|
||||
}
|
||||
return completed
|
||||
}
|
||||
|
||||
func (s *ReserveAcService) upsertInspectionFileChecklistSection(
|
||||
ctx context.Context,
|
||||
in ReserveAcUpdateInput,
|
||||
inspectionID []byte,
|
||||
helicopterID []byte,
|
||||
section string,
|
||||
payload []requestdto.ReserveAcFileChecklistItem,
|
||||
payloadPointer string,
|
||||
reserveAcID []byte,
|
||||
) error {
|
||||
templateFiles, err := in.HeliFile.ListByHelicopterAndSection(ctx, helicopterID, section)
|
||||
if err != nil {
|
||||
if len(reserveAcID) == 16 {
|
||||
_ = s.Delete(ctx, reserveAcID, in.ActorUserID)
|
||||
}
|
||||
return &ReserveAcUpdateError{Status: 400, Title: "Create failed", Detail: err.Error()}
|
||||
}
|
||||
|
||||
type requestedChecklist struct {
|
||||
fileID []byte
|
||||
isDone bool
|
||||
}
|
||||
requested := make([]requestedChecklist, 0, len(payload))
|
||||
for i := range payload {
|
||||
fileID, parseErr := uuidv7.ParseString(strings.TrimSpace(payload[i].HelicopterFileID))
|
||||
if parseErr != nil {
|
||||
if len(reserveAcID) == 16 {
|
||||
_ = s.Delete(ctx, reserveAcID, in.ActorUserID)
|
||||
}
|
||||
return &ReserveAcUpdateError{Status: 422, Title: "Validation error", Detail: "helicopter_file_id is invalid UUID", Pointer: payloadPointer}
|
||||
}
|
||||
requested = append(requested, requestedChecklist{
|
||||
fileID: fileID,
|
||||
isDone: payload[i].IsDone,
|
||||
})
|
||||
}
|
||||
requestedByFileID := make(map[string]bool, len(requested))
|
||||
for i := range requested {
|
||||
requestedByFileID[string(requested[i].fileID)] = requested[i].isDone
|
||||
}
|
||||
|
||||
existingRows, err := in.FileChecklist.ListByInspectionID(ctx, inspectionID)
|
||||
if err != nil {
|
||||
if len(reserveAcID) == 16 {
|
||||
_ = s.Delete(ctx, reserveAcID, in.ActorUserID)
|
||||
}
|
||||
return &ReserveAcUpdateError{Status: 400, Title: "Create failed", Detail: err.Error()}
|
||||
}
|
||||
existingByFileID := make(map[string]*flightinspectionfilechecklist.FlightInspectionFileChecklist, len(existingRows))
|
||||
for i := range existingRows {
|
||||
fileID := string(existingRows[i].HelicopterFileID)
|
||||
existingByFileID[fileID] = &existingRows[i]
|
||||
}
|
||||
|
||||
templateSet := make(map[string]struct{}, len(templateFiles))
|
||||
for i := range templateFiles {
|
||||
fileKey := string(templateFiles[i].ID)
|
||||
templateSet[fileKey] = struct{}{}
|
||||
|
||||
current := existingByFileID[fileKey]
|
||||
targetDone, hasOverride := requestedByFileID[fileKey]
|
||||
|
||||
if templateFiles[i].IsMandatory && !targetDone {
|
||||
if len(reserveAcID) == 16 {
|
||||
_ = s.Delete(ctx, reserveAcID, in.ActorUserID)
|
||||
}
|
||||
return &ReserveAcUpdateError{Status: 422, Title: "Validation error", Detail: "file_checklist must be fully checked", Pointer: payloadPointer}
|
||||
}
|
||||
|
||||
if current == nil {
|
||||
if !hasOverride {
|
||||
targetDone = false
|
||||
}
|
||||
newRow := &flightinspectionfilechecklist.FlightInspectionFileChecklist{
|
||||
FlightInspectionID: inspectionID,
|
||||
HelicopterFileID: templateFiles[i].ID,
|
||||
IsDone: targetDone,
|
||||
CreatedBy: in.ActorUserID,
|
||||
UpdatedBy: in.ActorUserID,
|
||||
}
|
||||
if err := in.FileChecklist.Create(ctx, newRow); err != nil {
|
||||
if len(reserveAcID) == 16 {
|
||||
_ = s.Delete(ctx, reserveAcID, in.ActorUserID)
|
||||
}
|
||||
return &ReserveAcUpdateError{Status: 400, Title: "Create failed", Detail: err.Error()}
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if !hasOverride {
|
||||
targetDone = current.IsDone
|
||||
}
|
||||
|
||||
if current.IsDone != targetDone {
|
||||
current.IsDone = targetDone
|
||||
current.UpdatedBy = in.ActorUserID
|
||||
if err := in.FileChecklist.Update(ctx, current); err != nil {
|
||||
if len(reserveAcID) == 16 {
|
||||
_ = s.Delete(ctx, reserveAcID, in.ActorUserID)
|
||||
}
|
||||
return &ReserveAcUpdateError{Status: 400, Title: "Create failed", Detail: err.Error()}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for i := range requested {
|
||||
if _, ok := templateSet[string(requested[i].fileID)]; ok {
|
||||
continue
|
||||
}
|
||||
if len(reserveAcID) == 16 {
|
||||
_ = s.Delete(ctx, reserveAcID, in.ActorUserID)
|
||||
}
|
||||
return &ReserveAcUpdateError{Status: 422, Title: "Validation error", Detail: "helicopter_file_id does not belong to selected helicopter/section", Pointer: payloadPointer}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user