package repository import ( "context" "database/sql" "fmt" "github.com/muyuqingfeng/iloom/purchaser-service/internal/model" ) type APRepo struct { db *sql.DB } func NewAPRepo(db *sql.DB) *APRepo { return &APRepo{db: db} } func (r *APRepo) List(ctx context.Context, companyID string) ([]model.AccountsPayable, error) { query := `SELECT ap.id, ap.plan_id, ap.purchaser_id, ap.textile_factory_id, ap.price_per_meter, ap.total_quantity, ap.total_amount, ap.paid_quantity, ap.paid_amount, ap.unpaid_quantity, ap.unpaid_amount, ap.status, ap.created_at, ap.updated_at, COALESCE(pp.plan_code, '') as plan_code, COALESCE(c.name, '') as factory_name FROM ilm_accounts_payable ap LEFT JOIN ilm_production_plan pp ON pp.id = ap.plan_id LEFT JOIN ilm_company c ON c.id = ap.textile_factory_id WHERE ap.purchaser_id = ? ORDER BY ap.created_at DESC` rows, err := r.db.QueryContext(ctx, query, companyID) if err != nil { return nil, fmt.Errorf("list accounts payable: %w", err) } defer rows.Close() var list []model.AccountsPayable for rows.Next() { var ap model.AccountsPayable if err := rows.Scan( &ap.ID, &ap.PlanID, &ap.PurchaserID, &ap.TextileFactoryID, &ap.PricePerMeter, &ap.TotalQuantity, &ap.TotalAmount, &ap.PaidQuantity, &ap.PaidAmount, &ap.UnpaidQuantity, &ap.UnpaidAmount, &ap.Status, &ap.CreatedAt, &ap.UpdatedAt, &ap.PlanCode, &ap.FactoryName, ); err != nil { return nil, fmt.Errorf("scan accounts payable: %w", err) } list = append(list, ap) } return list, nil } func (r *APRepo) Pay(ctx context.Context, tx *sql.Tx, apID string, amount float64) error { query := `UPDATE ilm_accounts_payable SET paid_amount = paid_amount + ?, unpaid_amount = unpaid_amount - ?, status = CASE WHEN unpaid_amount - ? <= 0 THEN 'completed' ELSE status END, updated_at = NOW() WHERE id = ? AND unpaid_amount >= ?` result, err := tx.ExecContext(ctx, query, amount, amount, amount, apID, amount) if err != nil { return fmt.Errorf("pay: %w", err) } rowsAffected, err := result.RowsAffected() if err != nil { return fmt.Errorf("check rows affected: %w", err) } if rowsAffected == 0 { return fmt.Errorf("payment failed: insufficient unpaid amount or record not found") } return nil } func (r *APRepo) TotalUnpaid(ctx context.Context, companyID string) (float64, error) { var total float64 err := r.db.QueryRowContext(ctx, `SELECT COALESCE(SUM(unpaid_amount), 0) FROM ilm_accounts_payable WHERE purchaser_id = ?`, companyID, ).Scan(&total) if err != nil { return 0, fmt.Errorf("total unpaid: %w", err) } return total, nil }