feat: 商品/专区/店铺按俱乐部分离,工单统计与点单手机号认证

商品与专区、店铺增加 club_id(历史默认 xq);列表按俱乐部过滤;工单列表返回待办统计;新增 hqshouji/rzwlsjh 手机号查询与认证接口。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
XingQue
2026-07-21 01:55:14 +08:00
parent 7c6e14db01
commit d5b8ff5b8a
15 changed files with 332 additions and 80 deletions

View File

@@ -0,0 +1,29 @@
from django.db import migrations, models
from django.db.models import Q
def backfill_club_xq(apps, schema_editor):
Dianpu = apps.get_model('shop', 'Dianpu')
Dianpu.objects.filter(Q(club_id__isnull=True) | Q(club_id='')).update(club_id='xq')
class Migration(migrations.Migration):
dependencies = [
('shop', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='dianpu',
name='club_id',
field=models.CharField(
db_index=True,
default='xq',
help_text='店铺按俱乐部隔离;历史数据默认星阙 xq',
max_length=16,
verbose_name='所属俱乐部',
),
),
migrations.RunPython(backfill_club_xq, migrations.RunPython.noop),
]

View File

@@ -59,6 +59,10 @@ class Dianpu(QModel):
verbose_name='作为上级累计获得分红')
shangji_ketixian_fenhong = models.DecimalField(max_digits=12, decimal_places=2, default=0.00,
verbose_name='作为上级可提现分红余额')
club_id = models.CharField(
max_length=16, default='xq', db_index=True, verbose_name='所属俱乐部',
help_text='店铺按俱乐部隔离;历史数据默认星阙 xq',
)
class Meta:
db_table = 'dianpu'

View File

