fix: 俱乐部类型排序隔离;商家派单仅本店已上架类型
单店排序写入 ClubShangpinLeixingConfig;sjspleixing/派单/链接/模板校验本店上架。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
be2892f419
commit
c10727c356
7 files changed
+113
-31
No files matched your search
@@ -643,11 +643,26 @@ class SaveProductOrderView(APIView):
|
||||
except:
|
||||
return Response({'code': 400, 'msg': 'id或paixu格式错误'})
|
||||
|
||||
from jituan.constants import DATA_SCOPE_ALL
|
||||
from jituan.services.club_context import (
|
||||
filter_club_char_field,
|
||||
resolve_club_scope,
|
||||
)
|
||||
from jituan.services.club_shangpin_leixing import save_club_leixing_order
|
||||
|
||||
club_scoped = resolve_club_scope(request) != DATA_SCOPE_ALL
|
||||
|
||||
with transaction.atomic():
|
||||
if sort_type == 'leixing':
|
||||
# 更新商品类型的排序
|
||||
for item in items:
|
||||
ShangpinLeixing.query.filter(id=item['id']).update(paixu=item['paixu'])
|
||||
if club_scoped:
|
||||
# 单店:写 ClubShangpinLeixingConfig.paixu,各俱乐部互不影响
|
||||
err = save_club_leixing_order(request, items)
|
||||
if err:
|
||||
return Response({'code': 400, 'msg': err})
|
||||
else:
|
||||
# 集团汇总:仍写全局类型排序(仅集团视图)
|
||||
for item in items:
|
||||
ShangpinLeixing.query.filter(id=item['id']).update(paixu=item['paixu'])
|
||||
else: # zhuanqu
|
||||
leixing_id = request.data.get('leixing_id')
|
||||
if not leixing_id:
|
||||
@@ -656,9 +671,12 @@ class SaveProductOrderView(APIView):
|
||||
leixing_id = int(leixing_id)
|
||||
except:
|
||||
return Response({'code': 400, 'msg': 'leixing_id格式错误'})
|
||||
# 可选:检查该专区是否属于该类型,但不强制,由前端保证
|
||||
# 专区本身按 club_id 隔离;更新时再按当前店过滤,防止串店
|
||||
for item in items:
|
||||
ShangpinZhuanqu.query.filter(id=item['id']).update(paixu=item['paixu'])
|
||||
qs = ShangpinZhuanqu.query.filter(id=item['id'], leixing_id=leixing_id)
|
||||
if club_scoped:
|
||||
qs = filter_club_char_field(qs, request, field='club_id')
|
||||
qs.update(paixu=item['paixu'])
|
||||
|
||||
return Response({'code': 0, 'msg': '排序保存成功'})
|
||||
|
||||
|
||||
@@ -95,6 +95,11 @@ class ShangjiaGenerateLinkView(APIView):
|
||||
except ShangpinLeixing.DoesNotExist:
|
||||
return Response({'code': 400, 'msg': '商品类型不存在或已禁用', 'data': {}}, status=400)
|
||||
|
||||
club_id = resolve_club_id_from_request(request)
|
||||
from jituan.services.club_shangpin_leixing import is_leixing_enabled_for_club
|
||||
if not is_leixing_enabled_for_club(club_id, shangpin_type_id):
|
||||
return Response({'code': 400, 'msg': '该商品类型未在本俱乐部上架', 'data': {}}, status=400)
|
||||
|
||||
# 查询模板
|
||||
try:
|
||||
moban = ShangjiaMoban.query.get(id=moban_id, UserID=user.UserUID, ProductTypeID=shangpin_type_id)
|
||||
@@ -106,7 +111,6 @@ class ShangjiaGenerateLinkView(APIView):
|
||||
return Response({'code': 400, 'msg': f'余额不足,当前余额{shangjia.yue}元', 'data': {}}, status=400)
|
||||
|
||||
# 打手+管事分成(与普通派单 sjpaifa 同一套算法,打手优先)
|
||||
club_id = resolve_club_id_from_request(request)
|
||||
try:
|
||||
from jituan.services.order_deal import check_merchant_dispatch_block
|
||||
block = check_merchant_dispatch_block(club_id, user.UserUID)
|
||||
|
||||
@@ -266,7 +266,7 @@ class ShangjiaTianjiaMobanView(APIView):
|
||||
except (ValueError, TypeError):
|
||||
return Response({'code': 400, 'msg': '标签ID格式错误', 'data': {}}, status=400)
|
||||
|
||||
# 8. 验证商品类型是否存在且可用
|
||||
# 8. 验证商品类型是否存在且可用(且本俱乐部已上架)
|
||||
try:
|
||||
shangpin_obj = ShangpinLeixing.query.get(
|
||||
id=leixing_id,
|
||||
@@ -275,6 +275,11 @@ class ShangjiaTianjiaMobanView(APIView):
|
||||
except ShangpinLeixing.DoesNotExist:
|
||||
return Response({'code': 404, 'msg': '商品类型不存在或已禁用', 'data': {}}, status=404)
|
||||
|
||||
from jituan.services.club_context import resolve_club_id_from_request
|
||||
from jituan.services.club_shangpin_leixing import is_leixing_enabled_for_club
|
||||
if not is_leixing_enabled_for_club(resolve_club_id_from_request(request), leixing_id):
|
||||
return Response({'code': 400, 'msg': '该商品类型未在本俱乐部上架', 'data': {}}, status=400)
|
||||
|
||||
# 9. 检查同一用户、同一类型下是否已存在相同介绍的模板
|
||||
if ShangjiaMoban.query.filter(
|
||||
UserID=yonghu_id,
|
||||
|
||||
@@ -49,6 +49,10 @@ def _is_visible(club_id, leixing_id, cfg):
|
||||
|
||||
|
||||
def build_leixing_item(leixing, cfg=None):
|
||||
if cfg is not None:
|
||||
paixu = int(cfg.paixu or 0)
|
||||
else:
|
||||
paixu = int(leixing.paixu or 0)
|
||||
item = {
|
||||
'id': leixing.id,
|
||||
'jieshao': leixing.jieshao or '',
|
||||
@@ -57,7 +61,7 @@ def build_leixing_item(leixing, cfg=None):
|
||||
'yaoqiuleixing': leixing.yaoqiuleixing,
|
||||
'huiyuan_id': leixing.huiyuan_id,
|
||||
'yongjin': float(leixing.yongjin) if leixing.yongjin else None,
|
||||
'paixu': (cfg.paixu if cfg and cfg.paixu else leixing.paixu) or 0,
|
||||
'paixu': paixu,
|
||||
'shenhezhuangtai': leixing.shenhezhuangtai or 1,
|
||||
'bankuai_id': leixing.bankuai_id,
|
||||
'club_enabled': True,
|
||||
@@ -68,6 +72,44 @@ def build_leixing_item(leixing, cfg=None):
|
||||
return item
|
||||
|
||||
|
||||
def is_leixing_enabled_for_club(club_id, leixing_id):
|
||||
"""本俱乐部是否已上架该商品类型。"""
|
||||
club_id = (club_id or '').strip()
|
||||
if not club_id or leixing_id is None:
|
||||
return False
|
||||
cfg = ClubShangpinLeixingConfig.query.filter(
|
||||
club_id=club_id, leixing_id=int(leixing_id),
|
||||
).first()
|
||||
return _is_visible(club_id, int(leixing_id), cfg)
|
||||
|
||||
|
||||
def save_club_leixing_order(request, items):
|
||||
"""
|
||||
按本俱乐部写入类型排序(互不影响全局/其他店)。
|
||||
items: [{id, paixu}, ...]
|
||||
成功返回 None,失败返回错误文案。
|
||||
"""
|
||||
if club_write_blocked(request):
|
||||
return CLUB_WRITE_SCOPE_MSG
|
||||
club_id = club_id_for_write(request)
|
||||
if not club_id:
|
||||
return '无法解析当前俱乐部'
|
||||
with transaction.atomic():
|
||||
for item in items:
|
||||
leixing_id = int(item['id'])
|
||||
paixu = int(item['paixu'])
|
||||
row, _ = ClubShangpinLeixingConfig.query.get_or_create(
|
||||
club_id=club_id,
|
||||
leixing_id=leixing_id,
|
||||
defaults={'is_enabled': True, 'paixu': paixu},
|
||||
)
|
||||
if not row.is_enabled:
|
||||
continue
|
||||
row.paixu = paixu
|
||||
row.save(update_fields=['paixu', 'UpdateTime'])
|
||||
return None
|
||||
|
||||
|
||||
def build_club_leixing_list_for_api(club_id):
|
||||
"""小程序/抢单池:仅返回本俱乐部已上架的类型,图标优先俱乐部配置。"""
|
||||
cfg_map = _config_map(club_id)
|
||||
|
||||
@@ -63,6 +63,11 @@ def staff_dispatch_order(member, staff_user, data):
|
||||
except ShangpinLeixing.DoesNotExist:
|
||||
return False, {'code': 400, 'msg': '商品类型不存在', 'data': None}
|
||||
|
||||
club_id = getattr(member, 'club_id', None) or ''
|
||||
from jituan.services.club_shangpin_leixing import is_leixing_enabled_for_club
|
||||
if not is_leixing_enabled_for_club(club_id, shangpin_type.id):
|
||||
return False, {'code': 400, 'msg': '该商品类型未在本俱乐部上架', 'data': None}
|
||||
|
||||
if commission_enabled and commission_value_str:
|
||||
try:
|
||||
cv = float(commission_value_str)
|
||||
|
||||
@@ -106,6 +106,10 @@ def staff_generate_link(member, staff_user, data):
|
||||
except ShangpinLeixing.DoesNotExist:
|
||||
return False, {'code': 400, 'msg': '商品类型不存在或已禁用', 'data': {}}
|
||||
|
||||
from jituan.services.club_shangpin_leixing import is_leixing_enabled_for_club
|
||||
if not is_leixing_enabled_for_club(club_id, shangpin_type_id):
|
||||
return False, {'code': 400, 'msg': '该商品类型未在本俱乐部上架', 'data': {}}
|
||||
|
||||
try:
|
||||
moban = ShangjiaMoban.query.get(
|
||||
id=moban_id, UserID=merchant_id, ProductTypeID=shangpin_type_id,
|
||||
|
||||
+27
-23
@@ -116,21 +116,23 @@ class ShangpinLeixingView(APIView):
|
||||
return Response({'code': 403, 'msg': '非商家或有效客服,无权获取订单类型', 'data': []})
|
||||
|
||||
try:
|
||||
# 1. 查询审核通过且抢单要求类型为1的商品类型,按排序权重升序
|
||||
shangpin_queryset = ShangpinLeixing.query.filter(
|
||||
yaoqiuleixing=1,
|
||||
shenhezhuangtai=1
|
||||
).select_related('bankuai').order_by('paixu')
|
||||
from jituan.services.club_shangpin_leixing import build_club_leixing_list_for_api
|
||||
|
||||
# 2. 收集所有涉及到的板块ID
|
||||
bankuai_ids = shangpin_queryset.values_list('bankuai_id', flat=True).distinct()
|
||||
# 仅本俱乐部已上架类型(生成链接 / 自定义发单 / 常规单统一入口)
|
||||
club_id = resolve_club_id_from_request(request)
|
||||
club_rows = [
|
||||
r for r in build_club_leixing_list_for_api(club_id)
|
||||
if int(r.get('yaoqiuleixing') or 0) == 1
|
||||
and int(r.get('shenhezhuangtai') or 0) == 1
|
||||
]
|
||||
|
||||
# 3. 查询这些板块下的所有称号(每个称号绑定到一个板块)
|
||||
bankuai_ids = {
|
||||
r.get('bankuai_id') for r in club_rows if r.get('bankuai_id')
|
||||
}
|
||||
chenghao_list = Chenghao.query.filter(
|
||||
bankuai_id__in=bankuai_ids
|
||||
).values('id', 'mingcheng', 'texiao_miaoshu', 'bankuai_id')
|
||||
).values('id', 'mingcheng', 'texiao_miaoshu', 'bankuai_id') if bankuai_ids else []
|
||||
|
||||
# 4. 构建 板块ID -> 称号列表 的映射(确保准确关联)
|
||||
bankuai_chenghao_map = {}
|
||||
for ch in chenghao_list:
|
||||
bid = ch['bankuai_id']
|
||||
@@ -139,21 +141,18 @@ class ShangpinLeixingView(APIView):
|
||||
bankuai_chenghao_map[bid].append({
|
||||
'id': ch['id'],
|
||||
'mingcheng': ch['mingcheng'],
|
||||
'texiao_json': ch['texiao_miaoshu'] # 前端 chenghao-tag 组件需要
|
||||
'texiao_json': ch['texiao_miaoshu'],
|
||||
})
|
||||
|
||||
# 5. 组装最终数据
|
||||
data_list = []
|
||||
for sp in shangpin_queryset:
|
||||
item = {
|
||||
'id': sp.id,
|
||||
'yaoqiuleixing': sp.yaoqiuleixing,
|
||||
'huiyuan_id': sp.huiyuan_id,
|
||||
'jieshao': sp.jieshao,
|
||||
# 当前类型所属板块的称号列表(无板块则为空数组)
|
||||
'chenghaoList': bankuai_chenghao_map.get(sp.bankuai_id, [])
|
||||
}
|
||||
data_list.append(item)
|
||||
for sp in club_rows:
|
||||
data_list.append({
|
||||
'id': sp['id'],
|
||||
'yaoqiuleixing': sp.get('yaoqiuleixing'),
|
||||
'huiyuan_id': sp.get('huiyuan_id'),
|
||||
'jieshao': sp.get('jieshao') or '',
|
||||
'chenghaoList': bankuai_chenghao_map.get(sp.get('bankuai_id'), []),
|
||||
})
|
||||
|
||||
return Response({
|
||||
'code': 200,
|
||||
@@ -214,13 +213,18 @@ class ShangjiaPaifaView(APIView):
|
||||
except ValueError:
|
||||
return Response({'code': 400, 'msg': '价格格式错误'})
|
||||
|
||||
# ----- 5. 商品类型 -----
|
||||
# ----- 5. 商品类型(必须本俱乐部已上架)-----
|
||||
try:
|
||||
shangpin_type = ShangpinLeixing.query.get(id=shangpin_type_id)
|
||||
except ShangpinLeixing.DoesNotExist:
|
||||
logger.error(f"商品类型不存在: {shangpin_type_id}")
|
||||
return Response({'code': 400, 'msg': '商品类型不存在'})
|
||||
|
||||
from jituan.services.club_shangpin_leixing import is_leixing_enabled_for_club
|
||||
_dispatch_club = resolve_club_id_from_request(request)
|
||||
if not is_leixing_enabled_for_club(_dispatch_club, shangpin_type.id):
|
||||
return Response({'code': 400, 'msg': '该商品类型未在本俱乐部上架'})
|
||||
|
||||
# ----- 6. 押金 / 会员模式决定 -----
|
||||
final_yongjin = None
|
||||
if commission_enabled and commission_value_str:
|
||||
|
||||
Reference in new issue
Block a user