Files
KCGL/inventory-backend/app/models/transaction.py

183 lines
6.9 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 app.extensions import db, beijing_time
from datetime import datetime
from sqlalchemy import func
class TransBorrow(db.Model):
__tablename__ = 'trans_borrow'
id = db.Column(db.Integer, primary_key=True)
borrow_no = db.Column(db.String(100))
sku = db.Column(db.String(100))
source_table = db.Column(db.String(50))
stock_id = db.Column(db.Integer)
barcode = db.Column(db.String(100))
quantity = db.Column(db.Numeric(19, 4))
returned_quantity = db.Column(db.Numeric(19, 4), default=0)
borrower_name = db.Column(db.String(100))
borrow_time = db.Column(db.DateTime, default=beijing_time)
borrow_signature = db.Column(db.Text)
expected_return_time = db.Column(db.DateTime)
is_returned = db.Column(db.Boolean, default=False)
return_time = db.Column(db.DateTime)
return_operator = db.Column(db.String(100))
return_signature = db.Column(db.Text)
return_location = db.Column(db.String(100))
status = db.Column(db.String(20), default='borrowed')
remark = db.Column(db.Text)
def to_dict(self):
returned_qty = float(self.returned_quantity) if self.returned_quantity is not None else 0
total_qty = float(self.quantity) if self.quantity is not None else 0
pending_qty = total_qty - returned_qty
return {
'id': self.id,
'borrow_no': self.borrow_no,
'sku': self.sku,
'source_table': self.source_table,
'stock_id': self.stock_id,
'barcode': self.barcode,
'quantity': total_qty,
'returned_quantity': returned_qty,
'pending_quantity': pending_qty,
'borrower_name': self.borrower_name,
'borrow_time': self.borrow_time.strftime('%Y-%m-%d %H:%M') if self.borrow_time else None,
'borrow_signature': self.borrow_signature,
'expected_return_time': self.expected_return_time.strftime('%Y-%m-%d %H:%M') if self.expected_return_time else None,
'is_returned': self.is_returned,
'return_time': self.return_time.strftime('%Y-%m-%d %H:%M') if self.return_time else None,
'return_operator': self.return_operator,
'return_signature': self.return_signature,
'return_location': self.return_location,
'status': self.status,
'remark': self.remark,
}
@classmethod
def get_borrowed_quantity(cls, source_table, stock_id):
"""
获取指定库存记录source_table 和 stock_id的借出未还数量总和。
返回浮点数,若无借出记录则返回 0.0。
"""
result = db.session.query(func.sum(cls.quantity)).filter(
cls.source_table == source_table,
cls.stock_id == stock_id,
cls.is_returned == False
).scalar()
return float(result) if result is not None else 0.0
class TransRepair(db.Model):
__tablename__ = 'trans_repair'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
# 维修单号 (新增)
repair_no = db.Column(db.String(50), nullable=True, unique=True)
# 关联基础信息 (新增)
base_id = db.Column(db.Integer, db.ForeignKey('material_base.id'), nullable=True)
# SKU 保留
sku = db.Column(db.String(100))
# 序列号SN (新增,用于单台追溯)
serial_number = db.Column(db.String(100), nullable=True)
# 来源追溯 (兼容旧数据)
source_table = db.Column(db.String(50))
stock_id = db.Column(db.Integer)
is_self_made = db.Column(db.Boolean, default=False)
related_product_id = db.Column(db.Integer)
# 入库/接收时间
arrival_date = db.Column(db.Date)
# 维修状态 (新增)
repair_status = db.Column(db.String(50), default='待检测')
# 客户反馈
fault_description = db.Column(db.Text)
# 预计修复时间
expected_repair_time = db.Column(db.String(100))
# 维修日志/结果
repair_result = db.Column(db.Text)
# 维修人
repair_manager = db.Column(db.String(100))
# 出库交付时间
shipping_date = db.Column(db.Date)
# 客户名/来源
related_contract_id = db.Column(db.String(100))
# 成本与售价
cost_price = db.Column(db.Numeric(19, 4))
sale_price = db.Column(db.Numeric(19, 4))
# 数据隔离 (新增)
company_id = db.Column(db.Integer, nullable=True)
# 关联关系
base = db.relationship('MaterialBase', backref='repairs')
def to_dict(self):
return {
'id': self.id,
'repair_no': self.repair_no,
'base_id': self.base_id,
'sku': self.sku,
'serial_number': self.serial_number,
'source_table': self.source_table,
'stock_id': self.stock_id,
'arrival_date': self.arrival_date.strftime('%Y-%m-%d') if self.arrival_date else None,
'repair_status': self.repair_status,
'expected_repair_time': self.expected_repair_time,
'shipping_date': self.shipping_date.strftime('%Y-%m-%d') if self.shipping_date else None,
'is_self_made': self.is_self_made,
'related_product_id': self.related_product_id,
'related_contract_id': self.related_contract_id,
'repair_manager': self.repair_manager,
'fault_description': self.fault_description,
'repair_result': self.repair_result,
'cost_price': float(self.cost_price) if self.cost_price is not None else None,
'sale_price': float(self.sale_price) if self.sale_price is not None else None,
'company_id': self.company_id,
}
class TransScrap(db.Model):
__tablename__ = 'trans_scrap'
id = db.Column(db.Integer, primary_key=True)
sku = db.Column(db.String(100))
source_table = db.Column(db.String(50))
stock_id = db.Column(db.Integer)
quantity = db.Column(db.Numeric(19, 4))
reason = db.Column(db.Text)
operator_name = db.Column(db.String(100))
operation_time = db.Column(db.DateTime, default=beijing_time)
approver_name = db.Column(db.String(100))
approval_status = db.Column(db.String(20), default='pending')
cost_at_scrap = db.Column(db.Numeric(19, 4))
total_loss = db.Column(db.Numeric(19, 4))
def to_dict(self):
return {
'id': self.id,
'sku': self.sku,
'source_table': self.source_table,
'stock_id': self.stock_id,
'quantity': float(self.quantity) if self.quantity is not None else None,
'reason': self.reason,
'operator_name': self.operator_name,
'operation_time': self.operation_time.strftime('%Y-%m-%d %H:%M:%S') if self.operation_time else None,
'approver_name': self.approver_name,
'approval_status': self.approval_status,
'cost_at_scrap': float(self.cost_at_scrap) if self.cost_at_scrap is not None else None,
'total_loss': float(self.total_loss) if self.total_loss is not None else None,
}