新增对账单

This commit is contained in:
wwb 2026-01-05 20:59:48 +08:00
parent dbe09ab701
commit 6c3d8408c2
47 changed files with 4162 additions and 11 deletions

View File

@ -29,4 +29,6 @@ public interface ErrorCodeConstants extends cn.hangtag.module.system.enums.Erro
ErrorCode SALE_ORDER_NOT_FILE_EXPORT = new ErrorCode(7000, "订单中没有可导出的稿件");
ErrorCode SALE_ORDER_NOT_ATTRFILE_EXPORT = new ErrorCode(7000, "订单中没有可导出的附件");
ErrorCode CUSTOMER_GROUP_NOT_EXISTS = new ErrorCode(7100, "客户组别 不存在");
ErrorCode DELIVERY_ORDER_NOT_EXISTS = new ErrorCode(8000, "送货单不存在");
ErrorCode STATEMENT_ACCOUNT_NOT_EXISTS = new ErrorCode(9000, "对账单不存在");
}

View File

@ -0,0 +1,186 @@
package cn.hangtag.module.oms.controller.admin.deliveryorder;
import cn.hangtag.framework.apilog.core.annotation.ApiAccessLog;
import cn.hangtag.framework.common.pojo.CommonResult;
import cn.hangtag.framework.common.pojo.PageParam;
import cn.hangtag.framework.common.pojo.PageResult;
import cn.hangtag.framework.common.util.object.BeanUtils;
import cn.hangtag.framework.excel.core.util.ExcelUtils;
import cn.hangtag.module.oms.controller.admin.deliveryorder.vo.DeliveryOrderPageReqVO;
import cn.hangtag.module.oms.controller.admin.deliveryorder.vo.DeliveryOrderRespVO;
import cn.hangtag.module.oms.controller.admin.deliveryorder.vo.DeliveryOrderSaveReqVO;
import cn.hangtag.module.oms.convert.deliveryrder.DeliveryOrderConvert;
import cn.hangtag.module.oms.dal.dataobject.customer.CustomerDO;
import cn.hangtag.module.oms.dal.dataobject.deliveryorder.DeliveryOrderDO;
import cn.hangtag.module.oms.dal.dataobject.deliveryorder.DeliveryOrderEntryDO;
import cn.hangtag.module.oms.service.customer.CustomerService;
import cn.hangtag.module.oms.service.deliveryorder.DeliveryOrderService;
import cn.hangtag.module.system.dal.dataobject.user.AdminUserDO;
import cn.hangtag.module.system.service.user.AdminUserService;
import cn.hutool.core.collection.CollUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.lang3.StringUtils;
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.annotation.security.PermitAll;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.*;
import static cn.hangtag.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.hangtag.framework.common.pojo.CommonResult.success;
import static cn.hangtag.framework.common.util.collection.CollectionUtils.convertList;
@Tag(name = "管理后台 - 送货单")
@RestController
@RequestMapping("/oms/delivery-order")
@Validated
public class DeliveryOrderController {
@Resource
private DeliveryOrderService deliveryOrderService;
@Resource
private CustomerService customerService;
@Resource
private AdminUserService adminUserService;
@PostMapping("/create")
@Operation(summary = "创建送货单")
@PreAuthorize("@ss.hasPermission('oms:delivery-order:create')")
public CommonResult<Long> createDeliveryOrder(@Valid @RequestBody DeliveryOrderSaveReqVO createReqVO) {
return success(deliveryOrderService.createDeliveryOrder(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新送货单")
@PreAuthorize("@ss.hasPermission('oms:delivery-order:update')")
public CommonResult<Boolean> updateDeliveryOrder(@Valid @RequestBody DeliveryOrderSaveReqVO updateReqVO) {
deliveryOrderService.updateDeliveryOrder(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除送货单")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('oms:delivery-order:delete')")
public CommonResult<Boolean> deleteDeliveryOrder(@RequestParam("id") Long id) {
deliveryOrderService.deleteDeliveryOrder(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得送货单")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('oms:delivery-order:query')")
public CommonResult<DeliveryOrderRespVO> getDeliveryOrder(@RequestParam("id") Long id) {
DeliveryOrderDO deliveryOrder = deliveryOrderService.getDeliveryOrder(id);
String salesPersonIds = deliveryOrder.getSalesPersonIds();
StringBuffer personText = new StringBuffer();
if(StringUtils.isNotBlank(salesPersonIds)){
String[] split = salesPersonIds.split(";");
Long[] userIds = Arrays.stream(split).map(s -> Long.parseLong(s.trim())).toArray(Long[]::new);
List<AdminUserDO> userList = adminUserService.getUserList(Arrays.asList(userIds));
for (AdminUserDO adminUserDO : userList) {
if(personText.length()==0){
personText.append(adminUserDO.getUsername());
}else {
personText.append(adminUserDO.getUsername()+"; ");
}
}
}
DeliveryOrderRespVO deliveryOrderRespVO = BeanUtils.toBean(deliveryOrder, DeliveryOrderRespVO.class);
deliveryOrderRespVO.setSalesPersonNames(personText.toString());
return success(deliveryOrderRespVO);
}
@GetMapping("/page")
@Operation(summary = "获得送货单分页")
@PreAuthorize("@ss.hasPermission('oms:delivery-order:query')")
public CommonResult<PageResult<DeliveryOrderRespVO>> getDeliveryOrderPage(@Valid DeliveryOrderPageReqVO pageReqVO) {
PageResult<DeliveryOrderDO> pageResult = deliveryOrderService.getDeliveryOrderPage(pageReqVO);
if (CollUtil.isEmpty(pageResult.getList())) {
return success(new PageResult<>(pageResult.getTotal()));
}
// 拼接数据
Map<Long, CustomerDO> customerMap = customerService.getCustomerMap(
convertList(pageResult.getList(), DeliveryOrderDO::getCustomerId));
PageResult<DeliveryOrderRespVO> saleOrderRespVOPageResult = new PageResult<>(DeliveryOrderConvert.INSTANCE.convertList(pageResult.getList(), customerMap),
pageResult.getTotal());
saleOrderRespVOPageResult.setOtherMap(pageResult.getOtherMap());
//封装数据
//999999L 为客户
//1000000L 为业务员
Map<Long, AdminUserDO> userMap = new HashMap<>();
List<AdminUserDO> userListByDeptIds = adminUserService.getUserListByDeptIds(Collections.singletonList(1000000L));
for (AdminUserDO adminUserDO : userListByDeptIds) {
userMap.put(adminUserDO.getId(),adminUserDO);
}
List<DeliveryOrderRespVO> list = saleOrderRespVOPageResult.getList();
for (DeliveryOrderRespVO deliveryOrderRespVO : list) {
String salesPersonIds = deliveryOrderRespVO.getSalesPersonIds();
StringBuffer personText = new StringBuffer();
if(StringUtils.isNotBlank(salesPersonIds)){
String[] split = salesPersonIds.split(";");
Long[] userIds = Arrays.stream(split).map(s -> Long.parseLong(s.trim())).toArray(Long[]::new);
for (Long userId : userIds) {
AdminUserDO adminUserDO = userMap.get(userId);
if(adminUserDO!=null){
if(personText.length()==0){
personText.append(adminUserDO.getUsername());
}else {
personText.append(adminUserDO.getUsername()+"; ");
}
}
}
deliveryOrderRespVO.setSalesPersonNames(personText.toString());
}
}
return success(saleOrderRespVOPageResult);
}
@GetMapping("/export-excel")
@Operation(summary = "导出送货单 Excel")
@PreAuthorize("@ss.hasPermission('oms:delivery-order:export')")
@ApiAccessLog(operateType = EXPORT)
public void exportDeliveryOrderExcel(@Valid DeliveryOrderPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<DeliveryOrderDO> list = deliveryOrderService.getDeliveryOrderPage(pageReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "送货单.xls", "数据", DeliveryOrderRespVO.class,
BeanUtils.toBean(list, DeliveryOrderRespVO.class));
}
@GetMapping("/exportPdf")
@Operation(summary = "导出PDF")
@PermitAll
public void exportPdf(@RequestParam("ids") List<Long> ids,HttpServletResponse response) throws IOException {
deliveryOrderService.generatePdf(response,ids);
}
// ==================== 子表送货单明细 ====================
@GetMapping("/delivery-order-entry/list-by-parent-id")
@Operation(summary = "获得送货单明细列表")
@Parameter(name = "parentId", description = "主表ID")
@PreAuthorize("@ss.hasPermission('oms:delivery-order:query')")
public CommonResult<List<DeliveryOrderEntryDO>> getDeliveryOrderEntryListByParentId(@RequestParam("parentId") Long parentId) {
return success(deliveryOrderService.getDeliveryOrderEntryListByParentId(parentId));
}
}

View File

@ -0,0 +1,67 @@
package cn.hangtag.module.oms.controller.admin.deliveryorder.vo;
import lombok.*;
import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema;
import cn.hangtag.framework.common.pojo.PageParam;
import java.math.BigDecimal;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.hangtag.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 送货单分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DeliveryOrderPageReqVO extends PageParam {
@Schema(description = "单据编号")
private String billno;
@Schema(description = "销售订单号")
private String saleorderNo;
@Schema(description = "下单日期")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] saleorderDate;
@Schema(description = "日期")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] date;
@Schema(description = "物流公司")
private String logisticsCompany;
@Schema(description = "物流编码")
private String logisticsCode;
@Schema(description = "联系人")
private String contact;
@Schema(description = "联系人手机号")
private String phone;
@Schema(description = "销售订单ID", example = "3044")
private Long saleorderId;
@Schema(description = "客户ID", example = "6168")
private Long customerId;
@Schema(description = "客户名称", example = "6168")
private String customerName;
@Schema(description = "业务员id")
private String salesPersonIds;
@Schema(description = "客户采购编号")
private String customerPurNo;
@Schema(description = "销售合约号")
private String saleContractNo;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@ -0,0 +1,98 @@
package cn.hangtag.module.oms.controller.admin.deliveryorder.vo;
import cn.hangtag.module.oms.controller.admin.customer.vo.CustomerRespVO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import java.math.BigDecimal;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import com.alibaba.excel.annotation.*;
@Schema(description = "管理后台 - 送货单 Response VO")
@Data
@ExcelIgnoreUnannotated
public class DeliveryOrderRespVO {
@Schema(description = "单据编号", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("单据编号")
private String billno;
@Schema(description = "销售订单号", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("销售订单号")
private String saleorderNo;
@ExcelProperty("下单日期")
private LocalDateTime saleorderDate;
@Schema(description = "日期")
@ExcelProperty("日期")
private LocalDateTime date;
@Schema(description = "收货地址")
@ExcelProperty("收货地址")
private String address;
@Schema(description = "物流公司")
@ExcelProperty("物流公司")
private String logisticsCompany;
@Schema(description = "物流编码")
@ExcelProperty("物流编码")
private String logisticsCode;
@Schema(description = "联系人")
@ExcelProperty("联系人")
private String contact;
@Schema(description = "联系人手机号")
@ExcelProperty("联系人手机号")
private String phone;
@Schema(description = "电话")
@ExcelProperty("电话")
private String tel;
@Schema(description = "总数量")
@ExcelProperty("总数量")
private Integer totalQty;
@Schema(description = "总金额")
@ExcelProperty("总金额")
private BigDecimal totalAmount;
@Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "6675")
@ExcelProperty("ID")
private Long id;
@Schema(description = "销售订单ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "3044")
private Long saleorderId;
@Schema(description = "客户ID数组", example = "6168")
@ExcelProperty("客户ID数组")
private Long customerId;
@Schema(description = "业务员id")
@ExcelProperty("业务员id")
private String salesPersonIds;
@Schema(description = "业务员名称")
@ExcelProperty("业务员名称")
private String salesPersonNames;
@Schema(description = "客户采购编号")
@ExcelProperty("客户采购编号")
private String customerPurNo;
@Schema(description = "销售合约号")
@ExcelProperty("销售合约号")
private String saleContractNo;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间")
private LocalDateTime createTime;
@Schema(description = "客户")
private CustomerRespVO customer;
}

View File

@ -0,0 +1,76 @@
package cn.hangtag.module.oms.controller.admin.deliveryorder.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import javax.validation.constraints.*;
import java.math.BigDecimal;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import cn.hangtag.module.oms.dal.dataobject.deliveryorder.DeliveryOrderEntryDO;
@Schema(description = "管理后台 - 送货单新增/修改 Request VO")
@Data
public class DeliveryOrderSaveReqVO {
@Schema(description = "单据编号", requiredMode = Schema.RequiredMode.REQUIRED)
@NotEmpty(message = "单据编号不能为空")
private String billno;
@Schema(description = "销售订单号", requiredMode = Schema.RequiredMode.REQUIRED)
@NotEmpty(message = "销售订单号不能为空")
private String saleorderNo;
@Schema(description = "下单日期")
private LocalDateTime saleorderDate;
@Schema(description = "日期")
private LocalDateTime date;
@Schema(description = "收货地址")
private String address;
@Schema(description = "物流公司")
private String logisticsCompany;
@Schema(description = "物流编码")
private String logisticsCode;
@Schema(description = "联系人")
private String contact;
@Schema(description = "联系人手机号")
private String phone;
@Schema(description = "电话")
private String tel;
@Schema(description = "总数量")
private Integer totalQty;
@Schema(description = "总金额")
private BigDecimal totalAmount;
@Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "6675")
private Long id;
@Schema(description = "销售订单ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "3044")
@NotNull(message = "销售订单ID不能为空")
private Long saleorderId;
@Schema(description = "客户ID数组", example = "6168")
private Long customerId;
@Schema(description = "业务员id")
private String salesPersonIds;
@Schema(description = "客户采购编号")
private String customerPurNo;
@Schema(description = "销售合约号")
private String saleContractNo;
@Schema(description = "送货单明细列表")
private List<DeliveryOrderEntryDO> deliveryOrderEntrys;
}

View File

@ -273,4 +273,19 @@ public class SaleOrderController {
saleOrderService.exportAttrFile(response,id);
}
@PostMapping("/updatePushDeliveryOrder")
@Operation(summary = "下推生成发货单")
@PreAuthorize("@ss.hasPermission('oms:sale-order:updatePushDeliveryOrder')")
public CommonResult<Boolean> updatePushDeliveryOrder(@RequestBody JSONObject jobs) {
Long[] ids = jobs.getObject("ids", new Long[0].getClass());
String logisticsCompany = jobs.getString("logisticsCompany");
String logisticsCode = jobs.getString("logisticsCode");
saleOrderService.updatePushDeliveryOrder(Arrays.asList(ids),logisticsCompany,logisticsCode);
return success(true);
}
}

View File

@ -29,7 +29,6 @@ public class SaleOrderRespVO {
private String billno;
@Schema(description = "销售合约号前缀", example = "2")
@ExcelProperty("销售合约号前缀")
private String saleContractCodePrefix;
@Schema(description = "销售合约号", example = "2")

View File

@ -0,0 +1,273 @@
package cn.hangtag.module.oms.controller.admin.statementaccount;
import cn.hangtag.framework.apilog.core.annotation.ApiAccessLog;
import cn.hangtag.framework.common.pojo.CommonResult;
import cn.hangtag.framework.common.pojo.PageParam;
import cn.hangtag.framework.common.pojo.PageResult;
import cn.hangtag.framework.common.util.object.BeanUtils;
import cn.hangtag.framework.excel.core.util.ExcelUtils;
import cn.hangtag.module.oms.controller.admin.statementaccount.vo.StatementAccountCustomExcelVO;
import cn.hangtag.module.oms.controller.admin.statementaccount.vo.StatementAccountPageReqVO;
import cn.hangtag.module.oms.controller.admin.statementaccount.vo.StatementAccountRespVO;
import cn.hangtag.module.oms.controller.admin.statementaccount.vo.StatementAccountSaveReqVO;
import cn.hangtag.module.oms.convert.statementaccount.StatementAccountConvert;
import cn.hangtag.module.oms.dal.dataobject.customer.CustomerDO;
import cn.hangtag.module.oms.dal.dataobject.deliveryorder.DeliveryOrderDO;
import cn.hangtag.module.oms.dal.dataobject.statementaccount.StatementAccountDO;
import cn.hangtag.module.oms.dal.dataobject.statementaccount.StatementAccountEntryDO;
import cn.hangtag.module.oms.dal.mysql.statementaccount.StatementAccountMapper;
import cn.hangtag.module.oms.service.customer.CustomerService;
import cn.hangtag.module.oms.service.statementaccount.StatementAccountService;
import cn.hangtag.module.system.convert.user.UserConvert;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.util.ListUtils;
import com.alibaba.excel.util.MapUtils;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
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.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URL;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import static cn.hangtag.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.hangtag.framework.common.pojo.CommonResult.success;
import static cn.hangtag.framework.common.util.collection.CollectionUtils.convertList;
@Tag(name = "管理后台 - 对账单")
@RestController
@RequestMapping("/oms/statement-account")
@Validated
@Slf4j
public class StatementAccountController {
@Resource
private StatementAccountService statementAccountService;
@Resource
private StatementAccountMapper statementAccountMapper;
@Resource
private CustomerService customerService;
@PostMapping("/create")
@Operation(summary = "创建对账单")
@PreAuthorize("@ss.hasPermission('oms:statement-account:create')")
public CommonResult<Long> createStatementAccount(@Valid @RequestBody StatementAccountSaveReqVO createReqVO) {
return success(statementAccountService.createStatementAccount(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新对账单")
@PreAuthorize("@ss.hasPermission('oms:statement-account:update')")
public CommonResult<Boolean> updateStatementAccount(@Valid @RequestBody StatementAccountSaveReqVO updateReqVO) {
statementAccountService.updateStatementAccount(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除对账单")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('oms:statement-account:delete')")
public CommonResult<Boolean> deleteStatementAccount(@RequestParam("id") Long id) {
statementAccountService.deleteStatementAccount(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得对账单")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('oms:statement-account:query')")
public CommonResult<StatementAccountRespVO> getStatementAccount(@RequestParam("id") Long id) {
StatementAccountDO statementAccount = statementAccountService.getStatementAccount(id);
StatementAccountRespVO statementAccountRespVO = BeanUtils.toBean(statementAccount, StatementAccountRespVO.class);
if(statementAccountRespVO!=null){
Long customerId = statementAccountRespVO.getCustomerId();
CustomerDO customer = customerService.getCustomer(customerId);
if(customer!=null){
statementAccountRespVO.setCustomerId(customerId);
statementAccountRespVO.setCustomerNumber(customer.getNumber());
statementAccountRespVO.setCustomerName(customer.getName());
}
}
return success(statementAccountRespVO);
}
@GetMapping("/page")
@Operation(summary = "获得对账单分页")
@PreAuthorize("@ss.hasPermission('oms:statement-account:query')")
public CommonResult<PageResult<StatementAccountRespVO>> getStatementAccountPage(@Valid StatementAccountPageReqVO pageReqVO) {
LocalDateTime[] date = pageReqVO.getDate();
if(date!=null && date.length>=2){
DateTime beginDate = DateUtil.beginOfMonth(new Date(date[0].atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()));
DateTime endDate = DateUtil.endOfMonth(new Date(date[1].atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()));
date[0] = beginDate.toLocalDateTime();
date[1] = endDate.toLocalDateTime();
pageReqVO.setDate(date);
}
PageResult<StatementAccountDO> pageResult = statementAccountService.getStatementAccountPage(pageReqVO);
if (CollUtil.isEmpty(pageResult.getList())) {
return success(new PageResult<>(pageResult.getTotal()));
}
// 拼接数据
Map<Long, CustomerDO> customerMap = customerService.getCustomerMap(
convertList(pageResult.getList(), StatementAccountDO::getCustomerId));
PageResult<StatementAccountRespVO> respVOPageResult = new PageResult<>(StatementAccountConvert.INSTANCE.convertList(pageResult.getList(), customerMap),
pageResult.getTotal());
respVOPageResult.setOtherMap(pageResult.getOtherMap());
return success(respVOPageResult);
}
@GetMapping("/export-excel")
@Operation(summary = "导出对账单 Excel")
@PreAuthorize("@ss.hasPermission('oms:statement-account:export')")
@ApiAccessLog(operateType = EXPORT)
public void exportStatementAccountExcel(@Valid StatementAccountPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<StatementAccountDO> list = statementAccountService.getStatementAccountPage(pageReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "对账单.xls", "数据", StatementAccountRespVO.class,BeanUtils.toBean(list, StatementAccountRespVO.class));
}
// ==================== 子表对账单明细 ====================
@GetMapping("/statement-account-entry/list-by-parent-id")
@Operation(summary = "获得对账单明细列表")
@Parameter(name = "parentId", description = "主表ID")
@PreAuthorize("@ss.hasPermission('oms:statement-account:query')")
public CommonResult<List<StatementAccountEntryDO>> getStatementAccountEntryListByParentId(@RequestParam("parentId") Long parentId) {
return success(statementAccountService.getStatementAccountEntryListByParentId(parentId));
}
@GetMapping("/export-excel2")
@Operation(summary = "导出对账单 Excel")
@PreAuthorize("@ss.hasPermission('oms:statement-account:export')")
@ApiAccessLog(operateType = EXPORT)
public void exportStatementAccountExcel(@RequestParam("ids") List<Long> ids,
HttpServletResponse response) throws IOException {
LambdaQueryWrapper<StatementAccountDO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.in(StatementAccountDO::getId, ids);
List<StatementAccountDO> list = statementAccountMapper.selectList(lambdaQueryWrapper);
// 导出 Excel
//ExcelUtils.write(response, "对账单.xls", "数据", StatementAccountRespVO.class,BeanUtils.toBean(list, StatementAccountRespVO.class));
List<String> delFiles = new ArrayList<>();
List<File> files = new ArrayList<>();
for (StatementAccountDO statementAccount : list) {
List<StatementAccountCustomExcelVO> models = new ArrayList<>();
CustomerDO customer = customerService.getCustomer(statementAccount.getCustomerId());
BigDecimal totalAmount = BigDecimal.ZERO;
List<StatementAccountEntryDO> entrys = statementAccountService.getStatementAccountEntryListByParentId(statementAccount.getId());
for (StatementAccountEntryDO entry : entrys) {
StatementAccountCustomExcelVO model = new StatementAccountCustomExcelVO();
model.setBillno(statementAccount.getBillno());
if(entry.getOrderDate()!=null){
model.setSaleorderDate(DateUtil.date(entry.getOrderDate().toLocalDate()).toString("yyyy/MM/dd"));
}
if(entry.getDeliveryDate()!=null){
model.setDeliveryDate(DateUtil.date(entry.getDeliveryDate().toLocalDate()).toString("yyyy/MM/dd"));
}
model.setSaleorderNo(entry.getSaleContractNo());
model.setContact(entry.getContact());
model.setMaterialCode(entry.getMaterialCode());
model.setCustomerNo(entry.getMaterialName());
model.setSaleContractNo(entry.getSaleContractNo());
model.setQty(entry.getQty());
model.setPrice(entry.getPrice());
model.setAmount(entry.getAmount());
model.setUnit(entry.getUnit());
models.add(model);
totalAmount = totalAmount.add(entry.getAmount());
}
// 模板注意 {} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 "\{","\}"代替
// 填充list 的时候还要注意 模板中{.} 多了个点 表示list
// 如果填充list的对象是map,必须包涵所有list的key,哪怕数据为null必须使用map.put(key,null)
//docker生成路径
URL templateFileUrl = ResourceUtil.getResource("templates/dzd_excel_templates.xlsx");
String pathUrl = System.getProperty("user.dir") + "/pdffile";
String fileName = pathUrl+"/对账单-"+customer.getName()+"-"+DateUtil.date(statementAccount.getDate().toLocalDate()).toString("YYYYMM")+".xlsx";
try (ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileUrl.getPath()).build()) {
WriteSheet writeSheet = EasyExcel.writerSheet().build();
// 直接写入数据
excelWriter.fill(models, writeSheet);
// 写入list之前的数据
Map<String, Object> map = new HashMap<String, Object>();
map.put("headTitle", DateUtil.date(statementAccount.getDate().toLocalDate()).toString("yyyy年MM月")+"对账单");
String customerTitle = "";
if(customer!=null){
customerTitle = customer.getName() + " "+customer.getNumber();
}
map.put("headCustomerName", "客户名称:"+customerTitle);
map.put("totalAmount",totalAmount);
excelWriter.fill(map, writeSheet);
File file = FileUtil.file(fileName);
files.add(file);
delFiles.add(fileName);
}
}
String pathUrl = System.getProperty("user.dir") + "/pdffile";
String zipFileName = StrUtil.format(pathUrl + "/对账单_{}", new Date().getTime());
// 压缩到的位置
File zipFile = new File(zipFileName + ".zip");
ZipUtil.zip(zipFile, false, files.toArray(new File[files.size()]));
// 设置响应类型
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());
}
// 导出完删除
delFiles.add(zipFileName);
for (String delFile : delFiles) {
FileUtil.del(delFile);
}
}
}

View File

@ -0,0 +1,84 @@
package cn.hangtag.module.oms.controller.admin.statementaccount.vo;
import cn.hangtag.module.oms.controller.admin.customer.vo.CustomerRespVO;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 对账单 Response VO")
@Data
public class StatementAccountCustomExcelVO {
/**
* 下单日期
*/
@Schema(description = "下单日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "1808")
private String saleorderDate;
@Schema(description = "订单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1808")
private String saleorderNo;
/**
* 联系人
*/
@Schema(description = "联系人", requiredMode = Schema.RequiredMode.REQUIRED, example = "1808")
private String contact;
/**
* 送货日期
*/
@Schema(description = "送货日期", requiredMode = Schema.RequiredMode.REQUIRED, example = "1808")
private String deliveryDate;
/**
* 单据编号
*/
@Schema(description = "单据编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1808")
private String billno;
/**
* 合约编号
*/
@Schema(description = "合约编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1808")
private String saleContractNo;
/**
* 产品编号
*/
@Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1808")
private String materialCode;
/**
* 客户编号
*/
@Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1808")
private String customerNo;
/**
* 单位
*/
@Schema(description = "单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "1808")
private String unit;
/**
* 数量
*/
@Schema(description = "数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1808")
private Integer qty;
/**
* 单价
*/
@Schema(description = "单价", requiredMode = Schema.RequiredMode.REQUIRED, example = "1808")
private BigDecimal price;
/**
* 金额
*/
@Schema(description = "金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1808")
private BigDecimal amount;
}

View File

@ -0,0 +1,33 @@
package cn.hangtag.module.oms.controller.admin.statementaccount.vo;
import cn.hangtag.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.hangtag.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 对账单分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class StatementAccountPageReqVO extends PageParam {
@Schema(description = "单据编号", example = "1808")
private String billno;
@Schema(description = "日期月份")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] date;
@Schema(description = "客户", example = "1808")
private Long customerId;
@Schema(description = "客户名称", example = "1808")
private String customerName;
}

View File

@ -0,0 +1,46 @@
package cn.hangtag.module.oms.controller.admin.statementaccount.vo;
import cn.hangtag.module.oms.controller.admin.customer.vo.CustomerRespVO;
import cn.hangtag.module.oms.dal.dataobject.customer.CustomerDO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import com.alibaba.excel.annotation.*;
@Schema(description = "管理后台 - 对账单 Response VO")
@Data
@ExcelIgnoreUnannotated
public class StatementAccountRespVO {
@Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "6675")
private Long id;
/**
* 单据编号
*/
@Schema(description = "单据编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1808")
private String billno;
@Schema(description = "日期月份", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("日期月份")
private LocalDateTime date;
@Schema(description = "客户", requiredMode = Schema.RequiredMode.REQUIRED, example = "1808")
private Long customerId;
private String customerNumber;
private String customerName;
@Schema(description = "客户")
private CustomerRespVO customer;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间")
private LocalDateTime createTime;
}

View File

@ -0,0 +1,34 @@
package cn.hangtag.module.oms.controller.admin.statementaccount.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import javax.validation.constraints.*;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import cn.hangtag.module.oms.dal.dataobject.statementaccount.StatementAccountEntryDO;
@Schema(description = "管理后台 - 对账单新增/修改 Request VO")
@Data
public class StatementAccountSaveReqVO {
@Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "21486")
@ExcelProperty("ID")
private Long id;
@Schema(description = "单据编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1808")
private String billno;
@Schema(description = "日期月份", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "日期月份不能为空")
private LocalDateTime date;
@Schema(description = "客户", requiredMode = Schema.RequiredMode.REQUIRED, example = "1808")
@NotNull(message = "客户不能为空")
private Long customerId;
@Schema(description = "对账单明细列表")
private List<StatementAccountEntryDO> statementAccountEntrys;
}

View File

@ -0,0 +1,33 @@
package cn.hangtag.module.oms.convert.deliveryrder;
import cn.hangtag.framework.common.util.collection.CollectionUtils;
import cn.hangtag.framework.common.util.object.BeanUtils;
import cn.hangtag.module.oms.controller.admin.customer.vo.CustomerRespVO;
import cn.hangtag.module.oms.controller.admin.deliveryorder.vo.DeliveryOrderRespVO;
import cn.hangtag.module.oms.dal.dataobject.customer.CustomerDO;
import cn.hangtag.module.oms.dal.dataobject.deliveryorder.DeliveryOrderDO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.List;
import java.util.Map;
@Mapper
public interface DeliveryOrderConvert {
DeliveryOrderConvert INSTANCE = Mappers.getMapper(DeliveryOrderConvert.class);
CustomerRespVO convert(CustomerDO bean);
default List<DeliveryOrderRespVO> convertList(List<DeliveryOrderDO> list, Map<Long, CustomerDO> customerMap) {
return CollectionUtils.convertList(list, user -> convert(user, customerMap.get(user.getCustomerId())));
}
default DeliveryOrderRespVO convert(DeliveryOrderDO user, CustomerDO customer) {
DeliveryOrderRespVO userVO = BeanUtils.toBean(user, DeliveryOrderRespVO.class);
if (customer != null) {
userVO.setCustomer(convert(customer));
}
return userVO;
}
}

View File

@ -0,0 +1,33 @@
package cn.hangtag.module.oms.convert.statementaccount;
import cn.hangtag.framework.common.util.collection.CollectionUtils;
import cn.hangtag.framework.common.util.object.BeanUtils;
import cn.hangtag.module.oms.controller.admin.customer.vo.CustomerRespVO;
import cn.hangtag.module.oms.controller.admin.statementaccount.vo.StatementAccountRespVO;
import cn.hangtag.module.oms.dal.dataobject.customer.CustomerDO;
import cn.hangtag.module.oms.dal.dataobject.statementaccount.StatementAccountDO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.List;
import java.util.Map;
@Mapper
public interface StatementAccountConvert {
StatementAccountConvert INSTANCE = Mappers.getMapper(StatementAccountConvert.class);
CustomerRespVO convert(CustomerDO bean);
default List<StatementAccountRespVO> convertList(List<StatementAccountDO> list, Map<Long, CustomerDO> customerMap) {
return CollectionUtils.convertList(list, user -> convert(user, customerMap.get(user.getCustomerId())));
}
default StatementAccountRespVO convert(StatementAccountDO user, CustomerDO customer) {
StatementAccountRespVO userVO = BeanUtils.toBean(user, StatementAccountRespVO.class);
if (customer != null) {
userVO.setCustomer(convert(customer));
}
return userVO;
}
}

View File

@ -0,0 +1,103 @@
package cn.hangtag.module.oms.dal.dataobject.deliveryorder;
import cn.hangtag.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* 送货单 DO
*
* @author 王文斌
*/
@TableName("oms_delivery_order")
@KeySequence("oms_delivery_order_seq") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DeliveryOrderDO extends BaseDO {
/**
* 单据编号
*/
private String billno;
/**
* 销售订单号
*/
private String saleorderNo;
/**
* 日期
*/
private LocalDateTime date;
/**
* 收货地址
*/
private String address;
/**
* 物流公司
*/
private String logisticsCompany;
/**
* 物流编码
*/
private String logisticsCode;
/**
* 联系人
*/
private String contact;
/**
* 联系人手机号
*/
private String phone;
/**
* 电话
*/
private String tel;
/**
* 总数量
*/
private Integer totalQty;
/**
* 总金额
*/
private BigDecimal totalAmount;
/**
* ID
*/
@TableId
private Long id;
/**
* 销售订单ID
*/
private Long saleorderId;
/**
* 订单日期
*/
private LocalDateTime saleorderDate;
/**
* 客户ID数组
*/
private Long customerId;
/**
* 业务员id
*/
private String salesPersonIds;
/**
* 客户采购编号
*/
private String customerPurNo;
/**
* 销售合约号
*/
private String saleContractNo;
}

View File

@ -0,0 +1,74 @@
package cn.hangtag.module.oms.dal.dataobject.deliveryorder;
import lombok.*;
import java.math.BigDecimal;
import java.util.*;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.*;
import cn.hangtag.framework.mybatis.core.dataobject.BaseDO;
/**
* 送货单明细 DO
*
* @author 管理员
*/
@TableName("oms_delivery_order_entry")
@KeySequence("oms_delivery_order_entry_seq") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DeliveryOrderEntryDO extends BaseDO {
/**
* ID
*/
@TableId
private Long id;
/**
* 物料编码
*/
private String materialNumber;
/**
* 物料名称
*/
private String materialName;
/**
* 物料规格
*/
private String materialSpec;
/**
* 数量
*/
private Integer qty;
/**
* 单价
*/
private BigDecimal price;
/**
* 币别
*/
private String currency;
/**
* 主表ID
*/
private Long parentId;
/**
* 销售订单分录ID
*/
private Long saleorderentryId;
/**
* 物料ID
*/
private Long materialId;
/**
* 单位
*/
private String unit;
}

View File

@ -0,0 +1,46 @@
package cn.hangtag.module.oms.dal.dataobject.statementaccount;
import lombok.*;
import java.util.*;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.*;
import cn.hangtag.framework.mybatis.core.dataobject.BaseDO;
/**
* 对账单 DO
*
* @author wwb
*/
@TableName("oms_statement_account")
@KeySequence("oms_statement_account_seq") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class StatementAccountDO extends BaseDO {
/**
* ID
*/
@TableId
private Long id;
/**
* 单据编号
*/
private String billno;
/**
* 日期月份
*/
private LocalDateTime date;
/**
* 客户
*/
private Long customerId;
}

View File

@ -0,0 +1,93 @@
package cn.hangtag.module.oms.dal.dataobject.statementaccount;
import lombok.*;
import java.util.*;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import java.math.BigDecimal;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
import com.baomidou.mybatisplus.annotation.*;
import cn.hangtag.framework.mybatis.core.dataobject.BaseDO;
/**
* 对账单明细 DO
*
* @author wwb
*/
@TableName("oms_statement_account_entry")
@KeySequence("oms_statement_account_entry_seq") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class StatementAccountEntryDO extends BaseDO {
/**
* ID
*/
@TableId
private Long id;
/**
* 销售编号
*/
private String saleContractNo;
/**
* 下单日期
*/
private LocalDateTime orderDate;
/**
* 送货单编号
*/
private String deliveryNo;
/**
* 送货日期
*/
private LocalDateTime deliveryDate;
/**
* 产品ID
*/
private Long materialId;
/**
* 产品编号
*/
private String materialCode;
/**
* 产品名称
*/
private String materialName;
/**
* 币别
*/
private String currency;
/**
* 数量
*/
private Integer qty;
/**
* 单价
*/
private BigDecimal price;
/**
* 金额
*/
private BigDecimal amount;
/**
* 单位
*/
private String unit;
/**
* 联系人
*/
private String contact;
/**
* 主表ID
*/
private Long parentId;
}

View File

@ -0,0 +1,28 @@
package cn.hangtag.module.oms.dal.mysql.deliveryorder;
import java.util.*;
import cn.hangtag.framework.common.pojo.PageResult;
import cn.hangtag.framework.common.pojo.PageParam;
import cn.hangtag.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.hangtag.framework.mybatis.core.mapper.BaseMapperX;
import cn.hangtag.module.oms.dal.dataobject.deliveryorder.DeliveryOrderEntryDO;
import org.apache.ibatis.annotations.Mapper;
/**
* 送货单明细 Mapper
*
* @author 管理员
*/
@Mapper
public interface DeliveryOrderEntryMapper extends BaseMapperX<DeliveryOrderEntryDO> {
default List<DeliveryOrderEntryDO> selectListByParentId(Long parentId) {
return selectList(DeliveryOrderEntryDO::getParentId, parentId);
}
default int deleteByParentId(Long parentId) {
return delete(DeliveryOrderEntryDO::getParentId, parentId);
}
}

View File

@ -0,0 +1,40 @@
package cn.hangtag.module.oms.dal.mysql.deliveryorder;
import cn.hangtag.framework.common.pojo.PageResult;
import cn.hangtag.framework.mybatis.core.mapper.BaseMapperX;
import cn.hangtag.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.hangtag.module.oms.controller.admin.deliveryorder.vo.DeliveryOrderPageReqVO;
import cn.hangtag.module.oms.dal.dataobject.deliveryorder.DeliveryOrderDO;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* 送货单 Mapper
*
* @author 王文斌
*/
@Mapper
public interface DeliveryOrderMapper extends BaseMapperX<DeliveryOrderDO> {
default PageResult<DeliveryOrderDO> selectPage(DeliveryOrderPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<DeliveryOrderDO>()
.eqIfPresent(DeliveryOrderDO::getBillno, reqVO.getBillno())
.eqIfPresent(DeliveryOrderDO::getSaleorderNo, reqVO.getSaleorderNo())
.betweenIfPresent(DeliveryOrderDO::getDate, reqVO.getDate())
.eqIfPresent(DeliveryOrderDO::getLogisticsCode, reqVO.getLogisticsCode())
.eqIfPresent(DeliveryOrderDO::getContact, reqVO.getContact())
.eqIfPresent(DeliveryOrderDO::getPhone, reqVO.getPhone())
.eqIfPresent(DeliveryOrderDO::getSaleorderId, reqVO.getSaleorderId())
.eqIfPresent(DeliveryOrderDO::getCustomerId, reqVO.getCustomerId())
.eqIfPresent(DeliveryOrderDO::getSalesPersonIds, reqVO.getSalesPersonIds())
.eqIfPresent(DeliveryOrderDO::getCustomerPurNo, reqVO.getCustomerPurNo())
.eqIfPresent(DeliveryOrderDO::getSaleContractNo, reqVO.getSaleContractNo())
.betweenIfPresent(DeliveryOrderDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(DeliveryOrderDO::getId));
}
IPage<DeliveryOrderDO> selectPageV2(IPage<DeliveryOrderDO> page, @Param("reqVO") DeliveryOrderPageReqVO reqVO);
}

View File

@ -105,6 +105,16 @@ public interface SaleOrderMapper extends BaseMapperX<SaleOrderDO> {
*/
int updateSumQtyOrAmount(List<Long> ids);
/**
* 更新下推发货单全部后更新销售订单已完成状态
* @param ids
* @return
*/
int updateDeliveryOrderYWCStatus(List<Long> ids);
long querySumTotalQty(@Param("reqVO") SaleOrderPageReqVO reqVO);
}

View File

@ -0,0 +1,25 @@
package cn.hangtag.module.oms.dal.mysql.statementaccount;
import cn.hangtag.framework.mybatis.core.mapper.BaseMapperX;
import cn.hangtag.module.oms.dal.dataobject.statementaccount.StatementAccountEntryDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* 对账单明细 Mapper
*
* @author wwb
*/
@Mapper
public interface StatementAccountEntryMapper extends BaseMapperX<StatementAccountEntryDO> {
default List<StatementAccountEntryDO> selectListByParentId(Long parentId) {
return selectList(StatementAccountEntryDO::getParentId, parentId);
}
default int deleteByParentId(Long parentId) {
return delete(StatementAccountEntryDO::getParentId, parentId);
}
}

View File

@ -0,0 +1,29 @@
package cn.hangtag.module.oms.dal.mysql.statementaccount;
import cn.hangtag.framework.common.pojo.PageResult;
import cn.hangtag.framework.mybatis.core.mapper.BaseMapperX;
import cn.hangtag.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.hangtag.module.oms.controller.admin.statementaccount.vo.StatementAccountPageReqVO;
import cn.hangtag.module.oms.dal.dataobject.statementaccount.StatementAccountDO;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/**
* 对账单 Mapper
*
* @author wwb
*/
@Mapper
public interface StatementAccountMapper extends BaseMapperX<StatementAccountDO> {
default PageResult<StatementAccountDO> selectPage(StatementAccountPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<StatementAccountDO>()
.eqIfPresent(StatementAccountDO::getDate, reqVO.getDate())
.eqIfPresent(StatementAccountDO::getCustomerId, reqVO.getCustomerId())
.orderByDesc(StatementAccountDO::getId));
}
IPage<StatementAccountDO> selectPageV2(IPage<StatementAccountDO> page, @Param("reqVO") StatementAccountPageReqVO reqVO);
}

View File

@ -0,0 +1,28 @@
package cn.hangtag.module.oms.job;
import cn.hangtag.framework.quartz.core.handler.JobHandler;
import cn.hangtag.framework.tenant.core.aop.TenantIgnore;
import cn.hangtag.framework.tenant.core.job.TenantJob;
import cn.hangtag.module.oms.service.statementaccount.StatementAccountService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* 对账单生成Job
*/
@Component
@Slf4j
public class StatementActJob implements JobHandler {
@Resource
private StatementAccountService statementAccountService;
@Override
@TenantJob
public String execute(String param) throws Exception {
statementAccountService.generateStatementAccountData();
return null;
}
}

View File

@ -0,0 +1,80 @@
package cn.hangtag.module.oms.service.deliveryorder;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.*;
import javax.servlet.http.HttpServletResponse;
import javax.validation.*;
import cn.hangtag.module.oms.controller.admin.deliveryorder.vo.*;
import cn.hangtag.module.oms.dal.dataobject.deliveryorder.DeliveryOrderDO;
import cn.hangtag.module.oms.dal.dataobject.deliveryorder.DeliveryOrderEntryDO;
import cn.hangtag.framework.common.pojo.PageResult;
import cn.hangtag.framework.common.pojo.PageParam;
/**
* 送货单 Service 接口
*
* @author 王文斌
*/
public interface DeliveryOrderService {
/**
* 创建送货单
*
* @param createReqVO 创建信息
* @return 编号
*/
Long createDeliveryOrder(@Valid DeliveryOrderSaveReqVO createReqVO);
/**
* 更新送货单
*
* @param updateReqVO 更新信息
*/
void updateDeliveryOrder(@Valid DeliveryOrderSaveReqVO updateReqVO);
/**
* 删除送货单
*
* @param id 编号
*/
void deleteDeliveryOrder(Long id);
/**
* 获得送货单
*
* @param id 编号
* @return 送货单
*/
DeliveryOrderDO getDeliveryOrder(Long id);
/**
* 获得送货单分页
*
* @param pageReqVO 分页查询
* @return 送货单分页
*/
PageResult<DeliveryOrderDO> getDeliveryOrderPage(DeliveryOrderPageReqVO pageReqVO);
// ==================== 子表送货单明细 ====================
/**
* 获得送货单明细列表
*
* @param parentId 主表ID
* @return 送货单明细列表
*/
List<DeliveryOrderEntryDO> getDeliveryOrderEntryListByParentId(Long parentId);
/**
* 获取送货单编码
* @return
*/
String getNewDeliveryOrderCode();
boolean verifySaleOrderEntryIdIsRepeat(List<Long> saleOrderEntrys);
void generatePdf(HttpServletResponse response, List<Long> ids) throws IOException;
}

View File

@ -0,0 +1,387 @@
package cn.hangtag.module.oms.service.deliveryorder;
import cn.hangtag.framework.common.exception.ServiceException;
import cn.hangtag.framework.common.exception.enums.GlobalErrorCodeConstants;
import cn.hangtag.framework.common.pojo.PageResult;
import cn.hangtag.framework.common.util.FuncUtil;
import cn.hangtag.framework.common.util.object.BeanUtils;
import cn.hangtag.framework.mybatis.core.dataobject.BaseDO;
import cn.hangtag.module.oms.common.utils.WKHtmlToPdfUtil;
import cn.hangtag.module.oms.controller.admin.deliveryorder.vo.DeliveryOrderPageReqVO;
import cn.hangtag.module.oms.controller.admin.deliveryorder.vo.DeliveryOrderSaveReqVO;
import cn.hangtag.module.oms.dal.dataobject.customer.CustomerDO;
import cn.hangtag.module.oms.dal.dataobject.deliveryorder.DeliveryOrderDO;
import cn.hangtag.module.oms.dal.dataobject.deliveryorder.DeliveryOrderEntryDO;
import cn.hangtag.module.oms.dal.dataobject.productinfo.ProductInfoDO;
import cn.hangtag.module.oms.dal.dataobject.saleorder.SaleOrderDO;
import cn.hangtag.module.oms.dal.mysql.deliveryorder.DeliveryOrderEntryMapper;
import cn.hangtag.module.oms.dal.mysql.deliveryorder.DeliveryOrderMapper;
import cn.hangtag.module.oms.dal.mysql.productinfo.ProductInfoMapper;
import cn.hangtag.module.oms.serialnumber.CodingRulesUtils;
import cn.hangtag.module.oms.service.customer.CustomerService;
import cn.hangtag.module.oms.service.productinfo.ProductInfoService;
import cn.hangtag.module.system.dal.dataobject.user.AdminUserDO;
import cn.hangtag.module.system.service.user.AdminUserService;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.*;
import static cn.hangtag.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.hangtag.module.oms.enums.ErrorCodeConstants.DELIVERY_ORDER_NOT_EXISTS;
/**
* 送货单 Service 实现类
*
* @author 王文斌
*/
@Service
@Validated
@Slf4j
public class DeliveryOrderServiceImpl implements DeliveryOrderService {
@Resource
private DeliveryOrderMapper deliveryOrderMapper;
@Resource
private DeliveryOrderEntryMapper deliveryOrderEntryMapper;
@Resource
private CustomerService customerService;
@Resource
private ProductInfoMapper productInfoMapper;
@Resource
private ProductInfoService productInfoService;
@Resource
private TemplateEngine templateEngine;
@Resource
private AdminUserService adminUserService;
@Value("${oms.partyb}")
private String partyb;
@Value("${oms.partybAddress}")
private String partybAddress;
@Value("${pdfPath}")
private String pdfPath;
@Value("${wkappurl}")
private String wkappUrl;
@Override
@Transactional(rollbackFor = Exception.class)
public Long createDeliveryOrder(DeliveryOrderSaveReqVO createReqVO) {
// 插入
DeliveryOrderDO deliveryOrder = BeanUtils.toBean(createReqVO, DeliveryOrderDO.class);
deliveryOrderMapper.insert(deliveryOrder);
// 插入子表
createDeliveryOrderEntryList(deliveryOrder.getId(), createReqVO.getDeliveryOrderEntrys());
// 返回
return deliveryOrder.getId();
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateDeliveryOrder(DeliveryOrderSaveReqVO updateReqVO) {
// 校验存在
validateDeliveryOrderExists(updateReqVO.getId());
// 更新
DeliveryOrderDO updateObj = BeanUtils.toBean(updateReqVO, DeliveryOrderDO.class);
deliveryOrderMapper.updateById(updateObj);
// 更新子表
updateDeliveryOrderEntryList(updateReqVO.getId(), updateReqVO.getDeliveryOrderEntrys());
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteDeliveryOrder(Long id) {
// 校验存在
validateDeliveryOrderExists(id);
// 删除
deliveryOrderMapper.deleteById(id);
// 删除子表
deleteDeliveryOrderEntryByParentId(id);
}
private void validateDeliveryOrderExists(Long id) {
if (deliveryOrderMapper.selectById(id) == null) {
throw exception(DELIVERY_ORDER_NOT_EXISTS);
}
}
@Override
public DeliveryOrderDO getDeliveryOrder(Long id) {
return deliveryOrderMapper.selectById(id);
}
@Override
public PageResult<DeliveryOrderDO> getDeliveryOrderPage(DeliveryOrderPageReqVO pageReqVO) {
IPage<DeliveryOrderDO> page = new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize());
deliveryOrderMapper.selectPageV2(page,pageReqVO);
PageResult<DeliveryOrderDO> saleOrderDOPageResult = new PageResult<>(page.getRecords(), page.getTotal());
return saleOrderDOPageResult;
}
// ==================== 子表送货单明细 ====================
@Override
public List<DeliveryOrderEntryDO> getDeliveryOrderEntryListByParentId(Long parentId) {
return deliveryOrderEntryMapper.selectListByParentId(parentId);
}
private void createDeliveryOrderEntryList(Long parentId, List<DeliveryOrderEntryDO> list) {
list.forEach(o -> o.setParentId(parentId));
deliveryOrderEntryMapper.insertBatch(list);
}
private void updateDeliveryOrderEntryList(Long parentId, List<DeliveryOrderEntryDO> list) {
deleteDeliveryOrderEntryByParentId(parentId);
list.forEach(o -> o.setId(null).setUpdater(null).setUpdateTime(null)); // 解决更新情况下1id 冲突2updateTime 不更新
createDeliveryOrderEntryList(parentId, list);
}
private void deleteDeliveryOrderEntryByParentId(Long parentId) {
deliveryOrderEntryMapper.deleteByParentId(parentId);
}
private static final long deliveryOrderCodeId = 11L;
@Override
public String getNewDeliveryOrderCode() {
String s = "";
int count = 10;
while (true) {
count--;
try {
s = CodingRulesUtils.generateCode(deliveryOrderCodeId, false);
checkDeliveryOrderCode(null, s);
return s;
} catch (ServiceException e) {
log.warn("重复或者下一个编码");
if (count < 0) {
log.error("编码获取失败");
return "";
}
}
}
}
@Override
public boolean verifySaleOrderEntryIdIsRepeat(List<Long> saleOrderEntrys) {
int i = 1;
for (Long saleOrderEntryId : saleOrderEntrys) {
Long count = deliveryOrderEntryMapper.selectCount(DeliveryOrderEntryDO::getSaleorderentryId, saleOrderEntryId);
if(count>0){
throw new ServiceException(3500,""+i+"行数据已下推送货单");
}
i++;
}
return false;
}
@Override
public void generatePdf(HttpServletResponse response, List<Long> ids) throws IOException {
List<String> delFiles = new ArrayList<>();
List<File> files = new ArrayList<>();
List<DeliveryOrderDO> deliveryOrders = deliveryOrderMapper.selectList(DeliveryOrderDO::getId, ids);
for (DeliveryOrderDO deliveryOrder : deliveryOrders) {
List<DeliveryOrderEntryDO> entrys = getDeliveryOrderEntryListByParentId(deliveryOrder.getId());
String htmlContent = generateHtmlContent(deliveryOrder, entrys);
//docker生成路径
String pathUrl = System.getProperty("user.dir") + "/pdffile";
String fileName = StrUtil.format(pathUrl + "/DeliveryOrder_{}", deliveryOrder.getBillno());
//主宿机生成路径
String fileName2 = StrUtil.format(pdfPath + "/DeliveryOrder_{}", deliveryOrder.getBillno());
String templatePath = fileName + ".html";
String pdfPath = fileName + ".pdf";
String templatePath2 = fileName2 + ".html";
String pdfPath2 = fileName2 + ".pdf";
FileUtil.writeString(htmlContent, templatePath, "UTF-8");
log.info("已生成HTML文件" + templatePath);
//请求wkapp
JSONObject params = new JSONObject();
params.put("input_html_path", "file://" + templatePath2);
params.put("output_pdf_path", pdfPath2);
log.info("请求wkapp接口url" + wkappUrl + "/exehtmltopdf");
String result = HttpUtil.post(wkappUrl + "/exehtmltopdf", params, 5 * 60 * 1000);
log.info("请求wkapp接口返回结果" + result);
//WKHtmlToPdfUtil.convert(templatePath, pdfPath);
File file = FileUtil.file(pdfPath);
files.add(file);
delFiles.add(pdfPath);
delFiles.add(templatePath);
}
String pathUrl = System.getProperty("user.dir") + "/pdffile";
String zipFileName = StrUtil.format(pathUrl + "/DeliveryOrder_{}", new Date().getTime());
// 压缩到的位置
File zipFile = new File(zipFileName + ".zip");
ZipUtil.zip(zipFile, false, files.toArray(new File[files.size()]));
//downloadZip(zipFile,response);
// 设置响应类型
//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());
}
// 导出完删除
delFiles.add(zipFileName);
for (String delFile : delFiles) {
FileUtil.del(delFile);
}
}
private String generateHtmlContent(Long deliveryOrderId) {
DeliveryOrderDO deliveryOrder = getDeliveryOrder(deliveryOrderId);
List<DeliveryOrderEntryDO> deliveryOrderEntrys = getDeliveryOrderEntryListByParentId(deliveryOrderId);
Context context = generateHtmlContents(deliveryOrder, deliveryOrderEntrys);
return templateEngine.process("sendorder_pdf_template", context);
}
private String generateHtmlContent(DeliveryOrderDO deliveryOrder, List<DeliveryOrderEntryDO> deliveryOrderEntrys) {
Context context = generateHtmlContents(deliveryOrder, deliveryOrderEntrys);
return templateEngine.process("sendorder_pdf_template", context);
}
private Context generateHtmlContents(DeliveryOrderDO deliveryOrder, List<DeliveryOrderEntryDO> deliveryOrderEntrys) {
CustomerDO customer = customerService.getCustomer(deliveryOrder.getCustomerId());
Context context = new Context();
context.setVariable("title", "送货单");//标题
context.setVariable("customerName", customer.getName());//客户名称
context.setVariable("customerAddress", customer.getCompanyAddress());//客户地址
context.setVariable("contact", deliveryOrder.getContact() +" / "+deliveryOrder.getPhone());//联系人
context.setVariable("billno", deliveryOrder.getBillno());//送货单编号
context.setVariable("bizDate", DateUtil.date(deliveryOrder.getDate()).toString("yyMMdd"));//业务日期
context.setVariable("customerNo", customer.getNumber());//客户编号
context.setVariable("tel", deliveryOrder.getTel());//电话
String salesPersonIds = deliveryOrder.getSalesPersonIds();
StringBuffer personText = new StringBuffer();
if(StringUtils.isNotBlank(salesPersonIds)){
String[] split = salesPersonIds.split(";");
Long[] userIds = Arrays.stream(split).map(s -> Long.parseLong(s.trim())).toArray(Long[]::new);
List<AdminUserDO> userList = adminUserService.getUserList(Arrays.asList(userIds));
for (AdminUserDO adminUserDO : userList) {
if(personText.length()==0){
personText.append(adminUserDO.getUsername()+" / "+adminUserDO.getMobile());
}else {
personText.append(adminUserDO.getUsername()+" / "+adminUserDO.getMobile()+";");
}
}
}
context.setVariable("personText", personText.toString());//负责人
context.setVariable("totalQty", deliveryOrder.getTotalQty());//总数量
context.setVariable("logisticsCode", deliveryOrder.getLogisticsCode());//物流单号
context.setVariable("logisticsCompany", deliveryOrder.getLogisticsCompany());//物流公司
List<Map<String,Object>> list = new ArrayList<>();
for (int i = 0; i < deliveryOrderEntrys.size(); i++) {
DeliveryOrderEntryDO deliveryOrderEntry = deliveryOrderEntrys.get(i);
ProductInfoDO productInfo = productInfoService.getProductInfo(deliveryOrderEntry.getMaterialId());
//产品信息
String code = productInfo.getCode();
String name = productInfo.getName();
String details = productInfo.getDetails();
Double specSizeHeight = productInfo.getSpecSizeHeight();
Double specSizeWidth = productInfo.getSpecSizeWidth();
Double specSizeThk = productInfo.getSpecSizeThk();
StringBuilder specBuilder = new StringBuilder();
// 处理宽度
Double width = FuncUtil.toDouble(specSizeWidth, 0d);
if (width > 0) {
specBuilder.append(width);
}
Double height = FuncUtil.toDouble(specSizeHeight, 0d);
if ( height > 0) {
if (specBuilder.length() > 0) {
specBuilder.append(" * ");
}
specBuilder.append(height);
}
Double thickness = FuncUtil.toDouble(specSizeThk, 0d);
if (thickness > 0) {
if (specBuilder.length() > 0) {
specBuilder.append(" ");
}
specBuilder.append(thickness);
}
String spec = specBuilder.toString();
int j = i + 1;
Map<String,Object> items = new LinkedHashMap<>();
items.put("productDesc1", productInfo.getCode());
items.put("productDesc2", productInfo.getName());
items.put("productDesc3", deliveryOrder.getSaleContractNo());
items.put("productDesc4", deliveryOrder.getCustomerPurNo());
items.put("productDesc5", productInfo.getDetails());
items.put("qty", deliveryOrderEntry.getQty() +" " +deliveryOrderEntry.getUnit());
list.add(items);
}
context.setVariable("items",list);
return context;
}
private void checkDeliveryOrderCode(Long id, String code) {
if (FuncUtil.isNotEmpty(code)) {
LambdaQueryWrapper<DeliveryOrderDO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.select(DeliveryOrderDO::getId, DeliveryOrderDO::getBillno, BaseDO::getDeleted);
lambdaQueryWrapper.eq(DeliveryOrderDO::getBillno, code);
lambdaQueryWrapper.eq(DeliveryOrderDO::getDeleted, false);
List<DeliveryOrderDO> dos = deliveryOrderMapper.selectList(lambdaQueryWrapper);
if (FuncUtil.isEmpty(id) && FuncUtil.isNotEmpty(dos)) {
throw exception(GlobalErrorCodeConstants.DATA_DUPLICATE);
}
if (FuncUtil.isNotEmpty(id) && FuncUtil.isNotEmpty(dos)) {
for (DeliveryOrderDO aDo : dos) {
// 出现重复并当前id 不一致
if (!FuncUtil.equals(aDo.getId(), id)) {
throw exception(GlobalErrorCodeConstants.DATA_DUPLICATE);
}
}
}
}
}
}

View File

@ -77,7 +77,8 @@ public interface SaleOrderService {
Map<String, Long> getTabsCount(SaleOrderPageReqVO pageReqVO, Long customerId);
void updateSaleOrderBillStatus(List<Long> ids, String status);
void updateSaleOrderBillStatus(List<Long> ids, String status);
void updateSaleOrderBillStatus(List<Long> ids, String status,Map<String,Object> params);
void generateProduceOrder(List<Long> ids);
@ -169,4 +170,10 @@ public interface SaleOrderService {
* @param id
*/
void exportAttrFile(HttpServletResponse response, Long id);
/**
* 下推生成送货单
* @param ids
*/
void updatePushDeliveryOrder(List<Long> ids,String logisticsCompany,String logisticsCode);
}

View File

@ -13,6 +13,8 @@ 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.deliveryorder.vo.DeliveryOrderRespVO;
import cn.hangtag.module.oms.controller.admin.deliveryorder.vo.DeliveryOrderSaveReqVO;
import cn.hangtag.module.oms.controller.admin.produceorder.vo.ProduceOrderSaveReqVO;
import cn.hangtag.module.oms.controller.admin.product.vo.ProductPriceSaveReqVO;
import cn.hangtag.module.oms.controller.admin.salecontract.vo.SaleContractSaveReqVO;
@ -28,6 +30,8 @@ import cn.hangtag.module.oms.controller.admin.trade.vo.TradeOrderTrendReqVO;
import cn.hangtag.module.oms.controller.admin.trade.vo.TradeOrderTrendRespVO;
import cn.hangtag.module.oms.convert.saleorder.SaleOrderConvert;
import cn.hangtag.module.oms.dal.dataobject.customer.CustomerDO;
import cn.hangtag.module.oms.dal.dataobject.deliveryorder.DeliveryOrderDO;
import cn.hangtag.module.oms.dal.dataobject.deliveryorder.DeliveryOrderEntryDO;
import cn.hangtag.module.oms.dal.dataobject.product.ProductPriceDO;
import cn.hangtag.module.oms.dal.dataobject.productinfo.ProductInfoDO;
import cn.hangtag.module.oms.dal.dataobject.salecontract.SaleContractDO;
@ -36,6 +40,8 @@ import cn.hangtag.module.oms.dal.dataobject.saleorder.SaleOrderDO;
import cn.hangtag.module.oms.dal.dataobject.saleorderentry.SaleOrderEntryDO;
import cn.hangtag.module.oms.dal.dataobject.saleordersku.SaleOrderSkuDO;
import cn.hangtag.module.oms.dal.mysql.customer.CustomerMapper;
import cn.hangtag.module.oms.dal.mysql.deliveryorder.DeliveryOrderEntryMapper;
import cn.hangtag.module.oms.dal.mysql.deliveryorder.DeliveryOrderMapper;
import cn.hangtag.module.oms.dal.mysql.productinfo.ProductInfoMapper;
import cn.hangtag.module.oms.dal.mysql.salecontract.SaleContractMapper;
import cn.hangtag.module.oms.dal.mysql.saleorder.SaleOrderMapper;
@ -48,6 +54,7 @@ import cn.hangtag.module.oms.enums.saleorder.SaleOrderStatusEnum;
import cn.hangtag.module.oms.enums.saleorder.SaleOrderTypeEnum;
import cn.hangtag.module.oms.serialnumber.CodingRulesUtils;
import cn.hangtag.module.oms.service.customer.CustomerService;
import cn.hangtag.module.oms.service.deliveryorder.DeliveryOrderService;
import cn.hangtag.module.oms.service.produceorder.ProduceOrderService;
import cn.hangtag.module.oms.service.product.ProductPriceService;
import cn.hangtag.module.oms.service.productinfo.ProductInfoService;
@ -124,7 +131,8 @@ public class SaleOrderServiceImpl implements SaleOrderService {
private SaleOrderEntryMapper saleOrderEntryMapper;
@Resource
private SaleOrderSkuMapper skuOrderSkuMapper;
@Resource
private DeliveryOrderService deliveryOrderService;
@Resource
private SaleOrderSkuService saleOrderSkuService;
@Resource
@ -1610,6 +1618,76 @@ public class SaleOrderServiceImpl implements SaleOrderService {
}
}
@Override
public void updatePushDeliveryOrder(List<Long> ids,String logisticsCompany,String logisticsCode){
List<SaleOrderEntryDO> saleOrderEntryDOS = saleOrderEntryMapper.selectBatchIds(ids);
if(saleOrderEntryDOS!=null && !saleOrderEntryDOS.isEmpty()){
//验证是否重复下推
deliveryOrderService.verifySaleOrderEntryIdIsRepeat(ids);
Long parentId = saleOrderEntryDOS.get(0).getParentId();
SaleOrderDO saleOrderDO = saleOrderMapper.selectById(parentId);
if (!StringUtils.equalsAny(saleOrderDO.getBillStatus(), BillStatusEnum.YPLAN.getValue())) {
throw new ServiceException(001, "订单状态未排产,不允许生成送货单!");
}
//单据头
DeliveryOrderSaveReqVO deliveryOrderDO = new DeliveryOrderSaveReqVO();
deliveryOrderDO.setBillno(deliveryOrderService.getNewDeliveryOrderCode());
deliveryOrderDO.setSaleorderId(saleOrderDO.getId());
deliveryOrderDO.setSaleorderNo(saleOrderDO.getBillno());
deliveryOrderDO.setSaleorderDate(saleOrderDO.getCreateTime());
deliveryOrderDO.setCustomerId(saleOrderDO.getCustomerId());
deliveryOrderDO.setPhone(saleOrderDO.getPhone());
deliveryOrderDO.setContact(saleOrderDO.getContactName());
deliveryOrderDO.setDate(LocalDateTime.now());
deliveryOrderDO.setTel(saleOrderDO.getBillno());
deliveryOrderDO.setSalesPersonIds(saleOrderDO.getOrderFollowerUser());
deliveryOrderDO.setLogisticsCompany(logisticsCompany);
deliveryOrderDO.setLogisticsCode(logisticsCode);
deliveryOrderDO.setAddress(saleOrderDO.getAddress());
deliveryOrderDO.setSaleContractNo(saleOrderDO.getSaleContractCode());
deliveryOrderDO.setCustomerPurNo(saleOrderDO.getContractCode());
Integer totalQty = 0;
BigDecimal totalAmt = BigDecimal.ZERO;
List<DeliveryOrderEntryDO> entryLists = new ArrayList<>();
for (SaleOrderEntryDO saleOrderEntryDO : saleOrderEntryDOS) {
Integer qty = saleOrderEntryDO.getQty();
BigDecimal amount = saleOrderEntryDO.getAmount();
totalQty = totalQty+qty;
totalAmt = totalAmt.add(amount);
DeliveryOrderEntryDO entryDO = new DeliveryOrderEntryDO();
entryDO.setMaterialId(saleOrderEntryDO.getMaterialId());
entryDO.setMaterialNumber(saleOrderEntryDO.getMaterialNumber());
entryDO.setMaterialName(saleOrderEntryDO.getMaterialName());
entryDO.setMaterialSpec(saleOrderEntryDO.getMaterialSpec());
entryDO.setPrice(saleOrderEntryDO.getPrice());
entryDO.setUnit(saleOrderEntryDO.getUnit());
entryDO.setSaleorderentryId(saleOrderEntryDO.getId());
entryDO.setCurrency(saleOrderDO.getCurrency());
entryDO.setParentId(deliveryOrderDO.getId());
entryDO.setQty(qty);
entryLists.add(entryDO);
}
deliveryOrderDO.setTotalQty(totalQty);
deliveryOrderDO.setTotalAmount(totalAmt);
deliveryOrderDO.setDeliveryOrderEntrys(entryLists);
deliveryOrderService.createDeliveryOrder(deliveryOrderDO);
//更新销售订单订单状态
if (BillStatusEnum.YPLAN.getValue().equals(saleOrderDO.getBillStatus())) {
saleOrderMapper.updateDeliveryOrderYWCStatus(Collections.singletonList(saleOrderDO.getId()));
}
}
}
/**
* 下载ZIP压缩包(会对下载后的压缩包进行删除)
*

View File

@ -0,0 +1,78 @@
package cn.hangtag.module.oms.service.statementaccount;
import java.util.*;
import javax.validation.*;
import cn.hangtag.module.oms.controller.admin.statementaccount.vo.*;
import cn.hangtag.module.oms.dal.dataobject.statementaccount.StatementAccountDO;
import cn.hangtag.module.oms.dal.dataobject.statementaccount.StatementAccountEntryDO;
import cn.hangtag.framework.common.pojo.PageResult;
import cn.hangtag.framework.common.pojo.PageParam;
/**
* 对账单 Service 接口
*
* @author wwb
*/
public interface StatementAccountService {
/**
* 创建对账单
*
* @param createReqVO 创建信息
* @return 编号
*/
Long createStatementAccount(@Valid StatementAccountSaveReqVO createReqVO);
/**
* 更新对账单
*
* @param updateReqVO 更新信息
*/
void updateStatementAccount(@Valid StatementAccountSaveReqVO updateReqVO);
/**
* 删除对账单
*
* @param id 编号
*/
void deleteStatementAccount(Long id);
/**
* 获得对账单
*
* @param id 编号
* @return 对账单
*/
StatementAccountDO getStatementAccount(Long id);
/**
* 获得对账单分页
*
* @param pageReqVO 分页查询
* @return 对账单分页
*/
PageResult<StatementAccountDO> getStatementAccountPage(StatementAccountPageReqVO pageReqVO);
// ==================== 子表对账单明细 ====================
/**
* 获得对账单明细列表
*
* @param parentId 主表ID
* @return 对账单明细列表
*/
List<StatementAccountEntryDO> getStatementAccountEntryListByParentId(Long parentId);
/**
* 生成单据编码
* @return
*/
String getNewBillNo();
void generateStatementAccountData();
}

View File

@ -0,0 +1,259 @@
package cn.hangtag.module.oms.service.statementaccount;
import cn.hangtag.framework.common.exception.ServiceException;
import cn.hangtag.framework.common.exception.enums.GlobalErrorCodeConstants;
import cn.hangtag.framework.common.pojo.PageResult;
import cn.hangtag.framework.common.util.FuncUtil;
import cn.hangtag.framework.common.util.object.BeanUtils;
import cn.hangtag.framework.mybatis.core.dataobject.BaseDO;
import cn.hangtag.module.oms.controller.admin.statementaccount.vo.StatementAccountPageReqVO;
import cn.hangtag.module.oms.controller.admin.statementaccount.vo.StatementAccountSaveReqVO;
import cn.hangtag.module.oms.dal.dataobject.deliveryorder.DeliveryOrderDO;
import cn.hangtag.module.oms.dal.dataobject.deliveryorder.DeliveryOrderEntryDO;
import cn.hangtag.module.oms.dal.dataobject.statementaccount.StatementAccountDO;
import cn.hangtag.module.oms.dal.dataobject.statementaccount.StatementAccountEntryDO;
import cn.hangtag.module.oms.dal.mysql.deliveryorder.DeliveryOrderMapper;
import cn.hangtag.module.oms.dal.mysql.statementaccount.StatementAccountEntryMapper;
import cn.hangtag.module.oms.dal.mysql.statementaccount.StatementAccountMapper;
import cn.hangtag.module.oms.serialnumber.CodingRulesUtils;
import cn.hangtag.module.oms.service.deliveryorder.DeliveryOrderService;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static cn.hangtag.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.hangtag.module.oms.enums.ErrorCodeConstants.STATEMENT_ACCOUNT_NOT_EXISTS;
/**
* 对账单 Service 实现类
*
* @author wwb
*/
@Service
@Validated
@Slf4j
public class StatementAccountServiceImpl implements StatementAccountService {
@Resource
private StatementAccountMapper statementAccountMapper;
@Resource
private StatementAccountEntryMapper statementAccountEntryMapper;
@Resource
private DeliveryOrderService deliveryOrderService;
@Resource
private DeliveryOrderMapper deliveryOrderMapper;
@Override
@Transactional(rollbackFor = Exception.class)
public Long createStatementAccount(StatementAccountSaveReqVO createReqVO) {
// 插入
StatementAccountDO statementAccount = BeanUtils.toBean(createReqVO, StatementAccountDO.class);
statementAccountMapper.insert(statementAccount);
// 插入子表
createStatementAccountEntryList(statementAccount.getId(), createReqVO.getStatementAccountEntrys());
// 返回
return statementAccount.getId();
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateStatementAccount(StatementAccountSaveReqVO updateReqVO) {
// 校验存在
validateStatementAccountExists(updateReqVO.getId());
// 更新
StatementAccountDO updateObj = BeanUtils.toBean(updateReqVO, StatementAccountDO.class);
statementAccountMapper.updateById(updateObj);
// 更新子表
updateStatementAccountEntryList(updateReqVO.getId(), updateReqVO.getStatementAccountEntrys());
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteStatementAccount(Long id) {
// 校验存在
validateStatementAccountExists(id);
// 删除
statementAccountMapper.deleteById(id);
// 删除子表
deleteStatementAccountEntryByParentId(id);
}
private void validateStatementAccountExists(Long id) {
if (statementAccountMapper.selectById(id) == null) {
throw exception(STATEMENT_ACCOUNT_NOT_EXISTS);
}
}
@Override
public StatementAccountDO getStatementAccount(Long id) {
return statementAccountMapper.selectById(id);
}
@Override
public PageResult<StatementAccountDO> getStatementAccountPage(StatementAccountPageReqVO pageReqVO) {
IPage<StatementAccountDO> page = new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize());
statementAccountMapper.selectPageV2(page,pageReqVO);
PageResult<StatementAccountDO> saleOrderDOPageResult = new PageResult<>(page.getRecords(), page.getTotal());
return saleOrderDOPageResult;
}
// ==================== 子表对账单明细 ====================
@Override
public List<StatementAccountEntryDO> getStatementAccountEntryListByParentId(Long parentId) {
return statementAccountEntryMapper.selectListByParentId(parentId);
}
private static final long billNoRuleId = 11L;
@Override
public String getNewBillNo() {
String s = "";
int count = 10;
while (true) {
count--;
try {
s = CodingRulesUtils.generateCode(billNoRuleId, false);
checkBillNoCode(null, s);
return s;
} catch (ServiceException e) {
log.warn("重复或者下一个编码");
if (count < 0) {
log.error("编码获取失败");
return "";
}
}
}
}
private void checkBillNoCode(Long id, String code) {
if (FuncUtil.isNotEmpty(code)) {
LambdaQueryWrapper<StatementAccountDO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.select(StatementAccountDO::getId, StatementAccountDO::getBillno, BaseDO::getDeleted);
lambdaQueryWrapper.eq(StatementAccountDO::getBillno, code);
lambdaQueryWrapper.eq(StatementAccountDO::getDeleted, false);
List<StatementAccountDO> dos = statementAccountMapper.selectList(lambdaQueryWrapper);
if (FuncUtil.isEmpty(id) && FuncUtil.isNotEmpty(dos)) {
throw exception(GlobalErrorCodeConstants.DATA_DUPLICATE);
}
if (FuncUtil.isNotEmpty(id) && FuncUtil.isNotEmpty(dos)) {
for (StatementAccountDO aDo : dos) {
// 出现重复并当前id 不一致
if (!FuncUtil.equals(aDo.getId(), id)) {
throw exception(GlobalErrorCodeConstants.DATA_DUPLICATE);
}
}
}
}
}
private void createStatementAccountEntryList(Long parentId, List<StatementAccountEntryDO> list) {
list.forEach(o -> o.setParentId(parentId));
statementAccountEntryMapper.insertBatch(list);
}
private void updateStatementAccountEntryList(Long parentId, List<StatementAccountEntryDO> list) {
deleteStatementAccountEntryByParentId(parentId);
list.forEach(o -> o.setId(null).setUpdater(null).setUpdateTime(null)); // 解决更新情况下1id 冲突2updateTime 不更新
createStatementAccountEntryList(parentId, list);
}
private void deleteStatementAccountEntryByParentId(Long parentId) {
statementAccountEntryMapper.deleteByParentId(parentId);
}
@Transactional(rollbackFor = Exception.class)
@Override
public void generateStatementAccountData() {
//查询当月数据按客户分组创建对账单
LambdaQueryWrapper<DeliveryOrderDO> lambdaQueryWrapperx = new LambdaQueryWrapper<>();
lambdaQueryWrapperx.between(DeliveryOrderDO::getDate, DateUtil.beginOfMonth(DateUtil.date()),DateUtil.endOfMonth(DateUtil.date()));
List<DeliveryOrderDO> deliveryOrders = deliveryOrderMapper.selectList(lambdaQueryWrapperx);
Map<Long,List<DeliveryOrderDO>> groupCustomerMap = new HashMap<>();
for (DeliveryOrderDO deliveryOrder : deliveryOrders) {//按客户分组
if(groupCustomerMap.containsKey(deliveryOrder.getCustomerId())){
List<DeliveryOrderDO> list = groupCustomerMap.get(deliveryOrder.getCustomerId());
list.add(deliveryOrder);
groupCustomerMap.put(deliveryOrder.getCustomerId(), list);
}else {
groupCustomerMap.put(deliveryOrder.getCustomerId(), Stream.of(deliveryOrder).collect(Collectors.toList()));
}
}
for (Long customerId : groupCustomerMap.keySet()) {
List<DeliveryOrderDO> deliveryOrders2 = groupCustomerMap.get(customerId);
List<StatementAccountEntryDO> listentrys = new ArrayList<>();
for (DeliveryOrderDO deliveryOrder : deliveryOrders2) {
//创建对账单
StatementAccountSaveReqVO saveReqVO = new StatementAccountSaveReqVO();
boolean isAdd = true;
//查询是否存在重复数据
LambdaQueryWrapper<StatementAccountDO> lambdaQueryWrapper2 = new LambdaQueryWrapper<>();
lambdaQueryWrapper2.eq(StatementAccountDO::getCustomerId,customerId);
lambdaQueryWrapper2.between(StatementAccountDO::getDate, DateUtil.beginOfMonth(DateUtil.date()),DateUtil.endOfMonth(DateUtil.date()));
List<StatementAccountDO> statementAccounts2 = statementAccountMapper.selectList(lambdaQueryWrapper2);
if(!statementAccounts2.isEmpty()){
StatementAccountDO statementAccountDO = statementAccounts2.get(0);
saveReqVO.setId(statementAccountDO.getId());
saveReqVO.setBillno(statementAccountDO.getBillno());
saveReqVO.setCustomerId(statementAccountDO.getCustomerId());
saveReqVO.setDate(statementAccountDO.getDate());
isAdd = false;
}else {
DateTime date = DateUtil.beginOfMonth(new Date(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()));
saveReqVO.setBillno(getNewBillNo());
saveReqVO.setDate(date.toLocalDateTime());
}
saveReqVO.setCustomerId(deliveryOrder.getCustomerId());
List<DeliveryOrderEntryDO> deliveryOrderEntrys = deliveryOrderService.getDeliveryOrderEntryListByParentId(deliveryOrder.getId());
for (DeliveryOrderEntryDO deliveryOrderEntry : deliveryOrderEntrys) {
StatementAccountEntryDO saveEntry = new StatementAccountEntryDO();
saveEntry.setSaleContractNo(deliveryOrder.getSaleContractNo());
saveEntry.setOrderDate(deliveryOrder.getSaleorderDate());
saveEntry.setDeliveryNo(deliveryOrder.getBillno());
saveEntry.setDeliveryDate(deliveryOrder.getDate());
saveEntry.setMaterialId(deliveryOrderEntry.getMaterialId());
saveEntry.setMaterialCode(deliveryOrderEntry.getMaterialNumber());
saveEntry.setMaterialName(deliveryOrderEntry.getMaterialName());
saveEntry.setQty(deliveryOrderEntry.getQty());
saveEntry.setPrice(deliveryOrderEntry.getPrice());
saveEntry.setCurrency(deliveryOrderEntry.getCurrency());
saveEntry.setAmount(deliveryOrderEntry.getPrice().multiply(BigDecimal.valueOf(deliveryOrderEntry.getQty())).setScale(2, RoundingMode.HALF_UP));
saveEntry.setContact(deliveryOrder.getContact());
saveEntry.setUnit(deliveryOrderEntry.getUnit());
listentrys.add(saveEntry);
}
saveReqVO.setStatementAccountEntrys(listentrys);
if(!isAdd){
updateStatementAccount(saveReqVO);
}else {
createStatementAccount(saveReqVO);
}
}
}
}
}

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.hangtag.module.oms.dal.mysql.deliveryorder.DeliveryOrderMapper">
<!--
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
文档可见https://www.iocoder.cn/MyBatis/x-plugins/
-->
<select id="selectPageV2" resultType="cn.hangtag.module.oms.dal.dataobject.deliveryorder.DeliveryOrderDO">
select a.* from oms_delivery_order a
left join oms_customer cus on cus.id = a.customer_id
<where>
<if test="reqVO.billno != null and reqVO.billno != '' "> AND a.billno = #{reqVO.billno} </if>
<if test="reqVO.saleorderNo != null and reqVO.saleorderNo != '' "> AND a.saleorder_no = #{reqVO.saleorderNo} </if>
<if test="reqVO.date != null "> AND a.date between #{reqVO.date[0]} AND #{reqVO.date[1]}</if>
<if test="reqVO.customerName != null and reqVO.customerName != '' "> AND cus.name LIKE CONCAT('%',#{reqVO.customerName},'%') </if>
<if test="reqVO.logisticsCompany != null and reqVO.logisticsCompany != '' "> AND a.logistics_company = #{reqVO.logisticsCompany} </if>
<if test="reqVO.logisticsCode != null and reqVO.logisticsCode != '' "> AND a.logistics_code = #{reqVO.logisticsCode} </if>
<if test="reqVO.contact != null and reqVO.contact != '' "> AND a.contact LIKE CONCAT('%',#{reqVO.contact},'%') </if>
<if test="reqVO.phone != null and reqVO.phone != '' "> AND a.phone LIKE CONCAT('%',#{reqVO.phone},'%') </if>
<if test="reqVO.customerPurNo != null and reqVO.customerPurNo != '' "> AND a.customer_pur_no LIKE CONCAT('%',#{reqVO.customerPurNo},'%') </if>
<if test="reqVO.saleContractNo != null and reqVO.saleContractNo != '' "> AND a.sale_contract_no LIKE CONCAT('%',#{reqVO.saleContractNo},'%') </if>
<if test="reqVO.createTime != null "> AND a.createTime between #{reqVO.createTime[0]} AND #{reqVO.createTime[1}</if>
</where>
order by create_time desc
</select>
</mapper>

View File

@ -129,4 +129,29 @@
</update>
<update id="updateDeliveryOrderYWCStatus" parameterType="Long">
UPDATE oms_saleorder um
INNER JOIN (
SELECT
ud.parent_id master_id,
COUNT(ud.id) as total_up_details,
COUNT(dd.id) as matched_down_details
FROM oms_saleorder_entry ud
LEFT JOIN oms_delivery_order_entry dd ON dd.saleorderentry_id = ud.id
LEFT JOIN oms_delivery_order dm ON dm.saleorder_id = dd.id
AND dm.saleorder_id = ud.parent_id -- 下游主表与上游主表的关联
WHERE ud.parent_id in
<foreach item="id" collection="list" open="(" separator="," close=")">
#{id}
</foreach>
-- 指定上游主表ID
GROUP BY ud.parent_id
) stats ON stats.master_id = um.id
SET um.bill_status = 'F',um.order_status = 2
WHERE stats.total_up_details = stats.matched_down_details
AND um.bill_status = 'E'
AND stats.total_up_details > 0; -- 确保有子表数据
</update>
</mapper>

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.hangtag.module.oms.dal.mysql.statementaccount.StatementAccountMapper">
<!--
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
文档可见https://www.iocoder.cn/MyBatis/x-plugins/
-->
<select id="selectPageV2" resultType="cn.hangtag.module.oms.dal.dataobject.statementaccount.StatementAccountDO">
select a.* from oms_statement_account a
left join oms_customer cus on cus.id = a.customer_id
<where>
<if test="reqVO.billno != null and reqVO.billno != '' "> AND a.billno = #{reqVO.billno} </if>
<if test="reqVO.date != null "> AND a.date between #{reqVO.date[0]} AND #{reqVO.date[1]}</if>
<if test="reqVO.customerName != null and reqVO.customerName != '' "> AND cus.name LIKE CONCAT('%',#{reqVO.customerName},'%') </if>
</where>
order by billno desc
</select>
</mapper>

View File

@ -0,0 +1,292 @@
<!DOCTYPE html>
<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
<title th:text="${title}">送货单</title>
<!-- 引入 Bootstrap -->
<style>
@page {
size: a4;
}
/* 内联CSS样式确保在PDF中正确渲染 */
body {
font-family: "SimSun", serif;
padding: 10px;
line-height: 1.6;
}
h1 {
text-align: center;
margin-top: 0px;
margin-bottom: 0px;
color: #333;
}
h3 {
text-align: center;
margin-top: 0px;
margin-bottom: 0px;
color: #333;
}
h4 {
text-align: center;
margin-top: 0px;
margin-bottom: 0px;
color: #333;
}
.row {
box-sizing: border-box;
overflow: hidden;
margin-left: 0 !important;
margin-right: 0 !important;
}
.font-title {
font-size: 11.5px;
}
.border-bottom {
border-bottom: 2px solid #000;
/* 修改为您想要的颜色和宽度 */
}
.border-top {
border-top: 2px solid #000;
/* 修改为您想要的颜色和宽度 */
}
.fixed-bottom {
margin-top: 115px;
}
.itemtitle {
flex: 0 0 55%;
}
.table>:not(caption)>*>* {
padding: 0px 0px 0px 0px;
border-bottom-width: 0px;
}
.tablelist tr{
font-size: 14px;
}
.formhead{
height: 40mm;
}
.tablelist{
position: relative; /* 为内部绝对定位的元素提供参考 */
height: 180mm; /* 容器高度 */
}
.absolute-item {
position: absolute; /* 绝对定位 */
top: 0; /* 顶部对齐 */
left: 0; /* 左侧对齐 */
right: 0; /* 右侧对齐 */
bottom: 0; /* 底部对齐 */
overflow: hidden; /* 隐藏溢出的内容 */
}
</style>
</head>
<body>
<h3 >东莞嘉晋印刷有限公司</h3>
<h4 >地址:东莞市凤岗镇竹尾田村麻埔坳工业区</h4>
<h4 >电话0769-87773701 传真0769-87505156</h4>
<h3 >送货单</h3>
<table class="formhead" style="width: 100%;font-size: 14px;">
<tr>
<td style="width: 10%;vertical-align: top;"></td>
<td style="width: 40%;vertical-align: top;" th:text="': '+${customerName}"></td>
<td style="width: 12.5%;text-align: right;vertical-align: top;">送货单编号</td>
<td style="width: 32.5%;vertical-align: top;" th:text="': '+${billno}">:</td>
</tr>
<tr>
<td style="width: 1%;vertical-align: top;"></td>
<td style="width: 49%;vertical-align: top;" th:text="' '+${customerAddress}"></td>
<td style="width: 12%; text-align: right;vertical-align: top;">日期</td>
<td style="width: 33%;vertical-align: top;" th:text="': '+${bizDate}">:</td>
</tr>
<tr>
<td style="width: 1%;vertical-align: top;"></td>
<td style="width: 49%;vertical-align: top;" th:text="' '+${contact}"></td>
<td style="width: 12%;text-align: right;vertical-align: top;">客户</td>
<td style="width: 33%;vertical-align: top;" th:text="': '+${customerNo}">:</td>
</tr>
<tr>
<td style="width: 1%;vertical-align: top;"></td>
<td style="width: 49%;vertical-align: top;"></td>
<td style="width: 12%;text-align: right;vertical-align: top;">电话</td>
<td style="width: 33%;vertical-align: top;" th:text="': '+${tel}">:</td>
</tr>
<tr>
<td style="width: 10%;">负责人</td>
<td style="width: 90%;" colspan="3" th:text="': '+${personText}">:</td>
</tr>
</table>
<div class="tablelist">
<div class="absolute-item">
<table class="table" style="width: 100%; border-collapse: collapse;">
<thead style="border-bottom:1px solid black;">
<tr>
<th style="width: 5%;text-align: left;">项目</th>
<th style="width: 90%;text-align: left;">产品说明</th>
<th style="width: 5%;text-align: left;">数量</th>
</tr>
</thead>
<tbody>
<tr th:each="item, stat : ${items}" >
<td style="border: 0;vertical-align: top;" th:text="${stat.index + 1}">1</td>
<td style="border: 0;" >
<span th:text="${item.productDesc1}"></span>
<br/><span th:text="${item.productDesc2}"></span>
<br/><span th:text="${item.productDesc3}"></span>
<br/><span th:text="${item.productDesc4}"></span>
<br/><span th:text="${item.productDesc5}"></span>
</td>
<td style="border: 0;vertical-align: top;" th:text="${item.qty}">CCC</td>
</tr>
<!-- <tr>
<td th:text="${item1}">1</td>
<td th:text="${explain1}">Doe</td>
<td style="text-align: center; " th:text="${qty1}">12344</td>
</tr>
<tr>
<td></td>
<td scope="row" colspan="6" th:text="${explain11}">跨越多列的标题</td>
</tr>
<tr>
<td></td>
<td scope="row" colspan="6" th:text="${explain12}">跨越多列的标题</td>
</tr>
<tr>
<td></td>
<td scope="row" colspan="6" th:text="${explain13}">跨越多列的标题</td>
</tr>
<tr>
<td th:text="${item2}">2</td>
<td th:text="${explain2}">Doe</td>
<td style="text-align: center; " th:text="${qty2}">12344</td>
</tr>
<tr>
<td></td>
<td scope="row" colspan="6" th:text="${explain21}">跨越多列的标题</td>
</tr>
<tr>
<td></td>
<td scope="row" colspan="6" th:text="${explain22}">跨越多列的标题</td>
</tr>
<tr>
<td></td>
<td scope="row" colspan="6" th:text="${explain23}">跨越多列的标题</td>
</tr>
<tr>
<td th:text="${item3}">3</td>
<td th:text="${explain3}">Doe</td>
<td style="text-align: center; " th:text="${qty3}">12344</td>
<tr>
<td></td>
<td scope="row" colspan="6" th:text="${explain31}">跨越多列的标题</td>
</tr>
<tr>
<td></td>
<td scope="row" colspan="6" th:text="${explain32}">跨越多列的标题</td>
</tr>
<tr>
<td></td>
<td scope="row" colspan="6" th:text="${explain33}">跨越多列的标题</td>
</tr>
<tr>
<td th:text="${item4}">4</td>
<td th:text="${explain4}">Doe</td>
<td style="text-align: center; " th:text="${qty4}">12344</td>
</tr>
<tr>
<td></td>
<td scope="row" colspan="6" th:text="${explain41}">跨越多列的标题</td>
</tr>
<tr>
<td></td>
<td scope="row" colspan="6" th:text="${explain42}">跨越多列的标题</td>
</tr>
<tr>
<td></td>
<td scope="row" colspan="6" th:text="${explain43}">跨越多列的标题</td>
</tr>
<tr>
<td th:text="${item5}">5</td>
<td th:text="${explain5}">Doe</td>
<td style="text-align: center; " th:text="${qty5}">12344</td>
</tr>
<tr>
<td></td>
<td scope="row" colspan="6" th:text="${explain51}">跨越多列的标题</td>
</tr>
<tr>
<td></td>
<td scope="row" colspan="6" th:text="${explain52}">跨越多列的标题</td>
</tr>
<tr>
<td></td>
<td scope="row" colspan="6" th:text="${explain53}">跨越多列的标题</td>
</tr>-->
</tbody>
</table>
</div>
</div>
<br />
<div class="row">
<span style="font-weight:bolder;font-size: 14px;">备注:</span>
</div>
<br/>
<br/>
<div>
<p style="text-align: right;font-size: 14px;">
<span style="font-weight:bolder"><<<合计<span th:text="${totalQty}">11111</span> 件>>> &nbsp;&nbsp;&nbsp;</span>
</p>
<p style="text-align: right;font-size: 14px;">
<span style="font-weight:bolder">速运公司:<span th:text="${logisticsCompany}">11111</span> &nbsp;&nbsp;&nbsp;</span>
<span style="font-weight:bolder">单号:<span th:text="${logisticsCode}">11111</span> &nbsp;&nbsp;&nbsp;</span>
</p>
</div>
<div class="fixed-bottom">
<table style="width: 100%;font-size: 14px;">
<tr>
<td style="width: 50%;font-weight: bold;border-bottom: 1px solid black; "></td>
<td style="width: 50%;font-weight: bold;border-bottom: 1px solid black; "></td>
</tr>
<tr>
<td style="width: 50%;font-weight: bold;">东莞嘉晋印刷有限公司</td>
<td style="width: 50%;font-weight: bold;">收货方签名盖章</td>
</tr>
</table>
</div>
</body>
</html>

View File

@ -0,0 +1,69 @@
import request from '@/config/axios'
// 送货单 VO
export interface DeliveryOrderVO {
billno: string // 单据编号
saleorderNo: string // 销售订单号
date: Date // 日期
address: string // 收货地址
logisticsCompany: string // 物流公司
logisticsCode: string // 物流编码
contact: string // 联系人
phone: string // 联系人手机号
tel: string // 电话
totalQty: number // 总数量
totalAmount: number // 总金额
id: number // ID
saleorderId: number // 销售订单ID
customerId: number // 客户ID数组
salesPersonIds: string // 业务员id
customerPurNo: string // 客户采购编号
saleContractNo: string // 销售合约号
}
// 送货单 API
export const DeliveryOrderApi = {
// 查询送货单分页
getDeliveryOrderPage: async (params: any) => {
return await request.get({ url: `/oms/delivery-order/page`, params })
},
// 查询送货单详情
getDeliveryOrder: async (id: number) => {
return await request.get({ url: `/oms/delivery-order/get?id=` + id })
},
// 新增送货单
createDeliveryOrder: async (data: DeliveryOrderVO) => {
return await request.post({ url: `/oms/delivery-order/create`, data })
},
// 修改送货单
updateDeliveryOrder: async (data: DeliveryOrderVO) => {
return await request.put({ url: `/oms/delivery-order/update`, data })
},
// 删除送货单
deleteDeliveryOrder: async (id: number) => {
return await request.delete({ url: `/oms/delivery-order/delete?id=` + id })
},
// 导出送货单 Excel
exportDeliveryOrder: async (params) => {
return await request.download({ url: `/oms/delivery-order/export-excel`, params })
},
// ==================== 子表(送货单明细) ====================
// 获得送货单明细列表
getDeliveryOrderEntryListByParentId: async (parentId) => {
return await request.get({ url: `/oms/delivery-order/delivery-order-entry/list-by-parent-id?parentId=` + parentId })
},
// 导出PIPDF
exportPdf: async (ids: number[]) => {
const params = {
ids: ids.join(',')
}
return await request.download({ url: `/oms/delivery-order/exportPdf`, params})
} ,
}

View File

@ -26,6 +26,12 @@ export interface SaleOrderVO {
totalAmount: number // 总金额
}
// 销售订单 VO
export interface SaleOrderEntryVO {
itemKey: number // ID
parentId: number // 主表id
}
// 销售订单 API
export const SaleOrderApi = {
// 查询销售订单分页
@ -142,5 +148,11 @@ export const SaleOrderApi = {
data: data
})
},
//生成发货单
updatePushDeliveryOrder: async (data) => {
return await request.post({
url: `/oms/sale-order/updatePushDeliveryOrder`,
data: data
})
}
}

View File

@ -0,0 +1,55 @@
import request from '@/config/axios'
// 对账单 VO
export interface StatementAccountVO {
date: Date // 日期月份
customerId: number // 客户
}
// 对账单 API
export const StatementAccountApi = {
// 查询对账单分页
getStatementAccountPage: async (params: any) => {
return await request.get({ url: `/oms/statement-account/page`, params })
},
// 查询对账单详情
getStatementAccount: async (id: number) => {
return await request.get({ url: `/oms/statement-account/get?id=` + id })
},
// 新增对账单
createStatementAccount: async (data: StatementAccountVO) => {
return await request.post({ url: `/oms/statement-account/create`, data })
},
// 修改对账单
updateStatementAccount: async (data: StatementAccountVO) => {
return await request.put({ url: `/oms/statement-account/update`, data })
},
// 删除对账单
deleteStatementAccount: async (id: number) => {
return await request.delete({ url: `/oms/statement-account/delete?id=` + id })
},
// 导出对账单 Excel
exportStatementAccount: async (params) => {
return await request.download({ url: `/oms/statement-account/export-excel`, params })
},
// 导出对账单 Excel
exportStatementAccount2: async (ids: number[]) => {
const params = {
ids: ids.join(',')
}
return await request.download({ url: `/oms/statement-account/export-excel2`, params })
},
// ==================== 子表(对账单明细) ====================
// 获得对账单明细列表
getStatementAccountEntryListByParentId: async (parentId) => {
return await request.get({ url: `/oms/statement-account/statement-account-entry/list-by-parent-id?parentId=` + parentId })
}
}

View File

@ -212,6 +212,17 @@ export function dateFormatter2(_row: any, _column: TableColumnCtx<any>, cellValu
return cellValue ? formatDate(cellValue, 'YYYY-MM-DD') : ''
}
/**
* element plus Formatter 使 YYYY-MM-DD
*
* @param row
* @param column
* @param cellValue
*/
export function dateFormatter3(_row: any, _column: TableColumnCtx<any>, cellValue: any): string {
return cellValue ? formatDate(cellValue, 'YYYYMM') : ''
}
/**
* 时间为00:00:00
* @param param

View File

@ -0,0 +1,207 @@
<template>
<Dialog title="详情" v-model="dialogVisible" width="65%">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="150px"
:inline="true"
hide-required-asterisk="true"
disabled="true"
v-loading="formLoading"
>
<el-form-item label="单据编号" prop="billno">
<el-input v-model="formData.billno" placeholder="" />
</el-form-item>
<el-form-item label="销售订单号" prop="saleorderNo">
<el-input v-model="formData.saleorderNo" placeholder="" />
</el-form-item>
<el-form-item label="下单日期" prop="saleorderDate">
<el-date-picker
v-model="formData.saleorderDate"
type="date"
value-format="x"
placeholder="选择日期"
/>
</el-form-item>
<el-form-item label="日期" prop="date">
<el-date-picker
v-model="formData.date"
type="date"
value-format="x"
placeholder="选择日期"
/>
</el-form-item>
<el-form-item label="收货地址" prop="address">
<el-input v-model="formData.address" placeholder="" />
</el-form-item>
<el-form-item label="物流公司" prop="logisticsCompany">
<el-input v-model="formData.logisticsCompany" placeholder="" />
</el-form-item>
<el-form-item label="物流编码" prop="logisticsCode">
<el-input v-model="formData.logisticsCode" placeholder="" />
</el-form-item>
<el-form-item label="联系人" prop="contact">
<el-input v-model="formData.contact" placeholder="" />
</el-form-item>
<el-form-item label="联系人手机号" prop="phone">
<el-input v-model="formData.phone" placeholder="" />
</el-form-item>
<el-form-item label="电话" prop="tel">
<el-input v-model="formData.tel" placeholder="" />
</el-form-item>
<el-form-item label="总数量" prop="totalQty">
<el-input v-model="formData.totalQty" placeholder="" />
</el-form-item>
<el-form-item label="总金额" prop="totalAmount">
<el-input v-model="formData.totalAmount" placeholder="" />
</el-form-item>
<!-- <el-form-item label="业务员id" prop="salesPersonIds">
<el-input v-model="formData.salesPersonIds" placeholder="请输入业务员id" />
</el-form-item>-->
<el-form-item label="业务员" prop="salesPersonNames">
<el-input v-model="formData.salesPersonNames" placeholder="" />
</el-form-item>
<el-form-item label="客户采购编号" prop="customerPurNo">
<el-input v-model="formData.customerPurNo" placeholder="" />
</el-form-item>
<el-form-item label="销售合约号" prop="saleContractNo">
<el-input v-model="formData.saleContractNo" placeholder="" />
</el-form-item>
</el-form>
<!-- 子表的表单 -->
<el-tabs v-model="subTabsName">
<el-tab-pane label="送货单明细" name="deliveryOrderEntry">
<DeliveryOrderEntryForm ref="deliveryOrderEntryFormRef" :parent-id="formData.id" />
</el-tab-pane>
</el-tabs>
<template #footer>
<!-- <el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>-->
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { DeliveryOrderApi, DeliveryOrderVO } from '@/api/oms/deliveryorder'
import DeliveryOrderEntryForm from './components/DeliveryOrderEntryForm.vue'
/** 送货单 表单 */
defineOptions({ name: 'DeliveryOrderForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
billno: undefined,
saleorderNo: undefined,
saleorderDate: undefined,
date: undefined,
address: undefined,
logisticsCompany: undefined,
logisticsCode: undefined,
contact: undefined,
phone: undefined,
tel: undefined,
totalQty: undefined,
totalAmount: undefined,
id: undefined,
saleorderId: undefined,
customerId: undefined,
salesPersonIds: undefined,
salesPersonNames: undefined,
customerPurNo: undefined,
saleContractNo: undefined
})
const formRules = reactive({
billno: [{ required: true, message: '单据编号不能为空', trigger: 'blur' }],
saleorderNo: [{ required: true, message: '销售订单号不能为空', trigger: 'blur' }],
saleorderId: [{ required: true, message: '销售订单ID不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
/** 子表的表单 */
const subTabsName = ref('deliveryOrderEntry')
const deliveryOrderEntryFormRef = ref()
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await DeliveryOrderApi.getDeliveryOrder(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
try {
await deliveryOrderEntryFormRef.value.validate()
} catch (e) {
subTabsName.value = 'deliveryOrderEntry'
return
}
//
formLoading.value = true
try {
const data = formData.value as unknown as DeliveryOrderVO
//
data.deliveryOrderEntrys = deliveryOrderEntryFormRef.value.getData()
if (formType.value === 'create') {
await DeliveryOrderApi.createDeliveryOrder(data)
message.success(t('common.createSuccess'))
} else {
await DeliveryOrderApi.updateDeliveryOrder(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
billno: undefined,
saleorderNo: undefined,
saleorderDate: undefined,
date: undefined,
address: undefined,
logisticsCompany: undefined,
logisticsCode: undefined,
contact: undefined,
phone: undefined,
tel: undefined,
totalQty: undefined,
totalAmount: undefined,
id: undefined,
saleorderId: undefined,
customerId: undefined,
salesPersonIds: undefined,
salesPersonNames: undefined,
customerPurNo: undefined,
saleContractNo: undefined
}
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,126 @@
<template>
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
v-loading="formLoading"
label-width="0px"
:inline-message="true"
disabled="true"
>
<el-table :data="formData" class="-mt-10px">
<el-table-column label="序号" type="index" width="100" />
<el-table-column label="物料编码" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.materialNumber`" :rules="formRules.materialNumber" class="mb-0px!" >
<el-input v-model="row.materialNumber" placeholder="" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="物料名称" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.materialName`" :rules="formRules.materialName" class="mb-0px!">
<el-input v-model="row.materialName" placeholder="" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="物料规格" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.materialSpec`" :rules="formRules.materialSpec" class="mb-0px!" >
<el-input v-model="row.materialSpec" placeholder="" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="数量" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.qty`" :rules="formRules.qty" class="mb-0px!" >
<el-input v-model="row.qty" placeholder="" disabled="true"/>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="单位" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.unit`" :rules="formRules.unit" class="mb-0px!">
<el-input v-model="row.unit" placeholder="" />
</el-form-item>
</template>
</el-table-column>
<!-- <el-table-column align="center" fixed="right" label="操作" width="60">
<template #default="{ $index }">
<el-button @click="handleDelete($index)" link></el-button>
</template>
</el-table-column>-->
</el-table>
</el-form>
<!-- <el-row justify="center" class="mt-3">
<el-button @click="handleAdd" round>+ 添加送货单明细</el-button>
</el-row>-->
</template>
<script setup lang="ts">
import { DeliveryOrderApi } from '@/api/oms/deliveryorder'
const props = defineProps<{
parentId: undefined // ID
}>()
const formLoading = ref(false) //
const formData = ref([])
const formRules = reactive({
parentId: [{ required: true, message: '主表ID不能为空', trigger: 'blur' }],
saleorderentryId: [{ required: true, message: '销售订单分录ID不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
/** 监听主表的关联字段的变化,加载对应的子表数据 */
watch(
() => props.parentId,
async (val) => {
// 1.
formData.value = []
// 2. val
if (!val) {
return;
}
try {
formLoading.value = true
formData.value = await DeliveryOrderApi.getDeliveryOrderEntryListByParentId(val)
} finally {
formLoading.value = false
}
},
{ immediate: true }
)
/** 新增按钮操作 */
const handleAdd = () => {
const row = {
materialNumber: undefined,
materialName: undefined,
materialSpec: undefined,
qty: undefined,
id: undefined,
parentId: undefined,
saleorderentryId: undefined,
materialId: undefined,
unit: undefined
}
row.parentId = props.parentId
formData.value.push(row)
}
/** 删除按钮操作 */
const handleDelete = (index) => {
formData.value.splice(index, 1)
}
/** 表单校验 */
const validate = () => {
return formRef.value.validate()
}
/** 表单值 */
const getData = () => {
return formData.value
}
defineExpose({ validate, getData })
</script>

View File

@ -0,0 +1,333 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="88px"
>
<el-form-item label="单据编号" prop="billno">
<el-input
v-model="queryParams.billno"
placeholder="请输入单据编号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="销售订单号" prop="saleorderNo">
<el-input
v-model="queryParams.saleorderNo"
placeholder="请输入销售订单号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="日期" prop="date">
<el-date-picker
v-model="queryParams.date"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="客户" prop="customerName">
<el-input
v-model="queryParams.customerName"
placeholder="请输入客户名称"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="物流编码" prop="logisticsCode">
<el-input
v-model="queryParams.logisticsCode"
placeholder="请输入物流编码"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="联系人" prop="contact">
<el-input
v-model="queryParams.contact"
placeholder="请输入联系人"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="联系人手机号" prop="phone" label-width="100px">
<el-input
v-model="queryParams.phone"
placeholder="请输入联系人手机号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="客户采购编号" prop="customerPurNo" label-width="100px">
<el-input
v-model="queryParams.customerPurNo"
placeholder="请输入客户采购编号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="销售合约号" prop="saleContractNo">
<el-input
v-model="queryParams.saleContractNo"
placeholder="请输入销售合约号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<!-- <el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['oms:delivery-order:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>-->
<el-button
type="primary"
plain
:loading="exportLoading2"
@click="exportPdf()"
:disabled="selectionList.length === 0"
>
导出PDF
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['oms:delivery-order:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list"
:stripe="true"
:show-overflow-tooltip="true"
@selection-change="handleSelectionChange"
>
<el-table-column width="30" label="选择" type="selection" />
<el-table-column label="单据编号" align="center" prop="billno" width="180px" />
<el-table-column label="销售订单号" align="center" prop="saleorderNo" width="180px" />
<el-table-column
label="日期"
align="center"
prop="date"
:formatter="dateFormatter2"
width="100px"
/>
<el-table-column label="收货地址" align="center" prop="address" width="180px"/>
<el-table-column label="物流公司" align="center" prop="logisticsCompany" width="110px"/>
<el-table-column label="物流编码" align="center" prop="logisticsCode" width="150px"/>
<el-table-column label="联系人" align="center" prop="contact" width="110px"/>
<el-table-column label="联系人手机号" align="center" prop="phone" width="160px"/>
<el-table-column label="电话" align="center" prop="tel" width="160px" />
<el-table-column label="总数量" align="center" prop="totalQty" width="80px" />
<el-table-column label="总金额" align="center" prop="totalAmount" width="100px" />
<el-table-column label="客户名称" align="center" prop="customer.name" width="220px"/>
<el-table-column label="客户采购编号" align="center" prop="customerPurNo" width="180px"/>
<el-table-column label="销售合约号" align="center" prop="saleContractNo" width="180px"/>
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['oms:delivery-order:update']"
>
查看
</el-button>
<!-- <el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['oms:delivery-order:delete']"
>
删除
</el-button>-->
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<DeliveryOrderForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import {dateFormatter, dateFormatter2, formatDate} from '@/utils/formatTime'
import download from '@/utils/download'
import {DeliveryOrderApi, DeliveryOrderVO} from '@/api/oms/deliveryorder'
import DeliveryOrderForm from './DeliveryOrderForm.vue'
/** 送货单 列表 */
defineOptions({ name: 'DeliveryOrder' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<DeliveryOrderVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
billno: undefined,
saleorderNo: undefined,
date: [],
logisticsCode: undefined,
contact: undefined,
phone: undefined,
saleorderId: undefined,
customerId: undefined,
customerName: undefined,
salesPersonIds: undefined,
customerPurNo: undefined,
saleContractNo: undefined,
createTime: []
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await DeliveryOrderApi.getDeliveryOrderPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await DeliveryOrderApi.deleteDeliveryOrder(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await DeliveryOrderApi.exportDeliveryOrder(queryParams)
download.excel(data, '送货单.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 选中操作 */
const selectionList = ref<DeliveryOrderVO[]>([])
const handleSelectionChange = (rows: DeliveryOrderVO[]) => {
selectionList.value = rows
}
const exportLoading2 = ref(false) //
/** 导出PIpdf文件 */
const exportPdf = async () => {
try {
const ids = selectionList.value.map((item) => item.id)
//
await message.exportConfirm("是否确认导出PDF")
//
exportLoading2.value = true
//
const data = await DeliveryOrderApi.exportPdf(ids)
download.zip(data, '送货单.zip')
selectionList.value = selectionList.value.filter((item) => !ids.includes(item.id))
} catch {
} finally {
exportLoading2.value = false
}
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>

View File

@ -148,7 +148,10 @@
<template v-slot:title>
<div class="entrysContainer">
<div>产品信息</div>
<el-button type="primary" @click="addProduct" v-if="formData.billStatus == 'B'">新增行</el-button>
<div>
<el-button type="primary" @click="addProduct" v-if="formData.billStatus == 'B'">新增行</el-button>
<el-button type="primary" @click="pushDeliveryOrder" v-if="formData.billStatus == 'E'">生成发货单</el-button>
</div>
</div>
</template>
<el-descriptions-item labelClassName="no-colon">
@ -164,9 +167,10 @@
<el-table :data="formData.entrys"
border
:on-cell-click="cellClick"
@selection-change="handleSelectionChange"
>
<el-table-column width="30" label="选择" type="selection" />
<el-table-column label="产品编码" prop="materialNumber" width="150"/>
<el-table-column label="产品名称" prop="materialName" width="150"/>
<el-table-column label="产品规格" prop="materialSpec" width="150" />
@ -277,6 +281,28 @@
</el-descriptions>
</ContentWrap>
<!-- 生成下推发货单对话框 -->
<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.ids" type="text" />
</el-form-item>
<el-form-item label="物流公司" prop="logisticsCompany" >
<el-input v-model="pushOutBillform.logisticsCompany" type="text" placeholder="请输入物流公司" />
</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>
<!-- 各种操作的弹窗 -->
<OrderUpdateRemarkForm ref="updateRemarkForm" @success="getDetail" />
<OrderUpdateAddressForm ref="updateAddressFormRef" @success="getDetail" />
@ -291,7 +317,7 @@ import OrderUpdateAddressForm from '@/views/oms/saleorder/form/OrderUpdateAddres
import ProductInfoList from '@/components/ProductInfoList/index.vue'
import { useTagsViewStore } from '@/store/modules/tagsView'
import { propTypes } from '@/utils/propTypes'
import {SaleOrderApi, SaleOrderVO} from "@/api/oms/saleorder";
import {SaleOrderApi, SaleOrderEntryVO, SaleOrderVO} from "@/api/oms/saleorder";
defineOptions({ name: 'TradeOrderDetail' })
@ -328,6 +354,17 @@ const itemFormRules = reactive({
const itemFormEntrysRef = ref() // Ref
//
const pushOutBillOpen = ref(false)
const pushOutBillTitle = ref('物流信息')
const pushOutBillform = reactive({
ids: undefined,
logisticsCompany: undefined,
logisticsCode: undefined
})
const itemFormEntrysRules = reactive({
price: [{ required: true, message: '单价不能为空', trigger: 'blur' },
{ validator: validatePrice, trigger: 'change' } //
@ -377,6 +414,58 @@ const addProduct = () => {
that.filterParam.brandId = formData.value.brandId
productInfoListRef.value.openDialog(that.filterParam)
}
//
const pushDeliveryOrder = async () => {
try {
const entryIds = selectionList.value.map((item) => item.id)
if(Array.isArray(entryIds) && entryIds.length === 0){
message.error("请选择数据行!");
return;
}
pushOutBillform.logisticsCompany = undefined
pushOutBillform.logisticsCode = undefined
pushOutBillOpen.value = true
} catch {}
}
/** 下推生成发货单提交按钮 */
const submitPushOutBillForm = async () => {
const entryIds = selectionList.value.map((item) => item.id)
if(pushOutBillform.logisticsCode != null) {
const data = {
ids:entryIds,
logisticsCompany:pushOutBillform.logisticsCompany,
logisticsCode:pushOutBillform.logisticsCode
}
await SaleOrderApi.updatePushDeliveryOrder(data).then(response => {
debugger;
message.success("生成送货单成功");
pushOutBillOpen.value = false;
});
//
await getDetail()
selectionList.value = selectionList.value.filter((item) => !entryIds.includes(item.id))
}else {
message.error(`请填写物流信息!`)
}
}
/** 生成发货单取消按钮 */
const pushOutBillCancel = () =>{
pushOutBillOpen.value = false
pushOutBillform.logisticsCompany = undefined
pushOutBillform.logisticsCode = undefined
}
/** 选中操作 */
const selectionList = ref<SaleOrderEntryVO[]>([])
const handleSelectionChange = (rows) => {
selectionList.value = rows
}
const submit = (data) => {
for (let i = 0; i < data.length; i++) {
addRow(data[i])
@ -523,7 +612,7 @@ onMounted(async () => {
display: flex;
justify-content: space-between;
align-items: center;
width: 160px; /* 宽度为父容器的80% */
width: 280px; /* 宽度为父容器的80% */
padding: 0px;
margin: 0 auto; /* 可选,用于水平居中 */
}

View File

@ -327,11 +327,11 @@
>
下载附件
</el-dropdown-item>
<el-dropdown-item
<!-- <el-dropdown-item
command="pushOutBill"
>
下推生成出货单
</el-dropdown-item>
</el-dropdown-item>-->
</el-dropdown-menu>
</template>
</el-dropdown>
@ -788,7 +788,7 @@ const submitPushOutBillForm = async () => {
message.error(`请填写物流单号!`)
}
}
/** 驳回取消按钮 */
/** 生成发货单取消按钮 */
const pushOutBillCancel = () =>{
pushOutBillOpen.value = false
pushOutBillform.logisticsCode = undefined

View File

@ -0,0 +1,129 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible" width="65%">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
disabled="true"
v-loading="formLoading"
>
<el-form-item label="月份" prop="date">
<el-date-picker
v-model="formData.date"
type="date"
format="YYYY-MM"
value-format="x"
placeholder="选择日期月份"
/>
</el-form-item>
<el-form-item label="客户名称" prop="customerName">
<el-input v-model="formData.customerName" placeholder="请输入客户" />
</el-form-item>
</el-form>
<!-- 子表的表单 -->
<el-tabs v-model="subTabsName">
<el-tab-pane label="对账单明细" name="statementAccountEntry">
<StatementAccountEntryForm ref="statementAccountEntryFormRef" :parent-id="formData.id" />
</el-tab-pane>
</el-tabs>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { StatementAccountApi, StatementAccountVO } from '@/api/oms/statementaccount'
import StatementAccountEntryForm from './components/StatementAccountEntryForm.vue'
/** 对账单 表单 */
defineOptions({ name: 'StatementAccountForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
date: undefined,
customerId: undefined,
customerNumber: undefined,
customerName: undefined,
customer: undefined
})
const formRules = reactive({
date: [{ required: true, message: '日期月份不能为空', trigger: 'blur' }],
customerId: [{ required: true, message: '客户不能为空', trigger: 'blur' }]
})
const formRef = ref() // Ref
/** 子表的表单 */
const subTabsName = ref('statementAccountEntry')
const statementAccountEntryFormRef = ref()
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await StatementAccountApi.getStatementAccount(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
try {
await statementAccountEntryFormRef.value.validate()
} catch (e) {
subTabsName.value = 'statementAccountEntry'
return
}
//
formLoading.value = true
try {
const data = formData.value as unknown as StatementAccountVO
//
data.statementAccountEntrys = statementAccountEntryFormRef.value.getData()
if (formType.value === 'create') {
await StatementAccountApi.createStatementAccount(data)
message.success(t('common.createSuccess'))
} else {
await StatementAccountApi.updateStatementAccount(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
date: undefined,
customerId: undefined,
customerNumber: undefined,
customerName: undefined,
customer: undefined
}
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,180 @@
<template>
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
v-loading="formLoading"
label-width="0px"
:inline-message="true"
disabled="true"
>
<el-table :data="formData" class="-mt-10px">
<el-table-column label="序号" type="index" width="100" />
<el-table-column label="销售编号" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.saleContractNo`" :rules="formRules.saleContractNo" class="mb-0px!">
<el-input v-model="row.saleContractNo" placeholder="" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="下单日期" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.orderDate`" :rules="formRules.orderDate" class="mb-0px!">
<el-date-picker
v-model="row.orderDate"
type="date"
value-format="x"
placeholder="选择下单日期"
/>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="送货单编号" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.deliveryNo`" :rules="formRules.deliveryNo" class="mb-0px!">
<el-input v-model="row.deliveryNo" placeholder="" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="送货日期" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.deliveryDate`" :rules="formRules.deliveryDate" class="mb-0px!">
<el-date-picker
v-model="row.deliveryDate"
type="date"
value-format="x"
placeholder="选择送货日期"
/>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="产品编号" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.materialCode`" :rules="formRules.materialCode" class="mb-0px!">
<el-input v-model="row.materialCode" placeholder="" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="币别" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.currency`" :rules="formRules.currency" class="mb-0px!">
<el-input v-model="row.currency" placeholder="" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="数量" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.qty`" :rules="formRules.qty" class="mb-0px!">
<el-input v-model="row.qty" placeholder="" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="单价" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.price`" :rules="formRules.price" class="mb-0px!">
<el-input v-model="row.price" placeholder="" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="金额" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.amount`" :rules="formRules.amount" class="mb-0px!">
<el-input v-model="row.amount" placeholder="" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="单位" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.unit`" :rules="formRules.unit" class="mb-0px!">
<el-input v-model="row.unit" placeholder="" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="联系人" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.contact`" :rules="formRules.contact" class="mb-0px!">
<el-input v-model="row.contact" placeholder="" />
</el-form-item>
</template>
</el-table-column>
<!-- <el-table-column align="center" fixed="right" label="操作" width="60">
<template #default="{ $index }">
<el-button @click="handleDelete($index)" link></el-button>
</template>
</el-table-column>-->
</el-table>
</el-form>
<!-- <el-row justify="center" class="mt-3">
<el-button @click="handleAdd" round>+ 添加对账单明细</el-button>
</el-row>-->
</template>
<script setup lang="ts">
import { StatementAccountApi } from '@/api/oms/statementaccount'
const props = defineProps<{
parentId: undefined // ID
}>()
const formLoading = ref(false) //
const formData = ref([])
const formRules = reactive({
})
const formRef = ref() // Ref
/** 监听主表的关联字段的变化,加载对应的子表数据 */
watch(
() => props.parentId,
async (val) => {
// 1.
formData.value = []
// 2. val
if (!val) {
return;
}
try {
formLoading.value = true
formData.value = await StatementAccountApi.getStatementAccountEntryListByParentId(val)
} finally {
formLoading.value = false
}
},
{ immediate: true }
)
/** 新增按钮操作 */
const handleAdd = () => {
const row = {
saleContractNo: undefined,
orderDate: undefined,
deliveryNo: undefined,
deliveryDate: undefined,
materialCode: undefined,
currency: undefined,
qty: undefined,
price: undefined,
amount: undefined,
unit: undefined,
customerNo: undefined,
contact: undefined,
parentId: undefined
}
row.parentId = props.parentId
formData.value.push(row)
}
/** 删除按钮操作 */
const handleDelete = (index) => {
formData.value.splice(index, 1)
}
/** 表单校验 */
const validate = () => {
return formRef.value.validate()
}
/** 表单值 */
const getData = () => {
return formData.value
}
defineExpose({ validate, getData })
</script>

View File

@ -0,0 +1,224 @@
<template>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="日期月份" prop="date">
<el-date-picker
v-model="queryParams.date"
type="monthrange"
value-format="YYYY-MM-DD HH:mm:ss"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
start-placeholder="开始月份"
end-placeholder="结束月份"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="客户" prop="customerName">
<el-input
v-model="queryParams.customerName"
placeholder="请输入客户"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<!-- <el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['oms:statement-account:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>-->
<el-button
type="success"
plain
@click="handleExport2"
:loading="exportLoading"
v-hasPermi="['oms:statement-account:export']"
:disabled="selectionList.length === 0"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true"
@selection-change="handleSelectionChange"
>
<el-table-column width="30" label="选择" type="selection" />
<el-table-column label="单据编号" align="center" prop="billno" />
<el-table-column
label="日期月份"
align="center"
prop="date"
:formatter="dateFormatter3"
width="180px"
/>
<el-table-column label="客户" align="center" prop="customer.name" />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
/>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['oms:statement-account:update']"
>
查看
</el-button>
<!-- <el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['oms:statement-account:delete']"
>
删除
</el-button>-->
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<StatementAccountForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import download from '@/utils/download'
import {StatementAccountApi, StatementAccountVO} from '@/api/oms/statementaccount'
import {dateFormatter, dateFormatter2,dateFormatter3, formatDate} from '@/utils/formatTime'
import StatementAccountForm from './StatementAccountForm.vue'
/** 对账单 列表 */
defineOptions({ name: 'StatementAccount' })
const message = useMessage() //
const { t } = useI18n() //
const loading = ref(true) //
const list = ref<StatementAccountVO[]>([]) //
const total = ref(0) //
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
date: [],
customerName: undefined
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await StatementAccountApi.getStatementAccountPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await StatementAccountApi.deleteStatementAccount(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await StatementAccountApi.exportStatementAccount(queryParams)
download.excel(data, '对账单.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 选中操作 */
const selectionList = ref<StatementAccountVO[]>([])
const handleSelectionChange = (rows: StatementAccountVO[]) => {
selectionList.value = rows
}
/** 导出按钮操作 */
const handleExport2 = async () => {
try {
const ids = selectionList.value.map((item) => item.id)
//
await message.exportConfirm("是否导出选中数据")
//
exportLoading.value = true
const data = await StatementAccountApi.exportStatementAccount2(ids)
download.zip(data, '对账单.zip')
selectionList.value = selectionList.value.filter((item) => !ids.includes(item.id))
} catch {
} finally {
exportLoading.value = false
}
}
/** 初始化 **/
onMounted(() => {
getList()
})
</script>