diff --git a/bms-back/bms-admin/src/main/java/com/bms/web/controller/monitor/TabOrderMonitorController.java b/bms-back/bms-admin/src/main/java/com/bms/web/controller/monitor/TabOrderMonitorController.java new file mode 100644 index 00000000..115b6019 --- /dev/null +++ b/bms-back/bms-admin/src/main/java/com/bms/web/controller/monitor/TabOrderMonitorController.java @@ -0,0 +1,76 @@ +package com.bms.web.controller.monitor; + +import java.util.Collections; +import java.util.List; +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.RequestMapping; +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.page.PageDomain; +import com.bms.common.core.page.TableDataInfo; +import com.bms.common.core.page.TableSupport; +import com.bms.common.utils.StringUtils; +import com.bms.price.domain.vo.TabOrderMonitorQuery; +import com.bms.price.domain.vo.TabOrderMonitorVo; +import com.bms.price.oracle.TabOrderMonitorService; + +/** + * 订单数据源:查询上游 Oracle TAB_ORDER。 + */ +@RestController +@RequestMapping("/monitor/orderSource") +public class TabOrderMonitorController extends BaseController +{ + @Autowired + private TabOrderMonitorService tabOrderMonitorService; + + @PreAuthorize("@ss.hasPermi('monitor:orderSource:list')") + @GetMapping("/list") + public TableDataInfo list(TabOrderMonitorQuery query) + { + TableDataInfo rsp = new TableDataInfo(); + rsp.setCode(HttpStatus.SUCCESS); + rsp.setMsg("\u67e5\u8be2\u6210\u529f"); + if (!hasRequiredFilters(query)) + { + rsp.setRows(Collections.emptyList()); + rsp.setTotal(0L); + return rsp; + } + PageDomain pageDomain = TableSupport.buildPageRequest(); + int pageNum = pageDomain.getPageNum() == null ? 1 : pageDomain.getPageNum().intValue(); + int pageSize = pageDomain.getPageSize() == null ? 10 : pageDomain.getPageSize().intValue(); + long total = tabOrderMonitorService.count(query); + List rows = total <= 0L + ? Collections.emptyList() + : tabOrderMonitorService.selectPage(query, pageNum, pageSize); + rsp.setRows(rows); + rsp.setTotal(total); + return rsp; + } + + private static boolean hasRequiredFilters(TabOrderMonitorQuery query) + { + if (query == null) + { + return false; + } + boolean hasCustomer = false; + if (query.getCustomerCodes() != null) + { + for (String code : query.getCustomerCodes()) + { + if (StringUtils.isNotEmpty(code)) + { + hasCustomer = true; + break; + } + } + } + boolean hasTime = StringUtils.isNotEmpty(query.getBeginTime()) && StringUtils.isNotEmpty(query.getEndTime()); + return hasCustomer && hasTime; + } +} diff --git a/bms-back/bms-system/src/main/java/com/bms/price/domain/vo/TabOrderMonitorQuery.java b/bms-back/bms-system/src/main/java/com/bms/price/domain/vo/TabOrderMonitorQuery.java new file mode 100644 index 00000000..70eedd06 --- /dev/null +++ b/bms-back/bms-system/src/main/java/com/bms/price/domain/vo/TabOrderMonitorQuery.java @@ -0,0 +1,28 @@ +package com.bms.price.domain.vo; + +import java.io.Serializable; +import java.util.List; +import lombok.Data; + +/** + * 订单数据源(TAB_ORDER)监控查询条件。 + * 必须传客户 + 提货时间范围,避免全表扫描。 + */ +@Data +public class TabOrderMonitorQuery implements Serializable +{ + private static final long serialVersionUID = 1L; + + /** 客户代码列表 */ + private List customerCodes; + /** 提货时间起(yyyy-MM-dd 或 yyyy-MM-dd HH:mm:ss) */ + private String beginTime; + /** 提货时间止(yyyy-MM-dd 或 yyyy-MM-dd HH:mm:ss) */ + private String endTime; + /** 客户订单号 ORDER_ID */ + private String orderId; + /** 运单号 ORG_ORDER_ID */ + private String orgOrderId; + /** 转单号 TRANSFER_ORDER_ID */ + private String transferOrderId; +} diff --git a/bms-back/bms-system/src/main/java/com/bms/price/domain/vo/TabOrderMonitorVo.java b/bms-back/bms-system/src/main/java/com/bms/price/domain/vo/TabOrderMonitorVo.java new file mode 100644 index 00000000..9fc9c405 --- /dev/null +++ b/bms-back/bms-system/src/main/java/com/bms/price/domain/vo/TabOrderMonitorVo.java @@ -0,0 +1,50 @@ +package com.bms.price.domain.vo; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +/** 订单数据源(TAB_ORDER)列表行。 */ +@Data +public class TabOrderMonitorVo implements Serializable +{ + private static final long serialVersionUID = 1L; + + /** 客户订单号 */ + private String orderId; + /** 运单号 */ + private String orgOrderId; + /** 转单号 */ + private String transferOrderId; + /** 轨迹ID */ + private String trackId; + /** 客户代码 */ + private String customerCode; + /** 客户名称 */ + private String customerName; + /** 产品代码 */ + private String productCode; + /** 产品名称 */ + private String productName; + /** 产品底级代码 */ + private String productFloorCode; + /** 国家代码 */ + private String country; + /** 国家名称 */ + private String countryName; + /** 收件人邮编 */ + private String consigneePostcode; + /** 材积系数/计费重 */ + private BigDecimal dimensionalWeightFactor; + /** 体积重 */ + private BigDecimal volumeWeight; + /** 实重 */ + private BigDecimal weight; + /** 订单状态 ORDER_STATUS */ + private Integer orderStatus; + /** 提货时间 */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date pickupDate; +} diff --git a/bms-back/bms-system/src/main/java/com/bms/price/mapper/OracleUpstreamOrderMapper.java b/bms-back/bms-system/src/main/java/com/bms/price/mapper/OracleUpstreamOrderMapper.java index 9ec7231e..f62a9de7 100644 --- a/bms-back/bms-system/src/main/java/com/bms/price/mapper/OracleUpstreamOrderMapper.java +++ b/bms-back/bms-system/src/main/java/com/bms/price/mapper/OracleUpstreamOrderMapper.java @@ -1,7 +1,9 @@ package com.bms.price.mapper; +import java.util.List; import java.util.Map; import org.apache.ibatis.annotations.Param; +import com.bms.price.domain.vo.TabOrderMonitorQuery; /** Read upstream main order from Oracle (SLAVE datasource). */ public interface OracleUpstreamOrderMapper @@ -17,4 +19,12 @@ public interface OracleUpstreamOrderMapper Map selectByBarcode(@Param("orderTable") String orderTable, @Param("trackingNo") String trackingNo); Map selectByCustomerTrackId(@Param("orderTable") String orderTable, @Param("trackingNo") String trackingNo); + + long countTabOrderMonitor(@Param("orderTable") String orderTable, @Param("query") TabOrderMonitorQuery query); + + List> selectTabOrderMonitorPage( + @Param("orderTable") String orderTable, + @Param("query") TabOrderMonitorQuery query, + @Param("startRow") long startRow, + @Param("endRow") long endRow); } diff --git a/bms-back/bms-system/src/main/java/com/bms/price/oracle/TabOrderMonitorService.java b/bms-back/bms-system/src/main/java/com/bms/price/oracle/TabOrderMonitorService.java new file mode 100644 index 00000000..cf5e8a60 --- /dev/null +++ b/bms-back/bms-system/src/main/java/com/bms/price/oracle/TabOrderMonitorService.java @@ -0,0 +1,292 @@ +package com.bms.price.oracle; + +import java.math.BigDecimal; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.github.pagehelper.PageHelper; +import com.bms.common.annotation.DataSource; +import com.bms.common.enums.DataSourceType; +import com.bms.common.exception.ServiceException; +import com.bms.common.utils.StringUtils; +import com.bms.price.config.BillingProperties; +import com.bms.price.domain.vo.TabOrderMonitorQuery; +import com.bms.price.domain.vo.TabOrderMonitorVo; +import com.bms.price.mapper.OracleUpstreamOrderMapper; + +/** + * 订单数据源:从 Oracle TAB_ORDER 分页查询(SLAVE)。 + */ +@Service +public class TabOrderMonitorService +{ + private static final Logger log = LoggerFactory.getLogger(TabOrderMonitorService.class); + + @Autowired + private OracleUpstreamOrderMapper oracleUpstreamOrderMapper; + + @Autowired + private BillingProperties billingProperties; + + @DataSource(DataSourceType.SLAVE) + public long count(TabOrderMonitorQuery query) + { + validate(query); + String table = resolveTable(); + try + { + PageHelper.clearPage(); + return oracleUpstreamOrderMapper.countTabOrderMonitor(table, query); + } + catch (RuntimeException e) + { + throw new ServiceException("Oracle TAB_ORDER count failed: " + e.getMessage()); + } + finally + { + PageHelper.clearPage(); + } + } + + @DataSource(DataSourceType.SLAVE) + public List selectPage(TabOrderMonitorQuery query, int pageNum, int pageSize) + { + validate(query); + String table = resolveTable(); + int pn = pageNum < 1 ? 1 : pageNum; + int ps = pageSize < 1 ? 10 : pageSize; + if (ps > 200) + { + ps = 200; + } + long endRow = (long) pn * ps; + long startRow = endRow - ps; + try + { + PageHelper.clearPage(); + long t0 = System.currentTimeMillis(); + List> rows = oracleUpstreamOrderMapper.selectTabOrderMonitorPage(table, query, startRow, endRow); + log.info("oracle tab_order page customerSize={} begin={} end={} page={}/{} rows={} costMs={}", + query.getCustomerCodes() == null ? 0 : query.getCustomerCodes().size(), + query.getBeginTime(), query.getEndTime(), pn, ps, + rows == null ? 0 : rows.size(), System.currentTimeMillis() - t0); + if (rows == null || rows.isEmpty()) + { + return Collections.emptyList(); + } + List list = new ArrayList(rows.size()); + for (Map row : rows) + { + list.add(toVo(row)); + } + return list; + } + catch (RuntimeException e) + { + throw new ServiceException("Oracle TAB_ORDER list failed: " + e.getMessage()); + } + finally + { + PageHelper.clearPage(); + } + } + + private void validate(TabOrderMonitorQuery query) + { + if (query == null) + { + throw new ServiceException("请先选择客户和提货时间"); + } + List codes = query.getCustomerCodes(); + if (codes == null || codes.isEmpty()) + { + throw new ServiceException("请选择客户"); + } + List cleaned = new ArrayList(); + for (String c : codes) + { + if (StringUtils.isNotEmpty(c)) + { + cleaned.add(c.trim()); + } + } + if (cleaned.isEmpty()) + { + throw new ServiceException("请选择客户"); + } + query.setCustomerCodes(cleaned); + String begin = normalizeTime(query.getBeginTime(), true); + String end = normalizeTime(query.getEndTime(), false); + if (begin == null || end == null) + { + throw new ServiceException("请选择提货时间范围"); + } + query.setBeginTime(begin); + query.setEndTime(end); + query.setOrderId(trimToNull(query.getOrderId())); + query.setOrgOrderId(trimToNull(query.getOrgOrderId())); + query.setTransferOrderId(trimToNull(query.getTransferOrderId())); + } + + private static String trimToNull(String s) + { + if (StringUtils.isEmpty(s)) + { + return null; + } + String t = s.trim(); + return t.isEmpty() ? null : t; + } + + private String resolveTable() + { + String table = billingProperties.getOracle().getOrderTable(); + if (StringUtils.isEmpty(table)) + { + throw new ServiceException("bms.billing.oracle.order-table is empty"); + } + if (!table.matches("[A-Za-z0-9_\\.]+")) + { + throw new ServiceException("invalid oracle order table name"); + } + return table; + } + + private static String normalizeTime(String raw, boolean begin) + { + if (StringUtils.isEmpty(raw)) + { + return null; + } + String s = raw.trim(); + if (s.length() == 10) + { + return begin ? (s + " 00:00:00") : (s + " 23:59:59"); + } + if (s.length() >= 19) + { + return s.substring(0, 19); + } + return s; + } + + private static TabOrderMonitorVo toVo(Map row) + { + TabOrderMonitorVo vo = new TabOrderMonitorVo(); + vo.setOrderId(str(row, "ORDER_ID")); + vo.setOrgOrderId(str(row, "ORG_ORDER_ID")); + vo.setTransferOrderId(str(row, "TRANSFER_ORDER_ID")); + vo.setTrackId(str(row, "TRACK_ID")); + vo.setCustomerCode(str(row, "CUSTOMER_CODE")); + vo.setCustomerName(str(row, "CUSTOMER_NAME")); + vo.setProductCode(str(row, "PRODUCT_CODE")); + vo.setProductName(str(row, "PRODUCT_NAME")); + vo.setProductFloorCode(str(row, "PRODUCT_FLOOR_CODE")); + vo.setCountry(str(row, "COUNTRY")); + vo.setCountryName(str(row, "COUNTRY_NAME")); + vo.setConsigneePostcode(str(row, "CONSIGNEE_POSTCODE")); + vo.setDimensionalWeightFactor(decimal(row, "DIMENSIONAL_WEIGHT_FACTOR")); + vo.setVolumeWeight(decimal(row, "VOLUME_WEIGHT")); + vo.setWeight(decimal(row, "WEIGHT")); + vo.setOrderStatus(integer(row, "ORDER_STATUS")); + vo.setPickupDate(date(row, "PICKUP_DATE")); + return vo; + } + + private static String str(Map row, String key) + { + Object v = value(row, key); + return v == null ? null : String.valueOf(v).trim(); + } + + private static Integer integer(Map row, String key) + { + Object v = value(row, key); + if (v == null) + { + return null; + } + if (v instanceof Number) + { + return Integer.valueOf(((Number) v).intValue()); + } + try + { + return Integer.valueOf(String.valueOf(v).trim()); + } + catch (Exception e) + { + return null; + } + } + + private static BigDecimal decimal(Map row, String key) + { + Object v = value(row, key); + if (v == null) + { + return null; + } + if (v instanceof BigDecimal) + { + return (BigDecimal) v; + } + if (v instanceof Number) + { + return BigDecimal.valueOf(((Number) v).doubleValue()); + } + try + { + return new BigDecimal(String.valueOf(v).trim()); + } + catch (Exception e) + { + return null; + } + } + + private static Date date(Map row, String key) + { + Object v = value(row, key); + if (v == null) + { + return null; + } + if (v instanceof Timestamp) + { + return new Date(((Timestamp) v).getTime()); + } + if (v instanceof Date) + { + return (Date) v; + } + return null; + } + + private static Object value(Map row, String key) + { + if (row == null || key == null) + { + return null; + } + if (row.containsKey(key)) + { + return row.get(key); + } + for (Map.Entry e : row.entrySet()) + { + if (e.getKey() != null && e.getKey().equalsIgnoreCase(key)) + { + return e.getValue(); + } + } + return null; + } +} diff --git a/bms-back/bms-system/src/main/resources/mapper/price/OracleUpstreamOrderMapper.xml b/bms-back/bms-system/src/main/resources/mapper/price/OracleUpstreamOrderMapper.xml index dc8cd5f4..11b04384 100644 --- a/bms-back/bms-system/src/main/resources/mapper/price/OracleUpstreamOrderMapper.xml +++ b/bms-back/bms-system/src/main/resources/mapper/price/OracleUpstreamOrderMapper.xml @@ -44,4 +44,67 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" SELECT * FROM ${orderTable} WHERE CUSTOMER_TRACK_ID = #{trackingNo} ) WHERE ROWNUM <= 1 + + + o.BL_PICKUP = 1 + AND o.ORDER_STATUS IN (3, 4, 5, 6, 7, 8, 11) + AND o.CUSTOMER_CODE IN + + #{code} + + AND o.PICKUP_DATE >= TO_TIMESTAMP(#{query.beginTime}, 'YYYY-MM-DD HH24:MI:SS') + AND o.PICKUP_DATE <= TO_TIMESTAMP(#{query.endTime}, 'YYYY-MM-DD HH24:MI:SS') + + AND o.ORDER_ID = #{query.orderId} + + + AND o.ORG_ORDER_ID = #{query.orgOrderId} + + + AND o.TRANSFER_ORDER_ID = #{query.transferOrderId} + + + + + o.ORDER_ID, + o.ORG_ORDER_ID, + o.TRANSFER_ORDER_ID, + o.TRACK_ID, + o.CUSTOMER_CODE, + o.CUSTOMER_NAME, + o.PRODUCT_CODE, + o.PRODUCT_NAME, + o.PRODUCT_FLOOR_CODE, + o.COUNTRY, + o.COUNTRY_NAME, + o.CONSIGNEE_POSTCODE, + o.DIMENSIONAL_WEIGHT_FACTOR, + o.VOLUME_WEIGHT, + o.WEIGHT, + o.ORDER_STATUS, + o.PICKUP_DATE + + + + + + diff --git a/bms-back/sql/monitor/order_source_menu.sql b/bms-back/sql/monitor/order_source_menu.sql new file mode 100644 index 00000000..53405db2 --- /dev/null +++ b/bms-back/sql/monitor/order_source_menu.sql @@ -0,0 +1,14 @@ +-- 订单数据源 under system monitor (parent_id = 2) +SET NAMES utf8mb4; + +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 2325, N'订单数据源', 2, 9, 'orderSource', 'monitor/orderSource/index', '', 'OrderSource', 1, 0, 'C', '0', '0', 'monitor:orderSource:list', 'list', 'admin', sysdate(), N'查询上游 Oracle TAB_ORDER,需客户+提货时间筛选' +FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2325 OR perms = 'monitor:orderSource: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 2326, N'查询', 2325, 1, '', NULL, 1, 0, 'F', '0', '0', 'monitor:orderSource:list', '#', 'admin', sysdate() +FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2326); + +INSERT INTO sys_role_menu (role_id, menu_id) +SELECT 1, m.menu_id FROM (SELECT 2325 AS menu_id UNION SELECT 2326) 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/orderSource.js b/bms-front/src/api/monitor/orderSource.js new file mode 100644 index 00000000..06c3f9b8 --- /dev/null +++ b/bms-front/src/api/monitor/orderSource.js @@ -0,0 +1,10 @@ +import request from '@/utils/request' + +export function listOrderSource(query) { + return request({ + url: '/monitor/orderSource/list', + method: 'get', + params: query, + timeout: 60000 + }) +} diff --git a/bms-front/src/views/monitor/orderSource/index.vue b/bms-front/src/views/monitor/orderSource/index.vue new file mode 100644 index 00000000..5bdc644a --- /dev/null +++ b/bms-front/src/views/monitor/orderSource/index.vue @@ -0,0 +1,122 @@ + + +