Files
Django/merchant_ops/models.py
XingQue 9c029288ba feat(merchant): 订单操作流水表与按真实操作人统计
新增 merchant_order_action_log,在结算/撤单/退款/罚单/派单/换打手成功路径写入真实操作人;提供 action-stats / action-operators 接口供经营数据页筛选统计。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-15 23:42:39 +08:00

252 lines
12 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from decimal import Decimal
from django.db import models
from gvsdsdk.model_base import QModel
class MerchantStaffPermission(QModel):
"""权限字典(全局码表)"""
perm_code = models.CharField(max_length=64, unique=True, verbose_name='权限码')
perm_name = models.CharField(max_length=64, verbose_name='权限名称')
sort_order = models.IntegerField(default=0, verbose_name='排序')
status = models.IntegerField(default=1, verbose_name='1启用0停用')
CreateTime = models.DateTimeField(auto_now_add=True)
UpdateTime = models.DateTimeField(auto_now=True)
class Meta:
db_table = 'merchant_staff_permission'
verbose_name = '商家客服权限字典'
class MerchantStaffRole(QModel):
"""商家内角色merchant_id 为空表示系统模板)"""
club_id = models.CharField(max_length=16, default='xq', verbose_name='Club')
merchant_id = models.CharField(
max_length=7, null=True, blank=True, db_index=True, verbose_name='商家ID'
)
role_code = models.CharField(max_length=32, verbose_name='角色码')
role_name = models.CharField(max_length=64, verbose_name='角色名')
is_system = models.BooleanField(default=False, verbose_name='系统预置')
sort_order = models.IntegerField(default=0)
status = models.IntegerField(default=1, verbose_name='1启用0停用')
CreateTime = models.DateTimeField(auto_now_add=True)
UpdateTime = models.DateTimeField(auto_now=True)
class Meta:
db_table = 'merchant_staff_role'
verbose_name = '商家客服角色'
unique_together = [['merchant_id', 'role_code']]
class MerchantStaffRolePermission(QModel):
role = models.ForeignKey(
MerchantStaffRole, on_delete=models.CASCADE, related_name='role_permissions'
)
perm_code = models.CharField(max_length=64, db_index=True)
class Meta:
db_table = 'merchant_staff_role_permission'
unique_together = [['role', 'perm_code']]
class MerchantStaffInvite(QModel):
club_id = models.CharField(max_length=16, default='xq')
merchant_id = models.CharField(max_length=7, db_index=True, verbose_name='商家ID')
invite_code = models.CharField(max_length=32, unique=True, verbose_name='邀请码')
role = models.ForeignKey(
MerchantStaffRole, null=True, blank=True, on_delete=models.SET_NULL,
verbose_name='预绑角色'
)
status = models.IntegerField(default=0, verbose_name='0未用1已用2作废3过期')
created_by = models.CharField(max_length=7, verbose_name='创建人')
used_by = models.CharField(max_length=7, null=True, blank=True)
used_at = models.DateTimeField(null=True, blank=True)
expire_at = models.DateTimeField(null=True, blank=True)
CreateTime = models.DateTimeField(auto_now_add=True)
UpdateTime = models.DateTimeField(auto_now=True)
class Meta:
db_table = 'merchant_staff_invite'
indexes = [
models.Index(fields=['merchant_id', 'status', '-CreateTime']),
]
class MerchantStaffMember(QModel):
club_id = models.CharField(max_length=16, default='xq')
merchant_id = models.CharField(max_length=7, db_index=True)
staff_user_id = models.CharField(max_length=7, db_index=True)
role = models.ForeignKey(MerchantStaffRole, on_delete=models.PROTECT)
status = models.IntegerField(default=1, verbose_name='1正常0停用2已移除')
display_name = models.CharField(max_length=64, blank=True, default='')
merchant_remark = models.CharField(max_length=64, blank=True, default='', verbose_name='商家备注')
invited_by_code = models.ForeignKey(
MerchantStaffInvite, null=True, blank=True, on_delete=models.SET_NULL
)
joined_at = models.DateTimeField(auto_now_add=True)
revoked_at = models.DateTimeField(null=True, blank=True)
today_dispatch_count = models.IntegerField(default=0)
today_dispatch_amount = models.DecimalField(max_digits=12, decimal_places=2, default=Decimal('0.00'))
CreateTime = models.DateTimeField(auto_now_add=True)
UpdateTime = models.DateTimeField(auto_now=True)
class Meta:
db_table = 'merchant_staff_member'
unique_together = [['merchant_id', 'staff_user_id']]
indexes = [
models.Index(fields=['staff_user_id', 'status']),
]
class MerchantStaffMemberPermission(QModel):
member = models.ForeignKey(
MerchantStaffMember, on_delete=models.CASCADE, related_name='member_permissions'
)
perm_code = models.CharField(max_length=64)
granted = models.BooleanField(default=True, verbose_name='True授予False禁止')
class Meta:
db_table = 'merchant_staff_member_permission'
unique_together = [['member', 'perm_code']]
class MerchantStaffWallet(QModel):
merchant_id = models.CharField(max_length=7, db_index=True)
staff_user_id = models.CharField(max_length=7, db_index=True)
member = models.ForeignKey(
MerchantStaffMember, on_delete=models.CASCADE, related_name='wallets'
)
quota_total = models.DecimalField(max_digits=12, decimal_places=2, default=Decimal('0.00'))
quota_used = models.DecimalField(max_digits=12, decimal_places=2, default=Decimal('0.00'))
quota_frozen = models.DecimalField(max_digits=12, decimal_places=2, default=Decimal('0.00'))
UpdateTime = models.DateTimeField(auto_now=True)
CreateTime = models.DateTimeField(auto_now_add=True)
class Meta:
db_table = 'merchant_staff_wallet'
unique_together = [['merchant_id', 'staff_user_id']]
@property
def quota_available(self):
return self.quota_total - self.quota_used - self.quota_frozen
class MerchantStaffWalletLedger(QModel):
wallet = models.ForeignKey(MerchantStaffWallet, on_delete=models.CASCADE, related_name='ledgers')
merchant_id = models.CharField(max_length=7, db_index=True)
staff_user_id = models.CharField(max_length=7, db_index=True)
change_type = models.CharField(max_length=32)
amount = models.DecimalField(max_digits=12, decimal_places=2)
balance_after = models.DecimalField(max_digits=12, decimal_places=2)
related_order_id = models.CharField(max_length=32, null=True, blank=True)
operator_id = models.CharField(max_length=7)
remark = models.CharField(max_length=255, blank=True, default='')
CreateTime = models.DateTimeField(auto_now_add=True)
class Meta:
db_table = 'merchant_staff_wallet_ledger'
indexes = [models.Index(fields=['merchant_id', '-CreateTime'])]
class MerchantStaffDailyStats(QModel):
club_id = models.CharField(max_length=16, default='xq')
merchant_id = models.CharField(max_length=7, db_index=True)
staff_user_id = models.CharField(max_length=7, db_index=True)
member_id = models.BigIntegerField(db_index=True)
stat_date = models.DateField(db_index=True)
year = models.PositiveSmallIntegerField()
month = models.PositiveSmallIntegerField()
day = models.PositiveSmallIntegerField()
dispatch_count = models.IntegerField(default=0)
dispatch_amount = models.DecimalField(max_digits=12, decimal_places=2, default=Decimal('0.00'))
settle_count = models.IntegerField(default=0)
settle_amount = models.DecimalField(max_digits=12, decimal_places=2, default=Decimal('0.00'))
refund_count = models.IntegerField(default=0)
refund_amount = models.DecimalField(max_digits=12, decimal_places=2, default=Decimal('0.00'))
cancel_count = models.IntegerField(default=0)
penalty_count = models.IntegerField(default=0)
CreateTime = models.DateTimeField(auto_now_add=True)
UpdateTime = models.DateTimeField(auto_now=True)
class Meta:
db_table = 'merchant_staff_ri_tongji'
unique_together = [['merchant_id', 'staff_user_id', 'stat_date']]
indexes = [
models.Index(fields=['merchant_id', 'stat_date', '-dispatch_count']),
]
class MerchantOrderDispatch(QModel):
"""订单派单归属(不修改 orders 表)"""
order_id = models.CharField(max_length=32, unique=True, db_index=True)
merchant_id = models.CharField(max_length=7, db_index=True)
dispatch_actor_type = models.CharField(max_length=16, verbose_name='MERCHANT/STAFF')
dispatch_actor_id = models.CharField(max_length=7)
staff_member_id = models.BigIntegerField(null=True, blank=True, db_index=True)
CreateTime = models.DateTimeField(auto_now_add=True)
class Meta:
db_table = 'merchant_order_dispatch'
class MerchantStaffAuditLog(QModel):
merchant_id = models.CharField(max_length=7, db_index=True)
operator_user_id = models.CharField(max_length=7, db_index=True)
operator_type = models.CharField(max_length=16, verbose_name='MERCHANT_OWNER/STAFF')
staff_member_id = models.BigIntegerField(null=True, blank=True)
action = models.CharField(max_length=64, db_index=True)
resource_type = models.CharField(max_length=32, blank=True, default='')
resource_id = models.CharField(max_length=64, blank=True, default='')
value_before = models.JSONField(null=True, blank=True)
value_after = models.JSONField(null=True, blank=True)
amount = models.DecimalField(max_digits=12, decimal_places=2, null=True, blank=True)
request_ip = models.CharField(max_length=64, blank=True, default='')
remark = models.CharField(max_length=500, blank=True, default='')
CreateTime = models.DateTimeField(auto_now_add=True)
class Meta:
db_table = 'merchant_staff_audit_log'
indexes = [models.Index(fields=['merchant_id', '-CreateTime'])]
class MerchantDispatchTemplate(QModel):
merchant_id = models.CharField(max_length=7, db_index=True)
template_name = models.CharField(max_length=128)
template_type = models.CharField(max_length=16, default='EXPRESS')
payload_json = models.JSONField(default=dict)
created_by = models.CharField(max_length=7)
created_by_type = models.CharField(max_length=16, default='MERCHANT')
status = models.IntegerField(default=1)
use_count = models.IntegerField(default=0)
CreateTime = models.DateTimeField(auto_now_add=True)
UpdateTime = models.DateTimeField(auto_now=True)
class Meta:
db_table = 'merchant_dispatch_template'
class MerchantOrderActionLog(QModel):
"""商家侧订单操作流水:同一订单可多次记录,按真实操作人统计。"""
club_id = models.CharField(max_length=16, default='xq', db_index=True)
merchant_id = models.CharField(max_length=7, db_index=True)
order_id = models.CharField(max_length=32, db_index=True)
action_code = models.PositiveSmallIntegerField(db_index=True, verbose_name='行为码')
operator_user_id = models.CharField(max_length=7, db_index=True)
operator_type = models.CharField(max_length=16, verbose_name='MERCHANT/STAFF')
staff_member_id = models.BigIntegerField(null=True, blank=True, db_index=True)
role_code = models.CharField(max_length=32, blank=True, default='')
role_name = models.CharField(max_length=64, blank=True, default='')
amount = models.DecimalField(max_digits=12, decimal_places=2, null=True, blank=True)
leixing_id = models.IntegerField(null=True, blank=True, db_index=True)
remark = models.CharField(max_length=500, blank=True, default='')
CreateTime = models.DateTimeField(auto_now_add=True, db_index=True)
class Meta:
db_table = 'merchant_order_action_log'
verbose_name = '商家订单操作流水'
indexes = [
models.Index(fields=['merchant_id', 'operator_user_id', '-CreateTime']),
models.Index(fields=['merchant_id', 'action_code', '-CreateTime']),
models.Index(fields=['merchant_id', 'leixing_id', '-CreateTime']),
]