feature: cancel invoice

fix : orders invoiced twice
pull/6221/head
Gauthier LO 2023-08-01 12:09:02 +02:00
parent f999fc3a25
commit d2ddab74a1
22 changed files with 183 additions and 16 deletions

View File

@ -323,9 +323,9 @@ public class InvoiceController {
}
@GetMapping(value = "/downloadInvoiceDetail")
public byte[] downloadInvoiceDetail(@RequestParam("invoiceNumber") String invoiceNumber) throws IOException {
public byte[] downloadInvoiceDetail(@RequestParam("invoiceNumber") String invoiceNumber, @RequestParam("invoiceEntity") String invoiceEntity) throws IOException {
List<FactureDetail> res = shippingInvoiceService.getInvoiceDetail(invoiceNumber);
return shippingInvoiceService.exportToExcel(res, invoiceNumber);
return shippingInvoiceService.exportToExcel(res, invoiceNumber, invoiceEntity);
}
@GetMapping(value = "/breakdown/byShop")

View File

@ -17,8 +17,7 @@ import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.business.entity.Client;
import org.jeecg.modules.business.entity.ShippingInvoice;
import org.jeecg.modules.business.service.EmailService;
import org.jeecg.modules.business.service.IShippingInvoiceService;
import org.jeecg.modules.business.service.*;
import org.jeecg.modules.business.vo.ShippingInvoicePage;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
@ -70,6 +69,14 @@ import java.util.stream.Stream;
@RequestMapping("/generated/shippingInvoice")
@Slf4j
public class ShippingInvoiceController {
@Autowired
private IClientService clientService;
@Autowired
private IPlatformOrderContentService platformOrderContentService;
@Autowired
private IPlatformOrderService platformOrderService;
@Autowired
private ISavRefundService savRefundService;
@Autowired
private IShippingInvoiceService shippingInvoiceService;
@Autowired
@ -296,6 +303,30 @@ public class ShippingInvoiceController {
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
@ -471,4 +502,55 @@ public class ShippingInvoiceController {
log.info("Found client for invoice {} : {}", invoiceNumber, client.fullName());
return Result.OK(client);
}
/**
* Deletes an invoice
* @param invoiceNumber invoice number to cancel
* @return if update successful
*/
@PostMapping(value = "/cancelInvoice")
public Result<?> cancelInvoice(@RequestParam("id") String id, @RequestParam("invoiceNumber") String invoiceNumber, @RequestParam("clientId") String clientId) {
log.info("Cancelling invoice number : {}", invoiceNumber);
platformOrderContentService.cancelInvoice(invoiceNumber);
platformOrderService.cancelInvoice(invoiceNumber);
savRefundService.cancelInvoice(invoiceNumber);
shippingInvoiceService.delMain(id);
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);
if(invoicePathList.isEmpty() ||detailPathList.isEmpty()) {
log.error("FILE NOT FOUND : " + invoiceNumber);
return Result.ok("Invoice canceled, but file not found.");
}
else {
for (Path path : invoicePathList) {
log.info(path.toString());
}
for (Path path : detailPathList) {
log.info(path.toString());
}
try {
File invoiceFile = new File(invoicePathList.get(0).toString());
File detailFile = new File(detailPathList.get(0).toString());
if(invoiceFile.delete()) {
log.info("Invoice file {} delete successful.", invoicePathList.get(0).toString());
} else {
log.error("Invoice file delete fail.");
return Result.error("Invoice file delete fail.");
}
if(detailFile.delete()) {
log.info("Detail file {} delete successful.", detailPathList.get(0).toString());
} else {
log.error("Detail file delete fail.");
return Result.error("Detail file delete fail.");
}
} catch (Exception e) {
e.printStackTrace();
return Result.error(e.getMessage());
}
}
log.info("Invoice files deleted.");
return Result.ok("Invoice cancel successful.");
}
}

View File

@ -387,7 +387,7 @@ public class ShippingInvoiceFactory {
List<SavRefundWithDetail> savRefunds,
String subject, boolean skipShippingTimeComparing) throws UserException {
log.info("Orders to be invoiced: {}", orderAndContent);
if (orderAndContent == null) {
if (orderAndContent == null || orderAndContent.size() == 0) {
throw new UserException("No platform order in the selected period!");
}
Map<String, BigDecimal> skuRealWeights = new HashMap<>();
@ -397,7 +397,7 @@ public class ShippingInvoiceFactory {
Map<LogisticChannel, List<LogisticChannelPrice>> channelPriceMap;
Map<String, LogisticChannel> logisticChannelMap = logisticChannelMapper.getAll().stream()
.collect(toMap(LogisticChannel::getId, Function.identity()));
if(subject.contains("Pre") || subject.contains("All")) {
if(subject.contains("order time")) {
channelPriceMap = getChannelPriceMap(logisticChannelMap, orderAndContent, skipShippingTimeComparing, "order");
}
else {

View File

@ -50,6 +50,12 @@ public class ShippingInvoice implements Serializable {
*/
@ApiModelProperty(value = "更新人")
private String updateBy;
/**
* ID
*/
@Excel(name = "客户", width = 15)
@ApiModelProperty(value = "客户")
private String clientId;
/**
*
*/
@ -103,6 +109,9 @@ public class ShippingInvoice implements Serializable {
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
public void setClientI(String clientId) {
this.clientId = clientId;
}
public void setInvoiceNumber(String invoiceNumber) {
this.invoiceNumber = invoiceNumber;
}
@ -135,6 +144,7 @@ public class ShippingInvoice implements Serializable {
Date createTime,
String updateBy,
Date updateTime,
String clientId,
String invoiceNumber,
BigDecimal totalAmount,
BigDecimal discountAmount,
@ -145,6 +155,7 @@ public class ShippingInvoice implements Serializable {
this.createTime = createTime;
this.updateBy = updateBy;
this.updateTime = updateTime;
this.clientId = clientId;
this.invoiceNumber = invoiceNumber;
this.totalAmount = totalAmount;
this.discountAmount = discountAmount;
@ -153,12 +164,13 @@ public class ShippingInvoice implements Serializable {
}
public static ShippingInvoice of(
String username,
String clientId,
String invoiceNumber,
BigDecimal totalAmount,
BigDecimal discountAmount,
BigDecimal paidAmount
) {
return new ShippingInvoice(null, username, new Date(), username, new Date(),
return new ShippingInvoice(null, username, new Date(), username, new Date(), clientId,
invoiceNumber, totalAmount, discountAmount, totalAmount.subtract(discountAmount), paidAmount);
}
}

View File

@ -1,6 +1,7 @@
package org.jeecg.modules.business.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.jeecg.modules.business.entity.Client;
import org.springframework.stereotype.Repository;
@ -13,4 +14,5 @@ import org.springframework.stereotype.Repository;
@Repository
public interface ClientMapper extends BaseMapper<Client> {
String getClientEntity(@Param("id") String id);
}

View File

@ -73,4 +73,5 @@ public interface PlatformOrderContentMapper extends BaseMapper<PlatformOrderCont
List<PlatformOrderContent> findUninvoicedShippedOrderContents();
List<PlatformOrderContent> fetchPlatformOrderContentsToArchive(@Param("orderIDs") List<String> orderIDs);
void insertPlatformOrderContentsArchives(@Param("orderContents") List<PlatformOrderContent> platformOrderContents);
void cancelInvoice(@Param("invoiceNumber") String invoiceNumber);
}

View File

@ -181,4 +181,5 @@ public interface PlatformOrderMapper extends BaseMapper<PlatformOrder> {
List<PlatformOrder> fetchOrdersToArchiveBetweenDate(@Param("startDate") String startDate, @Param("endDate") String endDate);
List<PlatformOrder> fetchOrdersToArchiveBeforeDate(@Param("endDate") String endDate);
void insertPlatformOrdersArchives(@Param("orders") List<PlatformOrder> platformOrders);
void cancelInvoice(@Param("invoiceNumber") String invoiceNumber);
}

View File

@ -17,4 +17,5 @@ import java.util.List;
@Repository
public interface SavRefundMapper extends BaseMapper<SavRefund> {
List<BigDecimal> fetchRefundAmount(@Param("invoiceNumber") String invoiceNumber);
void cancelInvoice(@Param("invoiceNumber") String invoiceNumber);
}

View File

@ -1,5 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.jeecg.modules.business.mapper.ClientMapper">
<select id="getClientEntity" parameterType="java.lang.String" resultType="java.lang.String">
SELECT invoice_entity
FROM client
WHERE id = #{id}
</select>
</mapper>

View File

@ -279,4 +279,13 @@
)
</foreach>;
</insert>
<update id="cancelInvoice">
UPDATE platform_order_content
SET purchase_fee = 0.0,
shipping_fee = NULL,
service_fee = NULL,
vat = NULL,
purchase_fee = 0.0
WHERE platform_order_id IN (SELECT id FROM platform_order WHERE shipping_invoice_number = #{invoiceNumber});
</update>
</mapper>

View File

@ -464,7 +464,8 @@
SELECT po.id
FROM platform_order po
JOIN logistic_channel lc ON po.logistic_channel_name = lc.zh_name
WHERE po.shop_id IN
WHERE shipping_invoice_number IS NULL
AND po.shop_id IN
<foreach
collection="shops"
separator=","
@ -493,7 +494,8 @@
SELECT po.id
FROM platform_order po
JOIN logistic_channel lc ON po.logistic_channel_name = lc.zh_name
WHERE po.shop_id IN
WHERE shipping_invoice_number IS NULL
AND po.shop_id IN
<foreach
collection="shops"
separator=","
@ -587,4 +589,14 @@
)
</foreach>;
</insert>
<update id="cancelInvoice">
UPDATE platform_order
SET fret_fee = NULL,
order_service_fee = NULL,
shipping_invoice_number = NULL,
picking_fee = 0.0,
packaging_material_fee = 0.0
WHERE shipping_invoice_number = #{invoiceNumber};
</update>
</mapper>

View File

@ -6,4 +6,11 @@
FROM sav_refund s
WHERE s.invoice_number = #{invoiceNumber}
</select>
<update id="cancelInvoice">
UPDATE sav_refund
SET invoice_number = NULL,
refund_date = NULL,
total_refund_amount = 0.0
WHERE invoice_number = #{invoiceNumber};
</update>
</mapper>

View File

@ -37,7 +37,7 @@ public interface IClientService extends IService<Client> {
*
*/
public void delBatchMain (Collection<? extends Serializable> idList);
public String getClientEntity(String id);
/**
* Get current user's client information
* @return client or null if current user's role is not client

View File

@ -42,4 +42,10 @@ public interface IPlatformOrderContentService extends IService<PlatformOrderCont
*/
List<PlatformOrderContent> fetchPlatformOrderContentsToArchive(List<String> orderIDs);
void savePlatformOrderContentArchive(List<PlatformOrderContent> platformOrderContents);
/**
* Cancels an invoice
* @param invoiceNumber
*/
void cancelInvoice(String invoiceNumber);
}

View File

@ -165,4 +165,10 @@ public interface IPlatformOrderService extends IService<PlatformOrder> {
* @param platformOrders list of platform orders
*/
void savePlatformOrderArchive(List<PlatformOrder> platformOrders);
/**
* Cancel Invoice
* @param invoiceNumber
*/
void cancelInvoice(String invoiceNumber);
}

View File

@ -13,5 +13,9 @@ import java.util.List;
* @Version: V1.0
*/
public interface ISavRefundService extends IService<SavRefund> {
List<BigDecimal> getRefundAmount(String invoiceNumber);
List<BigDecimal> getRefundAmount(String invoiceNumber);/**
* Cancel Invoice
* @param invoiceNumber
*/
void cancelInvoice(String invoiceNumber);
}

View File

@ -258,13 +258,14 @@ public class PlatformOrderShippingInvoiceService {
// save to DB
org.jeecg.modules.business.entity.ShippingInvoice shippingInvoiceEntity = org.jeecg.modules.business.entity.ShippingInvoice.of(
username,
invoice.client().getId(),
invoice.code(),
invoice.getTotalAmount(),
invoice.reducedAmount(),
invoice.paidAmount()
);
shippingInvoiceMapper.insert(shippingInvoiceEntity);
return new InvoiceMetaData(filename, invoice.code());
return new InvoiceMetaData(filename, invoice.code(), invoice.client().getInvoiceEntity());
}
/**
@ -317,7 +318,7 @@ public class PlatformOrderShippingInvoiceService {
return factureDetailMapper.selectList(queryWrapper);
}
public byte[] exportToExcel(List<FactureDetail> details, String invoiceNumber) throws IOException {
public byte[] exportToExcel(List<FactureDetail> details, String invoiceNumber, String invoiceEntity) throws IOException {
SheetManager sheetManager = SheetManager.createXLSX();
for (String title : titles) {
sheetManager.write(title);
@ -370,15 +371,16 @@ public class PlatformOrderShippingInvoiceService {
sheetManager.nextRow();
}
Path target = Paths.get(INVOICE_DETAIL_DIR, "Détail_calcul_de_facture_" + invoiceNumber + ".xlsx");
Path target = Paths.get(INVOICE_DETAIL_DIR, "Détail_calcul_de_facture_" + invoiceNumber + "_(" + invoiceEntity + ").xlsx");
int i = 2;
while (Files.exists(target)) {
target = Paths.get(INVOICE_DETAIL_DIR, "Détail_calcul_de_facture_" + invoiceNumber + "_" + i + ".xlsx");
target = Paths.get(INVOICE_DETAIL_DIR, "Détail_calcul_de_facture_" + invoiceNumber + "_(" + invoiceEntity + ")_" + i + ".xlsx");
i++;
}
Files.createFile(target);
sheetManager.export(target);
sheetManager.getWorkbook().close();
System.gc();
return Files.readAllBytes(target);
}
}

View File

@ -117,4 +117,8 @@ public class ClientServiceImpl extends ServiceImpl<ClientMapper, Client> impleme
return clientUserMap.selectClientByUserId(sysUser.getId());
}
@Override
public String getClientEntity(String id) {
return clientMapper.getClientEntity(id);
}
}

View File

@ -62,4 +62,8 @@ public class PlatformOrderContentServiceImpl extends ServiceImpl<PlatformOrderCo
public void savePlatformOrderContentArchive(List<PlatformOrderContent> platformOrderContents) {
platformOrderContentMapper.insertPlatformOrderContentsArchives(platformOrderContents);
}
@Override
public void cancelInvoice(String invoiceNumber) {
platformOrderContentMapper.cancelInvoice(invoiceNumber);
}
}

View File

@ -378,4 +378,8 @@ public class PlatformOrderServiceImpl extends ServiceImpl<PlatformOrderMapper, P
public void savePlatformOrderArchive(List<PlatformOrder> platformOrders) {
platformOrderMap.insertPlatformOrdersArchives(platformOrders);
}
@Override
public void cancelInvoice(String invoiceNumber) {
platformOrderMap.cancelInvoice(invoiceNumber);
}
}

View File

@ -32,4 +32,8 @@ public class SavRefundServiceImpl extends ServiceImpl<SavRefundMapper, SavRefund
public List<BigDecimal> getRefundAmount(String invoiceNumber) {
return savRefundMapper.fetchRefundAmount(invoiceNumber);
}
@Override
public void cancelInvoice(String invoiceNumber) {
savRefundMapper.cancelInvoice(invoiceNumber);
}
}

View File

@ -8,4 +8,6 @@ public class InvoiceMetaData {
private final String filename;
private final String invoiceCode;
private final String invoiceEntity;
}