Commit 70157266 by yubin

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	ruoyi-inventory/src/main/java/com/ruoyi/inventory/service/impl/InventoryServiceImpl.java
parents 98bfcd2b e9e044a2
......@@ -8,12 +8,32 @@ export function listStocktakes(query) {
params: query
})
}
// 查询统计
export function listStocktakesCount(query) {
return request({
url: '/inventory/stocktakes/listCount',
method: 'get',
params: query
})
}
// 统计详情
export function getCountInfo(query) {
return request({
url: '/inventory/stocktakes/countInfo',
method: 'get',
params: query
})
}
// 查询盘点单主详细
export function getStocktakes(id) {
export function getStocktakes(id, operationType) {
return request({
url: '/inventory/stocktakes/' + id,
method: 'get'
url: '/inventory/stocktakes/',
method: 'get',
params: {
id: id,
operationType: operationType
}
})
}
......
......@@ -10,22 +10,21 @@
@click="handleAdd"
v-hasPermi="['inventory:stocktakes:add']"
>新增</el-button>
<el-button
type="danger"
plain
icon="el-icon-delete"
size="medium"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['inventory:stocktakes:remove']"
>删除</el-button>
<!-- <el-button-->
<!-- type="danger"-->
<!-- plain-->
<!-- icon="el-icon-delete"-->
<!-- size="medium"-->
<!-- :disabled="multiple"-->
<!-- @click="handleDelete"-->
<!-- v-hasPermi="['inventory:stocktakes:remove']"-->
<!-- >删除</el-button>-->
<el-button
type="success"
plain
icon="el-icon-tickets"
size="medium"
:disabled="single"
@click="handleConfirm"
@click="handleCount"
v-hasPermi="['inventory:stocktakes:count']"
>处理结果统计</el-button>
</template>
......@@ -80,24 +79,26 @@
<!-- <el-table-column label="排序号" align="center" prop="updateUserCode" />-->
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<!-- <el-button-->
<!-- size="mini"-->
<!-- type="text"-->
<!-- icon="el-icon-edit"-->
<!-- @click="handleUpdate(scope.row)"-->
<!-- v-hasPermi="['inventory:stocktakes:edit']"-->
<!-- >修改</el-button>-->
<el-button
size="mini"
type="text"
icon="el-icon-view"
@click="handleViewInfo(scope.row)"
v-hasPermi="['inventory:stocktakes:query']"
>查看</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleCheck(scope.row)"
v-if="scope.row.stocktakeStatus === '1'"
v-hasPermi="['inventory:stocktakes:check']"
>盘点</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
v-if="scope.row.stocktakeStatus === '1'"
@click="handleDelete(scope.row)"
v-hasPermi="['inventory:stocktakes:remove']"
>删除</el-button>
......@@ -106,6 +107,7 @@
type="text"
icon="el-icon-circle-check"
@click="handleConfirm(scope.row)"
v-if="scope.row.stocktakeStatus === '2'"
v-hasPermi="['inventory:stocktakes:confirm']"
>盘点确认</el-button>
</template>
......@@ -199,7 +201,20 @@
/>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitConfirmForm"> </el-button>
<el-button type="primary"
v-if="this.buttonShow"
@click="submitConfirmForm"> </el-button>
<el-button @click="cancelConfirm"> </el-button>
</div>
</el-dialog>
<!-- 处理统计弹窗-->
<el-dialog :title="confirmTitle" :visible.sync="countOpen" width="1500px" append-to-body>
<el-form ref="confirmFormRef" :model="form" :rules="rules" label-width="80px">
<!-- 引入子表组件(核心:传递数据+监听事件) -->
<stocktake-count-table/>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="cancelConfirm"> </el-button>
</div>
</el-dialog>
......@@ -208,14 +223,15 @@
<script>
import { listStocktakes, getStocktakes, delStocktakes, addStocktakes, updateStocktakes } from "@/api/inventory/stocktakes"
// 引入子表组件
// 引入子表组件--盘点
import stocktakeItemsTable from '@/views/inventory/stocktakes/stocktakeItemsTable.vue';
// 引入子表组件--统计
import stocktakeCountTable from '@/views/inventory/stocktakes/stocktakeCountTable.vue';
export default {
name: "Stocktakes",
dicts: ['stocktake_status'],
// 注册子组件
components: { stocktakeItemsTable },
components: { stocktakeItemsTable,stocktakeCountTable },
data() {
return {
// 遮罩层
......@@ -243,10 +259,12 @@ export default {
// 是否显示弹出层
open: false,
checkOpen: false,
confirmOpen: false,
buttonShow: true,//是否展示确认按钮
checkOpen: false, // 盘点弹窗
confirmOpen: false, // 盘点确认弹窗
checkTitle: "库存盘点",
confirmTitle: "盘点确认",
countOpen: false, // 盘点统计弹窗
// 查询参数
queryParams: {
......@@ -358,24 +376,45 @@ export default {
handleCheck(row) {
this.reset();
const id = row.id || this.ids
getStocktakes(id).then(response => {
getStocktakes(id,'check').then(response => {
this.form = response.data
// 过滤 undefined 行,避免子组件渲染报错
this.stocktakeItemsList = (response.data.stocktakeItemsList || []).filter(item => item);
this.checkOpen = true
})
},
// 盘点确认按钮:打开确认弹窗
// 盘点确认按钮:打开弹窗
handleConfirm(row) {
this.reset();
const id = row.id || this.ids
getStocktakes(id).then(response => {
this.buttonShow = true
this.confirmTitle = '盘点确认'
getStocktakes(id,'confirm').then(response => {
this.form = response.data
// 过滤 undefined 行,避免子组件渲染报错
this.stocktakeItemsList = (response.data.stocktakeItemsList || []).filter(item => item);
this.confirmOpen = true;
})
},
// 详情按钮:打开弹窗
handleViewInfo(row) {
this.reset();
const id = row.id || this.ids
this.buttonShow = false
this.confirmTitle = '盘点查看'
getStocktakes(id,'check').then(response => {
this.form = response.data
// 过滤 undefined 行,避免子组件渲染报错
this.stocktakeItemsList = (response.data.stocktakeItemsList || []).filter(item => item);
this.confirmOpen = true;
})
},
/** 处理结果统计按钮操作 */
handleCount() {
this.reset()
this.countOpen = true
this.confirmTitle = " 处理结果统计"
},
/** 子组件字段编辑事件(确保父组件数据同步) */
handleStocktakeItemChange(updatedRow) {
// 找到更新的行,替换数据(确保引用一致)
......@@ -441,7 +480,7 @@ export default {
// 取消操作
cancelCheck() { this.checkOpen = false; this.reset(); },
cancelConfirm() { this.confirmOpen = false; this.reset(); },
cancelConfirm() { this.confirmOpen = false; this.countOpen = false; this.reset(); },
/** 新增提交按钮 */
submitForm() {
......
<template>
<div class="app-container" >
<!-- 子表搜索栏(按需求添加搜索字段) -->
<div class="page-container">
<page-wrapper-search
:model="queryParams"
ref="queryForm"
size="small"
@search="handleQuery"
@reset="resetQuery"
>
<el-form-item label="计划日期">
<el-date-picker v-model="dateRange" style="width: 240px" value-format="yyyy-MM-dd" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
</el-form-item>
<el-form-item label="物料" prop="materialId">
<common-dict-select
v-model="queryParams.materialId"
dict-url="/inventory/materials/getMapList"
value-key="sap_no"
label-key="material_name"
placeholder="请选择物料"
@change="handleQuery"
@loaded="handleDictLoaded('material', $event)"
@input="queryParams.materialId = $event"
/>
</el-form-item>
<el-form-item label="仓库" prop="warehouseId">
<el-input
v-model="queryWarehouseName"
placeholder="请选择仓库"
readonly
@focus="openWarehouseSelector"
:suffix-icon="''"
>
<template v-if="queryWarehouseName" #suffix>
<i
class="el-icon-circle-close el-input__icon"
style="cursor: pointer;"
@click.stop="clearQueryWarehouse"
></i>
</template>
</el-input>
</el-form-item>
<el-form-item label="库位" prop="locationId">
<el-input
v-model="queryLocationName"
placeholder="请选择库位"
readonly
@focus="openLocationSelector"
:suffix-icon="''"
:disabled="!queryParams.warehousesCode"
>
<template v-if="queryLocationName" #suffix>
<i
class="el-icon-circle-close el-input__icon"
style="cursor: pointer;"
@click.stop="clearQueryLocation"
></i>
</template>
</el-input>
</el-form-item>
</page-wrapper-search>
<div class="table-container">
<el-table v-loading="loading" :data="stocktakesList" @selection-change="handleSelectionChange">
<el-table-column label="计划日期" align="center" prop="plannedDates" width="180" />
<el-table-column label="物料" prop="materialId" fixed>
<template slot-scope="scope">
{{ getDictLabel(materialDict, scope.row.materialId, 'sap_no', 'material_name') }}
</template>
</el-table-column>
<el-table-column label="SAP物料号" align="center" prop="sapNo" />
<el-table-column label="TS Code" align="center" prop="tsCode" />
<el-table-column label="危险类别" align="center" prop="hazardName" />
<!-- <el-table-column label="批次编号" prop="batchCode">-->
<!-- <template slot-scope="scope">-->
<!-- <el-input v-model="scope.row.batchCode" placeholder="请输入批次编号" disabled />-->
<!-- </template>-->
<!-- </el-table-column>-->
<el-table-column label="仓库Id" align="center" prop="warehousesId" v-if="false" />
<el-table-column label="库位Id" align="center" prop="locationId" v-if="false" />
<el-table-column label="仓库" align="center" prop="warehousesName" />
<el-table-column label="库位" align="center" prop="locationName" />
<el-table-column label="差异总数" align="center" prop="countQuantity" />
<!-- <template slot-scope="scope">-->
<!-- <el-input type="number" v-model="scope.row.varianceQuantity" placeholder="请输入差异数量" disabled />-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- <el-table-column label="单价" prop="unitPrice">-->
<!-- <template slot-scope="scope">-->
<!-- <el-input v-model="scope.row.unitPrice" placeholder="请输入单价" disabled />-->
<!-- </template>-->
<!-- </el-table-column>-->
<el-table-column label="差异总金额" prop="unitPrice">
<template slot-scope="scope">
{{ formatAmount(scope.row.countAmount) }}
</template>
<!-- <template slot-scope="scope">-->
<!-- <el-input v-model="scope.row.varianceAmount" placeholder="请输入差异金额" disabled />-->
<!-- </template>-->
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-view"
@click="handleCountViewInfo(scope.row)"
>查看</el-button>
</template>
</el-table-column>
</el-table>
</div>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<!-- 仓库选择组件 -->
<WarehouseSelector
v-model="warehouseSelectorVisible"
@selected="handleWarehouseSelected"
/>
<!-- 库位选择组件 -->
<LocationSelector
v-model="locationSelectorVisible"
:warehousesId="currentWarehouseId"
@selected="handleLocationSelected"
/>
</div>
<!-- 详情查看 -->
<el-dialog title="统计详情查看" :visible.sync="viewOpen" width="800px" append-to-body>
<el-table :data="detailList" border stripe size="small" style="width: 100%;">
<el-table-column label="计划日期" prop="plannedDates" />
<el-table-column label="物料" prop="materialId" fixed>
<template slot-scope="scope">
{{ getDictLabel(materialDict, scope.row.materialId, 'sap_no', 'material_name') || '无' }}
</template>
</el-table-column>
<el-table-column label="SAP物料号" prop="sapNo" />
<el-table-column label="仓库" prop="warehousesName" />
<el-table-column label="库位" prop="locationName" />
<el-table-column label="危险类别" prop="hazardName" />
<el-table-column label="差异数量" prop="varianceQuantity" />
<el-table-column label="差异金额" prop="varianceAmount">
<template slot-scope="scope">
{{ formatAmount(scope.row.varianceAmount) }}
</template>
</el-table-column>
</el-table>
<div slot="footer" class="dialog-footer">
<el-button @click="cancel">关 闭</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { listStocktakesCount,getCountInfo } from "@/api/inventory/stocktakes"
import { getDictLabel } from '@/utils/dictUtil'
import CommonDictSelect from '@/components/CommonDictSelect.vue'
import WarehouseSelector from "@/views/compononents/WarehouseSelector.vue"
import LocationSelector from "@/views/compononents/LocationSelector.vue"
export default {
name: "stocktakeCountTable",
components: { CommonDictSelect,WarehouseSelector,LocationSelector }, // 注册通用字典组件
props: {
// 接收父组件传递的子表原始数据(双向绑定)
itemsList: {
type: Array,
default: () => []
},
isConfirm: { // true=盘点确认(全部只读+显示所有字段),false=盘点(部分可编辑+隐藏部分字段)
type: Boolean,
default: false
}
},
data() {
return {
// 遮罩层
loading: true,
viewOpen:false,
queryParams: {
pageNum: 1,
pageSize: 10,
warehouseId: null,
stocktakeStatus: null,
plannedDates: null,
materialId: "",
locationId: ""
},
// 详情列表信息
detailList: [],
// 库存盘点表格数据
stocktakesList: [],
// 日期范围
dateRange: [],
// 仓库选择相关
warehouseSelectorVisible: false,
queryWarehouseName: null,
// 库位选择相关
locationSelectorVisible: false,
queryLocationName: null,
currentWarehouseId: "", // 存仓库原始ID(0eb22b11...),供库位联动
checkedRows: [], // 子表选中的行
materialDict: [], // 物料字典数组(存储sap_no和name)
warehouseDict: [], // 仓库数组
locationDict: [], // 库位数组
// 分页总数
total: 0,
// 表格加载状态
tableLoading: false
}
},
created() {
this.getList()
},
methods: {
// 挂载全局字典工具方法(模板中可直接调用)
getDictLabel,
/** 打开仓库选择器 */
openWarehouseSelector() {
this.warehouseSelectorVisible = true
},
// 取消按钮
cancel() {
this.viewOpen = false
this.detailList = []
},
// 详情按钮:打开弹窗
handleCountViewInfo(row) {
this.detailList = []; // 清空旧数据
// 接口请求添加try/catch和空值判断
getCountInfo(row).then(response => {
if (response && response.rows) {
this.detailList = response.rows; // 直接赋值数组给detailList
console.log('赋值后的detailList:', this.detailList); // 打印3
} else {
}
this.viewOpen = true;
}).catch(error => {
console.error('获取详情失败:', error);
this.$message.error('获取详情失败,请重试');
this.viewOpen = false;
})
},
// 仓库清空时触发
handleWarehouseClear() {
this.queryParams.locationId = ''
this.queryParams.warehouseId = ''
this.currentWarehouseId = ''
this.handleQuery()
},
/** 库位选择回调 */
handleLocationSelected(location) {
if (!location) return
this.queryParams.locationId = location.locationCode
this.queryLocationName = location.locationName || location.locationCode
// console.log('selected LocationName', location);
this.handleQuery()
},
/** 仓库选择回调 */
handleWarehouseSelected(warehouse) {
if (!warehouse) return
// 供库位联动:存仓库原始ID(0eb22b11...)
this.currentWarehouseId = warehouse.warehouseId
// 供列表筛选:存仓库编码333(匹配列表里的warehouseId:333
this.queryParams.warehouseId = warehouse.warehousesCode
this.queryParams.warehousesCode = warehouse.warehousesCode
this.queryWarehouseName = warehouse.warehousesName || warehouse.warehousesCode
// 仓库选择后,清空库位信息
this.queryLocationName = null
this.queryParams.locationId = null
this.handleQuery()
// console.log('selected warehouse', warehouse);
},
/** 格式化金额,保留2位小数 */
formatAmount(amount) {
if (amount === null || amount === undefined || isNaN(amount)) {
return '0.00'
}
return parseFloat(amount).toFixed(2)
},
// 搜索,补全逻辑(无后端请求,仅重置页码)
handleQuery() {
this.queryParams.pageNum = 1 // 搜索后重置页码
this.$nextTick(() => {
this.getList();
});
},
/** 清空仓库选择 */
clearQueryWarehouse() {
this.queryWarehouseName = null
this.queryParams.warehouseId = null
this.queryParams.warehousesCode = null
this.currentWarehouseId = ""
// 清空仓库时,同时清空库位
this.queryLocationName = null
this.queryParams.locationId = null
this.handleQuery()
},
/** 打开库位选择器 */
openLocationSelector() {
// console.log('this.currentWarehouseId========',this.currentWarehouseId)
if (!this.currentWarehouseId) {
this.$message.warning("请先选择仓库")
return
}
this.locationSelectorVisible = true
},
/** 清空库位选择 */
clearQueryLocation() {
this.queryLocationName = null
this.queryParams.locationId = null
this.handleQuery()
},
// 重置
resetQuery() {
this.queryWarehouseName = null
this.queryLocationName = null
this.currentWarehouseId = ''
this.dateRange = []
this.queryParams = {
pageNum: 1,
pageSize: 10,
materialId: "",
batchCode: "",
warehouseId: "",
locationId: ""
};
// 重置库位选择器
this.handleWarehouseClear()
},
// 关联查询列表
getList() {
this.loading = true
listStocktakesCount(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
this.stocktakesList = response.rows
this.total = response.total
this.loading = false
})
},
// 字典加载完成回调(缓存字典数据,供表格展示使用)
handleDictLoaded(type, data) {
switch (type) {
case 'material':
this.materialDict = data
break
case 'warehouse':
this.warehouseDict = data
break
case 'location':
this.locationDict = data
break
}
},
// 给子表设置序号
setRowIndex({row, rowIndex}) {
row.index = rowIndex + 1;
},
// 选中行变化
handleSelectionChange(selection) {
this.checkedRows = selection;
}
}
}
</script>
<style scoped>
.app-container {
padding: 16px;
}
.page-container {
background: #fff;
padding: 16px;
border-radius: 4px;
}
.table-container {
margin-top: 16px;
}
.mb8 {
margin-bottom: 8px;
}
/* 表格样式优化 */
:deep(.el-table) {
--el-table-header-text-color: #606266;
--el-table-row-hover-bg-color: #f5f7fa;
}
.disabled-input {
background-color: #f5f7fa !important; /* ElementUI disabled 背景色 */
border: 1px solid #e5e6eb !important; /* ElementUI disabled 边框色 */
color: #909399 !important; /* ElementUI disabled 文字色 */
cursor: not-allowed !important;
border-radius: 4px !important; /* 和输入框圆角一致 */
}
</style>
<template>
<div class="app-container" >
<!-- 子表搜索栏(按需求添加搜索字段) -->
<!-- 子表搜索栏 -->
<div class="page-container">
<page-wrapper-search
v-model="searchParams"
......@@ -21,74 +21,96 @@
/>
</el-form-item>
<el-form-item label="仓库" prop="warehouseId">
<common-dict-select
v-model="searchParams.warehouseId"
dict-url="/inventory/warehouses/getMapList"
value-key="warehouses_code"
label-key="warehouses_name"
<el-input
v-model="queryWarehouseName"
placeholder="请选择仓库"
@change="handleWarehouseChange"
@clear="handleWarehouseClear"
@loaded="handleDictLoaded('warehouse', $event)"
/>
readonly
@focus="openWarehouseSelector"
:suffix-icon="''"
>
<template v-if="queryWarehouseName" #suffix>
<i
class="el-icon-circle-close el-input__icon"
style="cursor: pointer;"
@click.stop="clearQueryWarehouse"
></i>
</template>
</el-input>
</el-form-item>
<el-form-item label="库位" prop="locationId">
<common-dict-select
ref="locationSelect"
v-model="searchParams.locationId"
dict-url="/inventory/locations/getMapList"
:dictParams="{ warehousesCode: searchParams.warehouseId }"
value-key="location_code"
label-key="location_name"
<el-input
v-model="queryLocationName"
placeholder="请选择库位"
:disabled="!searchParams.warehouseId"
@change="handleQuery"
@loaded="handleDictLoaded('location', $event)"
/>
readonly
@focus="openLocationSelector"
:suffix-icon="''"
:disabled="!searchParams.warehousesCode"
>
<template v-if="queryLocationName" #suffix>
<i
class="el-icon-circle-close el-input__icon"
style="cursor: pointer;"
@click.stop="clearQueryLocation"
></i>
</template>
</el-input>
</el-form-item>
</page-wrapper-search>
<!-- 仓库选择组件 -->
<WarehouseSelector
v-model="warehouseSelectorVisible"
@selected="handleWarehouseSelected"
/>
<!-- 库位选择组件 -->
<LocationSelector
v-model="locationSelectorVisible"
:warehousesId="currentWarehouseId"
@selected="handleLocationSelected"
/>
<!-- 表格 -->
<div class="table-container">
<el-table :data="filteredItemsList"
:row-class-name="setRowIndex"
@selection-change="handleSelectionChange"
border
size="small">
<el-table-column label="子表ID" align="center" prop="id" v-if="false" />
<el-table-column label="物料" prop="materialId" fixed>
<el-table-column label="子表ID" align="center" width="150px" prop="id" v-if="false" />
<el-table-column label="物料" prop="materialId" width="150px" fixed>
<template slot-scope="scope">
<!-- {{ getDictLabel(materialDict, scope.row.materialId, 'sap_no', 'material_name') }}-->
<div class="el-input__inner disabled-input" style="padding: 0 15px; height: 32px; line-height: 32px;">
{{ getDictLabel(materialDict, scope.row.materialId, 'sap_no', 'material_name') }}
</div>
</template>
</el-table-column>
<el-table-column label="批次编号" prop="batchCode">
<el-table-column label="批次编号" prop="batchCode" width="150px" >
<template slot-scope="scope">
<el-input v-model="scope.row.batchCode" placeholder="请输入批次编号" disabled />
</template>
</el-table-column>
<el-table-column label="仓库" prop="warehouseId">
<el-table-column label="仓库" prop="warehouseName" width="150px" >
<template slot-scope="scope">
<!-- <el-input v-model="scope.row.warehouseId" placeholder="请输入仓库ID" disabled />-->
<div class="el-input__inner disabled-input" style="padding: 0 15px; height: 32px; line-height: 32px;">
{{ getDictLabel(warehouseDict, scope.row.warehouseId, 'warehouses_code', 'warehouses_name') }}
</div>
<el-input v-model="scope.row.warehouseName" placeholder="请输入仓库" disabled />
<!-- <div class="el-input__inner disabled-input" style="padding: 0 15px; height: 32px; line-height: 32px;">-->
<!-- {{ scope.row.warehouse_name || scope.row.warehouseId || '未知仓库' }}-->
<!-- </div>-->
</template>
</el-table-column>
<el-table-column label="库位" prop="locationId">
<el-table-column label="库位" prop="locationName" width="150px" >
<template slot-scope="scope">
<div class="el-input__inner disabled-input" style="padding: 0 15px; height: 32px; line-height: 32px;">
{{ getDictLabel(locationDict, scope.row.locationId, 'location_code', 'location_name') }}
</div>
<!-- <div class="el-input__inner disabled-input" style="padding: 0 15px; height: 32px; line-height: 32px;">-->
<!-- {{ scope.row.location_name || scope.row.locationId || '未知库位' }}-->
<!-- </div>-->
<el-input v-model="scope.row.locationName" placeholder="请输入库位" disabled />
</template>
</el-table-column>
<el-table-column label="系统数量" prop="systemQuantity">
<el-table-column label="系统数量" prop="systemQuantity" width="150px" >
<template slot-scope="scope">
<el-input v-model="scope.row.systemQuantity" placeholder="请输入系统数量" disabled />
</template>
</el-table-column>
<el-table-column label="实际数量" prop="actualQuantity">
<el-table-column label="实际数量" prop="actualQuantity" width="150px" >
<template slot-scope="scope">
<el-input v-model="scope.row.actualQuantity"
placeholder="请输入实际数量"
......@@ -98,17 +120,31 @@
/>
</template>
</el-table-column>
<el-table-column label="差异数量" prop="varianceQuantity">
<el-table-column label="差异数量" prop="varianceQuantity" width="150px" >
<template slot-scope="scope">
<el-input type="number" v-model="scope.row.varianceQuantity" placeholder="请输入差异数量" disabled />
</template>
</el-table-column>
<el-table-column label="是否已调整" prop="adjusted" v-if="isConfirm">
<el-table-column label="单价" prop="unitPrice" width="150px" >
<template slot-scope="scope">
<div class="el-input__inner disabled-input" style="padding: 0 15px; height: 32px; line-height: 32px;">
{{ formatAmount(scope.row.unitPrice) }}
</div>
</template>
</el-table-column>
<el-table-column label="差异金额" prop="varianceAmount" width="150px" >
<template slot-scope="scope">
<div class="el-input__inner disabled-input" style="padding: 0 15px; height: 32px; line-height: 32px;">
{{ formatAmount(scope.row.varianceAmount) }}
</div>
</template>
</el-table-column>
<el-table-column label="是否已调整" prop="adjusted" v-if="isConfirm" width="150px" >
<template slot-scope="scope">
<el-input v-model="scope.row.adjusted" placeholder="请输入是否已调整0否1是" disabled />
</template>
</el-table-column>
<el-table-column label="调整原因" prop="adjustmentReason">
<el-table-column label="调整原因" prop="adjustmentReason" width="150px" >
<template slot-scope="scope">
<el-input
v-model="scope.row.adjustmentReason"
......@@ -120,12 +156,12 @@
/>
</template>
</el-table-column>
<el-table-column label="调整人" prop="adjustedBy" v-if="isConfirm">
<el-table-column label="调整人" prop="adjustedBy" v-if="isConfirm" width="150px" >
<template slot-scope="scope">
<el-input v-model="scope.row.adjustedBy" placeholder="请输入调整人" disabled />
</template>
</el-table-column>
<el-table-column label="调整时间" prop="adjustedAt"v-if="isConfirm">
<el-table-column label="调整时间" prop="adjustedAt"v-if="isConfirm" width="150px" >
<template slot-scope="scope">
<el-date-picker clearable v-model="scope.row.adjustedAt" type="date" value-format="yyyy-MM-dd" placeholder="请选择调整时间" disabled />
</template>
......@@ -146,9 +182,12 @@
<script>
import { getDictLabel } from '@/utils/dictUtil'
import CommonDictSelect from '@/components/CommonDictSelect.vue'
import WarehouseSelector from "@/views/compononents/WarehouseSelector.vue"
import LocationSelector from "@/views/compononents/LocationSelector.vue"
export default {
name: "stocktakeItemsTable",
components: { CommonDictSelect }, // 注册通用字典组件
components: { CommonDictSelect,WarehouseSelector,LocationSelector }, // 注册通用字典组件
props: {
// 接收父组件传递的子表原始数据(双向绑定)
itemsList: {
......@@ -168,8 +207,16 @@ export default {
materialId: "",
batchCode: "",
warehouseId: "",
warehousesCode: null,
locationId: ""
},
// 仓库选择相关
warehouseSelectorVisible: false,
queryWarehouseName: null,
// 库位选择相关
locationSelectorVisible: false,
queryLocationName: null,
currentWarehouseId: "", // 存仓库原始ID(0eb22b11...),供库位联动
checkedRows: [], // 子表选中的行
materialDict: [], // 物料字典数组(存储sap_no和name)
warehouseDict: [], // 仓库数组
......@@ -192,8 +239,8 @@ export default {
const normalizedItems = this.itemsList.map(item => ({
...item,
materialId: String(item.materialId || '').trim(),
warehouseId: String(item.warehouseId || '').trim(),
locationId: String(item.locationId || '').trim()
warehouseId: String(item.warehouseId || item.warehouses_code || '').trim(),
locationId: String(item.locationId || item.location_code || '').trim()
}))
// 精准筛选
......@@ -220,6 +267,22 @@ export default {
methods: {
// 挂载全局字典工具方法(模板中可直接调用)
getDictLabel,
// 手动加载字典(按你的字典接口规则来)
loadDict(type) {
// 字典接口地址(和你注释里的common-dict-select一致)
const dictConfig = {
// material: { url: '/inventory/materials/getMapList' },
warehouse: { url: '/inventory/warehouses/getMapList' },
// 库位字典需要传仓库编码(warehousesCode),
location: { url: '/inventory/locations/getMapList', params: { warehousesCode: this.searchParams.warehousesCode } }
}
const config = dictConfig[type]
if (!config) return
this.$http.get(config.url, { params: config.params }).then(res => {
this.handleDictLoaded(type, res.data || [])
})
},
// 仓库选择变化时触发
handleWarehouseChange(warehouseId) {
// 1. 清空库位选择
......@@ -228,18 +291,81 @@ export default {
this.searchParams.warehouseId = warehouseId
this.handleQuery()
},
/** 打开仓库选择器 */
openWarehouseSelector() {
this.warehouseSelectorVisible = true
},
// 仓库清空时触发
handleWarehouseClear() {
this.searchParams.locationId = ''
this.searchParams.warehouseId = ''
this.currentWarehouseId = ''
this.handleQuery()
},
/** 库位选择回调 */
handleLocationSelected(location) {
if (!location) return
this.searchParams.locationId = location.locationCode
this.queryLocationName = location.locationName || location.locationCode
// console.log('selected LocationName', location);
this.handleQuery()
},
/** 仓库选择回调 */
handleWarehouseSelected(warehouse) {
if (!warehouse) return
// 供库位联动:存仓库原始ID(0eb22b11...)
this.currentWarehouseId = warehouse.warehouseId
// 供列表筛选:存仓库编码333(匹配列表里的warehouseId:333
this.searchParams.warehouseId = warehouse.warehousesCode
this.searchParams.warehousesCode = warehouse.warehousesCode
this.queryWarehouseName = warehouse.warehousesName || warehouse.warehousesCode
// 仓库选择后,清空库位信息
this.queryLocationName = null
this.searchParams.locationId = null
this.handleQuery()
// console.log('selected warehouse', warehouse);
},
/** 格式化金额,保留2位小数 */
formatAmount(amount) {
if (amount === null || amount === undefined || isNaN(amount)) {
return '0.00'
}
return parseFloat(amount).toFixed(2)
},
// 搜索,补全逻辑(无后端请求,仅重置页码)
handleQuery() {
this.searchParams.pageNum = 1; // 搜索后重置页码
},
/** 清空仓库选择 */
clearQueryWarehouse() {
this.queryWarehouseName = null
this.searchParams.warehouseId = null
this.searchParams.warehousesCode = null
this.currentWarehouseId = ""
// 清空仓库时,同时清空库位
this.queryLocationName = null
this.searchParams.locationId = null
this.handleQuery()
},
/** 打开库位选择器 */
openLocationSelector() {
if (!this.currentWarehouseId) {
this.$message.warning("请先选择仓库")
return
}
this.locationSelectorVisible = true
},
/** 清空库位选择 */
clearQueryLocation() {
this.queryLocationName = null
this.searchParams.locationId = null
this.handleQuery()
},
// 重置
resetQuery() {
this.queryWarehouseName = null
this.queryLocationName = null
this.currentWarehouseId = ''
this.searchParams = {
pageNum: 1,
pageSize: 10,
......@@ -310,13 +436,17 @@ export default {
// 子表字段编辑时,同步给父组件(确保数据一致)
handleItemChange(row) {
if (!row.actualQuantity || row.actualQuantity === '') {
row.varianceAmount = null;
row.varianceQuantity = null;
row.adjustmentReason = null;
} else {
// 处理空值/非数字情况,默认0
const actualQty = Number(row.actualQuantity) || 0
const systemQty = Number(row.systemQuantity) || 0
// 计算差异:实际数量 - 系统数量
row.varianceQuantity = actualQty - systemQty
// 计算差异金额:差异数量*单价
row.varianceAmount = (row.varianceQuantity * row.unitPrice).toFixed(2) * 1
}
// 实时校验调整原因,触发样式更新
this.$nextTick(() => {
......@@ -343,16 +473,15 @@ export default {
.mb8 {
margin-bottom: 8px;
}
/* 表格样式优化 */
:deep(.el-table) {
--el-table-header-text-color: #606266;
--el-table-row-hover-bg-color: #f5f7fa;
}
.disabled-input {
background-color: #f5f7fa !important; /* ElementUI disabled 背景色 */
border: 1px solid #e5e6eb !important; /* ElementUI disabled 边框色 */
color: #909399 !important; /* ElementUI disabled 文字色 */
background-color: #f5f7fa !important;
border: 1px solid #e5e6eb !important;
color: #909399 !important;
cursor: not-allowed !important;
border-radius: 4px !important; /* 和输入框圆角一致 */
border-radius: 4px !important;
}
</style>
......@@ -4,16 +4,10 @@ import java.util.List;
import javax.servlet.http.HttpServletResponse;
import com.ruoyi.inventory.domain.TO.StocktakesTO;
import com.ruoyi.inventory.domain.TO.StocktakesVo;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
......@@ -65,10 +59,11 @@ public class StocktakesController extends BaseController
* 获取库存盘点详细信息
*/
@PreAuthorize("@ss.hasPermi('inventory:stocktakes:query')")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") String id)
@GetMapping(value = "/")
public AjaxResult getInfo(@RequestParam("id") String id,
@RequestParam(required = false) String operationType)
{
return success(stocktakesService.selectStocktakesById(id));
return success(stocktakesService.selectStocktakesById(id,operationType));
}
/**
......@@ -103,4 +98,31 @@ public class StocktakesController extends BaseController
{
return toAjax(stocktakesService.deleteStocktakesByIds(ids));
}
/**
* @description: 查询处理统计
* @author cs
* @date 2025/12/8
* @version 1.0
*/
@GetMapping("/listCount")
public TableDataInfo listCount(StocktakesVo stocktakes)
{
startPage();
List<StocktakesVo> list = stocktakesService.selectStocktakesListCount(stocktakes);
return getDataTable(list);
}
/**
* @description: 查询处理统计-详情
* @author cs
* @date 2025/12/9
* @version 1.0
*/
@GetMapping("/countInfo")
public TableDataInfo countInfo(StocktakesVo stocktakes)
{
startPage();
List<StocktakesVo> list = stocktakesService.selectStocktakesCountInfo(stocktakes);
return getDataTable(list);
}
}
......@@ -124,6 +124,18 @@ public class StocktakeItems extends BaseEntity
@Excel(name = "排序号")
private String updateUserCode;
/** 单价 */
@Excel(name = "单价")
private double unitPrice;
public double getUnitPrice() {
return unitPrice;
}
public void setUnitPrice(double unitPrice) {
this.unitPrice = unitPrice;
}
public String getInventoryId() {
return inventoryId;
}
......
......@@ -3,6 +3,7 @@ package com.ruoyi.inventory.domain;
import java.util.List;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.inventory.domain.TO.StocktakeItemsTo;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel;
......@@ -71,7 +72,7 @@ public class Stocktakes extends BaseEntity
private String updateUserCode;
/** 盘点单明细信息 */
private List<StocktakeItems> stocktakeItemsList;
private List<StocktakeItemsTo> stocktakeItemsList;
public void setId(String id)
{
......@@ -203,12 +204,12 @@ public class Stocktakes extends BaseEntity
return updateUserCode;
}
public List<StocktakeItems> getStocktakeItemsList()
public List<StocktakeItemsTo> getStocktakeItemsList()
{
return stocktakeItemsList;
}
public void setStocktakeItemsList(List<StocktakeItems> stocktakeItemsList)
public void setStocktakeItemsList(List<StocktakeItemsTo> stocktakeItemsList)
{
this.stocktakeItemsList = stocktakeItemsList;
}
......
package com.ruoyi.inventory.domain.TO;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.inventory.domain.StocktakeItems;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import java.util.Date;
/**
* 盘点单明细对象 stocktake_items
*
* @author ruoyi
* @date 2025-12-02
*/
public class StocktakeItemsTo extends StocktakeItems
{
private String warehouseName;
private String locationName;
public String getWarehouseName() {
return warehouseName;
}
public void setWarehouseName(String warehouseName) {
this.warehouseName = warehouseName;
}
public String getLocationName() {
return locationName;
}
public void setLocationName(String locationName) {
this.locationName = locationName;
}
}
package com.ruoyi.inventory.domain.TO;
import com.ruoyi.inventory.domain.Stocktakes;
import java.util.Date;
/**
* 库存盘点对象 stocktakes
*
* @author ruoyi
* @date 2025-12-02
*/
public class StocktakesVo extends Stocktakes
{
/** 提交按钮类型,check是盘点,confirm 是确认盘点 */
private String sapNo;
private String plannedDates;
private String materialId;
private String warehousesName;
private String locationName;
private String warehousesId;
private String locationId;
private String tsCode;
private String hazardName;
private String varianceQuantity;
private String varianceAmount;
private String countQuantity;
private String countAmount;
// 计划日期数组(接收拆分后的值)
private String[] plannedDateArray;
// 仓库ID数组
private String[] warehouseIdArray;
// 库位ID数组
private String[] locationIdArray;
public String[] getPlannedDateArray() {
return plannedDateArray;
}
public void setPlannedDateArray(String[] plannedDateArray) {
this.plannedDateArray = plannedDateArray;
}
public String[] getWarehouseIdArray() {
return warehouseIdArray;
}
public void setWarehouseIdArray(String[] warehouseIdArray) {
this.warehouseIdArray = warehouseIdArray;
}
public String[] getLocationIdArray() {
return locationIdArray;
}
public void setLocationIdArray(String[] locationIdArray) {
this.locationIdArray = locationIdArray;
}
public String getMaterialId() {
return materialId;
}
public String getPlannedDates() {
return plannedDates;
}
public void setPlannedDates(String plannedDates) {
this.plannedDates = plannedDates;
}
public String getLocationId() {
return locationId;
}
public void setLocationId(String locationId) {
this.locationId = locationId;
}
public void setMaterialId(String materialId) {
this.materialId = materialId;
}
public String getSapNo() {
return sapNo;
}
public void setSapNo(String sapNo) {
this.sapNo = sapNo;
}
public String getWarehousesName() {
return warehousesName;
}
public void setWarehousesName(String warehousesName) {
this.warehousesName = warehousesName;
}
public String getLocationName() {
return locationName;
}
public void setLocationName(String locationName) {
this.locationName = locationName;
}
public String getWarehousesId() {
return warehousesId;
}
public void setWarehousesId(String warehousesId) {
this.warehousesId = warehousesId;
}
public String getTsCode() {
return tsCode;
}
public void setTsCode(String tsCode) {
this.tsCode = tsCode;
}
public String getHazardName() {
return hazardName;
}
public void setHazardName(String hazardName) {
this.hazardName = hazardName;
}
public String getVarianceQuantity() {
return varianceQuantity;
}
public void setVarianceQuantity(String varianceQuantity) {
this.varianceQuantity = varianceQuantity;
}
public String getVarianceAmount() {
return varianceAmount;
}
public void setVarianceAmount(String varianceAmount) {
this.varianceAmount = varianceAmount;
}
public String getCountQuantity() {
return countQuantity;
}
public void setCountQuantity(String countQuantity) {
this.countQuantity = countQuantity;
}
public String getCountAmount() {
return countAmount;
}
public void setCountAmount(String countAmount) {
this.countAmount = countAmount;
}
}
......@@ -5,6 +5,7 @@ import java.util.List;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.inventory.domain.Inventory;
import com.ruoyi.inventory.domain.StocktakeItems;
import com.ruoyi.inventory.domain.TO.StocktakeItemsTo;
/**
* 库存Mapper接口
......@@ -79,7 +80,7 @@ public interface InventoryMapper
* @date 2025/12/3
* @version 1.0
*/
List<StocktakeItems> selectstocktakeItemsList();
List<StocktakeItemsTo> selectstocktakeItemsList();
/**
* 按物料汇总统计库存
......
package com.ruoyi.inventory.mapper;
import java.util.List;
import java.util.Map;
import com.ruoyi.inventory.domain.StocktakeItems;
import com.ruoyi.inventory.domain.TO.StocktakeItemsTo;
import com.ruoyi.inventory.domain.TO.StocktakesVo;
/**
* 盘点单明细Mapper接口
......@@ -58,4 +62,10 @@ public interface StocktakeItemsMapper
* @return 结果
*/
public int deleteStocktakeItemsByIds(String[] ids);
// 主表调用获取子表信息
public List<StocktakeItemsTo> selectStocktakeItemsByMain(Map<String, Object> query);
// 查询处理统计-详情
public List<StocktakesVo> selectStocktakesCountInfo(StocktakesVo stocktakes);
}
package com.ruoyi.inventory.mapper;
import java.util.List;
import java.util.Map;
import com.ruoyi.inventory.domain.Stocktakes;
import com.ruoyi.inventory.domain.StocktakeItems;
import com.ruoyi.inventory.domain.TO.StocktakesVo;
/**
* 盘点单主Mapper接口
......@@ -15,7 +18,6 @@ public interface StocktakesMapper
/**
* 查询盘点单主
*
* @param id 盘点单主主键
* @return 盘点单主
*/
public Stocktakes selectStocktakesById(String id);
......@@ -84,4 +86,12 @@ public interface StocktakesMapper
* @return 结果
*/
public int deleteStocktakeItemsByStocktakeId(String id);
/**
* @description: 查询处理统计
* @author cs
* @date 2025/12/8
* @version 1.0
*/
public List<StocktakesVo> selectStocktakesListCount(StocktakesVo stocktakes);
}
......@@ -7,6 +7,7 @@ import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.inventory.domain.Inventory;
import com.ruoyi.inventory.domain.OutboundOrderItems;
import com.ruoyi.inventory.domain.StocktakeItems;
import com.ruoyi.inventory.domain.TO.StocktakeItemsTo;
/**
* 库存Service接口
......@@ -88,7 +89,7 @@ public interface IInventoryService
* @date 2025/12/3
* @version 1.0
*/
public List<StocktakeItems> selectstocktakeItemsList();
public List<StocktakeItemsTo> selectstocktakeItemsList();
/**
* 按物料汇总统计库存
......
package com.ruoyi.inventory.service;
import java.util.List;
import java.util.Map;
import com.ruoyi.inventory.domain.StocktakeItems;
import com.ruoyi.inventory.domain.TO.StocktakeItemsTo;
import com.ruoyi.inventory.domain.TO.StocktakesVo;
/**
* 盘点单明细Service接口
......@@ -19,6 +23,9 @@ public interface IStocktakeItemsService
*/
public StocktakeItems selectStocktakeItemsById(String id);
// 主表调用
public List<StocktakeItemsTo> selectStocktakeItemsByMain(Map<String,Object> query);
/**
* 查询盘点单明细列表
*
......@@ -58,4 +65,7 @@ public interface IStocktakeItemsService
* @return 结果
*/
public int deleteStocktakeItemsById(String id);
// 查询处理统计-详情
public List<StocktakesVo> selectStocktakesCountInfo(StocktakesVo stocktakes);
}
package com.ruoyi.inventory.service;
import java.util.List;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.inventory.domain.Stocktakes;
import com.ruoyi.inventory.domain.TO.StocktakesTO;
import com.ruoyi.inventory.domain.TO.StocktakesVo;
import org.springframework.web.bind.annotation.GetMapping;
/**
* 库存盘点Service接口
......@@ -15,10 +19,9 @@ public interface IStocktakesService
/**
* 查询库存盘点
*
* @param id 库存盘点主键
* @return 库存盘点
*/
public Stocktakes selectStocktakesById(String id);
public Stocktakes selectStocktakesById(String id,String operationType);
/**
* 查询库存盘点列表
......@@ -59,4 +62,22 @@ public interface IStocktakesService
* @return 结果
*/
public int deleteStocktakesById(String id);
/**
* @description: 查询处理统计
* @author cs
* @date 2025/12/8
* @version 1.0
*/
public List<StocktakesVo> selectStocktakesListCount(StocktakesVo stocktakes);
/**
* @description: 查询处理统计-详情
* @author cs
* @date 2025/12/9
* @version 1.0
*/
public List<StocktakesVo> selectStocktakesCountInfo(StocktakesVo stocktakes);
}
package com.ruoyi.inventory.service.impl;
import java.util.List;
import java.util.Map;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.inventory.domain.TO.StocktakeItemsTo;
import com.ruoyi.inventory.domain.TO.StocktakesVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.inventory.mapper.StocktakeItemsMapper;
......@@ -33,6 +37,15 @@ public class StocktakeItemsServiceImpl implements IStocktakeItemsService
}
/**
* @description: 主表调用获取子表信息
* @author cs
* @date 2025/12/5
* @version 1.0
*/
public List<StocktakeItemsTo> selectStocktakeItemsByMain(Map<String,Object> query){
return stocktakeItemsMapper.selectStocktakeItemsByMain(query);
}
/**
* 查询盘点单明细列表
*
* @param stocktakeItems 盘点单明细
......@@ -93,4 +106,24 @@ public class StocktakeItemsServiceImpl implements IStocktakeItemsService
{
return stocktakeItemsMapper.deleteStocktakeItemsById(id);
}
// 查询处理统计-详情
@Override
public List<StocktakesVo> selectStocktakesCountInfo(StocktakesVo stocktakes){
String plannedDates = stocktakes.getPlannedDates();
String warehousesId = stocktakes.getWarehousesId();
String locationId = stocktakes.getLocationId();
if (plannedDates != null && !plannedDates.isEmpty()) {
stocktakes.setPlannedDateArray(plannedDates.split(","));
}
// 2. 拆分仓库ID
if (warehousesId != null && !warehousesId.isEmpty()) {
stocktakes.setWarehouseIdArray(warehousesId.split(","));
}
// 3. 拆分库位ID
if (locationId != null && !locationId.isEmpty()) {
stocktakes.setLocationIdArray(locationId.split(","));
}
return stocktakeItemsMapper.selectStocktakesCountInfo(stocktakes);
}
}
package com.ruoyi.inventory.service.impl;
import java.util.Date;
import java.util.List;
import java.util.*;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.inventory.domain.Inventory;
import com.ruoyi.inventory.domain.InventoryTransactions;
import com.ruoyi.inventory.domain.TO.StocktakeItemsTo;
import com.ruoyi.inventory.domain.TO.StocktakesTO;
import com.ruoyi.inventory.domain.TO.StocktakesVo;
import com.ruoyi.inventory.mapper.StocktakeItemsMapper;
import com.ruoyi.inventory.service.IInventoryService;
import com.ruoyi.inventory.service.IInventoryTransactionsService;
import com.ruoyi.inventory.service.IStocktakeItemsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import com.ruoyi.common.utils.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.inventory.domain.StocktakeItems;
import com.ruoyi.inventory.mapper.StocktakesMapper;
import com.ruoyi.inventory.domain.Stocktakes;
import com.ruoyi.inventory.service.IStocktakesService;
import org.springframework.web.bind.annotation.GetMapping;
/**
* 盘点单主Service业务层处理
......@@ -51,9 +54,21 @@ public class StocktakesServiceImpl implements IStocktakesService
* @return 盘点单主
*/
@Override
public Stocktakes selectStocktakesById(String id)
public Stocktakes selectStocktakesById(String id,String operationType)
{
return stocktakesMapper.selectStocktakesById(id);
// 获取主表信息
Stocktakes stocktakes = stocktakesMapper.selectStocktakesById(id);
// 获取子表信息
Map<String,Object> query = new HashMap<>();
query.put("stocktake_id",id);
if("confirm".equals(operationType)){
// 盘点确认时只查看 变更的
query.put("adjusted",1);
}
List<StocktakeItemsTo> stocktakeItems = stocktakeItemsService.selectStocktakeItemsByMain(query);
stocktakes.setStocktakeItemsList(stocktakeItems);
return stocktakes;
}
/**
......@@ -93,7 +108,7 @@ public class StocktakesServiceImpl implements IStocktakesService
Inventory inventory = new Inventory();
inventory.setInventoryStatus(1L);
inventory.setIsUsed(1L);
List<StocktakeItems> stocktakeItemsList = inventoryService.selectstocktakeItemsList();
List<StocktakeItemsTo> stocktakeItemsList = inventoryService.selectstocktakeItemsList();
stocktakes.setStocktakeItemsList(stocktakeItemsList);
insertStocktakeItems(stocktakes);
return rows;
......@@ -122,8 +137,8 @@ public class StocktakesServiceImpl implements IStocktakesService
Date nowDate = DateUtils.getNowDate();//统一调整时间
if("check".equals(operationType)){
// 盘点提交
List<StocktakeItems> stocktakeItemsList = stocktakes.getStocktakeItemsList();
for (StocktakeItems stocktakeItems : stocktakeItemsList) {
List<StocktakeItemsTo> stocktakeItemsList = stocktakes.getStocktakeItemsList();
for (StocktakeItemsTo stocktakeItems : stocktakeItemsList) {
stocktakeItems.setAdjustedBy(loginUserId);//调整人
stocktakeItems.setAdjustedAt(nowDate);//调整时间
stocktakeItems.setUpdateUserCode(loginUserId);//更新人
......@@ -150,15 +165,16 @@ public class StocktakesServiceImpl implements IStocktakesService
if("confirm".equals(operationType)){
// 确认盘点 提交
// 库存表根据子表数据更新库存量 --因为盘点确认时查询的就是有调整的子表数据,又因为库存操作表需要的货主id子表中没有,所以需要根据id查询库存表
List<StocktakeItems> stocktakeItemsList = stocktakes.getStocktakeItemsList();
for (StocktakeItems stocktakeItems : stocktakeItemsList) {
List<StocktakeItemsTo> stocktakeItemsList = stocktakes.getStocktakeItemsList();
for (StocktakeItemsTo stocktakeItems : stocktakeItemsList) {
// 获取实际数量
Long actualQuantity = stocktakeItems.getActualQuantity();
// 库存表id
String inventoryId = stocktakeItems.getInventoryId();
// 变更前数量 之所以不用库存表中的数量,是因为变更是从盘点计划时开始算的
Long quantity = stocktakeItems.getSystemQuantity();
// 获取库存信息
Inventory inv = inventoryService.selectInventoryById(inventoryId);
Long quantity = inv.getQuantity(); // 变更前数量
inv.setUpdateTime(nowDate);//更新时间
inv.setUpdateUserCode(loginUserId);//更新人
inv.setQuantity(actualQuantity);// 更新实际数量
......@@ -236,7 +252,7 @@ public class StocktakesServiceImpl implements IStocktakesService
*/
public void insertStocktakeItems(Stocktakes stocktakes)
{
List<StocktakeItems> stocktakeItemsList = stocktakes.getStocktakeItemsList();
List<StocktakeItemsTo> stocktakeItemsList = stocktakes.getStocktakeItemsList();
String stocktakeid = stocktakes.getId(); // 盘点单号
String createUserCode = stocktakes.getCreateUserCode();// 创建人
Date createTime = stocktakes.getCreateTime();// 创建日期
......@@ -253,6 +269,7 @@ public class StocktakesServiceImpl implements IStocktakesService
stocktakeItems.setCreateUserCode(createUserCode);
stocktakeItems.setCreateTime(createTime);
list.add(stocktakeItems);
}
if (list.size() > 0)
{
......@@ -260,4 +277,29 @@ public class StocktakesServiceImpl implements IStocktakesService
}
}
}
/**
* @description: 查询处理统计
* @author cs
* @date 2025/12/8
* @version 1.0
*/
@Override
public List<StocktakesVo> selectStocktakesListCount(StocktakesVo stocktakes)
{
List<StocktakesVo> list = stocktakesMapper.selectStocktakesListCount(stocktakes);
return list;
}
/**
* @description: 查询处理统计-详情
* @author cs
* @date 2025/12/9
* @version 1.0
*/
@Override
public List<StocktakesVo> selectStocktakesCountInfo(StocktakesVo stocktakes)
{
List<StocktakesVo> list = stocktakeItemsService.selectStocktakesCountInfo(stocktakes);
return list;
}
}
......@@ -32,13 +32,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="warehousesId" column="warehouses_id" />
</resultMap>
<resultMap type="StocktakeItems" id="StocktakeItemsResult">
<resultMap type="com.ruoyi.inventory.domain.TO.StocktakeItemsTo" id="StocktakeItemsResult">
<result property="id" column="id" />
<result property="stocktakeId" column="stocktake_id" />
<result property="materialId" column="material_id" />
<result property="batchCode" column="batch_code" />
<result property="warehouseId" column="warehouse_id" />
<result property="locationId" column="location_id" />
<result property="warehouseName" column="warehouse_name" />
<result property="locationName" column="location_name" />
<result property="systemQuantity" column="system_quantity" />
<result property="actualQuantity" column="actual_quantity" />
<result property="varianceQuantity" column="variance_quantity" />
......@@ -52,7 +54,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="adjustedAt" column="adjusted_at" />
<result property="startTime" column="start_time" />
<result property="endTime" column="end_time" />
<result property="materialRange" column="material_range" />
<result property="locationRange" column="location_range" />
<result property="remark" column="remark" />
<result property="isUsed" column="is_used" />
<result property="sortNo" column="sort_no" />
<result property="createTime" column="create_time" />
<result property="createUserCode" column="create_user_code" />
<result property="updateTime" column="update_time" />
<result property="updateUserCode" column="update_user_code" />
<result property="inventoryId" column="inventory_id" />
<result property="unitPrice" column="unit_price" />
</resultMap>
<resultMap type="com.ruoyi.inventory.domain.vo.InventorySummaryVO" id="InventorySummaryResult">
......@@ -189,7 +201,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</select>
<select id="selectstocktakeItemsList" resultMap="StocktakeItemsResult">
select material_id, batch_id, location_id, warehouse_id, quantity as system_quantity
select id as inventory_id,material_id, batch_id, location_id, warehouses_id as warehouse_id, quantity as system_quantity
from inventory
where is_used = 1 and inventory_status = 1
order by warehouse_id,location_id,material_id
......
......@@ -4,13 +4,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.inventory.mapper.StocktakeItemsMapper">
<resultMap type="StocktakeItems" id="StocktakeItemsResult">
<resultMap type="com.ruoyi.inventory.domain.TO.StocktakeItemsTo" id="StocktakeItemsResult">
<result property="id" column="id" />
<result property="stocktakeId" column="stocktake_id" />
<result property="materialId" column="material_id" />
<result property="batchCode" column="batch_code" />
<result property="warehouseId" column="warehouse_id" />
<result property="locationId" column="location_id" />
<result property="warehouseName" column="warehouse_name" />
<result property="locationName" column="location_name" />
<result property="systemQuantity" column="system_quantity" />
<result property="actualQuantity" column="actual_quantity" />
<result property="varianceQuantity" column="variance_quantity" />
......@@ -34,10 +36,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="updateTime" column="update_time" />
<result property="updateUserCode" column="update_user_code" />
<result property="inventoryId" column="inventory_id" />
<result property="unitPrice" column="unit_price" />
</resultMap>
<sql id="selectStocktakeItemsVo">
select id, inventory_id, stocktake_id, material_id, batch_code, warehouse_id, location_id, system_quantity, actual_quantity, variance_quantity, variance_amount, stocktake_status, counted_by, counted_at, adjusted, adjustment_reason, adjusted_by, adjusted_at, start_time, end_time, material_range, location_range, remark, is_used, sort_no, create_time, create_user_code, update_time, update_user_code from stocktake_items
select id, inventory_id,unit_price, stocktake_id, material_id, batch_code, warehouse_id, location_id, system_quantity, actual_quantity, variance_quantity, variance_amount, stocktake_status, counted_by, counted_at, adjusted, adjustment_reason, adjusted_by, adjusted_at, start_time, end_time, material_range, location_range, remark, is_used, sort_no, create_time, create_user_code, update_time, update_user_code from stocktake_items
</sql>
<select id="selectStocktakeItemsList" parameterType="StocktakeItems" resultMap="StocktakeItemsResult">
......@@ -67,6 +70,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="sortNo != null "> and sort_no = #{sortNo}</if>
<if test="createUserCode != null and createUserCode != ''"> and create_user_code = #{createUserCode}</if>
<if test="updateUserCode != null and updateUserCode != ''"> and update_user_code = #{updateUserCode}</if>
<if test="unitPrice != null and unitPrice != ''"> and unit_price = #{unitPrice}</if>
</where>
</select>
......@@ -75,6 +79,80 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
where id = #{id}
</select>
<select id="selectStocktakeItemsByMain" parameterType="java.util.Map" resultMap="StocktakeItemsResult">
select st_it.id
, st_it.inventory_id
,st_it.unit_price
, st_it.stocktake_id
, st_it.material_id
, st_it.batch_code
, st_it.warehouse_id
, st_it.location_id
, st_it.system_quantity
, st_it.actual_quantity
, st_it.variance_quantity
, st_it.variance_amount
, st_it.stocktake_status
, st_it.counted_by
, st_it.counted_at
, st_it.adjusted
, st_it.adjustment_reason
, st_it.adjusted_by
, st_it.adjusted_at
, st_it.start_time
, st_it.end_time
, st_it.material_range
, st_it.location_range
,(select w.warehouses_name from warehouses w where st_it.warehouse_id = w.warehouses_code and w.is_used = 1) as warehouse_name
,(select sl.location_name from storage_locations sl where st_it.location_id = sl.location_code and sl.is_used = 1) as location_name
from stocktake_items st_it
where stocktake_id = #{stocktake_id} and is_used = 1
<if test="adjusted != null and adjusted != ''"> and adjusted = #{adjusted}</if>
</select>
<!-- 查询处理统计-详情-->
<select id="selectStocktakesCountInfo" resultType="com.ruoyi.inventory.domain.TO.StocktakesVo">
select
st_it.material_id as materialId
,ma.sap_no as sapNo
,date_format(st.planned_date,'%Y%m%d') as plannedDates
,w.warehouses_name as warehousesName
,sl.location_name as locationName
,st_it.warehouse_id as warehousesId
,st_it.location_id as locationID
,ma.ts_code as tsCode
,dict.dict_label as hazardName
,IFNULL(st_it.variance_quantity, '0') as varianceQuantity
,IFNULL(st_it.variance_amount, '0') as varianceAmount
from stocktakes st
left join stocktake_items st_it on st.id = st_it.stocktake_id and st_it.is_used = 1
left join materials ma on st_it.material_id = ma.sap_no and ma.is_used = 1
left join warehouses w on st_it.warehouse_id = w.warehouses_code and w.is_used = 1
left join storage_locations sl on st_it.location_id = sl.location_code and sl.is_used = 1
left join sys_dict_data dict on ma.hazard_id = dict.dict_sort and dict.status =0 and dict.dict_type ='danger_type'
where
st.is_used = 1
<if test="materialId != null "> and st_it.material_id = #{materialId}</if>
<if test="plannedDateArray != null and plannedDateArray.length > 0">
and date_format(st.planned_date,'%Y%m%d') in
<foreach item="date" collection="plannedDateArray" open="(" separator="," close=")">
#{date}
</foreach>
</if>
<if test="warehouseIdArray != null and warehouseIdArray.length > 0">
and st_it.warehouse_id in
<foreach item="warehouse" collection="warehouseIdArray" open="(" separator="," close=")">
#{warehouse}
</foreach>
</if>
<if test="locationIdArray != null and locationIdArray.length > 0">
and st_it.location_id in
<foreach item="location" collection="locationIdArray" open="(" separator="," close=")">
#{location}
</foreach>
</if>
order by st.planned_date
</select>
<insert id="insertStocktakeItems" parameterType="StocktakeItems">
insert into stocktake_items
<trim prefix="(" suffix=")" suffixOverrides=",">
......@@ -107,6 +185,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="createUserCode != null">create_user_code,</if>
<if test="updateTime != null">update_time,</if>
<if test="updateUserCode != null">update_user_code,</if>
<if test="unitPrice != null"> unit_price,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">#{id},</if>
......@@ -138,6 +217,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="createUserCode != null">#{createUserCode},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="updateUserCode != null">#{updateUserCode},</if>
<if test="unitPrice != null"> #{unitPrice},</if>
</trim>
</insert>
......@@ -172,18 +252,23 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="createUserCode != null">create_user_code = #{createUserCode},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="updateUserCode != null">update_user_code = #{updateUserCode},</if>
<if test="unitPrice != null"> unit_price = #{unitPrice},</if>
</trim>
where id = #{id}
</update>
<delete id="deleteStocktakeItemsById" parameterType="String">
delete from stocktake_items where id = #{id}
</delete>
<update id="deleteStocktakeItemsById" parameterType="String">
update stocktake_items
set is_used = 0
where id = #{id}
</update>
<delete id="deleteStocktakeItemsByIds" parameterType="String">
delete from stocktake_items where id in
<update id="deleteStocktakeItemsByIds" parameterType="String">
update from stocktake_items
set is_used = 0
where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</update>
</mapper>
\ No newline at end of file
......@@ -23,41 +23,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="updateUserCode" column="update_user_code" />
</resultMap>
<resultMap id="StocktakesStocktakeItemsResult" type="Stocktakes" extends="StocktakesResult">
<collection property="stocktakeItemsList" ofType="StocktakeItems" column="id" select="selectStocktakeItemsList" />
</resultMap>
<resultMap type="StocktakeItems" id="StocktakeItemsResult">
<result property="id" column="id" />
<result property="stocktakeId" column="stocktake_id" />
<result property="inventoryId" column="inventory_id" />
<result property="materialId" column="material_id" />
<result property="batchCode" column="batch_code" />
<result property="warehouseId" column="warehouse_id" />
<result property="locationId" column="location_id" />
<result property="systemQuantity" column="system_quantity" />
<result property="actualQuantity" column="actual_quantity" />
<result property="varianceQuantity" column="variance_quantity" />
<result property="varianceAmount" column="variance_amount" />
<result property="stocktakeStatus" column="stocktake_status" />
<result property="countedBy" column="counted_by" />
<result property="countedAt" column="counted_at" />
<result property="adjusted" column="adjusted" />
<result property="adjustmentReason" column="adjustment_reason" />
<result property="adjustedBy" column="adjusted_by" />
<result property="adjustedAt" column="adjusted_at" />
<result property="startTime" column="start_time" />
<result property="endTime" column="end_time" />
<result property="materialRange" column="material_range" />
<result property="locationRange" column="location_range" />
<result property="remark" column="remark" />
<result property="isUsed" column="is_used" />
<result property="sortNo" column="sort_no" />
<result property="createTime" column="create_time" />
<result property="createUserCode" column="create_user_code" />
<result property="updateTime" column="update_time" />
<result property="updateUserCode" column="update_user_code" />
</resultMap>
<sql id="selectStocktakesVo">
select id, stocktake_id, stocktake_type, warehouse_id, stocktake_status, planned_date, material_range, location_range, total_variance_amount, remark, is_used, sort_no, create_time, create_user_code, update_time, update_user_code from stocktakes
......@@ -84,24 +50,52 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="sortNo != null "> and sort_no = #{sortNo}</if>
<if test="createUserCode != null and createUserCode != ''"> and create_user_code = #{createUserCode}</if>
<if test="updateUserCode != null and updateUserCode != ''"> and update_user_code = #{updateUserCode}</if>
order by create_time,planned_date,update_time desc
<!-- 数据范围过滤 -->
${params.dataScope}
</select>
<select id="selectStocktakesById" parameterType="String" resultMap="StocktakesStocktakeItemsResult">
<select id="selectStocktakesById" parameterType="String" resultMap="StocktakesResult">
select id, stocktake_id, stocktake_type, warehouse_id, stocktake_status, planned_date, material_range, location_range
, total_variance_amount, remark, is_used, sort_no, create_time, create_user_code, update_time, update_user_code
from stocktakes
where id = #{id}
</select>
<select id="selectStocktakeItemsList" resultMap="StocktakeItemsResult">
select id, inventory_id, stocktake_id, material_id, batch_code, warehouse_id, location_id, system_quantity, actual_quantity, variance_quantity, variance_amount, stocktake_status, counted_by, counted_at, adjusted, adjustment_reason, adjusted_by, adjusted_at, start_time, end_time, material_range, location_range, remark, is_used, sort_no, create_time, create_user_code, update_time, update_user_code
from stocktake_items
where stocktake_id = #{stocktake_id} and is_used = 1
<!-- 查询处理统计-->
<select id="selectStocktakesListCount" resultType="com.ruoyi.inventory.domain.TO.StocktakesVo">
select
st_it.material_id as materialId
,ma.sap_no as sapNo
,GROUP_CONCAT(DISTINCT date_format(st.planned_date,'%Y%m%d') SEPARATOR ',') as plannedDates
,GROUP_CONCAT(DISTINCT w.warehouses_name SEPARATOR ',') as warehousesName
,GROUP_CONCAT(DISTINCT sl.location_name SEPARATOR ',') as locationName
,GROUP_CONCAT(DISTINCT st_it.warehouse_id SEPARATOR ',') as warehousesId
,GROUP_CONCAT(DISTINCT st_it.location_id SEPARATOR ',') as locationId
,ma.ts_code as tsCode
,GROUP_CONCAT(DISTINCT dict.dict_label SEPARATOR ',') as hazardName
,IFNULL(sum(st_it.variance_quantity), '0') as countQuantity
,IFNULL(sum(st_it.variance_amount), '0') as countAmount
from stocktakes st
left join stocktake_items st_it on st.id = st_it.stocktake_id and st_it.is_used = 1
left join materials ma on st_it.material_id = ma.sap_no and ma.is_used = 1
left join warehouses w on st_it.warehouse_id = w.warehouses_code and w.is_used = 1
left join storage_locations sl on st_it.location_id = sl.location_code and sl.is_used = 1
left join sys_dict_data dict on ma.hazard_id = dict.dict_sort and dict.status =0 and dict.dict_type ='danger_type'
where
st.is_used = 1
<if test="materialId != null "> and st_it.material_id = #{materialId}</if>
<if test="params.beginTime != null and params.beginTime != ''"><!-- 开始时间检索 -->
AND date_format(st.planned_date,'%Y%m%d') &gt;= date_format(#{params.beginTime},'%Y%m%d')
</if>
<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
AND date_format(st.planned_date,'%Y%m%d') &lt;= date_format(#{params.endTime},'%Y%m%d')
</if>
<if test="warehouseId != null "> and st_it.warehouse_id = #{warehouseId}</if>
<if test="locationId != null "> and st_it.location_id = #{locationId}</if>
group by st_it.material_id
</select>
<insert id="insertStocktakes" parameterType="Stocktakes">
insert into stocktakes
<trim prefix="(" suffix=")" suffixOverrides=",">
......@@ -193,7 +187,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<insert id="batchStocktakeItems">
insert into stocktake_items( id, stocktake_id, inventory_id, material_id, batch_code, warehouse_id, location_id, system_quantity, actual_quantity, variance_quantity, variance_amount, stocktake_status, counted_by, counted_at, adjusted, adjustment_reason, adjusted_by, adjusted_at, start_time, end_time, material_range, location_range, remark, is_used, sort_no, create_time, create_user_code, update_time, update_user_code) values
<foreach item="item" index="index" collection="list" separator=",">
( #{item.id}, #{item.stocktakeId}, #{inventoryId}, #{item.materialId}, #{item.batchCode}, #{item.warehouseId}, #{item.locationId}, #{item.systemQuantity}, #{item.actualQuantity}, #{item.varianceQuantity}, #{item.varianceAmount}, #{item.stocktakeStatus}, #{item.countedBy}, #{item.countedAt}, #{item.adjusted}, #{item.adjustmentReason}, #{item.adjustedBy}, #{item.adjustedAt}, #{item.startTime}, #{item.endTime}, #{item.materialRange}, #{item.locationRange}, #{item.remark}, #{item.isUsed}, #{item.sortNo}, #{item.createTime}, #{item.createUserCode}, #{item.updateTime}, #{item.updateUserCode})
( #{item.id}, #{item.stocktakeId}, #{item.inventoryId}, #{item.materialId}, #{item.batchCode}, #{item.warehouseId}, #{item.locationId}, #{item.systemQuantity}, #{item.actualQuantity}, #{item.varianceQuantity}, #{item.varianceAmount}, #{item.stocktakeStatus}, #{item.countedBy}, #{item.countedAt}, #{item.adjusted}, #{item.adjustmentReason}, #{item.adjustedBy}, #{item.adjustedAt}, #{item.startTime}, #{item.endTime}, #{item.materialRange}, #{item.locationRange}, #{item.remark}, #{item.isUsed}, #{item.sortNo}, #{item.createTime}, #{item.createUserCode}, #{item.updateTime}, #{item.updateUserCode})
</foreach>
</insert>
</mapper>
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论