init push

This commit is contained in:
2026-07-16 22:16:45 +07:00
commit 8b068bdb10
1021 changed files with 332816 additions and 0 deletions

View File

@@ -0,0 +1,278 @@
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
}