销售订单增加附件下载

This commit is contained in:
wwb 2025-12-08 11:59:50 +08:00
parent cb54921eaf
commit 9538904f0f
12 changed files with 369 additions and 8 deletions

View File

@ -69,4 +69,7 @@ public interface FileApi {
* @return {@link FileInfoVO }
*/
FileInfoVO rename(String id, String name);
byte[] getFileContent(Long configId,String path) throws Exception;
}

View File

@ -41,4 +41,11 @@ public class FileApiImpl implements FileApi {
public FileInfoVO rename(String id, String name) {
return fileService.rename(id, name);
}
@Override
public byte[] getFileContent(Long configId, String path) throws Exception {
return fileService.getFileContent(configId, path);
}
}

View File

@ -21,7 +21,8 @@ public enum BillStatusEnum {
SUBMIT("B", "待审核"),
AUDIT("C", "待排产"),
INVALID("D", "作废"),
YPLAN("E", "已排产");
YPLAN("E", "已排产"),
COMPLETED("F", "已完成");
/**
* 状态

View File

@ -31,6 +31,8 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.annotation.security.PermitAll;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
@ -204,5 +206,4 @@ public class AppSaleOrderController{
String code = saleOrderService.getNewContractCode2();
return success(code);
}
}

View File

@ -9,7 +9,10 @@ import cn.hangtag.module.oms.service.customer.CustomerService;
import cn.hangtag.module.system.api.user.AdminUserApi;
import cn.hangtag.module.system.api.user.dto.AdminUserRespDTO;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import com.alibaba.fastjson.JSONObject;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
@ -170,6 +173,16 @@ public class SaleOrderController {
}
@PostMapping("/pushOutBill")
@Operation(summary = "下推生成出货单")
@PreAuthorize("@ss.hasPermission('oms:sale-order:pushOutBill')")
public CommonResult<Boolean> pushOutBill(@RequestBody JSONObject jobs) {
//Long[] ids = jobs.getObject("ids", new Long[0].getClass());
Long ids = jobs.getLong("ids");
String logisticsCode = jobs.getString("logisticsCode");
saleOrderService.updateSaleOrderBillStatus(Arrays.asList(ids), "updateLogisticsCode", MapUtil.of("logisticsCode",logisticsCode));
return success(true);
}
@PutMapping("/update-remark")
@ -215,4 +228,11 @@ public class SaleOrderController {
saleOrderService.exportDesignSourceFile(response,ids);
}
@GetMapping("/exportAttrFile")
@Operation(summary = "下载销售订单的附件文件")
@PermitAll
public void exportAttrFile(@RequestParam("id") Long id,HttpServletResponse response) throws IOException {
saleOrderService.exportAttrFile(response,id);
}
}

View File

@ -178,6 +178,11 @@ public class SaleOrderDO extends BaseDO {
*/
private String currencyType;
/**
* 物流单号
*/
private String logisticsCode;
/**
* 下单客户上传的 附件文件 infra_file id
* 允许多个

View File

@ -2,6 +2,7 @@ package cn.hangtag.module.oms.service.saleorder;
import java.io.IOException;
import java.util.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.*;
@ -153,4 +154,11 @@ public interface SaleOrderService {
* @param ids IDs
*/
void exportDesignSourceFile(HttpServletResponse response, List<Long> ids);
/**
* 下载销售订单 附件文件
* @param response
* @param id
*/
void exportAttrFile(HttpServletResponse response, Long id);
}

View File

