265 lines
8.4 KiB
Go
Raw Normal View History

package repository
import (
"context"
"database/sql"
"fmt"
"time"
"github.com/google/uuid"
"github.com/muyuqingfeng/iloom/purchaser-service/internal/model"
)
type ProductRepo struct {
db *sql.DB
}
func NewProductRepo(db *sql.DB) *ProductRepo {
return &ProductRepo{db: db}
}
func (r *ProductRepo) List(ctx context.Context, companyID string) ([]model.Product, error) {
query := `SELECT id, company_id, product_name, fabric_code, color, color_code,
weight, warp_weight, weft_weight, total_weight, yarn_usage_per_meter,
production_price, total_stock, raw_fabric_meters, raw_fabric_rolls,
image_url, yarn_types, yarn_ratios, created_at, updated_at
FROM products WHERE company_id = ? ORDER BY created_at DESC`
rows, err := r.db.QueryContext(ctx, query, companyID)
if err != nil {
return nil, fmt.Errorf("list products: %w", err)
}
defer rows.Close()
var products []model.Product
for rows.Next() {
var p model.Product
if err := rows.Scan(
&p.ID, &p.CompanyID, &p.ProductName, &p.FabricCode, &p.Color, &p.ColorCode,
&p.Weight, &p.WarpWeight, &p.WeftWeight, &p.TotalWeight,
&p.YarnUsagePerMeter, &p.ProductionPrice,
&p.TotalStock, &p.RawFabricMeters, &p.RawFabricRolls,
&p.ImageURL, &p.YarnTypes, &p.YarnRatios,
&p.CreatedAt, &p.UpdatedAt,
); err != nil {
return nil, fmt.Errorf("scan product: %w", err)
}
products = append(products, p)
}
return products, nil
}
func (r *ProductRepo) Create(ctx context.Context, p *model.Product) error {
query := `INSERT INTO products
(id, company_id, product_name, fabric_code, color, color_code,
weight, warp_weight, weft_weight, total_weight, yarn_usage_per_meter,
production_price, total_stock, raw_fabric_meters, raw_fabric_rolls,
image_url, yarn_types, yarn_ratios, created_at, updated_at)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`
_, err := r.db.ExecContext(ctx, query,
p.ID, p.CompanyID, p.ProductName, p.FabricCode, p.Color, p.ColorCode,
p.Weight, p.WarpWeight, p.WeftWeight, p.TotalWeight,
p.YarnUsagePerMeter, p.ProductionPrice,
p.TotalStock, p.RawFabricMeters, p.RawFabricRolls,
p.ImageURL, p.YarnTypes, p.YarnRatios,
p.CreatedAt, p.UpdatedAt,
)
if err != nil {
return fmt.Errorf("insert product: %w", err)
}
return nil
}
func (r *ProductRepo) Update(ctx context.Context, p *model.Product) error {
query := `UPDATE products SET
product_name = ?, fabric_code = ?, color = ?, color_code = ?,
weight = ?, warp_weight = ?, weft_weight = ?, total_weight = ?,
yarn_usage_per_meter = ?, production_price = ?,
image_url = ?, yarn_types = ?, yarn_ratios = ?, updated_at = ?
WHERE id = ?`
_, err := r.db.ExecContext(ctx, query,
p.ProductName, p.FabricCode, p.Color, p.ColorCode,
p.Weight, p.WarpWeight, p.WeftWeight, p.TotalWeight,
p.YarnUsagePerMeter, p.ProductionPrice,
p.ImageURL, p.YarnTypes, p.YarnRatios, time.Now(),
p.ID,
)
if err != nil {
return fmt.Errorf("update product: %w", err)
}
return nil
}
func (r *ProductRepo) Delete(ctx context.Context, id, companyID string) error {
_, err := r.db.ExecContext(ctx,
`DELETE FROM products WHERE id = ? AND company_id = ?`,
id, companyID,
)
if err != nil {
return fmt.Errorf("delete product: %w", err)
}
return nil
}
func (r *ProductRepo) Inbound(ctx context.Context, tx *sql.Tx, rec *model.ProductInventoryRecord) error {
query := `INSERT INTO ilm_product_inventory
(id, product_id, batch_no, rolls, meters, notes, operator_id, company_id, warehouse_id, created_at)
VALUES (?,?,?,?,?,?,?,?,?,?)`
_, err := tx.ExecContext(ctx, query,
rec.ID, rec.ProductID, rec.BatchNo, rec.Rolls, rec.Meters,
rec.Notes, rec.OperatorID, rec.CompanyID, rec.WarehouseID, rec.CreatedAt,
)
if err != nil {
return fmt.Errorf("insert inbound record: %w", err)
}
return nil
}
func (r *ProductRepo) UpdateStock(ctx context.Context, tx *sql.Tx, productID string, deltaMeters float64, deltaRolls int) error {
query := `UPDATE products SET
total_stock = total_stock + ?,
raw_fabric_meters = raw_fabric_meters + ?,
raw_fabric_rolls = raw_fabric_rolls + ?,
updated_at = ?
WHERE id = ?`
_, err := tx.ExecContext(ctx, query, deltaMeters, deltaMeters, deltaRolls, time.Now(), productID)
if err != nil {
return fmt.Errorf("update stock: %w", err)
}
return nil
}
func (r *ProductRepo) Outbound(ctx context.Context, tx *sql.Tx, rec *model.ProductOutboundRecord) error {
query := `INSERT INTO ilm_product_outbound
(id, product_id, batch_no, rolls, meters, outbound_type, notes,
operator_id, company_id, recipient_company_id, recipient_company_name,
source_batch_id, washing_plan_id, created_at)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)`
_, err := tx.ExecContext(ctx, query,
rec.ID, rec.ProductID, rec.BatchNo, rec.Rolls, rec.Meters,
rec.OutboundType, rec.Notes,
rec.OperatorID, rec.CompanyID,
rec.RecipientCompanyID, rec.RecipientCompanyName,
rec.SourceBatchID, rec.WashingPlanID, rec.CreatedAt,
)
if err != nil {
return fmt.Errorf("insert outbound record: %w", err)
}
return nil
}
func (r *ProductRepo) Records(ctx context.Context, productID string) ([]model.ProductInventoryRecord, error) {
query := `SELECT id, product_id, batch_no, rolls, meters, notes,
operator_id, company_id, warehouse_id, created_at
FROM ilm_product_inventory
WHERE product_id = ? ORDER BY created_at DESC`
rows, err := r.db.QueryContext(ctx, query, productID)
if err != nil {
return nil, fmt.Errorf("list records: %w", err)
}
defer rows.Close()
var records []model.ProductInventoryRecord
for rows.Next() {
var rec model.ProductInventoryRecord
if err := rows.Scan(
&rec.ID, &rec.ProductID, &rec.BatchNo, &rec.Rolls, &rec.Meters,
&rec.Notes, &rec.OperatorID, &rec.CompanyID, &rec.WarehouseID, &rec.CreatedAt,
); err != nil {
return nil, fmt.Errorf("scan record: %w", err)
}
records = append(records, rec)
}
return records, nil
}
func (r *ProductRepo) UpdatePrice(ctx context.Context, tx *sql.Tx, productID string, newPrice float64) error {
_, err := tx.ExecContext(ctx,
`UPDATE products SET production_price = ?, updated_at = ? WHERE id = ?`,
newPrice, time.Now(), productID,
)
if err != nil {
return fmt.Errorf("update price: %w", err)
}
return nil
}
func (r *ProductRepo) GetPrice(ctx context.Context, productID string) (*float64, error) {
var price *float64
err := r.db.QueryRowContext(ctx,
`SELECT production_price FROM products WHERE id = ?`, productID,
).Scan(&price)
if err != nil {
return nil, fmt.Errorf("get price: %w", err)
}
return price, nil
}
func (r *ProductRepo) InsertPriceHistory(ctx context.Context, tx *sql.Tx, productID string, oldPrice *float64, newPrice float64, reason, changedBy string) error {
id := uuid.New().String()
var reasonPtr *string
if reason != "" {
reasonPtr = &reason
}
var changedByPtr *string
if changedBy != "" {
changedByPtr = &changedBy
}
_, err := tx.ExecContext(ctx,
`INSERT INTO ilm_product_price_history
(id, product_id, old_price, new_price, reason, changed_by, created_at)
VALUES (?,?,?,?,?,?,?)`,
id, productID, oldPrice, newPrice, reasonPtr, changedByPtr, time.Now(),
)
if err != nil {
return fmt.Errorf("insert price history: %w", err)
}
return nil
}
func (r *ProductRepo) PriceHistory(ctx context.Context, productID string) ([]model.ProductPriceHistory, error) {
query := `SELECT id, product_id, old_price, new_price, reason, changed_by, created_at
FROM ilm_product_price_history
WHERE product_id = ? ORDER BY created_at DESC`
rows, err := r.db.QueryContext(ctx, query, productID)
if err != nil {
return nil, fmt.Errorf("list price history: %w", err)
}
defer rows.Close()
var history []model.ProductPriceHistory
for rows.Next() {
var h model.ProductPriceHistory
if err := rows.Scan(
&h.ID, &h.ProductID, &h.OldPrice, &h.NewPrice,
&h.Reason, &h.ChangedBy, &h.CreatedAt,
); err != nil {
return nil, fmt.Errorf("scan price history: %w", err)
}
history = append(history, h)
}
return history, nil
}
func (r *ProductRepo) Count(ctx context.Context, companyID string) (int, error) {
var count int
err := r.db.QueryRowContext(ctx,
`SELECT COUNT(*) FROM products WHERE company_id = ?`, companyID,
).Scan(&count)
if err != nil {
return 0, fmt.Errorf("count products: %w", err)
}
return count, nil
}
func (r *ProductRepo) TotalStock(ctx context.Context, companyID string) (float64, error) {
var total float64
err := r.db.QueryRowContext(ctx,
`SELECT COALESCE(SUM(total_stock), 0) FROM products WHERE company_id = ?`, companyID,
).Scan(&total)
if err != nil {
return 0, fmt.Errorf("total stock: %w", err)
}
return total, nil
}