Procházet zdrojové kódy

chart sql improt

production
CANCERYS\kw093 před 1 měsícem
rodič
revize
7141c0f6b4
2 změnil soubory, kde provedl 56 přidání a 34 odebrání
  1. +52
    -32
      src/main/java/com/ffii/fpsms/modules/chart/service/ChartService.kt
  2. +4
    -2
      src/main/java/com/ffii/fpsms/modules/chart/web/ChartController.kt

+ 52
- 32
src/main/java/com/ffii/fpsms/modules/chart/service/ChartService.kt Zobrazit soubor

@@ -40,27 +40,28 @@ open class ChartService(

/**
* Delivery orders: order count and total line qty by date.
* Uses delivery_order.completeDate or estimatedArrivalDate for date.
* X-axis date: [delivery_order.estimatedArrivalDate] only (no completeDate/orderDate fallback).
* Rows without estimatedArrivalDate are excluded.
*/
fun getDeliveryOrderByDate(startDate: LocalDate?, endDate: LocalDate?): List<Map<String, Any>> {
val args = mutableMapOf<String, Any>()
val startSql = if (startDate != null) {
args["startDate"] = startDate.toString()
"AND DATE(COALESCE(do.completeDate, do.estimatedArrivalDate, do.orderDate)) >= :startDate"
"AND DATE(do.estimatedArrivalDate) >= :startDate"
} else ""
val endSql = if (endDate != null) {
args["endDate"] = endDate.toString()
"AND DATE(COALESCE(do.completeDate, do.estimatedArrivalDate, do.orderDate)) <= :endDate"
"AND DATE(do.estimatedArrivalDate) <= :endDate"
} else ""
val sql = """
SELECT
DATE_FORMAT(COALESCE(do.completeDate, do.estimatedArrivalDate, do.orderDate), '%Y-%m-%d') AS date,
DATE_FORMAT(do.estimatedArrivalDate, '%Y-%m-%d') AS date,
COUNT(DISTINCT do.id) AS orderCount,
COALESCE(SUM(dol.qty), 0) AS totalQty
FROM delivery_order do
LEFT JOIN delivery_order_line dol ON dol.deliveryOrderId = do.id AND dol.deleted = 0
WHERE do.deleted = 0 $startSql $endSql
GROUP BY DATE(COALESCE(do.completeDate, do.estimatedArrivalDate, do.orderDate))
WHERE do.deleted = 0 AND do.estimatedArrivalDate IS NOT NULL $startSql $endSql
GROUP BY DATE(do.estimatedArrivalDate)
ORDER BY date
""".trimIndent()
return jdbcDao.queryForList(sql, args)
@@ -529,17 +530,32 @@ open class ChartService(
* Stock in vs stock out by date.
* Stock in: stock_in_line.acceptedQty, date from stock_in.completeDate or receiptDate/created.
* Stock out: stock_out_line.qty, date from stock_out.completeDate or created.
*
* Date range is applied inside each UNION branch (predicate pushdown) so we do not aggregate
* all history before filtering. Reads filtered headers first via STRAIGHT_JOIN (si/so then lines).
*/
fun getStockInOutByDate(startDate: LocalDate?, endDate: LocalDate?): List<Map<String, Any>> {
val args = mutableMapOf<String, Any>()
val startSql = if (startDate != null) {
args["startDate"] = startDate.toString()
"AND u.dt >= :startDate"
} else ""
val endSql = if (endDate != null) {
args["endDate"] = endDate.toString()
"AND u.dt <= :endDate"
} else ""
if (startDate != null) args["startDate"] = startDate.toString()
if (endDate != null) args["endDate"] = endDate.toString()
val inDateFilter = buildString {
if (startDate != null) {
append(" AND DATE(COALESCE(si.completeDate, sil.receiptDate, si.created)) >= :startDate")
}
if (endDate != null) {
append(" AND DATE(COALESCE(si.completeDate, sil.receiptDate, si.created)) <= :endDate")
}
}
val outDateFilter = buildString {
if (startDate != null) {
append(" AND DATE(COALESCE(so.completeDate, so.created)) >= :startDate")
}
if (endDate != null) {
append(" AND DATE(COALESCE(so.completeDate, so.created)) <= :endDate")
}
}
val startSql = if (startDate != null) "AND u.dt >= :startDate" else ""
val endSql = if (endDate != null) "AND u.dt <= :endDate" else ""
val sql = """
SELECT DATE_FORMAT(u.dt, '%Y-%m-%d') AS date,
COALESCE(SUM(u.inQty), 0) AS inQty,
@@ -547,16 +563,16 @@ open class ChartService(
FROM (
SELECT DATE(COALESCE(si.completeDate, sil.receiptDate, si.created)) AS dt,
SUM(COALESCE(sil.acceptedQty, 0)) AS inQty, 0 AS outQty
FROM stock_in_line sil
INNER JOIN stock_in si ON sil.stockInId = si.id AND si.deleted = 0
WHERE sil.deleted = 0
FROM stock_in si
STRAIGHT_JOIN stock_in_line sil ON sil.stockInId = si.id AND sil.deleted = 0
WHERE si.deleted = 0$inDateFilter
GROUP BY DATE(COALESCE(si.completeDate, sil.receiptDate, si.created))
UNION ALL
SELECT DATE(COALESCE(so.completeDate, so.created)) AS dt,
0 AS inQty, SUM(COALESCE(sol.qty, 0)) AS outQty
FROM stock_out_line sol
INNER JOIN stock_out so ON sol.stockOutId = so.id AND so.deleted = 0
WHERE sol.deleted = 0
FROM stock_out so
STRAIGHT_JOIN stock_out_line sol ON sol.stockOutId = so.id AND sol.deleted = 0
WHERE so.deleted = 0$outDateFilter
GROUP BY DATE(COALESCE(so.completeDate, so.created))
) u
WHERE 1=1 $startSql $endSql
@@ -568,23 +584,25 @@ open class ChartService(

/**
* Distinct items that appear in delivery_order_line in the period (for multi-select options).
* Period filter: [delivery_order.estimatedArrivalDate] only; null ETA excluded.
* Uses STRAIGHT_JOIN so MySQL reads filtered `delivery_order` first (avoids full scan on `delivery_order_line`).
*/
fun getTopDeliveryItemsItemOptions(startDate: LocalDate?, endDate: LocalDate?): List<Map<String, Any>> {
val args = mutableMapOf<String, Any>()
val startSql = if (startDate != null) {
args["startDate"] = startDate.toString()
"AND DATE(COALESCE(do.completeDate, do.estimatedArrivalDate, do.orderDate)) >= :startDate"
"AND DATE(do.estimatedArrivalDate) >= :startDate"
} else ""
val endSql = if (endDate != null) {
args["endDate"] = endDate.toString()
"AND DATE(COALESCE(do.completeDate, do.estimatedArrivalDate, do.orderDate)) <= :endDate"
"AND DATE(do.estimatedArrivalDate) <= :endDate"
} else ""
val sql = """
SELECT DISTINCT it.code AS itemCode, COALESCE(it.name, '') AS itemName
FROM delivery_order_line dol
INNER JOIN delivery_order do ON dol.deliveryOrderId = do.id AND do.deleted = 0
INNER JOIN items it ON dol.itemId = it.id AND it.deleted = 0
WHERE dol.deleted = 0 $startSql $endSql
FROM delivery_order do
STRAIGHT_JOIN delivery_order_line dol ON dol.deliveryOrderId = do.id AND dol.deleted = 0
STRAIGHT_JOIN items it ON it.id = dol.itemId AND it.deleted = 0
WHERE do.deleted = 0 AND do.estimatedArrivalDate IS NOT NULL $startSql $endSql
ORDER BY it.code
""".trimIndent()
return jdbcDao.queryForList(sql, args)
@@ -592,6 +610,8 @@ open class ChartService(

/**
* Top delivery items by total qty in the period. When itemCodes is non-empty, only those items (still ordered by totalQty, limit applied).
* Period filter: [delivery_order.estimatedArrivalDate] only; null ETA excluded.
* Uses STRAIGHT_JOIN so MySQL reads filtered `delivery_order` first (avoids full scan on `delivery_order_line`).
*/
fun getTopDeliveryItems(
startDate: LocalDate?,
@@ -602,11 +622,11 @@ open class ChartService(
val args = mutableMapOf<String, Any>("limit" to limit)
val startSql = if (startDate != null) {
args["startDate"] = startDate.toString()
"AND DATE(COALESCE(do.completeDate, do.estimatedArrivalDate, do.orderDate)) >= :startDate"
"AND DATE(do.estimatedArrivalDate) >= :startDate"
} else ""
val endSql = if (endDate != null) {
args["endDate"] = endDate.toString()
"AND DATE(COALESCE(do.completeDate, do.estimatedArrivalDate, do.orderDate)) <= :endDate"
"AND DATE(do.estimatedArrivalDate) <= :endDate"
} else ""
val itemSql = if (!itemCodes.isNullOrEmpty()) {
val codes = itemCodes.map { it.trim() }.filter { it.isNotBlank() }
@@ -620,10 +640,10 @@ open class ChartService(
it.code AS itemCode,
it.name AS itemName,
SUM(COALESCE(dol.qty, 0)) AS totalQty
FROM delivery_order_line dol
INNER JOIN delivery_order do ON dol.deliveryOrderId = do.id AND do.deleted = 0
INNER JOIN items it ON dol.itemId = it.id AND it.deleted = 0
WHERE dol.deleted = 0 $startSql $endSql $itemSql
FROM delivery_order do
STRAIGHT_JOIN delivery_order_line dol ON dol.deliveryOrderId = do.id AND dol.deleted = 0
STRAIGHT_JOIN items it ON it.id = dol.itemId AND it.deleted = 0
WHERE do.deleted = 0 AND do.estimatedArrivalDate IS NOT NULL $startSql $endSql $itemSql
GROUP BY dol.itemId, it.code, it.name
ORDER BY totalQty DESC
LIMIT :limit


+ 4
- 2
src/main/java/com/ffii/fpsms/modules/chart/web/ChartController.kt Zobrazit soubor

@@ -26,7 +26,7 @@ class ChartController(

/**
* GET /chart/delivery-order-by-date?startDate=&endDate=
* Returns [{ date, orderCount, totalQty }]
* Returns [{ date, orderCount, totalQty }]. Date axis: delivery_order.estimatedArrivalDate only (null ETA excluded).
*/
@GetMapping("/delivery-order-by-date")
fun getDeliveryOrderByDate(
@@ -129,7 +129,7 @@ class ChartController(

/**
* GET /chart/stock-in-out-by-date?startDate=&endDate=
* Returns [{ date, inQty, outQty }]
* Returns [{ date, inQty, outQty }]. Date range pushed into each UNION branch; si/so read before lines.
*/
@GetMapping("/stock-in-out-by-date")
fun getStockInOutByDate(
@@ -140,6 +140,7 @@ class ChartController(
/**
* GET /chart/top-delivery-items-item-options?startDate=&endDate=
* Returns [{ itemCode, itemName }] — distinct items in delivery lines in the period (for multi-select).
* Period: delivery_order.estimatedArrivalDate only (null ETA excluded).
*/
@GetMapping("/top-delivery-items-item-options")
fun getTopDeliveryItemsItemOptions(
@@ -150,6 +151,7 @@ class ChartController(
/**
* GET /chart/top-delivery-items?startDate=&endDate=&limit=20&itemCode=A&itemCode=B
* Returns [{ itemCode, itemName, totalQty }]. When itemCode present, only those items (still by totalQty, limit).
* Period: delivery_order.estimatedArrivalDate only (null ETA excluded).
*/
@GetMapping("/top-delivery-items")
fun getTopDeliveryItems(


Načítá se…
Zrušit
Uložit