"""操作审计。""" from decimal import Decimal from merchant_ops.constants import ACTOR_MERCHANT, ACTOR_STAFF, AUDIT_ACTION_LABELS from merchant_ops.models import MerchantStaffAuditLog, MerchantStaffMember def write_audit( merchant_id, operator_user_id, operator_type, action, *, staff_member_id=None, resource_type='', resource_id='', value_before=None, value_after=None, amount=None, request_ip='', remark='', ): MerchantStaffAuditLog.objects.create( merchant_id=merchant_id, operator_user_id=operator_user_id, operator_type=operator_type, staff_member_id=staff_member_id, action=action, resource_type=resource_type, resource_id=str(resource_id) if resource_id else '', value_before=value_before, value_after=value_after, amount=Decimal(str(amount)) if amount is not None else None, request_ip=request_ip or '', remark=remark or '', ) def audit_staff(member, action, request, **kwargs): write_audit( member.merchant_id, member.staff_user_id, ACTOR_STAFF, action, staff_member_id=member.id, request_ip=_client_ip(request), **kwargs, ) def audit_owner(merchant_id, operator_id, action, request, **kwargs): write_audit( merchant_id, operator_id, ACTOR_MERCHANT, action, request_ip=_client_ip(request), **kwargs, ) def _client_ip(request): xff = request.META.get('HTTP_X_FORWARDED_FOR') if xff: return xff.split(',')[0].strip() return request.META.get('REMOTE_ADDR', '') or '' def audit_action_label(action): return AUDIT_ACTION_LABELS.get(action, action) def serialize_audit_row(row, member_map=None): """格式化审计记录供前端展示。""" member_map = member_map or {} label = audit_action_label(row.action) operator_name = '商家老板' role_name = '' if row.operator_type == ACTOR_STAFF and row.staff_member_id: m = member_map.get(row.staff_member_id) if m: operator_name = m.display_name or m.staff_user_id role_name = m.role.role_name if m.role else '' else: operator_name = row.operator_user_id elif row.operator_type == ACTOR_MERCHANT: operator_name = '商家老板' return { 'id': row.id, 'operator_user_id': row.operator_user_id, 'operator_type': row.operator_type, 'operator_name': operator_name, 'role_name': role_name, 'action': row.action, 'action_label': label, 'resource_type': row.resource_type, 'resource_id': row.resource_id, 'amount': str(row.amount) if row.amount is not None else '', 'remark': row.remark, 'time': row.CreateTime.strftime('%Y-%m-%d %H:%M:%S') if row.CreateTime else '', }