diff --git a/inventory-backend/app/models/transaction.py b/inventory-backend/app/models/transaction.py
index 8bce544..2cc3bcb 100644
--- a/inventory-backend/app/models/transaction.py
+++ b/inventory-backend/app/models/transaction.py
@@ -13,6 +13,7 @@ class TransBorrow(db.Model):
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)
@@ -26,6 +27,9 @@ class TransBorrow(db.Model):
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,
@@ -33,7 +37,9 @@ class TransBorrow(db.Model):
'source_table': self.source_table,
'stock_id': self.stock_id,
'barcode': self.barcode,
- 'quantity': float(self.quantity) if self.quantity is not None else None,
+ '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,
diff --git a/inventory-backend/app/services/trans_service.py b/inventory-backend/app/services/trans_service.py
index 4e426a6..2dee1c1 100644
--- a/inventory-backend/app/services/trans_service.py
+++ b/inventory-backend/app/services/trans_service.py
@@ -113,10 +113,12 @@ class TransService:
@staticmethod
def process_return(data, operator_name):
"""
- 还库逻辑:
- 1. 恢复可用库存
- 2. 更新库位 (如果有变动)
- 3. 记录库管签字
+ 还库逻辑(支持部分归还):
+ 1. 校验本次归还数量不能大于待还数量
+ 2. 恢复可用库存(按本次归还数量)
+ 3. 更新库位 (如果有变动)
+ 4. 记录库管签字
+ 5. 更新归还数量和状态(部分归还/全部归还)
"""
items = data.get('items', [])
signature = data.get('signature_path') # 库管签字
@@ -129,32 +131,55 @@ class TransService:
try:
for item in items:
borrow_id = item.get('id')
+ # 前端传入的本次归还数量
+ return_qty = float(item.get('return_qty', 0))
# 前端如果没有填 return_location,应该在提交前处理好,或者这里做 fallback
# 这里假设前端传来的 return_location 就是最终要保存的库位
final_location = item.get('return_location')
record = TransBorrow.query.with_for_update().get(borrow_id)
- if not record or record.is_returned:
+ if not record:
continue
+ # 计算待还数量
+ returned_qty = float(record.returned_quantity) if record.returned_quantity else 0
+ total_qty = float(record.quantity) if record.quantity else 0
+ pending_qty = total_qty - returned_qty
+
+ # 校验归还数量
+ if return_qty <= 0:
+ raise ValueError(f"归还数量必须大于0")
+ if return_qty > pending_qty:
+ raise ValueError(f"本次归还数量({return_qty})不能大于待还数量({pending_qty})")
+
ModelClass = model_map.get(record.source_table)
if ModelClass:
stock = ModelClass.query.with_for_update().get(record.stock_id)
if stock:
- # 1. 恢复可用库存
- stock.available_quantity = float(stock.available_quantity) + float(record.quantity)
+ # 1. 恢复可用库存(按本次归还数量)
+ stock.available_quantity = float(stock.available_quantity) + return_qty
# 2. 更新库位 (如果提供了有效值)
if final_location:
stock.warehouse_location = final_location
- # 3. 更新借用单状态
- record.is_returned = True
- record.status = 'returned'
+ # 3. 更新归还数量
+ new_returned_qty = returned_qty + return_qty
+ record.returned_quantity = new_returned_qty
+
+ # 4. 更新状态
+ if new_returned_qty >= total_qty:
+ record.is_returned = True
+ record.status = 'returned'
+ else:
+ record.is_returned = False
+ record.status = 'partial_returned'
+
record.return_time = datetime.now()
record.return_operator = operator_name
record.return_signature = signature
- record.return_location = final_location
+ if final_location:
+ record.return_location = final_location
db.session.commit()
except Exception as e:
diff --git a/inventory-web/src/views/transaction/records.vue b/inventory-web/src/views/transaction/records.vue
index 50dcb07..581b2fe 100644
--- a/inventory-web/src/views/transaction/records.vue
+++ b/inventory-web/src/views/transaction/records.vue
@@ -22,6 +22,22 @@
+
+
+ {{ row.quantity }}
+
+
+
+
+ {{ row.returned_quantity || 0 }}
+
+
+
+
+ {{ row.pending_quantity }}
+ 0
+
+
@@ -42,9 +58,9 @@
-
- {{ row.status==='returned'?'已还':'借出中' }}
-
+ 已还
+ 部分归还
+ 未还
diff --git a/inventory-web/src/views/transaction/return.vue b/inventory-web/src/views/transaction/return.vue
index c98519d..c1ccfe0 100644
--- a/inventory-web/src/views/transaction/return.vue
+++ b/inventory-web/src/views/transaction/return.vue
@@ -47,6 +47,33 @@
+
+
+ {{ row.quantity }}
+
+
+
+
+ {{ row.returned_quantity || 0 }}
+
+
+
+
+ {{ row.pending_quantity }}
+
+
+
+
+
+
+
+
@@ -253,6 +280,8 @@ const scanItem = async () => {
const item = res.data
// 默认将归还库位填为当前库位
item.return_location = item.current_location || ''
+ // 默认归还数量为待还数量
+ item.return_qty = item.pending_quantity
returnList.value.push(item)
barcode.value = ''