新增 merchant_order_action_log,在结算/撤单/退款/罚单/派单/换打手成功路径写入真实操作人;提供 action-stats / action-operators 接口供经营数据页筛选统计。 Co-authored-by: Cursor <cursoragent@cursor.com>
252 lines
12 KiB
Python
252 lines
12 KiB
Python
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']),
|
||
]
|