package repository import ( "context" "database/sql" "fmt" "time" ) type PaymentWithDetails struct { ID string `json:"id"` WashingPlanID string `json:"washing_plan_id"` CompanyID string `json:"company_id"` Amount float64 `json:"amount"` Status string `json:"status"` Notes *string `json:"notes,omitempty"` PaidAt *time.Time `json:"paid_at,omitempty"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` PlanCode string `json:"plan_code"` FromCompanyName string `json:"from_company_name"` } type PaymentRepo struct { db *sql.DB } func NewPaymentRepo(db *sql.DB) *PaymentRepo { return &PaymentRepo{db: db} } func (r *PaymentRepo) ListByCompany(ctx context.Context, companyID string) ([]PaymentWithDetails, error) { query := `SELECT wpy.id, wpy.washing_plan_id, wpy.company_id, wpy.amount, wpy.status, wpy.notes, wpy.paid_at, wpy.created_at, wpy.updated_at, COALESCE(wp.plan_code, '') AS plan_code, COALESCE(c.name, '') AS from_company_name FROM ilm_washing_payment wpy LEFT JOIN ilm_washing_plan wp ON wpy.washing_plan_id = wp.id LEFT JOIN ilm_company c ON wp.company_id = c.id WHERE wpy.company_id = ? ORDER BY wpy.created_at DESC` rows, err := r.db.QueryContext(ctx, query, companyID) if err != nil { return nil, fmt.Errorf("list payments: %w", err) } defer rows.Close() var payments []PaymentWithDetails for rows.Next() { var p PaymentWithDetails if err := rows.Scan( &p.ID, &p.WashingPlanID, &p.CompanyID, &p.Amount, &p.Status, &p.Notes, &p.PaidAt, &p.CreatedAt, &p.UpdatedAt, &p.PlanCode, &p.FromCompanyName, ); err != nil { return nil, fmt.Errorf("scan payment: %w", err) } payments = append(payments, p) } return payments, nil } func (r *PaymentRepo) Confirm(ctx context.Context, paymentID string) error { query := `UPDATE ilm_washing_payment SET status = 'confirmed', paid_at = NOW(), updated_at = NOW() WHERE id = ?` result, err := r.db.ExecContext(ctx, query, paymentID) if err != nil { return fmt.Errorf("confirm payment: %w", err) } affected, err := result.RowsAffected() if err != nil { return fmt.Errorf("rows affected: %w", err) } if affected == 0 { return fmt.Errorf("payment not found") } return nil } func (r *PaymentRepo) CountPending(ctx context.Context, companyID string) (int, error) { var count int err := r.db.QueryRowContext(ctx, `SELECT COUNT(*) FROM ilm_washing_payment WHERE company_id = ? AND status = 'pending'`, companyID, ).Scan(&count) if err != nil { return 0, fmt.Errorf("count pending payments: %w", err) } return count, nil }