From cd4ad1e5fe51b6c051fc96f261cc147de813bf05 Mon Sep 17 00:00:00 2001 From: Gauthier LO Date: Mon, 21 Aug 2023 12:45:04 +0200 Subject: [PATCH] feature : Making Shipping invoice in breakdown page + zip files and email --- .../admin/PendingTaskController.java | 177 ++++++++++++++++++ .../shippingInvoice/InvoiceController.java | 114 ++++++++--- .../ShippingInvoiceController.java | 2 +- .../modules/business/entity/PendingTask.java | 67 +++++++ .../business/mapper/PendingTaskMapper.java | 21 +++ .../business/mapper/xml/PendingTaskMapper.xml | 14 ++ .../mapper/xml/PlatformOrderMapper.xml | 2 - .../business/service/IPendingTaskService.java | 15 ++ .../PlatformOrderShippingInvoiceService.java | 87 ++++++++- .../service/impl/PendingTaskServiceImpl.java | 32 ++++ .../modules/business/vo/InvoiceMetaData.java | 2 + .../templates/breakdownInvoiceMail.ftl | 98 ++++++++++ .../src/main/resources/application-dev.yml | 2 +- 13 files changed, 597 insertions(+), 36 deletions(-) create mode 100644 jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/controller/admin/PendingTaskController.java create mode 100644 jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/entity/PendingTask.java create mode 100644 jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/mapper/PendingTaskMapper.java create mode 100644 jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/mapper/xml/PendingTaskMapper.xml create mode 100644 jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/service/IPendingTaskService.java create mode 100644 jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/service/impl/PendingTaskServiceImpl.java create mode 100644 jeecg-module-system/jeecg-system-biz/src/main/resources/templates/breakdownInvoiceMail.ftl diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/controller/admin/PendingTaskController.java b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/controller/admin/PendingTaskController.java new file mode 100644 index 000000000..305402f98 --- /dev/null +++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/controller/admin/PendingTaskController.java @@ -0,0 +1,177 @@ +package org.jeecg.modules.business.controller.admin; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.jeecg.common.api.vo.Result; +import org.jeecg.common.system.query.QueryGenerator; +import org.jeecg.common.util.oConvertUtils; +import org.jeecg.modules.business.entity.PendingTask; +import org.jeecg.modules.business.service.IPendingTaskService; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.extern.slf4j.Slf4j; + +import org.jeecgframework.poi.excel.ExcelImportUtil; +import org.jeecgframework.poi.excel.def.NormalExcelConstants; +import org.jeecgframework.poi.excel.entity.ExportParams; +import org.jeecgframework.poi.excel.entity.ImportParams; +import org.jeecgframework.poi.excel.view.JeecgEntityExcelView; +import org.jeecg.common.system.base.controller.JeecgController; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; +import org.springframework.web.servlet.ModelAndView; +import com.alibaba.fastjson.JSON; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.jeecg.common.aspect.annotation.AutoLog; +import org.apache.shiro.authz.annotation.RequiresPermissions; + + /** + * @Description: to know if a task in launched + * @Author: jeecg-boot + * @Date: 2023-08-17 + * @Version: V1.0 + */ +@Api(tags="pendingTask") +@RestController +@RequestMapping("/pendingTask") +@Slf4j +public class PendingTaskController extends JeecgController { + @Autowired + private IPendingTaskService pendingTaskService; + + /** + * 分页列表查询 + * + * @param pendingTask + * @param pageNo + * @param pageSize + * @param req + * @return + */ + //@AutoLog(value = "to know if a task in launched-分页列表查询") + @ApiOperation(value="to know if a task in launched-分页列表查询", notes="to know if a task in launched-分页列表查询") + @GetMapping(value = "/list") + public Result> queryPageList(PendingTask pendingTask, + @RequestParam(name="pageNo", defaultValue="1") Integer pageNo, + @RequestParam(name="pageSize", defaultValue="10") Integer pageSize, + HttpServletRequest req) { + QueryWrapper queryWrapper = QueryGenerator.initQueryWrapper(pendingTask, req.getParameterMap()); + Page page = new Page(pageNo, pageSize); + IPage pageList = pendingTaskService.page(page, queryWrapper); + return Result.OK(pageList); + } + + /** + * 添加 + * + * @param pendingTask + * @return + */ + @AutoLog(value = "to know if a task in launched-添加") + @ApiOperation(value="to know if a task in launched-添加", notes="to know if a task in launched-添加") + @PostMapping(value = "/add") + public Result add(@RequestBody PendingTask pendingTask) { + pendingTaskService.save(pendingTask); + return Result.OK("添加成功!"); + } + + /** + * 编辑 + * + * @param pendingTask + * @return + */ + @AutoLog(value = "to know if a task in launched-编辑") + @ApiOperation(value="to know if a task in launched-编辑", notes="to know if a task in launched-编辑") + @RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST}) + public Result edit(@RequestBody PendingTask pendingTask) { + pendingTaskService.updateById(pendingTask); + return Result.OK("编辑成功!"); + } + + /** + * 通过id删除 + * + * @param id + * @return + */ + @AutoLog(value = "to know if a task in launched-通过id删除") + @ApiOperation(value="to know if a task in launched-通过id删除", notes="to know if a task in launched-通过id删除") + @DeleteMapping(value = "/delete") + public Result delete(@RequestParam(name="id",required=true) String id) { + pendingTaskService.removeById(id); + return Result.OK("删除成功!"); + } + + /** + * 批量删除 + * + * @param ids + * @return + */ + @AutoLog(value = "to know if a task in launched-批量删除") + @ApiOperation(value="to know if a task in launched-批量删除", notes="to know if a task in launched-批量删除") + @DeleteMapping(value = "/deleteBatch") + public Result deleteBatch(@RequestParam(name="ids",required=true) String ids) { + this.pendingTaskService.removeByIds(Arrays.asList(ids.split(","))); + return Result.OK("批量删除成功!"); + } + + /** + * 通过id查询 + * + * @param id + * @return + */ + //@AutoLog(value = "to know if a task in launched-通过id查询") + @ApiOperation(value="to know if a task in launched-通过id查询", notes="to know if a task in launched-通过id查询") + @GetMapping(value = "/queryById") + public Result queryById(@RequestParam(name="id",required=true) String id) { + PendingTask pendingTask = pendingTaskService.getById(id); + if(pendingTask==null) { + return Result.error("未找到对应数据"); + } + return Result.OK(pendingTask); + } + + /** + * 导出excel + * + * @param request + * @param pendingTask + */ + @RequestMapping(value = "/exportXls") + public ModelAndView exportXls(HttpServletRequest request, PendingTask pendingTask) { + return super.exportXls(request, pendingTask, PendingTask.class, "to know if a task in launched"); + } + + /** + * 通过excel导入数据 + * + * @param request + * @param response + * @return + */ + @RequestMapping(value = "/importExcel", method = RequestMethod.POST) + public Result importExcel(HttpServletRequest request, HttpServletResponse response) { + return super.importExcel(request, response, PendingTask.class); + } + + @PostMapping(value = "/reset") + public Result resetTask(@RequestBody String taskCode) { + pendingTaskService.setStatus(0, "BI"); + return Result.ok("Reset successful !"); + } +} diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/controller/admin/shippingInvoice/InvoiceController.java b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/controller/admin/shippingInvoice/InvoiceController.java index d1408652a..e8bf07e10 100644 --- a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/controller/admin/shippingInvoice/InvoiceController.java +++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/controller/admin/shippingInvoice/InvoiceController.java @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.alibaba.fastjson.JSONObject; +import freemarker.template.Template; import io.swagger.annotations.Api; import lombok.extern.slf4j.Slf4j; import org.apache.shiro.SecurityUtils; @@ -21,17 +22,28 @@ import org.jeecg.modules.business.vo.*; import org.jeecg.modules.quartz.entity.QuartzJob; import org.jeecg.modules.quartz.service.IQuartzJobService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.env.Environment; +import org.springframework.ui.freemarker.FreeMarkerTemplateUtils; import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer; +import javax.mail.Authenticator; +import javax.mail.PasswordAuthentication; +import javax.mail.Session; import javax.servlet.http.HttpServletRequest; -import java.io.IOException; +import java.io.*; import java.math.BigDecimal; import java.math.RoundingMode; +import java.nio.file.Path; +import java.nio.file.Paths; import java.text.ParseException; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; /** * Controller for request related to shipping invoice @@ -61,6 +73,22 @@ public class InvoiceController { private IExchangeRatesService iExchangeRatesService; @Autowired private IQuartzJobService quartzJobService; + @Autowired + private IPendingTaskService pendingTaskService; + @Autowired + private FreeMarkerConfigurer freemarkerConfigurer; + @Autowired + private EmailService emailService; + + @Value("${jeecg.path.shippingInvoiceDir}") + private String INVOICE_DIR; + + @Value("${jeecg.path.shippingInvoiceDetailDir}") + private String INVOICE_DETAIL_DIR; + + @Autowired + Environment env; + @GetMapping(value = "/shopsByClient") public Result> getShopsByClient(@RequestParam("clientID") String clientID) { @@ -424,40 +452,72 @@ public class InvoiceController { /** * Invoices all available orders with status 3 for a list of client - * @param clientCodes list of clients to invoice - * @param invoiceType invoice type (shipping or complete) + * @param shippingClientIds list of clients to invoice shipping fees + * @param completeClientIds list of clients to invoice complete fees * @return list of invoice infos */ @GetMapping(value = "/breakdown/makeInvoice") - public Result makeBreakdownInvoice(@RequestParam(value = "codes[]") List clientCodes, @RequestParam("invoiceType") int invoiceType) { - Map> clientShopIDsMap = new HashMap<>(); + public Result makeBreakdownInvoice(@RequestParam(value = "shipping[]", required = false) List shippingClientIds, + @RequestParam(value = "complete[]", required = false) List completeClientIds) throws IOException { + List metaDataErrorList = new ArrayList<>(); + if(pendingTaskService.getStatus("BI").equals("1")) { + return Result.error("Task is already running, please retry in a moment !"); + } List invoiceList = new ArrayList<>(); - for(String id: clientCodes) { - clientShopIDsMap.put(id, shopService.listIdByClient(id)); + pendingTaskService.setStatus(1, "BI"); + if(shippingClientIds != null) { + log.info("Making shipping invoice for clients : {}", shippingClientIds); + invoiceList.addAll(shippingInvoiceService.breakdownInvoiceClientByType(shippingClientIds, 0)); } - for(Map.Entry> entry: clientShopIDsMap.entrySet()) { - Period period = shippingInvoiceService.getValidPeriod(entry.getValue()); - Calendar calendar = Calendar.getInstance(); - calendar.setTime(period.start()); - String start = calendar.get(Calendar.YEAR) + "-" + (calendar.get(Calendar.MONTH)+1 < 10 ? "0" : "") + (calendar.get(Calendar.MONTH)+1) + "-" + (calendar.get(Calendar.DAY_OF_MONTH) < 10 ? "0" : "") + (calendar.get(Calendar.DAY_OF_MONTH)); - calendar.setTime(period.end()); - String end = calendar.get(Calendar.YEAR) + "-" + (calendar.get(Calendar.MONTH)+1 < 10 ? "0" : "") + (calendar.get(Calendar.MONTH)+1) + "-" + (calendar.get(Calendar.DAY_OF_MONTH)+1 < 10 ? "0" : "") + (calendar.get(Calendar.DAY_OF_MONTH)+1); - System.out.println( "[" + start + "] --- [" + end + "]"); - try { - ShippingInvoiceParam param = new ShippingInvoiceParam(entry.getKey(), entry.getValue(), start, end, Collections.singletonList(3), Arrays.asList("0", "1")); - InvoiceMetaData metaData; - if(invoiceType == 0) - metaData = shippingInvoiceService.makeInvoice(param); - else - metaData = shippingInvoiceService.makeCompleteInvoicePostShipping(param, "post"); - invoiceList.add(metaData); - } catch (UserException | IOException | ParseException e) { - log.error(e.getMessage()); + if(completeClientIds != null) { + log.info("Making complete shipping invoice for clients : {}", completeClientIds); + invoiceList.addAll(shippingInvoiceService.breakdownInvoiceClientByType(completeClientIds, 1)); + } + if(!invoiceList.isEmpty()) { + List filenameList = new ArrayList<>(); + for(InvoiceMetaData metaData: invoiceList){ + if(metaData.getInvoiceCode().equals("error")) { + metaDataErrorList.add(metaData); + } + else { + filenameList.add(INVOICE_DIR + "//" + metaData.getFilename()); + List factureDetails = shippingInvoiceService.getInvoiceDetail(metaData.getInvoiceCode()); + List refunds = savRefundWithDetailService.getRefundsByInvoiceNumber(metaData.getInvoiceCode()); + shippingInvoiceService.exportToExcel(factureDetails, refunds, metaData.getInvoiceCode(), metaData.getInvoiceEntity()); + filenameList.add(INVOICE_DETAIL_DIR + "//Détail_calcul_de_facture_" + metaData.getInvoiceCode() + "_(" + metaData.getInvoiceEntity() + ").xlsx"); + } + } + String zipFilename = shippingInvoiceService.zipInvoices(filenameList); + String subject = "Invoices generated from Breakdown Page"; + String destEmail = env.getProperty("spring.mail.username"); + Properties prop = emailService.getMailSender(); + Map templateModel = new HashMap<>(); + templateModel.put("errors", metaDataErrorList); + + Session session = Session.getInstance(prop, new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(env.getProperty("spring.mail.username"), env.getProperty("spring.mail.password")); + } + }); + try { + freemarkerConfigurer = emailService.freemarkerClassLoaderConfig(); + Template freemarkerTemplate = freemarkerConfigurer.getConfiguration() + .getTemplate("breakdownInvoiceMail.ftl"); + String htmlBody = FreeMarkerTemplateUtils.processTemplateIntoString(freemarkerTemplate, templateModel); + emailService.sendMessageWithAttachment(destEmail, subject, htmlBody, zipFilename,session); + log.info("Mail sent successfully"); + return Result.OK("component.email.emailSent"); + } + catch(Exception e) { + e.printStackTrace(); + return Result.error("An error occurred while trying to send an email."); } - System.gc(); } - return Result.ok(invoiceList); + pendingTaskService.setStatus(0, "BI"); + return Result.ok(); } + /** * Get an estimate of shipping fees for selected orders * @param param Parameters for creating a pre-shipping invoice diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/controller/admin/shippingInvoice/ShippingInvoiceController.java b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/controller/admin/shippingInvoice/ShippingInvoiceController.java index 591bac0ce..64fe943c5 100644 --- a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/controller/admin/shippingInvoice/ShippingInvoiceController.java +++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/controller/admin/shippingInvoice/ShippingInvoiceController.java @@ -478,7 +478,7 @@ public class ShippingInvoiceController { return Result.OK("component.email.emailSent"); } catch(Exception e) { - return Result.error("An error occured while trying to send an email."); + return Result.error("An error occurred while trying to send an email."); } } diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/entity/PendingTask.java b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/entity/PendingTask.java new file mode 100644 index 000000000..70c275379 --- /dev/null +++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/entity/PendingTask.java @@ -0,0 +1,67 @@ +package org.jeecg.modules.business.entity; + +import java.io.Serializable; +import java.io.UnsupportedEncodingException; +import java.util.Date; +import java.math.BigDecimal; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.TableLogic; +import lombok.Data; +import com.fasterxml.jackson.annotation.JsonFormat; +import org.springframework.format.annotation.DateTimeFormat; +import org.jeecgframework.poi.excel.annotation.Excel; +import org.jeecg.common.aspect.annotation.Dict; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + * @Description: to know if a task in launched + * @Author: jeecg-boot + * @Date: 2023-08-17 + * @Version: V1.0 + */ +@Data +@TableName("pending_task") +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = false) +@ApiModel(value="pending_task对象", description="to know if a task in launched") +public class PendingTask implements Serializable { + private static final long serialVersionUID = 1L; + + /**主键*/ + @TableId(type = IdType.ASSIGN_ID) + @ApiModelProperty(value = "主键") + private java.lang.String id; + /**创建人*/ + @ApiModelProperty(value = "创建人") + private java.lang.String createBy; + /**创建日期*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "创建日期") + private java.util.Date createTime; + /**更新人*/ + @ApiModelProperty(value = "更新人") + private java.lang.String updateBy; + /**更新日期*/ + @JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") + @ApiModelProperty(value = "更新日期") + private java.util.Date updateTime; + /**task name*/ + @Excel(name = "task name", width = 15) + @ApiModelProperty(value = "task name") + private java.lang.String name; + /**description*/ + @Excel(name = "description", width = 15) + @ApiModelProperty(value = "description") + private java.lang.String description; + /**task status*/ + @Excel(name = "task status", width = 15) + @ApiModelProperty(value = "task status") + private java.lang.String onGoing; +} diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/mapper/PendingTaskMapper.java b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/mapper/PendingTaskMapper.java new file mode 100644 index 000000000..e3c649917 --- /dev/null +++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/mapper/PendingTaskMapper.java @@ -0,0 +1,21 @@ +package org.jeecg.modules.business.mapper; + +import java.util.List; + +import org.apache.ibatis.annotations.Param; +import org.jeecg.modules.business.entity.PendingTask; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.springframework.stereotype.Repository; + +/** + * @Description: to know if a task in launched + * @Author: jeecg-boot + * @Date: 2023-08-17 + * @Version: V1.0 + */ + +@Repository +public interface PendingTaskMapper extends BaseMapper { + void setStatus(@Param("status") int status, @Param("code") String taskCode); + String getStatus(@Param("code") String taskCode); +} diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/mapper/xml/PendingTaskMapper.xml b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/mapper/xml/PendingTaskMapper.xml new file mode 100644 index 000000000..90ad2c091 --- /dev/null +++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/mapper/xml/PendingTaskMapper.xml @@ -0,0 +1,14 @@ + + + + + UPDATE pending_task + SET on_going = #{status} + WHERE code = #{code}; + + + \ No newline at end of file diff --git a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/mapper/xml/PlatformOrderMapper.xml b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/mapper/xml/PlatformOrderMapper.xml index 50a8e46be..eaebeed64 100644 --- a/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/mapper/xml/PlatformOrderMapper.xml +++ b/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/business/mapper/xml/PlatformOrderMapper.xml @@ -486,7 +486,6 @@ #{warehouse} AND po.shipping_time between #{startDate} AND #{endDate} - AND po.shipping_invoice_number IS NULL AND po.erp_status = 3;