diff --git a/inventory-backend/app/api/v1/stock/adjustment.py b/inventory-backend/app/api/v1/stock/adjustment.py
index 8cc99ec..a319d9e 100644
--- a/inventory-backend/app/api/v1/stock/adjustment.py
+++ b/inventory-backend/app/api/v1/stock/adjustment.py
@@ -225,40 +225,121 @@ def get_stocks():
# --------------------------------------------------------
-# 5. 一键引入盘点差异
-# POST /api/v1/stock/adjustment/import-from-stocktake
+# 5. 获取盘点差异列表
+# GET /api/v1/stock/adjustment/stocktake-discrepancies
# --------------------------------------------------------
-@adjustment_bp.route('/import-from-stocktake', methods=['POST'])
+@adjustment_bp.route('/stocktake-discrepancies', methods=['GET'])
@jwt_required()
-@permission_required('stock_adjustment:operation')
-def import_from_stocktake():
- """从盘点差异记录导入为盘盈盘亏单"""
- identity = get_jwt_identity()
- operator = identity.get('username', 'system') if isinstance(identity, dict) else str(identity)
-
+@permission_required('stock_adjustment:list')
+def get_stocktake_discrepancies():
+ """获取所有有差异的盘点记录"""
try:
# 查询所有有差异的盘点记录
drafts = StocktakeDraft.query.filter(StocktakeDraft.diff_qty != 0).all()
- if not drafts:
- return jsonify({'code': 200, 'msg': '暂无盘点差异记录', 'data': {'count': 0}})
-
- count = 0
+ items = []
for draft in drafts:
- # 判断盘盈/盘亏
diff = float(draft.diff_qty or 0)
if diff == 0:
continue
- adjust_type = 'profit' if diff > 0 else 'loss'
- adjust_quantity = abs(diff)
-
# 获取物料基础信息
base_id = None
+ material_name = ''
+ spec_model = ''
sku = ''
warehouse_location = ''
# 根据source_table获取对应的库存记录
+ stock_model = get_stock_model(draft.source_table)
+ if stock_model and draft.stock_id:
+ stock = stock_model.query.get(draft.stock_id)
+ if stock:
+ base_id = getattr(stock, 'base_id', None)
+ sku = getattr(stock, 'sku', None) or getattr(stock, 'SKU', '')
+ warehouse_location = getattr(stock, 'warehouse_location', '')
+
+ # 联表查询 MaterialBase
+ if base_id:
+ material = MaterialBase.query.get(base_id)
+ if material:
+ material_name = material.name
+ spec_model = material.spec_model
+
+ items.append({
+ 'draft_id': draft.id,
+ 'source_table': draft.source_table,
+ 'stock_id': draft.stock_id,
+ 'base_id': base_id,
+ 'sku': sku,
+ 'material_name': material_name,
+ 'spec_model': spec_model,
+ 'warehouse_location': warehouse_location,
+ 'stock_qty': float(draft.stock_qty or 0),
+ 'quantity': float(draft.quantity or 0),
+ 'diff_qty': diff,
+ 'adjust_type': 'profit' if diff > 0 else 'loss',
+ 'remark': draft.remark or ''
+ })
+
+ return jsonify({
+ 'code': 200,
+ 'data': {
+ 'items': items,
+ 'total': len(items)
+ }
+ })
+
+ except Exception as e:
+ return jsonify({'code': 500, 'msg': f'获取盘点差异失败: {str(e)}'}), 500
+
+
+# --------------------------------------------------------
+# 6. 批量导入盘点差异(按需勾选)
+# POST /api/v1/stock/adjustment/import-from-stocktake
+# --------------------------------------------------------
+@adjustment_bp.route('/import-from-stocktake', methods=['POST'])
+@jwt_required()
+@permission_required('stock_adjustment:operation')
+def import_from_stocktake():
+ """批量导入选中的盘点差异记录"""
+ identity = get_jwt_identity()
+ # 修复操作人保存为0的Bug,确保保存真实的用户名
+ operator = identity.get('username', 'system') if isinstance(identity, dict) else str(identity)
+ if not operator or operator == '0':
+ operator = identity if identity else 'system'
+
+ data = request.get_json()
+ if not data or 'records' not in data:
+ return jsonify({'code': 400, 'msg': '缺少records参数'}), 400
+
+ records = data.get('records', [])
+ if not records:
+ return jsonify({'code': 400, 'msg': '请选择要导入的记录'}), 400
+
+ try:
+ count = 0
+ for item in records:
+ draft_id = item.get('draft_id')
+ reason = item.get('reason', '盘点差异导入')
+
+ # 获取对应的盘点记录
+ draft = StocktakeDraft.query.get(draft_id)
+ if not draft:
+ continue
+
+ diff = float(draft.diff_qty or 0)
+ if diff == 0:
+ continue
+
+ adjust_type = 'profit' if diff > 0 else 'loss'
+ adjust_quantity = abs(diff)
+
+ # 获取物料基础信息
+ base_id = None
+ sku = ''
+ warehouse_location = ''
+
stock_model = get_stock_model(draft.source_table)
if stock_model and draft.stock_id:
stock = stock_model.query.get(draft.stock_id)
@@ -270,9 +351,6 @@ def import_from_stocktake():
# 生成调整单号
order_no = generate_order_no()
- # 使用备注或默认原因
- reason = draft.remark if draft.remark else '盘点差异自动生成'
-
# 创建调整单
adjustment = StockAdjustment(
order_no=order_no,
@@ -291,7 +369,7 @@ def import_from_stocktake():
count += 1
db.session.commit()
- return jsonify({'code': 200, 'msg': '导入成功', 'data': {'count': count}})
+ return jsonify({'code': 200, 'msg': f'成功导入 {count} 条记录', 'data': {'count': count}})
except Exception as e:
db.session.rollback()
diff --git a/inventory-web/src/views/stock/adjustment/index.vue b/inventory-web/src/views/stock/adjustment/index.vue
index c9da0cd..8a95a73 100644
--- a/inventory-web/src/views/stock/adjustment/index.vue
+++ b/inventory-web/src/views/stock/adjustment/index.vue
@@ -130,6 +130,49 @@
style="margin-top: 15px; justify-content: center"
/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ row.diff_qty > 0 ? '+' : '' }}{{ row.diff_qty }}
+
+
+
+
+
+
+ {{ row.adjust_type === 'profit' ? '盘盈' : '盘亏' }}
+
+
+
+
+
+
+
+
+
+
+ 暂无盘点差异记录
+
+
+
+ 取消
+
+ 勾选导入 ({{ selectedReviewRows.length }})
+
+
+
@@ -182,6 +225,80 @@ const stockLimit = ref(20)
const stockKeyword = ref('')
const selectedStock = ref(null)
+// 盘点差异审核
+const showReviewDialog = ref(false)
+const reviewLoading = ref(false)
+const reviewList = ref([])
+const selectedReviewRows = ref([])
+const reviewTableRef = ref()
+const importLoading = ref(false)
+
+// 获取盘点差异列表
+async function fetchReviewList() {
+ reviewLoading.value = true
+ try {
+ const res = await request({
+ url: '/v1/stock/adjustment/stocktake-discrepancies',
+ method: 'get'
+ })
+ if (res.code === 200) {
+ // 为每条记录设置默认原因
+ reviewList.value = (res.data.items || []).map((item: any) => ({
+ ...item,
+ reason: item.remark || '盘点差异导入'
+ }))
+ }
+ } catch (e) {
+ ElMessage.error('获取盘点差异失败')
+ } finally {
+ reviewLoading.value = false
+ }
+}
+
+// 打开审核弹窗
+async function openReviewDialog() {
+ showReviewDialog.value = true
+ selectedReviewRows.value = []
+ await fetchReviewList()
+}
+
+// 勾选变化
+function handleReviewSelectionChange(rows: any[]) {
+ selectedReviewRows.value = rows
+}
+
+// 导入选中的记录
+async function handleImportSelected() {
+ if (selectedReviewRows.value.length === 0) {
+ ElMessage.warning('请选择要导入的记录')
+ return
+ }
+
+ importLoading.value = true
+ try {
+ const records = selectedReviewRows.value.map(row => ({
+ draft_id: row.draft_id,
+ reason: row.reason || '盘点差异导入'
+ }))
+ const res = await request({
+ url: '/v1/stock/adjustment/import-from-stocktake',
+ method: 'post',
+ data: { records }
+ })
+ if (res.code === 200) {
+ ElMessage.success(res.msg || '导入成功')
+ showReviewDialog.value = false
+ fetchData()
+ } else {
+ ElMessage.error(res.msg || '导入失败')
+ }
+ } catch (e) {
+ ElMessage.error('导入失败')
+ } finally {
+ importLoading.value = false
+ }
+}
+
// 获取列表
async function fetchData() {
loading.value = true
@@ -297,29 +414,9 @@ async function submitForm() {
}
}
-// 一键引入盘点差异
+// 一键引入盘点差异 - 打开审核弹窗
async function handleImportStocktake() {
- try {
- await ElMessageBox.confirm('确定要将当前所有的盘点差异导入为盘盈盘亏单吗?', '提示', {
- confirmButtonText: '确定',
- cancelButtonText: '取消',
- type: 'warning'
- })
- const res = await request({
- url: '/v1/stock/adjustment/import-from-stocktake',
- method: 'post'
- })
- if (res.code === 200) {
- ElMessage.success(`成功导入 ${res.data.count} 条盘点差异记录`)
- fetchData()
- } else {
- ElMessage.error(res.msg || '导入失败')
- }
- } catch (e) {
- if (e !== 'cancel') {
- ElMessage.error('导入失败')
- }
- }
+ await openReviewDialog()
}
onMounted(() => {