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,300 @@
package mysql
import (
"context"
"errors"
"strings"
"time"
"gorm.io/gorm"
flightinspection "wucher/internal/domain/flight_inspection"
"wucher/internal/domain/helicopter"
reserveac "wucher/internal/domain/reserve_ac"
"wucher/internal/shared/pkg/uuidv7"
shareddto "wucher/internal/transport/http/dto/shared"
)
type ReserveAcRepository struct {
db *gorm.DB
}
func NewReserveAcRepository(db *gorm.DB) *ReserveAcRepository {
return &ReserveAcRepository{db: db}
}
func (r *ReserveAcRepository) Create(ctx context.Context, row *reserveac.ReserveAc) error {
return r.db.WithContext(ctx).Create(row).Error
}
func (r *ReserveAcRepository) Update(ctx context.Context, row *reserveac.ReserveAc) error {
return r.db.WithContext(ctx).Save(row).Error
}
func (r *ReserveAcRepository) 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,
}
res := r.db.WithContext(ctx).
Model(&reserveac.ReserveAc{}).
Where("id = ? AND deleted_at IS NULL", id).
Updates(updates)
if res.Error != nil {
return res.Error
}
if res.RowsAffected == 0 {
return gorm.ErrRecordNotFound
}
return nil
}
func (r *ReserveAcRepository) GetByID(ctx context.Context, id []byte) (*reserveac.ReserveAc, error) {
var row reserveac.ReserveAc
err := r.db.WithContext(ctx).
Preload("Aircraft").
Preload("Inspection").
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 *ReserveAcRepository) GetActiveByInspectionID(ctx context.Context, inspectionID []byte) (*reserveac.ReserveAc, error) {
if len(inspectionID) != 16 {
return nil, nil
}
var row reserveac.ReserveAc
err := r.db.WithContext(ctx).
Preload("Aircraft").
Preload("Inspection").
Where("inspection_id = ? AND deleted_at IS NULL", inspectionID).
Limit(1).
Find(&row).Error
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, nil
}
if err != nil {
return nil, err
}
if len(row.ID) == 0 {
return nil, nil
}
return &row, nil
}
func (r *ReserveAcRepository) List(ctx context.Context, filter string, sort string, limit, offset int) ([]reserveac.ReserveAc, int64, error) {
rows := make([]reserveac.ReserveAc, 0)
var total int64
base := r.db.WithContext(ctx).Model(&reserveac.ReserveAc{}).Where("deleted_at IS NULL")
if strings.TrimSpace(filter) != "" {
like := "%" + strings.ToLower(strings.TrimSpace(filter)) + "%"
base = base.Where(
"LOWER(status) LIKE ? OR LOWER(HEX(id)) LIKE ? OR LOWER(HEX(helicopter_id)) LIKE ? OR LOWER(HEX(inspection_id)) LIKE ?",
like, like, like, like,
)
}
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 (r *ReserveAcRepository) AircraftExists(ctx context.Context, helicopterID []byte) (bool, error) {
if len(helicopterID) != 16 {
return false, nil
}
var total int64
err := r.db.WithContext(ctx).
Model(&helicopter.Helicopter{}).
Where("id = ?", helicopterID).
Count(&total).Error
return total > 0, err
}
func (r *ReserveAcRepository) FlightInspectionExists(ctx context.Context, inspectionID []byte) (bool, error) {
if len(inspectionID) != 16 {
return false, nil
}
var total int64
err := r.db.WithContext(ctx).
Model(&flightinspection.FlightInspection{}).
Where("id = ?", inspectionID).
Count(&total).Error
return total > 0, err
}
func (r *ReserveAcRepository) ExistsActiveByInspectionID(ctx context.Context, inspectionID []byte, excludeID []byte) (bool, error) {
if len(inspectionID) != 16 {
return false, nil
}
var total int64
q := r.db.WithContext(ctx).
Model(&reserveac.ReserveAc{}).
Where("inspection_id = ? AND deleted_at IS NULL", inspectionID)
if len(excludeID) == 16 {
q = q.Where("id <> ?", excludeID)
}
if err := q.Count(&total).Error; err != nil {
return false, err
}
return total > 0, nil
}
func (r *ReserveAcRepository) GetLastDailyInspectionByHelicopterID(ctx context.Context, helicopterID []byte) (*shareddto.LastDailyInspection, error) {
if len(helicopterID) != 16 {
return nil, nil
}
type row struct {
ID []byte `gorm:"column:id"`
Name string `gorm:"column:name"`
ShortName string `gorm:"column:short_name"`
At time.Time `gorm:"column:inspected_at"`
}
var out row
err := r.db.WithContext(ctx).
Table("reserve_acs ra").
Select(`
fi.id AS id,
TRIM(CONCAT(COALESCE(u.first_name, ''), ' ', COALESCE(u.last_name, ''))) AS name,
COALESCE(NULLIF(pp.short_name, ''), NULLIF(tp.short_name, ''), '') AS short_name,
COALESCE(afi.updated_at, fpc.updated_at, bfi.updated_at) AS inspected_at`).
Joins("JOIN flight_inspections fi ON fi.id = ra.inspection_id").
Joins("LEFT JOIN before_flight_inspections bfi ON bfi.flight_inspection_id = fi.id").
Joins("LEFT JOIN flight_prep_checks fpc ON fpc.flight_inspection_id = fi.id").
Joins("LEFT JOIN after_flight_inspections afi ON afi.flight_inspection_id = fi.id").
Joins(`JOIN users u ON u.id = CASE
WHEN afi.updated_at IS NOT NULL THEN afi.updated_by
WHEN fpc.updated_at IS NOT NULL THEN fpc.updated_by
WHEN bfi.updated_at IS NOT NULL THEN bfi.updated_by
ELSE NULL
END`).
Joins("LEFT JOIN pilot_profiles pp ON pp.user_id = u.id").
Joins("LEFT JOIN technician_profiles tp ON tp.user_id = u.id").
Where("ra.helicopter_id = ? AND ra.deleted_at IS NULL", helicopterID).
Where("COALESCE(afi.updated_at, fpc.updated_at, bfi.updated_at) IS NOT NULL").
Order("fi.inspection_date DESC").
Order("COALESCE(afi.updated_at, fpc.updated_at, bfi.updated_at) DESC").
Limit(1).
Take(&out).Error
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, nil
}
if err != nil {
return nil, err
}
return &shareddto.LastDailyInspection{
ID: out.ID,
Name: strings.TrimSpace(out.Name),
ShortName: strings.TrimSpace(out.ShortName),
At: out.At.UTC(),
}, nil
}
func (r *ReserveAcRepository) GetLastDailyInspectionSummaryByHelicopterID(ctx context.Context, helicopterID []byte) (*shareddto.LastDailyInspectionSummary, error) {
if len(helicopterID) != 16 {
return nil, nil
}
type row struct {
InspectionID []byte `gorm:"column:inspection_id"`
InspectorID []byte `gorm:"column:inspector_id"`
InspectorName string `gorm:"column:inspector_name"`
InspectorLicenseNo string `gorm:"column:inspector_license_no"`
BaseID []byte `gorm:"column:base_id"`
BaseName string `gorm:"column:base_name"`
BaseAbbreviation string `gorm:"column:base_abbreviation"`
BaseType string `gorm:"column:base_type"`
InspectedAt time.Time `gorm:"column:inspected_at"`
CompletedCount int `gorm:"column:completed_count"`
TotalCount int `gorm:"column:total_count"`
}
var out row
err := r.db.WithContext(ctx).
Table("reserve_acs ra").
Select(`
ra.inspection_id AS inspection_id,
COALESCE(u.id, ra.updated_by) AS inspector_id,
COALESCE(
NULLIF(TRIM(CONCAT(COALESCE(u.first_name, ''), ' ', COALESCE(u.last_name, ''))), ''),
NULLIF(TRIM(u.username), ''),
NULLIF(TRIM(u.email), ''),
''
) AS inspector_name,
COALESCE(NULLIF(pp.license_no, ''), NULLIF(tp.license_no, ''), '') AS inspector_license_no,
ra.base_id AS base_id,
COALESCE(TRIM(b.base), '') AS base_name,
COALESCE(TRIM(b.base_abbreviation), '') AS base_abbreviation,
COALESCE(NULLIF(LOWER(bc.key), ''), 'base') AS base_type,
COALESCE(afi.updated_at, fpc.updated_at, bfi.updated_at, ra.updated_at) AS inspected_at,
(
SELECT COUNT(*)
FROM flight_inspection_file_checklists fic
WHERE fic.flight_inspection_id = fi.id
) AS total_count,
(
SELECT COUNT(*)
FROM flight_inspection_file_checklists fic
WHERE fic.flight_inspection_id = fi.id AND fic.is_done = 1
) AS completed_count
`).
Joins("JOIN flight_inspections fi ON fi.id = ra.inspection_id").
Joins("LEFT JOIN before_flight_inspections bfi ON bfi.flight_inspection_id = fi.id").
Joins("LEFT JOIN flight_prep_checks fpc ON fpc.flight_inspection_id = fi.id").
Joins("LEFT JOIN after_flight_inspections afi ON afi.flight_inspection_id = fi.id").
Joins(`LEFT JOIN users u ON u.id = CASE
WHEN afi.updated_at IS NOT NULL THEN afi.updated_by
WHEN fpc.updated_at IS NOT NULL THEN fpc.updated_by
WHEN bfi.updated_at IS NOT NULL THEN bfi.updated_by
ELSE ra.updated_by
END`).
Joins("LEFT JOIN pilot_profiles pp ON pp.user_id = u.id").
Joins("LEFT JOIN technician_profiles tp ON tp.user_id = u.id").
Joins("LEFT JOIN bases b ON b.id = ra.base_id AND b.deleted_at IS NULL").
Joins("LEFT JOIN base_categories bc ON bc.id = b.base_category_id").
Where("ra.helicopter_id = ? AND ra.deleted_at IS NULL", helicopterID).
Where("COALESCE(afi.updated_at, fpc.updated_at, bfi.updated_at, ra.updated_at) IS NOT NULL").
Order("fi.inspection_date DESC, COALESCE(afi.updated_at, fpc.updated_at, bfi.updated_at, ra.updated_at) DESC").
Limit(1).
Take(&out).Error
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, nil
}
if err != nil {
return nil, err
}
inspectionID, _ := uuidv7.BytesToString(out.InspectionID)
inspectorID, _ := uuidv7.BytesToString(out.InspectorID)
baseID, _ := uuidv7.BytesToString(out.BaseID)
return &shareddto.LastDailyInspectionSummary{
InspectionID: inspectionID,
Status: "inspected_cleared",
InspectorID: inspectorID,
InspectorName: strings.TrimSpace(out.InspectorName),
InspectorLicenseNo: strings.TrimSpace(out.InspectorLicenseNo),
BaseID: baseID,
BaseName: strings.TrimSpace(out.BaseName),
BaseAbbreviation: strings.TrimSpace(out.BaseAbbreviation),
BaseType: strings.TrimSpace(out.BaseType),
InspectedAt: out.InspectedAt.UTC(),
InspectionFilesChecklistCompleted: out.CompletedCount,
InspectionFilesChecklistTotal: out.TotalCount,
}, nil
}