from app.extensions import db, beijing_time import json def _beijing_now(): """ 统一时间口径:naive 北京时间,与 created_at / OutboundApproval / BorrowApproval 一致。 ★ 原先返回 tz-aware 时间,配合 timestamptz 列才正确;现已将该表列类型统一为 timestamp without time zone(见 db_migrations/unify_approval_timezone.sql), 故此处必须返回 naive 值,否则存库会被当 UTC 处理而早 8 小时。 """ return beijing_time() class ScrapApproval(db.Model): """ 报废申请/审批单(镜像 BorrowApproval / OutboundApproval) 与出/借库的关键差异:items_json 里每条明细必须携带 source_table + stock_id(精准定位到某条实物库存记录), 因为报废从“申请那一刻”就要求指明具体要报废的东西。 """ __tablename__ = 'scrap_approval' id = db.Column(db.Integer, primary_key=True) request_no = db.Column(db.String(100), unique=True, nullable=False, index=True) applicant_id = db.Column(db.Integer, nullable=False, index=True) remark = db.Column(db.Text) # 报废原因 # 状态: 0-待审批, 1-已通过(待执行), 2-已驳回, 3-已执行(已报废) status = db.Column(db.Integer, default=0, nullable=False, index=True) allowed_approvers = db.Column(db.Text) # JSON: [{"type":"user","value":123}, ...] actual_approver_id = db.Column(db.Integer, index=True) approved_at = db.Column(db.DateTime) reject_reason = db.Column(db.Text) # 明细快照: [{"source_table","stock_id","sku","name","spec_model","location","batch_number","scrap_qty"}] items_json = db.Column(db.Text, nullable=False) # 执行信息 executed_at = db.Column(db.DateTime) executor_name = db.Column(db.String(100)) created_at = db.Column(db.DateTime, default=_beijing_now, nullable=False) updated_at = db.Column(db.DateTime, default=_beijing_now, onupdate=_beijing_now, nullable=False) def set_items(self, items): self.items_json = json.dumps(items or [], ensure_ascii=False) def get_items(self): try: return json.loads(self.items_json) if self.items_json else [] except Exception: return [] def set_allowed_approvers(self, approvers): self.allowed_approvers = json.dumps(approvers or [], ensure_ascii=False) def get_allowed_approvers(self): try: return json.loads(self.allowed_approvers) if self.allowed_approvers else [] except Exception: return [] @staticmethod def _user_name(user_id): if not user_id: return '' try: from app.models.system import SysUser u = SysUser.query.get(user_id) return u.username if u else '' except Exception: return '' def to_dict(self): return { 'id': self.id, 'request_no': self.request_no, 'applicant_id': self.applicant_id, 'applicant_name': self._user_name(self.applicant_id), 'remark': self.remark or '', 'status': self.status, 'allowed_approvers': self.get_allowed_approvers(), 'actual_approver_id': self.actual_approver_id, 'actual_approver_name': self._user_name(self.actual_approver_id), 'approved_at': self.approved_at.strftime('%Y-%m-%d %H:%M:%S') if self.approved_at else None, 'reject_reason': self.reject_reason or '', 'items': self.get_items(), 'executed_at': self.executed_at.strftime('%Y-%m-%d %H:%M:%S') if self.executed_at else None, 'executor_name': self.executor_name or '', 'created_at': self.created_at.strftime('%Y-%m-%d %H:%M:%S') if self.created_at else None, }