diff --git a/backend/urls.py b/backend/urls.py index c178a91..466d624 100644 --- a/backend/urls.py +++ b/backend/urls.py @@ -14,7 +14,8 @@ from .view import (GetRolePermissionView, FineApplyView, PunishDashouView, FaKuanTongJiView, FaKuanLieBiaoView, FaKuanChuLiView, FaKuanChuangJianView, FaKuanPingTaiShenHeView, HqbkxxView,BkxgView,CaiwuView,CwhybkhqView, HybkjtsjView, SzxxView, CwddhqlxView, CwhqjtddsjView, - CwqtczhqView, KhpzhqView, ChzsgcView,KhgglView, ShgxgsjView, KhjlglView, KhjlczView, ZxkfghdsView) + CwqtczhqView, KhpzhqView, ChzsgcView,KhgglView, ShgxgsjView, KhjlglView, KhjlczView, ZxkfghdsView, + DashouGiftHuiyuanSaveView, DashouGiftHuiyuanRemoveView) from config.views import MiniappScriptHoutaiListView, MiniappScriptHoutaiModifyView from rank.reward_houtai_views import RankRewardHoutaiListView, RankRewardHoutaiSaveView, RankRewardHoutaiClaimsView @@ -30,6 +31,8 @@ urlpatterns = [ path('kefuhqdslb', KefuGetDashouListView.as_view(), name='客服获取打手数据'), path('kefuhqdsxq', KefuGetDashouDetailView.as_view(), name='客服获取打手具体信息'), path('kefuxgds', KefuUpdateDashouView.as_view(), name='客服修改打手数据'), + path('dszsonghy', DashouGiftHuiyuanSaveView.as_view(), name='打手赠送会员'), + path('dsycsonghy', DashouGiftHuiyuanRemoveView.as_view(), name='移除打手赠送会员'), path('hqsjgllb', KefuGetShangjiaListView.as_view(), name='后台获取商家列表'), path('hthqsjxq', KefuGetShangjiaDetailView.as_view(), name='后台获取商家详情'), path('xgsjxx', KefuUpdateShangjiaView.as_view(), name='后台修改商家数据'), diff --git a/backend/view.py b/backend/view.py index 0923bd1..12fe0cc 100644 --- a/backend/view.py +++ b/backend/view.py @@ -36,6 +36,7 @@ from .views.kefu import ( KefuGetDashouListView, KefuGetDashouDetailView, KefuUpdateDashouView, KefuGetShangjiaListView, KefuGetShangjiaDetailView, KefuUpdateShangjiaView, KefuChatPermissionsView, + DashouGiftHuiyuanSaveView, DashouGiftHuiyuanRemoveView, ) from .views.products import ( GetProductBaseDataView, GetProductListView, SaveProductOrderView, @@ -96,6 +97,7 @@ __all__ = [ 'GetAdminRolesView', 'GetAdminUserListView', 'ModifyAdminUserView', 'AddAdminUserView', # kefu 'KefuGetDashouListView', 'KefuGetDashouDetailView', 'KefuUpdateDashouView', + 'DashouGiftHuiyuanSaveView', 'DashouGiftHuiyuanRemoveView', 'KefuGetShangjiaListView', 'KefuGetShangjiaDetailView', 'KefuUpdateShangjiaView', 'KefuChatPermissionsView', # products diff --git a/backend/views/kefu.py b/backend/views/kefu.py index 8c1187c..8abfde9 100644 --- a/backend/views/kefu.py +++ b/backend/views/kefu.py @@ -304,6 +304,7 @@ class KefuGetDashouDetailView(APIView): 'data': { 'user_info': user_info, 'member_list': member_list, + 'gift_member_list': [], 'all_members': all_members, 'permissions': permissions, } @@ -369,11 +370,15 @@ class KefuGetDashouDetailView(APIView): # 7. 查询所有会员类型(用于前端添加会员) all_members = list(Huiyuan.query.all().values('huiyuan_id', 'jieshao')) + from jituan.services.gift_huiyuan import list_gift_huiyuan_for_admin + gift_member_list = list_gift_huiyuan_for_admin(uid) + return Response({ 'code': 0, 'data': { 'user_info': user_info, 'member_list': member_list, + 'gift_member_list': gift_member_list, 'all_members': all_members, 'permissions': permissions, # 返回当前客服的权限列表 } @@ -1150,6 +1155,223 @@ class KefuChatPermissionsView(APIView): }) +class DashouGiftHuiyuanSaveView(APIView): + """ + 赠送会员 / 改期(免费接单资格,写入 dashou_zengsong_huiyuan) + POST /houtai/dszsonghy + Body: { + phone, dashou_id, huiyuan_id, + daoqi_time: 'YYYY-MM-DD' 或 'YYYY-MM-DD HH:MM:SS', + id?: 已有记录ID(改期时建议传) + } + """ + permission_classes = [IsAuthenticated] + parser_classes = [JSONParser] + + def post(self, request): + from jituan.services.gift_huiyuan import ( + has_gift_huiyuan_permission, + parse_gift_daoqi_time, + upsert_gift_huiyuan, + update_gift_huiyuan_daoqi, + ) + from products.models import Huiyuan as HuiyuanModel + + phone = (request.data.get('phone') or request.data.get('username') or '').strip() + dashou_id = (request.data.get('dashou_id') or request.data.get('uid') or '').strip() + huiyuan_id = (request.data.get('huiyuan_id') or '').strip() + record_id = request.data.get('id') + raw_daoqi = request.data.get('daoqi_time') + + kefu, permissions = verify_kefu_permission(request, phone or None) + if kefu is None: + return permissions + if not has_gift_huiyuan_permission(permissions): + return Response({'code': 403, 'msg': '无赠送会员权限(需打手基础管理或加积分权限)'}) + + if not dashou_id: + return Response({'code': 400, 'msg': '缺少打手ID'}) + daoqi_time, err = parse_gift_daoqi_time(raw_daoqi) + if err: + return Response({'code': 400, 'msg': err}) + + try: + dashou_user = User.query.get(UserUID=dashou_id) + except User.DoesNotExist: + return Response({'code': 404, 'msg': '打手不存在'}) + denied = forbid_if_user_out_of_scope(request, dashou_user) + if denied: + return denied + try: + dashou_user.DashouProfile + except ObjectDoesNotExist: + return Response({'code': 404, 'msg': '该用户不是打手'}) + + song_ren = getattr(kefu.user, 'Phone', None) or phone + operator = song_ren + + # 有记录ID:只改期 + if record_id not in (None, ''): + try: + rid = int(record_id) + except (TypeError, ValueError): + return Response({'code': 400, 'msg': '无效的记录ID'}) + rec, err = update_gift_huiyuan_daoqi( + record_id=rid, + yonghu_id=dashou_id, + daoqi_time=daoqi_time, + song_ren=song_ren, + ) + if err: + return Response({'code': 400, 'msg': err}) + try: + hy_name = HuiyuanModel.query.get(huiyuan_id=rec.huiyuan_id).jieshao + except HuiyuanModel.DoesNotExist: + hy_name = rec.huiyuan_id + write_xiugai_log( + yonghuid=dashou_id, + xiugaiid=operator, + leixing=XIUGAI_LEIXING_DASHOU, + huiyuan_id=rec.huiyuan_id, + qitashuoming=( + f'【后台】修改赠送会员到期时间:会员ID={rec.huiyuan_id}({hy_name}),' + f'新到期={rec.daoqi_time.strftime("%Y-%m-%d %H:%M:%S")},' + f'打手ID={dashou_id},操作人={operator}' + ), + ) + return Response({ + 'code': 0, + 'msg': '改期成功', + 'data': { + 'id': rec.id, + 'huiyuan_id': rec.huiyuan_id, + 'daoqi_time': rec.daoqi_time.strftime('%Y-%m-%d %H:%M:%S'), + }, + }) + + if not huiyuan_id: + return Response({'code': 400, 'msg': '缺少会员ID'}) + + rec, created, jifen_info, err = upsert_gift_huiyuan( + yonghu_id=dashou_id, + huiyuan_id=huiyuan_id, + daoqi_time=daoqi_time, + song_ren=song_ren, + ) + if err: + return Response({'code': 400, 'msg': err}) + + try: + hy_name = HuiyuanModel.query.get(huiyuan_id=huiyuan_id).jieshao + except HuiyuanModel.DoesNotExist: + hy_name = huiyuan_id + + if jifen_info: + write_xiugai_log( + yonghuid=dashou_id, + xiugaiid=operator, + leixing=XIUGAI_LEIXING_DASHOU, + jifen=jifen_info['after'], + yjifen=jifen_info['before'], + qitashuoming=( + f'【后台】送会员时整改积分:{jifen_info["before"]} → {jifen_info["after"]},' + f'原积分={jifen_info["before"]},整改后={jifen_info["after"]},' + f'打手ID={dashou_id},操作人={operator}(送会员免费接单)' + ), + ) + + action_label = '赠送' if created else '更新到期时间' + write_xiugai_log( + yonghuid=dashou_id, + xiugaiid=operator, + leixing=XIUGAI_LEIXING_DASHOU, + huiyuan_id=huiyuan_id, + qitashuoming=( + f'【后台】{action_label}赠送会员(免费接单):会员ID={huiyuan_id}({hy_name}),' + f'到期={rec.daoqi_time.strftime("%Y-%m-%d %H:%M:%S")},' + f'打手ID={dashou_id},操作人={operator}(写入赠送会员表,非购买会员)' + ), + ) + return Response({ + 'code': 0, + 'msg': '赠送成功' if created else '到期时间已更新', + 'data': { + 'id': rec.id, + 'huiyuan_id': rec.huiyuan_id, + 'daoqi_time': rec.daoqi_time.strftime('%Y-%m-%d %H:%M:%S'), + 'created': created, + 'jifen_adjusted': bool(jifen_info), + 'jifen': jifen_info, + }, + }) + + +class DashouGiftHuiyuanRemoveView(APIView): + """ + 移除赠送会员 + POST /houtai/dsycsonghy + Body: { phone, dashou_id, id? , huiyuan_id? } + """ + permission_classes = [IsAuthenticated] + parser_classes = [JSONParser] + + def post(self, request): + from jituan.services.gift_huiyuan import ( + has_gift_huiyuan_permission, + remove_gift_huiyuan, + ) + + phone = (request.data.get('phone') or request.data.get('username') or '').strip() + dashou_id = (request.data.get('dashou_id') or request.data.get('uid') or '').strip() + record_id = request.data.get('id') + huiyuan_id = (request.data.get('huiyuan_id') or '').strip() + + kefu, permissions = verify_kefu_permission(request, phone or None) + if kefu is None: + return permissions + if not has_gift_huiyuan_permission(permissions): + return Response({'code': 403, 'msg': '无移除赠送会员权限'}) + + if not dashou_id: + return Response({'code': 400, 'msg': '缺少打手ID'}) + + try: + dashou_user = User.query.get(UserUID=dashou_id) + except User.DoesNotExist: + return Response({'code': 404, 'msg': '打手不存在'}) + denied = forbid_if_user_out_of_scope(request, dashou_user) + if denied: + return denied + + rid = None + if record_id not in (None, ''): + try: + rid = int(record_id) + except (TypeError, ValueError): + return Response({'code': 400, 'msg': '无效的记录ID'}) + + ok, err = remove_gift_huiyuan( + record_id=rid, + yonghu_id=dashou_id if not rid else None, + huiyuan_id=huiyuan_id if not rid else None, + ) + if err: + return Response({'code': 400, 'msg': err}) + + operator = getattr(kefu.user, 'Phone', None) or phone + write_xiugai_log( + yonghuid=dashou_id, + xiugaiid=operator, + leixing=XIUGAI_LEIXING_DASHOU, + huiyuan_id=huiyuan_id or '', + qitashuoming=( + f'【后台】移除赠送会员(免费接单):记录ID={rid or "-"},' + f'会员ID={huiyuan_id or "-"},打手ID={dashou_id},操作人={operator}' + ), + ) + return Response({'code': 0, 'msg': '移除成功'}) + + diff --git a/jituan/services/gift_huiyuan.py b/jituan/services/gift_huiyuan.py new file mode 100644 index 0000000..3f7f07e --- /dev/null +++ b/jituan/services/gift_huiyuan.py @@ -0,0 +1,240 @@ +"""后台赠送会员(免费接单):与购买会员 Huiyuangoumai 分离。""" +from datetime import datetime, time + +from django.db import transaction +from django.utils import timezone +from django.utils.dateparse import parse_datetime, parse_date + +from products.models import Huiyuan +from users.models import DashouZengsongHuiyuan, UserDashou + +GIFT_HUIYUAN_PERMS = frozenset({ + '000001', '001aa', '001bb', '001cc', '001dd', '001ee', +}) +TARGET_JIFEN_ON_GIFT = 10 + + +def has_gift_huiyuan_permission(permissions): + return any(p in (permissions or []) for p in GIFT_HUIYUAN_PERMS) + + +def _gift_record_active(record, now=None): + if not record or not record.daoqi_time: + return False + from jituan.services.huiyuan_bundle import _normalize_datetime_for_compare + now = _normalize_datetime_for_compare(now or timezone.now()) + daoqi = _normalize_datetime_for_compare(record.daoqi_time) + return daoqi > now + + +def parse_gift_daoqi_time(raw): + """ + 解析到期时间。 + 支持:'YYYY-MM-DD HH:MM:SS' / ISO / 'YYYY-MM-DD'(当天 23:59:59)。 + """ + if raw is None or str(raw).strip() == '': + return None, '请填写到期时间' + text = str(raw).strip() + dt = parse_datetime(text.replace('/', '-')) + if dt is None: + d = parse_date(text.replace('/', '-')) + if d is None: + try: + dt = datetime.strptime(text, '%Y-%m-%d %H:%M:%S') + except ValueError: + try: + d = datetime.strptime(text, '%Y-%m-%d').date() + except ValueError: + return None, '到期时间格式错误,请用 YYYY-MM-DD 或 YYYY-MM-DD HH:MM:SS' + dt = datetime.combine(d, time(23, 59, 59)) + else: + dt = datetime.combine(d, time(23, 59, 59)) + if timezone.is_naive(dt) and timezone.is_aware(timezone.now()): + dt = timezone.make_aware(dt, timezone.get_current_timezone()) + elif (not timezone.is_naive(dt)) and (not timezone.is_aware(timezone.now())): + dt = timezone.make_naive(dt, timezone.get_current_timezone()) + if dt <= timezone.now(): + return None, '到期时间必须晚于当前时间' + return dt, None + + +def list_gift_huiyuan_for_admin(yonghu_id): + """后台详情:全部赠送记录(含已过期),附会员名。""" + records = list( + DashouZengsongHuiyuan.query.filter(yonghu_id=yonghu_id).order_by('-daoqi_time') + ) + if not records: + return [] + name_map = { + h.huiyuan_id: h.jieshao + for h in Huiyuan.query.filter( + huiyuan_id__in=[r.huiyuan_id for r in records] + ).only('huiyuan_id', 'jieshao') + } + now = timezone.now() + out = [] + for r in records: + active = _gift_record_active(r, now=now) + out.append({ + 'id': r.id, + 'huiyuan_id': r.huiyuan_id, + 'huiyuan_name': name_map.get(r.huiyuan_id, f'会员{r.huiyuan_id}'), + 'daoqi_time': r.daoqi_time.strftime('%Y-%m-%d %H:%M:%S') if r.daoqi_time else '', + 'song_ren': r.song_ren or '', + 'song_time': r.CreateTime.strftime('%Y-%m-%d %H:%M:%S') if r.CreateTime else '', + 'is_active': active, + }) + return out + + +def user_has_gift_huiyuan_access(yonghu_id, required_huiyuan_id, club_id=None): + """抢单资格:赠送会员是否覆盖所需会员类型(支持总会员展开)。""" + from jituan.services.huiyuan_bundle import ( + huiyuan_ids_match, + is_bundle_huiyuan, + normalize_huiyuan_id, + resolve_bundle_included_ids, + _included_huiyuan_id_set, + ) + + req = normalize_huiyuan_id(required_huiyuan_id) + if not req: + return True + req_set = {req, req.lstrip('0') or '0'} + now = timezone.now() + for rec in DashouZengsongHuiyuan.query.filter(yonghu_id=yonghu_id): + if not _gift_record_active(rec, now=now): + continue + if huiyuan_ids_match(rec.huiyuan_id, req): + return True + if is_bundle_huiyuan(rec.huiyuan_id): + included = resolve_bundle_included_ids( + rec.huiyuan_id, + club_id=club_id, + yonghu_id=yonghu_id, + ) + if req_set & _included_huiyuan_id_set(included): + return True + return False + + +def build_gift_clumber_items(yonghu_id, club_id=None): + """抢单池 clumber:未过期赠送会员条目。""" + from jituan.services.huiyuan_bundle import ( + _append_bundle_sub_clumber, + _append_clumber_id_variants, + format_legacy_daoqi, + is_bundle_huiyuan, + resolve_bundle_included_ids, + _resolve_user_club_id, + ) + + items = [] + seen = set() + effective_club = _resolve_user_club_id(yonghu_id, club_id) + now = timezone.now() + for rec in DashouZengsongHuiyuan.query.filter(yonghu_id=yonghu_id): + if not _gift_record_active(rec, now=now): + continue + try: + hy = Huiyuan.query.get(huiyuan_id=rec.huiyuan_id) + ming = hy.jieshao or f'会员{rec.huiyuan_id}' + except Huiyuan.DoesNotExist: + ming = f'会员{rec.huiyuan_id}' + base = { + 'huiyuanming': ming, + 'daoqi': format_legacy_daoqi(rec.daoqi_time), + 'huiyuan_zhuangtai': 1, + 'shifou_daoqi': False, + 'is_gift': True, + } + if is_bundle_huiyuan(rec.huiyuan_id): + base['is_bundle'] = True + base['bundle_huiyuan_id'] = rec.huiyuan_id + base['included_huiyuan_ids'] = resolve_bundle_included_ids( + rec.huiyuan_id, + club_id=effective_club, + yonghu_id=yonghu_id, + ) + _append_clumber_id_variants(items, seen, base, rec.huiyuan_id) + _append_bundle_sub_clumber(items, seen, base) + return items + + +def upsert_gift_huiyuan(*, yonghu_id, huiyuan_id, daoqi_time, song_ren): + """ + 赠送或改期。同一打手同一会员类型仅一条记录。 + 返回 (record, created, jifen_changed_info_or_None, error_msg) + jifen_changed_info = {'before': x, 'after': 10} 若调整了积分 + """ + huiyuan_id = str(huiyuan_id or '').strip() + if not huiyuan_id: + return None, False, None, '缺少会员ID' + if not Huiyuan.query.filter(huiyuan_id=huiyuan_id).exists(): + return None, False, None, '会员类型不存在' + + jifen_info = None + with transaction.atomic(): + try: + dashou = UserDashou.objects.select_for_update().select_related('user').get( + user__UserUID=yonghu_id + ) + except UserDashou.DoesNotExist: + return None, False, None, '打手不存在' + + before_jifen = int(dashou.jifen or 0) + if before_jifen != TARGET_JIFEN_ON_GIFT: + dashou.jifen = TARGET_JIFEN_ON_GIFT + dashou.save(update_fields=['jifen']) + jifen_info = {'before': before_jifen, 'after': TARGET_JIFEN_ON_GIFT} + + locked_qs = DashouZengsongHuiyuan.objects.select_for_update().filter( + yonghu_id=yonghu_id, huiyuan_id=huiyuan_id + ) + existing = locked_qs.first() + if existing: + existing.daoqi_time = daoqi_time + existing.song_ren = song_ren + existing.save(update_fields=['daoqi_time', 'song_ren', 'UpdateTime']) + return existing, False, jifen_info, None + + record = DashouZengsongHuiyuan.query.create( + yonghu_id=yonghu_id, + huiyuan_id=huiyuan_id, + daoqi_time=daoqi_time, + song_ren=song_ren, + ) + return record, True, jifen_info, None + + +def update_gift_huiyuan_daoqi(*, record_id, yonghu_id, daoqi_time, song_ren): + """按记录 ID 改期。""" + try: + rec = DashouZengsongHuiyuan.query.get(id=record_id) + except DashouZengsongHuiyuan.DoesNotExist: + return None, '赠送会员记录不存在' + if str(rec.yonghu_id) != str(yonghu_id): + return None, '记录与打手不匹配' + rec.daoqi_time = daoqi_time + if song_ren: + rec.song_ren = song_ren + rec.save(update_fields=['daoqi_time', 'song_ren', 'UpdateTime']) + return rec, None + + +def remove_gift_huiyuan(*, record_id=None, yonghu_id=None, huiyuan_id=None): + """按记录 ID,或 (yonghu_id, huiyuan_id) 移除。""" + qs = DashouZengsongHuiyuan.query + if record_id: + deleted, _ = qs.filter(id=record_id).delete() + if not deleted: + return False, '赠送会员记录不存在' + return True, None + yonghu_id = str(yonghu_id or '').strip() + huiyuan_id = str(huiyuan_id or '').strip() + if not yonghu_id or not huiyuan_id: + return False, '缺少记录ID或会员ID' + deleted, _ = qs.filter(yonghu_id=yonghu_id, huiyuan_id=huiyuan_id).delete() + if not deleted: + return False, '赠送会员记录不存在' + return True, None diff --git a/jituan/services/huiyuan_bundle.py b/jituan/services/huiyuan_bundle.py index 018e621..3af7512 100644 --- a/jituan/services/huiyuan_bundle.py +++ b/jituan/services/huiyuan_bundle.py @@ -231,6 +231,10 @@ def user_has_huiyuan_access(yonghu_id, required_huiyuan_id, club_id=None): if _czjilu_grants_huiyuan_access(yonghu_id, req, club_id): return True + + from jituan.services.gift_huiyuan import user_has_gift_huiyuan_access + if user_has_gift_huiyuan_access(yonghu_id, req, club_id=club_id): + return True return False @@ -498,26 +502,33 @@ def _build_clumber_from_paid_czjilu(yonghu_id, club_id=None): def _finalize_clumber_for_legacy_client(items): - """老端只认 huiyuanid;去掉 is_trial 等内部字段。""" + """老端只认 huiyuanid;去掉 is_trial / is_gift 等内部字段。""" cleaned = [] for it in items or []: row = dict(it) row.pop('is_trial', None) + row.pop('is_gift', None) cleaned.append(row) return cleaned def ensure_grab_pool_clumber(yonghu_id, club_id=None): """ - dddhq / dashouxinxi:只读 huiyuangoumai + 有效期内充值单 生成 clumber(体验=正式)。 + dddhq / dashouxinxi:只读 huiyuangoumai + 有效期内充值单 + 赠送会员 生成 clumber。 总会员展开子会员虚拟条目供老端 clumber 比对;不写库、不补开通。 """ + from jituan.services.gift_huiyuan import build_gift_clumber_items + effective_club = _resolve_user_club_id(yonghu_id, club_id) items = _build_user_clumber_core(yonghu_id, club_id=effective_club) items = _merge_clumber_extra_items( items, _build_clumber_from_paid_czjilu(yonghu_id, club_id=effective_club), ) + items = _merge_clumber_extra_items( + items, + build_gift_clumber_items(yonghu_id, club_id=effective_club), + ) items = _finalize_clumber_for_legacy_client(items) return bool(items), items diff --git a/users/migrations/0005_dashou_zengsong_huiyuan.py b/users/migrations/0005_dashou_zengsong_huiyuan.py new file mode 100644 index 0000000..5e7a712 --- /dev/null +++ b/users/migrations/0005_dashou_zengsong_huiyuan.py @@ -0,0 +1,33 @@ +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0004_user_shangjia_youzhi'), + ] + + operations = [ + migrations.CreateModel( + name='DashouZengsongHuiyuan', + fields=[ + ('id', models.AutoField(primary_key=True, serialize=False, verbose_name='记录ID')), + ('yonghu_id', models.CharField(db_index=True, max_length=7, verbose_name='打手用户ID')), + ('huiyuan_id', models.CharField(db_index=True, max_length=6, verbose_name='会员ID')), + ('daoqi_time', models.DateTimeField(db_index=True, verbose_name='到期时间')), + ('song_ren', models.CharField(max_length=30, verbose_name='赠送人账号')), + ('CreateTime', models.DateTimeField(auto_now_add=True, verbose_name='赠送时间')), + ('UpdateTime', models.DateTimeField(auto_now=True, verbose_name='更新时间')), + ], + options={ + 'verbose_name': '打手赠送会员', + 'verbose_name_plural': '打手赠送会员', + 'db_table': 'dashou_zengsong_huiyuan', + 'indexes': [ + models.Index(fields=['yonghu_id', 'huiyuan_id'], name='dashou_zeng_yonghu__7a1c01_idx'), + models.Index(fields=['yonghu_id', 'daoqi_time'], name='dashou_zeng_yonghu__8b2d02_idx'), + ], + 'unique_together': {('yonghu_id', 'huiyuan_id')}, + }, + ), + ] diff --git a/users/models.py b/users/models.py index 82088dd..567c360 100644 --- a/users/models.py +++ b/users/models.py @@ -553,7 +553,31 @@ class Xiugaijilu(QModel): return f"修改记录-用户{self.yonghuid}" +class DashouZengsongHuiyuan(QModel): + """ + 后台赠送会员(免费接单资格),与 Huiyuangoumai 购买会员完全分离。 + 仅用于抢单/抢单池资格;不参与提现正式会员校验。 + """ + id = models.AutoField(primary_key=True, verbose_name='记录ID') + yonghu_id = models.CharField(max_length=7, db_index=True, verbose_name='打手用户ID') + huiyuan_id = models.CharField(max_length=6, db_index=True, verbose_name='会员ID') + daoqi_time = models.DateTimeField(db_index=True, verbose_name='到期时间') + song_ren = models.CharField(max_length=30, verbose_name='赠送人账号') + CreateTime = models.DateTimeField(auto_now_add=True, verbose_name='赠送时间') + UpdateTime = models.DateTimeField(auto_now=True, verbose_name='更新时间') + class Meta: + db_table = 'dashou_zengsong_huiyuan' + verbose_name = '打手赠送会员' + verbose_name_plural = verbose_name + unique_together = [['yonghu_id', 'huiyuan_id']] + indexes = [ + models.Index(fields=['yonghu_id', 'huiyuan_id']), + models.Index(fields=['yonghu_id', 'daoqi_time']), + ] + + def __str__(self): + return f"赠送会员-用户{self.yonghu_id}-会员{self.huiyuan_id}" # yonghu/models.py - 新增排行榜模型