@@ -4,6 +4,7 @@ import com.ffii.fpsms.modules.jobOrder.entity.JobOrderRepository
import com.ffii.fpsms.modules.jobOrder.web.model.PrintRequest
import com.ffii.fpsms.modules.jobOrder.web.model.PrintRequest
import com.ffii.fpsms.modules.jobOrder.web.model.LaserRequest
import com.ffii.fpsms.modules.jobOrder.web.model.LaserRequest
import org.springframework.stereotype.Service
import org.springframework.stereotype.Service
import java.time.LocalDate
import com.ffii.core.support.JdbcDao
import com.ffii.core.support.JdbcDao
@@ -12,6 +13,131 @@ open class PSService(
private val jdbcDao: JdbcDao,
private val jdbcDao: JdbcDao,
) {
) {
/** Default: past 30 days including today. */
fun getItemDailyOut(fromDate: LocalDate? = null, toDate: LocalDate? = null): List<Map<String, Any>> {
val to = toDate ?: LocalDate.now()
val from = fromDate ?: to.minusDays(29)
val args = mapOf(
"fromDate" to from.toString(),
"toDate" to to.toString(),
)
val sql = """
SELECT
(SELECT dailyQty FROM item_daily_out WHERE itemCode = items.code) AS dailyQty,
(SELECT
IFNULL(ROUND(AVG(d.dailyQty)), 0)
FROM
(SELECT
SUM(dol.qty) AS dailyQty
FROM
delivery_order_line dol
LEFT JOIN delivery_order do ON dol.deliveryOrderId = do.id
WHERE
do.deleted = 0
AND dol.itemId = items.id
AND do.estimatedArrivalDate >= :fromDate AND do.estimatedArrivalDate <= :toDate
GROUP BY do.estimatedArrivalDate) AS d) AS avgQtyLastMonth,
(SELECT SUM(reqQty) FROM job_order WHERE bomId = bom.id AND status != 'completed') AS pendingJobQty,
(SELECT COUNT(1) FROM coffee_or_tea WHERE systemType = 'coffee' AND itemCode = items.code AND deleted = 0) AS isCoffee,
(SELECT COUNT(1) FROM coffee_or_tea WHERE systemType = 'tea' AND itemCode = items.code AND deleted = 0) AS isTea,
(SELECT COUNT(1) FROM coffee_or_tea WHERE systemType = 'lemon' AND itemCode = items.code AND deleted = 0) AS isLemon,
CASE WHEN item_fake_onhand.onHandQty IS NOT NULL THEN item_fake_onhand.onHandQty
ELSE inventory.onHandQty - 500 END AS stockQty,
bom.baseScore,
bom.outputQty,
bom.outputQtyUom,
(SELECT udfudesc
FROM delivery_order_line
LEFT JOIN uom_conversion ON delivery_order_line.uomId = uom_conversion.id
WHERE delivery_order_line.itemId = bom.itemId
LIMIT 1) AS doUom,
items.code AS itemCode,
items.name AS itemName,
uc_stock.udfudesc AS unit,
bom.description,
inventory.onHandQty,
item_fake_onhand.onHandQty AS fakeOnHandQty,
bom.itemId,
bom.id AS bomId,
CASE WHEN bom.isDark = 5 THEN 11 WHEN bom.isDark = 3 THEN 6 WHEN bom.isDark = 1 THEN 2 ELSE 0 END AS markDark,
CASE WHEN bom.isFloat = 5 THEN 11 WHEN bom.isFloat = 3 THEN 6 WHEN bom.isFloat = 1 THEN 2 ELSE 0 END AS markFloat,
CASE WHEN bom.isDense = 5 THEN 11 WHEN bom.isDense = 3 THEN 6 WHEN bom.isDense = 1 THEN 2 ELSE 0 END AS markDense,
bom.timeSequence AS markTimeSequence,
bom.complexity AS markComplexity,
CASE WHEN bom.allergicSubstances = 5 THEN 11 ELSE 0 END AS markAS,
inventory.id AS inventoryId
FROM
bom
LEFT JOIN items ON bom.itemId = items.id
LEFT JOIN inventory ON items.id = inventory.itemId
LEFT JOIN item_fake_onhand ON items.code = item_fake_onhand.itemCode
LEFT JOIN item_uom iu ON iu.itemId = items.id AND iu.stockUnit = 1
LEFT JOIN uom_conversion uc_stock ON uc_stock.id = iu.uomId
WHERE 1
""".trimIndent()
return jdbcDao.queryForList(sql, args)
}
/** Update or insert dailyQty for itemCode. */
fun setDailyQtyOut(itemCode: String, dailyQty: Number) {
val args = mapOf("itemCode" to itemCode, "dailyQty" to dailyQty)
val updated = jdbcDao.executeUpdate(
"UPDATE item_daily_out SET dailyQty = :dailyQty WHERE itemCode = :itemCode",
args
)
if (updated == 0) {
jdbcDao.executeUpdate(
"INSERT INTO item_daily_out (itemCode, dailyQty) VALUES (:itemCode, :dailyQty)",
args
)
}
}
/** Remove dailyQty override for itemCode (delete row from item_daily_out). */
fun clearDailyQtyOut(itemCode: String) {
jdbcDao.executeUpdate(
"DELETE FROM item_daily_out WHERE itemCode = :itemCode",
mapOf("itemCode" to itemCode)
)
}
/** Set or clear item_fake_onhand for itemCode. If onHandQty is null, delete the row; else update or insert. */
fun setFakeOnHand(itemCode: String, onHandQty: Number?) {
if (onHandQty == null) {
jdbcDao.executeUpdate(
"DELETE FROM item_fake_onhand WHERE itemCode = :itemCode",
mapOf("itemCode" to itemCode)
)
return
}
val args = mapOf("itemCode" to itemCode, "onHandQty" to onHandQty)
val updated = jdbcDao.executeUpdate(
"UPDATE item_fake_onhand SET onHandQty = :onHandQty WHERE itemCode = :itemCode",
args
)
if (updated == 0) {
jdbcDao.executeUpdate(
"INSERT INTO item_fake_onhand (itemCode, onHandQty) VALUES (:itemCode, :onHandQty)",
args
)
}
}
/** Set or clear coffee_or_tea for itemCode + systemType (coffee / tea / lemon). */
fun setCoffeeOrTea(itemCode: String, systemType: String, enabled: Boolean) {
val args = mapOf("itemCode" to itemCode, "systemType" to systemType)
jdbcDao.executeUpdate(
"DELETE FROM coffee_or_tea WHERE itemCode = :itemCode AND systemType = :systemType",
args
)
if (enabled) {
jdbcDao.executeUpdate(
"INSERT INTO coffee_or_tea (itemCode, systemType) VALUES (:itemCode, :systemType)",
args
)
}
}
fun searchProductionSchedules(produceAt: String): List<Map<String, Any>> {
fun searchProductionSchedules(produceAt: String): List<Map<String, Any>> {
val args = mapOf(
val args = mapOf(
"produceAt" to produceAt,
"produceAt" to produceAt,