material_manage_system/internal/repository/outbound.go
2026-09-21 14:13:30 +08:00

250 lines
6.9 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package repository
import (
"database/sql"
"time"
"github.com/wmms/wmms/internal/model"
"github.com/wmms/wmms/pkg/database"
)
type OutboundRepo struct{}
func NewOutboundRepo() *OutboundRepo {
return &OutboundRepo{}
}
func (r *OutboundRepo) Create(order *model.OutboundOrder) error {
return r.CreateTx(nil, order)
}
func (r *OutboundRepo) CreateTx(tx *sql.Tx, order *model.OutboundOrder) error {
shouldCommit := false
if tx == nil {
var err error
tx, err = database.DB.Begin()
if err != nil {
return err
}
shouldCommit = true
}
if shouldCommit {
defer tx.Rollback()
}
query := `INSERT INTO outbound_orders (outbound_date, operator, handler, receiver, remark) VALUES (?, ?, ?, ?, ?)`
result, err := tx.Exec(query, order.OutboundDate, order.Operator, order.Handler, order.Receiver, order.Remark)
if err != nil {
return err
}
orderID, err := result.LastInsertId()
if err != nil {
return err
}
order.ID = orderID
order.OutboundNo = model.OrderNo("OUT", orderID)
if _, err = tx.Exec(`UPDATE outbound_orders SET outbound_no = ? WHERE id = ?`, order.OutboundNo, orderID); err != nil {
return err
}
for i := range order.Items {
item := &order.Items[i]
item.OutboundOrderID = orderID
query := `INSERT INTO outbound_items (outbound_order_id, material_id, quantity) VALUES (?, ?, ?)`
result, err := tx.Exec(query, orderID, item.MaterialID, item.Quantity)
if err != nil {
return err
}
itemID, err := result.LastInsertId()
if err != nil {
return err
}
item.ID = itemID
}
if shouldCommit {
return tx.Commit()
}
return nil
}
func (r *OutboundRepo) GetByID(id int64) (*model.OutboundOrder, error) {
order := &model.OutboundOrder{}
query := `SELECT id, COALESCE(outbound_no, CONCAT('OUT-', LPAD(id, 8, '0'))), COALESCE(operator, ''), outbound_date, handler, receiver, COALESCE(remark, ''), created_at, updated_at FROM outbound_orders WHERE id = ?`
err := database.DB.QueryRow(query, id).Scan(&order.ID, &order.OutboundNo, &order.Operator, &order.OutboundDate, &order.Handler, &order.Receiver, &order.Remark, &order.CreatedAt, &order.UpdatedAt)
if err != nil {
return nil, err
}
itemsQuery := `SELECT oi.id, oi.outbound_order_id, oi.material_id, oi.quantity, m.material_code, m.name, m.status
FROM outbound_items oi
JOIN materials m ON oi.material_id = m.id
WHERE oi.outbound_order_id = ?`
rows, err := database.DB.Query(itemsQuery, id)
if err != nil {
return nil, err
}
defer rows.Close()
for rows.Next() {
var item model.OutboundItem
err := rows.Scan(&item.ID, &item.OutboundOrderID, &item.MaterialID, &item.Quantity, &item.MaterialCode, &item.MaterialName, &item.MaterialStatus)
if err != nil {
return nil, err
}
order.Items = append(order.Items, item)
}
// 状态不落库:outbound_orders 没有 status 列,统一在这里给出。引入状态机时改为真实读写。
order.Status = "completed"
return order, nil
}
func (r *OutboundRepo) List(search string, limit, offset int) ([]model.OutboundOrder, int64, error) {
countQuery := `SELECT COUNT(*) FROM outbound_orders WHERE 1=1`
var countArgs []interface{}
if search != "" {
countQuery += ` AND (handler LIKE ? OR receiver LIKE ?)`
searchPattern := "%" + search + "%"
countArgs = append(countArgs, searchPattern, searchPattern)
}
var total int64
err := database.DB.QueryRow(countQuery, countArgs...).Scan(&total)
if err != nil {
return nil, 0, err
}
query := `SELECT id, COALESCE(outbound_no, CONCAT('OUT-', LPAD(id, 8, '0'))), COALESCE(operator, ''), outbound_date, handler, receiver, COALESCE(remark, ''), created_at, updated_at FROM outbound_orders WHERE 1=1`
var args []interface{}
if search != "" {
query += ` AND (handler LIKE ? OR receiver LIKE ?)`
searchPattern := "%" + search + "%"
args = append(args, searchPattern, searchPattern)
}
query += ` ORDER BY id DESC LIMIT ? OFFSET ?`
args = append(args, limit, offset)
rows, err := database.DB.Query(query, args...)
if err != nil {
return nil, 0, err
}
defer rows.Close()
var orders []model.OutboundOrder
for rows.Next() {
var order model.OutboundOrder
err := rows.Scan(&order.ID, &order.OutboundNo, &order.Operator, &order.OutboundDate, &order.Handler, &order.Receiver, &order.Remark, &order.CreatedAt, &order.UpdatedAt)
if err != nil {
return nil, 0, err
}
// 同上:状态在查询层给出,列表里一并补上。
order.Status = "completed"
orders = append(orders, order)
}
return orders, total, nil
}
func (r *OutboundRepo) GetByMaterialID(materialID int64) ([]model.OutboundRecord, error) {
query := `SELECT oi.id, oi.outbound_order_id, oo.handler, oo.receiver, oi.quantity, oi.created_at
FROM outbound_items oi
JOIN outbound_orders oo ON oi.outbound_order_id = oo.id
WHERE oi.material_id = ?
ORDER BY oi.id DESC`
rows, err := database.DB.Query(query, materialID)
if err != nil {
return nil, err
}
defer rows.Close()
var records []model.OutboundRecord
for rows.Next() {
var rec model.OutboundRecord
err := rows.Scan(&rec.ID, &rec.OutboundID, &rec.Handler, &rec.Receiver, &rec.Quantity, &rec.CreatedAt)
if err != nil {
return nil, err
}
records = append(records, rec)
}
return records, nil
}
func (r *OutboundRepo) GetOutboundDate(id int64) (time.Time, error) {
var outboundDate time.Time
query := `SELECT outbound_date FROM outbound_orders WHERE id = ?`
err := database.DB.QueryRow(query, id).Scan(&outboundDate)
return outboundDate, err
}
func (r *OutboundRepo) Delete(id int64) error {
return r.DeleteTx(nil, id)
}
func (r *OutboundRepo) DeleteTx(tx *sql.Tx, id int64) error {
if tx == nil {
var err error
tx, err = database.DB.Begin()
if err != nil {
return err
}
defer tx.Rollback()
_, err = tx.Exec(`DELETE FROM outbound_orders WHERE id = ?`, id)
if err != nil {
return err
}
return tx.Commit()
}
_, err := tx.Exec(`DELETE FROM outbound_orders WHERE id = ?`, id)
return err
}
func (r *OutboundRepo) Update(id int64, req *model.UpdateOutboundRequest) error {
return r.UpdateTx(nil, id, req)
}
func (r *OutboundRepo) UpdateTx(tx *sql.Tx, id int64, req *model.UpdateOutboundRequest) error {
shouldCommit := false
if tx == nil {
var err error
tx, err = database.DB.Begin()
if err != nil {
return err
}
shouldCommit = true
}
if shouldCommit {
defer tx.Rollback()
}
// Update order basic fields
query := `UPDATE outbound_orders SET operator = ?, handler = ?, receiver = ?, remark = ? WHERE id = ?`
_, err := tx.Exec(query, req.Operator, req.Handler, req.Receiver, req.Remark, id)
if err != nil {
return err
}
// Delete old items
_, err = tx.Exec(`DELETE FROM outbound_items WHERE outbound_order_id = ?`, id)
if err != nil {
return err
}
// Insert new items
for i := range req.Items {
item := &req.Items[i]
query := `INSERT INTO outbound_items (outbound_order_id, material_id, quantity) VALUES (?, ?, ?)`
_, err = tx.Exec(query, id, item.MaterialID, item.Quantity)
if err != nil {
return err
}
}
if shouldCommit {
return tx.Commit()
}
return nil
}