package model import ( "context" "fmt" "strings" "github.com/zeromicro/go-zero/core/stores/sqlx" ) var _ InvProductPanModel = (*customInvProductPanModel)(nil) // PanListItem is the aggregated view row for the pan-dimension panel. // Colors is aggregated from the bolts on this pan; spec is omitted (product-level only). type PanListItem struct { PanId string `db:"pan_id"` ProductId string `db:"product_id"` Name string `db:"name"` Position string `db:"position"` ProductName string `db:"product_name"` Colors string `db:"colors"` BoltCount int64 `db:"bolt_count"` TotalLengthM float64 `db:"total_length_m"` } type ( InvProductPanModel interface { invProductPanModel FindByProductId(ctx context.Context, productId string) ([]*InvProductPan, error) DeleteByProductId(ctx context.Context, productId string) error BulkReplace(ctx context.Context, productId, tenantId string, pans []*InvProductPan) error FindPanList(ctx context.Context, tenantId string, page, pageSize int64, productName, position string) ([]*PanListItem, int64, error) } customInvProductPanModel struct { *defaultInvProductPanModel } ) func NewInvProductPanModel(conn sqlx.SqlConn) InvProductPanModel { return &customInvProductPanModel{ defaultInvProductPanModel: newInvProductPanModel(conn), } } func (m *customInvProductPanModel) FindByProductId(ctx context.Context, productId string) ([]*InvProductPan, error) { var list []*InvProductPan query := fmt.Sprintf("SELECT %s FROM %s WHERE `product_id` = ? ORDER BY `sort_order`", invProductPanRows, m.table) err := m.conn.QueryRowsCtx(ctx, &list, query, productId) if err != nil { return nil, err } return list, nil } func (m *customInvProductPanModel) DeleteByProductId(ctx context.Context, productId string) error { query := fmt.Sprintf("DELETE FROM %s WHERE `product_id` = ?", m.table) _, err := m.conn.ExecCtx(ctx, query, productId) return err } func (m *customInvProductPanModel) FindPanList(ctx context.Context, tenantId string, page, pageSize int64, productName, position string) ([]*PanListItem, int64, error) { where := "WHERE pan.tenant_id = ? AND p.deleted_at IS NULL" args := []interface{}{tenantId} if productName != "" { where += " AND p.product_name LIKE ?" args = append(args, "%"+productName+"%") } if position != "" { where += " AND pan.position LIKE ?" args = append(args, "%"+position+"%") } countQuery := fmt.Sprintf(`SELECT COUNT(DISTINCT pan.pan_id) FROM %s pan JOIN inv_product p ON p.product_id = pan.product_id %s`, m.table, where) var total int64 if err := m.conn.QueryRowCtx(ctx, &total, countQuery, args...); err != nil { return nil, 0, err } query := fmt.Sprintf(`SELECT pan.pan_id, pan.product_id, pan.name, pan.position, p.product_name, COALESCE(GROUP_CONCAT(DISTINCT b.color ORDER BY b.color SEPARATOR ', '), '') AS colors, COUNT(b.bolt_id) AS bolt_count, COALESCE(SUM(b.length_m), 0) AS total_length_m FROM %s pan JOIN inv_product p ON p.product_id = pan.product_id LEFT JOIN inv_product_bolt b ON b.pan_id = pan.pan_id %s GROUP BY pan.pan_id ORDER BY pan.created_at DESC LIMIT ? OFFSET ?`, m.table, where) args = append(args, pageSize, (page-1)*pageSize) var list []*PanListItem if err := m.conn.QueryRowsCtx(ctx, &list, query, args...); err != nil { return nil, 0, err } return list, total, nil } func (m *customInvProductPanModel) BulkReplace(ctx context.Context, productId, tenantId string, pans []*InvProductPan) error { return m.conn.TransactCtx(ctx, func(ctx context.Context, session sqlx.Session) error { delQuery := fmt.Sprintf("DELETE FROM %s WHERE `product_id` = ?", m.table) if _, err := session.ExecCtx(ctx, delQuery, productId); err != nil { return err } if len(pans) == 0 { return nil } placeholder := "(?, ?, ?, ?, ?, ?)" placeholders := make([]string, len(pans)) args := make([]interface{}, 0, len(pans)*6) for i, p := range pans { placeholders[i] = placeholder args = append(args, p.PanId, productId, p.Name, p.Position, p.SortOrder, tenantId) } insQuery := fmt.Sprintf("INSERT INTO %s (%s) VALUES %s", m.table, invProductPanRowsExpectAutoSet, strings.Join(placeholders, ",")) _, err := session.ExecCtx(ctx, insQuery, args...) return err }) }