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

103 lines
3.2 KiB
Go

package repository
import (
"context"
"database/sql"
"time"
)
type PlanSummary struct {
ID string `json:"id"`
PlanCode string `json:"plan_code"`
ProductName string `json:"product_name"`
FabricCode string `json:"fabric_code"`
Color string `json:"color"`
ColorCode string `json:"color_code"`
TargetQuantity float64 `json:"target_quantity"`
CompletedQuantity float64 `json:"completed_quantity"`
Status string `json:"status"`
Remark *string `json:"remark,omitempty"`
StartTime *time.Time `json:"start_time,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
FactoryID string `json:"factory_id"`
}
type PlanRepo struct {
db *sql.DB
}
func NewPlanRepo(db *sql.DB) *PlanRepo {
return &PlanRepo{db: db}
}
func (r *PlanRepo) ListByFactory(ctx context.Context, factoryCompanyID string) ([]PlanSummary, error) {
query := `
SELECT pp.id, pp.plan_code, pp.product_name, pp.fabric_code,
pp.color, pp.color_code, pp.target_quantity, pp.completed_quantity,
pp.status, pp.remark, pp.start_time, pp.created_at, pp.updated_at,
pf.factory_id
FROM ilm_production_plan pp
JOIN ilm_plan_factory pf ON pp.id = pf.plan_id
WHERE pf.factory_id = ? AND pf.factory_type = 'textile'
ORDER BY pp.created_at DESC`
rows, err := r.db.QueryContext(ctx, query, factoryCompanyID)
if err != nil {
return nil, err
}
defer rows.Close()
var plans []PlanSummary
for rows.Next() {
var p PlanSummary
if err := rows.Scan(
&p.ID, &p.PlanCode, &p.ProductName, &p.FabricCode,
&p.Color, &p.ColorCode, &p.TargetQuantity, &p.CompletedQuantity,
&p.Status, &p.Remark, &p.StartTime, &p.CreatedAt, &p.UpdatedAt,
&p.FactoryID,
); err != nil {
return nil, err
}
plans = append(plans, p)
}
return plans, rows.Err()
}
func (r *PlanRepo) GetByID(ctx context.Context, planID string) (*PlanSummary, error) {
query := `
SELECT pp.id, pp.plan_code, pp.product_name, pp.fabric_code,
pp.color, pp.color_code, pp.target_quantity, pp.completed_quantity,
pp.status, pp.remark, pp.start_time, pp.created_at, pp.updated_at,
COALESCE(pf.factory_id, '')
FROM ilm_production_plan pp
LEFT JOIN ilm_plan_factory pf ON pp.id = pf.plan_id AND pf.factory_type = 'textile'
WHERE pp.id = ?`
var p PlanSummary
err := r.db.QueryRowContext(ctx, query, planID).Scan(
&p.ID, &p.PlanCode, &p.ProductName, &p.FabricCode,
&p.Color, &p.ColorCode, &p.TargetQuantity, &p.CompletedQuantity,
&p.Status, &p.Remark, &p.StartTime, &p.CreatedAt, &p.UpdatedAt,
&p.FactoryID,
)
if err != nil {
return nil, err
}
return &p, nil
}
func (r *PlanRepo) CountByFactory(ctx context.Context, factoryCompanyID string) (total, active, completed int, err error) {
query := `
SELECT
COUNT(*),
SUM(CASE WHEN pp.status IN ('pending', 'in_progress') THEN 1 ELSE 0 END),
SUM(CASE WHEN pp.status = 'completed' THEN 1 ELSE 0 END)
FROM ilm_production_plan pp
JOIN ilm_plan_factory pf ON pp.id = pf.plan_id
WHERE pf.factory_id = ? AND pf.factory_type = 'textile'`
err = r.db.QueryRowContext(ctx, query, factoryCompanyID).Scan(&total, &active, &completed)
return
}