feat(jituan): 俱乐部商品类型/考核标签上架配置与抢单池过滤
This commit is contained in:
@@ -98,6 +98,10 @@ MENU_ROWS = [
|
||||
'perm_codes': ['8080a']},
|
||||
{'page_id': 'miniapp.withdraw-settings', 'name': '提现与收款设置', 'path': '/withdraw/settings', 'parent_id': 'miniapp', 'sort_order': 114,
|
||||
'perm_codes': ['5500a', '5500b', '5500c']},
|
||||
{'page_id': 'miniapp.leixing', 'name': '抢单商品类型', 'path': '/miniapp/leixing', 'parent_id': 'miniapp', 'sort_order': 115,
|
||||
'perm_codes': ['8080a']},
|
||||
{'page_id': 'miniapp.kaohe-tags', 'name': '抢单考核标签', 'path': '/miniapp/kaohe-tags', 'parent_id': 'miniapp', 'sort_order': 116,
|
||||
'perm_codes': ['8080a']},
|
||||
# 店铺
|
||||
{'page_id': 'shop', 'name': '店铺管理', 'path': '', 'parent_id': '', 'sort_order': 120},
|
||||
{'page_id': 'shop.list', 'name': '店铺列表', 'path': '/shop/list', 'parent_id': 'shop', 'sort_order': 121,
|
||||
|
||||
43
jituan/migrations/0007_club_catalog_config.py
Normal file
43
jituan/migrations/0007_club_catalog_config.py
Normal file
@@ -0,0 +1,43 @@
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('jituan', '0006_club_huiyuan_trial_fields'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='ClubShangpinLeixingConfig',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('club_id', models.CharField(db_index=True, max_length=16)),
|
||||
('leixing_id', models.IntegerField(db_index=True, verbose_name='全局商品类型ID')),
|
||||
('is_enabled', models.BooleanField(default=True, verbose_name='是否上架')),
|
||||
('tupian_url', models.CharField(blank=True, default='', max_length=500, verbose_name='俱乐部专属图标')),
|
||||
('paixu', models.IntegerField(default=0, verbose_name='排序权重')),
|
||||
('CreateTime', models.DateTimeField(auto_now_add=True)),
|
||||
('UpdateTime', models.DateTimeField(auto_now=True)),
|
||||
],
|
||||
options={
|
||||
'db_table': 'club_shangpin_leixing_config',
|
||||
'unique_together': {('club_id', 'leixing_id')},
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ClubKaoheChenghaoConfig',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('club_id', models.CharField(db_index=True, max_length=16)),
|
||||
('chenghao_id', models.IntegerField(db_index=True, verbose_name='全局称号ID')),
|
||||
('is_enabled', models.BooleanField(default=True, verbose_name='是否在抢单池筛选区展示')),
|
||||
('CreateTime', models.DateTimeField(auto_now_add=True)),
|
||||
('UpdateTime', models.DateTimeField(auto_now=True)),
|
||||
],
|
||||
options={
|
||||
'db_table': 'club_kaohe_chenghao_config',
|
||||
'unique_together': {('club_id', 'chenghao_id')},
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -121,6 +121,34 @@ class ClubHuiyuanPrice(QModel):
|
||||
unique_together = [['club_id', 'huiyuan_id']]
|
||||
|
||||
|
||||
class ClubShangpinLeixingConfig(QModel):
|
||||
"""各俱乐部小程序商品类型上架与图标(全局 ShangpinLeixing 由集团定义)。"""
|
||||
club_id = models.CharField(max_length=16, db_index=True)
|
||||
leixing_id = models.IntegerField(db_index=True, verbose_name='全局商品类型ID')
|
||||
is_enabled = models.BooleanField(default=True, verbose_name='是否上架')
|
||||
tupian_url = models.CharField(max_length=500, blank=True, default='', verbose_name='俱乐部专属图标')
|
||||
paixu = models.IntegerField(default=0, verbose_name='排序权重')
|
||||
CreateTime = models.DateTimeField(auto_now_add=True)
|
||||
UpdateTime = models.DateTimeField(auto_now=True)
|
||||
|
||||
class Meta:
|
||||
db_table = 'club_shangpin_leixing_config'
|
||||
unique_together = [['club_id', 'leixing_id']]
|
||||
|
||||
|
||||
class ClubKaoheChenghaoConfig(QModel):
|
||||
"""各俱乐部抢单池标签筛选区上架配置(全局 Chenghao 由集团定义)。"""
|
||||
club_id = models.CharField(max_length=16, db_index=True)
|
||||
chenghao_id = models.IntegerField(db_index=True, verbose_name='全局称号ID')
|
||||
is_enabled = models.BooleanField(default=True, verbose_name='是否在抢单池筛选区展示')
|
||||
CreateTime = models.DateTimeField(auto_now_add=True)
|
||||
UpdateTime = models.DateTimeField(auto_now=True)
|
||||
|
||||
class Meta:
|
||||
db_table = 'club_kaohe_chenghao_config'
|
||||
unique_together = [['club_id', 'chenghao_id']]
|
||||
|
||||
|
||||
class ClubLilubiao(QModel):
|
||||
"""各俱乐部分红/手续费配置(对应 lilubiao.fadanpingtai)。"""
|
||||
club_id = models.CharField(max_length=16, db_index=True)
|
||||
|
||||
@@ -100,5 +100,9 @@ def bootstrap_club_from_template(
|
||||
|
||||
Szjilu.objects.get_or_create(club_id=new_id)
|
||||
copy_display_config(template_id, new_id)
|
||||
from jituan.services.club_shangpin_leixing import copy_club_shangpin_leixing_config
|
||||
from jituan.services.club_kaohe_chenghao import copy_club_kaohe_chenghao_config
|
||||
copy_club_shangpin_leixing_config(template_id, new_id)
|
||||
copy_club_kaohe_chenghao_config(template_id, new_id)
|
||||
|
||||
return club
|
||||
|
||||
129
jituan/services/club_kaohe_chenghao.py
Normal file
129
jituan/services/club_kaohe_chenghao.py
Normal file
@@ -0,0 +1,129 @@
|
||||
"""俱乐部抢单池标签筛选区配置(全局考核称号由集团定义)。"""
|
||||
from jituan.constants import CLUB_ID_DEFAULT
|
||||
from jituan.models import ClubKaoheChenghaoConfig
|
||||
from jituan.services.club_context import (
|
||||
club_id_for_write,
|
||||
resolve_club_id_from_request,
|
||||
resolve_club_scope,
|
||||
)
|
||||
from jituan.constants import DATA_SCOPE_ALL
|
||||
from rank.models import Chenghao
|
||||
|
||||
CLUB_WRITE_SCOPE_MSG = '当前为集团汇总视图,请先在顶栏切换到具体俱乐部后再操作'
|
||||
|
||||
|
||||
def club_write_blocked(request):
|
||||
return resolve_club_scope(request) == DATA_SCOPE_ALL
|
||||
|
||||
|
||||
def _config_map(club_id):
|
||||
return {
|
||||
r.chenghao_id: r
|
||||
for r in ClubKaoheChenghaoConfig.query.filter(club_id=club_id)
|
||||
}
|
||||
|
||||
|
||||
def _is_visible(club_id, chenghao_id, cfg):
|
||||
if cfg is not None:
|
||||
return bool(cfg.is_enabled)
|
||||
return club_id == CLUB_ID_DEFAULT
|
||||
|
||||
|
||||
def filter_chenghao_ids_for_pool(club_id, chenghao_ids):
|
||||
"""抢单池标签筛选:仅保留本俱乐部已上架的称号 ID。"""
|
||||
if not chenghao_ids:
|
||||
return []
|
||||
cfg_map = _config_map(club_id)
|
||||
visible = []
|
||||
for cid in chenghao_ids:
|
||||
cfg = cfg_map.get(cid)
|
||||
if _is_visible(club_id, cid, cfg):
|
||||
visible.append(cid)
|
||||
return visible
|
||||
|
||||
|
||||
def build_club_kaohe_admin_list(request, bankuai_id=None):
|
||||
club_id = resolve_club_id_from_request(request)
|
||||
cfg_map = _config_map(club_id)
|
||||
qs = Chenghao.objects.filter(leixing='dashou')
|
||||
if bankuai_id:
|
||||
qs = qs.filter(bankuai_id=bankuai_id)
|
||||
enabled = []
|
||||
for ch in qs.order_by('id'):
|
||||
cfg = cfg_map.get(ch.id)
|
||||
if not _is_visible(club_id, ch.id, cfg):
|
||||
continue
|
||||
enabled.append({
|
||||
'id': ch.id,
|
||||
'mingcheng': ch.mingcheng,
|
||||
'bankuai_id': ch.bankuai_id,
|
||||
'kaioi_jinpai': bool(ch.kaioi_jinpai),
|
||||
'club_enabled': True,
|
||||
})
|
||||
return {
|
||||
'club_id': club_id,
|
||||
'list': enabled,
|
||||
'scope': resolve_club_scope(request),
|
||||
}
|
||||
|
||||
|
||||
def build_club_kaohe_catalog(request, bankuai_id=None):
|
||||
club_id = resolve_club_id_from_request(request)
|
||||
cfg_map = _config_map(club_id)
|
||||
qs = Chenghao.objects.filter(leixing='dashou')
|
||||
if bankuai_id:
|
||||
qs = qs.filter(bankuai_id=bankuai_id)
|
||||
catalog = []
|
||||
for ch in qs.order_by('mingcheng'):
|
||||
cfg = cfg_map.get(ch.id)
|
||||
if _is_visible(club_id, ch.id, cfg):
|
||||
continue
|
||||
catalog.append({
|
||||
'id': ch.id,
|
||||
'mingcheng': ch.mingcheng,
|
||||
'bankuai_id': ch.bankuai_id,
|
||||
})
|
||||
return {'club_id': club_id, 'catalog': catalog}
|
||||
|
||||
|
||||
def enable_chenghao_for_club(request, chenghao_id):
|
||||
if club_write_blocked(request):
|
||||
return None, CLUB_WRITE_SCOPE_MSG
|
||||
club_id = club_id_for_write(request)
|
||||
if not Chenghao.objects.filter(id=chenghao_id, leixing='dashou').exists():
|
||||
return None, '考核标签不存在'
|
||||
row, _ = ClubKaoheChenghaoConfig.query.get_or_create(
|
||||
club_id=club_id,
|
||||
chenghao_id=chenghao_id,
|
||||
defaults={'is_enabled': True},
|
||||
)
|
||||
row.is_enabled = True
|
||||
row.save(update_fields=['is_enabled', 'UpdateTime'])
|
||||
return {'chenghao_id': chenghao_id}, None
|
||||
|
||||
|
||||
def disable_chenghao_for_club(request, chenghao_id):
|
||||
if club_write_blocked(request):
|
||||
return None, CLUB_WRITE_SCOPE_MSG
|
||||
club_id = club_id_for_write(request)
|
||||
row, _ = ClubKaoheChenghaoConfig.query.get_or_create(
|
||||
club_id=club_id,
|
||||
chenghao_id=chenghao_id,
|
||||
defaults={'is_enabled': False},
|
||||
)
|
||||
row.is_enabled = False
|
||||
row.save(update_fields=['is_enabled', 'UpdateTime'])
|
||||
return {'chenghao_id': chenghao_id}, None
|
||||
|
||||
|
||||
def copy_club_kaohe_chenghao_config(template_club_id, new_club_id):
|
||||
for row in ClubKaoheChenghaoConfig.query.filter(club_id=template_club_id):
|
||||
if ClubKaoheChenghaoConfig.query.filter(
|
||||
club_id=new_club_id, chenghao_id=row.chenghao_id,
|
||||
).exists():
|
||||
continue
|
||||
ClubKaoheChenghaoConfig.query.create(
|
||||
club_id=new_club_id,
|
||||
chenghao_id=row.chenghao_id,
|
||||
is_enabled=row.is_enabled,
|
||||
)
|
||||
192
jituan/services/club_shangpin_leixing.py
Normal file
192
jituan/services/club_shangpin_leixing.py
Normal file
@@ -0,0 +1,192 @@
|
||||
"""俱乐部商品类型上架与图标(全局类型由集团定义)。"""
|
||||
import logging
|
||||
import os
|
||||
import uuid
|
||||
|
||||
from django.db import transaction
|
||||
|
||||
from jituan.constants import CLUB_ID_DEFAULT
|
||||
from jituan.models import ClubShangpinLeixingConfig
|
||||
from jituan.services.club_context import (
|
||||
club_id_for_write,
|
||||
resolve_club_id_from_request,
|
||||
resolve_club_scope,
|
||||
)
|
||||
from jituan.constants import DATA_SCOPE_ALL
|
||||
from products.models import ShangpinLeixing
|
||||
from utils.oss_utils import delete_from_oss, upload_to_oss, validate_image
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
CLUB_WRITE_SCOPE_MSG = '当前为集团汇总视图,请先在顶栏切换到具体俱乐部后再操作'
|
||||
|
||||
|
||||
def club_write_blocked(request):
|
||||
return resolve_club_scope(request) == DATA_SCOPE_ALL
|
||||
|
||||
|
||||
def _config_map(club_id):
|
||||
return {
|
||||
r.leixing_id: r
|
||||
for r in ClubShangpinLeixingConfig.query.filter(club_id=club_id)
|
||||
}
|
||||
|
||||
|
||||
def _resolve_tupian(leixing, cfg):
|
||||
if cfg and cfg.tupian_url:
|
||||
return cfg.tupian_url
|
||||
return leixing.tupian_url or ''
|
||||
|
||||
|
||||
def _is_visible(club_id, leixing_id, cfg):
|
||||
if cfg is not None:
|
||||
return bool(cfg.is_enabled)
|
||||
return club_id == CLUB_ID_DEFAULT
|
||||
|
||||
|
||||
def build_leixing_item(leixing, cfg=None):
|
||||
item = {
|
||||
'id': leixing.id,
|
||||
'jieshao': leixing.jieshao or '',
|
||||
'tupian_url': _resolve_tupian(leixing, cfg),
|
||||
'global_tupian_url': leixing.tupian_url or '',
|
||||
'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,
|
||||
'shenhezhuangtai': leixing.shenhezhuangtai or 1,
|
||||
'bankuai_id': leixing.bankuai_id,
|
||||
'club_enabled': True,
|
||||
'icon_source': 'club' if cfg and cfg.tupian_url else 'global',
|
||||
}
|
||||
return item
|
||||
|
||||
|
||||
def build_club_leixing_list_for_api(club_id):
|
||||
"""小程序/抢单池:仅返回本俱乐部已上架的类型,图标优先俱乐部配置。"""
|
||||
cfg_map = _config_map(club_id)
|
||||
rows = []
|
||||
for lx in ShangpinLeixing.query.exclude(shenhezhuangtai=2):
|
||||
cfg = cfg_map.get(lx.id)
|
||||
if not _is_visible(club_id, lx.id, cfg):
|
||||
continue
|
||||
rows.append(build_leixing_item(lx, cfg))
|
||||
rows.sort(key=lambda x: (-int(x['paixu'] or 0), x['id']))
|
||||
return rows
|
||||
|
||||
|
||||
def build_club_leixing_admin_list(request):
|
||||
club_id = resolve_club_id_from_request(request)
|
||||
cfg_map = _config_map(club_id)
|
||||
enabled = []
|
||||
for lx in ShangpinLeixing.query.exclude(shenhezhuangtai=2).order_by('-paixu', 'id'):
|
||||
cfg = cfg_map.get(lx.id)
|
||||
if not _is_visible(club_id, lx.id, cfg):
|
||||
continue
|
||||
item = build_leixing_item(lx, cfg)
|
||||
item['club_enabled'] = True
|
||||
enabled.append(item)
|
||||
enabled.sort(key=lambda x: (-int(x['paixu'] or 0), x['id']))
|
||||
return {
|
||||
'club_id': club_id,
|
||||
'list': enabled,
|
||||
'scope': resolve_club_scope(request),
|
||||
}
|
||||
|
||||
|
||||
def build_club_leixing_catalog(request):
|
||||
club_id = resolve_club_id_from_request(request)
|
||||
cfg_map = _config_map(club_id)
|
||||
catalog = []
|
||||
for lx in ShangpinLeixing.query.exclude(shenhezhuangtai=2).order_by('-paixu', 'id'):
|
||||
cfg = cfg_map.get(lx.id)
|
||||
if _is_visible(club_id, lx.id, cfg):
|
||||
continue
|
||||
catalog.append({
|
||||
'id': lx.id,
|
||||
'jieshao': lx.jieshao or '',
|
||||
'tupian_url': lx.tupian_url or '',
|
||||
'bankuai_id': lx.bankuai_id,
|
||||
})
|
||||
return {'club_id': club_id, 'catalog': catalog}
|
||||
|
||||
|
||||
def enable_leixing_for_club(request, leixing_id, paixu=0):
|
||||
if club_write_blocked(request):
|
||||
return None, CLUB_WRITE_SCOPE_MSG
|
||||
club_id = club_id_for_write(request)
|
||||
try:
|
||||
lx = ShangpinLeixing.query.get(id=leixing_id)
|
||||
except ShangpinLeixing.DoesNotExist:
|
||||
return None, '商品类型不存在'
|
||||
if lx.shenhezhuangtai == 2:
|
||||
return None, '该类型为审核专用,不可上架'
|
||||
|
||||
row, _ = ClubShangpinLeixingConfig.query.get_or_create(
|
||||
club_id=club_id,
|
||||
leixing_id=leixing_id,
|
||||
defaults={'is_enabled': True, 'paixu': int(paixu or lx.paixu or 0)},
|
||||
)
|
||||
row.is_enabled = True
|
||||
if paixu:
|
||||
row.paixu = int(paixu)
|
||||
row.save(update_fields=['is_enabled', 'paixu', 'UpdateTime'])
|
||||
return {'leixing_id': leixing_id}, None
|
||||
|
||||
|
||||
def disable_leixing_for_club(request, leixing_id):
|
||||
if club_write_blocked(request):
|
||||
return None, CLUB_WRITE_SCOPE_MSG
|
||||
club_id = club_id_for_write(request)
|
||||
row, _ = ClubShangpinLeixingConfig.query.get_or_create(
|
||||
club_id=club_id,
|
||||
leixing_id=leixing_id,
|
||||
defaults={'is_enabled': False},
|
||||
)
|
||||
row.is_enabled = False
|
||||
row.save(update_fields=['is_enabled', 'UpdateTime'])
|
||||
return {'leixing_id': leixing_id}, None
|
||||
|
||||
|
||||
def upload_leixing_icon(request, leixing_id, file_obj):
|
||||
if club_write_blocked(request):
|
||||
return None, CLUB_WRITE_SCOPE_MSG
|
||||
club_id = club_id_for_write(request)
|
||||
if not ShangpinLeixing.query.filter(id=leixing_id).exists():
|
||||
return None, '商品类型不存在'
|
||||
ok, msg = validate_image(file_obj)
|
||||
if not ok:
|
||||
return None, msg
|
||||
|
||||
ext = os.path.splitext(file_obj.name)[1].lower() or '.png'
|
||||
if ext not in ('.png', '.jpg', '.jpeg', '.webp'):
|
||||
ext = '.png'
|
||||
oss_path = f'club/{club_id}/miniapp/shangpinleixing/{leixing_id}_{uuid.uuid4().hex}{ext}'
|
||||
|
||||
row, _ = ClubShangpinLeixingConfig.query.get_or_create(
|
||||
club_id=club_id,
|
||||
leixing_id=leixing_id,
|
||||
defaults={'is_enabled': club_id == CLUB_ID_DEFAULT},
|
||||
)
|
||||
if row.tupian_url and row.tupian_url != oss_path:
|
||||
delete_from_oss(row.tupian_url)
|
||||
if not upload_to_oss(file_obj, oss_path):
|
||||
return None, '图片上传失败'
|
||||
row.tupian_url = oss_path
|
||||
row.save(update_fields=['tupian_url', 'UpdateTime'])
|
||||
return {'leixing_id': leixing_id, 'tupian_url': oss_path}, None
|
||||
|
||||
|
||||
def copy_club_shangpin_leixing_config(template_club_id, new_club_id):
|
||||
for row in ClubShangpinLeixingConfig.query.filter(club_id=template_club_id):
|
||||
if ClubShangpinLeixingConfig.query.filter(
|
||||
club_id=new_club_id, leixing_id=row.leixing_id,
|
||||
).exists():
|
||||
continue
|
||||
ClubShangpinLeixingConfig.query.create(
|
||||
club_id=new_club_id,
|
||||
leixing_id=row.leixing_id,
|
||||
is_enabled=row.is_enabled,
|
||||
tupian_url='', # 新俱乐部需自行上传图标,不复制 OSS 路径
|
||||
paixu=row.paixu,
|
||||
)
|
||||
@@ -51,6 +51,17 @@ from jituan.views import (
|
||||
ClubWechatLoginView,
|
||||
)
|
||||
|
||||
from jituan.views_club_catalog import (
|
||||
ClubKaoheChenghaoCatalogView,
|
||||
ClubKaoheChenghaoDisableView,
|
||||
ClubKaoheChenghaoEnableView,
|
||||
ClubKaoheChenghaoListView,
|
||||
ClubShangpinLeixingCatalogView,
|
||||
ClubShangpinLeixingDisableView,
|
||||
ClubShangpinLeixingEnableView,
|
||||
ClubShangpinLeixingIconView,
|
||||
ClubShangpinLeixingListView,
|
||||
)
|
||||
from jituan.views_identity_tag import (
|
||||
IdentityTagBindListView,
|
||||
IdentityTagBindView,
|
||||
@@ -110,5 +121,14 @@ urlpatterns = [
|
||||
path('houtai/hthycatalog', ClubMemberCatalogView.as_view(), name='jituan_member_catalog'),
|
||||
path('houtai/hthysj', ClubMemberEnableView.as_view(), name='jituan_member_enable'),
|
||||
path('houtai/hthyxj', ClubMemberDisableView.as_view(), name='jituan_member_disable'),
|
||||
path('houtai/club-leixing-list', ClubShangpinLeixingListView.as_view(), name='jituan_club_leixing_list'),
|
||||
path('houtai/club-leixing-catalog', ClubShangpinLeixingCatalogView.as_view(), name='jituan_club_leixing_catalog'),
|
||||
path('houtai/club-leixing-enable', ClubShangpinLeixingEnableView.as_view(), name='jituan_club_leixing_enable'),
|
||||
path('houtai/club-leixing-disable', ClubShangpinLeixingDisableView.as_view(), name='jituan_club_leixing_disable'),
|
||||
path('houtai/club-leixing-icon', ClubShangpinLeixingIconView.as_view(), name='jituan_club_leixing_icon'),
|
||||
path('houtai/club-kaohe-list', ClubKaoheChenghaoListView.as_view(), name='jituan_club_kaohe_list'),
|
||||
path('houtai/club-kaohe-catalog', ClubKaoheChenghaoCatalogView.as_view(), name='jituan_club_kaohe_catalog'),
|
||||
path('houtai/club-kaohe-enable', ClubKaoheChenghaoEnableView.as_view(), name='jituan_club_kaohe_enable'),
|
||||
path('houtai/club-kaohe-disable', ClubKaoheChenghaoDisableView.as_view(), name='jituan_club_kaohe_disable'),
|
||||
path('club/list', ClubListView.as_view(), name='jituan_club_list'),
|
||||
]
|
||||
|
||||
194
jituan/views_club_catalog.py
Normal file
194
jituan/views_club_catalog.py
Normal file
@@ -0,0 +1,194 @@
|
||||
"""俱乐部商品类型 / 考核标签筛选配置 — 后台 API。"""
|
||||
from rest_framework.parsers import FormParser, JSONParser, MultiPartParser
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
|
||||
from backend.view import verify_kefu_permission
|
||||
|
||||
|
||||
class ClubShangpinLeixingListView(APIView):
|
||||
"""POST /jituan/houtai/club-leixing-list"""
|
||||
permission_classes = [IsAuthenticated]
|
||||
parser_classes = [JSONParser]
|
||||
|
||||
def post(self, request):
|
||||
phone = (request.data.get('phone') or request.data.get('username') or '').strip()
|
||||
if not phone:
|
||||
return Response({'code': 401, 'msg': '缺少客服账号'})
|
||||
kefu, permissions = verify_kefu_permission(request, phone)
|
||||
if kefu is None:
|
||||
return permissions
|
||||
if '8080a' not in permissions:
|
||||
return Response({'code': 403, 'msg': '无权限管理小程序商品类型'})
|
||||
from jituan.services.club_shangpin_leixing import build_club_leixing_admin_list
|
||||
payload = build_club_leixing_admin_list(request)
|
||||
return Response({'code': 0, 'data': payload})
|
||||
|
||||
|
||||
class ClubShangpinLeixingCatalogView(APIView):
|
||||
"""POST /jituan/houtai/club-leixing-catalog"""
|
||||
permission_classes = [IsAuthenticated]
|
||||
parser_classes = [JSONParser]
|
||||
|
||||
def post(self, request):
|
||||
phone = (request.data.get('phone') or request.data.get('username') or '').strip()
|
||||
if not phone:
|
||||
return Response({'code': 401, 'msg': '缺少客服账号'})
|
||||
kefu, permissions = verify_kefu_permission(request, phone)
|
||||
if kefu is None:
|
||||
return permissions
|
||||
if '8080a' not in permissions:
|
||||
return Response({'code': 403, 'msg': '无权限'})
|
||||
from jituan.services.club_shangpin_leixing import build_club_leixing_catalog
|
||||
return Response({'code': 0, 'data': build_club_leixing_catalog(request)})
|
||||
|
||||
|
||||
class ClubShangpinLeixingEnableView(APIView):
|
||||
"""POST /jituan/houtai/club-leixing-enable"""
|
||||
permission_classes = [IsAuthenticated]
|
||||
parser_classes = [JSONParser]
|
||||
|
||||
def post(self, request):
|
||||
phone = (request.data.get('phone') or request.data.get('username') or '').strip()
|
||||
leixing_id = request.data.get('leixing_id')
|
||||
if not phone or not leixing_id:
|
||||
return Response({'code': 400, 'msg': '参数不完整'})
|
||||
kefu, permissions = verify_kefu_permission(request, phone)
|
||||
if kefu is None:
|
||||
return permissions
|
||||
if '8080a' not in permissions:
|
||||
return Response({'code': 403, 'msg': '无权限'})
|
||||
from jituan.services.club_shangpin_leixing import enable_leixing_for_club
|
||||
data, err = enable_leixing_for_club(request, int(leixing_id), request.data.get('paixu'))
|
||||
if err:
|
||||
return Response({'code': 400, 'msg': err})
|
||||
return Response({'code': 0, 'msg': '上架成功', 'data': data})
|
||||
|
||||
|
||||
class ClubShangpinLeixingDisableView(APIView):
|
||||
"""POST /jituan/houtai/club-leixing-disable"""
|
||||
permission_classes = [IsAuthenticated]
|
||||
parser_classes = [JSONParser]
|
||||
|
||||
def post(self, request):
|
||||
phone = (request.data.get('phone') or request.data.get('username') or '').strip()
|
||||
leixing_id = request.data.get('leixing_id')
|
||||
if not phone or not leixing_id:
|
||||
return Response({'code': 400, 'msg': '参数不完整'})
|
||||
kefu, permissions = verify_kefu_permission(request, phone)
|
||||
if kefu is None:
|
||||
return permissions
|
||||
if '8080a' not in permissions:
|
||||
return Response({'code': 403, 'msg': '无权限'})
|
||||
from jituan.services.club_shangpin_leixing import disable_leixing_for_club
|
||||
data, err = disable_leixing_for_club(request, int(leixing_id))
|
||||
if err:
|
||||
return Response({'code': 400, 'msg': err})
|
||||
return Response({'code': 0, 'msg': '已下架', 'data': data})
|
||||
|
||||
|
||||
class ClubShangpinLeixingIconView(APIView):
|
||||
"""POST /jituan/houtai/club-leixing-icon"""
|
||||
permission_classes = [IsAuthenticated]
|
||||
parser_classes = [MultiPartParser, FormParser, JSONParser]
|
||||
|
||||
def post(self, request):
|
||||
phone = (request.data.get('phone') or request.data.get('username') or '').strip()
|
||||
leixing_id = request.data.get('leixing_id')
|
||||
file_obj = request.FILES.get('file')
|
||||
if not phone or not leixing_id or not file_obj:
|
||||
return Response({'code': 400, 'msg': '参数不完整'})
|
||||
kefu, permissions = verify_kefu_permission(request, phone)
|
||||
if kefu is None:
|
||||
return permissions
|
||||
if '8080a' not in permissions:
|
||||
return Response({'code': 403, 'msg': '无权限'})
|
||||
from jituan.services.club_shangpin_leixing import upload_leixing_icon
|
||||
data, err = upload_leixing_icon(request, int(leixing_id), file_obj)
|
||||
if err:
|
||||
return Response({'code': 400, 'msg': err})
|
||||
return Response({'code': 0, 'msg': '上传成功', 'data': data})
|
||||
|
||||
|
||||
class ClubKaoheChenghaoListView(APIView):
|
||||
"""POST /jituan/houtai/club-kaohe-list"""
|
||||
permission_classes = [IsAuthenticated]
|
||||
parser_classes = [JSONParser]
|
||||
|
||||
def post(self, request):
|
||||
phone = (request.data.get('phone') or request.data.get('username') or '').strip()
|
||||
if not phone:
|
||||
return Response({'code': 401, 'msg': '缺少客服账号'})
|
||||
kefu, permissions = verify_kefu_permission(request, phone)
|
||||
if kefu is None:
|
||||
return permissions
|
||||
if '8080a' not in permissions:
|
||||
return Response({'code': 403, 'msg': '无权限'})
|
||||
bankuai_id = request.data.get('bankuai_id')
|
||||
from jituan.services.club_kaohe_chenghao import build_club_kaohe_admin_list
|
||||
payload = build_club_kaohe_admin_list(request, bankuai_id=bankuai_id)
|
||||
return Response({'code': 0, 'data': payload})
|
||||
|
||||
|
||||
class ClubKaoheChenghaoCatalogView(APIView):
|
||||
"""POST /jituan/houtai/club-kaohe-catalog"""
|
||||
permission_classes = [IsAuthenticated]
|
||||
parser_classes = [JSONParser]
|
||||
|
||||
def post(self, request):
|
||||
phone = (request.data.get('phone') or request.data.get('username') or '').strip()
|
||||
if not phone:
|
||||
return Response({'code': 401, 'msg': '缺少客服账号'})
|
||||
kefu, permissions = verify_kefu_permission(request, phone)
|
||||
if kefu is None:
|
||||
return permissions
|
||||
if '8080a' not in permissions:
|
||||
return Response({'code': 403, 'msg': '无权限'})
|
||||
bankuai_id = request.data.get('bankuai_id')
|
||||
from jituan.services.club_kaohe_chenghao import build_club_kaohe_catalog
|
||||
return Response({'code': 0, 'data': build_club_kaohe_catalog(request, bankuai_id=bankuai_id)})
|
||||
|
||||
|
||||
class ClubKaoheChenghaoEnableView(APIView):
|
||||
"""POST /jituan/houtai/club-kaohe-enable"""
|
||||
permission_classes = [IsAuthenticated]
|
||||
parser_classes = [JSONParser]
|
||||
|
||||
def post(self, request):
|
||||
phone = (request.data.get('phone') or request.data.get('username') or '').strip()
|
||||
chenghao_id = request.data.get('chenghao_id')
|
||||
if not phone or not chenghao_id:
|
||||
return Response({'code': 400, 'msg': '参数不完整'})
|
||||
kefu, permissions = verify_kefu_permission(request, phone)
|
||||
if kefu is None:
|
||||
return permissions
|
||||
if '8080a' not in permissions:
|
||||
return Response({'code': 403, 'msg': '无权限'})
|
||||
from jituan.services.club_kaohe_chenghao import enable_chenghao_for_club
|
||||
data, err = enable_chenghao_for_club(request, int(chenghao_id))
|
||||
if err:
|
||||
return Response({'code': 400, 'msg': err})
|
||||
return Response({'code': 0, 'msg': '上架成功', 'data': data})
|
||||
|
||||
|
||||
class ClubKaoheChenghaoDisableView(APIView):
|
||||
"""POST /jituan/houtai/club-kaohe-disable"""
|
||||
permission_classes = [IsAuthenticated]
|
||||
parser_classes = [JSONParser]
|
||||
|
||||
def post(self, request):
|
||||
phone = (request.data.get('phone') or request.data.get('username') or '').strip()
|
||||
chenghao_id = request.data.get('chenghao_id')
|
||||
if not phone or not chenghao_id:
|
||||
return Response({'code': 400, 'msg': '参数不完整'})
|
||||
kefu, permissions = verify_kefu_permission(request, phone)
|
||||
if kefu is None:
|
||||
return permissions
|
||||
if '8080a' not in permissions:
|
||||
return Response({'code': 403, 'msg': '无权限'})
|
||||
from jituan.services.club_kaohe_chenghao import disable_chenghao_for_club
|
||||
data, err = disable_chenghao_for_club(request, int(chenghao_id))
|
||||
if err:
|
||||
return Response({'code': 400, 'msg': err})
|
||||
return Response({'code': 0, 'msg': '已下架', 'data': data})
|
||||
@@ -5784,27 +5784,13 @@ class DashouHuoquLeixingView(APIView):
|
||||
try:
|
||||
logger.info(f"打手获取商品类型请求 - 用户ID: {request.user.UserUID}")
|
||||
|
||||
# 排除审核专用类型(shenhezhuangtai=2),兼容历史数据 shenhezhuangtai 为空或 0
|
||||
leixing_queryset = ShangpinLeixing.query.exclude(
|
||||
shenhezhuangtai=2
|
||||
).order_by('-paixu', 'id')
|
||||
from jituan.services.club_context import resolve_effective_club_id
|
||||
from jituan.services.club_shangpin_leixing import build_club_leixing_list_for_api
|
||||
|
||||
# 🔴 构建返回数据列表
|
||||
leixing_list = []
|
||||
for leixing in leixing_queryset:
|
||||
leixing_list.append({
|
||||
"id": leixing.id,
|
||||
"jieshao": leixing.jieshao or "",
|
||||
"tupian_url": leixing.tupian_url or "",
|
||||
"yaoqiuleixing": leixing.yaoqiuleixing,
|
||||
"huiyuan_id": leixing.huiyuan_id,
|
||||
"yongjin": float(leixing.yongjin) if leixing.yongjin else None,
|
||||
"paixu": leixing.paixu or 0,
|
||||
"shenhezhuangtai": leixing.shenhezhuangtai or 1
|
||||
})
|
||||
club_id = resolve_effective_club_id(request, request.user)
|
||||
leixing_list = build_club_leixing_list_for_api(club_id)
|
||||
|
||||
# 🔴 记录日志
|
||||
logger.info(f"返回商品类型数据:{len(leixing_list)}条,用户: {request.user.UserUID}")
|
||||
logger.info(f"返回商品类型数据:{len(leixing_list)}条,俱乐部:{club_id} 用户: {request.user.UserUID}")
|
||||
|
||||
# 🔴 返回成功响应
|
||||
# 注意:保持与前端原数据格式完全一致
|
||||
|
||||
@@ -88,25 +88,20 @@ class ShangpinHuoquView(APIView):
|
||||
try:
|
||||
logger.info("收到商品数据获取请求")
|
||||
|
||||
# 1. 查询商品类型(只查询正常状态的类型,并排序)
|
||||
# 正常运营:只显示 shenhezhuangtai=2 的商品类型
|
||||
leixing_queryset = ShangpinLeixing.query.filter(
|
||||
shenhezhuangtai=1 # 只取正常状态
|
||||
).order_by('-paixu', 'id') # 先按paixu降序,再按id升序
|
||||
from jituan.services.club_context import resolve_effective_club_id
|
||||
from jituan.services.club_shangpin_leixing import build_club_leixing_list_for_api
|
||||
|
||||
# 注意:审核期间使用下面这行代码(先注释掉)
|
||||
'''leixing_queryset = ShangpinLeixing.query.filter(
|
||||
shenhezhuangtai=2 # 审核期间:只取审核专用状态
|
||||
).order_by('-paixu', 'id')'''
|
||||
|
||||
shangpinleixing_data = []
|
||||
for leixing in leixing_queryset:
|
||||
shangpinleixing_data.append({
|
||||
"id": leixing.id,
|
||||
"jieshao": leixing.jieshao,
|
||||
"tupian_url": leixing.tupian_url,
|
||||
"paixu": leixing.paixu
|
||||
})
|
||||
club_id = resolve_effective_club_id(request, getattr(request, 'user', None))
|
||||
leixing_rows = build_club_leixing_list_for_api(club_id)
|
||||
shangpinleixing_data = [
|
||||
{
|
||||
'id': row['id'],
|
||||
'jieshao': row['jieshao'],
|
||||
'tupian_url': row['tupian_url'],
|
||||
'paixu': row['paixu'],
|
||||
}
|
||||
for row in leixing_rows
|
||||
]
|
||||
|
||||
# 2. 查询商品专区(只查询可见类型下的专区,并排序)
|
||||
# 先获取可见的类型ID列表
|
||||
|
||||
@@ -76,9 +76,18 @@ class BankuaiBiaoqianView(APIView):
|
||||
return Response({'code': 0, 'data': {'biaoqian_list': []}})
|
||||
|
||||
# 获取该板块下所有类型的标签(leixing可以为dashou/shangjia等,这里先返回所有)
|
||||
chenghao_list = Chenghao.objects.filter(bankuai=bankuai)
|
||||
chenghao_list = Chenghao.objects.filter(bankuai=bankuai, leixing='dashou')
|
||||
data = []
|
||||
from jituan.services.club_context import resolve_effective_club_id
|
||||
from jituan.services.club_kaohe_chenghao import filter_chenghao_ids_for_pool
|
||||
|
||||
club_id = resolve_effective_club_id(request, request.user)
|
||||
allowed_ids = set(
|
||||
filter_chenghao_ids_for_pool(club_id, list(chenghao_list.values_list('id', flat=True)))
|
||||
)
|
||||
for ch in chenghao_list:
|
||||
if ch.id not in allowed_ids:
|
||||
continue
|
||||
texiao_json = {}
|
||||
if ch.texiao_miaoshu:
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user