279 lines
8.0 KiB
Go
279 lines
8.0 KiB
Go
package mysql
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"strings"
|
|
"time"
|
|
|
|
"gorm.io/gorm"
|
|
|
|
fleetstatus "wucher/internal/domain/fleet_status"
|
|
)
|
|
|
|
type FleetStatusRepository struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
func NewFleetStatusRepository(db *gorm.DB) *FleetStatusRepository {
|
|
return &FleetStatusRepository{db: db}
|
|
}
|
|
|
|
func (r *FleetStatusRepository) Create(ctx context.Context, row *fleetstatus.FleetStatus) error {
|
|
return r.db.WithContext(ctx).Create(row).Error
|
|
}
|
|
|
|
func (r *FleetStatusRepository) CreateWithDB(ctx context.Context, db *gorm.DB, row *fleetstatus.FleetStatus) error {
|
|
return db.WithContext(ctx).Create(row).Error
|
|
}
|
|
|
|
func (r *FleetStatusRepository) Update(ctx context.Context, row *fleetstatus.FleetStatus) error {
|
|
return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
|
if err := tx.Model(&fleetstatus.FleetStatus{}).
|
|
Where("id = ? AND deleted_at IS NULL", row.ID).
|
|
Updates(map[string]any{
|
|
"helicopter_id": row.HelicopterID,
|
|
"status": row.Status,
|
|
"serviced_at": row.ServicedAt,
|
|
"updated_by": row.UpdatedBy,
|
|
}).Error; err != nil {
|
|
return err
|
|
}
|
|
if err := tx.Where("fleet_status_id = ?", row.ID).Delete(&fleetstatus.MaintenanceSchedule{}).Error; err != nil {
|
|
return err
|
|
}
|
|
if len(row.MaintenanceSchedules) > 0 {
|
|
for i := range row.MaintenanceSchedules {
|
|
row.MaintenanceSchedules[i].FleetStatusID = row.ID
|
|
}
|
|
if err := tx.Create(&row.MaintenanceSchedules).Error; err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if err := tx.Where("fleet_status_id = ?", row.ID).Delete(&fleetstatus.FleetStatusFile{}).Error; err != nil {
|
|
return err
|
|
}
|
|
if len(row.Files) > 0 {
|
|
for i := range row.Files {
|
|
row.Files[i].FleetStatusID = row.ID
|
|
}
|
|
if err := tx.Create(&row.Files).Error; err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
})
|
|
}
|
|
|
|
func (r *FleetStatusRepository) Delete(ctx context.Context, id []byte, deletedBy []byte) error {
|
|
now := time.Now().UTC()
|
|
return r.db.WithContext(ctx).
|
|
Model(&fleetstatus.FleetStatus{}).
|
|
Where("id = ? AND deleted_at IS NULL", id).
|
|
Updates(map[string]any{"deleted_at": now, "deleted_by": deletedBy, "updated_by": deletedBy}).Error
|
|
}
|
|
|
|
func (r *FleetStatusRepository) GetByID(ctx context.Context, id []byte) (*fleetstatus.FleetStatus, error) {
|
|
var row fleetstatus.FleetStatus
|
|
err := r.db.WithContext(ctx).
|
|
Preload("Helicopter").
|
|
Preload("MaintenanceSchedules").
|
|
Preload("Files").
|
|
Preload("Files.Attachment").
|
|
Preload("Files.Attachment.File").
|
|
Where("id = ? AND deleted_at IS NULL", id).
|
|
First(&row).Error
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, nil
|
|
}
|
|
return &row, err
|
|
}
|
|
|
|
func (r *FleetStatusRepository) List(ctx context.Context, filter, sort string, limit, offset int) ([]fleetstatus.FleetStatus, int64, error) {
|
|
rows := make([]fleetstatus.FleetStatus, 0)
|
|
var total int64
|
|
base := r.db.WithContext(ctx).
|
|
Model(&fleetstatus.FleetStatus{}).
|
|
Where("deleted_at IS NULL")
|
|
if strings.TrimSpace(filter) != "" {
|
|
like := "%" + strings.ToLower(strings.TrimSpace(filter)) + "%"
|
|
base = base.Where("LOWER(HEX(id)) LIKE ? OR LOWER(HEX(helicopter_id)) LIKE ?", like, like)
|
|
}
|
|
query := base
|
|
if strings.TrimSpace(sort) != "" {
|
|
query = query.Order(sort)
|
|
} else {
|
|
query = query.Order("created_at DESC")
|
|
}
|
|
if err := base.Count(&total).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
if limit > 0 {
|
|
query = query.Limit(limit).Offset(offset)
|
|
}
|
|
if err := query.Preload("Helicopter").
|
|
Preload("MaintenanceSchedules").
|
|
Preload("Files").
|
|
Preload("Files.Attachment").
|
|
Preload("Files.Attachment.File").
|
|
Find(&rows).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
return rows, total, nil
|
|
}
|
|
|
|
func (r *FleetStatusRepository) MarkServiced(ctx context.Context, id []byte, servicedAt time.Time, actorID []byte) error {
|
|
return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
|
var row fleetstatus.FleetStatus
|
|
if err := tx.Preload("Helicopter").
|
|
Preload("MaintenanceSchedules").
|
|
Where("id = ? AND deleted_at IS NULL", id).
|
|
First(&row).Error; err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(row.MaintenanceSchedules) > 0 {
|
|
logs := make([]fleetstatus.FleetStatusServiceLog, 0, len(row.MaintenanceSchedules))
|
|
for i := range row.MaintenanceSchedules {
|
|
item := row.MaintenanceSchedules[i]
|
|
logs = append(logs, fleetstatus.FleetStatusServiceLog{
|
|
FleetStatusID: row.ID,
|
|
HelicopterID: row.HelicopterID,
|
|
InspectionType: item.InspectionType,
|
|
Type: item.Type,
|
|
Due: item.Due,
|
|
Ext: item.Ext,
|
|
ServicedAt: servicedAt,
|
|
CreatedBy: actorID,
|
|
})
|
|
}
|
|
if err := tx.Create(&logs).Error; err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if err := tx.Where("fleet_status_id = ?", row.ID).Delete(&fleetstatus.MaintenanceSchedule{}).Error; err != nil {
|
|
return err
|
|
}
|
|
|
|
return tx.Model(&fleetstatus.FleetStatus{}).
|
|
Where("id = ? AND deleted_at IS NULL", row.ID).
|
|
Updates(map[string]any{
|
|
"status": fleetstatus.StatusServiced,
|
|
"serviced_at": servicedAt,
|
|
"updated_by": actorID,
|
|
}).
|
|
Error
|
|
})
|
|
}
|
|
|
|
func (r *FleetStatusRepository) LatestByHelicopterIDs(ctx context.Context, helicopterIDs [][]byte) (map[string]*fleetstatus.FleetStatus, error) {
|
|
out := make(map[string]*fleetstatus.FleetStatus)
|
|
|
|
filtered := make([][]byte, 0, len(helicopterIDs))
|
|
seen := make(map[string]struct{}, len(helicopterIDs))
|
|
for _, id := range helicopterIDs {
|
|
if len(id) != 16 {
|
|
continue
|
|
}
|
|
key := string(id)
|
|
if _, ok := seen[key]; ok {
|
|
continue
|
|
}
|
|
seen[key] = struct{}{}
|
|
filtered = append(filtered, append([]byte(nil), id...))
|
|
}
|
|
if len(filtered) == 0 {
|
|
return out, nil
|
|
}
|
|
|
|
rows := make([]fleetstatus.FleetStatus, 0)
|
|
// Ordered newest-first so the first row seen per helicopter is its latest.
|
|
if err := r.db.WithContext(ctx).
|
|
Where("deleted_at IS NULL").
|
|
Where("helicopter_id IN ?", filtered).
|
|
Order("created_at DESC, id DESC").
|
|
Preload("Helicopter").
|
|
Preload("MaintenanceSchedules").
|
|
Preload("Files").
|
|
Preload("Files.Attachment").
|
|
Preload("Files.Attachment.File").
|
|
Find(&rows).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
for i := range rows {
|
|
key := string(rows[i].HelicopterID)
|
|
if _, ok := out[key]; ok {
|
|
continue
|
|
}
|
|
row := rows[i]
|
|
out[key] = &row
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
func (r *FleetStatusRepository) ListServiceHistoryByHelicopterID(ctx context.Context, helicopterID []byte, limit, offset int) ([]fleetstatus.FleetStatusServiceLog, int64, error) {
|
|
rows := make([]fleetstatus.FleetStatusServiceLog, 0)
|
|
var total int64
|
|
|
|
base := r.db.WithContext(ctx).
|
|
Model(&fleetstatus.FleetStatusServiceLog{}).
|
|
Where("helicopter_id = ?", helicopterID)
|
|
if err := base.Count(&total).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
query := base.Order("serviced_at DESC, created_at DESC")
|
|
if limit > 0 {
|
|
query = query.Limit(limit).Offset(offset)
|
|
}
|
|
if err := query.Preload("Helicopter").Find(&rows).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
return rows, total, nil
|
|
}
|
|
|
|
func (r *FleetStatusRepository) HelicopterIDsWithFleetStatus(ctx context.Context) ([][]byte, error) {
|
|
type rowT struct {
|
|
HelicopterID []byte `gorm:"column:helicopter_id"`
|
|
}
|
|
rows := make([]rowT, 0)
|
|
err := r.db.WithContext(ctx).
|
|
Table("fleet_statuses").
|
|
Select("DISTINCT helicopter_id").
|
|
Where("deleted_at IS NULL").
|
|
Scan(&rows).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
out := make([][]byte, 0, len(rows))
|
|
for i := range rows {
|
|
if len(rows[i].HelicopterID) == 16 {
|
|
out = append(out, rows[i].HelicopterID)
|
|
}
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
func (r *FleetStatusRepository) HelicopterIDByMissionID(ctx context.Context, missionID []byte) ([]byte, error) {
|
|
if len(missionID) != 16 {
|
|
return nil, nil
|
|
}
|
|
var out struct {
|
|
HelicopterID []byte `gorm:"column:helicopter_id"`
|
|
}
|
|
err := r.db.WithContext(ctx).
|
|
Table("missions m").
|
|
Select("ra.helicopter_id AS helicopter_id").
|
|
Joins("JOIN flights f ON f.id = m.flight_id AND f.deleted_at IS NULL").
|
|
Joins("JOIN takeover_acs ta ON ta.id = f.takeover_ac_id AND ta.deleted_at IS NULL").
|
|
Joins("JOIN reserve_acs ra ON ra.id = ta.reserve_ac_id AND ra.deleted_at IS NULL").
|
|
Where("m.id = ? AND m.deleted_at IS NULL", missionID).
|
|
Limit(1).
|
|
Scan(&out).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return out.HelicopterID, nil
|
|
}
|
|
|