| | |
| | | package com.ruoyi.sales.service.impl; |
| | | |
| | | import cn.hutool.core.bean.BeanUtil; |
| | | import cn.hutool.core.convert.Convert; |
| | | import cn.hutool.core.date.LocalDateTimeUtil; |
| | | import cn.hutool.core.io.FileUtil; |
| | | import cn.hutool.core.lang.Assert; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.deepoove.poi.XWPFTemplate; |
| | | import com.deepoove.poi.config.Configure; |
| | | import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy; |
| | | import com.ruoyi.account.service.AccountIncomeService; |
| | | import com.ruoyi.aftersalesservice.pojo.AfterSalesService; |
| | | import com.ruoyi.basic.mapper.CustomerMapper; |
| | | import com.ruoyi.basic.mapper.ProductMapper; |
| | | import com.ruoyi.basic.mapper.ProductModelMapper; |
| | |
| | | import com.ruoyi.common.enums.FileNameType; |
| | | import com.ruoyi.common.enums.SaleEnum; |
| | | import com.ruoyi.common.exception.base.BaseException; |
| | | import com.ruoyi.common.utils.DateUtils; |
| | | import com.ruoyi.common.utils.EnumUtil; |
| | | import com.ruoyi.common.utils.SecurityUtils; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.common.utils.*; |
| | | import com.ruoyi.common.utils.poi.ExcelUtil; |
| | | import com.ruoyi.framework.security.LoginUser; |
| | | import com.ruoyi.framework.web.domain.AjaxResult; |
| | | import com.ruoyi.other.mapper.TempFileMapper; |
| | | import com.ruoyi.other.pojo.TempFile; |
| | | import com.ruoyi.production.mapper.*; |
| | | import com.ruoyi.production.pojo.*; |
| | | import com.ruoyi.production.service.ProductionProductMainService; |
| | | import com.ruoyi.production.service.impl.ProductionProductMainServiceImpl; |
| | | import com.ruoyi.project.system.domain.SysDept; |
| | | import com.ruoyi.project.system.domain.SysUser; |
| | | import com.ruoyi.project.system.mapper.SysDeptMapper; |
| | | import com.ruoyi.project.system.mapper.SysUserMapper; |
| | | import com.ruoyi.quality.mapper.QualityInspectMapper; |
| | | import com.ruoyi.quality.pojo.QualityInspect; |
| | | import com.ruoyi.sales.dto.*; |
| | | import com.ruoyi.sales.mapper.*; |
| | | import com.ruoyi.sales.pojo.*; |
| | | import com.ruoyi.sales.service.ISalesLedgerProductService; |
| | | import com.ruoyi.sales.service.ISalesLedgerService; |
| | | import com.ruoyi.sales.vo.ExportProcessContractVo; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.SneakyThrows; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.io.FilenameUtils; |
| | | import org.springframework.beans.BeanUtils; |
| | |
| | | import org.springframework.data.redis.core.script.DefaultRedisScript; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.web.context.request.RequestContextHolder; |
| | | import org.springframework.web.context.request.ServletRequestAttributes; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import javax.validation.constraints.NotNull; |
| | | import java.io.IOException; |
| | | import java.io.InputStream; |
| | | import java.lang.reflect.Field; |
| | |
| | | @RequiredArgsConstructor |
| | | @Slf4j |
| | | public class SalesLedgerServiceImpl extends ServiceImpl<SalesLedgerMapper, SalesLedger> implements ISalesLedgerService { |
| | | private final AccountIncomeService accountIncomeService; |
| | | |
| | | private final SalesLedgerMapper salesLedgerMapper; |
| | | |
| | | private final CustomerMapper customerMapper; |
| | | |
| | | private final SalesLedgerProductMapper salesLedgerProductMapper; |
| | | private final SalesLedgerProductServiceImpl salesLedgerProductServiceImpl; |
| | | |
| | | private final CommonFileMapper commonFileMapper; |
| | | |
| | | private final TempFileMapper tempFileMapper; |
| | | |
| | | private final ReceiptPaymentMapper receiptPaymentMapper; |
| | | |
| | | private final ShippingInfoServiceImpl shippingInfoServiceImpl; |
| | | |
| | | private final CommonFileServiceImpl commonFileService; |
| | | |
| | | private final ShippingInfoMapper shippingInfoMapper; |
| | | |
| | | private final InvoiceLedgerMapper invoiceLedgerMapper; |
| | | |
| | | private final SalesLedgerSchedulingMapper salesLedgerSchedulingMapper; |
| | | |
| | | private final SalesLedgerWorkMapper salesLedgerWorkMapper; |
| | | |
| | | private final SalesLedgerProductionAccountingMapper salesLedgerProductionAccountingMapper; |
| | | |
| | | private final InvoiceRegistrationProductMapper invoiceRegistrationProductMapper; |
| | | |
| | | private final InvoiceRegistrationMapper invoiceRegistrationMapper; |
| | | |
| | | private final ProductOrderMapper productOrderMapper; |
| | | |
| | | private final ProcessRouteMapper processRouteMapper; |
| | | private final ProductProcessRouteMapper productProcessRouteMapper; |
| | | |
| | | private final ProcessRouteItemMapper processRouteItemMapper; |
| | | |
| | | private final ProductProcessRouteItemMapper productProcessRouteItemMapper; |
| | | |
| | | private final ProductWorkOrderMapper productWorkOrderMapper; |
| | | |
| | | private final ProductionProductMainMapper productionProductMainMapper; |
| | | |
| | | private final ProductionProductOutputMapper productionProductOutputMapper; |
| | | |
| | | private final ProductionProductInputMapper productionProductInputMapper; |
| | | |
| | | private final QualityInspectMapper qualityInspectMapper; |
| | | |
| | | @Autowired |
| | | private SysDeptMapper sysDeptMapper; |
| | | |
| | | @Value("${file.upload-dir}") |
| | | private String uploadDir; |
| | | |
| | | private static final String LOCK_PREFIX = "contract_no_lock:"; |
| | | private static final long LOCK_WAIT_TIMEOUT = 10; // éçå¾
è¶
æ¶æ¶é´ï¼ç§ï¼ |
| | | private static final long LOCK_EXPIRE_TIME = 30; // éèªå¨è¿ææ¶é´ï¼ç§ï¼ |
| | | |
| | | private final AccountIncomeService accountIncomeService; |
| | | private final SalesLedgerMapper salesLedgerMapper; |
| | | private final CustomerMapper customerMapper; |
| | | private final SalesLedgerProductMapper salesLedgerProductMapper; |
| | | private final SalesLedgerProductServiceImpl salesLedgerProductServiceImpl; |
| | | private final CommonFileMapper commonFileMapper; |
| | | private final TempFileMapper tempFileMapper; |
| | | private final ReceiptPaymentMapper receiptPaymentMapper; |
| | | private final ShippingInfoServiceImpl shippingInfoServiceImpl; |
| | | private final CommonFileServiceImpl commonFileService; |
| | | private final ShippingInfoMapper shippingInfoMapper; |
| | | private final InvoiceLedgerMapper invoiceLedgerMapper; |
| | | private final SalesLedgerSchedulingMapper salesLedgerSchedulingMapper; |
| | | private final SalesLedgerWorkMapper salesLedgerWorkMapper; |
| | | private final SalesLedgerProductionAccountingMapper salesLedgerProductionAccountingMapper; |
| | | private final InvoiceRegistrationProductMapper invoiceRegistrationProductMapper; |
| | | private final InvoiceRegistrationMapper invoiceRegistrationMapper; |
| | | private final ProductOrderMapper productOrderMapper; |
| | | private final ProcessRouteMapper processRouteMapper; |
| | | private final ProductProcessRouteMapper productProcessRouteMapper; |
| | | private final ProcessRouteItemMapper processRouteItemMapper; |
| | | private final ProductProcessRouteItemMapper productProcessRouteItemMapper; |
| | | private final ProductWorkOrderMapper productWorkOrderMapper; |
| | | private final ProductionProductMainMapper productionProductMainMapper; |
| | | private final ProductionProductOutputMapper productionProductOutputMapper; |
| | | private final ProductionProductInputMapper productionProductInputMapper; |
| | | private final QualityInspectMapper qualityInspectMapper; |
| | | private final RedisTemplate<String, String> redisTemplate; |
| | | @Autowired |
| | | private SysDeptMapper sysDeptMapper; |
| | | @Value("${file.upload-dir}") |
| | | private String uploadDir; |
| | | @Autowired |
| | | private ProductModelMapper productModelMapper; |
| | | |
| | |
| | | @Autowired |
| | | private ProductionProductMainService productionProductMainService; |
| | | ; |
| | | @Autowired |
| | | private SysUserMapper sysUserMapper; |
| | | |
| | | @Override |
| | | public List<SalesLedger> selectSalesLedgerList(SalesLedgerDto salesLedgerDto) { |
| | | return salesLedgerMapper.selectSalesLedgerList(salesLedgerDto); |
| | | } |
| | | |
| | | |
| | | public List<SalesLedgerProduct> getSalesLedgerProductListByRelateId(Long relateId, SaleEnum type){ |
| | | public List<SalesLedgerProduct> getSalesLedgerProductListByRelateId(Long relateId, SaleEnum type) { |
| | | LambdaQueryWrapper<SalesLedgerProduct> productWrapper = new LambdaQueryWrapper<>(); |
| | | productWrapper.eq(SalesLedgerProduct::getSalesLedgerId, relateId); |
| | | productWrapper.eq(SalesLedgerProduct::getType, type.getCode()); |
| | |
| | | return salesLedgerMapper.selectSalesLedgerListPage(page, salesLedgerDto); |
| | | } |
| | | |
| | | @Autowired |
| | | private SysUserMapper sysUserMapper; |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public AjaxResult importData(MultipartFile file) { |
| | |
| | | return salesLedgerDtoIPage; |
| | | } |
| | | |
| | | @Override |
| | | public void exportProcessContract(Long id) { |
| | | //å å·¥æ¿æ½åå |
| | | ExportProcessContractVo exportProcessContract = new ExportProcessContractVo(); |
| | | exportProcessContract.setId(id); |
| | | SalesLedger salesLedger = salesLedgerMapper.selectById(id); |
| | | // æ¥è¯¢å®¢æ·å
¬å¸ä¿¡æ¯ |
| | | Customer customer = customerMapper.selectById(salesLedger.getCustomerId()); |
| | | exportProcessContract.setCreateTime(LocalDateTimeUtil.format(Optional.ofNullable(salesLedger.getExecutionDate()).orElse(LocalDate.now()), "yyyyå¹´MMæddæ¥")); |
| | | exportProcessContract.setRemark(Optional.ofNullable(salesLedger.getRemarks()).orElse("æ ")); // 夿³¨ |
| | | exportProcessContract.setPlaceOfSinging(Optional.ofNullable(salesLedger.getPlaceOfSinging()).orElse("")); |
| | | |
| | | // å
é¨ç±»ç¨äºåå¨èåç»æ |
| | | private static class GroupedCustomer { |
| | | private final Long customerId; |
| | | private final String customerName; |
| | | private BigDecimal totalAmount = BigDecimal.ZERO; |
| | | // å¡«åç²æ¹ä¿¡æ¯ |
| | | ExportProcessContractVo.Customer partyA = ExportProcessContractVo.Customer.getCustomer(customer); |
| | | exportProcessContract.setPartyAClientName(customer.getCustomerName()); |
| | | exportProcessContract.setPartyA(partyA); |
| | | |
| | | public GroupedCustomer(Long customerId, String customerName) { |
| | | this.customerId = customerId; |
| | | this.customerName = customerName; |
| | | // å¡«å乿¹ä¿¡æ¯ |
| | | ExportProcessContractVo.Customer partyB = new ExportProcessContractVo.Customer(); |
| | | exportProcessContract.setPartyBClientName("");//todo@ 乿¹å
¬å¸åç§° |
| | | exportProcessContract.setPartyB(partyB); |
| | | |
| | | // å¡«åååä¿¡æ¯ |
| | | final BigDecimal[] totalAmount = {BigDecimal.ZERO}; // æ»éé¢ |
| | | LambdaQueryWrapper<SalesLedgerProduct> productWrapper = new LambdaQueryWrapper<>(); |
| | | productWrapper.eq(SalesLedgerProduct::getSalesLedgerId, salesLedger.getId()); |
| | | productWrapper.eq(SalesLedgerProduct::getType, 1); |
| | | List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(productWrapper); |
| | | List<ExportProcessContractVo.SaleProduct> productList = products.stream().map(it -> { |
| | | ExportProcessContractVo.SaleProduct saleProduct = BeanUtil.copyProperties(it, ExportProcessContractVo.SaleProduct.class); |
| | | // è®¡ç®æ»ä»·æ ¼ |
| | | totalAmount[0] = totalAmount[0].add(Optional.ofNullable(saleProduct.getTaxInclusiveTotalPrice()).orElse(BigDecimal.ZERO)); |
| | | return saleProduct; |
| | | }).collect(Collectors.toList()); |
| | | // 第ä¸ä¸ªè®¾ç½® ååç¼å· |
| | | if (!productList.isEmpty()) { |
| | | productList.get(0).setSalesContractNo(salesLedger.getSalesContractNo()); |
| | | } |
| | | // æ¥çç¨ç ç论ä¸ç¨çåä¸ï¼å¦æå¤ç¨ç为空 |
| | | Map<BigDecimal, Long> rateMap = productList.stream().map(product -> product.getTaxRate()).filter(Objects::nonNull) |
| | | .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); |
| | | String taxRateStr = rateMap.size() == 1 ? rateMap.keySet().iterator().next().toString() + " %" : ""; |
| | | exportProcessContract.setTaxRate(taxRateStr); |
| | | exportProcessContract.setSaleProducts(productList);// ååä¿¡æ¯ |
| | | // 设置大åçæ»ä»·æ ¼ |
| | | exportProcessContract.setTotalAmountZh(Convert.digitToChinese(totalAmount[0].doubleValue())); |
| | | |
| | | exportProcessContractToWord(exportProcessContract); |
| | | } |
| | | |
| | | @SneakyThrows |
| | | private void exportProcessContractToWord(@NotNull ExportProcessContractVo exportProcessContract){ |
| | | // ç¡®ä¿ saleProducts ä¸ä¸º null |
| | | if (exportProcessContract.getSaleProducts() == null) { |
| | | exportProcessContract.setSaleProducts(new ArrayList<>()); |
| | | } |
| | | |
| | | public void addAmount(BigDecimal amount) { |
| | | if (amount != null) { |
| | | this.totalAmount = this.totalAmount.add(amount); |
| | | } |
| | | } |
| | | // 模æ¿è¾å
¥æµ |
| | | InputStream inputStream = this.getClass().getResourceAsStream("/static/contract_tmp.docx"); |
| | | Assert.isTrue(inputStream != null, "模æ¿ä¸åå¨"); |
| | | |
| | | public Long getCustomerId() { |
| | | return customerId; |
| | | } |
| | | // 转 Map |
| | | Map<String, Object> dataMap = BeanUtil.beanToMap(exportProcessContract); |
| | | |
| | | public String getCustomerName() { |
| | | return customerName; |
| | | } |
| | | // ç»å®å¾ªç¯çç¥ |
| | | Configure configure = Configure.builder() |
| | | .bind("saleProducts", new LoopRowTableRenderPolicy()) |
| | | .build(); |
| | | |
| | | public BigDecimal getTotalAmount() { |
| | | return totalAmount; |
| | | } |
| | | // æ¸²ææ¨¡æ¿ |
| | | XWPFTemplate template = XWPFTemplate.compile(inputStream, configure) |
| | | .render(dataMap); |
| | | // template.write(FileUtil.getOutputStream("/Users/ONEX/Downloads/a.docx")); |
| | | |
| | | // è¾åºå°æµè§å¨ |
| | | HttpServletResponse response = |
| | | ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())) |
| | | .getResponse(); |
| | | response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document"); |
| | | response.setHeader("Content-Disposition", "attachment;filename="+ StrUtil.format("{}-{}",exportProcessContract.getPartyAClientName(),exportProcessContract.getCreateTime()) +"åå.docx"); |
| | | |
| | | template.write(response.getOutputStream()); |
| | | template.close(); |
| | | response.flushBuffer(); |
| | | } |
| | | |
| | | /** |
| | |
| | | // 4. å¤çåè¡¨æ°æ® |
| | | List<SalesLedgerProduct> productList = salesLedgerDto.getProductData(); |
| | | if (productList != null && !productList.isEmpty()) { |
| | | handleSalesLedgerProducts(salesLedger.getId(), productList, EnumUtil.fromCode(SaleEnum.class,salesLedgerDto.getType())); |
| | | handleSalesLedgerProducts(salesLedger.getId(), productList, EnumUtil.fromCode(SaleEnum.class, salesLedgerDto.getType())); |
| | | updateMainContractAmount( |
| | | salesLedger.getId(), |
| | | productList, |
| | |
| | | throw new BaseException("æä»¶è¿ç§»å¤±è´¥: " + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | // æä»¶è¿ç§»æ¹æ³ |
| | | |
| | | /** |
| | | * å°ä¸´æ¶æä»¶è¿ç§»å°æ£å¼ç®å½ |
| | |
| | | } |
| | | } |
| | | |
| | | // æä»¶è¿ç§»æ¹æ³ |
| | | |
| | | @Override |
| | | public void handleSalesLedgerProducts(Long salesLedgerId, List<SalesLedgerProduct> products, SaleEnum type) { |
| | |
| | | throw new RuntimeException("å¨ææ´æ°ä¸»è¡¨éé¢å¤±è´¥", e); |
| | | } |
| | | } |
| | | |
| | | // å
é¨ç±»ç¨äºåå¨èåç»æ |
| | | private static class GroupedCustomer { |
| | | private final Long customerId; |
| | | private final String customerName; |
| | | private BigDecimal totalAmount = BigDecimal.ZERO; |
| | | |
| | | public GroupedCustomer(Long customerId, String customerName) { |
| | | this.customerId = customerId; |
| | | this.customerName = customerName; |
| | | } |
| | | |
| | | public void addAmount(BigDecimal amount) { |
| | | if (amount != null) { |
| | | this.totalAmount = this.totalAmount.add(amount); |
| | | } |
| | | } |
| | | |
| | | public Long getCustomerId() { |
| | | return customerId; |
| | | } |
| | | |
| | | public String getCustomerName() { |
| | | return customerName; |
| | | } |
| | | |
| | | public BigDecimal getTotalAmount() { |
| | | return totalAmount; |
| | | } |
| | | } |
| | | } |