feature : feature : Self-service invoicing rework + Purchase Order Registration Page + ShippingFeeBillableNotificationJob

pull/6221/head
Gauthier LO 2024-01-04 15:57:15 +01:00
parent b2a8e88559
commit 67cb86e25b
34 changed files with 946 additions and 223 deletions

View File

@ -8,20 +8,15 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.business.controller.UserException;
import org.jeecg.modules.business.domain.purchase.invoice.InvoiceData;
import org.jeecg.modules.business.entity.*;
import org.jeecg.modules.business.service.*;
import org.jeecg.modules.business.vo.InventoryImport;
import org.jeecg.modules.business.vo.PromotionCouple;
import org.jeecg.modules.business.vo.PurchaseOrderPage;
import org.jeecg.modules.business.vo.SkuQuantity;
import org.jeecg.modules.business.vo.*;
import org.jeecg.modules.business.vo.clientPlatformOrder.PurchaseConfirmation;
import org.jeecg.modules.business.vo.clientPlatformOrder.section.ClientInfo;
import org.jeecgframework.poi.excel.ExcelImportUtil;
@ -55,27 +50,22 @@ import java.util.stream.Collectors;
@RequestMapping("/purchaseOrder")
@Slf4j
public class PurchaseOrderController {
private final IPurchaseOrderService purchaseOrderService;
private final IPurchaseOrderSkuService purchaseOrderSkuService;
private final ISkuPromotionHistoryService skuPromotionHistoryService;
private final ISkuService skuService;
private final IImportedInventoryService importedInventoryService;
private final IClientService clientService;
private final IPlatformOrderService platformOrderService;
@Autowired
public PurchaseOrderController(IPurchaseOrderService purchaseOrderService,
IPurchaseOrderSkuService purchaseOrderSkuService,
ISkuPromotionHistoryService skuPromotionHistoryService, ISkuService skuService,
IImportedInventoryService importedInventoryService, IClientService clientService, IPlatformOrderService platformOrderService) {
this.purchaseOrderService = purchaseOrderService;
this.purchaseOrderSkuService = purchaseOrderSkuService;
this.skuPromotionHistoryService = skuPromotionHistoryService;
this.skuService = skuService;
this.importedInventoryService = importedInventoryService;
this.clientService = clientService;
this.platformOrderService = platformOrderService;
}
private IPurchaseOrderService purchaseOrderService;
@Autowired
private IPurchaseOrderSkuService purchaseOrderSkuService;
@Autowired
private ISkuPromotionHistoryService skuPromotionHistoryService;
@Autowired
private ISkuService skuService;
@Autowired
private IImportedInventoryService importedInventoryService;
@Autowired
private IClientService clientService;
@Autowired
private IPlatformOrderService platformOrderService;
@Autowired
private IShippingInvoiceService shippingInvoiceService;
/**
* Page query for purchase order
@ -121,12 +111,21 @@ public class PurchaseOrderController {
@AutoLog(value = "商品采购订单-添加")
@ApiOperation(value="商品采购订单-添加", notes="商品采购订单-添加")
@PostMapping(value = "/addPurchaseAndOrder")
public Result<?> addPurchaseAndOrder(@RequestBody PurchaseOrderPage purchaseOrderPage) {
public Result<?> addPurchaseAndOrder( @RequestBody PurchaseOrderPage purchaseOrderPage) {
PurchaseOrder purchaseOrder = new PurchaseOrder();
BeanUtils.copyProperties(purchaseOrderPage, purchaseOrder);
List<String> platformOrderIds = new ArrayList<>(Arrays.asList(purchaseOrderPage.getPlatformOrderId().split(",")));
purchaseOrder.setPaymentDocumentString(new String(purchaseOrderPage.getPaymentDocument()));
purchaseOrder.setInventoryDocumentString(new String(purchaseOrderPage.getInventoryDocument()));
String purchaseID = UUID.randomUUID().toString();
purchaseOrder.setId(purchaseID);
purchaseOrderService.save(purchaseOrder);
if(purchaseOrderPage.getPlatformOrderId() == null) {
return Result.OK("sys.api.entryAddSuccess");
}
List<String> platformOrderIds = Arrays.stream(purchaseOrderPage.getPlatformOrderId().split(","))
.map(String::trim)
.collect(Collectors.toList());
log.info("Creating new purchase order and attributing it to orders: {}", platformOrderIds);
// test 5757661446491 & 5757658267995 poId
List<PlatformOrder> platformOrders = platformOrderService.selectByPlatformOrderIds(platformOrderIds);
Map<String, List<String>> platformOrderIdUpdateMap = new HashMap<>();
if(!platformOrders.isEmpty()) {
@ -145,8 +144,6 @@ public class PurchaseOrderController {
log.error("Platform orders not found: {}", platformOrderIds);
platformOrderIdUpdateMap.put("fail", platformOrderIds);
}
purchaseOrderService.save(purchaseOrder);
return Result.OK("sys.api.entryAddSuccess", platformOrderIdUpdateMap);
}
// /**
@ -187,17 +184,23 @@ public class PurchaseOrderController {
* @param purchaseOrderPage
* @return
*/
@Transactional
@AutoLog(value = "purchase_order-编辑")
@ApiOperation(value="purchase_order-编辑", notes="purchase_order-编辑")
@RequestMapping(value = "/editPurchaseAndOrder", method = {RequestMethod.PUT,RequestMethod.POST})
public Result<?> editPurchaseAndOrder(@RequestBody PurchaseOrderPage purchaseOrderPage) {
PurchaseOrder purchaseOrder = new PurchaseOrder();
BeanUtils.copyProperties(purchaseOrderPage, purchaseOrder);
purchaseOrder.setPaymentDocumentString(new String(purchaseOrderPage.getPaymentDocument()));
purchaseOrder.setInventoryDocumentString(new String(purchaseOrderPage.getInventoryDocument()));
if(purchaseOrderPage.getPlatformOrderId() == null) {
purchaseOrderService.updateById(purchaseOrder);
return Result.OK("sys.api.entryEditSuccess");
}
List<String> platformOrderIds = new ArrayList<>(Arrays.asList(purchaseOrderPage.getPlatformOrderId().split(",")));
log.info("Editing purchase order and attributing it to orders : {}", platformOrderIds);
log.info("Removing previous attribution to orders");
platformOrderService.removePurchaseInvoiceNumber(purchaseOrder.getInvoiceNumber());
// test 5757661446491 & 5757658267995 poId
List<PlatformOrder> platformOrders = platformOrderService.selectByPlatformOrderIds(platformOrderIds);
log.info("Platform orders found for attribution : {}", platformOrders.stream().map(PlatformOrder::getPlatformOrderId).collect(Collectors.toList()));
Map<String, List<String>> platformOrderIdUpdateMap = new HashMap<>();
@ -216,7 +219,6 @@ public class PurchaseOrderController {
log.error("Platform orders not found: {}", platformOrderIds);
platformOrderIdUpdateMap.put("fail", platformOrderIds);
}
purchaseOrderService.updateById(purchaseOrder);
return Result.OK("sys.api.entryEditSuccess", platformOrderIdUpdateMap);
}
@ -231,6 +233,11 @@ public class PurchaseOrderController {
@ApiOperation(value = "商品采购订单-通过id删除", notes = "商品采购订单-通过id删除")
@DeleteMapping(value = "/delete")
public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
PurchaseOrder po = purchaseOrderService.getById(id);
if(po.getInventoryDocumentString() != null && !po.getInventoryDocumentString().isEmpty())
shippingInvoiceService.deleteAttachmentFile(po.getInventoryDocumentString());
if(po.getPaymentDocumentString() != null && !po.getPaymentDocumentString().isEmpty())
shippingInvoiceService.deleteAttachmentFile(po.getPaymentDocumentString());
purchaseOrderService.delMain(id);
return Result.OK("sys.api.entryDeleteSuccess");
}
@ -245,10 +252,56 @@ public class PurchaseOrderController {
@ApiOperation(value = "商品采购订单-批量删除", notes = "商品采购订单-批量删除")
@DeleteMapping(value = "/deleteBatch")
public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
List<PurchaseOrder> purchaseOrders = purchaseOrderService.listByIds(Arrays.asList(ids.split(",")));
for(PurchaseOrder po : purchaseOrders) {
if(po.getInventoryDocumentString() != null && !po.getInventoryDocumentString().isEmpty())
shippingInvoiceService.deleteAttachmentFile(po.getInventoryDocumentString());
if(po.getPaymentDocumentString() != null && !po.getPaymentDocumentString().isEmpty())
shippingInvoiceService.deleteAttachmentFile(po.getPaymentDocumentString());
}
this.purchaseOrderService.delBatchMain(Arrays.asList(ids.split(",")));
return Result.OK("sys.api.entryBatchDeleteSuccess");
}
/**
* Cancel a purchase order's invoice.
* @param purchaseId purchase ID
* @param invoiceNumber invoice number
* @return
*/
@AutoLog(value = "商品采购订单-通过id删除")
@ApiOperation(value = "商品采购订单-通过id删除", notes = "商品采购订单-通过id删除")
@DeleteMapping(value = "/cancelInvoice")
public Result<?> cancelInvoice(@RequestParam("id") String purchaseId,
@RequestParam("invoiceNumber") String invoiceNumber) {
PurchaseOrder po = purchaseOrderService.getById(purchaseId);
if(po.getInventoryDocumentString() != null && !po.getInventoryDocumentString().isEmpty())
shippingInvoiceService.deleteAttachmentFile(po.getInventoryDocumentString());
if(po.getPaymentDocumentString() != null && !po.getPaymentDocumentString().isEmpty())
shippingInvoiceService.deleteAttachmentFile(po.getPaymentDocumentString());
purchaseOrderService.cancelInvoice(purchaseId, invoiceNumber);
return Result.OK("sys.api.entryDeleteSuccess");
}
/**
* Cancel multiple purchase order's invoice.
* @param purchaseIds list of purchase IDs
* @return
*/
@AutoLog(value = "商品采购订单-批量删除")
@ApiOperation(value = "商品采购订单-批量删除", notes = "商品采购订单-批量删除")
@DeleteMapping(value = "/cancelBatchInvoice")
public Result<?> cancelBatchInvoice(@RequestParam("ids") String purchaseIds) {
List<PurchaseOrder> purchaseOrders = purchaseOrderService.listByIds(Arrays.asList(purchaseIds.split(",")));
for(PurchaseOrder po : purchaseOrders) {
if(po.getInventoryDocumentString() != null && !po.getInventoryDocumentString().isEmpty())
shippingInvoiceService.deleteAttachmentFile(po.getInventoryDocumentString());
if(po.getPaymentDocumentString() != null && !po.getPaymentDocumentString().isEmpty())
shippingInvoiceService.deleteAttachmentFile(po.getPaymentDocumentString());
}
purchaseOrderService.cancelBatchInvoice(purchaseIds);
return Result.OK("sys.api.entryDeleteSuccess");
}
/**
* id
*
@ -447,7 +500,7 @@ public class PurchaseOrderController {
* @param purchaseID purchaseID
*/
@RequestMapping(value = "/invoiceMeta", method = RequestMethod.GET)
public InvoiceData getInvoiceMetaData(@RequestParam String purchaseID, HttpServletResponse response) throws IOException, URISyntaxException {
public InvoiceMetaData getInvoiceMetaData(@RequestParam String purchaseID, HttpServletResponse response) throws IOException, URISyntaxException {
return purchaseOrderService.makeInvoice(purchaseID);
}

View File

@ -35,10 +35,6 @@ public class UserClientController {
public Result<?> getClientByUserId() {
LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
String userId = loginUser.getId();
// userId = "1708866308713140225"; //EP
// userId = "1724445090933100545"; //ND
// userId = "1730541854207422465"; // OV
userId = "1731689285213171713"; // JW
Client client = userClientService.getClientMinInfoByUserId(userId);
if(client == null) {
List<SysRole> sysRoles = sysUserRoleService.getUserRole(userId);

View File

@ -1,12 +1,12 @@
package org.jeecg.modules.business.controller.admin.shippingInvoice;
import cn.hutool.core.date.DateTime;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
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 freemarker.template.TemplateException;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.MutableTriple;
@ -18,11 +18,12 @@ import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.modules.business.controller.UserException;
import org.jeecg.modules.business.domain.api.mabang.getorderlist.OrderStatus;
import org.jeecg.modules.business.domain.purchase.invoice.InvoiceData;
import org.jeecg.modules.business.domain.purchase.invoice.PurchaseInvoiceEntry;
import org.jeecg.modules.business.entity.*;
import org.jeecg.modules.business.mapper.ExchangeRatesMapper;
import org.jeecg.modules.business.mapper.PlatformOrderContentMapper;
import org.jeecg.modules.business.mapper.PlatformOrderMapper;
import org.jeecg.modules.business.mapper.PurchaseOrderContentMapper;
import org.jeecg.modules.business.service.*;
import org.jeecg.modules.business.vo.*;
import org.jeecg.modules.quartz.entity.QuartzJob;
@ -44,6 +45,7 @@ import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.StandardSocketOptions;
import java.net.URISyntaxException;
import java.text.ParseException;
import java.time.LocalDate;
@ -90,6 +92,8 @@ public class InvoiceController {
@Autowired
private IPurchaseOrderService purchaseOrderService;
@Autowired
private PurchaseOrderContentMapper purchaseOrderContentMapper;
@Autowired
private IShippingInvoiceService iShippingInvoiceService;
@Autowired
private ISavRefundService iSavRefundService;
@ -280,17 +284,40 @@ public class InvoiceController {
if(clientCategory.equals(ClientCategory.CategoryName.CONFIRMED.getName()) || clientCategory.equals(ClientCategory.CategoryName.VIP.getName())) {
balanceService.updateBalance(param.clientID(), metaData.getInvoiceCode(), "shipping");
}
if(clientCategory.equals(ClientCategory.CategoryName.SELF_SERVICE.getName())) {
String subject = "Self-service shipping invoice";
String destEmail = env.getProperty("spring.mail.username");
Properties prop = emailService.getMailSender();
Map<String, Object> templateModel = new HashMap<>();
templateModel.put("invoiceType", "shipping invoice");
templateModel.put("invoiceEntity", clientService.getById(param.clientID()).getInternalCode());
templateModel.put("invoiceNumber", metaData.getInvoiceCode());
Session session = Session.getInstance(prop, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(env.getProperty("spring.mail.username"), env.getProperty("spring.mail.password"));
}
});
freemarkerConfigurer = emailService.freemarkerClassLoaderConfig();
Template template = freemarkerConfigurer.getConfiguration().getTemplate("admin/invoiceNotification.ftl");
String htmlBody = FreeMarkerTemplateUtils.processTemplateIntoString(template, templateModel);
emailService.sendSimpleMessage(destEmail, subject, htmlBody, session);
log.info("Mail sent successfully");
}
return Result.OK(metaData);
} catch (UserException e) {
return Result.error(e.getMessage());
} catch (IOException | ParseException e) {
log.error(e.getMessage());
return Result.error("Sorry, server error, please try later");
} catch (TemplateException | MessagingException e) {
throw new RuntimeException(e);
}
}
/**
* Make invoice for specified orders and type
*
* Make purchase invoice for specified orders and type
* used by self-service clients
* @param param Parameters for creating an invoice
* @return Result of the generation, in case of error, message will be contained,
* in case of success, data will contain filename.
@ -298,26 +325,45 @@ public class InvoiceController {
@Transactional
@PostMapping(value = "/makeManualPurchaseInvoice")
public Result<?> makeManualPurchaseInvoice(@RequestBody ShippingInvoiceOrderParam param) {
InvoiceMetaData metaData;
try {
// todo : au final on facture les sku directement sans checker s'il y en aura trop
String currency = clientService.getById(param.clientID()).getCurrency();
List<PlatformOrderContent> orderContents = platformOrderContentMap.fetchOrderContent(param.orderIds());
List<String> skuIds = orderContents.stream().map(PlatformOrderContent::getSkuId).collect(Collectors.toList());
List<SkuQuantity> skuQuantities = skuService.getSkuQuantitiesFromOrderIds(param.orderIds());
String purchaseId = purchaseOrderService.addPurchase(skuQuantities ,param.orderIds());
metaData = purchaseOrderService.makeInvoice(purchaseId);
platformOrderService.updatePurchaseInvoiceNumber(param.orderIds(), metaData.getInvoiceCode());
String clientCategory = clientCategoryService.getClientCategoryByClientId(param.clientID());
InvoiceData metaData = purchaseOrderService.makeInvoice(purchaseId);
if(clientCategory.equals(ClientCategory.CategoryName.CONFIRMED.getName()) || clientCategory.equals(ClientCategory.CategoryName.VIP.getName())) {
balanceService.updateBalance(param.clientID(), metaData.getCode(), "shipping");
// if(clientCategory.equals(ClientCategory.CategoryName.CONFIRMED.getName()) || clientCategory.equals(ClientCategory.CategoryName.VIP.getName())) {
// balanceService.updateBalance(param.clientID(), metaData.getCode(), "purchase");
// }
if(clientCategory.equals(ClientCategory.CategoryName.SELF_SERVICE.getName())) {
String subject = "Self-service purchase invoice";
String destEmail = env.getProperty("spring.mail.username");
Properties prop = emailService.getMailSender();
Map<String, Object> templateModel = new HashMap<>();
templateModel.put("invoiceType", "purchase invoice");
templateModel.put("invoiceEntity", clientService.getById(param.clientID()).getInternalCode());
templateModel.put("invoiceNumber", metaData.getInvoiceCode());
Session session = Session.getInstance(prop, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(env.getProperty("spring.mail.username"), env.getProperty("spring.mail.password"));
}
});
freemarkerConfigurer = emailService.freemarkerClassLoaderConfig();
Template template = freemarkerConfigurer.getConfiguration().getTemplate("admin/invoiceNotification.ftl");
String htmlBody = FreeMarkerTemplateUtils.processTemplateIntoString(template, templateModel);
emailService.sendSimpleMessage(destEmail, subject, htmlBody, session);
log.info("Mail sent successfully");
}
return Result.OK();
return Result.OK(metaData);
} catch (UserException e) {
return Result.error(e.getMessage());
} catch (IOException e) {
log.error(e.getMessage());
return Result.error("Sorry, server error, please try later");
} catch (URISyntaxException e) {
} catch (URISyntaxException | MessagingException | TemplateException e) {
throw new RuntimeException(e);
}
}
@ -337,7 +383,28 @@ public class InvoiceController {
InvoiceMetaData metaData = shippingInvoiceService.makeCompleteInvoice(param);
String clientCategory = clientCategoryService.getClientCategoryByClientId(param.clientID());
if(clientCategory.equals(ClientCategory.CategoryName.CONFIRMED.getName()) || clientCategory.equals(ClientCategory.CategoryName.VIP.getName())) {
balanceService.updateBalance(param.clientID(), metaData.getInvoiceCode(), "complete");
balanceService.updateBalance(param.clientID(), metaData.getInvoiceCode(), "complete");
}
if(clientCategory.equals(ClientCategory.CategoryName.SELF_SERVICE.getName())) {
String subject = "Self-service complete invoice";
String destEmail = env.getProperty("spring.mail.username");
Properties prop = emailService.getMailSender();
Map<String, Object> templateModel = new HashMap<>();
templateModel.put("invoiceType", "complete invoice");
templateModel.put("invoiceEntity", clientService.getById(param.clientID()).getInternalCode());
templateModel.put("invoiceNumber", metaData.getInvoiceCode());
Session session = Session.getInstance(prop, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(env.getProperty("spring.mail.username"), env.getProperty("spring.mail.password"));
}
});
freemarkerConfigurer = emailService.freemarkerClassLoaderConfig();
Template template = freemarkerConfigurer.getConfiguration().getTemplate("admin/invoiceNotification.ftl");
String htmlBody = FreeMarkerTemplateUtils.processTemplateIntoString(template, templateModel);
emailService.sendSimpleMessage(destEmail, subject, htmlBody, session);
log.info("Mail sent successfully");
}
return Result.OK(metaData);
} catch (UserException e) {
@ -345,7 +412,7 @@ public class InvoiceController {
} catch (IOException | ParseException e) {
log.error(e.getMessage());
return Result.error("Sorry, server error, please try later");
} catch (MessagingException e) {
} catch (MessagingException | TemplateException e) {
throw new RuntimeException(e);
}
}
@ -356,7 +423,6 @@ public class InvoiceController {
" and erpStatuses : " + erpStatuses.toString());
Period period = shippingInvoiceService.getValidOrderTimePeriod(shopIDs, erpStatuses);
if (period.isValid()) {
System.out.println("start : " + period.start() + "; end : " + period.end());
return Result.OK(period);
}
return Result.error("No package in the selected period");
@ -489,7 +555,8 @@ public class InvoiceController {
errorMessages.add(orderAndStatus.getRight());
}
}
// sorting by order time ascending
finalOrderAndStatus = finalOrderAndStatus.stream().sorted(Comparator.comparing(o -> o.getLeft().getOrderTime())).collect(Collectors.toList());
// system notification
String errors = SECTION_START;
int max_entries = 100;
@ -508,7 +575,7 @@ public class InvoiceController {
templateParam.put("errors", errors);
templateParam.put("current_page", String.valueOf(current_page));
templateParam.put("total_page", String.valueOf(total_page));
TemplateMessageDTO message = new TemplateMessageDTO("admin", "Gauthier", "Self Service invoicing estimation Errors", templateParam, "expenses_overview_errors");
TemplateMessageDTO message = new TemplateMessageDTO("admin", "admin", "Self Service invoicing estimation Errors", templateParam, "expenses_overview_errors");
ISysBaseApi.sendTemplateAnnouncement(message);
}
}
@ -554,10 +621,11 @@ public class InvoiceController {
* @return byte array, in case of error, an empty array will be returned.
*/
@GetMapping(value = "/download")
public byte[] downloadInvoice(@RequestParam("filename") String filename) {
public byte[] downloadInvoice(@RequestParam("filename") String filename, @RequestParam(value = "type", required = false) String type) {
log.info("request for downloading shipping invoice");
String invoiceType = type == null ? "shipping" : type;
try {
return shippingInvoiceService.getInvoiceBinary(filename);
return shippingInvoiceService.getInvoiceBinary(filename, invoiceType);
} catch (IOException e) {
log.error(e.getMessage());
return new byte[0];
@ -761,22 +829,9 @@ public class InvoiceController {
public Result<?> getPurchaseFeesEstimateByOrders(@RequestBody ShippingInvoiceOrderParam param) {
String currency = clientService.getById(param.clientID()).getCurrency();
List<PlatformOrder> orders = platformOrderMapper.fetchByIds(param.orderIds());
Map<String, List<PlatformOrder>> orderIdsMapByShop = new HashMap<>();
for(PlatformOrder order : orders) {
String shopId = order.getShopId();
System.out.println("Adding order " + order.getId() + " to shop " + shopId);
if(orderIdsMapByShop.containsKey(shopId)) {
System.out.println(orderIdsMapByShop.get(shopId));
orderIdsMapByShop.get(shopId).add(order);
}
else {
List<PlatformOrder> orderIds = new ArrayList<>();
orderIds.add(order);
orderIdsMapByShop.put(shopId, orderIds);
}
}
Map<String, List<PlatformOrder>> ordersMapByShop = orders.stream().collect(Collectors.groupingBy(PlatformOrder::getShopId));
Map<String, Estimation> estimationsByShop = new HashMap<>();
for(Map.Entry<String, List<PlatformOrder>> entry : orderIdsMapByShop.entrySet()) {
for(Map.Entry<String, List<PlatformOrder>> entry : ordersMapByShop.entrySet()) {
String shopId = entry.getKey();
List<String> orderIds = entry.getValue().stream().map(PlatformOrder::getId).collect(Collectors.toList());
ShippingInvoiceOrderParam finalParam = new ShippingInvoiceOrderParam(param.clientID(), orderIds, param.getType());
@ -787,8 +842,13 @@ public class InvoiceController {
return Result.OK("No estimation found.");
// purchase estimation
// only calculate purchase estimation if products are not available, else it's already been paid
List<String> orderIdsWithProductUnavailable = entry.getValue().stream().filter(order -> order.getProductAvailable().equals("0")).map(PlatformOrder::getId).collect(Collectors.toList());
// only calculate purchase estimation if products are not available and purchaseInvoiceNumber is null, else it's already been paid
List<String> orderIdsWithProductUnavailable = entry.getValue().stream()
.filter(
order -> order.getProductAvailable().equals("0")
&& order.getPurchaseInvoiceNumber() == null
&& order.getVirtualProductAvailable().equals("0"))
.map(PlatformOrder::getId).collect(Collectors.toList());
BigDecimal shippingFeesEstimation = BigDecimal.ZERO;
BigDecimal purchaseEstimation = BigDecimal.ZERO;
boolean isCompleteInvoiceReady = true;
@ -829,21 +889,33 @@ public class InvoiceController {
}
@GetMapping(value = "/checkInvoiceValidity")
public Result<?> checkInvoiceValidity(@RequestParam("invoiceNumber") String invoiceNumber, @RequestParam("email") String email, @RequestParam("orgCode") String orgCode) {
public Result<?> checkInvoiceValidity(@RequestParam("invoiceNumber") String invoiceNumber) {
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
String orgCode = sysUser.getOrgCode();
String email = sysUser.getEmail();
String invoiceID;
String customerFullName;
invoiceID = iShippingInvoiceService.getShippingInvoiceId(invoiceNumber);
boolean isShippingInvoice = invoiceNumber.charAt(8) == '7' || invoiceNumber.charAt(8) == '2';
if(isShippingInvoice)
invoiceID = iShippingInvoiceService.getShippingInvoiceId(invoiceNumber);
else
invoiceID = purchaseOrderService.getInvoiceId(invoiceNumber);
// if invoice exists
if (invoiceID == null) {
return Result.error("Error 404 page not found.");
return Result.error(404,"Error 404 page not found.");
}
// if user is a customer, we check if he's the owner of the shops
Client client = iShippingInvoiceService.getShopOwnerFromInvoiceNumber(invoiceNumber);
Client client;
if(isShippingInvoice)
client = iShippingInvoiceService.getShopOwnerFromInvoiceNumber(invoiceNumber);
else
client = clientService.getClientFromPurchase(invoiceID);
customerFullName = client.fullName();
String destEmail;
if(orgCode.contains("A04")) {
System.out.println(email + " - " + client.getEmail());
if(!client.getEmail().equals(email)) {
return Result.error("Not authorized to view this page.");
return Result.error(403,"Not authorized to view this page.");
}
else {
destEmail = client.getEmail();
@ -943,6 +1015,67 @@ public class InvoiceController {
return Result.OK(invoiceDatas);
}
@GetMapping(value = "/purchaseInvoiceData")
public Result<?> getPurchaseInvoiceData(@RequestParam("invoiceNumber") String invoiceNumber,
@RequestParam("originalCurrency") String originalCurrency,
@RequestParam("targetCurrency") String targetCurrency
){
InvoiceDatas invoiceDatas = new InvoiceDatas();
List<PurchaseOrder> invoices = purchaseOrderService.getPurchasesByInvoiceNumber(invoiceNumber);
if(invoices == null) {
return Result.error("No data for product found.");
}
List<PurchaseInvoiceEntry> invoiceData = new ArrayList<>();
for(PurchaseOrder order : invoices) {
invoiceData.addAll(purchaseOrderContentMapper.selectInvoiceDataByID(order.getId()));
}
List<BigDecimal> refundList = iSavRefundService.getRefundAmount(invoiceNumber);
Map<String, Map.Entry<Integer, BigDecimal>> feeAndQtyPerSku = new HashMap<>(); // it maps number of order and purchase fee per item : <France,<250, 50.30>>, <UK, <10, 2.15>>
BigDecimal refund = BigDecimal.ZERO;
// on parcours toutes les commandes pour récupérer : country, purchaseFee
for(PurchaseInvoiceEntry data : invoiceData) {
String sku = data.getSku_en_name();
BigDecimal purchaseFeePerSku = data.getTotalAmount();
Integer qty = data.getQuantity();
// On vérifie si on a déjà ce pays dans la map
// si oui on additionne la "qty" et "purchase fee"
// sinon on ajoute juste à la map
if(!feeAndQtyPerSku.containsKey(sku)) {
feeAndQtyPerSku.put(sku, new AbstractMap.SimpleEntry<>(qty, purchaseFeePerSku));
}
else {
BigDecimal existingGlobalFee = feeAndQtyPerSku.get(sku).getValue();
Integer existingOrderQuantity = feeAndQtyPerSku.get(sku).getKey();
existingOrderQuantity += qty;
existingGlobalFee = existingGlobalFee.add(purchaseFeePerSku);
feeAndQtyPerSku.remove(sku);
feeAndQtyPerSku.put(sku, new AbstractMap.SimpleEntry<>(existingOrderQuantity, existingGlobalFee));
}
}
// on fait la somme des remboursements
if(!refundList.isEmpty()) {
for (BigDecimal amount : refundList) {
refund = refund.add(amount);
}
}
// si la monnaie utilisé par le client n'est pas l'euro on calcul le total dans sa monnaie
if(!targetCurrency.equals(originalCurrency)) {
BigDecimal exchangeRate = iExchangeRatesService.getExchangeRate(originalCurrency,targetCurrency);
BigDecimal finalAmount = invoices.stream().map(PurchaseOrder::getFinalAmount).reduce(BigDecimal.ZERO, BigDecimal::add).multiply(exchangeRate);
finalAmount = finalAmount.setScale(2, RoundingMode.DOWN);
invoiceDatas.setFinalAmount(finalAmount);
}
invoiceDatas.setInvoiceNumber(invoiceNumber);
invoiceDatas.setDiscount(invoices.stream().map(PurchaseOrder::getDiscountAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
invoiceDatas.setRefund(refund);
invoiceDatas.setFinalAmountEur(invoices.stream().map(PurchaseOrder::getFinalAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
invoiceDatas.setFeeAndQtyPerSku(feeAndQtyPerSku);
return Result.OK(invoiceDatas);
}
public String countryNameFormatting(String country) {
Pattern p = Pattern.compile("(\\w*)", Pattern.UNICODE_CHARACTER_CLASS);
Matcher m = p.matcher(country);
@ -979,4 +1112,15 @@ public class InvoiceController {
}
return Result.OK().success("sys.api.syncRequestSubmitted");
}
@GetMapping(value = "/duplicateInvoiceNumberCheck")
public Result<?> duplicateInvoiceNumberCheck(@RequestParam("invoiceNumber") String invoiceNumber) {
if(iShippingInvoiceService.getShippingInvoice(invoiceNumber) != null
|| purchaseOrderService.getInvoiceId(invoiceNumber) != null
|| !platformOrderService.getPlatformOrdersByInvoiceNumber(invoiceNumber).isEmpty()) {
return Result.error("Invoice number already exists.");
}
else {
return Result.OK("Invoice number is available.");
}
}
}

View File

@ -10,6 +10,8 @@ import java.util.Map;
public class InvoiceDatas {
@JSONField(name = "invoiceNumber")
private String invoiceNumber;
@JSONField(name = "feeAndQtyPerSku")
private Map<String, Map.Entry<Integer, BigDecimal>> feeAndQtyPerSku;
@JSONField(name = "feeAndQtyPerCountry")
private Map<String, Map.Entry<Integer, BigDecimal>> feeAndQtyPerCountry;
@JSONField(name = "vat")

View File

@ -84,7 +84,6 @@ public class ShippingInvoiceController {
private FreeMarkerConfigurer freemarkerConfigurer;
@Autowired
private EmailService emailService;
private static final String EXTENSION = ".xlsx";
@Value("${jeecg.path.shippingInvoiceDir}")
private String INVOICE_LOCATION;
@Value("${jeecg.path.shippingInvoiceDetailDir}")
@ -281,81 +280,7 @@ public class ShippingInvoiceController {
return Result.OK("文件导入失败!");
}
/** Finds the absolute path of invoice file by recursively walking the directory and it's subdirectories
*
* @param dirPath
* @param invoiceNumber
* @return List of paths for the file but should only find one result
*/
public List<Path> getPath(String dirPath, String invoiceNumber) {
List<Path> pathList = new ArrayList<>();
//Recursively list all files
//The walk() method returns a Stream by walking the file tree beginning with a given starting file/directory in a depth-first manner.
try (Stream<Path> stream = Files.walk(Paths.get(dirPath))) {
pathList = stream.map(Path::normalize)
.filter(Files::isRegularFile) // directories, hidden files and files without extension are not included
.filter(path -> path.getFileName().toString().contains(invoiceNumber))
.filter(path -> path.getFileName().toString().endsWith(EXTENSION))
.collect(Collectors.toList());
}
catch(IOException e) {
e.printStackTrace();
}
return pathList;
}
/** Finds the absolute path of invoice file by recursively walking the directory and it's subdirectories
*
* @param dirPath
* @param invoiceNumber
* @return List of paths for the file but should only find one result
*/
public List<Path> getPath(String dirPath, String invoiceNumber, String invoiceEntity) {
List<Path> pathList = new ArrayList<>();
//Recursively list all files
//The walk() method returns a Stream by walking the file tree beginning with a given starting file/directory in a depth-first manner.
try (Stream<Path> stream = Files.walk(Paths.get(dirPath))) {
pathList = stream.map(Path::normalize)
.filter(Files::isRegularFile) // directories, hidden files and files without extension are not included
.filter(path -> path.getFileName().toString().contains(invoiceNumber))
.filter(path -> path.getFileName().toString().contains(invoiceEntity))
.filter(path -> path.getFileName().toString().endsWith(EXTENSION))
.collect(Collectors.toList());
}
catch(IOException e) {
e.printStackTrace();
}
return pathList;
}
/**
* Finds the absolute path of invoice file and return the path
* @param invoiceNumber
* @param filetype if it's an invoice or invoice detail
* @return String returns the path of the invoice file
*/
public String getInvoiceList(String invoiceNumber, String filetype) {
log.info("Invoice number : " + invoiceNumber);
List<Path> pathList = new ArrayList<>();
if(filetype.equals("invoice")) {
log.info("File asked is of type invoice");
pathList = getPath(INVOICE_LOCATION, invoiceNumber);
}
if(filetype.equals("detail")) {
log.info("File asked is of type invoice detail");
pathList = getPath(INVOICE_DETAIL_LOCATION, invoiceNumber);
}
if(pathList.isEmpty()) {
log.error("NO INVOICE FILE FOUND : " + invoiceNumber);
return "ERROR";
}
else {
for (Path path : pathList) {
log.info(path.toString());
}
return pathList.get(0).toString();
}
}
/**
* Downloads the invoice and returns it in form of bytearray
@ -366,7 +291,7 @@ public class ShippingInvoiceController {
*/
@GetMapping(value = "/downloadCompleteInvoiceExcel")
public ResponseEntity<?> download(@RequestParam("invoiceNumber") String invoiceNumber, @RequestParam("filetype") String filetype) throws IOException {
String filename = getInvoiceList(invoiceNumber, filetype);
String filename = shippingInvoiceService.getInvoiceList(invoiceNumber, filetype);
if(!filename.equals("ERROR")) {
File file = new File(filename);
@ -398,7 +323,7 @@ public class ShippingInvoiceController {
}
public String convertToPdf(String invoiceNumber, String fileType) throws Exception {
String excelFilePath = getInvoiceList(invoiceNumber, fileType);// (C:\PATH\filename.xlsx)
String excelFilePath = shippingInvoiceService.getInvoiceList(invoiceNumber, fileType);// (C:\PATH\filename.xlsx)
if(!excelFilePath.equals("ERROR")) {
String pdfFilePath= INVOICE_PDF_LOCATION + "/" + invoiceNumber + ".pdf";
@ -457,7 +382,7 @@ public class ShippingInvoiceController {
public Result<?> sendDetailsByEmail(@RequestParam("invoiceNumber") String invoiceNumber,
@RequestParam("email") String email,
@RequestParam("invoiceEntity") String invoiceEntity) throws Exception {
String filePath = getInvoiceList(invoiceNumber, "detail");
String filePath = shippingInvoiceService.getInvoiceList(invoiceNumber, "detail");
String fileType = "Détails de facture";
String subject = "Détails de facture N°" + invoiceNumber;
Properties prop = emailService.getMailSender();
@ -519,8 +444,8 @@ public class ShippingInvoiceController {
balanceService.deleteBalance(id, OperationType.Debit.name());
log.info("Deleting invoice files ...");
String invoiceEntity = clientService.getClientEntity(clientId);
List<Path> invoicePathList = getPath(INVOICE_LOCATION, invoiceNumber, invoiceEntity);
List<Path> detailPathList = getPath(INVOICE_DETAIL_LOCATION, invoiceNumber, invoiceEntity);
List<Path> invoicePathList = shippingInvoiceService.getPath(INVOICE_LOCATION, invoiceNumber, invoiceEntity);
List<Path> detailPathList = shippingInvoiceService.getPath(INVOICE_DETAIL_LOCATION, invoiceNumber, invoiceEntity);
boolean invoiceDeleted = false, detailDeleted = false;
if(invoicePathList.isEmpty()) {
@ -586,8 +511,8 @@ public class ShippingInvoiceController {
for(int i = 0; i < ids.size(); i++) {
String invoiceNumber = invoiceNumbers.get(i);
String invoiceEntity = clientService.getClientEntity(clientIds.get(i));
List<Path> invoicePathList = getPath(INVOICE_LOCATION, invoiceNumber, invoiceEntity);
List<Path> detailPathList = getPath(INVOICE_DETAIL_LOCATION, invoiceNumber, invoiceEntity);
List<Path> invoicePathList = shippingInvoiceService.getPath(INVOICE_LOCATION, invoiceNumber, invoiceEntity);
List<Path> detailPathList = shippingInvoiceService.getPath(INVOICE_DETAIL_LOCATION, invoiceNumber, invoiceEntity);
if(invoicePathList.isEmpty()) {
log.error("FILE NOT FOUND : " + invoiceNumber + ", " + invoiceEntity);

View File

@ -98,8 +98,7 @@ public class TransactionController {
Date startDate = orders.stream().map(PlatformOrder::getOrderTime).min(Date::compareTo).get();
Date endDate = orders.stream().map(PlatformOrder::getOrderTime).max(Date::compareTo).get();
List<String> orderIds = orders.stream().map(PlatformOrder::getId).collect(Collectors.toList());
System.out.println("Orders size : " + orderIds.size());
System.out.println("Orders : " + orderIds);
log.info("{} Orders to be estimated", orderIds.size());
ShippingInvoiceFactory factory = new ShippingInvoiceFactory(
platformOrderService, clientMapper, shopMapper, logisticChannelMapper, logisticChannelPriceMapper,
platformOrderContentService, skuDeclaredValueService, countryService, exchangeRatesMapper,
@ -158,7 +157,7 @@ public class TransactionController {
param.put("errors", errors);
param.put("current_page", String.valueOf(current_page));
param.put("total_page", String.valueOf(total_page));
TemplateMessageDTO message = new TemplateMessageDTO("admin", "Gauthier", "Expenses Overview Errors", param, "expenses_overview_errors");
TemplateMessageDTO message = new TemplateMessageDTO("admin", "admin", "Expenses Overview Errors", param, "expenses_overview_errors");
ISysBaseApi.sendTemplateAnnouncement(message);
}
}

View File

@ -0,0 +1,81 @@
package org.jeecg.modules.business.domain.job;
import freemarker.template.Template;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.modules.business.service.EmailService;
import org.jeecg.modules.business.service.IPlatformOrderService;
import org.jeecg.modules.business.vo.ShippingFeeBillableOrders;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import java.util.*;
import java.util.stream.Collectors;
import static java.util.stream.Collectors.*;
@Slf4j
public class ShippingFeeBillableNotificationJob implements Job {
@Autowired
private IPlatformOrderService platformOrderService;
@Autowired
private EmailService emailService;
@Autowired
private FreeMarkerConfigurer freemarkerConfigurer;
@Autowired
Environment env;
/**
* Job that finds all order contents from uninvoiced orders with missing stock and checks if products have been ordered
* @param jobExecutionContext
* @throws JobExecutionException
*/
@Transactional
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
log.info("Shipping Fee Billable Notification Job started ...");
List<ShippingFeeBillableOrders> shippingFeeBillableOrders = platformOrderService.fetchShippingFeeBillableOrders();
if (shippingFeeBillableOrders.isEmpty()) {
log.info("No orders awaiting shipping fees to be billed.");
return;
}
Map<String, List<ShippingFeeBillableOrders>> ordersByClientEmail = shippingFeeBillableOrders.stream().collect(groupingBy(ShippingFeeBillableOrders::getEmail));
Properties prop = emailService.getMailSender();
Session session = Session.getInstance(prop, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(env.getProperty("spring.mail.username"), env.getProperty("spring.mail.password"));
}
});
for(Map.Entry<String, List<ShippingFeeBillableOrders>> entry : ordersByClientEmail.entrySet()) {
String subject = "Shipping Fee Billable Notification";
String destEmail = entry.getKey();
Map<String, Object> templateModel = new HashMap<>();
templateModel.put("fullName", entry.getValue().get(0).getFullName());
templateModel.put("orderNumbers", entry.getValue().stream().map(ShippingFeeBillableOrders::getOrderNumber).collect(Collectors.toList()));
try {
freemarkerConfigurer = emailService.freemarkerClassLoaderConfig();
Template template = freemarkerConfigurer.getConfiguration().getTemplate("client/shippingFeeBillableNotification.ftl");
String htmlBody = FreeMarkerTemplateUtils.processTemplateIntoString(template, templateModel);
emailService.sendSimpleMessage(destEmail, subject, htmlBody, session);
log.info("Mail sent successfully");
} catch (Exception e) {
log.error("Error sending mail: " + e.getMessage());
}
}
log.info("Shipping Fee Billable Notification Job finished ...");
}
}

View File

@ -140,10 +140,6 @@ public class SkuShippingQtyJob implements Job {
}
skuData.setStockAfterDistribution(skuData.getStockQuantity() - content.getQuantity());
skuData.calculateVirtualQuantity();
if(skuData.getStockAfterDistribution() < 0) {
System.out.println("===================== ERRRRRRRRRRRRRRRROOOOOOOOOOOOOOOOOORRR ======================");
System.out.println("Order : " + orderMapEntry.getKey().getPlatformOrderId() + " --- Sku : " + skuIdToErpCodeMap.get(content.getSkuId()) + " --- Stock : " + skuData.getStockQuantity() + " --- Stock after subtracting : " + skuData.getStockAfterDistribution() + " --- Virtual Stock : " + skuData.getVirtualQuantity() + " --- Shipping Quantity : " + skuData.getShippingQuantity());
}
}
}
log.info("Sku Shipping Quantity after subtracting the quantity from orders with product available");
@ -164,14 +160,12 @@ public class SkuShippingQtyJob implements Job {
List<PlatformOrderContent> orderContentsToUpdate = new ArrayList<>();
// Subtract the virtual stock quantity from the orders with missing stock, then update stock availability
for (Map.Entry<PlatformOrder, List<PlatformOrderContent>> orderMapEntry : orderMapWithMissingStock.entrySet()) {
System.out.println("Order time : " + orderMapEntry.getKey().getOrderTime());
boolean allContentsHaveStock = true;
for(PlatformOrderContent content : orderMapEntry.getValue()) {
// subtract the quantity from skuShippingQtyDataMap, if enough stock, set virtualProductAvailable to 1
SkuShippingQtyData skuData = skuShippingQtyDataMap.get(skuIdToErpCodeMap.get(content.getSkuId()));
if(skuData == null) {
System.out.println("SKU DATA IS NULL for Sku : " + skuIdToErpCodeMap.get(content.getSkuId()));
System.out.println("Sku ID : " + content.getSkuId());
log.info("SKU data is null for Sku erpCode : {} - Sku ID : {}", skuIdToErpCodeMap.get(content.getSkuId()), content.getSkuId());
allContentsHaveStock = false;
continue;
}
@ -197,7 +191,6 @@ public class SkuShippingQtyJob implements Job {
// Update the database
if(!ordersToUpdate.isEmpty()) {
platformOrderService.updateBatchById(ordersToUpdate);
// TODO : send email to client and ask him to pay for shipping fees
}
if(!orderContentsToUpdate.isEmpty()) {
platformOrderContentService.updateBatchById(orderContentsToUpdate);

View File

@ -370,14 +370,11 @@ public class ShippingInvoiceFactory {
emailService.newSendSimpleMessage(destEmail, emailSubject, templateName, templateModel);
}
// removing orders that can't be invoiced
System.out.println("Orders and content size BEFORE : " + orderAndContent.size());
System.out.println("Orders to remove size : " + ordersToRemove.size());
for(Map.Entry<String, List<String>> entry : ordersToRemove.entrySet()) {
for(String platformOrderId : entry.getValue()) {
orderAndContent.keySet().removeIf(order -> order.getPlatformOrderId().equals(platformOrderId));
}
}
System.out.println("Orders and content size AFTER : " + orderAndContent.size());
BigDecimal eurToUsd = exchangeRatesMapper.getLatestExchangeRate("EUR", "USD");
if(orderAndContent.isEmpty()) {
@ -635,11 +632,9 @@ public class ShippingInvoiceFactory {
shops.forEach(shop -> shopPackageMatFeeMap.put(shop.getId(), shop.getPackagingMaterialFee()));
String invoiceCode = generateInvoiceCode();
log.info("New invoice code: {}", invoiceCode);
System.out.println("Order and content size BEFORE : " + orderAndContent.size());
Map<String, List<String>> ordersWithPB = calculateFees(balance, logisticChannelMap, orderAndContent, channelPriceMap, countryList, skuRealWeights, skuServiceFees,
latestDeclaredValues, client, shopServiceFeeMap, shopPackageMatFeeMap, invoiceCode);
orderAndContent.entrySet().removeIf(entries -> ordersWithPB.containsKey(entries.getKey().getId()));
System.out.println("Order and content size AFTER : " + orderAndContent.size());
if(orderAndContent.isEmpty()) {
log.error("No order was invoiced for customer {} because : {}", client.getInternalCode(), ordersWithPB);
throw new UserException("Customer " + customerId + " errors : " + ordersWithPB);
@ -730,9 +725,6 @@ public class ShippingInvoiceFactory {
// find logistic channel price for each order based on its content
for (PlatformOrder uninvoicedOrder : orderContentMap.keySet()) {
if(skip) {
if(client.getInternalCode().equals("FT")) {
System.out.println("uninvoicedOrder order time : " + uninvoicedOrder.getOrderTime());
}
platformOrderIdsWithPb.put(uninvoicedOrder.getId(), Collections.singletonList("Skipped"));
continue;
}
@ -847,7 +839,6 @@ public class ShippingInvoiceFactory {
}
// removing orders that can't be invoiced
log.info("Number of orders with problem for client {} : {}", client.getInternalCode(), platformOrderIdsWithPb.size());
platformOrderIdsWithPb.keySet().forEach(System.out::println);
return platformOrderIdsWithPb;
}

View File

@ -68,7 +68,7 @@ public class ClientCategory implements Serializable {
@Getter
public enum CategoryName {
SELF_SERVICE("self_service"),
SELF_SERVICE("self-service"),
CONFIRMED ("confirmed"),
VIP("vip");

View File

@ -38,9 +38,6 @@ public class OrderContentDetail {
*/
public BigDecimal totalPrice() {
BigDecimal unit = skuDetail.getPrice().getPrice(quantity, exchangeRate);
if(unit == null) {
System.out.println("Unit is null : " + skuDetail.getSkuId() + "sku price: " + skuDetail.getPrice() + "quantity: " + quantity);
}
BigDecimal total = unit.multiply(new BigDecimal(quantity));
log.info("unit: {}", unit);
log.info("total: {}", total);

View File

@ -22,4 +22,9 @@ public interface ClientMapper extends BaseMapper<Client> {
String getClientIdByCode(@Param("code") String code);
List<Client> getClientByType(@Param("type") String type);
Client getClientByCode(@Param("code") String internalCode);
Client getClientFromOrder(@Param("orderId")String orderId);
Client getClientFromPurchase(@Param("purchaseId") String purchaseId);
List<String> getClientsFromPurchases(@Param("purchaseIds") List<String> purchaseIds);
}

View File

@ -5,6 +5,7 @@ import org.apache.ibatis.annotations.Param;
import org.jeecg.modules.business.domain.api.mabang.getorderlist.Order;
import org.jeecg.modules.business.entity.PlatformOrder;
import org.jeecg.modules.business.entity.PlatformOrderShopSync;
import org.jeecg.modules.business.vo.ShippingFeeBillableOrders;
import org.jeecg.modules.business.vo.clientPlatformOrder.ClientPlatformOrderPage;
import org.jeecg.modules.business.vo.clientPlatformOrder.section.OrderQuantity;
import org.springframework.stereotype.Repository;
@ -200,4 +201,12 @@ public interface PlatformOrderMapper extends BaseMapper<PlatformOrder> {
List<PlatformOrder> selectByPlatformOrderIds(@Param("platformOrderIds") List<String> platformOrderIds);
void removePurchaseInvoiceNumber(@Param("invoiceNumber") String purchaseInvoiceNumber);
void removePurchaseInvoiceNumbers(@Param("invoiceNumbers") List<String> invoiceNumbers);
void updatePurchaseInvoiceNumber(@Param("orderIds") List<String> orderIds, @Param("invoiceNumber") String invoiceNumber);
List<ShippingFeeBillableOrders> fetchShippingFeeBillableOrders();
List<PlatformOrder> getPlatformOrdersByInvoiceNumber(@Param("invoiceNumber") String invoiceNumber);
}

View File

@ -25,4 +25,6 @@ public interface PurchaseOrderContentMapper extends BaseMapper<PurchaseOrderSku>
void addAll(@Param("creator") String creator, @Param("purchaseID") String purchaseID, @Param("data") List<OrderContentEntry> orderContent);
List<PurchaseInvoiceEntry> selectInvoiceDataByID(@Param("purchaseID") String purchaseID);
void deleteFromPurchaseIds(@Param("purchaseIds") List<String> purchaseIds);
}

View File

@ -4,6 +4,7 @@ import java.math.BigDecimal;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import org.jeecg.modules.business.entity.PlatformOrder;
import org.jeecg.modules.business.entity.PurchaseOrder;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springframework.stereotype.Repository;
@ -97,4 +98,10 @@ public interface PurchaseOrderMapper extends BaseMapper<PurchaseOrder> {
void deleteInvoice(@Param("invoiceNumber") String invoiceNumber);
void deleteBatchInvoice(@Param("invoiceNumbers") List<String> invoiceNumbers);
String getInvoiceId(@Param("invoiceNumber") String invoiceNumber);
List<PurchaseOrder> getPurchasesByInvoiceNumber(@Param("invoiceNumber") String invoiceNumber);
List<PlatformOrder> getPlatformOrder(@Param("invoiceNumber") String invoiceNumber);
}

View File

@ -32,4 +32,30 @@
WHERE cc.name = #{type}
AND c.active = 1;
</select>
<select id="getClientFromOrder" resultType="org.jeecg.modules.business.entity.Client">
SELECT c.*
FROM client c
JOIN shop s
ON c.id = s.owner_id
JOIN platform_order po
ON s.id = po.shop_id
WHERE po.id = #{orderId};
</select>
<select id="getClientFromPurchase" resultType="org.jeecg.modules.business.entity.Client">
SELECT c.*
FROM client c
JOIN purchase_order po
ON c.id = po.client_id
WHERE po.id = #{purchaseId};
</select>
<select id="getClientsFromPurchases" resultType="org.jeecg.modules.business.entity.Client">
SELECT c.*
FROM client c
JOIN purchase_order po
ON c.id = po.client_id
WHERE po.id IN
<foreach collection="purchaseIds" separator="," open="(" close=")" index="index" item="purchaseId">
#{purchaseId}
</foreach>;
</select>
</mapper>

View File

@ -664,7 +664,7 @@
AND create_time BETWEEN #{startDate} AND #{endDate};
</select>
<select id="fetchByIds" resultType="org.jeecg.modules.business.entity.PlatformOrder">
SELECT id, shop_id, product_available
SELECT id, shop_id, product_available, virtual_product_available, purchase_invoice_number
FROM platform_order
WHERE id IN
<foreach collection="orderIds" separator="," open="(" close=")" index="index" item="orderId">
@ -709,4 +709,35 @@
SET purchase_invoice_number = NULL
WHERE purchase_invoice_number = #{invoiceNumber}
</update>
<update id="removePurchaseInvoiceNumbers">
UPDATE platform_order
SET purchase_invoice_number = NULL
WHERE purchase_invoice_number IN
<foreach collection="invoiceNumbers" separator="," open="(" close=")" index="index" item="invoiceNumber">
#{invoiceNumber}
</foreach>;
</update>
<update id="updatePurchaseInvoiceNumber">
UPDATE platform_order
SET purchase_invoice_number = #{invoiceNumber}
WHERE id IN
<foreach collection="orderIds" separator="," open="(" close=")" index="index" item="orderId">
#{orderId}
</foreach>
</update>
<select id="fetchShippingFeeBillableOrders" resultType="org.jeecg.modules.business.vo.ShippingFeeBillableOrders">
SELECT CONCAT(c.first_name, ' ', c.surname) as full_name, c.email, po.platform_order_number as order_number
FROM platform_order po
JOIN shop s ON po.shop_id = s.id
JOIN client c ON s.owner_id = c.id
WHERE po.shipping_invoice_number IS NULL
AND po.purchase_invoice_number IS NOT NULL
AND po.erp_status IN (1,2)
AND po.product_available = 1
</select>
<select id="getPlatformOrdersByInvoiceNumber" resultType="org.jeecg.modules.business.entity.PlatformOrder">
SELECT *
FROM platform_order
WHERE shipping_invoice_number = #{invoiceNumber};
</select>
</mapper>

View File

@ -19,6 +19,17 @@
JOIN product p on s.product_id = p.id
WHERE purchase_order_id = #{purchaseID}
</select>
<select id="selectInvoicesDataByID" resultType="org.jeecg.modules.business.domain.purchase.invoice.PurchaseInvoiceEntry">
SELECT s.erp_code, p.en_name, SUM(pos.quantity) as quantity, SUM(pos.total_amount) as total_amount
FROM purchase_order_sku pos
JOIN sku s on pos.sku_id = s.id
JOIN product p on s.product_id = p.id
WHERE purchase_order_id IN
<foreach collection="purchaseIds" item="purchaseId" index="i" open="(" close=")" separator=",">
#{purchaseId}
</foreach>
GROUP BY s.erp_code
</select>
<insert id="addAll">
INSERT INTO purchase_order_sku(id, create_by, create_time, update_by, update_time, purchase_order_id, quantity,
@ -29,4 +40,12 @@
#{item.skuID})
</foreach>
</insert>
<delete id="deleteFromPurchaseIds">
DELETE
FROM purchase_order_sku
WHERE purchase_order_id IN
<foreach collection="purchaseIds" item="purchaseId" index="i" open="(" close=")" separator=",">
#{purchaseId}
</foreach>
</delete>
</mapper>

View File

@ -81,4 +81,19 @@
#{invoiceNumber}
</foreach>
</delete>
<select id="getInvoiceId" resultType="java.lang.String">
SELECT id
FROM purchase_order
WHERE invoice_number = #{invoiceNumber}
</select>
<select id="getPurchasesByInvoiceNumber" resultType="org.jeecg.modules.business.entity.PurchaseOrder">
SELECT *
FROM purchase_order
WHERE invoice_number = #{invoiceNumber}
</select>
<select id="getPlatformOrder" resultType="org.jeecg.modules.business.entity.PlatformOrder">
SELECT *
FROM platform_order
WHERE shipping_invoice_number = #{invoiceNumber}
</select>
</mapper>

View File

@ -146,6 +146,9 @@
<foreach collection="orderIds" separator="," open="(" close=")" index="index" item="orderId">
#{orderId}
</foreach>
AND erp_status IN ('1','2', '3')
AND product_available = 0
AND virtual_product_available = 0
GROUP BY sku_id;
</select>
</mapper>

View File

@ -48,4 +48,10 @@ public interface IClientService extends IService<Client> {
Client getCurrentClient();
List<Client> getClientsByType(String type);
Client getClientFromOrder(String orderId);
Client getClientFromPurchase(String purchaseId);
List<String> getClientsFromPurchases(List<String> purchaseIds);
}

View File

@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.modules.business.controller.UserException;
import org.jeecg.modules.business.entity.*;
import org.jeecg.modules.business.vo.PlatformOrderQuantity;
import org.jeecg.modules.business.vo.ShippingFeeBillableOrders;
import org.jeecg.modules.business.vo.SkuQuantity;
import org.jeecg.modules.business.vo.clientPlatformOrder.ClientPlatformOrderPage;
import org.jeecg.modules.business.vo.clientPlatformOrder.PurchaseConfirmation;
@ -208,4 +209,14 @@ public interface IPlatformOrderService extends IService<PlatformOrder> {
List<PlatformOrder> selectByPlatformOrderIds(List<String> platformOrderIds);
void removePurchaseInvoiceNumber(String purchaseInvoiceNumber);
void removePurchaseInvoiceNumbers(List<String> invoiceNumbers);
void updatePurchaseInvoiceNumber(List<String> orderIds, String invoiceCode);
/**
* Fetch all orders with productAvailable = 1, purchaseInvoiceNumber NOT NULL, invoiceNumber NULL and erp_status IN (1,2)
* @return
*/
List<ShippingFeeBillableOrders> fetchShippingFeeBillableOrders();
List<PlatformOrder> getPlatformOrdersByInvoiceNumber(String invoiceNumber);
}

View File

@ -3,8 +3,8 @@ package org.jeecg.modules.business.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.modules.business.controller.UserException;
import org.jeecg.modules.business.domain.purchase.invoice.InvoiceData;
import org.jeecg.modules.business.entity.*;
import org.jeecg.modules.business.vo.InvoiceMetaData;
import org.jeecg.modules.business.vo.SkuQuantity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
@ -44,6 +44,12 @@ public interface IPurchaseOrderService extends IService<PurchaseOrder> {
*/
public void delBatchMain(Collection<? extends Serializable> idList);
@Transactional
void cancelInvoice(String purchaseId, String invoiceNumber);
@Transactional
void cancelBatchInvoice(String ids);
/**
* Set purchase orders to the page indicated by argument.
*
@ -104,7 +110,7 @@ public interface IPurchaseOrderService extends IService<PurchaseOrder> {
* @return the file in binary
* @throws IOException IO error while reading the file.
*/
InvoiceData makeInvoice(String purchaseID) throws IOException, URISyntaxException;
InvoiceMetaData makeInvoice(String purchaseID) throws IOException, URISyntaxException;
byte[] getInvoiceByte(String invoiceCode) throws IOException;
@ -113,4 +119,10 @@ public interface IPurchaseOrderService extends IService<PurchaseOrder> {
void cancelInvoice(String invoiceNumber);
void cancelBatchInvoice(List<String> invoiceNumbers);
String getInvoiceId(String invoiceNumber);
List<PurchaseOrder> getPurchasesByInvoiceNumber(String invoiceNumber);
List<PlatformOrder> getPlatformOrder(String invoiceNumber);
}

View File

@ -4,6 +4,7 @@ import org.jeecg.modules.business.entity.*;
import com.baomidou.mybatisplus.extension.service.IService;
import java.io.Serializable;
import java.nio.file.Path;
import java.util.Collection;
import java.util.List;
@ -40,4 +41,10 @@ public interface IShippingInvoiceService extends IService<ShippingInvoice> {
public List<PlatformOrderContent> getPlatformOrderContent(String platformOrderId);
public Client getShopOwnerFromInvoiceNumber(String invoiceNumber);
Currency getInvoiceCurrencyByCode(String invoiceCode);
// Utils
public List<Path> getPath(String dirPath, String invoiceNumber);
public List<Path> getPath(String dirPath, String invoiceNumber, String invoiceEntity);
public String getInvoiceList(String invoiceNumber, String filetype);
boolean deleteAttachmentFile(String filename);
}

View File

@ -3,7 +3,6 @@ package org.jeecg.modules.business.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.modules.business.controller.UserException;
import org.jeecg.modules.business.domain.excel.SheetManager;
@ -102,6 +101,9 @@ public class PlatformOrderShippingInvoiceService {
@Value("${jeecg.path.shippingInvoiceDir}")
private String INVOICE_DIR;
@Value("${jeecg.path.purchaseInvoiceDir}")
private String PURCHASE_INVOICE_DIR;
@Value("${jeecg.path.shippingInvoiceDetailDir}")
private String INVOICE_DETAIL_DIR;
@ -343,8 +345,9 @@ public class PlatformOrderShippingInvoiceService {
* @return byte array of the file
* @throws IOException error when reading file
*/
public byte[] getInvoiceBinary(String filename) throws IOException {
Path out = Paths.get(INVOICE_DIR, filename);
public byte[] getInvoiceBinary(String filename, String type) throws IOException {
String path = type.equals("shipping") ? INVOICE_DIR : PURCHASE_INVOICE_DIR;
Path out = Paths.get(path, filename);
return Files.readAllBytes(out);
}
@ -529,7 +532,6 @@ public class PlatformOrderShippingInvoiceService {
invoiceList.add(new InvoiceMetaData("", "error", internalCode, clientId, "No order to invoice."));
continue;
}
System.out.println("Period: [" + period.start() + " - " + period.end() + "]");
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));

View File

@ -1,7 +1,6 @@
package org.jeecg.modules.business.service.impl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.Pair;
import org.jeecg.modules.business.entity.*;
import org.jeecg.modules.business.mapper.BalanceMapper;
import org.jeecg.modules.business.mapper.ClientCategoryMapper;
@ -18,8 +17,6 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @Description: balance
@ -92,15 +89,12 @@ public class BalanceServiceImpl extends ServiceImpl<BalanceMapper, Balance> impl
SysUser sysUser = new SysUser();
String currency = currencyService.getCodeById(currencyId);
Balance balance = balanceMapper.getBalanceByOperation(operationId, operationType);
System.out.println("balance exist ? : " + balance);
if(balance == null) {
throw new Exception("Balance not found !");
}
balanceMapper.deleteBalance(operationId, operationType);
BigDecimal currentBalance = balanceMapper.getBalanceByClientIdAndCurrency(clientId, currency);
System.out.println("current balance : " + currentBalance);
BigDecimal finalBalance = operationType.equals(Balance.OperationType.Credit.name()) ? currentBalance.add(amount) : currentBalance.subtract(amount);
System.out.println("final balance : " + finalBalance);
Balance newBalance = Balance.of(sysUser.getUsername(), clientId, currencyId, operationType, operationId, finalBalance);
balanceMapper.insert(newBalance);
}

View File

@ -123,6 +123,21 @@ public class ClientServiceImpl extends ServiceImpl<ClientMapper, Client> impleme
return clientMapper.getClientByType(type);
}
@Override
public Client getClientFromOrder(String orderId) {
return clientMapper.getClientFromOrder(orderId);
}
@Override
public Client getClientFromPurchase(String purchaseId) {
return clientMapper.getClientFromPurchase(purchaseId);
}
@Override
public List<String> getClientsFromPurchases(List<String> purchaseIds) {
return clientMapper.getClientsFromPurchases(purchaseIds);
}
@Override
public String getClientEntity(String id) {
return clientMapper.getClientEntity(id);

View File

@ -13,10 +13,7 @@ import org.jeecg.modules.business.mapper.PlatformOrderMapper;
import org.jeecg.modules.business.service.IClientService;
import org.jeecg.modules.business.service.IPlatformOrderService;
import org.jeecg.modules.business.service.IShippingFeesWaiverProductService;
import org.jeecg.modules.business.vo.PlatformOrderQuantity;
import org.jeecg.modules.business.vo.SkuDetail;
import org.jeecg.modules.business.vo.SkuQuantity;
import org.jeecg.modules.business.vo.SkuShippingFeesWaiver;
import org.jeecg.modules.business.vo.*;
import org.jeecg.modules.business.vo.clientPlatformOrder.ClientPlatformOrderPage;
import org.jeecg.modules.business.vo.clientPlatformOrder.PurchaseConfirmation;
import org.jeecg.modules.business.vo.clientPlatformOrder.section.ClientInfo;
@ -290,7 +287,6 @@ public class PlatformOrderServiceImpl extends ServiceImpl<PlatformOrderMapper, P
@Override
public Map<String, Map<PlatformOrder, List<PlatformOrderContent>>> findUninvoicedOrders() {
List<PlatformOrder> orderList = platformOrderMap.findUninvoicedShippedOrders();
System.out.println("orderList size : " + orderList.size());
List<PlatformOrderContent> orderContents = platformOrderContentMap.findUninvoicedShippedOrderContents();
Map<String, PlatformOrder> orderMap = orderList.stream().collect(toMap(PlatformOrder::getId, Function.identity()));
Map<String, String> orderMapByShopId = orderList.stream().collect(toMap(PlatformOrder::getId, PlatformOrder::getShopId));
@ -441,4 +437,24 @@ public class PlatformOrderServiceImpl extends ServiceImpl<PlatformOrderMapper, P
public void removePurchaseInvoiceNumber(String purchaseInvoiceNumber) {
platformOrderMap.removePurchaseInvoiceNumber(purchaseInvoiceNumber);
}
@Override
public void removePurchaseInvoiceNumbers(List<String> invoiceNumbers) {
platformOrderMap.removePurchaseInvoiceNumbers(invoiceNumbers);
}
@Override
public void updatePurchaseInvoiceNumber(List<String> orderIds, String invoiceCode) {
platformOrderMap.updatePurchaseInvoiceNumber(orderIds, invoiceCode);
}
@Override
public List<ShippingFeeBillableOrders> fetchShippingFeeBillableOrders() {
return platformOrderMap.fetchShippingFeeBillableOrders();
}
@Override
public List<PlatformOrder> getPlatformOrdersByInvoiceNumber(String invoiceNumber) {
return platformOrderMap.getPlatformOrdersByInvoiceNumber(invoiceNumber);
}
}

View File

@ -1,17 +1,27 @@
package org.jeecg.modules.business.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.modules.business.entity.*;
import org.jeecg.modules.business.mapper.ShippingInvoiceMapper;
import org.jeecg.modules.business.service.IShippingInvoiceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @Description:
@ -25,7 +35,31 @@ public class ShippingInvoiceServiceImpl extends ServiceImpl<ShippingInvoiceMappe
@Autowired
private ShippingInvoiceMapper shippingInvoiceMapper;
private static enum EXTENSION {
XLSX(".xlsx"),
XLS(".xls"),
CSV(".csv"),
PDF(".pdf"),
JPG(".jpg"),
PNG(".png"),
JPEG(".jpeg");
@Getter
private final String extension;
EXTENSION(String extension) {
this.extension = extension;
}
}
@Value("${jeecg.path.shippingInvoiceDir}")
private String INVOICE_LOCATION;
@Value("${jeecg.path.shippingInvoiceDetailDir}")
private String INVOICE_DETAIL_LOCATION;
@Value("${jeecg.path.shippingInvoicePdfDir}")
private String INVOICE_PDF_LOCATION;
@Value("${jeecg.path.shippingInvoiceDetailPdfDir}")
private String INVOICE_DETAIL_PDF_LOCAION;
@Value("${jeecg.path.upload}")
private String UPLOAD_DIR;
@Autowired
public ShippingInvoiceServiceImpl(ShippingInvoiceMapper shippingInvoiceMapper) {
this.shippingInvoiceMapper = shippingInvoiceMapper;
@ -95,4 +129,132 @@ public class ShippingInvoiceServiceImpl extends ServiceImpl<ShippingInvoiceMappe
return shippingInvoiceMapper.fetchPlatformOrderContent(platformOrderId);
}
/** Finds the absolute path of invoice file by recursively walking the directory and it's subdirectories
*
* @param dirPath
* @param invoiceNumber
* @return List of paths for the file but should only find one result
*/
public List<Path> getPath(String dirPath, String invoiceNumber) {
List<Path> pathList = new ArrayList<>();
//Recursively list all files
//The walk() method returns a Stream by walking the file tree beginning with a given starting file/directory in a depth-first manner.
try (Stream<Path> stream = Files.walk(Paths.get(dirPath))) {
pathList = stream.map(Path::normalize)
.filter(Files::isRegularFile) // directories, hidden files and files without extension are not included
.filter(path -> path.getFileName().toString().contains(invoiceNumber))
.filter(path -> path.getFileName().toString().endsWith(EXTENSION.XLSX.getExtension()))
.collect(Collectors.toList());
}
catch(IOException e) {
e.printStackTrace();
}
return pathList;
}
/** Finds the absolute path of invoice file by recursively walking the directory and it's subdirectories
*
* @param dirPath
* @param invoiceNumber
* @return List of paths for the file but should only find one result
*/
public List<Path> getPath(String dirPath, String invoiceNumber, String invoiceEntity) {
List<Path> pathList = new ArrayList<>();
//Recursively list all files
//The walk() method returns a Stream by walking the file tree beginning with a given starting file/directory in a depth-first manner.
try (Stream<Path> stream = Files.walk(Paths.get(dirPath))) {
pathList = stream.map(Path::normalize)
.filter(Files::isRegularFile) // directories, hidden files and files without extension are not included
.filter(path -> path.getFileName().toString().contains(invoiceNumber))
.filter(path -> path.getFileName().toString().contains(invoiceEntity))
.filter(path -> path.getFileName().toString().endsWith(EXTENSION.XLSX.getExtension()))
.collect(Collectors.toList());
}
catch(IOException e) {
e.printStackTrace();
}
return pathList;
}
/** Finds the absolute path of any file by recursively walking the directory and it's subdirectories
*
* @param dirPath
* @param filename
* @param extension
* @return List of paths for the file but should only find one result
*/
public List<Path> getAttachementPath(String dirPath, String filename, String extension) {
List<Path> pathList = new ArrayList<>();
//Recursively list all files
//The walk() method returns a Stream by walking the file tree beginning with a given starting file/directory in a depth-first manner.
try (Stream<Path> stream = Files.walk(Paths.get(dirPath))) {
pathList = stream.map(Path::normalize)
.filter(Files::isRegularFile) // directories, hidden files and files without extension are not included
.filter(path -> path.getFileName().toString().contains(filename))
.filter(path -> path.getFileName().toString().endsWith(extension))
.collect(Collectors.toList());
}
catch(IOException e) {
e.printStackTrace();
}
return pathList;
}
/**
* Finds the absolute path of invoice file and return the path
* @param invoiceNumber
* @param filetype if it's an invoice or invoice detail
* @return String returns the path of the invoice file
*/
public String getInvoiceList(String invoiceNumber, String filetype) {
log.info("Invoice number : " + invoiceNumber);
List<Path> pathList = new ArrayList<>();
if(filetype.equals("invoice")) {
log.info("File asked is of type invoice");
pathList = getPath(INVOICE_LOCATION, invoiceNumber);
}
if(filetype.equals("detail")) {
log.info("File asked is of type invoice detail");
pathList = getPath(INVOICE_DETAIL_LOCATION, invoiceNumber);
}
if(pathList.isEmpty()) {
log.error("NO INVOICE FILE FOUND : " + invoiceNumber);
return "ERROR";
}
else {
for (Path path : pathList) {
log.info(path.toString());
}
return pathList.get(0).toString();
}
}
@Override
public boolean deleteAttachmentFile(String filepath) {
String filename = filepath.substring(filepath.lastIndexOf("/")+1, filepath.lastIndexOf("."));
System.out.println(filename);
String extension = filepath.substring(filepath.lastIndexOf("."));
List<Path> attachmentPathList = getAttachementPath(UPLOAD_DIR, filename, extension);
boolean isFileDeleted = false;
if(attachmentPathList.isEmpty()) {
log.error("FILE NOT FOUND : " + filepath);
} else {
for (Path path : attachmentPathList) {
log.info(path.toString());
}
try {
File attachmentFile = new File(attachmentPathList.get(0).toString());
if(attachmentFile.delete()) {
log.info("Attachment file {} delete successful.", attachmentPathList.get(0).toString());
isFileDeleted = true;
} else {
log.error("Attachment file delete fail.");
}
} catch (Exception e) {
e.printStackTrace();
}
}
return isFileDeleted;
}
}

View File

@ -181,7 +181,6 @@ public class SkuServiceImpl extends ServiceImpl<SkuMapper, Sku> implements ISkuS
public void addInventory(List<SkuQuantity> skuQuantities, List<String> platformOrderIDs) {
Objects.requireNonNull(skuQuantities);
Objects.requireNonNull(platformOrderIDs);
Map<String, Integer> quantityPurchased = skuQuantities.stream()
.collect(
Collectors.toMap(
@ -189,11 +188,13 @@ public class SkuServiceImpl extends ServiceImpl<SkuMapper, Sku> implements ISkuS
SkuQuantity::getQuantity
)
);
// Add surplus of purchased quantity to SKU's "purchasing amount"
if (!platformOrderIDs.isEmpty()) {
List<SkuQuantity> used = platformOrderContentMapper.searchOrderContent(platformOrderIDs);
for (SkuQuantity sq : used) {
if(!quantityPurchased.containsKey(sq.getID())) {
break;
}
int quantity = quantityPurchased.get(sq.getID());
quantityPurchased.put(sq.getID(), quantity - sq.getQuantity());
}

View File

@ -2,18 +2,17 @@ package org.jeecg.modules.business.service.impl.purchase;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.modules.business.controller.UserException;
import org.jeecg.modules.business.domain.codeGeneration.PurchaseInvoiceCodeRule;
import org.jeecg.modules.business.domain.purchase.invoice.InvoiceData;
import org.jeecg.modules.business.domain.purchase.invoice.PurchaseInvoice;
import org.jeecg.modules.business.domain.purchase.invoice.PurchaseInvoiceEntry;
import org.jeecg.modules.business.entity.*;
import org.jeecg.modules.business.mapper.*;
import org.jeecg.modules.business.service.*;
import org.jeecg.modules.business.vo.OrderContentEntry;
import org.jeecg.modules.business.vo.PromotionDetail;
import org.jeecg.modules.business.vo.PromotionHistoryEntry;
import org.jeecg.modules.business.vo.SkuQuantity;
import org.jeecg.modules.business.vo.*;
import org.jeecg.modules.business.vo.clientPlatformOrder.section.OrdersStatisticData;
import org.jeecg.modules.message.handle.enums.SendMsgTypeEnum;
import org.jeecg.modules.message.util.PushMsgUtil;
@ -41,6 +40,7 @@ import java.util.stream.Collectors;
* @Date: 2021-04-03
* @Version: V1.0
*/
@Slf4j
@Service
public class PurchaseOrderServiceImpl extends ServiceImpl<PurchaseOrderMapper, PurchaseOrder> implements IPurchaseOrderService {
private final PurchaseOrderMapper purchaseOrderMapper;
@ -55,7 +55,9 @@ public class PurchaseOrderServiceImpl extends ServiceImpl<PurchaseOrderMapper, P
private final IPlatformOrderService platformOrderService;
private final PlatformOrderMapper platformOrderMapper;
private final IPlatformOrderContentService platformOrderContentService;
private final IShippingInvoiceService shippingInvoiceService;
private final ISkuService skuService;
private final ICurrencyService currencyService;
/**
* Directory where payment documents are put
@ -68,6 +70,12 @@ public class PurchaseOrderServiceImpl extends ServiceImpl<PurchaseOrderMapper, P
@Value("${jeecg.path.purchaseInvoiceDir}")
private String INVOICE_DIR;
@Value("${jeecg.path.shippingInvoiceDetailDir}")
private String INVOICE_DETAIL_DIR;
@Value("${jeecg.path.shippingInvoicePdfDir}")
private String INVOICE_PDF_DIR;
@Value("${jeecg.path.shippingInvoiceDetailPdfDir}")
private String INVOICE_DETAIL_PDF_DIR;
@Autowired
private PushMsgUtil pushMsgUtil;
@ -77,7 +85,7 @@ public class PurchaseOrderServiceImpl extends ServiceImpl<PurchaseOrderMapper, P
SkuPromotionHistoryMapper skuPromotionHistoryMapper, IClientService clientService,
IPlatformOrderService platformOrderService, PlatformOrderMapper platformOrderMapper,
IPlatformOrderContentService platformOrderContentService, ISkuService skuService,
ExchangeRatesMapper exchangeRatesMapper) {
ExchangeRatesMapper exchangeRatesMapper, IShippingInvoiceService shippingInvoiceService, ICurrencyService currencyService) {
this.purchaseOrderMapper = purchaseOrderMapper;
this.purchaseOrderContentMapper = purchaseOrderContentMapper;
this.skuPromotionHistoryMapper = skuPromotionHistoryMapper;
@ -87,6 +95,8 @@ public class PurchaseOrderServiceImpl extends ServiceImpl<PurchaseOrderMapper, P
this.platformOrderContentService = platformOrderContentService;
this.skuService = skuService;
this.exchangeRatesMapper = exchangeRatesMapper;
this.shippingInvoiceService = shippingInvoiceService;
this.currencyService = currencyService;
}
@Override
@ -138,18 +148,23 @@ public class PurchaseOrderServiceImpl extends ServiceImpl<PurchaseOrderMapper, P
@Override
@Transactional
public void delMain(String id) {
String invoiceNumber = purchaseOrderMapper.getInvoiceNumber(id);
purchaseOrderContentMapper.deleteByMainId(id);
skuPromotionHistoryMapper.deleteByMainId(id);
purchaseOrderMapper.deleteById(id);
platformOrderService.removePurchaseInvoiceNumber(invoiceNumber);
}
@Override
@Transactional
public void delBatchMain(Collection<? extends Serializable> idList) {
for (Serializable id : idList) {
String invoiceNumber = purchaseOrderMapper.getInvoiceNumber(id.toString());
purchaseOrderContentMapper.deleteByMainId(id.toString());
skuPromotionHistoryMapper.deleteByMainId(id.toString());
purchaseOrderMapper.deleteById(id);
platformOrderService.removePurchaseInvoiceNumber(invoiceNumber);
}
}
@ -165,6 +180,114 @@ public class PurchaseOrderServiceImpl extends ServiceImpl<PurchaseOrderMapper, P
page.setTotal(total);
}
@Override
@Transactional
public void cancelInvoice(String purchaseId, String invoiceNumber) {
String invoiceEntity = clientService.getClientFromPurchase(purchaseId).getInvoiceEntity();
platformOrderService.removePurchaseInvoiceNumber(invoiceNumber);
purchaseOrderMapper.deleteInvoice(invoiceNumber);
List<Path> invoicePathList = shippingInvoiceService.getPath(INVOICE_DIR, invoiceNumber, invoiceEntity);
List<Path> detailPathList = shippingInvoiceService.getPath(INVOICE_DETAIL_DIR, invoiceNumber, invoiceEntity);
boolean invoiceDeleted = false, detailDeleted = false;
if(invoicePathList.isEmpty()) {
log.error("FILE NOT FOUND : " + invoiceNumber);
} else {
for (Path path : invoicePathList) {
log.info(path.toString());
}
try {
File invoiceFile = new File(invoicePathList.get(0).toString());
if(invoiceFile.delete()) {
log.info("Invoice file {} delete successful.", invoicePathList.get(0).toString());
invoiceDeleted = true;
} else {
log.error("Invoice file delete fail.");
}
} catch (Exception e) {
e.printStackTrace();
}
}
if(detailPathList.isEmpty()) {
log.error("DETAIL FILE NOT FOUND : " + invoiceNumber);
} else {
for (Path path : detailPathList) {
log.info(path.toString());
}
try {
File detailFile = new File(detailPathList.get(0).toString());
if(detailFile.delete()) {
log.info("Detail file {} delete successful.", detailPathList.get(0).toString());
detailDeleted = true;
} else {
log.error("Detail file delete fail.");
}
} catch (Exception e) {
e.printStackTrace();
}
}
log.info("Invoice cancel successful." + (invoiceDeleted ? "" : " Failed to delete invoice file.") + (detailDeleted ? "" : " Failed to delete detail file."));
}
@Transactional
@Override
public void cancelBatchInvoice(String purchaseIds) {
List<String> purchaseIdList = Arrays.asList(purchaseIds.split(","));
List<PurchaseOrder> purchaseOrders = purchaseOrderMapper.selectBatchIds(purchaseIdList);
List<String> invoiceNumbers = purchaseOrders.stream().map(PurchaseOrder::getInvoiceNumber).collect(Collectors.toList());
log.info("Cancelling invoices : {}", invoiceNumbers);
platformOrderService.removePurchaseInvoiceNumbers(invoiceNumbers);
cancelBatchInvoice(invoiceNumbers);
purchaseOrderContentMapper.deleteFromPurchaseIds(purchaseIdList);
log.info("Deleting invoice files ...");
for(PurchaseOrder purchaseOrder : purchaseOrders) {
if(purchaseOrder.getInvoiceNumber() == null)
continue;
String invoiceNumber = purchaseOrder.getInvoiceNumber();
String invoiceEntity = clientService.getClientEntity(purchaseOrder.getClientId());
List<Path> invoicePathList = shippingInvoiceService.getPath(INVOICE_DIR, invoiceNumber, invoiceEntity);
List<Path> detailPathList = shippingInvoiceService.getPath(INVOICE_DETAIL_DIR, invoiceNumber, invoiceEntity);
if(invoicePathList.isEmpty()) {
log.error("FILE NOT FOUND : " + invoiceNumber + ", " + invoiceEntity);
} else {
for (Path path : invoicePathList) {
log.info(path.toString());
}
try {
File invoiceFile = new File(invoicePathList.get(0).toString());
if(invoiceFile.delete()) {
log.info("Invoice file {} delete successful.", invoicePathList.get(0).toString());
} else {
log.error("Invoice file delete fail.");
}
} catch (Exception e) {
e.printStackTrace();
}
}
if(detailPathList.isEmpty()) {
log.error("DETAIL FILE NOT FOUND : " + invoiceNumber + ", " + invoiceEntity);
} else {
for (Path path : detailPathList) {
log.info(path.toString());
}
try {
File detailFile = new File(detailPathList.get(0).toString());
if(detailFile.delete()) {
log.info("Detail file {} delete successful.", detailPathList.get(0).toString());
} else {
log.error("Detail file {} delete fail.", detailPathList.get(0).toString());
}
} catch (Exception e) {
e.printStackTrace();
}
}
System.gc();
}
log.info("End of invoice files deletion.");
}
@Transactional
@Override
public void confirmPayment(String purchaseID) {
@ -233,7 +356,16 @@ public class PurchaseOrderServiceImpl extends ServiceImpl<PurchaseOrderMapper, P
Objects.requireNonNull(platformOrderIDs);
Client client = clientService.getCurrentClient();
if(client == null) {
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
if(sysUser.getUsername().equals("admin")) {
String poId = platformOrderIDs.get(0);
client = clientService.getClientFromOrder(poId);
}
else
throw new UserException("User is not a client");
}
String currencyId = currencyService.getIdByCode(client.getCurrency());
List<OrderContentDetail> details = platformOrderService.searchPurchaseOrderDetail(skuQuantities);
OrdersStatisticData data = OrdersStatisticData.makeData(details, null);
@ -245,8 +377,8 @@ public class PurchaseOrderServiceImpl extends ServiceImpl<PurchaseOrderMapper, P
purchaseOrderMapper.addPurchase(
purchaseID,
client.fullName(),
currencyId,
client.getId(),
client.getCurrency(),
data.getEstimatedTotalPrice(),
data.getReducedAmount(),
data.finalAmount(),
@ -275,7 +407,6 @@ public class PurchaseOrderServiceImpl extends ServiceImpl<PurchaseOrderMapper, P
.filter(orderContentDetail -> orderContentDetail.getSkuDetail().getPromotion() != Promotion.ZERO_PROMOTION)
.map(orderContentDetail -> {
String promotion = orderContentDetail.getSkuDetail().getPromotion().getId();
System.out.println(promotion);
int count = orderContentDetail.promotionCount();
return new PromotionHistoryEntry(promotion, count);
}).collect(Collectors.toList());
@ -327,13 +458,13 @@ public class PurchaseOrderServiceImpl extends ServiceImpl<PurchaseOrderMapper, P
OrdersStatisticData data = OrdersStatisticData.makeData(details, null);
String purchaseID = UUID.randomUUID().toString();
String currencyId = currencyService.getIdByCode(client.getCurrency());
// 1. save purchase itself
purchaseOrderMapper.addPurchase(
purchaseID,
username,
currencyId,
client.getId(),
client.getCurrency(),
data.getEstimatedTotalPrice(),
data.getReducedAmount(),
data.finalAmount(),
@ -362,7 +493,6 @@ public class PurchaseOrderServiceImpl extends ServiceImpl<PurchaseOrderMapper, P
.filter(orderContentDetail -> orderContentDetail.getSkuDetail().getPromotion() != Promotion.ZERO_PROMOTION)
.map(orderContentDetail -> {
String promotion = orderContentDetail.getSkuDetail().getPromotion().getId();
System.out.println(promotion);
int count = orderContentDetail.promotionCount();
return new PromotionHistoryEntry(promotion, count);
}).collect(Collectors.toList());
@ -450,22 +580,29 @@ public class PurchaseOrderServiceImpl extends ServiceImpl<PurchaseOrderMapper, P
}
@Override
public InvoiceData makeInvoice(String purchaseID) throws IOException, URISyntaxException {
public InvoiceMetaData makeInvoice(String purchaseID) throws IOException, URISyntaxException {
Client client = clientService.getCurrentClient();
if(client == null) {
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
if (sysUser.getUsername().equals("admin")) {
client = clientService.getClientFromPurchase(purchaseID);
}
}
List<PurchaseInvoiceEntry> purchaseOrderSkuList = purchaseOrderContentMapper.selectInvoiceDataByID(purchaseID);
List<PromotionDetail> promotionDetails = skuPromotionHistoryMapper.selectPromotionByPurchase(purchaseID);
String invoiceCode = purchaseOrderMapper.selectById(purchaseID).getInvoiceNumber();
BigDecimal eurToUsd = exchangeRatesMapper.getLatestExchangeRate("EUR", "USD");
String filename = "Invoice N°" + invoiceCode + " (" + client.getInvoiceEntity() + ").xlsx";
Path template = Paths.get(INVOICE_TEMPLATE);
Path newInvoice = Paths.get(INVOICE_DIR, invoiceCode + ".xlsx");
Path newInvoice = Paths.get(INVOICE_DIR, filename);
if (Files.notExists(newInvoice)) {
Files.copy(template, newInvoice);
PurchaseInvoice pv = new PurchaseInvoice(client, invoiceCode, "Purchase Invoice", purchaseOrderSkuList, promotionDetails, eurToUsd);
pv.toExcelFile(newInvoice);
return new InvoiceData(pv.client().getInvoiceEntity(), invoiceCode);
return new InvoiceMetaData(filename,invoiceCode, pv.client().getInternalCode(), pv.client().getInvoiceEntity(), "");
}
return new InvoiceData(client.getInvoiceEntity(), invoiceCode);
return new InvoiceMetaData(filename, invoiceCode, client.getInternalCode(), client.getInvoiceEntity(), "");
}
@Override
@ -488,4 +625,19 @@ public class PurchaseOrderServiceImpl extends ServiceImpl<PurchaseOrderMapper, P
public void cancelBatchInvoice(List<String> invoiceNumbers) {
purchaseOrderMapper.deleteBatchInvoice(invoiceNumbers);
}
@Override
public String getInvoiceId(String invoiceNumber) {
return purchaseOrderMapper.getInvoiceId(invoiceNumber);
}
@Override
public List<PurchaseOrder> getPurchasesByInvoiceNumber(String invoiceNumber) {
return purchaseOrderMapper.getPurchasesByInvoiceNumber(invoiceNumber);
}
@Override
public List<PlatformOrder> getPlatformOrder(String invoiceNumber) {
return purchaseOrderMapper.getPlatformOrder(invoiceNumber);
}
}

View File

@ -0,0 +1,10 @@
package org.jeecg.modules.business.vo;
import lombok.Data;
@Data
public class ShippingFeeBillableOrders {
private String fullName;
private String email;
private String orderNumber;
}

View File

@ -0,0 +1,17 @@
<#include "../components/header.ftl">
<tr>
<td style="padding:35px 0;">Cher Collègue</td>
</tr>
<tr>
<td style="padding:0 0 35px 0;">Un client vient de créer une facture, merci de vérifier les informations liées à la facture :</td>
</tr>
<tr>
<td style="padding:10px 0;"><b>Type de facture :</b> ${invoiceType}</td>
</tr>
<tr>
<td style="padding:10px 0;"><b>Client :</b> ${invoiceEntity}</td>
</tr>
<tr>
<td style="padding:10px 0;"><b>Numéro de facture :</b> <a href="http://app.wia-sourcing.com/business/admin/shippingInvoice/Invoice?invoice=${invoiceNumber}"> ${invoiceNumber} </a></td>
</tr>
<#include "../components/footer.ftl">

View File

@ -0,0 +1,20 @@
<#include "../components/header.ftl">
<tr>
<td style="padding:35px 0;">Cher(e) ${fullName},</td>
</tr>
<tr>
<td style="padding:0 0 20px 0;">Vous pouvez dès à présent facturer les frais de livraisons pour <span style="color:#0B49A6;font-weight:bold">${orderNumbers?size}</span> commande<#if orderNumbers?size &gt; 1>s</#if> :</td>
</tr>
<tr>
<td>
<ul>
<#list orderNumbers as orderNumber>
<li>${orderNumber}</li>
</#list>
</ul>
</td>
</tr>
<tr>
<td style="padding:0 0 35px 0;">Pour toute information complémentaire nous vous invitons à vous rapprocher de votre conseiller.</td>
</tr>
<#include "../components/footer.ftl">