feat: add unscanned items sheet to stocktake export and fix user real name mapping
This commit is contained in:
@ -694,9 +694,117 @@ def export_stocktake():
|
|||||||
ws3.cell(row=row_idx, column=8, value=pending_qty).border = thin_border
|
ws3.cell(row=row_idx, column=8, value=pending_qty).border = thin_border
|
||||||
ws3.cell(row=row_idx, column=9, value=to_beijing_time(borrow.borrow_time)).border = thin_border
|
ws3.cell(row=row_idx, column=9, value=to_beijing_time(borrow.borrow_time)).border = thin_border
|
||||||
ws3.cell(row=row_idx, column=10, value='无限期' if not borrow.expected_return_time else to_beijing_time(borrow.expected_return_time)).border = thin_border
|
ws3.cell(row=row_idx, column=10, value='无限期' if not borrow.expected_return_time else to_beijing_time(borrow.expected_return_time)).border = thin_border
|
||||||
|
|
||||||
|
# ===== Sheet 4: 未盘点明细(疑似漏盘) =====
|
||||||
|
# 逻辑:获取已盘点的集合,遍历库存表,找出未盘点且有库存的物资
|
||||||
|
ws4 = wb.create_sheet("未盘点明细(疑似漏盘)")
|
||||||
|
unscanned_headers = ["物料名称", "SKU", "规格型号", "库位", "调整后账面数", "实盘数", "差异数", "状态"]
|
||||||
|
set_header_row(ws4, unscanned_headers)
|
||||||
|
|
||||||
|
# 获取已盘点的 (source_table, stock_id) 集合
|
||||||
|
all_drafts = StocktakeDraft.query.all()
|
||||||
|
scanned_set = {(d.source_table, d.stock_id) for d in all_drafts}
|
||||||
|
|
||||||
|
def get_borrowed_qty(source_table, stock_id):
|
||||||
|
"""获取某库存的借出未还数量"""
|
||||||
|
try:
|
||||||
|
borrowed = TransBorrow.query.filter(
|
||||||
|
TransBorrow.source_table == source_table,
|
||||||
|
TransBorrow.stock_id == stock_id,
|
||||||
|
TransBorrow.is_returned == False
|
||||||
|
).all()
|
||||||
|
total = sum((b.quantity or 0) - (b.returned_quantity or 0) for b in borrowed)
|
||||||
|
return total
|
||||||
|
except:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
unscanned_items = []
|
||||||
|
|
||||||
|
# 遍历 StockBuy
|
||||||
|
for stock in StockBuy.query.all():
|
||||||
|
key = ('stock_buy', stock.id)
|
||||||
|
if key in scanned_set:
|
||||||
|
continue
|
||||||
|
stock_qty = float(stock.stock_quantity or 0)
|
||||||
|
if stock_qty <= 0:
|
||||||
|
continue
|
||||||
|
# 扣除外借数量
|
||||||
|
borrowed_qty = get_borrowed_qty('stock_buy', stock.id)
|
||||||
|
expected_qty = stock_qty - borrowed_qty
|
||||||
|
if expected_qty > 0:
|
||||||
|
mat_info = get_material_info('stock_buy', stock.id)
|
||||||
|
unscanned_items.append({
|
||||||
|
'name': mat_info['name'],
|
||||||
|
'sku': mat_info['sku'],
|
||||||
|
'spec': mat_info['spec'],
|
||||||
|
'location': mat_info['location'],
|
||||||
|
'stock_qty': expected_qty,
|
||||||
|
'actual_qty': 0,
|
||||||
|
'diff_qty': -expected_qty,
|
||||||
|
'status': '未盘点'
|
||||||
|
})
|
||||||
|
|
||||||
|
# 遍历 StockSemi
|
||||||
|
if StockSemi:
|
||||||
|
for stock in StockSemi.query.all():
|
||||||
|
key = ('stock_semi', stock.id)
|
||||||
|
if key in scanned_set:
|
||||||
|
continue
|
||||||
|
stock_qty = float(stock.stock_quantity or 0)
|
||||||
|
if stock_qty <= 0:
|
||||||
|
continue
|
||||||
|
borrowed_qty = get_borrowed_qty('stock_semi', stock.id)
|
||||||
|
expected_qty = stock_qty - borrowed_qty
|
||||||
|
if expected_qty > 0:
|
||||||
|
mat_info = get_material_info('stock_semi', stock.id)
|
||||||
|
unscanned_items.append({
|
||||||
|
'name': mat_info['name'],
|
||||||
|
'sku': mat_info['sku'],
|
||||||
|
'spec': mat_info['spec'],
|
||||||
|
'location': mat_info['location'],
|
||||||
|
'stock_qty': expected_qty,
|
||||||
|
'actual_qty': 0,
|
||||||
|
'diff_qty': -expected_qty,
|
||||||
|
'status': '未盘点'
|
||||||
|
})
|
||||||
|
|
||||||
|
# 遍历 StockProduct
|
||||||
|
if StockProduct:
|
||||||
|
for stock in StockProduct.query.all():
|
||||||
|
key = ('stock_product', stock.id)
|
||||||
|
if key in scanned_set:
|
||||||
|
continue
|
||||||
|
stock_qty = float(stock.stock_quantity or 0)
|
||||||
|
if stock_qty <= 0:
|
||||||
|
continue
|
||||||
|
borrowed_qty = get_borrowed_qty('stock_product', stock.id)
|
||||||
|
expected_qty = stock_qty - borrowed_qty
|
||||||
|
if expected_qty > 0:
|
||||||
|
mat_info = get_material_info('stock_product', stock.id)
|
||||||
|
unscanned_items.append({
|
||||||
|
'name': mat_info['name'],
|
||||||
|
'sku': mat_info['sku'],
|
||||||
|
'spec': mat_info['spec'],
|
||||||
|
'location': mat_info['location'],
|
||||||
|
'stock_qty': expected_qty,
|
||||||
|
'actual_qty': 0,
|
||||||
|
'diff_qty': -expected_qty,
|
||||||
|
'status': '未盘点'
|
||||||
|
})
|
||||||
|
|
||||||
|
# 写入未盘点明细
|
||||||
|
for row_idx, item in enumerate(unscanned_items, 2):
|
||||||
|
ws4.cell(row=row_idx, column=1, value=item['name']).border = thin_border
|
||||||
|
ws4.cell(row=row_idx, column=2, value=item['sku']).border = thin_border
|
||||||
|
ws4.cell(row=row_idx, column=3, value=item['spec']).border = thin_border
|
||||||
|
ws4.cell(row=row_idx, column=4, value=item['location']).border = thin_border
|
||||||
|
ws4.cell(row=row_idx, column=5, value=item['stock_qty']).border = thin_border
|
||||||
|
ws4.cell(row=row_idx, column=6, value=item['actual_qty']).border = thin_border
|
||||||
|
ws4.cell(row=row_idx, column=7, value=item['diff_qty']).border = thin_border
|
||||||
|
ws4.cell(row=row_idx, column=8, value=item['status']).border = thin_border
|
||||||
|
|
||||||
# 调整列宽
|
# 调整列宽
|
||||||
for ws in [ws1, ws2, ws3]:
|
for ws in [ws1, ws2, ws3, ws4]:
|
||||||
for col in ws.columns:
|
for col in ws.columns:
|
||||||
max_length = 0
|
max_length = 0
|
||||||
col_letter = col[0].column_letter
|
col_letter = col[0].column_letter
|
||||||
|
|||||||
Reference in New Issue
Block a user