Compare commits
5 Commits
ae63748060
...
5510bae3b2
| Author | SHA1 | Date | |
|---|---|---|---|
| 5510bae3b2 | |||
| 5842042db6 | |||
| fa8b113f9d | |||
| b37049a4d7 | |||
| 6cc3d1b6e0 |
@ -1,5 +1,5 @@
|
|||||||
from flask import Blueprint, jsonify, request, send_file
|
from flask import Blueprint, jsonify, request, send_file
|
||||||
from app.extensions import db
|
from app.extensions import db, beijing_time
|
||||||
# ★★★ 修复点:必须引入 datetime,否则下方更新时间时会报错 500 ★★★
|
# ★★★ 修复点:必须引入 datetime,否则下方更新时间时会报错 500 ★★★
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from app.utils.decorators import permission_required
|
from app.utils.decorators import permission_required
|
||||||
@ -889,3 +889,95 @@ def export_stocktake():
|
|||||||
import traceback
|
import traceback
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
return jsonify({"message": f"导出失败: {str(e)}"}), 500
|
return jsonify({"message": f"导出失败: {str(e)}"}), 500
|
||||||
|
|
||||||
|
|
||||||
|
# --------------------------------------------------------
|
||||||
|
# 生成漏盘数据 - 将未扫描的库存标记为全额盘亏
|
||||||
|
# POST /api/v1/inbound/stocktake/generate-missing
|
||||||
|
# --------------------------------------------------------
|
||||||
|
@bp.route('/stocktake/generate-missing', methods=['POST'])
|
||||||
|
@permission_required('inventory_stocktake:operation')
|
||||||
|
def generate_missing_stocktake():
|
||||||
|
"""
|
||||||
|
生成漏盘数据:
|
||||||
|
找出所有真实库存 > 0,但未被盘点扫描到的物料,
|
||||||
|
自动生成盘点草稿,标记为盘亏(实盘=0,差异=-库存数)
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# 1. 获取所有已有盘点记录的 (source_table, stock_id) 集合
|
||||||
|
existing_records = db.session.query(
|
||||||
|
StocktakeDraft.source_table,
|
||||||
|
StocktakeDraft.stock_id
|
||||||
|
).distinct().all()
|
||||||
|
|
||||||
|
scanned_keys = set()
|
||||||
|
for src_table, stock_id in existing_records:
|
||||||
|
if stock_id:
|
||||||
|
scanned_keys.add((src_table, stock_id))
|
||||||
|
|
||||||
|
# 2. 获取所有真实库存 > 0 的记录
|
||||||
|
all_stock = []
|
||||||
|
|
||||||
|
# 采购库存
|
||||||
|
for item in StockBuy.query.filter(StockBuy.stock_quantity > 0).all():
|
||||||
|
all_stock.append({
|
||||||
|
'source_table': 'stock_buy',
|
||||||
|
'stock_id': item.id,
|
||||||
|
'base_id': item.base_id,
|
||||||
|
'stock_qty': float(item.stock_quantity or 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
# 半成品库存
|
||||||
|
if StockSemi:
|
||||||
|
for item in StockSemi.query.filter(StockSemi.stock_quantity > 0).all():
|
||||||
|
all_stock.append({
|
||||||
|
'source_table': 'stock_semi',
|
||||||
|
'stock_id': item.id,
|
||||||
|
'base_id': item.base_id,
|
||||||
|
'stock_qty': float(item.stock_quantity or 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
# 成品库存
|
||||||
|
if StockProduct:
|
||||||
|
for item in StockProduct.query.filter(StockProduct.stock_quantity > 0).all():
|
||||||
|
all_stock.append({
|
||||||
|
'source_table': 'stock_product',
|
||||||
|
'stock_id': item.id,
|
||||||
|
'base_id': item.base_id,
|
||||||
|
'stock_qty': float(item.stock_quantity or 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
# 3. 找出漏盘记录(库存中有但盘点中没有的)
|
||||||
|
missing_count = 0
|
||||||
|
for stock in all_stock:
|
||||||
|
key = (stock['source_table'], stock['stock_id'])
|
||||||
|
if key not in scanned_keys:
|
||||||
|
# 生成漏盘草稿
|
||||||
|
draft = StocktakeDraft(
|
||||||
|
user_id='system',
|
||||||
|
uuid=f'MISSING-{stock["source_table"]}-{stock["stock_id"]}',
|
||||||
|
quantity=0, # 实盘数为0
|
||||||
|
scan_time=beijing_time(),
|
||||||
|
session_id='AUTO_GENERATED',
|
||||||
|
source_table=stock['source_table'],
|
||||||
|
stock_id=stock['stock_id'],
|
||||||
|
stock_qty=stock['stock_qty'],
|
||||||
|
diff_qty=-stock['stock_qty'], # 差异 = 0 - 库存数 = 负数
|
||||||
|
remark='未盘点到,系统自动标记为盘亏'
|
||||||
|
)
|
||||||
|
db.session.add(draft)
|
||||||
|
missing_count += 1
|
||||||
|
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
'code': 200,
|
||||||
|
'msg': f'成功生成 {missing_count} 条漏盘记录',
|
||||||
|
'data': {'count': missing_count}
|
||||||
|
})
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
db.session.rollback()
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
return jsonify({'code': 500, 'msg': f'生成漏盘数据失败: {str(e)}'}), 500
|
||||||
|
|||||||
@ -9,18 +9,39 @@ from app.models.inbound.buy import StockBuy
|
|||||||
from app.models.inbound.semi import StockSemi
|
from app.models.inbound.semi import StockSemi
|
||||||
from app.models.inbound.product import StockProduct
|
from app.models.inbound.product import StockProduct
|
||||||
from app.models.inbound.stocktake import StocktakeDraft
|
from app.models.inbound.stocktake import StocktakeDraft
|
||||||
from datetime import datetime
|
from datetime import datetime, timedelta
|
||||||
import random
|
from sqlalchemy import func
|
||||||
import string
|
|
||||||
|
|
||||||
adjustment_bp = Blueprint('adjustment', __name__, url_prefix='/stock/adjustment')
|
adjustment_bp = Blueprint('adjustment', __name__, url_prefix='/stock/adjustment')
|
||||||
|
|
||||||
|
|
||||||
|
def get_beijing_time():
|
||||||
|
"""获取北京时间 (UTC+8)"""
|
||||||
|
return datetime.utcnow() + timedelta(hours=8)
|
||||||
|
|
||||||
|
|
||||||
def generate_order_no():
|
def generate_order_no():
|
||||||
"""生成单号 ADJ-YYYYMMDD-XXXX"""
|
"""生成单号 ADJ-YYYYMMDD-XXXX,按天严格自增"""
|
||||||
today = datetime.now().strftime('%Y%m%d')
|
bj_time = get_beijing_time()
|
||||||
suffix = ''.join(random.choices(string.digits, k=4))
|
date_str = bj_time.strftime('%Y%m%d')
|
||||||
return f'ADJ-{today}-{suffix}'
|
prefix = f"ADJ-{date_str}-"
|
||||||
|
|
||||||
|
# 查询今天已有的最大单号
|
||||||
|
last_order = StockAdjustment.query.filter(
|
||||||
|
StockAdjustment.order_no.like(f"{prefix}%")
|
||||||
|
).order_by(StockAdjustment.order_no.desc()).first()
|
||||||
|
|
||||||
|
if last_order:
|
||||||
|
# 解析最后的 4 位流水号并 +1
|
||||||
|
try:
|
||||||
|
last_seq = int(last_order.order_no.split('-')[-1])
|
||||||
|
new_seq = last_seq + 1
|
||||||
|
except (ValueError, IndexError):
|
||||||
|
new_seq = 1
|
||||||
|
else:
|
||||||
|
new_seq = 1
|
||||||
|
|
||||||
|
return f"{prefix}{new_seq:04d}" # 补齐 4 位,如 0001
|
||||||
|
|
||||||
|
|
||||||
def get_stock_model(source_table):
|
def get_stock_model(source_table):
|
||||||
@ -134,7 +155,8 @@ def create():
|
|||||||
return jsonify({'code': 400, 'msg': '无效的调整类型'}), 400
|
return jsonify({'code': 400, 'msg': '无效的调整类型'}), 400
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# 创建调整单
|
# 创建调整单(强制使用北京时间)
|
||||||
|
bj_time = get_beijing_time()
|
||||||
adjustment = StockAdjustment(
|
adjustment = StockAdjustment(
|
||||||
order_no=generate_order_no(),
|
order_no=generate_order_no(),
|
||||||
base_id=base_id,
|
base_id=base_id,
|
||||||
@ -148,7 +170,9 @@ def create():
|
|||||||
adjust_quantity=adjust_quantity,
|
adjust_quantity=adjust_quantity,
|
||||||
reason=reason,
|
reason=reason,
|
||||||
status='completed',
|
status='completed',
|
||||||
operator=operator
|
operator=operator,
|
||||||
|
create_time=bj_time,
|
||||||
|
update_time=bj_time
|
||||||
)
|
)
|
||||||
db.session.add(adjustment)
|
db.session.add(adjustment)
|
||||||
|
|
||||||
@ -351,7 +375,8 @@ def import_from_stocktake():
|
|||||||
# 生成调整单号
|
# 生成调整单号
|
||||||
order_no = generate_order_no()
|
order_no = generate_order_no()
|
||||||
|
|
||||||
# 创建调整单
|
# 创建调整单(强制使用北京时间)
|
||||||
|
bj_time = get_beijing_time()
|
||||||
adjustment = StockAdjustment(
|
adjustment = StockAdjustment(
|
||||||
order_no=order_no,
|
order_no=order_no,
|
||||||
base_id=base_id,
|
base_id=base_id,
|
||||||
@ -363,7 +388,9 @@ def import_from_stocktake():
|
|||||||
adjust_quantity=adjust_quantity,
|
adjust_quantity=adjust_quantity,
|
||||||
reason=reason,
|
reason=reason,
|
||||||
status='pending',
|
status='pending',
|
||||||
operator=operator
|
operator=operator,
|
||||||
|
create_time=bj_time,
|
||||||
|
update_time=bj_time
|
||||||
)
|
)
|
||||||
db.session.add(adjustment)
|
db.session.add(adjustment)
|
||||||
count += 1
|
count += 1
|
||||||
@ -374,3 +401,54 @@ def import_from_stocktake():
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
db.session.rollback()
|
db.session.rollback()
|
||||||
return jsonify({'code': 500, 'msg': f'导入失败: {str(e)}'}), 500
|
return jsonify({'code': 500, 'msg': f'导入失败: {str(e)}'}), 500
|
||||||
|
|
||||||
|
|
||||||
|
# --------------------------------------------------------
|
||||||
|
# 7. 处理调整单(关联入库SKU或出库单号)
|
||||||
|
# POST /api/v1/stock/adjustment/<id>/process
|
||||||
|
# --------------------------------------------------------
|
||||||
|
@adjustment_bp.route('/<int:id>/process', methods=['POST'])
|
||||||
|
@jwt_required()
|
||||||
|
@permission_required('stock_adjustment:operation')
|
||||||
|
def process_adjustment(id):
|
||||||
|
"""处理待处理的调整单,关联入库SKU或出库单号"""
|
||||||
|
identity = get_jwt_identity()
|
||||||
|
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:
|
||||||
|
return jsonify({'code': 400, 'msg': '缺少参数'}), 400
|
||||||
|
|
||||||
|
linked_sku = data.get('linked_sku', '')
|
||||||
|
linked_outbound_no = data.get('linked_outbound_no', '')
|
||||||
|
|
||||||
|
try:
|
||||||
|
adjustment = StockAdjustment.query.get(id)
|
||||||
|
if not adjustment:
|
||||||
|
return jsonify({'code': 404, 'msg': '调整单不存在'}), 404
|
||||||
|
|
||||||
|
if adjustment.status != 'pending':
|
||||||
|
return jsonify({'code': 400, 'msg': '只能处理待处理状态的调整单'}), 400
|
||||||
|
|
||||||
|
# 根据调整类型校验必填项
|
||||||
|
if adjustment.adjust_type == 'profit':
|
||||||
|
if not linked_sku:
|
||||||
|
return jsonify({'code': 400, 'msg': '盘盈调整必须关联入库SKU'}), 400
|
||||||
|
adjustment.linked_sku = linked_sku
|
||||||
|
elif adjustment.adjust_type == 'loss':
|
||||||
|
if not linked_outbound_no:
|
||||||
|
return jsonify({'code': 400, 'msg': '盘亏调整必须关联出库单号'}), 400
|
||||||
|
adjustment.linked_outbound_no = linked_outbound_no
|
||||||
|
|
||||||
|
adjustment.status = 'completed'
|
||||||
|
adjustment.operator = operator
|
||||||
|
adjustment.update_time = get_beijing_time()
|
||||||
|
|
||||||
|
db.session.commit()
|
||||||
|
return jsonify({'code': 200, 'msg': '处理成功', 'data': adjustment.to_dict()})
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
db.session.rollback()
|
||||||
|
return jsonify({'code': 500, 'msg': f'处理失败: {str(e)}'}), 500
|
||||||
|
|||||||
@ -34,6 +34,10 @@ class StockAdjustment(db.Model):
|
|||||||
reason = db.Column(db.String(500), nullable=False)
|
reason = db.Column(db.String(500), nullable=False)
|
||||||
# 状态:'pending' 待处理 / 'completed' 已完成 / 'cancelled' 已取消
|
# 状态:'pending' 待处理 / 'completed' 已完成 / 'cancelled' 已取消
|
||||||
status = db.Column(db.String(20), default='pending')
|
status = db.Column(db.String(20), default='pending')
|
||||||
|
# 关联入库SKU(盘盈时填写)
|
||||||
|
linked_sku = db.Column(db.String(100), comment='关联入库SKU(盘盈时填写)')
|
||||||
|
# 关联出库单号(盘亏时填写)
|
||||||
|
linked_outbound_no = db.Column(db.String(100), comment='关联出库单号(盘亏时填写)')
|
||||||
# 操作人/经办人
|
# 操作人/经办人
|
||||||
operator = db.Column(db.String(100))
|
operator = db.Column(db.String(100))
|
||||||
# 创建时间
|
# 创建时间
|
||||||
@ -56,6 +60,8 @@ class StockAdjustment(db.Model):
|
|||||||
'adjust_quantity': float(self.adjust_quantity or 0),
|
'adjust_quantity': float(self.adjust_quantity or 0),
|
||||||
'reason': self.reason,
|
'reason': self.reason,
|
||||||
'status': self.status,
|
'status': self.status,
|
||||||
|
'linked_sku': self.linked_sku,
|
||||||
|
'linked_outbound_no': self.linked_outbound_no,
|
||||||
'operator': self.operator,
|
'operator': self.operator,
|
||||||
'create_time': self.create_time.strftime('%Y-%m-%d %H:%M:%S') if self.create_time else None,
|
'create_time': self.create_time.strftime('%Y-%m-%d %H:%M:%S') if self.create_time else None,
|
||||||
'update_time': self.update_time.strftime('%Y-%m-%d %H:%M:%S') if self.update_time else None,
|
'update_time': self.update_time.strftime('%Y-%m-%d %H:%M:%S') if self.update_time else None,
|
||||||
|
|||||||
@ -95,6 +95,7 @@
|
|||||||
<el-option label="销售出库" value="SALES" />
|
<el-option label="销售出库" value="SALES" />
|
||||||
<el-option label="内部领用" value="USE" />
|
<el-option label="内部领用" value="USE" />
|
||||||
<el-option label="调拨出库" value="TRANSFER" />
|
<el-option label="调拨出库" value="TRANSFER" />
|
||||||
|
<el-option label="盘亏出库" value="LOSS" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|||||||
@ -43,6 +43,18 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="reason" label="调整原因" min-width="150" show-overflow-tooltip />
|
<el-table-column prop="reason" label="调整原因" min-width="150" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="linked_sku" label="关联SKU" width="120" show-overflow-tooltip>
|
||||||
|
<template #default="{ row }">
|
||||||
|
<span v-if="row.adjust_type === 'profit'">{{ row.linked_sku || '-' }}</span>
|
||||||
|
<span v-else>-</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="linked_outbound_no" label="关联出库单" width="140" show-overflow-tooltip>
|
||||||
|
<template #default="{ row }">
|
||||||
|
<span v-if="row.adjust_type === 'loss'">{{ row.linked_outbound_no || '-' }}</span>
|
||||||
|
<span v-else>-</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column prop="operator" label="操作人" width="100" />
|
<el-table-column prop="operator" label="操作人" width="100" />
|
||||||
<el-table-column prop="status" label="状态" width="90" align="center">
|
<el-table-column prop="status" label="状态" width="90" align="center">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
@ -52,6 +64,14 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="create_time" label="创建时间" width="160" />
|
<el-table-column prop="create_time" label="创建时间" width="160" />
|
||||||
|
<el-table-column label="操作" width="100" fixed="right">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-button v-if="row.status === 'pending' && userStore.hasPermission('stock_adjustment:operation')" type="primary" link @click="openProcessDialog(row)">
|
||||||
|
处理
|
||||||
|
</el-button>
|
||||||
|
<span v-else>-</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<!-- 分页 -->
|
<!-- 分页 -->
|
||||||
@ -173,6 +193,30 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
|
<!-- 处理调整单弹窗 -->
|
||||||
|
<el-dialog v-model="showProcessDialog" title="处理调整单" width="500px" :close-on-click-modal="false">
|
||||||
|
<el-form label-width="120px">
|
||||||
|
<el-form-item label="调整单号">
|
||||||
|
<el-input v-model="processForm.order_no" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="调整类型">
|
||||||
|
<el-tag :type="processForm.adjust_type === 'profit' ? 'success' : 'danger'">
|
||||||
|
{{ processForm.adjust_type === 'profit' ? '盘盈' : '盘亏' }}
|
||||||
|
</el-tag>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item :label="processForm.adjust_type === 'profit' ? '关联入库SKU' : '关联出库单号'">
|
||||||
|
<el-input
|
||||||
|
v-model="processForm.linked_value"
|
||||||
|
:placeholder="processForm.adjust_type === 'profit' ? '请输入已入库的SKU' : '请输入对应的出库单号'"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="showProcessDialog = false">取消</el-button>
|
||||||
|
<el-button type="primary" @click="handleProcessSubmit" :loading="processLoading">确认处理</el-button>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -233,6 +277,68 @@ const selectedReviewRows = ref<any[]>([])
|
|||||||
const reviewTableRef = ref()
|
const reviewTableRef = ref()
|
||||||
const importLoading = ref(false)
|
const importLoading = ref(false)
|
||||||
|
|
||||||
|
// 处理调整单
|
||||||
|
const showProcessDialog = ref(false)
|
||||||
|
const processLoading = ref(false)
|
||||||
|
const processForm = ref({
|
||||||
|
id: null as number | null,
|
||||||
|
order_no: '',
|
||||||
|
adjust_type: '',
|
||||||
|
linked_value: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
// 打开处理弹窗
|
||||||
|
function openProcessDialog(row: any) {
|
||||||
|
processForm.value = {
|
||||||
|
id: row.id,
|
||||||
|
order_no: row.order_no,
|
||||||
|
adjust_type: row.adjust_type,
|
||||||
|
linked_value: ''
|
||||||
|
}
|
||||||
|
showProcessDialog.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交处理
|
||||||
|
async function handleProcessSubmit() {
|
||||||
|
if (!processForm.value.id) return
|
||||||
|
|
||||||
|
if (processForm.value.adjust_type === 'profit' && !processForm.value.linked_value) {
|
||||||
|
ElMessage.warning('请输入已入库的SKU')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (processForm.value.adjust_type === 'loss' && !processForm.value.linked_value) {
|
||||||
|
ElMessage.warning('请输入对应的出库单号')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
processLoading.value = true
|
||||||
|
try {
|
||||||
|
const data: any = {}
|
||||||
|
if (processForm.value.adjust_type === 'profit') {
|
||||||
|
data.linked_sku = processForm.value.linked_value
|
||||||
|
} else {
|
||||||
|
data.linked_outbound_no = processForm.value.linked_value
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await request({
|
||||||
|
url: `/v1/stock/adjustment/${processForm.value.id}/process`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
if (res.code === 200) {
|
||||||
|
ElMessage.success('处理成功')
|
||||||
|
showProcessDialog.value = false
|
||||||
|
fetchData()
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res.msg || '处理失败')
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
ElMessage.error('处理失败')
|
||||||
|
} finally {
|
||||||
|
processLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 获取盘点差异列表
|
// 获取盘点差异列表
|
||||||
async function fetchReviewList() {
|
async function fetchReviewList() {
|
||||||
reviewLoading.value = true
|
reviewLoading.value = true
|
||||||
|
|||||||
@ -103,8 +103,8 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-button v-if="userStore.hasPermission('inventory_stocktake:operation')" type="danger" size="large" class="w-100 action-btn" @click="openFinishDialog" :icon="Checked">
|
<el-button v-if="userStore.hasPermission('inventory_stocktake:operation')" type="danger" size="large" class="w-100 action-btn" @click="handleGenerateMissing" :icon="Checked">
|
||||||
结束盘点
|
结束盘点并生成差异
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@ -993,6 +993,46 @@ const openFinishDialog = () => {
|
|||||||
finishStocktake()
|
finishStocktake()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ★ 新增:结束盘点(计算漏盘)- 将未扫描的库存标记为全额盘亏
|
||||||
|
const handleGenerateMissing = async () => {
|
||||||
|
if (stats.value.total === 0) {
|
||||||
|
ElMessage.warning('暂无盘点数据')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await ElMessageBox.confirm(
|
||||||
|
'确认结束当前盘点吗?系统将自动把所有未扫描到的库存标记为全额盘亏!',
|
||||||
|
'提示',
|
||||||
|
{
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
btnLoading.value = true
|
||||||
|
const res = await request({
|
||||||
|
url: '/v1/inbound/stock/stocktake/generate-missing',
|
||||||
|
method: 'post'
|
||||||
|
})
|
||||||
|
|
||||||
|
if (res.code === 200) {
|
||||||
|
ElMessage.success(`成功生成 ${res.data.count} 条漏盘记录`)
|
||||||
|
// 刷新差异列表
|
||||||
|
await checkServerDraft()
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res.msg || '生成漏盘数据失败')
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
if (e !== 'cancel') {
|
||||||
|
ElMessage.error('生成漏盘数据失败')
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
btnLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ★ 重写: 结束盘点 - 纯前端状态流转,不再调用后端
|
// ★ 重写: 结束盘点 - 纯前端状态流转,不再调用后端
|
||||||
const finishStocktake = async () => {
|
const finishStocktake = async () => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
Reference in New Issue
Block a user