@ -2,14 +2,15 @@ package cn.hangtag.module.oms.service.saleorder;
import cn.hangtag.framework.common.exception.ServiceException;
import cn.hangtag.framework.common.exception.enums.GlobalErrorCodeConstants;
import cn.hangtag.framework.common.pojo.FileInfoVO;
import cn.hangtag.framework.common.pojo.PageResult;
import cn.hangtag.framework.common.util.FuncUtil;
import cn.hangtag.framework.common.util.cache.CacheUtils;
import cn.hangtag.framework.common.util.object.BeanUtils;
import cn.hangtag.framework.common.util.validation.AssertUtil;
import cn.hangtag.framework.mybatis.core.dataobject.BaseDO;
import cn.hangtag.framework.security.core.LoginUser;
import cn.hangtag.framework.security.core.util.SecurityFrameworkUtils;
import cn.hangtag.module.infra.api.file.FileApi;
import cn.hangtag.module.oms.common.utils.NumberChineseFormatterUtils;
import cn.hangtag.module.oms.controller.admin.common.vo.DataComparisonRespVO;
import cn.hangtag.module.oms.controller.admin.produceorder.vo.ProduceOrderSaveReqVO;
@ -60,6 +61,7 @@ import cn.hangtag.module.system.service.mail.MailSendService;
import cn.hangtag.module.system.service.user.AdminUserService;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.io.FileUtil;
@ -83,6 +85,7 @@ import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import java.io.*;
@ -145,6 +148,9 @@ public class SaleOrderServiceImpl implements SaleOrderService {
@Resource
private AdminUserService adminUserService;
@Resource
private FileApi fileApi;
@Value("${oms.partyb}")
private String partyb;
@ -315,6 +321,19 @@ public class SaleOrderServiceImpl implements SaleOrderService {
}
}
break;
case "updateLogisticsCode": //更新物流单号
for (SaleOrderDO saleOrder : saleOrders) {
if (!StringUtils.equalsAny(saleOrder.getBillStatus(), BillStatusEnum.YPLAN.getValue())) {
throw new ServiceException(001, "订单状态未排产,不允许生成出货单!");
}
if (BillStatusEnum.YPLAN.getValue().equals(saleOrder.getBillStatus()) && (params != null && params.size() > 0)) {
saleOrder.setBillStatus(BillStatusEnum.COMPLETED.getValue());
saleOrder.setOrderStatus(SaleOrderStatusEnum.YWC.getValue());
saleOrder.setLogisticsCode((String) params.get("logisticsCode"));
saleOrderMapper.updateById(saleOrder);
}
}
break;
case "submit": //提交
for (SaleOrderDO saleOrder : saleOrders) {
if (BillStatusEnum.REJECT.getValue().equals(saleOrder.getBillStatus())) {
@ -776,25 +795,32 @@ public class SaleOrderServiceImpl implements SaleOrderService {
}
}
DateTime createTime = DateUtil.date();
String createTimestr = DateUtil.formatDateTime(createTime);
order.setCreateTime(createTime.toLocalDateTime());
saleOrderMapper.insert(order);
saleOrderEntryMapper.insertBatch(entryList);
skuOrderSkuMapper.insertBatch(skuList);
updateCustomerInvoiceData(order);
//发送下单邮件
Long customerId = order.getCustomerId();
CustomerDO customerDO = customerMapper.selectById(customerId);
String orderFollowerUser = order.getOrderFollowerUser();
if (StringUtils.isNotBlank(orderFollowerUser) && customerDO != null) {
AdminUserDO user = adminUserService.getUser(Long.valueOf(orderFollowerUser));
String email = user.getEmail();
MailSendMessage message = new MailSendMessage();
message.setAccountId(1L);
message.setMail(email);
message.setTitle("OMS订单系统");
message.setTitle("OMS订单系统 "+order.getSaleContractCode()+" "+createTimestr);
StringBuffer content = new StringBuffer();
content.append("您好,客户:" + customerDO.getName() + " 来新的订单啦,订单号:" + order.getBillno() + ",下单时间:" + DateUtil.date().toString() + " 请进行处理!");
//content.append("您好,客户:【" + customerDO.getName() + "】 来新的订单啦,订单号:" + order.getBillno() + ",下单时间:" + DateUtil.date().toString() + " 请进行处理!");
content.append("您好,客户:【" + customerDO.getName() + "】 来新的订单啦,订单号:" + order.getBillno() + ",下单时间:" + createTimestr + " 请进行处理!");
message.setContent(content.toString());
mailSendService.doSendMail(message);
}
@ -1332,6 +1358,88 @@ public class SaleOrderServiceImpl implements SaleOrderService {
}
@SneakyThrows
@Override
public void exportAttrFile(HttpServletResponse response, Long id){
// 获取销售订单
LambdaQueryWrapper<SaleOrderDO> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SaleOrderDO::getId, id);
List<SaleOrderDO> entityData = saleOrderMapper.selectList(queryWrapper);
if (FuncUtil.isEmpty(entityData)) {
throw exception(ErrorCodeConstants.SALE_ORDER_NOT_FILE_EXPORT);
}
String accessoryFileIds = entityData.get(0).getAccessoryFileIds();
if(StringUtils.isBlank(accessoryFileIds)){
throw exception(ErrorCodeConstants.SALE_ORDER_NOT_FILE_EXPORT);
}
List<FileInfoVO> fileInfo = fileApi.getFileInfo(accessoryFileIds);
// 通过容器创建文件
String pathUrl = System.getProperty("user.dir") + "/attfile/orderattfile";
pathUrl = pathUrl.replaceAll("//", "/");
File file1 = new File(pathUrl);
if (!file1.exists()) {
System.out.println("创建目录:" + pathUrl);
file1.mkdirs();
}
List<File> files = new ArrayList<>();
List<String> delFiles = new ArrayList<>();
for (FileInfoVO fileInfoVO : fileInfo) {
String sourceFile = fileInfoVO.getUrl();
if (FuncUtil.isNotEmpty(sourceFile)) {
// 创建文件
String templatePath2 = StrUtil.format(pathUrl + "/{}", fileInfoVO.getName());
try {
FileUtil.touch(templatePath2);
} catch (Exception e) {
e.printStackTrace();
}
//String htmlText = HttpUtil.get(sourceFile);
//FileUtil.writeString(htmlText, templatePath2, "UTF-8");
// 获取请求的路径
String path = StrUtil.subAfter(fileInfoVO.getUrl(), "/get/", false);
if (StrUtil.isEmpty(path)) {
continue;
//throw new IllegalArgumentException("结尾的 path 路径必须传递");
}
byte[] fileContent = fileApi.getFileContent(23L, path);
File file = FileUtil.writeBytes(fileContent,templatePath2);
files.add(file);
delFiles.add(templatePath2);
}
}
if (FuncUtil.isEmpty(files)) {
throw exception(ErrorCodeConstants.SALE_ORDER_NOT_FILE_EXPORT);
}
String zipFileName = StrUtil.format(pathUrl + "/销售订单附件_{}.zip", entityData.get(0).getBillno());
// 压缩到的位置
File zipFile = new File(zipFileName);
System.out.println("文件:" + zipFileName);
ZipUtil.zip(zipFile, false, files.toArray(new File[files.size()]));
// 设置响应类型
//response.setContentType("application/pdf");
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(zipFile.getName(), "UTF-8"));
// 输出PDF到响应输出流
// 将文件内容写入响应流
try (InputStream inputStream = new FileInputStream(zipFile)) {
IoUtil.copy(inputStream, response.getOutputStream());
} catch (IOException e) {
// 异常处理
log.info("写入流失败,{}", e.getMessage());
}
}
/**
* 下载ZIP压缩包(会对下载后的压缩包进行删除)
*

View File

@ -123,5 +123,20 @@ export const SaleOrderApi = {
ids: ids.join(',')
}
return await request.download({ url: `/oms/sale-order/exportDesignSourceFile`, params})
}
},
// 下载附件
exportAttrFile: async (id: number) => {
const params = {
id: id
}
return await request.download({ url: `/oms/sale-order/exportAttrFile`, params})
},
// 驳回
pushOutBill: async (data) => {
return await request.post({
url: `/oms/sale-order/pushOutBill`,
data: data
})
},
}

View File

@ -259,7 +259,7 @@
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center" width="150" fixed="right">
<el-table-column label="操作" align="center" width="220" fixed="right">
<template #default="scope">
<el-button
v-hasPermi="['oms:sale-order:query']"
@ -278,6 +278,33 @@
>
删除
</el-button>
&nbsp;
<el-dropdown
@command="(command) => handleCommand(command, scope.row)"
>
<el-button type="primary" link><Icon icon="ep:d-arrow-right" /> 更多</el-button>
<template #dropdown>
<el-dropdown-menu>
<!-- <el-dropdown-item
command="handleDelete"
v-if="checkPermi(['oms:customer:delete'])"
>
<Icon icon="ep:delete" />删除
</el-dropdown-item>-->
<el-dropdown-item
:loading="exportLoading4"
command="exportAttrFile"
>
下载附件
</el-dropdown-item>
<el-dropdown-item
command="pushOutBill"
>
下推生成出库单
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
</el-table-column>
</el-table>
@ -308,6 +335,25 @@
</div>
</el-dialog>
<!-- 生成下推发货单对话框 -->
<el-dialog :title="pushOutBillTitle" v-model="pushOutBillOpen" width="750px" append-to-body>
<el-form ref="form" :model="pushOutBillform" label-width="80px" >
<el-form-item label="id" prop="id" v-if="false">
<el-input v-model="pushOutBillform.id" type="text" />
</el-form-item>
<el-form-item label="物流单号" prop="logisticsCode" >
<el-input v-model="pushOutBillform.logisticsCode" type="text" placeholder="请输入物流单号" />
</el-form-item>
</el-form>
<div class="dialog-footer" style="text-align: right">
<el-button type="primary" @click="submitPushOutBillForm"> </el-button>
<el-button @click="pushOutBillCancel"> </el-button>
</div>
</el-dialog>
</template>
<script setup lang="ts">
@ -371,6 +417,7 @@ const queryFormRef = ref() // 搜索的表单
const exportLoading = ref(false) //
const exportLoading2 = ref(false) //
const exportLoading3 = ref(false) //
const exportLoading4 = ref(false) //
//
@ -380,6 +427,16 @@ const rejectform = reactive({
rejectReason: undefined
})
//
const pushOutBillOpen = ref(false)
const pushOutBillTitle = ref('')
const pushOutBillform = reactive({
id: undefined,
logisticsCode: undefined
})
/** 查询列表 */
const getList = async () => {
@ -621,6 +678,62 @@ const openDetail = (id: number) => {
push({ name: 'SaleOrderDetail', params: { id } })
}
/** 下载附件 */
const exportAttrFile = async (id: number,billno:string) => {
try {
//
exportLoading4.value = true
//
const data = await SaleOrderApi.exportAttrFile(id)
message.notifySuccess(`导出成功`);
download.zip(data, `订单附件_${billno}.zip`)
} catch {
} finally {
exportLoading4.value = false
}
}
/** 下推生成发货单 */
const pushOutBill = (id: number,billstatus: string) => {
if(billstatus!='E'){
message.error("请选择订单状态已排产的数据行");
return;
}
pushOutBillform.id = id
pushOutBillform.logisticsCode = undefined
pushOutBillOpen.value = true
}
/** 下推生成发货单提交按钮 */
const submitPushOutBillForm = async () => {
//const billStatus = selectionList.value.map((item) => item.billStatus)
if(pushOutBillform.logisticsCode != null) {
const data = {
ids:pushOutBillform.id,
logisticsCode:pushOutBillform.logisticsCode
}
await SaleOrderApi.pushOutBill(data).then(response => {
message.success("更新成功");
pushOutBillOpen.value = false;
getList();
});
}else {
message.error(`请填写物流单号!`)
}
}
/** 驳回取消按钮 */
const pushOutBillCancel = () =>{
pushOutBillOpen.value = false
pushOutBillform.logisticsCode = undefined
}
/** 导出稿件元文件 */
const exportDesignFile = async () => {
try {
@ -652,6 +765,22 @@ const tableRowClassName = ({
return ''
}
/** 操作分发 */
const handleCommand = (command: string,row: SaleOrderVO) => {
switch (command) {
case 'exportAttrFile':
exportAttrFile(row.id,row.billno)
break
case 'pushOutBill':
pushOutBill(row.id,row.billStatus)
break
default:
break
}
}
// /
watch(

View File

@ -127,4 +127,11 @@ export const SaleOrderApi = {
editOrder: async (id: string,data: any) => {
return await request.post({ url: `/front/oms/sale-order/editOrder/${id}`,data})
},
// 下载附件
exportAttrFile: async (id: number) => {
const params = {
id: id
}
return await request.download({ url: `/oms/sale-order/exportAttrFile`, params})
},
}

View File

@ -233,7 +233,7 @@
:formatter="dateFormatter"
width="180px"
/>
<el-table-column :label="t('billlist.operate')" align="center" width="230" fixed="right">
<el-table-column :label="t('billlist.operate')" align="center" width="250" fixed="right">
<template #default="scope">
<router-link :to="'/order/createorder?id='+scope.row.id+'&type=copyAdd&_t=2'" >
<el-button
@ -276,6 +276,29 @@
>
删除
</el-button>-->
&nbsp;
<el-dropdown
@command="(command) => handleCommand(command, scope.row)"
>
<el-button type="primary" link><Icon icon="ep:d-arrow-right" /> 更多</el-button>
<template #dropdown>
<el-dropdown-menu>
<!-- <el-dropdown-item
command="handleDelete"
v-if="checkPermi(['oms:customer:delete'])"
>
<Icon icon="ep:delete" />删除
</el-dropdown-item>-->
<el-dropdown-item
:loading="exportLoading4"
command="exportAttrFile"
>
下载附件
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
</el-table-column>
</el-table>
@ -367,6 +390,7 @@ const queryParams = reactive({
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
const exportLoading4 = ref(false) //
//
@ -592,6 +616,24 @@ const openDetail = (id: number) => {
push({ name: 'SaleOrderDetail', params: { id } })
}
/** 下载附件 */
const exportAttrFile = async (id: number,billno:string) => {
try {
//
exportLoading4.value = true
//
const data = await SaleOrderApi.exportAttrFile(id)
message.notifySuccess(`导出成功`);
download.zip(data, `订单附件_${billno}.zip`)
} catch {
} finally {
exportLoading4.value = false
}
}
const tableRowClassName = ({row, rowIndex}: {
row: SaleOrderVO
rowIndex: number
@ -603,6 +645,21 @@ const tableRowClassName = ({row, rowIndex}: {
}
/** 操作分发 */
const handleCommand = (command: string,row: SaleOrderVO) => {
switch (command) {
case 'exportAttrFile':
exportAttrFile(row.id,row.billno)
break
default:
break
}
}
// /
watch(
() => currentRoute.value,