Chever John 9c39c8cbd7
init: iloom WMS monorepo with K8s deployment manifests
Go workspace (go.work) with 5 microservices + shared library:
- gateway (8080), auth-service (8081), purchaser-service (8082)
- textile-service (8083), washing-service (8084)
- shared: proto definitions, common packages

Infrastructure: docker-compose for local dev, K8s manifests for
K3s cluster deployment (mysql/redis/etcd + traefik ingress).

Frontend (iloom-flatten) added as git submodule.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-14 11:33:31 +08:00

93 lines
2.6 KiB
Go

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
}