@@ -158,17 +158,20 @@ class ShopGoodsView(APIView):
# 2. 判断用户是否拥有特殊身份
has_special = self._has_special_identity(user_main)
# 3. 根据绑定关系及店铺状态决定数据获取策略
# 3. 根据绑定关系及店铺状态决定数据获取策略(店铺须属当前俱乐部)
from jituan.constants import CLUB_ID_DEFAULT
from jituan.services.club_context import resolve_effective_club_id
club_id = resolve_effective_club_id(request, user_main) or CLUB_ID_DEFAULT
if binding:
dianpu = binding.dianpu
if dianpu.zhuangtai == 1:
# 店铺正常 -> 返回店铺专属商品(需通过平台审核)
shop_club = (getattr(dianpu, 'club_id', None) or CLUB_ID_DEFAULT)
if dianpu.zhuangtai == 1 and shop_club == club_id:
data = self._get_shop_goods(dianpu)
else:
# 店铺被封 -> 返回公共商品有特殊身份则返回审核状态为1的否则返回2的
# 店铺封禁或不属于当前俱乐部 → 公共商品
data = self._get_public_goods(True)
else:
# 无绑定店铺,根据身份决定返回公共商品的审核状态
data = self._get_public_goods(has_special)
return Response({'code': 200, 'data': data})
@@ -241,9 +244,10 @@ class ShopGoodsView(APIView):
).order_by('-paixu', 'id')
shangpin_data = list(shangpin_queryset)
# 字段映射:前端统一使用 leixing_id
# 字段映射:前端统一使用 leixing_id;已拼展示用 xiaoliang 别名
for sp in shangpin_data:
sp['leixing_id'] = sp.pop('dianpu_leixing_id')
sp['xiaoliang'] = sp.get('duiwai_xiaoliang') or 0
else:
shangpin_data = []
@@ -260,32 +264,50 @@ class ShopGoodsView(APIView):
- 必须满足 dianpu 为空且 dianpu_leixing 为空(即纯公共数据)。
- 审核状态:若 use_audit_status_one=True则返回 shenhezhuangtai=1 的数据;
否则返回 shenhezhuangtai=2 的数据(审核专用)。
- 按俱乐部隔离:类型走俱乐部可见配置;专区/商品按 club_id 过滤(历史默认 xq
"""
from jituan.constants import CLUB_ID_DEFAULT
from jituan.services.club_context import resolve_effective_club_id
from jituan.services.club_shangpin_leixing import build_club_leixing_list_for_api
target_shenhe = 1 if use_audit_status_one else 2
club_id = resolve_effective_club_id(self.request, getattr(self.request, 'user', None)) or CLUB_ID_DEFAULT
# 1. 公共商品类型:原有审核状态为 target_shenhe
leixing_queryset = ShangpinLeixing.query.filter(
shenhezhuangtai=target_shenhe
).order_by('-paixu', 'id')
leixing_data = []
for lx in leixing_queryset:
leixing_data.append({
'id': lx.id,
'jieshao': lx.jieshao,
'tupian_url': lx.tupian_url,
'paixu': lx.paixu
})
# 1. 公共商品类型:按俱乐部可见类型
if use_audit_status_one:
leixing_rows = build_club_leixing_list_for_api(club_id)
leixing_data = [
{
'id': row['id'],
'jieshao': row['jieshao'],
'tupian_url': row['tupian_url'],
'paixu': row['paixu'],
}
for row in leixing_rows
]
else:
leixing_queryset = ShangpinLeixing.query.filter(
shenhezhuangtai=target_shenhe
).order_by('-paixu', 'id')
leixing_data = []
for lx in leixing_queryset:
leixing_data.append({
'id': lx.id,
'jieshao': lx.jieshao,
'tupian_url': lx.tupian_url,
'paixu': lx.paixu
})
visible_leixing_ids = [lx['id'] for lx in leixing_data]
# 2. 专区:dianpu 为空,且 dianpu_leixing 为空leixing_id 在可见范围内,原有审核状态为 target_shenhe
# 2. 专区:当前俱乐部 + 公共
if visible_leixing_ids:
zhuanqu_queryset = ShangpinZhuanqu.query.filter(
dianpu__isnull=True,
dianpu_leixing__isnull=True, # 🔥 必须为空
dianpu_leixing__isnull=True,
leixing_id__in=visible_leixing_ids,
shenhezhuangtai=target_shenhe
shenhezhuangtai=target_shenhe,
club_id=club_id,
).order_by('-paixu', 'id')
else:
zhuanqu_queryset = ShangpinZhuanqu.query.none()
@@ -299,20 +321,23 @@ class ShopGoodsView(APIView):
'paixu': zq.paixu
})
# 3. 商品:dianpu 为空dianpu_leixing 为空,专区在可见范围内,原有审核状态为 target_shenhe
# 3. 商品:当前俱乐部 + 公共
zhuanqu_ids = [zq['id'] for zq in zhuanqu_data]
if zhuanqu_ids:
shangpin_queryset = Shangpin.query.filter(
dianpu__isnull=True,
dianpu_leixing__isnull=True, # 🔥 必须为空
dianpu_leixing__isnull=True,
leixing_id__in=visible_leixing_ids,
zhuanqu_id__in=zhuanqu_ids,
shenhezhuangtai=target_shenhe
shenhezhuangtai=target_shenhe,
club_id=club_id,
).values(
'id', 'biaoqian', 'jiage', 'tupian_url', 'duiwai_xiaoliang', 'paixu',
'leixing_id', 'zhuanqu_id'
).order_by('-paixu', 'id')
shangpin_data = list(shangpin_queryset)
for sp in shangpin_data:
sp['xiaoliang'] = sp.get('duiwai_xiaoliang') or 0
else:
shangpin_data = []

View File

@@ -275,14 +275,14 @@ class SubShopModifyView(APIView):
mima=mima,
is_active=True
)
# 创建店铺,关联上级
# 创建店铺,关联上级(俱乐部与上级一致)
dianpu = Dianpu.query.create(
pingzheng=pingzheng,
dianpu_mingcheng=dianpu_mingcheng,
lianxi_dianhua=lianxi_dianhua or '',
yaoqing_dianpu_id=parent_dianpu.id, # 关键:绑定上级
fenhong_choucheng_feilv=fenhong_feilv,
# 其他字段使用默认值
club_id=getattr(parent_dianpu, 'club_id', None) or 'xq',
)
return Response({
'code': 200,