mirror of https://github.com/jeecgboot/jeecg-boot
feat: client invoicing page optimization with filters etc..
parent
aab90a0e2c
commit
b8124a880f
|
@ -529,10 +529,15 @@ public class InvoiceController {
|
|||
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
|
||||
@RequestParam(name = "pageSize", defaultValue = "50") Integer pageSize,
|
||||
@RequestParam(name = "column", defaultValue = "order_time") String column,
|
||||
@RequestParam(name = "order", defaultValue = "ASC") String order) {
|
||||
@RequestParam(name = "order", defaultValue = "ASC") String order,
|
||||
@RequestParam(name ="shippingAvailable[]", required = false) List<Integer> shippingAvailable,
|
||||
@RequestParam(name ="purchaseAvailable[]", required = false) List<Integer> purchaseAvailable,
|
||||
@RequestParam(name = "productAvailable[]", required = false) List<Integer> productAvailable
|
||||
) {
|
||||
log.info("User : {} is requesting uninvoiced orders for shops : [{}]",
|
||||
((LoginUser) SecurityUtils.getSubject().getPrincipal()).getUsername(),
|
||||
shopIds);
|
||||
List<Integer> productStatuses = productAvailable == null || productAvailable.isEmpty() ? Arrays.asList(Integer.valueOf(PlatformOrderFront.productStatus.Unavailable.code), Integer.valueOf(PlatformOrderFront.productStatus.Available.code), Integer.valueOf(PlatformOrderFront.productStatus.Ordered.code)) : productAvailable;
|
||||
String parsedColumn = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, column.replace("_dictText",""));
|
||||
String parsedOrder = order.toUpperCase();
|
||||
if(!parsedOrder.equals("ASC") && !parsedOrder.equals("DESC")) {
|
||||
|
@ -545,158 +550,15 @@ public class InvoiceController {
|
|||
e.printStackTrace();
|
||||
return Result.error("Error 400 : Bad Request");
|
||||
}
|
||||
// checking shipping data availability
|
||||
// // checking shipping data availability
|
||||
List<String> shopIdList = Arrays.asList(shopIds.split(","));
|
||||
// fetch order that can be invoiced either by shipping or purchase or both
|
||||
List<PlatformOrder> allOrders = platformOrderService.findUninvoicedOrdersByShopForClient(shopIdList, Collections.singletonList(1), parsedColumn, parsedOrder, 1, -1);
|
||||
int total = allOrders.size();
|
||||
List<PlatformOrder> orders = platformOrderService.findUninvoicedOrdersByShopForClient(shopIdList, Collections.singletonList(1), parsedColumn, parsedOrder, pageNo, pageSize);
|
||||
// LinkedList<PlatformOrder> sortedOrders = orders.stream().sorted(Comparator.comparing(PlatformOrder::getOrderTime)).collect(Collectors.toCollection(LinkedList::new));
|
||||
if(orders.isEmpty())
|
||||
return Result.OK("No order to invoice.");
|
||||
Map<String, String> shops = shopService.listByIds(shopIdList).stream().collect(Collectors.toMap(Shop::getId, Shop::getName));
|
||||
List<String> orderIds = orders.stream().map(PlatformOrder::getId).collect(Collectors.toList());
|
||||
Map<PlatformOrder, List<PlatformOrderContent>> orderContentMap = platformOrderService.fetchOrderData(orderIds);
|
||||
// some orders may not have content, so we have to re-add them
|
||||
if(orderIds.size() != orderContentMap.size()) {
|
||||
List<String> orderIdsInMap = orderContentMap.keySet().stream().map(PlatformOrder::getId).collect(Collectors.toList());
|
||||
List<String> orderIdsWithoutContent = orderIds.stream().filter(id -> !orderIdsInMap.contains(id)).collect(Collectors.toList());
|
||||
List<PlatformOrder> ordersWithoutContent = platformOrderService.listByIds(orderIdsWithoutContent);
|
||||
Map<PlatformOrder, List<PlatformOrderContent>> orderContentMapWithoutContent = new HashMap<>();
|
||||
for(PlatformOrder po : ordersWithoutContent) {
|
||||
orderContentMapWithoutContent.put(po, new ArrayList<>());
|
||||
}
|
||||
orderContentMap.putAll(orderContentMapWithoutContent);
|
||||
}
|
||||
|
||||
Map<String, String> errorMapToOrderId = new HashMap<>();
|
||||
List<PlatformOrderFront> orderFronts = new ArrayList<>();
|
||||
|
||||
for(Map.Entry<PlatformOrder, List<PlatformOrderContent>> entry : orderContentMap.entrySet()) {
|
||||
PlatformOrderFront orderFront = new PlatformOrderFront();
|
||||
BeanUtils.copyProperties(entry.getKey(), orderFront);
|
||||
|
||||
//rename shop id by shop name to prevent it to leak in front
|
||||
orderFront.setShopId(shops.get(orderFront.getShopId()));
|
||||
// set default value of shipping and purchase availability
|
||||
orderFront.setShippingAvailable(Available.code);
|
||||
orderFront.setPurchaseAvailable(Available.code);
|
||||
|
||||
if(entry.getValue().isEmpty()) {
|
||||
if(!errorMapToOrderId.containsKey(entry.getKey().getPlatformOrderId()))
|
||||
errorMapToOrderId.put(entry.getKey().getPlatformOrderId(), "Error : order has no content : " + entry.getKey().getPlatformOrderId());
|
||||
else
|
||||
errorMapToOrderId.put(entry.getKey().getPlatformOrderId(), errorMapToOrderId.get(entry.getKey().getPlatformOrderId()) + " and has no content");
|
||||
orderFront.setShippingAvailable(Unavailable.code);
|
||||
orderFront.setPurchaseAvailable(Unavailable.code);
|
||||
orderFronts.add(orderFront);
|
||||
continue;
|
||||
}
|
||||
|
||||
List<String> skuIds = entry.getValue().stream().map(PlatformOrderContent::getSkuId).distinct().collect(Collectors.toList());
|
||||
// finds the first sku that isn't in db
|
||||
List<Sku> skuIdsFound = skuService.listByIds(skuIds);
|
||||
if(skuIdsFound.size() != skuIds.size()) {
|
||||
if(!errorMapToOrderId.containsKey(entry.getKey().getPlatformOrderId()))
|
||||
errorMapToOrderId.put(entry.getKey().getPlatformOrderId(), "Error : Missing one or more sku in db for order : " + entry.getKey().getPlatformOrderId());
|
||||
else
|
||||
errorMapToOrderId.put(entry.getKey().getPlatformOrderId(), errorMapToOrderId.get(entry.getKey().getPlatformOrderId()) + " and missing one or more sku in db");
|
||||
|
||||
orderFront.setShippingAvailable(Unavailable.code);
|
||||
orderFront.setPurchaseAvailable(Unavailable.code);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(entry.getKey().getShippingInvoiceNumber() == null) {
|
||||
// checks if logistic channel is missing
|
||||
if(entry.getKey().getLogisticChannelName().isEmpty() && entry.getKey().getInvoiceLogisticChannelName() == null) {
|
||||
if(!errorMapToOrderId.containsKey(entry.getKey().getPlatformOrderId()))
|
||||
errorMapToOrderId.put(entry.getKey().getPlatformOrderId(), "Error : Missing logistic channel for order : " + entry.getKey().getPlatformOrderId());
|
||||
else
|
||||
errorMapToOrderId.put(entry.getKey().getPlatformOrderId(), errorMapToOrderId.get(entry.getKey().getPlatformOrderId()) + " and missing logistic channel");
|
||||
orderFront.setShippingAvailable(Unavailable.code);
|
||||
}
|
||||
// finds the first product with missing weight
|
||||
String missingWeightSkuId = skuWeightService.searchFirstEmptyWeightSku(skuIds);
|
||||
if(missingWeightSkuId != null) {
|
||||
if(!errorMapToOrderId.containsKey(entry.getKey().getPlatformOrderId()))
|
||||
errorMapToOrderId.put(entry.getKey().getPlatformOrderId(), "Error : Missing one or more weight for order : " + entry.getKey().getPlatformOrderId());
|
||||
else
|
||||
errorMapToOrderId.put(entry.getKey().getPlatformOrderId(), errorMapToOrderId.get(entry.getKey().getPlatformOrderId()) + " and missing weight");
|
||||
orderFront.setShippingAvailable(Unavailable.code);
|
||||
}
|
||||
}
|
||||
if(entry.getKey().getPurchaseInvoiceNumber() == null) {
|
||||
// finds the first sku with missing price
|
||||
String missingPriceSkuId = skuService.searchFirstMissingPriceSku(skuIds);
|
||||
if(missingPriceSkuId != null) {
|
||||
if(!errorMapToOrderId.containsKey(entry.getKey().getPlatformOrderId()))
|
||||
errorMapToOrderId.put(entry.getKey().getPlatformOrderId(), "Error : Missing one or more sku price for order : " + entry.getKey().getPlatformOrderId());
|
||||
else
|
||||
errorMapToOrderId.put(entry.getKey().getPlatformOrderId(), errorMapToOrderId.get(entry.getKey().getPlatformOrderId()) + " and missing one or more sku price");
|
||||
orderFront.setPurchaseAvailable(Unavailable.code);
|
||||
}
|
||||
}
|
||||
|
||||
// set purchase order status (-1 = unavailable, 0 = available, 1 = invoiced, 2 = paid)
|
||||
if(entry.getKey().getProductAvailable() == null) {
|
||||
orderFront.setProductAvailable(PlatformOrderFront.productStatus.Unavailable.code);
|
||||
entry.getKey().setProductAvailable(PlatformOrderFront.productStatus.Unavailable.code);
|
||||
}
|
||||
if(entry.getKey().getProductAvailable().equals(PlatformOrderFront.productStatus.Unavailable.code)
|
||||
&& entry.getKey().getVirtualProductAvailable().equals(PlatformOrderFront.productStatus.Available.code)
|
||||
&& entry.getKey().getPurchaseInvoiceNumber() == null
|
||||
)
|
||||
orderFront.setProductAvailable(PlatformOrderFront.productStatus.Ordered.code);
|
||||
if(entry.getKey().getPurchaseInvoiceNumber() != null) {
|
||||
PurchaseOrder purchase = purchaseOrderService.getPurchaseByInvoiceNumber(entry.getKey().getPurchaseInvoiceNumber());
|
||||
if(purchase.getPaidAmount().compareTo(BigDecimal.ZERO) == 0)
|
||||
orderFront.setPurchaseAvailable(Invoiced.code);// invoiced
|
||||
else
|
||||
orderFront.setPurchaseAvailable(Paid.code);// paid
|
||||
}
|
||||
// set shipping order status (-1 = unavailable, 0 = available, 1 = invoiced, 2 = paid)
|
||||
if(entry.getKey().getShippingInvoiceNumber() != null) {
|
||||
ShippingInvoice shippingInvoice = iShippingInvoiceService.getShippingInvoice(entry.getKey().getShippingInvoiceNumber());
|
||||
if(shippingInvoice.getPaidAmount().compareTo(BigDecimal.ZERO) == 0) {
|
||||
orderFront.setShippingAvailable(Invoiced.code); // invoiced
|
||||
}
|
||||
else {
|
||||
orderFront.setShippingAvailable(Paid.code); // paid
|
||||
}
|
||||
}
|
||||
orderFronts.add(orderFront);
|
||||
}
|
||||
|
||||
List<String> errorMessages = new ArrayList<>(errorMapToOrderId.values());
|
||||
|
||||
// sorting by order time ascending
|
||||
orderFronts = orderFronts.stream().sorted(Comparator.comparing(PlatformOrderFront::getOrderTime)).collect(Collectors.toList());
|
||||
// system notification
|
||||
String errors = SECTION_START;
|
||||
int max_entries = 100;
|
||||
int current_page = 0;
|
||||
int total_page = (int) Math.ceil((double) errorMessages.size() /max_entries);
|
||||
for(int i = 1; i <= errorMessages.size(); i++) {
|
||||
if(i%max_entries == 1) {
|
||||
errors = SECTION_START;
|
||||
current_page++;
|
||||
}
|
||||
errors = errors.concat("<li>" + i + " : " + errorMessages.get(i-1) +"</li>");
|
||||
if(i%max_entries==0 || i == errorMessages.size()) {
|
||||
errors = errors.concat(SECTION_END);
|
||||
Map<String, String> templateParam = new HashMap<>();
|
||||
templateParam.put("nb_entries", String.valueOf(errorMessages.size()));
|
||||
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", "admin", "Self Service invoicing estimation Errors", templateParam, "expenses_overview_errors");
|
||||
ISysBaseApi.sendTemplateAnnouncement(message);
|
||||
}
|
||||
}
|
||||
List<PlatformOrderFront> orders = platformOrderService.fetchUninvoicedOrdersByShopForClientFullSQL(shopIdList, Collections.singletonList(1), parsedColumn, parsedOrder, pageNo, pageSize,
|
||||
productStatuses, shippingAvailable, purchaseAvailable);
|
||||
int total = orders.get(0).getTotalCount();
|
||||
|
||||
IPage<PlatformOrderFront> page = new Page<>();
|
||||
page.setRecords(orderFronts);
|
||||
page.setRecords(orders);
|
||||
page.setSize(pageSize);
|
||||
page.setCurrent(pageNo);
|
||||
page.setTotal(total);
|
||||
|
|
|
@ -6,10 +6,7 @@ import org.jeecg.modules.business.domain.api.mabang.getorderlist.Order;
|
|||
import org.jeecg.modules.business.domain.api.yd.YDTrackingNumberData;
|
||||
import org.jeecg.modules.business.entity.PlatformOrder;
|
||||
import org.jeecg.modules.business.entity.PlatformOrderShopSync;
|
||||
import org.jeecg.modules.business.vo.OrderKpi;
|
||||
import org.jeecg.modules.business.vo.PlatformOrderOption;
|
||||
import org.jeecg.modules.business.vo.PlatformOrderPage;
|
||||
import org.jeecg.modules.business.vo.ShippingFeeBillableOrders;
|
||||
import org.jeecg.modules.business.vo.*;
|
||||
import org.jeecg.modules.business.vo.clientPlatformOrder.ClientPlatformOrderPage;
|
||||
import org.jeecg.modules.business.vo.clientPlatformOrder.section.OrderQuantity;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
@ -193,7 +190,10 @@ public interface PlatformOrderMapper extends BaseMapper<PlatformOrder> {
|
|||
List<PlatformOrder> findUninvoicedShippingOrdersByShopForClient(@Param("shopIds") List<String> shopIds, @Param("erpStatuses") List<Integer> erpStatuses);
|
||||
List<PlatformOrder> fetchUninvoicedPurchaseOrdersByShopForClient(@Param("shopIds") List<String> shopIds, @Param("erpStatuses") List<Integer> erpStatuses);
|
||||
List<PlatformOrder> findUninvoicedOrdersByShopForClient(@Param("shopIds") List<String> shopIds, @Param("erpStatuses") List<Integer> erpStatuses,
|
||||
@Param("column") String column, @Param("order") String order, @Param("offset") Integer offset, @Param("size") Integer pageSize);
|
||||
@Param("column") String column, @Param("order") String order, @Param("offset") Integer offset, @Param("size") Integer pageSize);
|
||||
List<PlatformOrderFront> fetchUninvoicedOrdersByShopForClientFullSQL(@Param("shopIds") List<String> shopIds, @Param("erpStatuses") List<Integer> erpStatuses,
|
||||
@Param("column") String column, @Param("order") String order, @Param("offset") Integer offset, @Param("size") Integer pageSize,
|
||||
@Param("productStatuses") List<Integer> productStatuses, @Param("shippingStatuses") List<Integer> shippingStatuses, @Param("purchaseStatuses") List<Integer> purchaseStatuses);
|
||||
List<String> findUninvoicedOrderIdsByShopForClient(@Param("shopIds") List<String> shopIds, @Param("erpStatuses") List<Integer> erpStatuses);
|
||||
|
||||
List<PlatformOrder> fetchEmptyLogisticChannelOrders(@Param("startDate") String startDate,@Param("endDate") String endDate);
|
||||
|
|
|
@ -682,6 +682,110 @@
|
|||
</if>
|
||||
;
|
||||
</select>
|
||||
|
||||
<select id="fetchUninvoicedOrdersByShopForClientFullSQL" resultType="org.jeecg.modules.business.vo.PlatformOrderFront">
|
||||
WITH sku_stats AS (
|
||||
SELECT
|
||||
sku.id AS sku_id,
|
||||
COUNT(sw.sku_id) AS weight_count,
|
||||
COUNT(sp.sku_id) AS price_count
|
||||
FROM sku
|
||||
LEFT JOIN sku_weight sw ON sku.id = sw.sku_id
|
||||
LEFT JOIN sku_price sp ON sku.id = sp.sku_id
|
||||
GROUP BY sku.id
|
||||
),
|
||||
uninvoiced_orders AS (
|
||||
SELECT
|
||||
po.id AS id,
|
||||
s.name AS shop_id,
|
||||
po.platform_order_number AS platform_order_number,
|
||||
po.order_time AS order_time,
|
||||
po.country AS country,
|
||||
MIN(
|
||||
CASE
|
||||
WHEN poc.id IS NULL OR sku.id IS NULL THEN -1
|
||||
WHEN po.shipping_invoice_number IS NULL
|
||||
AND (po.logistic_channel_name IS NULL OR po.logistic_channel_name = '')
|
||||
AND (po.invoice_logistic_channel_name IS NULL OR po.invoice_logistic_channel_name = '') THEN -1
|
||||
WHEN po.shipping_invoice_number IS NULL AND stats.weight_count = 0 THEN -1
|
||||
WHEN po.shipping_invoice_number IS NOT NULL AND si.paid_amount > 0.00 THEN 2
|
||||
WHEN po.shipping_invoice_number IS NOT NULL AND si.paid_amount = 0.00 THEN 1
|
||||
ELSE 0
|
||||
END
|
||||
) AS shipping_available,
|
||||
MIN(
|
||||
CASE
|
||||
WHEN po.purchase_invoice_number IS NULL AND stats.price_count = 0 THEN -1
|
||||
WHEN po.purchase_invoice_number IS NOT NULL AND pur.paid_amount > 0.00 THEN 2
|
||||
WHEN po.purchase_invoice_number IS NOT NULL AND pur.paid_amount = 0.00 THEN 1
|
||||
ELSE 0
|
||||
END
|
||||
) AS purchase_available,
|
||||
CASE
|
||||
WHEN po.product_available = 0
|
||||
AND po.virtual_product_available = 1
|
||||
AND po.purchase_invoice_number IS NULL THEN 2
|
||||
ELSE COALESCE(po.product_available, 0)
|
||||
END AS product_available
|
||||
FROM platform_order po
|
||||
JOIN shop s ON po.shop_id = s.id
|
||||
LEFT JOIN platform_order_content poc ON po.id = poc.platform_order_id
|
||||
LEFT JOIN sku ON poc.sku_id = sku.id
|
||||
LEFT JOIN sku_stats stats ON sku.id = stats.sku_id
|
||||
LEFT JOIN purchase_order pur ON pur.invoice_number = po.purchase_invoice_number
|
||||
LEFT JOIN shipping_invoice si ON po.shipping_invoice_number = si.invoice_number
|
||||
WHERE po.erp_status IN
|
||||
<foreach
|
||||
collection="erpStatuses"
|
||||
separator=","
|
||||
open="("
|
||||
close=")"
|
||||
index="index"
|
||||
item="erpStatus"
|
||||
>
|
||||
#{erpStatus}
|
||||
</foreach>
|
||||
AND poc.erp_status <> 5
|
||||
AND (po.shipping_invoice_number IS NULL
|
||||
OR (po.shipping_invoice_number LIKE '%%%%-%%-2%%%'
|
||||
AND po.purchase_invoice_number IS NULL
|
||||
)
|
||||
)
|
||||
AND shop_id IN
|
||||
<foreach
|
||||
collection="shopIds"
|
||||
separator=","
|
||||
open="("
|
||||
close=")"
|
||||
index="index"
|
||||
item="shopId"
|
||||
>
|
||||
#{shopId}
|
||||
</foreach>
|
||||
GROUP BY po.id, po.platform_order_number, po.product_available, po.virtual_product_available, po.purchase_invoice_number
|
||||
)
|
||||
SELECT *, COUNT(*) OVER() AS total_count
|
||||
FROM uninvoiced_orders
|
||||
WHERE
|
||||
product_available IN
|
||||
<foreach collection="productStatuses" separator="," open="(" close=")" index="index" item="productStatus">
|
||||
#{productStatus}
|
||||
</foreach>
|
||||
<if test="shippingStatuses != null">
|
||||
AND shipping_available IN
|
||||
<foreach collection="shippingStatuses" separator="," open="(" close=")" index="index" item="shippingStatus">
|
||||
#{shippingStatus}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="purchaseStatuses != null">
|
||||
AND purchase_available IN
|
||||
<foreach collection="purchaseStatuses" separator="," open="(" close=")" index="index" item="purchaseStatus">
|
||||
#{purchaseStatus}
|
||||
</foreach>
|
||||
</if>
|
||||
ORDER BY ${column} ${order}
|
||||
LIMIT #{offset}, #{size};
|
||||
</select>
|
||||
<insert id="insertPlatformOrdersArchives" parameterType="list">
|
||||
INSERT INTO platform_order_delete(id, create_by,
|
||||
create_time, update_by,
|
||||
|
|
|
@ -219,6 +219,10 @@ public interface IPlatformOrderService extends IService<PlatformOrder> {
|
|||
* @return
|
||||
*/
|
||||
List<PlatformOrder> findUninvoicedOrdersByShopForClient(List<String> shopIds, List<Integer> erpStatuses, String column, String order, Integer pageNo, Integer pageSize);
|
||||
|
||||
List<PlatformOrderFront> fetchUninvoicedOrdersByShopForClientFullSQL(List<String> shopIds, List<Integer> erpStatuses, String column, String order, Integer pageNo, Integer pageSize,
|
||||
List<Integer> productAvailable, List<Integer> shippingAvailable, List<Integer> purchaseAvailable);
|
||||
|
||||
/**
|
||||
* Get ids of all order that can be invoiced by small clients (type 2) themselves.
|
||||
*
|
||||
|
|
|
@ -434,6 +434,12 @@ public class PlatformOrderServiceImpl extends ServiceImpl<PlatformOrderMapper, P
|
|||
int offset = (pageNo - 1) * pageSize;
|
||||
return platformOrderMap.findUninvoicedOrdersByShopForClient(shopIds, erpStatuses, column, order, offset, pageSize);
|
||||
}
|
||||
@Override
|
||||
public List<PlatformOrderFront> fetchUninvoicedOrdersByShopForClientFullSQL(List<String> shopIds, List<Integer> erpStatuses, String column, String order, Integer pageNo, Integer pageSize,
|
||||
List<Integer> productAvailable, List<Integer> shippingAvailable, List<Integer> purchaseAvailable) {
|
||||
int offset = (pageNo - 1) * pageSize;
|
||||
return platformOrderMap.fetchUninvoicedOrdersByShopForClientFullSQL(shopIds, erpStatuses, column, order, offset, pageSize, productAvailable, shippingAvailable, purchaseAvailable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> findUninvoicedOrderIdsByShopForClient(List<String> shopIds, List<Integer> erpStatuses) {
|
||||
|
|
|
@ -106,6 +106,8 @@ public class PlatformOrderFront {
|
|||
@ApiModelProperty(value = "可开采购票(0=不可,1=可)")
|
||||
private String purchaseAvailable;
|
||||
|
||||
private Integer totalCount;
|
||||
|
||||
public enum invoiceStatus {
|
||||
Unavailable("-1"),
|
||||
Available("0"),
|
||||
|
|
Loading…
Reference in New Issue