386 lines
12 KiB
Go
386 lines
12 KiB
Go
package mysql
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"time"
|
|
|
|
"gorm.io/gorm"
|
|
|
|
"wucher/internal/domain/flight"
|
|
)
|
|
|
|
type FlightRepository struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
func preloadTakeoverRelations(q *gorm.DB) *gorm.DB {
|
|
return q.
|
|
Preload("Takeover").
|
|
Preload("Takeover.Base").
|
|
Preload("Takeover.Base.OperationalShiftTimes").
|
|
Preload("Takeover.ReserveAc").
|
|
Preload("Takeover.ReserveAc.Aircraft").
|
|
Preload("Takeover.ReserveAc.Inspection").
|
|
Preload("Takeover.RosterCrews").
|
|
Preload("Takeover.OtherPeople")
|
|
}
|
|
|
|
func NewFlightRepository(db *gorm.DB) *FlightRepository {
|
|
return &FlightRepository{db: db}
|
|
}
|
|
|
|
func (r *FlightRepository) Create(ctx context.Context, row *flight.Flight) error {
|
|
return r.db.WithContext(ctx).Create(row).Error
|
|
}
|
|
|
|
func (r *FlightRepository) GetLatestMissionCodeByPrefix(ctx context.Context, prefix string) (string, error) {
|
|
var out struct {
|
|
MissionCode string `gorm:"column:mission_code"`
|
|
}
|
|
err := r.db.WithContext(ctx).
|
|
Table("flights").
|
|
Select("mission_code").
|
|
Where("mission_code LIKE ? AND deleted_at IS NULL", prefix+"%").
|
|
Order("mission_code DESC").
|
|
Limit(1).
|
|
Scan(&out).Error
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return out.MissionCode, nil
|
|
}
|
|
|
|
func (r *FlightRepository) Update(ctx context.Context, row *flight.Flight) error {
|
|
return r.db.WithContext(ctx).Save(row).Error
|
|
}
|
|
|
|
func (r *FlightRepository) Delete(ctx context.Context, id []byte, deletedBy []byte) error {
|
|
now := time.Now().UTC()
|
|
updates := map[string]any{
|
|
"deleted_at": now,
|
|
"deleted_by": deletedBy,
|
|
"updated_by": deletedBy,
|
|
}
|
|
return r.db.WithContext(ctx).
|
|
Model(&flight.Flight{}).
|
|
Where("id = ? AND deleted_at IS NULL", id).
|
|
Updates(updates).Error
|
|
}
|
|
|
|
func (r *FlightRepository) GetByID(ctx context.Context, id []byte) (*flight.Flight, error) {
|
|
var row flight.Flight
|
|
err := r.db.WithContext(ctx).
|
|
Model(&flight.Flight{}).
|
|
Select(flightReadSelectSQL()).
|
|
Preload("Takeover").
|
|
Preload("Takeover.Base").
|
|
Preload("Takeover.Base.OperationalShiftTimes").
|
|
Preload("Takeover.ReserveAc").
|
|
Preload("Takeover.ReserveAc.Aircraft").
|
|
Preload("Takeover.ReserveAc.Inspection").
|
|
Preload("Takeover.RosterCrews").
|
|
Preload("Takeover.OtherPeople").
|
|
Joins("LEFT JOIN users cu ON cu.id = flights.created_by").
|
|
Joins("LEFT JOIN users uu ON uu.id = flights.updated_by").
|
|
Where("flights.id = ? AND flights.deleted_at IS NULL", id).
|
|
First(&row).Error
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, nil
|
|
}
|
|
return &row, err
|
|
}
|
|
|
|
func (r *FlightRepository) ListByUserID(ctx context.Context, userID []byte, limit, offset int) ([]flight.Flight, int64, error) {
|
|
rows := make([]flight.Flight, 0)
|
|
var total int64
|
|
|
|
base := r.db.WithContext(ctx).
|
|
Model(&flight.Flight{}).
|
|
Select(flightReadSelectSQL()).
|
|
Preload("Takeover").
|
|
Preload("Takeover.Base").
|
|
Preload("Takeover.ReserveAc").
|
|
Preload("Takeover.ReserveAc.Aircraft").
|
|
Preload("Takeover.ReserveAc.Inspection").
|
|
Preload("Takeover.RosterCrews").
|
|
Preload("Takeover.OtherPeople").
|
|
Joins("LEFT JOIN users cu ON cu.id = flights.created_by").
|
|
Joins("LEFT JOIN users uu ON uu.id = flights.updated_by").
|
|
Where("flights.deleted_at IS NULL").
|
|
Where(
|
|
`EXISTS (
|
|
SELECT 1
|
|
FROM duty_roster_crews c
|
|
JOIN duty_rosters r ON r.id = c.roster_id
|
|
WHERE c.user_id = ?
|
|
AND c.deleted_at IS NULL
|
|
AND r.deleted_at IS NULL
|
|
AND r.flight_id = flights.id
|
|
)`,
|
|
userID,
|
|
)
|
|
|
|
if err := base.Count(&total).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
query := base.Order("flights.date DESC, flights.created_at DESC")
|
|
if limit > 0 {
|
|
query = query.Limit(limit).Offset(offset)
|
|
}
|
|
if err := query.Find(&rows).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
return rows, total, nil
|
|
}
|
|
|
|
func (r *FlightRepository) ListByCreatedBy(ctx context.Context, createdBy []byte, filter string, date string, sort string, limit, offset int) ([]flight.Flight, int64, error) {
|
|
rows := make([]flight.Flight, 0)
|
|
var total int64
|
|
|
|
base := r.db.WithContext(ctx).
|
|
Model(&flight.Flight{}).
|
|
Select(flightReadSelectSQL()).
|
|
Preload("Takeover").
|
|
Preload("Takeover.Base").
|
|
Preload("Takeover.ReserveAc").
|
|
Preload("Takeover.ReserveAc.Aircraft").
|
|
Preload("Takeover.ReserveAc.Inspection").
|
|
Preload("Takeover.RosterCrews").
|
|
Preload("Takeover.OtherPeople").
|
|
Joins("LEFT JOIN users cu ON cu.id = flights.created_by").
|
|
Joins("LEFT JOIN users uu ON uu.id = flights.updated_by").
|
|
Where("flights.deleted_at IS NULL").
|
|
Where("flights.created_by = ?", createdBy)
|
|
if filter != "" {
|
|
like := "%" + filter + "%"
|
|
base = base.Where("flights.mission_code LIKE ?", like)
|
|
}
|
|
if date != "" {
|
|
base = base.Where("flights.date = ?", date)
|
|
}
|
|
|
|
if err := base.Count(&total).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
query := base
|
|
if sort != "" {
|
|
query = query.Order(sort)
|
|
} else {
|
|
query = query.Order("flights.date DESC, flights.created_at DESC")
|
|
}
|
|
if limit > 0 {
|
|
query = query.Limit(limit).Offset(offset)
|
|
}
|
|
if err := query.Find(&rows).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
return rows, total, nil
|
|
}
|
|
|
|
func (r *FlightRepository) GetByReserveAcID(ctx context.Context, reserveAcID []byte) (*flight.Flight, error) {
|
|
var row flight.Flight
|
|
err := r.db.WithContext(ctx).
|
|
Model(&flight.Flight{}).
|
|
Select(flightReadSelectSQL()).
|
|
Preload("Takeover").
|
|
Preload("Takeover.Base").
|
|
Preload("Takeover.ReserveAc").
|
|
Preload("Takeover.ReserveAc.Aircraft").
|
|
Preload("Takeover.ReserveAc.Inspection").
|
|
Preload("Takeover.RosterCrews").
|
|
Preload("Takeover.OtherPeople").
|
|
Joins("LEFT JOIN users cu ON cu.id = flights.created_by").
|
|
Joins("LEFT JOIN users uu ON uu.id = flights.updated_by").
|
|
Joins("JOIN takeover_acs ta ON ta.id = flights.takeover_ac_id AND ta.deleted_at IS NULL").
|
|
Where("ta.reserve_ac_id = ? AND flights.deleted_at IS NULL", reserveAcID).
|
|
First(&row).Error
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, nil
|
|
}
|
|
return &row, err
|
|
}
|
|
|
|
func (r *FlightRepository) ListByReserveAcID(ctx context.Context, reserveAcID []byte) ([]flight.Flight, error) {
|
|
rows := make([]flight.Flight, 0)
|
|
err := r.db.WithContext(ctx).
|
|
Model(&flight.Flight{}).
|
|
Select(flightReadSelectSQL()).
|
|
Preload("Takeover").
|
|
Preload("Takeover.Base").
|
|
Preload("Takeover.ReserveAc").
|
|
Preload("Takeover.ReserveAc.Aircraft").
|
|
Preload("Takeover.ReserveAc.Inspection").
|
|
Preload("Takeover.RosterCrews").
|
|
Preload("Takeover.OtherPeople").
|
|
Joins("LEFT JOIN users cu ON cu.id = flights.created_by").
|
|
Joins("LEFT JOIN users uu ON uu.id = flights.updated_by").
|
|
Joins("JOIN takeover_acs ta ON ta.id = flights.takeover_ac_id AND ta.deleted_at IS NULL").
|
|
Where("ta.reserve_ac_id = ? AND flights.deleted_at IS NULL", reserveAcID).
|
|
Order("flights.created_at ASC, flights.id ASC").
|
|
Find(&rows).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return rows, nil
|
|
}
|
|
|
|
func (r *FlightRepository) GetByTakeoverAcID(ctx context.Context, takeoverAcID []byte) (*flight.Flight, error) {
|
|
var row flight.Flight
|
|
err := r.db.WithContext(ctx).
|
|
Model(&flight.Flight{}).
|
|
Select(flightReadSelectSQL()).
|
|
Preload("Takeover").
|
|
Preload("Takeover.Base").
|
|
Preload("Takeover.ReserveAc").
|
|
Preload("Takeover.ReserveAc.Aircraft").
|
|
Preload("Takeover.ReserveAc.Inspection").
|
|
Preload("Takeover.RosterCrews").
|
|
Preload("Takeover.OtherPeople").
|
|
Joins("LEFT JOIN users cu ON cu.id = flights.created_by").
|
|
Joins("LEFT JOIN users uu ON uu.id = flights.updated_by").
|
|
Where("flights.takeover_ac_id = ? AND flights.deleted_at IS NULL", takeoverAcID).
|
|
First(&row).Error
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, nil
|
|
}
|
|
return &row, err
|
|
}
|
|
|
|
func (r *FlightRepository) ListByTakeoverAcIDs(ctx context.Context, takeoverAcIDs [][]byte) ([]flight.Flight, error) {
|
|
if len(takeoverAcIDs) == 0 {
|
|
return []flight.Flight{}, nil
|
|
}
|
|
rows := make([]flight.Flight, 0)
|
|
err := r.db.WithContext(ctx).
|
|
Model(&flight.Flight{}).
|
|
Select(flightListSelectSQL()).
|
|
Preload("Takeover").
|
|
Preload("Takeover.Base").
|
|
Preload("Takeover.ReserveAc").
|
|
Preload("Takeover.ReserveAc.Aircraft").
|
|
Preload("Takeover.ReserveAc.Inspection").
|
|
Preload("Takeover.RosterCrews").
|
|
Preload("Takeover.OtherPeople").
|
|
Where("flights.takeover_ac_id IN ? AND flights.deleted_at IS NULL", takeoverAcIDs).
|
|
Find(&rows).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return rows, nil
|
|
}
|
|
|
|
func (r *FlightRepository) GetByDutyRosterID(ctx context.Context, dutyRosterID []byte) (*flight.Flight, error) {
|
|
var row flight.Flight
|
|
err := r.db.WithContext(ctx).
|
|
Model(&flight.Flight{}).
|
|
Select(flightListSelectSQL()).
|
|
Preload("Takeover").
|
|
Preload("Takeover.Base").
|
|
Preload("Takeover.ReserveAc").
|
|
Preload("Takeover.ReserveAc.Aircraft").
|
|
Preload("Takeover.ReserveAc.Inspection").
|
|
Preload("Takeover.RosterCrews").
|
|
Preload("Takeover.OtherPeople").
|
|
Joins("JOIN duty_rosters dr ON dr.flight_id = flights.id AND dr.deleted_at IS NULL").
|
|
Where("dr.id = ? AND flights.deleted_at IS NULL", dutyRosterID).
|
|
First(&row).Error
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, nil
|
|
}
|
|
return &row, err
|
|
}
|
|
|
|
func (r *FlightRepository) ListByDutyRosterIDs(ctx context.Context, dutyRosterIDs [][]byte) ([]flight.Flight, error) {
|
|
if len(dutyRosterIDs) == 0 {
|
|
return []flight.Flight{}, nil
|
|
}
|
|
rows := make([]flight.Flight, 0)
|
|
err := r.db.WithContext(ctx).
|
|
Model(&flight.Flight{}).
|
|
Select(flightListSelectSQL()).
|
|
Preload("Takeover").
|
|
Preload("Takeover.ReserveAc").
|
|
Preload("Takeover.ReserveAc.Aircraft").
|
|
Preload("Takeover.ReserveAc.Inspection").
|
|
Joins("JOIN duty_rosters dr ON dr.flight_id = flights.id AND dr.deleted_at IS NULL").
|
|
Where("dr.id IN ? AND flights.deleted_at IS NULL", dutyRosterIDs).
|
|
Find(&rows).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return rows, nil
|
|
}
|
|
|
|
func (r *FlightRepository) List(ctx context.Context, filter string, date string, sort string, limit, offset int) ([]flight.Flight, int64, error) {
|
|
rows := make([]flight.Flight, 0)
|
|
var total int64
|
|
|
|
base := r.db.WithContext(ctx).
|
|
Model(&flight.Flight{}).
|
|
Select(flightReadSelectSQL()).
|
|
Preload("Takeover").
|
|
Preload("Takeover.Base").
|
|
Preload("Takeover.ReserveAc").
|
|
Preload("Takeover.ReserveAc.Aircraft").
|
|
Preload("Takeover.ReserveAc.Inspection").
|
|
Preload("Takeover.RosterCrews").
|
|
Preload("Takeover.OtherPeople").
|
|
Joins("LEFT JOIN users cu ON cu.id = flights.created_by").
|
|
Joins("LEFT JOIN users uu ON uu.id = flights.updated_by").
|
|
Where("flights.deleted_at IS NULL")
|
|
if filter != "" {
|
|
like := "%" + filter + "%"
|
|
base = base.Where("flights.mission_code LIKE ?", like)
|
|
}
|
|
if date != "" {
|
|
base = base.Where("flights.date = ?", date)
|
|
}
|
|
|
|
query := base
|
|
if sort != "" {
|
|
query = query.Order(sort)
|
|
}
|
|
if err := base.Count(&total).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
if limit > 0 {
|
|
query = query.Limit(limit).Offset(offset)
|
|
}
|
|
if err := query.Find(&rows).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
return rows, total, nil
|
|
}
|
|
|
|
func flightListSelectSQL() string {
|
|
// created_by_name / updated_by_name are resolved via correlated subqueries so the list
|
|
// queries carry the auditor display names without needing extra user JOINs (the read
|
|
// query joins users; the list variants don't). Keeps get-all in parity with get-by-id.
|
|
return `flights.*,
|
|
(SELECT dr.id FROM duty_rosters dr WHERE dr.flight_id = flights.id AND dr.deleted_at IS NULL LIMIT 1) AS duty_roster_id,
|
|
(SELECT ta.reserve_ac_id FROM takeover_acs ta WHERE ta.id = flights.takeover_ac_id AND ta.deleted_at IS NULL LIMIT 1) AS reserve_ac_id,
|
|
COALESCE((SELECT NULLIF(TRIM(CONCAT(COALESCE(cu.first_name, ''), ' ', COALESCE(cu.last_name, ''))), '')
|
|
FROM users cu WHERE cu.id = flights.created_by), '') AS created_by_name,
|
|
COALESCE((SELECT NULLIF(TRIM(CONCAT(COALESCE(uu.first_name, ''), ' ', COALESCE(uu.last_name, ''))), '')
|
|
FROM users uu WHERE uu.id = flights.updated_by), '') AS updated_by_name`
|
|
}
|
|
|
|
func flightReadSelectSQL() string {
|
|
return `flights.*,
|
|
(SELECT dr.id FROM duty_rosters dr WHERE dr.flight_id = flights.id AND dr.deleted_at IS NULL LIMIT 1) AS duty_roster_id,
|
|
(SELECT ta.reserve_ac_id FROM takeover_acs ta WHERE ta.id = flights.takeover_ac_id AND ta.deleted_at IS NULL LIMIT 1) AS reserve_ac_id,
|
|
COALESCE(
|
|
NULLIF(TRIM(CONCAT(COALESCE(cu.first_name, ''), ' ', COALESCE(cu.last_name, ''))), ''),
|
|
''
|
|
) AS created_by_name,
|
|
COALESCE(
|
|
NULLIF(TRIM(CONCAT(COALESCE(uu.first_name, ''), ' ', COALESCE(uu.last_name, ''))), ''),
|
|
''
|
|
) AS updated_by_name`
|
|
}
|