package mysql import ( "context" "errors" "strings" "time" "gorm.io/gorm" "wucher/internal/domain/health_insurance_companies" "wucher/internal/shared/pkg/sortkey" ) type HealthInsuranceCompaniesRepository struct { db *gorm.DB } func NewHealthInsuranceCompaniesRepository(db *gorm.DB) *HealthInsuranceCompaniesRepository { return &HealthInsuranceCompaniesRepository{db: db} } func (r *HealthInsuranceCompaniesRepository) Create(ctx context.Context, row *health_insurance_companies.HealthInsuranceCompany) error { requestedIsActive := row.IsActive db := r.db.WithContext(ctx) if err := db.Create(row).Error; err != nil { return err } return db.Model(&health_insurance_companies.HealthInsuranceCompany{}).Where("id = ?", row.ID).UpdateColumn("is_active", requestedIsActive).Error } func (r *HealthInsuranceCompaniesRepository) Update(ctx context.Context, row *health_insurance_companies.HealthInsuranceCompany) error { return r.db.WithContext(ctx).Save(row).Error } func (r *HealthInsuranceCompaniesRepository) Delete(ctx context.Context, id []byte, deletedBy []byte) error { if err := ensureNoReferenceBeforeDelete(ctx, r.db, "health_insurance_companies", id); err != nil { return err } now := time.Now().UTC() updates := map[string]any{ "deleted_at": now, "deleted_by": deletedBy, "updated_by": deletedBy, } return mapDeleteConstraintError(r.db.WithContext(ctx). Model(&health_insurance_companies.HealthInsuranceCompany{}). Where("id = ? AND deleted_at IS NULL", id). Updates(updates).Error) } func (r *HealthInsuranceCompaniesRepository) GetByID(ctx context.Context, id []byte) (*health_insurance_companies.HealthInsuranceCompany, error) { var row health_insurance_companies.HealthInsuranceCompany err := r.db.WithContext(ctx).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 *HealthInsuranceCompaniesRepository) List(ctx context.Context, filter, sort string, limit, offset int) ([]health_insurance_companies.HealthInsuranceCompany, int64, error) { var rows []health_insurance_companies.HealthInsuranceCompany var total int64 base := r.db.WithContext(ctx).Model(&health_insurance_companies.HealthInsuranceCompany{}).Where("deleted_at IS NULL") if filter != "" { like := "%" + filter + "%" base = base.Where("name LIKE ? OR state LIKE ? OR address LIKE ? OR mobile_number LIKE ? OR email LIKE ? OR note LIKE ?", like, like, like, like, like, like) } query := base if sort != "" { query = query.Order(sort) } else { for _, clause := range sortkey.ActivePositiveSortClauses("health_insurance_companies", "is_active", "sortkey", "name", false) { query = query.Order(clause) } } 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 *HealthInsuranceCompaniesRepository) ResolveStateDetails(ctx context.Context, stateNames []string) (map[string]health_insurance_companies.StateDetail, error) { normalized := make([]string, 0, len(stateNames)) seen := map[string]struct{}{} for _, stateName := range stateNames { key := strings.ToLower(strings.TrimSpace(stateName)) if key == "" { continue } if _, ok := seen[key]; ok { continue } seen[key] = struct{}{} normalized = append(normalized, key) } if len(normalized) == 0 { return map[string]health_insurance_companies.StateDetail{}, nil } type row struct { LandID string `gorm:"column:land_id"` FederalStateID string `gorm:"column:federal_state_id"` FederalState string `gorm:"column:federal_state"` LandName string `gorm:"column:land_name"` LandISOCode string `gorm:"column:land_iso_code"` StateKey string `gorm:"column:state_key"` } var rows []row err := r.db.WithContext(ctx). Table("federal_states"). Select("LOWER(TRIM(federal_states.name)) AS state_key, LOWER(HEX(lands.id)) AS land_id, LOWER(HEX(federal_states.id)) AS federal_state_id, federal_states.name AS federal_state, lands.name AS land_name, lands.land_iso_code AS land_iso_code"). Joins("JOIN lands ON lands.id = federal_states.land_id AND lands.deleted_at IS NULL"). Where("federal_states.deleted_at IS NULL"). Where("LOWER(TRIM(federal_states.name)) IN ?", normalized). Scan(&rows).Error if err != nil { return nil, err } out := make(map[string]health_insurance_companies.StateDetail, len(rows)) for i := range rows { if rows[i].StateKey == "" { continue } if _, exists := out[rows[i].StateKey]; exists { continue } out[rows[i].StateKey] = health_insurance_companies.StateDetail{ LandID: rows[i].LandID, FederalStateID: rows[i].FederalStateID, FederalState: rows[i].FederalState, LandName: rows[i].LandName, LandISOCode: rows[i].LandISOCode, } } return out, nil } func (r *HealthInsuranceCompaniesRepository) ResolveLandDetails(ctx context.Context, landIDs []string) (map[string]health_insurance_companies.LandDetail, error) { normalized := make([]string, 0, len(landIDs)) seen := map[string]struct{}{} for _, landID := range landIDs { key := normalizeLandKey(landID) if key == "" { continue } if _, ok := seen[key]; ok { continue } seen[key] = struct{}{} normalized = append(normalized, key) } if len(normalized) == 0 { return map[string]health_insurance_companies.LandDetail{}, nil } type row struct { LandID string `gorm:"column:land_id"` LandName string `gorm:"column:land_name"` LandISOCode string `gorm:"column:land_iso_code"` } var rows []row err := r.db.WithContext(ctx). Table("lands"). Select("LOWER(HEX(lands.id)) AS land_id, lands.name AS land_name, lands.land_iso_code AS land_iso_code"). Where("lands.deleted_at IS NULL"). Where("LOWER(HEX(lands.id)) IN ?", normalized). Scan(&rows).Error if err != nil { return nil, err } out := make(map[string]health_insurance_companies.LandDetail, len(rows)) for i := range rows { if rows[i].LandID == "" { continue } if _, exists := out[rows[i].LandID]; exists { continue } out[rows[i].LandID] = health_insurance_companies.LandDetail{ LandID: rows[i].LandID, LandName: rows[i].LandName, LandISOCode: rows[i].LandISOCode, } } return out, nil } func normalizeLandKey(raw string) string { key := strings.ToLower(strings.TrimSpace(raw)) key = strings.ReplaceAll(key, "-", "") return key }