package repository import ( "database/sql" "time" "github.com/wmms/wmms/internal/model" "github.com/wmms/wmms/pkg/database" ) type InboundRepo struct{} func NewInboundRepo() *InboundRepo { return &InboundRepo{} } func (r *InboundRepo) Create(order *model.InboundOrder) error { return r.CreateTx(nil, order) } func (r *InboundRepo) CreateTx(tx *sql.Tx, order *model.InboundOrder) 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 inbound_orders (inbound_date, handler, supplier) VALUES (?, ?, ?)` result, err := tx.Exec(query, order.InboundDate, order.Handler, order.Supplier) if err != nil { return err } orderID, err := result.LastInsertId() if err != nil { return err } order.ID = orderID for i := range order.Items { item := &order.Items[i] item.InboundOrderID = orderID query := `INSERT INTO inbound_items (inbound_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 *InboundRepo) GetByID(id int64) (*model.InboundOrder, error) { order := &model.InboundOrder{} query := `SELECT id, inbound_date, handler, supplier, created_at, updated_at FROM inbound_orders WHERE id = ?` err := database.DB.QueryRow(query, id).Scan(&order.ID, &order.InboundDate, &order.Handler, &order.Supplier, &order.CreatedAt, &order.UpdatedAt) if err != nil { return nil, err } itemsQuery := `SELECT ii.id, ii.inbound_order_id, ii.material_id, ii.quantity, m.material_code, m.name FROM inbound_items ii JOIN materials m ON ii.material_id = m.id WHERE ii.inbound_order_id = ?` rows, err := database.DB.Query(itemsQuery, id) if err != nil { return nil, err } defer rows.Close() for rows.Next() { var item model.InboundItem err := rows.Scan(&item.ID, &item.InboundOrderID, &item.MaterialID, &item.Quantity, &item.MaterialCode, &item.MaterialName) if err != nil { return nil, err } order.Items = append(order.Items, item) } order.Status = "completed" return order, nil } func (r *InboundRepo) List(search string, limit, offset int) ([]model.InboundOrder, int64, error) { countQuery := `SELECT COUNT(*) FROM inbound_orders WHERE 1=1` var countArgs []interface{} if search != "" { countQuery += ` AND (handler LIKE ? OR supplier 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, inbound_date, handler, supplier, created_at, updated_at FROM inbound_orders WHERE 1=1` var args []interface{} if search != "" { query += ` AND (handler LIKE ? OR supplier 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.InboundOrder for rows.Next() { var order model.InboundOrder err := rows.Scan(&order.ID, &order.InboundDate, &order.Handler, &order.Supplier, &order.CreatedAt, &order.UpdatedAt) if err != nil { return nil, 0, err } order.Status = "completed" orders = append(orders, order) } return orders, total, nil } func (r *InboundRepo) GetByMaterialID(materialID int64) ([]model.InboundRecord, error) { query := `SELECT ii.id, ii.inbound_order_id, io.handler, io.supplier, ii.quantity, ii.created_at FROM inbound_items ii JOIN inbound_orders io ON ii.inbound_order_id = io.id WHERE ii.material_id = ? ORDER BY ii.id DESC` rows, err := database.DB.Query(query, materialID) if err != nil { return nil, err } defer rows.Close() var records []model.InboundRecord for rows.Next() { var rec model.InboundRecord err := rows.Scan(&rec.ID, &rec.InboundID, &rec.Handler, &rec.Supplier, &rec.Quantity, &rec.CreatedAt) if err != nil { return nil, err } records = append(records, rec) } return records, nil } func (r *InboundRepo) GetInboundDate(id int64) (time.Time, error) { var inboundDate time.Time query := `SELECT inbound_date FROM inbound_orders WHERE id = ?` err := database.DB.QueryRow(query, id).Scan(&inboundDate) return inboundDate, err } func (r *InboundRepo) Delete(id int64) error { return r.DeleteTx(nil, id) } func (r *InboundRepo) 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 inbound_orders WHERE id = ?`, id) if err != nil { return err } return tx.Commit() } _, err := tx.Exec(`DELETE FROM inbound_orders WHERE id = ?`, id) return err } func (r *InboundRepo) Update(id int64, req *model.UpdateInboundRequest) error { return r.UpdateTx(nil, id, req) } func (r *InboundRepo) UpdateTx(tx *sql.Tx, id int64, req *model.UpdateInboundRequest) 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 inbound_orders SET handler = ?, supplier = ? WHERE id = ?` _, err := tx.Exec(query, req.Handler, req.Supplier, id) if err != nil { return err } // Delete old items _, err = tx.Exec(`DELETE FROM inbound_items WHERE inbound_order_id = ?`, id) if err != nil { return err } // Insert new items for i := range req.Items { item := &req.Items[i] query := `INSERT INTO inbound_items (inbound_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 }