87 lines
2.5 KiB
Go
87 lines
2.5 KiB
Go
|
|
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
|
||
|
|
}
|