feat(biz): 优化销售出库单功能并完善库存管理
This commit is contained in:
parent
e2b337a7d0
commit
de339b5b2b
@ -2,6 +2,7 @@ package com.ningxia.yunxi.chemmes.module.biz.controller.admin.prostorage.vo;
|
|||||||
|
|
||||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||||
import com.alibaba.excel.annotation.ExcelProperty;
|
import com.alibaba.excel.annotation.ExcelProperty;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@ -43,6 +44,7 @@ public class ProStorageRespVO {
|
|||||||
|
|
||||||
@Schema(description = "业务日期")
|
@Schema(description = "业务日期")
|
||||||
@ExcelProperty("业务日期")
|
@ExcelProperty("业务日期")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||||
private LocalDate billDate;
|
private LocalDate billDate;
|
||||||
|
|
||||||
@Schema(description = "操作人id", example = "21958")
|
@Schema(description = "操作人id", example = "21958")
|
||||||
|
|||||||
@ -9,9 +9,8 @@ import org.springframework.format.annotation.DateTimeFormat;
|
|||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
import static com.ningxia.yunxi.chemmes.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
import static com.ningxia.yunxi.chemmes.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
|
||||||
|
|
||||||
@Schema(description = "管理后台 - 销售出库单主分页 Request VO")
|
@Schema(description = "管理后台 - 销售出库单主分页 Request VO")
|
||||||
@Data
|
@Data
|
||||||
@ -19,15 +18,12 @@ import static com.ningxia.yunxi.chemmes.framework.common.util.date.DateUtils.FOR
|
|||||||
@ToString(callSuper = true)
|
@ToString(callSuper = true)
|
||||||
public class SaleDeliveryPageReqVO extends PageParam {
|
public class SaleDeliveryPageReqVO extends PageParam {
|
||||||
|
|
||||||
@Schema(description = "创建时间")
|
|
||||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
|
||||||
private LocalDateTime[] createTime;
|
|
||||||
|
|
||||||
@Schema(description = "销售出库单号(SC+年份+月份+3位流水号)")
|
@Schema(description = "销售出库单号(SC+年份+月份+3位流水号)")
|
||||||
private String saleDeliveryNo;
|
private String saleDeliveryNo;
|
||||||
|
|
||||||
@Schema(description = "单据日期")
|
@Schema(description = "单据日期")
|
||||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
|
||||||
private LocalDate[] deliveryDate;
|
private LocalDate[] deliveryDate;
|
||||||
|
|
||||||
@Schema(description = "客户id", example = "11842")
|
@Schema(description = "客户id", example = "11842")
|
||||||
|
|||||||
@ -1,33 +1,31 @@
|
|||||||
package com.ningxia.yunxi.chemmes.module.biz.controller.admin.storehouse;
|
package com.ningxia.yunxi.chemmes.module.biz.controller.admin.storehouse;
|
||||||
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
import com.ningxia.yunxi.chemmes.framework.common.pojo.CommonResult;
|
||||||
import javax.annotation.Resource;
|
|
||||||
import org.springframework.validation.annotation.Validated;
|
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
|
||||||
|
|
||||||
import javax.validation.constraints.*;
|
|
||||||
import javax.validation.*;
|
|
||||||
import javax.servlet.http.*;
|
|
||||||
import java.util.*;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import com.ningxia.yunxi.chemmes.framework.common.pojo.PageParam;
|
import com.ningxia.yunxi.chemmes.framework.common.pojo.PageParam;
|
||||||
import com.ningxia.yunxi.chemmes.framework.common.pojo.PageResult;
|
import com.ningxia.yunxi.chemmes.framework.common.pojo.PageResult;
|
||||||
import com.ningxia.yunxi.chemmes.framework.common.pojo.CommonResult;
|
|
||||||
import com.ningxia.yunxi.chemmes.framework.common.util.object.BeanUtils;
|
import com.ningxia.yunxi.chemmes.framework.common.util.object.BeanUtils;
|
||||||
import static com.ningxia.yunxi.chemmes.framework.common.pojo.CommonResult.success;
|
|
||||||
|
|
||||||
import com.ningxia.yunxi.chemmes.framework.excel.core.util.ExcelUtils;
|
import com.ningxia.yunxi.chemmes.framework.excel.core.util.ExcelUtils;
|
||||||
|
|
||||||
import com.ningxia.yunxi.chemmes.framework.operatelog.core.annotations.OperateLog;
|
import com.ningxia.yunxi.chemmes.framework.operatelog.core.annotations.OperateLog;
|
||||||
import static com.ningxia.yunxi.chemmes.framework.operatelog.core.enums.OperateTypeEnum.*;
|
import com.ningxia.yunxi.chemmes.module.biz.controller.admin.storehouse.vo.StoreHousePageReqVO;
|
||||||
|
import com.ningxia.yunxi.chemmes.module.biz.controller.admin.storehouse.vo.StoreHouseRespVO;
|
||||||
import com.ningxia.yunxi.chemmes.module.biz.controller.admin.storehouse.vo.*;
|
import com.ningxia.yunxi.chemmes.module.biz.controller.admin.storehouse.vo.StoreHouseSaveReqVO;
|
||||||
import com.ningxia.yunxi.chemmes.module.biz.dal.dataobject.storehouse.StoreHouseDO;
|
import com.ningxia.yunxi.chemmes.module.biz.dal.dataobject.storehouse.StoreHouseDO;
|
||||||
import com.ningxia.yunxi.chemmes.module.biz.service.storehouse.StoreHouseService;
|
import com.ningxia.yunxi.chemmes.module.biz.service.storehouse.StoreHouseService;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static com.ningxia.yunxi.chemmes.framework.common.pojo.CommonResult.success;
|
||||||
|
import static com.ningxia.yunxi.chemmes.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
|
||||||
|
|
||||||
@Tag(name = "管理后台 - 仓储主数据")
|
@Tag(name = "管理后台 - 仓储主数据")
|
||||||
@RestController
|
@RestController
|
||||||
@ -91,12 +89,13 @@ public class StoreHouseController {
|
|||||||
ExcelUtils.write(response, "仓储主数据.xls", "数据", StoreHouseRespVO.class,
|
ExcelUtils.write(response, "仓储主数据.xls", "数据", StoreHouseRespVO.class,
|
||||||
BeanUtils.toBean(list, StoreHouseRespVO.class));
|
BeanUtils.toBean(list, StoreHouseRespVO.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/get-store-house-select")
|
@GetMapping("/get-store-house-select")
|
||||||
@Operation(summary = "获得仓储下拉框数据")
|
@Operation(summary = "获得仓储下拉框数据")
|
||||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||||
@PreAuthorize("@ss.hasPermission('biz:store-house:query')")
|
@PreAuthorize("@ss.hasPermission('biz:store-house:query')")
|
||||||
public CommonResult<List<StoreHouseRespVO>> getStoreHouseSelect() {
|
public CommonResult<List<StoreHouseRespVO>> getStoreHouseSelect(@RequestParam(value = "storeType", required = false, defaultValue = "") String storeType) {
|
||||||
List<StoreHouseDO> list = storeHouseService.getStoreHouseSelect();
|
List<StoreHouseDO> list = storeHouseService.getStoreHouseSelect(storeType);
|
||||||
return success(BeanUtils.toBean(list, StoreHouseRespVO.class));
|
return success(BeanUtils.toBean(list, StoreHouseRespVO.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
package com.ningxia.yunxi.chemmes.module.biz.controller.admin.storehouse.vo;
|
package com.ningxia.yunxi.chemmes.module.biz.controller.admin.storehouse.vo;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||||
import lombok.*;
|
import com.alibaba.excel.annotation.ExcelProperty;
|
||||||
import java.util.*;
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import java.util.*;
|
|
||||||
import org.springframework.format.annotation.DateTimeFormat;
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import com.alibaba.excel.annotation.*;
|
|
||||||
import com.ningxia.yunxi.chemmes.framework.excel.core.annotations.DictFormat;
|
import com.ningxia.yunxi.chemmes.framework.excel.core.annotations.DictFormat;
|
||||||
import com.ningxia.yunxi.chemmes.framework.excel.core.convert.DictConvert;
|
import com.ningxia.yunxi.chemmes.framework.excel.core.convert.DictConvert;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
@Schema(description = "管理后台 - 仓储主数据 Response VO")
|
@Schema(description = "管理后台 - 仓储主数据 Response VO")
|
||||||
@Data
|
@Data
|
||||||
@ -21,6 +21,7 @@ public class StoreHouseRespVO {
|
|||||||
|
|
||||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
@ExcelProperty("创建时间")
|
@ExcelProperty("创建时间")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||||
private LocalDateTime createTime;
|
private LocalDateTime createTime;
|
||||||
|
|
||||||
@Schema(description = "仓储编码")
|
@Schema(description = "仓储编码")
|
||||||
|
|||||||
@ -17,8 +17,8 @@ public interface SaleDeliveryMapper extends BaseMapperX<SaleDeliveryDO> {
|
|||||||
|
|
||||||
default PageResult<SaleDeliveryDO> selectPage(SaleDeliveryPageReqVO reqVO) {
|
default PageResult<SaleDeliveryDO> selectPage(SaleDeliveryPageReqVO reqVO) {
|
||||||
return selectPage(reqVO, new LambdaQueryWrapperX<SaleDeliveryDO>()
|
return selectPage(reqVO, new LambdaQueryWrapperX<SaleDeliveryDO>()
|
||||||
.betweenIfPresent(SaleDeliveryDO::getCreateTime, reqVO.getCreateTime())
|
|
||||||
.likeIfPresent(SaleDeliveryDO::getSaleDeliveryNo, reqVO.getSaleDeliveryNo())
|
.likeIfPresent(SaleDeliveryDO::getSaleDeliveryNo, reqVO.getSaleDeliveryNo())
|
||||||
|
.likeIfPresent(SaleDeliveryDO::getCustName, reqVO.getCustName())
|
||||||
.betweenIfPresent(SaleDeliveryDO::getDeliveryDate, reqVO.getDeliveryDate())
|
.betweenIfPresent(SaleDeliveryDO::getDeliveryDate, reqVO.getDeliveryDate())
|
||||||
.eqIfPresent(SaleDeliveryDO::getDeliveryStatus, reqVO.getDeliveryStatus())
|
.eqIfPresent(SaleDeliveryDO::getDeliveryStatus, reqVO.getDeliveryStatus())
|
||||||
.eqIfPresent(SaleDeliveryDO::getDeliveryType, reqVO.getDeliveryType())
|
.eqIfPresent(SaleDeliveryDO::getDeliveryType, reqVO.getDeliveryType())
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
package com.ningxia.yunxi.chemmes.module.biz.dal.mysql.storehouse;
|
package com.ningxia.yunxi.chemmes.module.biz.dal.mysql.storehouse;
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import com.ningxia.yunxi.chemmes.framework.common.pojo.PageResult;
|
import com.ningxia.yunxi.chemmes.framework.common.pojo.PageResult;
|
||||||
import com.ningxia.yunxi.chemmes.framework.mybatis.core.query.LambdaQueryWrapperX;
|
|
||||||
import com.ningxia.yunxi.chemmes.framework.mybatis.core.mapper.BaseMapperX;
|
import com.ningxia.yunxi.chemmes.framework.mybatis.core.mapper.BaseMapperX;
|
||||||
|
import com.ningxia.yunxi.chemmes.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||||
|
import com.ningxia.yunxi.chemmes.module.biz.controller.admin.storehouse.vo.StoreHousePageReqVO;
|
||||||
import com.ningxia.yunxi.chemmes.module.biz.dal.dataobject.storehouse.StoreHouseDO;
|
import com.ningxia.yunxi.chemmes.module.biz.dal.dataobject.storehouse.StoreHouseDO;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
import com.ningxia.yunxi.chemmes.module.biz.controller.admin.storehouse.vo.*;
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 仓储主数据 Mapper
|
* 仓储主数据 Mapper
|
||||||
@ -31,8 +31,10 @@ public interface StoreHouseMapper extends BaseMapperX<StoreHouseDO> {
|
|||||||
.eq(StoreHouseDO::getStoreHouseCd, storeHouseCd).ne(ObjectUtil.isNotEmpty(id), StoreHouseDO::getId, id));
|
.eq(StoreHouseDO::getStoreHouseCd, storeHouseCd).ne(ObjectUtil.isNotEmpty(id), StoreHouseDO::getId, id));
|
||||||
}
|
}
|
||||||
|
|
||||||
default List<StoreHouseDO> getStoreHouseSelect(){
|
default List<StoreHouseDO> getStoreHouseSelect(String storeType) {
|
||||||
return selectList(new LambdaQueryWrapperX<StoreHouseDO>()
|
return selectList(new LambdaQueryWrapperX<StoreHouseDO>()
|
||||||
.eq(StoreHouseDO::getEnabledStatus, 0));
|
.eq(StoreHouseDO::getEnabledStatus, 0)
|
||||||
|
.eqIfPresent(StoreHouseDO::getStoreType, storeType));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,12 @@
|
|||||||
package com.ningxia.yunxi.chemmes.module.biz.service.storehouse;
|
package com.ningxia.yunxi.chemmes.module.biz.service.storehouse;
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import javax.validation.*;
|
|
||||||
import com.ningxia.yunxi.chemmes.module.biz.controller.admin.storehouse.vo.*;
|
|
||||||
import com.ningxia.yunxi.chemmes.module.biz.dal.dataobject.storehouse.StoreHouseDO;
|
|
||||||
import com.ningxia.yunxi.chemmes.framework.common.pojo.PageResult;
|
import com.ningxia.yunxi.chemmes.framework.common.pojo.PageResult;
|
||||||
import com.ningxia.yunxi.chemmes.framework.common.pojo.PageParam;
|
import com.ningxia.yunxi.chemmes.module.biz.controller.admin.storehouse.vo.StoreHousePageReqVO;
|
||||||
|
import com.ningxia.yunxi.chemmes.module.biz.controller.admin.storehouse.vo.StoreHouseSaveReqVO;
|
||||||
|
import com.ningxia.yunxi.chemmes.module.biz.dal.dataobject.storehouse.StoreHouseDO;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 仓储主数据 Service 接口
|
* 仓储主数据 Service 接口
|
||||||
@ -52,5 +53,5 @@ public interface StoreHouseService {
|
|||||||
*/
|
*/
|
||||||
PageResult<StoreHouseDO> getStoreHousePage(StoreHousePageReqVO pageReqVO);
|
PageResult<StoreHouseDO> getStoreHousePage(StoreHousePageReqVO pageReqVO);
|
||||||
|
|
||||||
List<StoreHouseDO> getStoreHouseSelect();
|
List<StoreHouseDO> getStoreHouseSelect(String storeType);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -79,8 +79,8 @@ public class StoreHouseServiceImpl implements StoreHouseService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<StoreHouseDO> getStoreHouseSelect() {
|
public List<StoreHouseDO> getStoreHouseSelect(String storeType) {
|
||||||
return storeHouseMapper.getStoreHouseSelect();
|
return storeHouseMapper.getStoreHouseSelect(storeType);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,6 +39,6 @@ export const exportStoreHouse = async (params) => {
|
|||||||
return await request.download({ url: `/biz/store-house/export-excel`, params })
|
return await request.download({ url: `/biz/store-house/export-excel`, params })
|
||||||
}
|
}
|
||||||
//获取仓储主数据下拉列表
|
//获取仓储主数据下拉列表
|
||||||
export const getStoreHouseSelect = async () => {
|
export const getStoreHouseSelect = async (storeType?: string) => {
|
||||||
return await request.get({ url: `/biz/store-house/get-store-house-select`})
|
return await request.get({ url: `/biz/store-house/get-store-house-select`, params: { storeType }})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -355,6 +355,13 @@ export function getCurrentMonthRange(): [string, string] {
|
|||||||
now.endOf('day').format('YYYY-MM-DD HH:mm:ss')
|
now.endOf('day').format('YYYY-MM-DD HH:mm:ss')
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
export function getCurrentSimMonthRange(): [string, string] {
|
||||||
|
const now = dayjs()
|
||||||
|
return [
|
||||||
|
now.startOf('month').format('YYYY-MM-DD'),
|
||||||
|
now.endOf('day').format('YYYY-MM-DD')
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取日期范围
|
* 获取日期范围
|
||||||
|
|||||||
@ -62,7 +62,12 @@
|
|||||||
<el-table-column label="产品编码" align="center" prop="matCode" width="120px" />
|
<el-table-column label="产品编码" align="center" prop="matCode" width="120px" />
|
||||||
<el-table-column label="产品名称" align="center" prop="matName" width="180px" />
|
<el-table-column label="产品名称" align="center" prop="matName" width="180px" />
|
||||||
<el-table-column label="规格型号" align="center" prop="spec" width="120px" />
|
<el-table-column label="规格型号" align="center" prop="spec" width="120px" />
|
||||||
<el-table-column label="单位" align="center" prop="unit" width="80px" />
|
<el-table-column label="单位" align="center" prop="unit" width="90px">
|
||||||
|
<template #default="scope">
|
||||||
|
{{ getUnitName(scope.row.unit) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<!-- 分页 -->
|
<!-- 分页 -->
|
||||||
@ -90,9 +95,23 @@ import * as InventoryApi from '@/api/biz/prostorageinventory'
|
|||||||
import * as StoreHouseApi from '@/api/biz/storehouse'
|
import * as StoreHouseApi from '@/api/biz/storehouse'
|
||||||
import * as StoreAreaApi from '@/api/biz/storearea'
|
import * as StoreAreaApi from '@/api/biz/storearea'
|
||||||
import { useMessage } from '@/hooks/web/useMessage'
|
import { useMessage } from '@/hooks/web/useMessage'
|
||||||
|
import { getDictOptions } from '@/utils/dict'
|
||||||
|
|
||||||
const message = useMessage()
|
const message = useMessage()
|
||||||
|
|
||||||
|
// 单位数据字典
|
||||||
|
const unitOptions = ref<any[]>([])
|
||||||
|
|
||||||
|
// 获取单位名称
|
||||||
|
const getUnitName = (unit: string | number) => {
|
||||||
|
if (!unit && unit !== 0) return '-'
|
||||||
|
const item = unitOptions.value.find(opt => String(opt.value) === String(unit))
|
||||||
|
return item ? item.label : unit
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化单位字典
|
||||||
|
unitOptions.value = getDictOptions('mat_unit')
|
||||||
|
|
||||||
const dialogVisible = ref(false)
|
const dialogVisible = ref(false)
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const inventoryList = ref([])
|
const inventoryList = ref([])
|
||||||
@ -114,27 +133,20 @@ const queryParams = reactive({
|
|||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
storeHouseId: undefined,
|
storeHouseId: undefined,
|
||||||
storeAreaId: undefined,
|
storeAreaId: undefined,
|
||||||
matName: undefined,
|
|
||||||
spec: undefined,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// 仓储列表(条件:store_type = '3' and enabled_status = 1)
|
// 仓储列表(条件:store_type = '3' )
|
||||||
const storeHouseList = ref([])
|
const storeHouseList = ref([])
|
||||||
|
|
||||||
// 库区列表(条件:store_house_id = 选中的仓储ID and enabled_status = 1)
|
// 库区列表(条件:store_house_id = 选中的仓储ID )
|
||||||
const storeAreaList = ref([])
|
const storeAreaList = ref([])
|
||||||
|
|
||||||
/** 获取仓储列表 */
|
/** 获取仓储列表 */
|
||||||
const getStoreHouseList = async () => {
|
const getStoreHouseList = async () => {
|
||||||
try {
|
try {
|
||||||
// 使用分页接口,传入条件:store_type = '3' and enabled_status = 1
|
// 使用专用下拉接口:get-store-house-select,条件:store_type = '3'
|
||||||
const data = await StoreHouseApi.getStoreHousePage({
|
const data = await StoreHouseApi.getStoreHouseSelect('3')
|
||||||
storeType: '3',
|
storeHouseList.value = data || []
|
||||||
enabledStatus: 1,
|
|
||||||
pageNo: 1,
|
|
||||||
pageSize: 100,
|
|
||||||
})
|
|
||||||
storeHouseList.value = data.list || []
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取仓储列表失败:', error)
|
console.error('获取仓储列表失败:', error)
|
||||||
storeHouseList.value = []
|
storeHouseList.value = []
|
||||||
@ -147,14 +159,9 @@ const getStoreAreaList = async (storeHouseId?: number) => {
|
|||||||
if (!storeHouseId) return
|
if (!storeHouseId) return
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 使用分页接口,传入条件:store_house_id = 选中的仓储ID and enabled_status = 1
|
// 使用专用下拉接口:get-store-area-select,条件:store_house_id = 选中的仓储ID and enabled_status = 1
|
||||||
const data = await StoreAreaApi.getStoreAreaPage({
|
const data = await StoreAreaApi.getStoreAreaSelect(storeHouseId)
|
||||||
storeHouseId,
|
storeAreaList.value = data || []
|
||||||
enabledStatus: 1,
|
|
||||||
pageNo: 1,
|
|
||||||
pageSize: 100,
|
|
||||||
})
|
|
||||||
storeAreaList.value = data.list || []
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取库区列表失败:', error)
|
console.error('获取库区列表失败:', error)
|
||||||
storeAreaList.value = []
|
storeAreaList.value = []
|
||||||
@ -175,13 +182,6 @@ const getList = async () => {
|
|||||||
...queryParams
|
...queryParams
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据用户需求添加模糊查询条件
|
|
||||||
if (queryParams.storeHouseId) {
|
|
||||||
params.storeHouseName = { like: '%仓库%' }
|
|
||||||
}
|
|
||||||
if (queryParams.storeAreaId) {
|
|
||||||
params.storeAreaName = { like: '%库区%' }
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = await InventoryApi.getProStorageInventoryPage(params)
|
const data = await InventoryApi.getProStorageInventoryPage(params)
|
||||||
// 按批次号升序排列
|
// 按批次号升序排列
|
||||||
@ -230,6 +230,9 @@ const resetQuery = () => {
|
|||||||
queryParams.spec = undefined
|
queryParams.spec = undefined
|
||||||
queryParams.pageNo = 1
|
queryParams.pageNo = 1
|
||||||
storeAreaList.value = []
|
storeAreaList.value = []
|
||||||
|
// 重置时不自动查询,需手动点击搜索
|
||||||
|
inventoryList.value = []
|
||||||
|
total.value = 0
|
||||||
getList()
|
getList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -13,28 +13,30 @@
|
|||||||
<el-form-item label="销售订单">
|
<el-form-item label="销售订单">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="formData.saleOrdNo"
|
v-model="formData.saleOrdNo"
|
||||||
readonly
|
disabled
|
||||||
class="cursor-not-allowed"
|
class="cursor-not-allowed"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<el-form-item label="单据日期">
|
<el-form-item label="单据日期">
|
||||||
<el-input v-model="formData.deliveryDate" readonly class="cursor-not-allowed" />
|
<el-input v-model="formData.deliveryDate" disabled class="cursor-not-allowed" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<el-form-item label="单据状态">
|
<el-form-item label="单据状态" disabled>
|
||||||
<el-tag :type="formData.deliveryStatus === '1' ? 'info' : 'success'">
|
<el-input
|
||||||
{{ formData.deliveryStatus === '1' ? '已创建' : '已确认' }}
|
v-model="deliveryTypeText"
|
||||||
</el-tag>
|
disabled
|
||||||
|
class="cursor-not-allowed"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<el-form-item label="交货方式">
|
<el-form-item label="交货方式">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="deliveryTypeText"
|
v-model="deliveryTypeText"
|
||||||
readonly
|
disabled
|
||||||
class="cursor-not-allowed"
|
class="cursor-not-allowed"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -43,39 +45,39 @@
|
|||||||
<el-row :gutter="20" class="mt-4">
|
<el-row :gutter="20" class="mt-4">
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-form-item label="客户名称">
|
<el-form-item label="客户名称">
|
||||||
<el-input v-model="formData.custName" readonly class="cursor-not-allowed" />
|
<el-input v-model="formData.custName" disabled class="cursor-not-allowed" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-form-item label="产品名称">
|
<el-form-item label="产品名称">
|
||||||
<el-input v-model="formData.materialName" readonly class="cursor-not-allowed" />
|
<el-input v-model="formData.materialName" disabled class="cursor-not-allowed" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-form-item label="规格型号">
|
<el-form-item label="规格型号">
|
||||||
<el-input v-model="formData.spec" readonly class="cursor-not-allowed" />
|
<el-input v-model="formData.spec" disabled class="cursor-not-allowed" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row :gutter="20" class="mt-4">
|
<el-row :gutter="20" class="mt-4">
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<el-form-item label="出库单号">
|
<el-form-item label="出库单号">
|
||||||
<el-input v-model="formData.saleDeliveryNo" readonly class="cursor-not-allowed" />
|
<el-input v-model="formData.saleDeliveryNo" disabled class="cursor-not-allowed" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<el-form-item label="订单数量">
|
<el-form-item label="订单数量">
|
||||||
<el-input v-model="formData.ordQty" readonly class="cursor-not-allowed" />
|
<el-input v-model="formData.ordQty" disabled class="cursor-not-allowed" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<el-form-item label="剩余数量">
|
<el-form-item label="剩余数量">
|
||||||
<el-input v-model="formData.remaimQty" readonly class="cursor-not-allowed" />
|
<el-input v-model="formData.remaimQty" disabled class="cursor-not-allowed" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<el-form-item label="发货数量">
|
<el-form-item label="发货数量">
|
||||||
<el-input v-model="formData.deliveriedQty" readonly class="cursor-not-allowed" />
|
<el-input v-model="formData.deliveriedQty" disabled class="cursor-not-allowed" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@ -85,7 +87,7 @@
|
|||||||
<el-input
|
<el-input
|
||||||
v-model="formData.remark"
|
v-model="formData.remark"
|
||||||
type="textarea"
|
type="textarea"
|
||||||
readonly
|
disabled
|
||||||
:rows="3"
|
:rows="3"
|
||||||
class="cursor-not-allowed"
|
class="cursor-not-allowed"
|
||||||
/>
|
/>
|
||||||
@ -100,17 +102,17 @@
|
|||||||
<el-row :gutter="20">
|
<el-row :gutter="20">
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-form-item label="联系人">
|
<el-form-item label="联系人">
|
||||||
<el-input v-model="formData.contact" readonly class="cursor-not-allowed" />
|
<el-input v-model="formData.contact" disabled class="cursor-not-allowed" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-form-item label="联系电话">
|
<el-form-item label="联系电话">
|
||||||
<el-input v-model="formData.conPhone" readonly class="cursor-not-allowed" />
|
<el-input v-model="formData.conPhone" disabled class="cursor-not-allowed" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-form-item label="联系地址">
|
<el-form-item label="联系地址">
|
||||||
<el-input v-model="formData.conAddress" readonly class="cursor-not-allowed" />
|
<el-input v-model="formData.conAddress" disabled class="cursor-not-allowed" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@ -186,6 +188,9 @@ const totalQty = computed(() => {
|
|||||||
const deliveryTypeText = computed(() => {
|
const deliveryTypeText = computed(() => {
|
||||||
return formData.deliveryType === '1' ? '发货' : (formData.deliveryType === '2' ? '自提' : '-')
|
return formData.deliveryType === '1' ? '发货' : (formData.deliveryType === '2' ? '自提' : '-')
|
||||||
})
|
})
|
||||||
|
const deliveryStatusText = computed(() => {
|
||||||
|
return formData.deliveryStatus === '1' ? '已创建' : (formData.deliveryStatus === '2' ? '已确认' : '-')
|
||||||
|
})
|
||||||
|
|
||||||
const getSummary = (param: any) => {
|
const getSummary = (param: any) => {
|
||||||
const { columns, data } = param
|
const { columns, data } = param
|
||||||
|
|||||||
@ -115,7 +115,20 @@
|
|||||||
<el-row :gutter="20">
|
<el-row :gutter="20">
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-form-item label="联系人" prop="contact">
|
<el-form-item label="联系人" prop="contact">
|
||||||
<el-input v-model="formData.contact" placeholder="请输入联系人" />
|
<el-select
|
||||||
|
v-model="formData.contact"
|
||||||
|
placeholder="请选择联系人"
|
||||||
|
clearable
|
||||||
|
@change="handleContactChange"
|
||||||
|
style="width: 100%"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in contactOptions"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
@ -143,17 +156,17 @@
|
|||||||
<el-table-column label="序号" type="index" width="60px" align="center" />
|
<el-table-column label="序号" type="index" width="60px" align="center" />
|
||||||
<el-table-column label="仓库(*)" prop="warehouse" width="150px" align="center">
|
<el-table-column label="仓库(*)" prop="warehouse" width="150px" align="center">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-input v-model="scope.row.warehouse" placeholder="从库存选择" readonly />
|
{{ scope.row.warehouse }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="库区(*)" prop="warehouseArea" width="150px" align="center">
|
<el-table-column label="库区(*)" prop="warehouseArea" width="150px" align="center">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-input v-model="scope.row.warehouseArea" placeholder="从库存选择" readonly />
|
{{ scope.row.warehouseArea }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="批次号(*)" prop="batchNo" width="150px" align="center">
|
<el-table-column label="批次号(*)" prop="batchNo" width="150px" align="center">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-input v-model="scope.row.batchNo" placeholder="从库存选择" readonly />
|
{{ scope.row.batchNo }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="库存数量" prop="stockQty" width="150px" align="center">
|
<el-table-column label="库存数量" prop="stockQty" width="150px" align="center">
|
||||||
@ -232,6 +245,7 @@ import { ref, reactive, computed } from 'vue'
|
|||||||
import * as SaleDeliveryApi from '@/api/biz/saledelivery'
|
import * as SaleDeliveryApi from '@/api/biz/saledelivery'
|
||||||
import * as OrderApi from '@/api/biz/tsoorder'
|
import * as OrderApi from '@/api/biz/tsoorder'
|
||||||
import * as CustomerApi from '@/api/biz/customer'
|
import * as CustomerApi from '@/api/biz/customer'
|
||||||
|
import * as InventoryApi from '@/api/biz/prostorageinventory'
|
||||||
import { watch } from 'vue'
|
import { watch } from 'vue'
|
||||||
import OrderSelectDialog from './OrderSelectDialog.vue'
|
import OrderSelectDialog from './OrderSelectDialog.vue'
|
||||||
import ProStorageInventorySelectDialog from '../prostorageinventory/ProStorageInventorySelectDialog.vue'
|
import ProStorageInventorySelectDialog from '../prostorageinventory/ProStorageInventorySelectDialog.vue'
|
||||||
@ -274,6 +288,12 @@ const formData = reactive({
|
|||||||
contact: undefined,
|
contact: undefined,
|
||||||
conPhone: undefined,
|
conPhone: undefined,
|
||||||
conAddress: undefined,
|
conAddress: undefined,
|
||||||
|
contact1: undefined,
|
||||||
|
conPhone1: undefined,
|
||||||
|
conAddress1: undefined,
|
||||||
|
contact2: undefined,
|
||||||
|
conPhone2: undefined,
|
||||||
|
conAddress2: undefined,
|
||||||
remark: undefined,
|
remark: undefined,
|
||||||
saleOrdId: undefined,
|
saleOrdId: undefined,
|
||||||
saleOrdNo: undefined,
|
saleOrdNo: undefined,
|
||||||
@ -289,6 +309,41 @@ const formData = reactive({
|
|||||||
deliveriedQty: undefined,
|
deliveriedQty: undefined,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 联系人选项列表
|
||||||
|
const contactOptions = computed(() => {
|
||||||
|
const options = []
|
||||||
|
if (formData.contact1) {
|
||||||
|
options.push({
|
||||||
|
label: formData.contact1,
|
||||||
|
value: '1',
|
||||||
|
phone: formData.conPhone1,
|
||||||
|
address: formData.conAddress1
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (formData.contact2) {
|
||||||
|
options.push({
|
||||||
|
label: formData.contact2,
|
||||||
|
value: '2',
|
||||||
|
phone: formData.conPhone2,
|
||||||
|
address: formData.conAddress2
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return options
|
||||||
|
})
|
||||||
|
|
||||||
|
// 联系人选择变更处理
|
||||||
|
const handleContactChange = (value: string) => {
|
||||||
|
if (value === '1') {
|
||||||
|
formData.contact = formData.contact1
|
||||||
|
formData.conPhone = formData.conPhone1
|
||||||
|
formData.conAddress = formData.conAddress1
|
||||||
|
} else if (value === '2') {
|
||||||
|
formData.contact = formData.contact2
|
||||||
|
formData.conPhone = formData.conPhone2
|
||||||
|
formData.conAddress = formData.conAddress2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 产品列表
|
// 产品列表
|
||||||
const productList = ref([])
|
const productList = ref([])
|
||||||
|
|
||||||
@ -359,16 +414,6 @@ const formRules = reactive({
|
|||||||
deliveryStatus: [{ required: true, message: '单据状态不能为空', trigger: 'change' }],
|
deliveryStatus: [{ required: true, message: '单据状态不能为空', trigger: 'change' }],
|
||||||
deliveriedQty: [
|
deliveriedQty: [
|
||||||
{ required: true, message: '发货数量不能为空', trigger: 'change' },
|
{ required: true, message: '发货数量不能为空', trigger: 'change' },
|
||||||
{
|
|
||||||
validator: (rule, value, callback) => {
|
|
||||||
if (value && formData.remaimQty !== undefined && Number(value) > Number(formData.remaimQty)) {
|
|
||||||
callback(new Error(`发货数量不能大于剩余数量(${formData.remaimQty})`))
|
|
||||||
} else {
|
|
||||||
callback()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
trigger: ['change', 'blur']
|
|
||||||
}
|
|
||||||
],
|
],
|
||||||
custName: [{ required: true, message: '客户名称不能为空', trigger: 'change' }],
|
custName: [{ required: true, message: '客户名称不能为空', trigger: 'change' }],
|
||||||
materialName: [{ required: true, message: '产品名称不能为空', trigger: 'change' }],
|
materialName: [{ required: true, message: '产品名称不能为空', trigger: 'change' }],
|
||||||
@ -394,6 +439,40 @@ const open = async (type: string, id?: number) => {
|
|||||||
try {
|
try {
|
||||||
const data = await SaleDeliveryApi.getSaleDelivery(id)
|
const data = await SaleDeliveryApi.getSaleDelivery(id)
|
||||||
Object.assign(formData, data)
|
Object.assign(formData, data)
|
||||||
|
|
||||||
|
// 保存两个联系人的信息
|
||||||
|
formData.contact1 = data.contact1
|
||||||
|
formData.conPhone1 = data.conPhone1
|
||||||
|
formData.conAddress1 = data.conAddress1
|
||||||
|
formData.contact2 = data.contact2
|
||||||
|
formData.conPhone2 = data.conPhone2
|
||||||
|
formData.conAddress2 = data.conAddress2
|
||||||
|
|
||||||
|
// 判断当前选择的联系人
|
||||||
|
// 注意:后端返回的 contact 可能是联系人名称,也可能是 '1' 或 '2'
|
||||||
|
const originalContact = data.contact
|
||||||
|
if (originalContact === '1' || (data.contact1 && originalContact === data.contact1)) {
|
||||||
|
formData.contact = '1'
|
||||||
|
formData.conPhone = data.conPhone1 || data.conPhone
|
||||||
|
formData.conAddress = data.conAddress1 || data.conAddress
|
||||||
|
} else if (originalContact === '2' || (data.contact2 && originalContact === data.contact2)) {
|
||||||
|
formData.contact = '2'
|
||||||
|
formData.conPhone = data.conPhone2 || data.conPhone
|
||||||
|
formData.conAddress = data.conAddress2 || data.conAddress
|
||||||
|
} else {
|
||||||
|
// 如果都不匹配,且有contact1,则默认选择contact1
|
||||||
|
if (data.contact1) {
|
||||||
|
formData.contact = '1'
|
||||||
|
formData.conPhone = data.conPhone1
|
||||||
|
formData.conAddress = data.conAddress1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果客户ID存在,从客户信息获取联系人(如果发货单数据中没有联系人信息)
|
||||||
|
if (data.custId && (!data.contact1 && !data.contact2)) {
|
||||||
|
await loadCustomerContact(data.custId)
|
||||||
|
}
|
||||||
|
|
||||||
// 加载产品列表 - 支持多种字段名,并映射字段
|
// 加载产品列表 - 支持多种字段名,并映射字段
|
||||||
let itemsData = []
|
let itemsData = []
|
||||||
if (data.items && data.items.length > 0) {
|
if (data.items && data.items.length > 0) {
|
||||||
@ -481,7 +560,6 @@ const openOrderSelect = () => {
|
|||||||
|
|
||||||
/** 处理订单选择 */
|
/** 处理订单选择 */
|
||||||
const handleOrderSelect = async (data: any) => {
|
const handleOrderSelect = async (data: any) => {
|
||||||
console.log('handleOrderSelect data:', data)
|
|
||||||
formData.saleOrdId = data.saleOrdId
|
formData.saleOrdId = data.saleOrdId
|
||||||
formData.saleOrdNo = data.saleOrdNo
|
formData.saleOrdNo = data.saleOrdNo
|
||||||
formData.custId = data.custId
|
formData.custId = data.custId
|
||||||
@ -495,28 +573,6 @@ const handleOrderSelect = async (data: any) => {
|
|||||||
formData.deliveriedQty = data.remaimQty
|
formData.deliveriedQty = data.remaimQty
|
||||||
formData.unit = data.unit
|
formData.unit = data.unit
|
||||||
|
|
||||||
// 将订单日期带入到单据日期
|
|
||||||
if (data.ordDate) {
|
|
||||||
// 确保日期格式为 YYYY-MM-DD 字符串类型
|
|
||||||
const ordDateStr = String(data.ordDate).trim()
|
|
||||||
if (/^\d{4}-\d{2}-\d{2}$/.test(ordDateStr)) {
|
|
||||||
formData.deliveryDate = ordDateStr
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
const date = new Date(data.ordDate)
|
|
||||||
if (!isNaN(date.getTime())) {
|
|
||||||
formData.deliveryDate = date.toISOString().split('T')[0]
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.warn('日期转换失败:', e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 如果没有订单日期,清空单据日期
|
|
||||||
formData.deliveryDate = null
|
|
||||||
}
|
|
||||||
console.log('formData after set:', formData)
|
|
||||||
|
|
||||||
// 添加到选项列表以便显示
|
// 添加到选项列表以便显示
|
||||||
if (!saleOrderOptions.value.find(item => item.id === data.saleOrdId)) {
|
if (!saleOrderOptions.value.find(item => item.id === data.saleOrdId)) {
|
||||||
saleOrderOptions.value.push({
|
saleOrderOptions.value.push({
|
||||||
@ -531,8 +587,20 @@ const handleOrderSelect = async (data: any) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 只有在新增模式下才查询客户联系人信息(编辑模式下已有数据)
|
// 先清空联系人信息,然后查询客户联系人信息
|
||||||
if (data.custId && formType.value === 'create') {
|
if (data.custId) {
|
||||||
|
// 清空之前的联系人信息
|
||||||
|
formData.contact1 = undefined
|
||||||
|
formData.conPhone1 = undefined
|
||||||
|
formData.conAddress1 = undefined
|
||||||
|
formData.contact2 = undefined
|
||||||
|
formData.conPhone2 = undefined
|
||||||
|
formData.conAddress2 = undefined
|
||||||
|
formData.contact = undefined
|
||||||
|
formData.conPhone = undefined
|
||||||
|
formData.conAddress = undefined
|
||||||
|
|
||||||
|
// 查询客户联系人信息
|
||||||
await loadCustomerContact(data.custId)
|
await loadCustomerContact(data.custId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -542,10 +610,24 @@ const loadCustomerContact = async (custId: number) => {
|
|||||||
try {
|
try {
|
||||||
const customer = await CustomerApi.getCustomer(custId)
|
const customer = await CustomerApi.getCustomer(custId)
|
||||||
if (customer) {
|
if (customer) {
|
||||||
|
// 保存两个联系人的信息
|
||||||
|
formData.contact1 = customer.contact1
|
||||||
|
formData.conPhone1 = customer.conPhone1
|
||||||
|
formData.conAddress1 = customer.conAddress1
|
||||||
|
formData.contact2 = customer.contact2
|
||||||
|
formData.conPhone2 = customer.conPhone2
|
||||||
|
formData.conAddress2 = customer.conAddress2
|
||||||
|
|
||||||
// 优先使用contact1,如果为空则使用contact2
|
// 优先使用contact1,如果为空则使用contact2
|
||||||
formData.contact = customer.contact1 || customer.contact2
|
if (customer.contact1) {
|
||||||
formData.conPhone = customer.conPhone1 || customer.conPhone2
|
formData.contact = '1'
|
||||||
formData.conAddress = customer.conAddress1 || customer.conAddress2
|
formData.conPhone = customer.conPhone1
|
||||||
|
formData.conAddress = customer.conAddress1
|
||||||
|
} else if (customer.contact2) {
|
||||||
|
formData.contact = '2'
|
||||||
|
formData.conPhone = customer.conPhone2
|
||||||
|
formData.conAddress = customer.conAddress2
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('查询客户联系人信息失败', error)
|
console.error('查询客户联系人信息失败', error)
|
||||||
@ -609,15 +691,14 @@ const removeProductItem = (index: number) => {
|
|||||||
const emit = defineEmits(['success', 'close'])
|
const emit = defineEmits(['success', 'close'])
|
||||||
|
|
||||||
/** 验证发货数量 */
|
/** 验证发货数量 */
|
||||||
const validateDeliveryQty = () => {
|
const validateDeliveryQty = async () => {
|
||||||
const remaimQty = parseInt(formData.remaimQty) || 0
|
|
||||||
const totalDeliveriedQty = totalQty.value
|
const totalDeliveriedQty = totalQty.value
|
||||||
|
|
||||||
// 验证每个产品项的发货袋数和发货数量不能为空且必须大于0
|
// 验证每个产品项的发货袋数和发货数量不能为空且必须大于0
|
||||||
for (let i = 0; i < productList.value.length; i++) {
|
for (let i = 0; i < productList.value.length; i++) {
|
||||||
const item = productList.value[i]
|
const item = productList.value[i]
|
||||||
const deliveriedBag = parseInt(item.deliveriedBag) || 0
|
const deliveriedBag = parseFloat(item.deliveriedBag) || 0
|
||||||
const deliveriedQty = parseInt(item.deliveriedQty) || 0
|
const deliveriedQty = parseFloat(item.deliveriedQty) || 0
|
||||||
|
|
||||||
if (!item.deliveriedBag || deliveriedBag <= 0) {
|
if (!item.deliveriedBag || deliveriedBag <= 0) {
|
||||||
message.warning(`第${i + 1}行:发货袋数不能为空且必须大于0`)
|
message.warning(`第${i + 1}行:发货袋数不能为空且必须大于0`)
|
||||||
@ -630,24 +711,84 @@ const validateDeliveryQty = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (totalDeliveriedQty > remaimQty) {
|
// 1. 验证订单剩余数量:ord_qty - deliveried_qty >= 发货数量
|
||||||
message.warning(`发货总数量(${totalDeliveriedQty})不能超过剩余数量(${remaimQty})`)
|
if (formData.saleOrdId && formData.materialName) {
|
||||||
|
try {
|
||||||
|
const orderDetail = await OrderApi.getOrder(formData.saleOrdId)
|
||||||
|
if (orderDetail && orderDetail.items) {
|
||||||
|
const item = orderDetail.items.find(i =>
|
||||||
|
i.materialName === formData.materialName &&
|
||||||
|
(!formData.spec || i.spec === formData.spec)
|
||||||
|
)
|
||||||
|
if (item) {
|
||||||
|
const ordQty = parseFloat(item.ordQty) || 0
|
||||||
|
const deliveriedQty = parseFloat(item.deliveriedQty) || 0
|
||||||
|
const remainQty = ordQty - deliveriedQty
|
||||||
|
|
||||||
|
if (isNaN(remainQty) || remainQty < totalDeliveriedQty) {
|
||||||
|
message.warning(`该订单产品剩余数量小于发货数量,请确认!`)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('查询订单剩余数量失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 验证明细表发货合计数量必须等于表单发货数量
|
||||||
|
const formDeliveriedQty = parseFloat(formData.deliveriedQty) || 0
|
||||||
|
if (totalDeliveriedQty !== formDeliveriedQty) {
|
||||||
|
message.warning(`产品发货数量跟出库单数量不一致,请确认!`)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// 验证明细表发货合计数量必须等于表单发货数量
|
// 3. 验证库存袋数:循环检查每个仓库、库区、批次号的库存袋数是否大于等于发货袋数
|
||||||
const formDeliveriedQty = parseInt(formData.deliveriedQty) || 0
|
const groupedByLot = {}
|
||||||
if (totalDeliveriedQty !== formDeliveriedQty) {
|
productList.value.forEach(item => {
|
||||||
message.warning(`明细表发货合计(${totalDeliveriedQty})必须等于表单发货数量(${formDeliveriedQty})`)
|
const key = `${item.storeHouseId}-${item.storeAreaId}-${item.batchNo}`
|
||||||
|
if (!groupedByLot[key]) {
|
||||||
|
groupedByLot[key] = {
|
||||||
|
storeHouseName: item.warehouse,
|
||||||
|
storeAreaName: item.warehouseArea,
|
||||||
|
batchNo: item.batchNo,
|
||||||
|
totalDeliveriedBag: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
groupedByLot[key].totalDeliveriedBag += parseFloat(item.deliveriedBag) || 0
|
||||||
|
})
|
||||||
|
|
||||||
|
for (const key in groupedByLot) {
|
||||||
|
const group = groupedByLot[key]
|
||||||
|
try {
|
||||||
|
const inventoryData = await InventoryApi.getProStorageInventoryPage({
|
||||||
|
storeHouseId: key.split('-')[0],
|
||||||
|
storeAreaId: key.split('-')[1],
|
||||||
|
lotNo: group.batchNo,
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: 1
|
||||||
|
})
|
||||||
|
|
||||||
|
const inventory = inventoryData.list && inventoryData.list[0]
|
||||||
|
const stockPackQty = inventory ? parseFloat(inventory.packQty) || 0 : 0
|
||||||
|
|
||||||
|
if (stockPackQty < group.totalDeliveriedBag) {
|
||||||
|
message.warning(`${group.storeHouseName} + ${group.storeAreaName} ${group.batchNo}库存袋数小于发货袋数,请确认!`)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('查询库存袋数失败:', error)
|
||||||
|
message.warning(`查询${group.storeHouseName} ${group.storeAreaName} ${group.batchNo}库存失败,请确认!`)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
const submitForm = async () => {
|
const submitForm = async () => {
|
||||||
// 校验发货数量
|
// 校验发货数量
|
||||||
if (!validateDeliveryQty()) {
|
if (!(await validateDeliveryQty())) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -695,7 +836,7 @@ const submitForm = async () => {
|
|||||||
/** 提交确认 */
|
/** 提交确认 */
|
||||||
const submitAudit = async () => {
|
const submitAudit = async () => {
|
||||||
// 校验发货数量
|
// 校验发货数量
|
||||||
if (!validateDeliveryQty()) {
|
if (!(await validateDeliveryQty())) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -754,6 +895,14 @@ const resetForm = () => {
|
|||||||
contact: undefined,
|
contact: undefined,
|
||||||
conPhone: undefined,
|
conPhone: undefined,
|
||||||
conAddress: undefined,
|
conAddress: undefined,
|
||||||
|
// 清空联系人1信息
|
||||||
|
contact1: undefined,
|
||||||
|
conPhone1: undefined,
|
||||||
|
conAddress1: undefined,
|
||||||
|
// 清空联系人2信息
|
||||||
|
contact2: undefined,
|
||||||
|
conPhone2: undefined,
|
||||||
|
conAddress2: undefined,
|
||||||
remark: undefined,
|
remark: undefined,
|
||||||
saleOrdId: undefined,
|
saleOrdId: undefined,
|
||||||
saleOrdNo: undefined,
|
saleOrdNo: undefined,
|
||||||
|
|||||||
@ -156,14 +156,14 @@
|
|||||||
<!-- 明细表格 -->
|
<!-- 明细表格 -->
|
||||||
<div style="flex: 1; min-height: 0;" >
|
<div style="flex: 1; min-height: 0;" >
|
||||||
<div style="font-weight: bold; margin-bottom: 8px;">出库单明细</div>
|
<div style="font-weight: bold; margin-bottom: 8px;">出库单明细</div>
|
||||||
<el-table v-loading="detailLoading" :data="detailList" :stripe="true" :show-overflow-tooltip="true" :summary-method="getDetailSummary" show-summary border style="width: 50%">
|
<el-table v-loading="detailLoading" :data="detailList" :stripe="true" :show-overflow-tooltip="true" :summary-method="getDetailSummary" show-summary border style="width: 100%; max-width: 1000px;" >
|
||||||
<el-table-column label="序号" align="center" type="index" width="60px"/>
|
<el-table-column label="序号" align="center" type="index" width="60px"/>
|
||||||
<el-table-column label="库区" align="center" prop="warehouseArea" width="120px" />
|
<el-table-column label="库区" align="center" prop="warehouseArea" width="120px" />
|
||||||
<el-table-column label="库位" align="center" prop="storeHouseName" width="120px" />
|
<el-table-column label="库位" align="center" prop="storeHouseName" width="120px" />
|
||||||
<el-table-column label="批次号" align="center" prop="batchNo" width="120px" />
|
<el-table-column label="批次号" align="center" prop="batchNo" width="120px" />
|
||||||
<el-table-column label="发货数量" align="center" prop="deliveriedQty" width="120px" />
|
<el-table-column label="发货数量" align="center" prop="deliveriedQty" />
|
||||||
<el-table-column label="发货袋数" align="center" prop="deliveriedBag" width="120px" />
|
<el-table-column label="发货袋数" align="center" prop="deliveriedBag" />
|
||||||
<el-table-column label="单据规格" align="center" prop="bagSpec" width="120px" />
|
<el-table-column label="单袋规格" align="center" prop="bagSpec" />
|
||||||
<el-table-column label="单位" align="center" width="80px">
|
<el-table-column label="单位" align="center" width="80px">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<dict-tag v-if="scope.row.unit" :type="DICT_TYPE.UNIT" :value="scope.row.unit" />
|
<dict-tag v-if="scope.row.unit" :type="DICT_TYPE.UNIT" :value="scope.row.unit" />
|
||||||
@ -184,8 +184,7 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, reactive } from 'vue'
|
import { ref, reactive } from 'vue'
|
||||||
import { dateFormatter, getCurrentMonthRange } from '@/utils/formatTime'
|
import { dateFormatter, getCurrentSimMonthRange } from '@/utils/formatTime'
|
||||||
import download from '@/utils/download'
|
|
||||||
import * as SaleDeliveryApi from '@/api/biz/saledelivery'
|
import * as SaleDeliveryApi from '@/api/biz/saledelivery'
|
||||||
import SaleDeliveryForm from './SaleDeliveryForm.vue'
|
import SaleDeliveryForm from './SaleDeliveryForm.vue'
|
||||||
import SaleDeliveryDetail from './SaleDeliveryDetail.vue'
|
import SaleDeliveryDetail from './SaleDeliveryDetail.vue'
|
||||||
@ -214,7 +213,7 @@ const openDetail = (id: number) => {
|
|||||||
const queryParams = reactive({
|
const queryParams = reactive({
|
||||||
pageNo: 1,
|
pageNo: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
deliveryDate: getCurrentMonthRange(),
|
deliveryDate: getCurrentSimMonthRange(),
|
||||||
saleDeliveryNo: undefined,
|
saleDeliveryNo: undefined,
|
||||||
custName: undefined,
|
custName: undefined,
|
||||||
deliveryStatus: undefined,
|
deliveryStatus: undefined,
|
||||||
@ -259,7 +258,8 @@ const getList = async () => {
|
|||||||
|
|
||||||
// 自动加载第一条数据的详情
|
// 自动加载第一条数据的详情
|
||||||
if (list.value.length > 0) {
|
if (list.value.length > 0) {
|
||||||
await viewDetail(list.value[0])
|
// await viewDetail(list.value[0])
|
||||||
|
detailList.value = []
|
||||||
} else {
|
} else {
|
||||||
// 没有数据时清空明细
|
// 没有数据时清空明细
|
||||||
detailList.value = []
|
detailList.value = []
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user