Commit 45790555 by yubin

Merge remote-tracking branch 'origin/master'

parents a4d031f7 4d03ec75
......@@ -49,12 +49,19 @@ export function delInbound_items(id) {
method: 'delete'
})
}
// 统计入库单明细
export function inbound_details(query){
return request({
url: '/inventory/inbound_items/details',
url: '/inventory/inbound_items/detailsList',
method: 'get',
params: query
})
}
// 明细关联信息
export function details_information(materialId){
return request({
url: 'inventory/inbound_items/detailsInformation',
method: 'get',
params: materialId
})
}
......@@ -18,3 +18,20 @@ export function exportInboundOutboundStatistics(query) {
})
}
// 查询出入库统计列表
export function listInboundDetails(query) {
return request({
url: '/inventory/statistics/listInboundDetails',
method: 'get',
params: query
})
}
// 查询出入库统计列表
export function listOutboundDetails(query) {
return request({
url: '/inventory/statistics/listOutboundDetails',
method: 'get',
params: query
})
}
......@@ -397,6 +397,44 @@ export default {
}
},
computed: {
// columns() {
// return [
// { prop: 'sapNo', label: 'SapNo', width: '150', editable: false },
// { prop: 'materialName', label: '货物名称', width: '150', editable: false },
// {
// prop: 'warehousesName',
// label: '源仓库',
// width: '150',
// editable: true,
// idProp: 'warehouseId'
// },
// {
// prop: 'locationName',
// label: '库位',
// width: '150',
// editable: true,
// idProp: 'locationId',
// codeProp: 'locationCode'
// },
// { prop: 'plannedQuantity', label: '计划数量', width: '100', type: 'number', editable: true },
// { prop: 'actualQuantity', label: '实际数量', width: '100', type: 'number', editable: true },
// // { prop: 'plannedPackages', label: '计划件数', width: '100', type: 'number', editable: true },
// { prop: 'actualPackages', label: '实际件数', width: '100', type: 'number', editable: true },
// { prop: 'divisor', label: '约数', width: '100', type: 'number', editable: true },
// { prop: 'labelColor', label: '标签颜色', width: '100', type: 'select', editable: true,
// options: labelColorOptions.map(item => ({
// value: item.value,
// label: item.label,
// raw: item.raw // 如果需要保持 raw 数据
// }))
// },
// { prop: 'voucherNumber', label: '凭证号', width: '150', editable: true },
// { prop: 'unitPrice', label: '单价', width: '100', type: 'number', editable: true },
// { prop: 'receivedBy', label: '收货人', width: '150', editable: true },
// { prop: 'labelQuantity', label: '贴标数量', width: '150',type: 'number', editable: true },
// { prop: 'remark', label: this.getRemarkLabel(), minWidth: '150', editable: true },
// ]
// },
multiple() {
return this.selectedRows.length === 0
},
......@@ -467,6 +505,18 @@ export default {
this.handlePagination()
},
methods: {
getRemarkLabel(){
if (!this.displayData || !this.displayData.orderTypeId) {
return '备注'
}
if(this.displayData.orderTypeId === 1 || this.displayData.orderTypeId === '1'){
return '收获库位'
}else if(this.displayData.orderTypeId === 2 || this.displayData.orderTypeId === '2'){
return '库位'
}else{
return '备注'
}
},
// 根据字典类型和值,获取对应的listClass(标签样式)
getDictListClass(dictType, value) {
const dictList = this.dict.type[dictType] || []
......@@ -756,7 +806,7 @@ export default {
errors.push(`第${index + 1}行:货物不能为空`)
}
if (parseFloat(item.actualQuantity) <= 0) {
errors.push(`第${index + 1}实际数量必须大于0`)
errors.push(`第${index + 1}行:实际数量必须大于0`)
}
})
return errors
......
......@@ -268,8 +268,8 @@
<el-form-item label="特殊存储要求" prop="specialRequirements">
<el-input v-model="form.specialRequirements" placeholder="请输入特殊存储要求" />
</el-form-item>
<el-form-item label="最高库存" prop="maxStockLevel">
<el-input v-model="form.maxStockLevel" placeholder="请输入最高库存" />
<el-form-item label="最低库存" prop="minStockLevel">
<el-input v-model="form.minStockLevel" placeholder="请输入最低库存" />
</el-form-item>
<el-form-item label="风险等级" prop="riskLevel">
<el-select v-model="form.riskLevel" placeholder="请选择风险等级" clearable>
......@@ -333,12 +333,12 @@
<el-form-item label="体积" prop="volume">
<el-input v-model="form.volume" placeholder="请输入体积" />
</el-form-item>
<el-form-item label="最高库存" prop="maxStockLevel">
<el-input v-model="form.maxStockLevel" placeholder="请输入最高库存" />
</el-form-item>
<el-form-item label="存储温度要求" prop="storageTemperature">
<el-input v-model="form.storageTemperature" placeholder="请输入存储温度要求" />
</el-form-item>
<el-form-item label="最低库存" prop="minStockLevel">
<el-input v-model="form.minStockLevel" placeholder="请输入最低库存" />
</el-form-item>
<el-form-item label="排序" prop="sortNo">
<el-input v-model="form.sortNo" placeholder="请输入排序" />
</el-form-item>
......@@ -479,9 +479,66 @@ export default {
// materialCode: [{ required: true, message: '请输入物料编码', trigger: 'blur' }],
materialName: [{ required: true, message: '请输入物料名称', trigger: 'blur' }],
sapNo: [{ required: true, message: '请输入SAP物料号', trigger: 'blur' }],
tsCode: [{ required: true, message: '请输入TS Code', trigger: 'blur' }]
tsCode: [{ required: true, message: '请输入TS Code', trigger: 'blur' }],
sortNo: [{ pattern: /^[0-9]\d*$/, message: '排序号必须为正整数', trigger: 'blur' }],
minStockLevel: [{ pattern: /^\d+$/, message: '最低库存必须为非负整数', trigger: 'blur' },
{ validator: (rule, value, callback) => {
if (value && Number(value) < 0) {
callback(new Error('最低库存不能为负数'));
}
callback();
}, trigger: 'blur' }
],
maxStockLevel: [{ pattern: /^\d+$/, message: '最高库存必须为非负整数', trigger: 'blur' },
{ validator: (rule, value, callback) => {
if (value && Number(value) < 0) {
callback(new Error('最高库存不能为负数'));
}
// 可选:校验最高库存 ≥ 最低库存
if (value && this.form && this.form.minStockLevel && Number(value) < Number(this.form.minStockLevel)) {
callback(new Error('最高库存不能小于最低库存'));
}
callback();
}, trigger: 'blur' }
],
shelfLifeDays: [{ pattern: /^[1-9]\d*$/, message: '保质期天数必须为非0开头的正整数', trigger: 'blur' }],
volume: [
{ pattern: /^\d+(\.\d{1,4})?$/, message: '体积必须为数字,最多保留4位小数', trigger: 'blur' },
{ validator: (rule, value, callback) => {
if (value && Number(value) < 0) {
callback(new Error('体积不能为负数'));
}
callback();
}, trigger: 'blur' }
],
unitWeight: [
{ pattern: /^\d+(\.\d{1,4})?$/, message: '单重必须为数字,最多保留4位小数', trigger: 'blur' },
{ validator: (rule, value, callback) => {
if (value && Number(value) < 0) {
callback(new Error('单重不能为负数'));
}
callback();
}, trigger: 'blur' }
],
packageWeight: [
{ pattern: /^\d+(\.\d{1,4})?$/, message: '包装重量必须为数字,最多保留4位小数', trigger: 'blur' },
{ validator: (rule, value, callback) => {
if (value && Number(value) < 0) {
callback(new Error('包装重量不能为负数'));
}
callback();
}, trigger: 'blur' }
],
totalWeight: [
{ pattern: /^\d+(\.\d{1,4})?$/, message: '总重量必须为数字,最多保留4位小数', trigger: 'blur' },
{ validator: (rule, value, callback) => {
if (value && Number(value) < 0) {
callback(new Error('总重量不能为负数'));
}
callback();
}, trigger: 'blur' }
],
},
loading: true
}
},
......
......@@ -262,7 +262,8 @@ export default {
},
rules: {
categoryCode: [{required: true, message:'请输入物料分类编码',trigger:'blur'}],
categoryName: [{required: true, message:'请输入物料分类名称', trigger:'blur'}]
categoryName: [{required: true, message:'请输入物料分类名称', trigger:'blur'}],
sortNo: [{ pattern: /^[0-9]\d*$/, message: '排序号必须为正整数', trigger: 'blur' }]
}
}
},
......
......@@ -87,12 +87,30 @@
<el-table-column label="出库次数" align="center" prop="outboundCount" min-width="100" />
<el-table-column label="入库数量" align="center" prop="inboundQuantity" min-width="120">
<template slot-scope="scope">
{{ formatNumber(scope.row.inboundQuantity) }}
<span
v-if="Number(scope.row.inboundQuantity || 0) > 0"
class="link-number"
@click="openDetailDialog('inbound', scope.row)"
>
{{ formatNumber(scope.row.inboundQuantity) }}
</span>
<span v-else>
{{ formatNumber(scope.row.inboundQuantity) }}
</span>
</template>
</el-table-column>
<el-table-column label="出库数量" align="center" prop="outboundQuantity" min-width="120">
<template slot-scope="scope">
{{ formatNumber(scope.row.outboundQuantity) }}
<span
v-if="Number(scope.row.outboundQuantity || 0) > 0"
class="link-number"
@click="openDetailDialog('outbound', scope.row)"
>
{{ formatNumber(scope.row.outboundQuantity) }}
</span>
<span v-else>
{{ formatNumber(scope.row.outboundQuantity) }}
</span>
</template>
</el-table-column>
<el-table-column label="入库总额" align="center" prop="inboundAmount" min-width="120">
......@@ -136,11 +154,43 @@
:warehousesId="queryParams.warehouseId"
@selected="handleLocationSelected"
/>
<!-- 出入库明细弹窗 -->
<el-dialog
:title="detailTitle"
:visible.sync="detailDialogVisible"
width="800px"
append-to-body
:close-on-click-modal="false"
>
<el-table
v-loading="detailLoading"
:data="detailList"
border
style="width: 100%"
max-height="500"
>
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column label="物料名称" prop="materialName" align="center" min-width="180" />
<el-table-column :label="detailType === 'inbound' ? '入库单号' : '出库单号'" prop="orderId" align="center" min-width="100" />
<el-table-column label="批次号" prop="batchNo" align="center" min-width="100" />
<el-table-column :label="detailType === 'inbound' ? '入库数量' : '出库数量'" prop="quantity" align="center" min-width="100" />
<el-table-column label="当前库存数量" v-if="detailType === 'inbound'" prop="inventoryQuantity" align="center" min-width="120" />
</el-table>
<div slot="footer" class="dialog-footer">
<el-button @click="detailDialogVisible = false">关闭</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { listInboundOutboundStatistics, exportInboundOutboundStatistics } from "@/api/inventory/inventory_statistics"
import {
listInboundOutboundStatistics,
exportInboundOutboundStatistics,
listInboundDetails,
listOutboundDetails
} from "@/api/inventory/inventory_statistics"
import RightToolbar from "@/components/RightToolbar"
import PageTitle from "@/components/PageTitle"
import WarehouseSelector from "@/views/compononents/WarehouseSelector.vue"
......@@ -181,7 +231,13 @@ export default {
queryWarehouseName: null,
// 库位选择相关
locationSelectorVisible: false,
queryLocationName: null
queryLocationName: null,
// 明细弹窗相关
detailDialogVisible: false,
detailLoading: false,
detailType: '',
detailTitle: '',
detailList: []
}
},
created() {
......@@ -269,6 +325,41 @@ export default {
this.queryParams.locationId = null
this.handleQuery()
},
/** 打开明细弹窗 */
openDetailDialog(type, row) {
this.detailType = type
this.detailTitle = type === 'inbound'
? `入库明细 - ${row.materialName || ''}`
: `出库明细 - ${row.materialName || ''}`
this.detailDialogVisible = true
this.fetchDetailList(row)
},
/** 查询明细列表 */
fetchDetailList(row) {
this.detailLoading = true
const params = { ...this.queryParams }
// 处理时间范围
if (params.dateRange && params.dateRange.length === 2) {
params.startDate = params.dateRange[0]
params.endDate = params.dateRange[1]
}
delete params.dateRange
// 当前行物料ID
params.materialId = row.materialId
const api = this.detailType === 'inbound' ? listInboundDetails : listOutboundDetails
api(params)
.then(res => {
this.detailList = res.rows || []
this.detailLoading = false
})
.catch(() => {
this.detailLoading = false
})
},
/** 格式化金额,保留2位小数 */
formatAmount(amount) {
if (amount === null || amount === undefined || isNaN(amount)) {
......@@ -327,5 +418,15 @@ export default {
.mb8 {
margin-bottom: 8px;
}
.link-number {
color: #409EFF;
cursor: pointer;
text-decoration: underline;
}
.link-number:hover {
color: #66b1ff;
}
</style>
......@@ -119,19 +119,42 @@ public class InboundOrderItemsController extends BaseController
}
/**
* 导出入库单明细列表
*/
@PreAuthorize("@ss.hasPermi('inventory:inbound_items:export')")
@Log(title = "入库单明细", businessType = BusinessType.EXPORT)
@PostMapping("/exportDetails")
public void exportDetails(HttpServletResponse response, InboundDetailsVO inboundDetailsVO)
{
List<InboundDetailsVO> list = inboundOrderItemsService.exportInboundDetails(inboundDetailsVO);
ExcelUtil<InboundDetailsVO> util = new ExcelUtil<InboundDetailsVO>(InboundDetailsVO.class);
util.exportExcel(response, list, "入库单明细数据");
}
/**
* 统计入库单物料明细
*/
@PreAuthorize("@ss.hasPermi('inventory:inbound_items:list')")
@GetMapping("/details")
@GetMapping("/detailsList")
public TableDataInfo itemDetails(InboundDetailsVO inboundDetailsVO) throws Exception
{
startPage();
System.out.println(inboundDetailsVO);
List<InboundDetailsVO> list = inboundOrderItemsService.selectInboundDetailsVOBySapNo(inboundDetailsVO);
return getDataTable(list);
}
/**
* 查看明细关联单号批次
*/
@PreAuthorize("@ss.hasPermi('inventory:inbound_items:list')")
@GetMapping("/detailsInformation")
public TableDataInfo itemDetailsByMaterialId(InboundDetailsVO inboundDetailsVO) throws Exception
{
startPage();
List<InboundDetailsVO> list = inboundOrderItemsService.selectDetailsByMaterialId(inboundDetailsVO);
return getDataTable(list);
}
/**
* 导入入库单物料明细
* (暂无用,入库导入功能统一写在inbound主表类中)
*/
......
......@@ -54,7 +54,7 @@ spring:
allow:
url-pattern: /druid/*
# 控制台管理用户名和密码
login-username: ruoyi
login-username: inventory
login-password: 123456
filter:
stat:
......
......@@ -7,6 +7,9 @@ ruoyi:
# 版权年份
copyrightYear: 2025
# 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
# 生产
# profile: /home/springboot/uploadPath
# 测试
profile: D:/ruoyi/uploadPath
# 获取ip地址开关
addressEnabled: false
......
......@@ -6,6 +6,7 @@ import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.inventory.domain.vo.InboundOutboundDetailVO;
import com.ruoyi.inventory.domain.vo.InboundOutboundStatisticsVO;
import com.ruoyi.inventory.service.IInventoryStatisticsService;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -50,5 +51,25 @@ public class InventoryStatisticsController extends BaseController {
ExcelUtil<InboundOutboundStatisticsVO> util = new ExcelUtil<>(InboundOutboundStatisticsVO.class);
util.exportExcel(response, list, "出入库统计数据");
}
/**
* 出库统计明细
*/
@GetMapping("/listOutboundDetails")
public TableDataInfo listOutboundDetails(InboundOutboundStatisticsVO query) {
startPage();
List<InboundOutboundDetailVO> list = inventoryStatisticsService.selectInboundDetails(query);
return getDataTable(list);
}
/**
* 入库统计明细
*/
@GetMapping("/listInboundDetails")
public TableDataInfo listInboundDetails(InboundOutboundStatisticsVO query) {
startPage();
List<InboundOutboundDetailVO> list = inventoryStatisticsService.selectInboundDetails(query);
return getDataTable(list);
}
}
package com.ruoyi.inventory.domain.vo;
import com.ruoyi.common.annotation.Excel;
import lombok.Data;
import java.util.Date;
@Data
public class InboundDetailsVO {
private static final long serialVersionUID = 1L;
// 基础物料字段
private String materialId;
@Excel(name = "物料SAP")
......@@ -16,21 +18,44 @@ public class InboundDetailsVO {
@Excel(name = "物料名")
private String materialName;
// 新增:TS编码(来自第一个SQL的m.ts_code)
@Excel(name = "TS编码")
private String tsCode;
// 新增:危险等级ID(来自第一个SQL的m.hazard_id)
@Excel(name = "危险等级ID")
private String hazardId;
// 新增:物料规格(来自第一个SQL的m.specification)
@Excel(name = "物料规格")
private String specification;
// 新增:物料单位(来自第一个SQL的m.material_unit)
@Excel(name = "物料单位")
private String materialUnit;
// 新增:单重(来自第一个SQL的m.unit_weight)
@Excel(name = "物料单重")
private Double unitWeight;
// 新增:计划入库数量(来自第一个SQL的SUM(ioi.planned_quantity))
@Excel(name = "计划入库数量")
private Long plannedQuantity;
@Excel(name = "入库单号")
private String orderId;
@Excel(name = "批次ID")
private String batchId;
// @Excel(name = "仓库ID")
private String warehouseId;
@Excel(name = "仓库名")
private String warehousesName;
// @Excel(name = "库位ID")
private String locationId;
@Excel(name = "库位名称") // 补充Excel注解
private String locationName;
@Excel(name = "入库数量")
......@@ -51,175 +76,11 @@ public class InboundDetailsVO {
@Excel(name = "备注")
private String remark;
@Excel(name = "入库时间")
@Excel(name = "入库时间") // 补充日期格式化
private Date inboundDate;
// 开始入库日期结束日库日期,仅作查询
private Date inboundDateStart;
private Date inboundDateEnd;
public String getMaterialId() {
return materialId;
}
public void setMaterialId(String materialId) {
this.materialId = materialId;
}
public String getMaterialName() {
return materialName;
}
public void setMaterialName(String materialName) {
this.materialName = materialName;
}
public String getOrderId() {
return orderId;
}
public void setOrderId(String orderId) {
this.orderId = orderId;
}
public String getBatchId() {
return batchId;
}
public void setBatchId(String batchId) {
this.batchId = batchId;
}
public String getWarehouseId() {
return warehouseId;
}
public void setWarehouseId(String warehouseId) {
this.warehouseId = warehouseId;
}
public String getLocationId() {
return locationId;
}
public void setLocationId(String locationId) {
this.locationId = locationId;
}
// 查询条件字段(无需Excel注解)
private Date inboundDateStart;
public Long getActualQuantity() {
return actualQuantity;
}
public void setActualQuantity(Long actualQuantity) {
this.actualQuantity = actualQuantity;
}
public Long getActualPackages() {
return actualPackages;
}
public void setActualPackages(Long actualPackages) {
this.actualPackages = actualPackages;
}
public String getLabelColor() {
return labelColor;
}
public void setLabelColor(String labelColor) {
this.labelColor = labelColor;
}
public Double getUnitPrice() {
return unitPrice;
}
public void setUnitPrice(Double unitPrice) {
this.unitPrice = unitPrice;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public Double getTotalPrice() {
return totalPrice;
}
public void setTotalPrice(Double totalPrice) {
this.totalPrice = totalPrice;
}
public Date getInboundDate() {
return inboundDate;
}
public void setInboundDate(Date inboundDate) {
this.inboundDate = inboundDate;
}
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 getSapNo() {
return sapNo;
}
public void setSapNo(String sapNo) {
this.sapNo = sapNo;
}
public Date getInboundDateStart() {
return inboundDateStart;
}
public void setInboundDateStart(Date inboundDateStart) {
this.inboundDateStart = inboundDateStart;
}
public Date getInboundDateEnd() {
return inboundDateEnd;
}
public void setInboundDateEnd(Date inboundDateEnd) {
this.inboundDateEnd = inboundDateEnd;
}
@Override
public String toString() {
return "InboundDetailsVO{" +
"materialId='" + materialId + '\'' +
", sapNo='" + sapNo + '\'' +
", materialName='" + materialName + '\'' +
", orderId='" + orderId + '\'' +
", batchId='" + batchId + '\'' +
", warehouseId='" + warehouseId + '\'' +
", warehousesName='" + warehousesName + '\'' +
", locationId='" + locationId + '\'' +
", locationName='" + locationName + '\'' +
", actualQuantity=" + actualQuantity +
", actualPackages=" + actualPackages +
", labelColor='" + labelColor + '\'' +
", unitPrice=" + unitPrice +
", totalPrice=" + totalPrice +
", remark='" + remark + '\'' +
", inboundDate=" + inboundDate +
'}';
}
private Date inboundDateEnd;
}
package com.ruoyi.inventory.domain.vo;
import lombok.Data;
/**
* 出入库明细视图对象(用于统计详情弹窗)
*/
@Data
public class InboundOutboundDetailVO {
/** 物料ID */
private String materialId;
/** 物料名称 */
private String materialName;
/** 批次号(入库批次/出库批次) */
private String batchNo;
/** 单号 */
private String orderId;
/** 出入库数量 */
private Long quantity;
/** 当前库存数量 */
private Long inventoryQuantity;
}
......@@ -38,7 +38,7 @@ public class InboundFinishTemplateVO extends BaseEntity {
private Long plannedQuantity;
@Excel(name = "件重")
private Double packageWeight;
private Double packageWeight2;
/** 约数 */
@Excel(name = "约数")
......@@ -56,7 +56,7 @@ public class InboundFinishTemplateVO extends BaseEntity {
private Long actualQuantity;
/** 库位 */
@Excel(name = "库位")
// @Excel(name = "库位")
private String locationId;
/** 仓库ID 暂无用 */
......@@ -106,7 +106,7 @@ public class InboundFinishTemplateVO extends BaseEntity {
private String orderType;
@Excel(name = "单个件重")
private Double packageWeight2;
private Double packageWeight;
/** 单价 */
// @Excel(name = "单价")
......
......@@ -62,7 +62,7 @@ public class InboundTRDCTemplateVO extends BaseEntity {
/** 备注 */
@Excel(name = "备注")
private String remark;
private String remark2;
/** 库位ID 检索条件 */
// @Excel(name = "收货库位")
......@@ -115,7 +115,7 @@ public class InboundTRDCTemplateVO extends BaseEntity {
/** 物料备注 */
// @Excel(name = "物料备注")
private String remark2;
private String remark;
/** 负责人 暂无用 */
// @Excel(name = "负责人 暂无用")
......
......@@ -73,7 +73,7 @@ public class InboundTemplateVO extends BaseEntity {
/** 库位ID 检索条件 */
@Excel(name = "收货库位")
private String relocationId;
private String remark2;
/** 标签颜色 字典,检索条件 */
@Excel(name = "标签颜色")
......@@ -122,7 +122,7 @@ public class InboundTemplateVO extends BaseEntity {
/** 物料备注 */
// @Excel(name = "物料备注")
private String remark2;
// private String remark2;
/** 负责人 暂无用 */
// @Excel(name = "负责人 暂无用")
......
......@@ -69,8 +69,19 @@ public interface InboundOrderItemsMapper
public int deleteInboundOrderItemsByIds(String[] ids);
/**
* 导出入库单明细
* @return 结果
*/
public List<InboundDetailsVO> exportInboundDetails(InboundDetailsVO inboundDetailsVO);
/**
* 统计入库单明细
* @return 结果
*/
public List<InboundDetailsVO> selectInboundDetailsVOBySapNo(InboundDetailsVO inboundDetailsVO);
/**
* 查看明细相关单号批次号等信息
* @return 结果
*/
public List<InboundDetailsVO> selectDetailsByMaterialId(InboundDetailsVO inboundDetailsVO);
}
......@@ -76,7 +76,15 @@ public interface InboundOrdersMapper
* @return 结果
*/
public int deleteInboundOrderItemsByOrderIds(String[] ids);
/**
* 批量新增入库单
*
* @param inboundOrdersList 入库单明细列表
* @return 结果
*/
public int batchInboundOrders(List<InboundOrders> inboundOrdersList);
/**
* 批量新增入库单明细
*
......
package com.ruoyi.inventory.mapper;
import com.ruoyi.inventory.domain.vo.InboundOutboundDetailVO;
import com.ruoyi.inventory.domain.vo.InboundOutboundStatisticsVO;
import org.apache.ibatis.annotations.Mapper;
......@@ -18,5 +19,15 @@ public interface InventoryStatisticsMapper {
* @return 汇总结果
*/
List<InboundOutboundStatisticsVO> selectInboundOutboundStatistics(InboundOutboundStatisticsVO query);
/**
* 入库明细(按物料+批次)
*/
List<InboundOutboundDetailVO> selectInboundDetails(InboundOutboundStatisticsVO query);
/**
* 出库明细(按物料+批次)
*/
List<InboundOutboundDetailVO> selectOutboundDetails(InboundOutboundStatisticsVO query);
}
......@@ -79,8 +79,20 @@ public interface IInboundOrderItemsService
public String importInboundOrderItems(List<InboundOrderItems> inboundOrderItems, Boolean isUpdateSupport, String operName);
/**
* 导出入库单明细
* @return 结果
*/
public List<InboundDetailsVO> exportInboundDetails(InboundDetailsVO inboundDetailsVO);
/**
* 统计入库单明细
* @return 结果
*/
public List<InboundDetailsVO> selectInboundDetailsVOBySapNo(InboundDetailsVO inboundDetailsVO);
/**
* 查看明细相关单号批次号等信息
* @return 结果
*/
public List<InboundDetailsVO> selectDetailsByMaterialId(InboundDetailsVO inboundDetailsVO);
}
package com.ruoyi.inventory.service;
import com.ruoyi.inventory.domain.vo.InboundOutboundDetailVO;
import com.ruoyi.inventory.domain.vo.InboundOutboundStatisticsVO;
import java.util.List;
......@@ -16,5 +17,15 @@ public interface IInventoryStatisticsService {
* @return 统计列表
*/
List<InboundOutboundStatisticsVO> selectInboundOutboundStatistics(InboundOutboundStatisticsVO query);
/**
* 入库明细
*/
List<InboundOutboundDetailVO> selectInboundDetails(InboundOutboundStatisticsVO query);
/**
* 出库明细
*/
List<InboundOutboundDetailVO> selectOutboundDetails(InboundOutboundStatisticsVO query);
}
......@@ -179,7 +179,17 @@ public class InboundOrderItemsServiceImpl implements IInboundOrderItemsService
}
@Override
public List<InboundDetailsVO> exportInboundDetails(InboundDetailsVO inboundDetailsVO) {
return inboundOrderItemsMapper.exportInboundDetails(inboundDetailsVO);
}
@Override
public List<InboundDetailsVO> selectInboundDetailsVOBySapNo(InboundDetailsVO inboundDetailsVO) {
return inboundOrderItemsMapper.selectInboundDetailsVOBySapNo(inboundDetailsVO);
}
@Override
public List<InboundDetailsVO> selectDetailsByMaterialId(InboundDetailsVO inboundDetailsVO) {
return inboundOrderItemsMapper.selectDetailsByMaterialId(inboundDetailsVO);
}
}
......@@ -281,7 +281,7 @@ public class InboundOrdersServiceImpl implements IInboundOrdersService
));
// 兜底:若分组结果为空,返回空的不可变Map(避免后续判空)
orderGroupMap = Optional.ofNullable(orderGroupMap).orElse(Collections.emptyMap());
// List<InboundOrders> orderList = new ArrayList<>();
// 4. 遍历每个入库单分组处理
for (Map.Entry<String, List<T>> entry : orderGroupMap.entrySet()) {
String orderKey = entry.getKey();
......@@ -295,6 +295,7 @@ public class InboundOrdersServiceImpl implements IInboundOrdersService
}
List<T> voList = entry.getValue();
InboundOrders mainDO = null;
List<InboundOrderItems> itemDOList = new ArrayList<>();
List<Inventory> inventoryList = new ArrayList<>();
try {
......@@ -305,7 +306,7 @@ public class InboundOrdersServiceImpl implements IInboundOrdersService
query.setOrderId(orderId);
query.setBatchId(batchId);
List<InboundOrders> existMain = inboundOrdersMapper.selectInboundOrdersList(query);
System.out.println(existMain);
if (existMain != null && !existMain.isEmpty()) {
if (isUpdateSupport == 0) {
// 不支持更新,跳过该入库单
......@@ -370,6 +371,7 @@ public class InboundOrdersServiceImpl implements IInboundOrdersService
}
mainDO.setOwnerId(olist.get(0).getId());
// orderList.add(mainDO);
// 插入主表
inboundOrdersMapper.insertInboundOrders(mainDO);
totalMainSuccess++;
......@@ -404,7 +406,6 @@ public class InboundOrdersServiceImpl implements IInboundOrdersService
itemDO.setInboundOrderId(mainDO.getId()); // 关联主表ID(核心!)
itemDO.setSortNo(0L);
// 反射获取remark2并设置
String remark2 = "";
try {
......@@ -475,6 +476,19 @@ public class InboundOrdersServiceImpl implements IInboundOrdersService
itemDO.setLocationId(locationId);
}
itemDOList.add(itemDO);
Double unitWeight = 0.0;
try{
if(itemDO.getPackageWeight() != null && itemDO.getActualQuantity() != null && itemDO.getActualPackages() != null){
unitWeight = itemDO.getPackageWeight() / (itemDO.getActualQuantity() / itemDO.getActualPackages());
}else{
unitWeight = itemDO.getPackageWeight() != null ? itemDO.getPackageWeight() : 0.0;
}
}catch (Exception e){
log.error("导入明细失败-入库单【{}】-SAP【{}】,实发数量和实际件数为空", orderId, sapNo, e);
throw new ServiceException("实发数量和实际件数为空");
}
Inventory inventoryDO = new Inventory(
Long.parseLong(mainDO.getOrderTypeId()),
orderId,
......@@ -483,8 +497,8 @@ public class InboundOrdersServiceImpl implements IInboundOrdersService
itemDO.getWarehouseId(),
itemDO.getLocationId(),
mainDO.getOwnerId(),
itemDO.getActualQuantity(),
itemDO.getPackageWeight() / itemDO.getActualPackages(),
itemDO.getActualQuantity() == null ? 0L : itemDO.getActualQuantity(),
unitWeight,
1L,
itemDO.getUnitPrice()
);
......@@ -533,6 +547,12 @@ public class InboundOrdersServiceImpl implements IInboundOrdersService
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
}
// try{
// totalMainSuccess = inboundOrdersMapper.batchInboundOrders(orderList);
// }catch(Exception e){
// TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
// throw new ServiceException("明细批量插入失败,成功" + totalMainSuccess + "条,总" + orderList.size() + "条");
// }
// 5. 结果汇总
if (totalMainFailure > 0 || totalItemFailure > 0) {
......
package com.ruoyi.inventory.service.impl;
import com.ruoyi.inventory.domain.vo.InboundOutboundDetailVO;
import com.ruoyi.inventory.domain.vo.InboundOutboundStatisticsVO;
import com.ruoyi.inventory.mapper.InventoryStatisticsMapper;
import com.ruoyi.inventory.service.IInventoryStatisticsService;
......@@ -21,5 +22,15 @@ public class InventoryStatisticsServiceImpl implements IInventoryStatisticsServi
public List<InboundOutboundStatisticsVO> selectInboundOutboundStatistics(InboundOutboundStatisticsVO query) {
return inventoryStatisticsMapper.selectInboundOutboundStatistics(query);
}
@Override
public List<InboundOutboundDetailVO> selectInboundDetails(InboundOutboundStatisticsVO query) {
return inventoryStatisticsMapper.selectInboundDetails(query);
}
@Override
public List<InboundOutboundDetailVO> selectOutboundDetails(InboundOutboundStatisticsVO query) {
return inventoryStatisticsMapper.selectOutboundDetails(query);
}
}
......@@ -108,5 +108,91 @@
GROUP BY t.material_id, m.material_name
ORDER BY m.material_name ASC
</select>
<!-- 出入库统计相关明细-->
<resultMap id="InOutDetailVO" type="com.ruoyi.inventory.domain.vo.InboundOutboundDetailVO">
<result column="material_id" property="materialId"/>
<result column="material_name" property="materialName"/>
<result column="batchNo" property="batchNo"/>
<result column="order_id" property="orderId"/>
<result column="quantity" property="quantity"/>
<result column="inventoryQuantity" property="inventoryQuantity"/>
</resultMap>
<select id="selectInboundDetails"
parameterType="com.ruoyi.inventory.domain.vo.InboundOutboundStatisticsVO"
resultMap="InOutDetailVO">
SELECT
i.material_id,
m1.material_name,
o.order_id,
o.batch_id as batchNo,
i.actual_quantity as quantity,
i.location_id,
inv.quantity as inventoryQuantity
FROM inbound_order_items i
LEFT JOIN inbound_orders o ON i.inbound_order_id = o.id
LEFT JOIN materials m1 ON m1.id = i.material_id
LEFT JOIN warehouses w ON w.id = i.warehouse_id
LEFT JOIN inventory inv ON inv.material_id = i.material_id and inv.order_id=i.order_id and inv.batch_id=i.batch_id and i.location_id = inv.location_id
<where>
and i.is_used = 1
<if test="warehouseId != null and warehouseId != ''">
AND i.warehouse_id = #{warehouseId}
</if>
<if test="locationId != null and locationId != ''">
AND i.location_id = #{locationId}
</if>
<if test="materialId != null and materialId != ''">
AND i.material_id = #{materialId}
</if>
<if test="warehousesCode != null and warehousesCode != ''">
AND w.warehouses_code LIKE CONCAT('%', #{warehousesCode}, '%')
</if>
<if test="startDate != null">
AND o.inbound_date &gt;= #{startDate}
</if>
<if test="endDate != null">
AND o.inbound_date &lt; DATE_ADD(#{endDate}, INTERVAL 1 DAY)
</if>
</where>
order by o.inbound_date asc
</select>
<select id="selectOutboundDetails"
parameterType="com.ruoyi.inventory.domain.vo.InboundOutboundStatisticsVO"
resultMap="InOutDetailVO">
SELECT
i.material_id,
m1.material_name,
o.order_id,
o.batch_code as batchNo,
i.actual_quantity as quantity
FROM outbound_order_items i
LEFT JOIN outbound_orders o ON i.outbound_order_id = o.id
LEFT JOIN materials m1 ON m1.id = i.material_id
LEFT JOIN warehouses w ON w.id = i.warehouse_id
<where>
i.is_used = 1
<if test="warehouseId != null and warehouseId != ''">
AND i.warehouse_id = #{warehouseId}
</if>
<if test="locationId != null and locationId != ''">
AND i.location_id = #{locationId}
</if>
<if test="materialId != null and materialId != ''">
AND i.material_id = #{materialId}
</if>
<if test="warehousesCode != null and warehousesCode != ''">
AND w.warehouses_code LIKE CONCAT('%', #{warehousesCode}, '%')
</if>
<if test="startDate != null">
AND o.inbound_date &gt;= #{startDate}
</if>
<if test="endDate != null">
AND o.inbound_date &lt; DATE_ADD(#{endDate}, INTERVAL 1 DAY)
</if>
</where>
order by i.shipped_at asc
</select>
</mapper>
......@@ -38,7 +38,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</resultMap>
<sql id="selectMaterialsVo">
select id, material_code, material_name,material_ename, sap_no, ts_code, category_code, hazard_id, specification, material_unit, unit_weight, package_weight, total_weight, volume, shelf_life_days, storage_temperature, special_requirements, is_batch_managed, is_serial_managed, min_stock_level, max_stock_level, is_used, is_active, risk_level, sort_no, create_time, create_user_code, update_time, update_user_code from materials
select id, material_code, material_name, material_ename, sap_no, ts_code, category_code, hazard_id, specification, material_unit, unit_weight, package_weight, total_weight, volume, shelf_life_days, storage_temperature, special_requirements, is_batch_managed, is_serial_managed, min_stock_level, max_stock_level, is_used, is_active, risk_level, sort_no, create_time, create_user_code, update_time, update_user_code from materials
</sql>
<select id="selectMaterialsList" parameterType="Materials" resultMap="MaterialsResult">
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论