feat: add column sorting and advanced filtering for purchase inbound

Co-authored-by: aider (openai/DeepSeek-V3.2-Thinking) <aider@aider.chat>
This commit is contained in:
dxc
2026-03-02 15:39:32 +08:00
parent 2ac64076dd
commit 893be24071
3 changed files with 234 additions and 8 deletions

View File

@ -106,7 +106,7 @@ def search_base():
# ------------------------------------------------------------------
# 1. 获取列表 (修改:接收 category material_type)
# 1. 获取列表 (修改:接收 category, material_type, orderByColumn, isAsc, advancedFilters)
# ------------------------------------------------------------------
@inbound_buy_bp.route('/list', methods=['GET'])
@permission_required('inbound_buy')
@ -121,11 +121,24 @@ def get_list():
material_type = request.args.get('material_type', '')
company = request.args.get('company', '')
# 排序参数
order_by = request.args.get('orderByColumn', '').strip()
is_asc = request.args.get('isAsc', '').strip()
# 高级筛选参数
advanced_filters_raw = request.args.get('advancedFilters', '[]')
import json
try:
advanced_filters = json.loads(advanced_filters_raw) if advanced_filters_raw else []
except json.JSONDecodeError:
advanced_filters = []
# 状态参数处理
statuses_str = request.args.get('statuses', '')
statuses = statuses_str.split(',') if statuses_str else []
result = BuyInboundService.get_list(page, limit, keyword, statuses, category, material_type, company)
result = BuyInboundService.get_list(page, limit, keyword, statuses, category, material_type, company,
order_by, is_asc, advanced_filters)
# 字段级脱敏
user_permissions = get_current_user_permissions()
if result.get('items'):

View File

@ -237,11 +237,13 @@ class BuyInboundService:
raise e
# ============================================================
# 5. 获取列表
# 5. 获取列表 (支持排序和高级筛选)
# ============================================================
@staticmethod
def get_list(page, limit, keyword=None, statuses=None, category=None, material_type=None, company=None):
def get_list(page, limit, keyword=None, statuses=None, category=None, material_type=None, company=None,
order_by='', is_asc='', advanced_filters=None):
try:
from sqlalchemy import and_, or_
query = db.session.query(StockBuy).outerjoin(MaterialBase, StockBuy.base_id == MaterialBase.id)
# 1. 通用关键词搜索
@ -279,7 +281,109 @@ class BuyInboundService:
else:
query = query.filter(and_(StockBuy.status.in_(statuses), StockBuy.stock_quantity > 0))
pagination = query.order_by(StockBuy.in_date.desc()).paginate(page=page, per_page=limit, error_out=False)
# 5. 高级动态筛选
if advanced_filters:
allowed_fields = {
'company_name': MaterialBase.company_name,
'material_name': MaterialBase.name,
'material_type': MaterialBase.material_type,
'category': MaterialBase.category,
'spec_model': MaterialBase.spec_model,
'unit': MaterialBase.unit,
'sku': StockBuy.sku,
'barcode': StockBuy.barcode,
'batch_number': StockBuy.batch_number,
'serial_number': StockBuy.serial_number,
'warehouse_location': StockBuy.warehouse_location,
'status': StockBuy.status,
'inspection_status': StockBuy.inspection_status,
'qty_inbound': StockBuy.in_quantity,
'qty_stock': StockBuy.stock_quantity,
'qty_available': StockBuy.available_quantity,
'unit_price': StockBuy.pre_tax_unit_price,
'total_price': StockBuy.total_price,
'tax_rate': StockBuy.tax_rate,
'currency': StockBuy.currency,
'exchange_rate': StockBuy.exchange_rate,
'supplier_name': StockBuy.supplier_name,
'purchaser': StockBuy.buyer_name,
'purchaser_email': StockBuy.buyer_email,
'source_link': StockBuy.original_link,
'detail_link': StockBuy.detail_link,
}
filter_conditions = []
for condition in advanced_filters:
field = condition.get('field')
operator = condition.get('operator')
value = condition.get('value')
if not field or not operator or value is None:
continue
column = allowed_fields.get(field)
if column is None:
continue
if operator == 'eq':
filter_conditions.append(column == value)
elif operator == 'ne':
filter_conditions.append(column != value)
elif operator == 'contains':
filter_conditions.append(column.ilike(f'%{value}%'))
elif operator == 'ge':
try:
num_val = float(value)
filter_conditions.append(column >= num_val)
except ValueError:
continue
elif operator == 'le':
try:
num_val = float(value)
filter_conditions.append(column <= num_val)
except ValueError:
continue
if filter_conditions:
query = query.filter(and_(*filter_conditions))
# 6. 排序处理
if order_by:
sort_field_map = {
'company_name': MaterialBase.company_name,
'material_name': MaterialBase.name,
'material_type': MaterialBase.material_type,
'category': MaterialBase.category,
'spec_model': MaterialBase.spec_model,
'unit': MaterialBase.unit,
'sku': StockBuy.sku,
'barcode': StockBuy.barcode,
'inbound_date': StockBuy.in_date,
'serial_number': StockBuy.serial_number,
'batch_number': StockBuy.batch_number,
'status': StockBuy.status,
'inspection_status': StockBuy.inspection_status,
'qty_inbound': StockBuy.in_quantity,
'qty_stock': StockBuy.stock_quantity,
'qty_available': StockBuy.available_quantity,
'warehouse_loc': StockBuy.warehouse_location,
'unit_price': StockBuy.pre_tax_unit_price,
'total_price': StockBuy.total_price,
'tax_rate': StockBuy.tax_rate,
'currency': StockBuy.currency,
'exchange_rate': StockBuy.exchange_rate,
'supplier_name': StockBuy.supplier_name,
'purchaser': StockBuy.buyer_name,
'purchaser_email': StockBuy.buyer_email,
'source_link': StockBuy.original_link,
'detail_link': StockBuy.detail_link,
}
column = sort_field_map.get(order_by)
if column:
if is_asc == 'asc':
query = query.order_by(column.asc())
elif is_asc == 'desc':
query = query.order_by(column.desc())
else:
# 默认排序
query = query.order_by(StockBuy.in_date.desc())
pagination = query.paginate(page=page, per_page=limit, error_out=False)
items = []
for item in pagination.items:
items.append(item.to_dict()) # 直接使用 model 的 to_dict