From b8e2a8e31a4b0b8e570b2a2eaa53054fc63a740d Mon Sep 17 00:00:00 2001 From: wuweihua <88888888> Date: Wed, 21 Oct 2026 15:08:13 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=A5=97=E9=A4=90=E4=BA=A7?= =?UTF-8?q?=E5=93=81=E7=BA=A2=E7=BA=BF=E4=BB=B7=E4=BF=AE=E6=94=B9=E5=86=85?= =?UTF-8?q?=E5=AE=B9=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../monitor/PriceLogController.java | 54 ++++ .../java/com/bms/price/search/EsLogType.java | 2 + .../bms/price/search/PriceChangeEsLog.java | 221 +++++++++++++++ .../service/impl/BmsProductServiceImpl.java | 37 ++- .../impl/BmsRedlineProductServiceImpl.java | 37 ++- .../service/impl/PrcPriceSetServiceImpl.java | 65 +++++ bms-back/sql/monitor/price_log_menu.sql | 36 +++ bms-front/src/api/monitor/priceLog.js | 16 ++ bms-front/src/views/monitor/eslog/index.vue | 3 +- .../src/views/monitor/priceLog/index.vue | 265 ++++++++++++++++++ 10 files changed, 731 insertions(+), 5 deletions(-) create mode 100644 bms-back/bms-admin/src/main/java/com/bms/web/controller/monitor/PriceLogController.java create mode 100644 bms-back/bms-system/src/main/java/com/bms/price/search/PriceChangeEsLog.java create mode 100644 bms-back/sql/monitor/price_log_menu.sql create mode 100644 bms-front/src/api/monitor/priceLog.js create mode 100644 bms-front/src/views/monitor/priceLog/index.vue diff --git a/bms-back/bms-admin/src/main/java/com/bms/web/controller/monitor/PriceLogController.java b/bms-back/bms-admin/src/main/java/com/bms/web/controller/monitor/PriceLogController.java new file mode 100644 index 00000000..94b17972 --- /dev/null +++ b/bms-back/bms-admin/src/main/java/com/bms/web/controller/monitor/PriceLogController.java @@ -0,0 +1,54 @@ +package com.bms.web.controller.monitor; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import com.bms.common.constant.HttpStatus; +import com.bms.common.core.controller.BaseController; +import com.bms.common.core.domain.AjaxResult; +import com.bms.common.core.page.PageDomain; +import com.bms.common.core.page.TableDataInfo; +import com.bms.common.core.page.TableSupport; +import com.bms.price.search.BillSearchPage; +import com.bms.price.search.EsLogType; +import com.bms.price.search.IBillSearchStore; + +/** + * Price before-after change log (sales / product / redline) from ES. + */ +@RestController +@RequestMapping("/monitor/priceLog") +public class PriceLogController extends BaseController +{ + @Autowired + private IBillSearchStore billSearchStore; + + @PreAuthorize("@ss.hasPermi('monitor:priceLog:list')") + @GetMapping("/list") + public TableDataInfo list( + @RequestParam(value = "bizId", required = false) String bizId, + @RequestParam(value = "status", required = false) String status) + { + PageDomain pageDomain = TableSupport.buildPageRequest(); + int pageNum = pageDomain.getPageNum() == null ? 1 : pageDomain.getPageNum().intValue(); + int pageSize = pageDomain.getPageSize() == null ? 10 : pageDomain.getPageSize().intValue(); + BillSearchPage page = billSearchStore.search(EsLogType.PRICE_CHANGE, bizId, status, pageNum, pageSize); + TableDataInfo rsp = new TableDataInfo(); + rsp.setCode(HttpStatus.SUCCESS); + rsp.setMsg("\u67e5\u8be2\u6210\u529f"); + rsp.setRows(page.getRows()); + rsp.setTotal(page.getTotal()); + return rsp; + } + + @PreAuthorize("@ss.hasPermi('monitor:priceLog:list')") + @GetMapping("/{docId}") + public AjaxResult getInfo(@PathVariable("docId") String docId) + { + return success(billSearchStore.getByDocId(docId)); + } +} diff --git a/bms-back/bms-system/src/main/java/com/bms/price/search/EsLogType.java b/bms-back/bms-system/src/main/java/com/bms/price/search/EsLogType.java index b5a02e7f..39d15f42 100644 --- a/bms-back/bms-system/src/main/java/com/bms/price/search/EsLogType.java +++ b/bms-back/bms-system/src/main/java/com/bms/price/search/EsLogType.java @@ -14,6 +14,8 @@ public final class EsLogType public static final String ARREARS = "ARREARS"; /** Monitor: sync billing from TAB_ORDER */ public static final String ORDER_SOURCE_SYNC = "ORDER_SOURCE_SYNC"; + /** Monitor: sales / product / redline price before-after changes */ + public static final String PRICE_CHANGE = "PRICE_CHANGE"; private EsLogType() { diff --git a/bms-back/bms-system/src/main/java/com/bms/price/search/PriceChangeEsLog.java b/bms-back/bms-system/src/main/java/com/bms/price/search/PriceChangeEsLog.java new file mode 100644 index 00000000..c7fda2a4 --- /dev/null +++ b/bms-back/bms-system/src/main/java/com/bms/price/search/PriceChangeEsLog.java @@ -0,0 +1,221 @@ +package com.bms.price.search; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import com.alibaba.fastjson2.JSON; +import com.bms.common.utils.SecurityUtils; +import com.bms.common.utils.StringUtils; +import com.bms.price.domain.PrcPriceSetDetail; + +/** + * Write sales / product / redline price before-after changes to ES (bms_biz_log). + */ +public final class PriceChangeEsLog +{ + public static final String KIND_SALES = "SALES"; + public static final String KIND_PRODUCT = "PRODUCT"; + public static final String KIND_REDLINE = "REDLINE"; + + public static final String ACTION_INSERT = "INSERT"; + public static final String ACTION_UPDATE = "UPDATE"; + public static final String ACTION_DELETE = "DELETE"; + public static final String ACTION_IMPORT = "IMPORT"; + + private PriceChangeEsLog() + { + } + + public static String operator() + { + try + { + String name = SecurityUtils.getUsername(); + return StringUtils.isEmpty(name) ? "unknown" : name; + } + catch (Exception e) + { + return "unknown"; + } + } + + public static Map change(String field, String fieldLabel, Object oldValue, Object newValue) + { + Map row = new LinkedHashMap(); + row.put("field", field); + row.put("fieldLabel", fieldLabel); + row.put("oldValue", stringify(oldValue)); + row.put("newValue", stringify(newValue)); + return row; + } + + public static boolean valuesEqual(Object a, Object b) + { + if (a == null && b == null) + { + return true; + } + if (a instanceof BigDecimal || b instanceof BigDecimal) + { + BigDecimal ba = toDecimal(a); + BigDecimal bb = toDecimal(b); + if (ba == null && bb == null) + { + return true; + } + if (ba == null || bb == null) + { + return false; + } + return ba.compareTo(bb) == 0; + } + return Objects.equals(stringify(a), stringify(b)); + } + + public static void addIfChanged(List> changes, String field, String fieldLabel, + Object oldValue, Object newValue) + { + if (changes == null || valuesEqual(oldValue, newValue)) + { + return; + } + changes.add(change(field, fieldLabel, oldValue, newValue)); + } + + /** Sales detail price fields (freight / registration / discount). */ + public static List> diffSalesDetail(PrcPriceSetDetail oldRow, PrcPriceSetDetail newRow) + { + List> changes = new ArrayList>(); + if (newRow == null) + { + if (oldRow != null) + { + addIfChanged(changes, "fvValue", "\u8fd0\u8d39\u5355\u4ef7", oldRow.getFvValue(), null); + addIfChanged(changes, "fvRegistrationFee", "\u6302\u53f7\u8d39", oldRow.getFvRegistrationFee(), null); + addIfChanged(changes, "discountValue", "\u6298\u6263", oldRow.getDiscountValue(), null); + } + return changes; + } + Object oldFv = oldRow == null ? null : oldRow.getFvValue(); + Object oldReg = oldRow == null ? null : oldRow.getFvRegistrationFee(); + Object oldDisc = oldRow == null ? null : oldRow.getDiscountValue(); + addIfChanged(changes, "fvValue", "\u8fd0\u8d39\u5355\u4ef7", oldFv, newRow.getFvValue()); + addIfChanged(changes, "fvRegistrationFee", "\u6302\u53f7\u8d39", oldReg, newRow.getFvRegistrationFee()); + addIfChanged(changes, "discountValue", "\u6298\u6263", oldDisc, newRow.getDiscountValue()); + return changes; + } + + public static List> diffCatalogPrice(BigDecimal oldFreight, BigDecimal oldReg, + BigDecimal newFreight, BigDecimal newReg) + { + List> changes = new ArrayList>(); + addIfChanged(changes, "freightPrice", "\u8fd0\u8d39\u5355\u4ef7", oldFreight, newFreight); + addIfChanged(changes, "registrationFee", "\u6302\u53f7\u8d39", oldReg, newReg); + return changes; + } + + public static Map bizKeysSales(PrcPriceSetDetail d) + { + Map keys = new LinkedHashMap(); + if (d == null) + { + return keys; + } + keys.put("psdId", d.getPsdId()); + keys.put("psvId", d.getPsvId()); + keys.put("productCode", d.getProductCode()); + keys.put("productName", d.getProductName()); + keys.put("countryCode", d.getCountryCode()); + keys.put("countryName", d.getCountryName()); + keys.put("zoneCode", d.getZoneCode()); + keys.put("weightMin", d.getWeightMin()); + keys.put("weightMax", d.getWeightMax()); + return keys; + } + + public static void save(IBillSearchStore store, String bizId, String priceKind, String action, + Map bizKeys, List> changes) + { + save(store, bizId, priceKind, action, bizKeys, changes, null, EsBizLogSupport.STATUS_SUCCESS, null); + } + + public static void save(IBillSearchStore store, String bizId, String priceKind, String action, + Map bizKeys, List> changes, Object extra, + String status, String errorMessage) + { + if (store == null || StringUtils.isEmpty(bizId)) + { + return; + } + if (changes != null && changes.isEmpty() && extra == null + && !ACTION_DELETE.equals(action) && !ACTION_INSERT.equals(action)) + { + return; + } + Map req = new LinkedHashMap(); + req.put("action", action); + req.put("operator", operator()); + req.put("priceKind", priceKind); + req.put("bizKeys", bizKeys); + req.put("changes", changes == null ? new ArrayList>() : changes); + if (extra != null) + { + req.put("extra", extra); + } + Map resp = new LinkedHashMap(); + resp.put("success", !EsBizLogSupport.STATUS_FAIL.equals(status)); + String st = StringUtils.isEmpty(status) ? EsBizLogSupport.STATUS_SUCCESS : status; + store.save(EsLogType.PRICE_CHANGE, bizId, JSON.toJSONString(req), JSON.toJSONString(resp), st, errorMessage); + } + + public static String bizIdSales(Long psdId) + { + return "SALES_" + (psdId == null ? System.currentTimeMillis() : psdId); + } + + public static String bizIdProduct(Long detailId) + { + return "PRODUCT_" + (detailId == null ? System.currentTimeMillis() : detailId); + } + + public static String bizIdRedline(Long detailId) + { + return "REDLINE_" + (detailId == null ? System.currentTimeMillis() : detailId); + } + + private static String stringify(Object v) + { + if (v == null) + { + return ""; + } + if (v instanceof BigDecimal) + { + return ((BigDecimal) v).stripTrailingZeros().toPlainString(); + } + return String.valueOf(v); + } + + private static BigDecimal toDecimal(Object v) + { + if (v == null || "".equals(v)) + { + return null; + } + if (v instanceof BigDecimal) + { + return (BigDecimal) v; + } + try + { + return new BigDecimal(String.valueOf(v).trim()); + } + catch (Exception e) + { + return null; + } + } +} diff --git a/bms-back/bms-system/src/main/java/com/bms/price/service/impl/BmsProductServiceImpl.java b/bms-back/bms-system/src/main/java/com/bms/price/service/impl/BmsProductServiceImpl.java index db007b9f..2ae4679e 100644 --- a/bms-back/bms-system/src/main/java/com/bms/price/service/impl/BmsProductServiceImpl.java +++ b/bms-back/bms-system/src/main/java/com/bms/price/service/impl/BmsProductServiceImpl.java @@ -39,10 +39,14 @@ import com.bms.price.domain.BmsProductCountry; import com.bms.price.domain.BmsProductImportTask; import com.bms.price.domain.CatalogPreviewApplyRequest; import com.bms.price.domain.PrcZone; +import com.bms.price.domain.PrcPriceSetDetail; import com.bms.price.mapper.BmsProductCountryMapper; import com.bms.price.mapper.BmsProductMapper; +import com.bms.price.mapper.PrcPriceSetDetailMapper; import com.bms.price.mapper.PrcZoneMapper; import com.bms.price.domain.PrcPriceExcelFile; +import com.bms.price.search.IBillSearchStore; +import com.bms.price.search.PriceChangeEsLog; import com.bms.price.service.IBmsProductService; import com.bms.price.service.IPrcPriceExcelFileService; import com.bms.price.service.IPrcSurchargeRelService; @@ -106,6 +110,12 @@ public class BmsProductServiceImpl implements IBmsProductService @Autowired private IPrcPriceExcelFileService priceExcelFileService; + @Autowired + private PrcPriceSetDetailMapper detailMapper; + + @Autowired + private IBillSearchStore billSearchStore; + @Override public BmsProduct selectBmsProductById(Long productId) { @@ -164,13 +174,36 @@ public class BmsProductServiceImpl implements IBmsProductService { if (country == null || country.getDetailId() == null) { - throw new ServiceException("明细行主键缺失,无法修改"); + throw new ServiceException("\u660e\u7ec6\u884c\u4e3b\u952e\u7f3a\u5931\uff0c\u65e0\u6cd5\u4fee\u6539"); } + PrcPriceSetDetail old = detailMapper.selectPrcPriceSetDetailById(country.getDetailId()); int rows = countryMapper.updateBmsProductCountry(country); if (rows > 0) { - // 生效/失效日期可能变化,状态按日期重算 + // Recalc status when effective/expire dates change countryMapper.refreshStatusByDates(); + List> changes = PriceChangeEsLog.diffCatalogPrice( + old == null ? null : old.getFvValue(), + old == null ? null : old.getFvRegistrationFee(), + country.getFreightPrice(), + country.getRegistrationFee()); + if (!changes.isEmpty()) + { + Map keys = new LinkedHashMap(); + keys.put("detailId", country.getDetailId()); + keys.put("productCode", country.getProductCode() != null ? country.getProductCode() + : (old == null ? null : old.getProductCode())); + keys.put("countryCode", country.getCountryCode() != null ? country.getCountryCode() + : (old == null ? null : old.getCountryCode())); + keys.put("zoneCode", country.getZoneCode() != null ? country.getZoneCode() + : (old == null ? null : old.getZoneCode())); + keys.put("weightMin", country.getWeightMin() != null ? country.getWeightMin() + : (old == null ? null : old.getWeightMin())); + keys.put("weightMax", country.getWeightMax() != null ? country.getWeightMax() + : (old == null ? null : old.getWeightMax())); + PriceChangeEsLog.save(billSearchStore, PriceChangeEsLog.bizIdProduct(country.getDetailId()), + PriceChangeEsLog.KIND_PRODUCT, PriceChangeEsLog.ACTION_UPDATE, keys, changes); + } } return rows; } diff --git a/bms-back/bms-system/src/main/java/com/bms/price/service/impl/BmsRedlineProductServiceImpl.java b/bms-back/bms-system/src/main/java/com/bms/price/service/impl/BmsRedlineProductServiceImpl.java index 6bef77d0..2eabc89b 100644 --- a/bms-back/bms-system/src/main/java/com/bms/price/service/impl/BmsRedlineProductServiceImpl.java +++ b/bms-back/bms-system/src/main/java/com/bms/price/service/impl/BmsRedlineProductServiceImpl.java @@ -40,11 +40,15 @@ import com.bms.price.domain.BmsRedlineProductImportTask; import com.bms.price.domain.RedlineCatalogPreviewApplyRequest; import com.bms.price.domain.PrcZone; import com.bms.price.domain.PrcSurchargeRel; +import com.bms.price.domain.PrcPriceSetDetail; import com.bms.price.mapper.BmsRedlineProductCountryMapper; import com.bms.price.mapper.BmsRedlineProductMapper; +import com.bms.price.mapper.PrcPriceSetDetailMapper; import com.bms.price.mapper.PrcSurchargeRelMapper; import com.bms.price.mapper.PrcZoneMapper; import com.bms.price.domain.PrcPriceExcelFile; +import com.bms.price.search.IBillSearchStore; +import com.bms.price.search.PriceChangeEsLog; import com.bms.price.service.IBmsRedlineProductService; import com.bms.price.service.IPrcPriceExcelFileService; import com.bms.price.domain.PriceType; @@ -107,6 +111,12 @@ public class BmsRedlineProductServiceImpl implements IBmsRedlineProductService @Autowired private IPrcPriceExcelFileService priceExcelFileService; + @Autowired + private PrcPriceSetDetailMapper detailMapper; + + @Autowired + private IBillSearchStore billSearchStore; + @Override public BmsRedlineProduct selectBmsRedlineProductById(Long productId) { @@ -165,13 +175,36 @@ public class BmsRedlineProductServiceImpl implements IBmsRedlineProductService { if (country == null || country.getDetailId() == null) { - throw new ServiceException("明细行主键缺失,无法修改"); + throw new ServiceException("\u660e\u7ec6\u884c\u4e3b\u952e\u7f3a\u5931\uff0c\u65e0\u6cd5\u4fee\u6539"); } + PrcPriceSetDetail old = detailMapper.selectPrcPriceSetDetailById(country.getDetailId()); int rows = countryMapper.updateBmsRedlineProductCountry(country); if (rows > 0) { - // 生效/失效日期可能变化,状态按日期重算 + // Recalc status when effective/expire dates change countryMapper.refreshStatusByDates(); + List> changes = PriceChangeEsLog.diffCatalogPrice( + old == null ? null : old.getFvValue(), + old == null ? null : old.getFvRegistrationFee(), + country.getFreightPrice(), + country.getRegistrationFee()); + if (!changes.isEmpty()) + { + Map keys = new LinkedHashMap(); + keys.put("detailId", country.getDetailId()); + keys.put("productCode", country.getProductCode() != null ? country.getProductCode() + : (old == null ? null : old.getProductCode())); + keys.put("countryCode", country.getCountryCode() != null ? country.getCountryCode() + : (old == null ? null : old.getCountryCode())); + keys.put("zoneCode", country.getZoneCode() != null ? country.getZoneCode() + : (old == null ? null : old.getZoneCode())); + keys.put("weightMin", country.getWeightMin() != null ? country.getWeightMin() + : (old == null ? null : old.getWeightMin())); + keys.put("weightMax", country.getWeightMax() != null ? country.getWeightMax() + : (old == null ? null : old.getWeightMax())); + PriceChangeEsLog.save(billSearchStore, PriceChangeEsLog.bizIdRedline(country.getDetailId()), + PriceChangeEsLog.KIND_REDLINE, PriceChangeEsLog.ACTION_UPDATE, keys, changes); + } } return rows; } diff --git a/bms-back/bms-system/src/main/java/com/bms/price/service/impl/PrcPriceSetServiceImpl.java b/bms-back/bms-system/src/main/java/com/bms/price/service/impl/PrcPriceSetServiceImpl.java index 8e88a588..6ee27cf3 100644 --- a/bms-back/bms-system/src/main/java/com/bms/price/service/impl/PrcPriceSetServiceImpl.java +++ b/bms-back/bms-system/src/main/java/com/bms/price/service/impl/PrcPriceSetServiceImpl.java @@ -51,6 +51,8 @@ import com.bms.price.mapper.PrcSurchargeRelMapper; import com.bms.common.core.domain.entity.SysUser; import com.bms.system.mapper.SysUserMapper; import com.bms.price.service.IBmsProductService; +import com.bms.price.search.IBillSearchStore; +import com.bms.price.search.PriceChangeEsLog; import com.bms.price.service.IPrcPriceExcelFileService; import com.bms.price.service.IPrcPriceSetService; import com.bms.price.task.PrcPriceSetSaveAsyncRunner; @@ -129,6 +131,9 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService @Autowired private IPrcPriceExcelFileService priceExcelFileService; + @Autowired + private IBillSearchStore billSearchStore; + @Override public PrcPriceSet selectPrcPriceSetById(Long priceSetId) { @@ -1505,8 +1510,27 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService } if (!deleteIds.isEmpty()) { + Map beforeReplace = new HashMap(); + for (PrcPriceSetDetail d : details) + { + if (d != null && d.getPsdId() != null && deleteIds.contains(d.getPsdId())) + { + beforeReplace.put(d.getPsdId(), d); + } + } // Draft/pending: hard delete covered rows; effect/expired: soft delete. deleteDetailRowsByIds(deleteIds, isDraftOrPendingVersionStatus(resolveVersionStatus(psvId))); + for (Long id : deleteIds) + { + PrcPriceSetDetail old = beforeReplace.get(id); + if (old == null) + { + continue; + } + PriceChangeEsLog.save(billSearchStore, PriceChangeEsLog.bizIdSales(id), + PriceChangeEsLog.KIND_SALES, PriceChangeEsLog.ACTION_IMPORT, + PriceChangeEsLog.bizKeysSales(old), PriceChangeEsLog.diffSalesDetail(old, null)); + } } removeDetailsByReplaceScopes(details, detailIndex, replaceScopes); } @@ -1573,6 +1597,8 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService { continue; } + BigDecimal oldFv = hit.getFvValue(); + BigDecimal oldReg = hit.getFvRegistrationFee(); detailMapper.updateDetailPrices(hit.getPsdId(), freight, registration); if (freight != null) { @@ -1582,6 +1608,14 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService { hit.setFvRegistrationFee(registration); } + List> changes = PriceChangeEsLog.diffSalesDetail( + buildPriceSnapshot(oldFv, oldReg), hit); + if (!changes.isEmpty()) + { + PriceChangeEsLog.save(billSearchStore, PriceChangeEsLog.bizIdSales(hit.getPsdId()), + PriceChangeEsLog.KIND_SALES, PriceChangeEsLog.ACTION_IMPORT, + PriceChangeEsLog.bizKeysSales(hit), changes); + } touched.add(hit.getPsdId()); updated++; } @@ -1606,6 +1640,9 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService { touched.add(created.getPsdId()); } + PriceChangeEsLog.save(billSearchStore, PriceChangeEsLog.bizIdSales(created.getPsdId()), + PriceChangeEsLog.KIND_SALES, PriceChangeEsLog.ACTION_IMPORT, + PriceChangeEsLog.bizKeysSales(created), PriceChangeEsLog.diffSalesDetail(null, created)); inserted++; } } @@ -2116,6 +2153,16 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService { replaceSalesSurchargeRels(java.util.Collections.singletonList(detail)); } + if (rows > 0) + { + List> changes = PriceChangeEsLog.diffSalesDetail(old, detail); + if (!changes.isEmpty()) + { + PriceChangeEsLog.save(billSearchStore, PriceChangeEsLog.bizIdSales(old.getPsdId()), + PriceChangeEsLog.KIND_SALES, PriceChangeEsLog.ACTION_UPDATE, + PriceChangeEsLog.bizKeysSales(detail.getPsdId() != null ? detail : old), changes); + } + } return rows; } @@ -2130,6 +2177,7 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService List softIds = new ArrayList(); Set hardTouchKeys = new HashSet(); Set softTouchKeys = new HashSet(); + List deletedSnapshots = new ArrayList(); for (Long id : psdIds) { if (id == null) @@ -2143,6 +2191,7 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService } PrcPriceSet db = requireSet(resolvePriceSetIdByPsvId(old.getPsvId())); assertChildEditable(db); + deletedSnapshots.add(old); boolean hard = isDraftOrPendingVersionStatus(resolveVersionStatus(old.getPsvId())); if (hard) { @@ -2172,6 +2221,13 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService rows += deleteDetailRowsByIds(softIds, false); cleanupOrphanSetProducts(softTouchKeys, false); } + for (PrcPriceSetDetail old : deletedSnapshots) + { + List> changes = PriceChangeEsLog.diffSalesDetail(old, null); + PriceChangeEsLog.save(billSearchStore, PriceChangeEsLog.bizIdSales(old.getPsdId()), + PriceChangeEsLog.KIND_SALES, PriceChangeEsLog.ACTION_DELETE, + PriceChangeEsLog.bizKeysSales(old), changes); + } return rows; } @@ -2195,6 +2251,15 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService return detailMapper.deletePrcPriceSetDetailByIds(arr); } + /** Snapshot freight/registration for import before-after log. */ + private PrcPriceSetDetail buildPriceSnapshot(BigDecimal fvValue, BigDecimal registrationFee) + { + PrcPriceSetDetail snap = new PrcPriceSetDetail(); + snap.setFvValue(fvValue); + snap.setFvRegistrationFee(registrationFee); + return snap; + } + /** Version status draft(0) / pending(3): hard delete children. */ private boolean isDraftOrPendingVersionStatus(String status) { diff --git a/bms-back/sql/monitor/price_log_menu.sql b/bms-back/sql/monitor/price_log_menu.sql new file mode 100644 index 00000000..596e3056 --- /dev/null +++ b/bms-back/sql/monitor/price_log_menu.sql @@ -0,0 +1,36 @@ +-- Price change log under system monitor +SET NAMES utf8mb4; + +SET @monitorParent := ( + SELECT menu_id FROM sys_menu + WHERE menu_type = 'M' AND (path = 'monitor' OR menu_name = N'系统监控') + ORDER BY menu_id + LIMIT 1 +); + +INSERT INTO sys_menu ( + menu_id, menu_name, parent_id, order_num, path, component, query, route_name, + is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark +) +SELECT 2350, N'价格日志', IFNULL(@monitorParent, 2), 10, + 'priceLog', 'monitor/priceLog/index', '', 'PriceLog', + 1, 0, 'C', '0', '0', 'monitor:priceLog:list', 'log', 'admin', sysdate(), + N'销售价/产品价/红线价改前改后(ES)' + FROM DUAL + WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2350 OR perms = 'monitor:priceLog:list'); + +INSERT INTO sys_menu ( + menu_id, menu_name, parent_id, order_num, path, component, + is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time +) +SELECT 2351, N'查询', 2350, 1, '', NULL, + 1, 0, 'F', '0', '0', 'monitor:priceLog:list', '#', 'admin', sysdate() + FROM DUAL + WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2351); + +INSERT INTO sys_role_menu (role_id, menu_id) +SELECT 1, m.menu_id + FROM (SELECT 2350 AS menu_id UNION SELECT 2351) m + WHERE NOT EXISTS ( + SELECT 1 FROM sys_role_menu rm WHERE rm.role_id = 1 AND rm.menu_id = m.menu_id + ); diff --git a/bms-front/src/api/monitor/priceLog.js b/bms-front/src/api/monitor/priceLog.js new file mode 100644 index 00000000..5e5accca --- /dev/null +++ b/bms-front/src/api/monitor/priceLog.js @@ -0,0 +1,16 @@ +import request from '@/utils/request' + +export function listPriceLog(query) { + return request({ + url: '/monitor/priceLog/list', + method: 'get', + params: query + }) +} + +export function getPriceLog(docId) { + return request({ + url: '/monitor/priceLog/' + encodeURIComponent(docId), + method: 'get' + }) +} diff --git a/bms-front/src/views/monitor/eslog/index.vue b/bms-front/src/views/monitor/eslog/index.vue index 2e2bd94c..925c751d 100644 --- a/bms-front/src/views/monitor/eslog/index.vue +++ b/bms-front/src/views/monitor/eslog/index.vue @@ -81,7 +81,8 @@ const typeOptions = [ { label: '试算', value: 'QUOTE' }, { label: '扣减额度', value: 'CREDIT' }, { label: '欠费清除', value: 'ARREARS' }, - { label: '订单数据源同步', value: 'ORDER_SOURCE_SYNC' } + { label: '订单数据源同步', value: 'ORDER_SOURCE_SYNC' }, + { label: '价格变更', value: 'PRICE_CHANGE' } ] const statusOptions = [ diff --git a/bms-front/src/views/monitor/priceLog/index.vue b/bms-front/src/views/monitor/priceLog/index.vue new file mode 100644 index 00000000..fbfa2730 --- /dev/null +++ b/bms-front/src/views/monitor/priceLog/index.vue @@ -0,0 +1,265 @@ + + + + +