|
|
@@ -30,7 +30,9 @@ import javax.servlet.http.HttpServletResponse;
|
|
|
import java.net.InetAddress;
|
|
|
import java.net.NetworkInterface;
|
|
|
import java.math.BigDecimal;
|
|
|
+import java.sql.Timestamp;
|
|
|
import java.time.LocalDate;
|
|
|
+import java.time.ZoneId;
|
|
|
import java.time.format.DateTimeFormatter;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.Collections;
|
|
|
@@ -237,9 +239,189 @@ public class SalesOrderController {
|
|
|
util.exportExcel(response, list, "销售订单");
|
|
|
}
|
|
|
|
|
|
- @ApiOperation("销售订单货品明细列表")
|
|
|
+ @ApiOperation("白条分配订单货品明细(销售日期、物流线/市场/客户、产品类型)")
|
|
|
@PostMapping("/goodsDetailList")
|
|
|
- public AjaxResult goodsDetailList(@RequestBody Map<String, String> params, HttpServletRequest request) throws Exception {
|
|
|
+ public AjaxResult goodsDetailList(@RequestBody(required = false) Map<String, String> params, HttpServletRequest request) throws Exception {
|
|
|
+ if (params == null) {
|
|
|
+ params = Collections.emptyMap();
|
|
|
+ }
|
|
|
+ String saleDate = params.get("saleDate");
|
|
|
+ if (StringUtils.isBlank(saleDate)) {
|
|
|
+ throw new Exception("销售日期不能为空");
|
|
|
+ }
|
|
|
+ saleDate = saleDate.trim();
|
|
|
+ String orgId = tokenService.getLoginOrgId(request);
|
|
|
+ String lineNum = trimOrNull(params.get("lineNum"));
|
|
|
+ String marketNum = trimOrNull(params.get("marketNum"));
|
|
|
+ String customerNum = trimOrNull(params.get("customerNum"));
|
|
|
+ List<String> productTypeList = parseCommaSeparatedList(trimOrNull(params.get("productTypes")));
|
|
|
+ if (!StringUtils.isNotEmpty(productTypeList)) {
|
|
|
+ productTypeList = new ArrayList<String>();
|
|
|
+ productTypeList.add("002");
|
|
|
+ }
|
|
|
+
|
|
|
+ Map<Long, BigDecimal> allocByGoodsId = loadAllocNumByGoodsLineId(
|
|
|
+ orgId, saleDate, lineNum, marketNum, customerNum, productTypeList);
|
|
|
+ List<Map<String, Object>> list = salesOrderGoodsMapper.listGoodsDetailByConditions(
|
|
|
+ orgId, saleDate, lineNum, marketNum, customerNum, productTypeList);
|
|
|
+ fillGoodsLineUnalloc(list, allocByGoodsId);
|
|
|
+ return success(list);
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 分配表 sale_id 对应订单货品明细主键 sog.id */
|
|
|
+ private Map<Long, BigDecimal> loadAllocNumByGoodsLineId(String orgId, String saleDate,
|
|
|
+ String lineNum, String marketNum, String customerNum,
|
|
|
+ List<String> productTypeList) {
|
|
|
+ List<Map<String, Object>> rows = salesOrderGoodsMapper.listAllocNumByOrderGoodsLine(
|
|
|
+ orgId, saleDate, lineNum, marketNum, customerNum, productTypeList);
|
|
|
+ Map<Long, BigDecimal> map = new HashMap<Long, BigDecimal>();
|
|
|
+ if (StringUtils.isEmpty(rows)) {
|
|
|
+ return map;
|
|
|
+ }
|
|
|
+ for (Map<String, Object> row : rows) {
|
|
|
+ if (row == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ Long goodsId = toLongValue(row.get("sale_id"));
|
|
|
+ if (goodsId == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ map.put(goodsId, toBigDecimal(row.get("alloc_num")));
|
|
|
+ }
|
|
|
+ return map;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void fillGoodsLineUnalloc(List<Map<String, Object>> list, Map<Long, BigDecimal> allocByGoodsId) {
|
|
|
+ if (StringUtils.isEmpty(list)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ for (Map<String, Object> row : list) {
|
|
|
+ if (row == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ Long goodsId = toLongValue(row.get("id"));
|
|
|
+ BigDecimal alloc = goodsId == null ? BigDecimal.ZERO : allocByGoodsId.getOrDefault(goodsId, BigDecimal.ZERO);
|
|
|
+ BigDecimal ass = toBigDecimal(row.get("ass_num"));
|
|
|
+ BigDecimal unalloc = ass.subtract(alloc);
|
|
|
+ if (unalloc.compareTo(BigDecimal.ZERO) < 0) {
|
|
|
+ unalloc = BigDecimal.ZERO;
|
|
|
+ }
|
|
|
+ row.put("alloc_num", alloc);
|
|
|
+ row.put("unalloc_num", unalloc);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static String trimOrNull(String s) {
|
|
|
+ return StringUtils.isBlank(s) ? null : s.trim();
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 逗号分隔编码列表(如产品类型 {@code 002,003});空或 null 解析结果为空列表前由调用方处理默认 */
|
|
|
+ private static List<String> parseCommaSeparatedList(String s) {
|
|
|
+ if (StringUtils.isBlank(s)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ List<String> out = new ArrayList<String>();
|
|
|
+ for (String p : s.split(",")) {
|
|
|
+ String t = p == null ? null : p.trim();
|
|
|
+ if (StringUtils.isNotBlank(t)) {
|
|
|
+ out.add(t);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return out.isEmpty() ? null : out;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static Long toLongValue(Object v) {
|
|
|
+ if (v == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ if (v instanceof Long) {
|
|
|
+ return (Long) v;
|
|
|
+ }
|
|
|
+ if (v instanceof Integer) {
|
|
|
+ return ((Integer) v).longValue();
|
|
|
+ }
|
|
|
+ if (v instanceof Number) {
|
|
|
+ return ((Number) v).longValue();
|
|
|
+ }
|
|
|
+ String s = String.valueOf(v).trim();
|
|
|
+ if (StringUtils.isBlank(s)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ return new BigDecimal(s.replace(",", "")).longValue();
|
|
|
+ } catch (Exception e) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /** JDBC/MyBatis 常见日期类型转为 {@link Date},无法解析时返回 null */
|
|
|
+ private static Date toUtilDate(Object v) {
|
|
|
+ if (v == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ if (v instanceof Date) {
|
|
|
+ return (Date) v;
|
|
|
+ }
|
|
|
+ if (v instanceof Timestamp) {
|
|
|
+ return new Date(((Timestamp) v).getTime());
|
|
|
+ }
|
|
|
+ if (v instanceof java.sql.Date) {
|
|
|
+ return new Date(((java.sql.Date) v).getTime());
|
|
|
+ }
|
|
|
+ if (v instanceof java.time.LocalDateTime) {
|
|
|
+ return Date.from(((java.time.LocalDateTime) v).atZone(ZoneId.systemDefault()).toInstant());
|
|
|
+ }
|
|
|
+ if (v instanceof LocalDate) {
|
|
|
+ return Date.from(((LocalDate) v).atStartOfDay(ZoneId.systemDefault()).toInstant());
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 按白条分配表汇总每条订单明细({@code sales_order_goods.id} = {@code pwsa.sale_id})的最大发货日期写入 {@code delivery_date}。
|
|
|
+ */
|
|
|
+ private void attachMaxDeliveryDatePerGoodsLine(String orgId, List<Map<String, Object>> detailRows) {
|
|
|
+ if (StringUtils.isEmpty(detailRows)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ LinkedHashSet<Long> saleIds = new LinkedHashSet<Long>();
|
|
|
+ for (Map<String, Object> row : detailRows) {
|
|
|
+ if (row == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ Long id = toLongValue(row.get("id"));
|
|
|
+ if (id != null) {
|
|
|
+ saleIds.add(id);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Map<Long, Date> deliveryBySaleId = new HashMap<Long, Date>(Math.max(8, saleIds.size()));
|
|
|
+ if (!saleIds.isEmpty()) {
|
|
|
+ List<Map<String, Object>> agg = salesOrderGoodsMapper.listMaxDeliveryDateBySaleIds(orgId, new ArrayList<Long>(saleIds));
|
|
|
+ if (StringUtils.isNotEmpty(agg)) {
|
|
|
+ for (Map<String, Object> r : agg) {
|
|
|
+ if (r == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ Long sid = toLongValue(r.get("sale_id"));
|
|
|
+ if (sid == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ deliveryBySaleId.put(sid, toUtilDate(r.get("delivery_date")));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for (Map<String, Object> row : detailRows) {
|
|
|
+ if (row == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ Long id = toLongValue(row.get("id"));
|
|
|
+ row.put("delivery_date", id == null ? null : deliveryBySaleId.get(id));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @ApiOperation("按品种级别统计订单未分配片数、可分配片数")
|
|
|
+ @PostMapping("/allocationStatsByVarietyGrade")
|
|
|
+ public AjaxResult allocationStatsByVarietyGrade(@RequestBody Map<String, String> params, HttpServletRequest request) throws Exception {
|
|
|
String saleDate = params == null ? null : params.get("saleDate");
|
|
|
if (StringUtils.isBlank(saleDate)) {
|
|
|
throw new Exception("销售日期不能为空");
|
|
|
@@ -248,14 +430,116 @@ public class SalesOrderController {
|
|
|
String lineNum = params.get("lineNum");
|
|
|
String marketNum = params.get("marketNum");
|
|
|
String customerNum = params.get("customerNum");
|
|
|
- List<Map<String, Object>> list = salesOrderGoodsMapper.listGoodsDetailByConditions(
|
|
|
+ List<String> productTypeList = parseCommaSeparatedList(trimOrNull(params.get("productTypeList")));
|
|
|
+ if (productTypeList == null) {
|
|
|
+ productTypeList = parseCommaSeparatedList(trimOrNull(params.get("productTypes")));
|
|
|
+ }
|
|
|
+ if (!StringUtils.isNotEmpty(productTypeList)) {
|
|
|
+ productTypeList = new ArrayList<String>();
|
|
|
+ productTypeList.add("002");
|
|
|
+ }
|
|
|
+
|
|
|
+ List<Map<String, Object>> assSummary = salesOrderGoodsMapper.summarizeAssNumByVarietyAndGrade(
|
|
|
orgId,
|
|
|
saleDate.trim(),
|
|
|
StringUtils.isBlank(lineNum) ? null : lineNum.trim(),
|
|
|
StringUtils.isBlank(marketNum) ? null : marketNum.trim(),
|
|
|
- StringUtils.isBlank(customerNum) ? null : customerNum.trim()
|
|
|
+ StringUtils.isBlank(customerNum) ? null : customerNum.trim(),
|
|
|
+ productTypeList
|
|
|
);
|
|
|
- return success(list);
|
|
|
+ List<Map<String, Object>> availSummary = salesOrderGoodsMapper.summarizeAvailWhiteStripByVarietyGrade(
|
|
|
+ orgId, saleDate.trim(), productTypeList);
|
|
|
+ List<Map<String, Object>> allocSummary = salesOrderGoodsMapper.summarizeAllocWhiteStripByVarietyGrade(
|
|
|
+ orgId, saleDate.trim(), productTypeList);
|
|
|
+
|
|
|
+ Map<String, BigDecimal> assMap = new LinkedHashMap<String, BigDecimal>();
|
|
|
+ Map<String, BigDecimal> allocMap = new LinkedHashMap<String, BigDecimal>();
|
|
|
+ Map<String, BigDecimal> availMap = new LinkedHashMap<String, BigDecimal>();
|
|
|
+ Map<String, String> varietyMap = new LinkedHashMap<String, String>();
|
|
|
+ Map<String, String> varietyNameMap = new LinkedHashMap<String, String>();
|
|
|
+ Map<String, String> gradeMap = new LinkedHashMap<String, String>();
|
|
|
+
|
|
|
+ for (Map<String, Object> row : assSummary) {
|
|
|
+ String variety = row == null || row.get("variety") == null ? null : String.valueOf(row.get("variety"));
|
|
|
+ String grade = row == null || row.get("grade") == null ? null : String.valueOf(row.get("grade"));
|
|
|
+ if (StringUtils.isBlank(variety) || StringUtils.isBlank(grade)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ String key = variety.trim() + "\0" + grade.trim();
|
|
|
+ assMap.put(key, toBigDecimal(row.get("ass_num")));
|
|
|
+ varietyMap.put(key, variety.trim());
|
|
|
+ gradeMap.put(key, grade.trim());
|
|
|
+ Object vn = row.get("variety_name");
|
|
|
+ if (vn != null && StringUtils.isNotBlank(String.valueOf(vn))) {
|
|
|
+ varietyNameMap.put(key, String.valueOf(vn));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for (Map<String, Object> row : allocSummary) {
|
|
|
+ String variety = row == null || row.get("variety") == null ? null : String.valueOf(row.get("variety"));
|
|
|
+ String grade = row == null || row.get("grade") == null ? null : String.valueOf(row.get("grade"));
|
|
|
+ if (StringUtils.isBlank(variety) || StringUtils.isBlank(grade)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ String key = variety.trim() + "\0" + grade.trim();
|
|
|
+ allocMap.put(key, toBigDecimal(row.get("alloc_ws_num")));
|
|
|
+ varietyMap.putIfAbsent(key, variety.trim());
|
|
|
+ gradeMap.putIfAbsent(key, grade.trim());
|
|
|
+ Object vn = row.get("variety_name");
|
|
|
+ if (vn != null && StringUtils.isNotBlank(String.valueOf(vn))) {
|
|
|
+ varietyNameMap.putIfAbsent(key, String.valueOf(vn));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for (Map<String, Object> row : availSummary) {
|
|
|
+ String variety = row == null || row.get("variety") == null ? null : String.valueOf(row.get("variety"));
|
|
|
+ String grade = row == null || row.get("grade") == null ? null : String.valueOf(row.get("grade"));
|
|
|
+ if (StringUtils.isBlank(variety) || StringUtils.isBlank(grade)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ String key = variety.trim() + "\0" + grade.trim();
|
|
|
+ availMap.put(key, toBigDecimal(row.get("avail_ws_num")));
|
|
|
+ varietyMap.putIfAbsent(key, variety.trim());
|
|
|
+ gradeMap.putIfAbsent(key, grade.trim());
|
|
|
+ Object vn = row.get("variety_name");
|
|
|
+ if (vn != null && StringUtils.isNotBlank(String.valueOf(vn))) {
|
|
|
+ varietyNameMap.putIfAbsent(key, String.valueOf(vn));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ LinkedHashSet<String> keys = new LinkedHashSet<String>();
|
|
|
+ keys.addAll(assMap.keySet());
|
|
|
+ keys.addAll(availMap.keySet());
|
|
|
+ keys.addAll(allocMap.keySet());
|
|
|
+
|
|
|
+ List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
|
|
|
+ for (String key : keys) {
|
|
|
+ BigDecimal assNum = assMap.getOrDefault(key, BigDecimal.ZERO);
|
|
|
+ BigDecimal allocNum = allocMap.getOrDefault(key, BigDecimal.ZERO);
|
|
|
+ BigDecimal orderUnAlloc = assNum.subtract(allocNum);
|
|
|
+ if (orderUnAlloc.compareTo(BigDecimal.ZERO) < 0) {
|
|
|
+ orderUnAlloc = BigDecimal.ZERO;
|
|
|
+ }
|
|
|
+ BigDecimal availNum = availMap.getOrDefault(key, BigDecimal.ZERO);
|
|
|
+
|
|
|
+ Map<String, Object> row = new LinkedHashMap<String, Object>();
|
|
|
+ row.put("variety", varietyMap.get(key));
|
|
|
+ row.put("varietyName", varietyNameMap.get(key));
|
|
|
+ row.put("grade", gradeMap.get(key));
|
|
|
+ row.put("orderUnAllocNum", orderUnAlloc);
|
|
|
+ row.put("availAllocNum", availNum);
|
|
|
+ result.add(row);
|
|
|
+ }
|
|
|
+ result.sort((a, b) -> {
|
|
|
+ String av = a.get("variety") == null ? "" : String.valueOf(a.get("variety"));
|
|
|
+ String bv = b.get("variety") == null ? "" : String.valueOf(b.get("variety"));
|
|
|
+ int c = av.compareTo(bv);
|
|
|
+ if (c != 0) {
|
|
|
+ return c;
|
|
|
+ }
|
|
|
+ String ag = a.get("grade") == null ? "" : String.valueOf(a.get("grade"));
|
|
|
+ String bg = b.get("grade") == null ? "" : String.valueOf(b.get("grade"));
|
|
|
+ return ag.compareTo(bg);
|
|
|
+ });
|
|
|
+ return success(result);
|
|
|
}
|
|
|
|
|
|
@ApiOperation("销售订单审核")
|
|
|
@@ -400,9 +684,7 @@ public class SalesOrderController {
|
|
|
.orderByAsc("market_num")
|
|
|
.orderByAsc("id");
|
|
|
List<BaseMarket> allMarkets = baseMarketService.list(marketQw);
|
|
|
- Map<String, List<BaseMarket>> marketsByLineNum = allMarkets.stream()
|
|
|
- .filter(m -> StringUtils.isNotBlank(m.getLineNum()))
|
|
|
- .collect(Collectors.groupingBy(m -> m.getLineNum().trim(), LinkedHashMap::new, Collectors.toList()));
|
|
|
+ Map<String, List<BaseMarket>> marketsByLineNum = groupMarketsByLineNum(allMarkets);
|
|
|
|
|
|
QueryWrapper<RelCustomerMarket> relQw = new QueryWrapper<RelCustomerMarket>()
|
|
|
.eq("org_id", orgId)
|
|
|
@@ -413,260 +695,171 @@ public class SalesOrderController {
|
|
|
List<BaseCustomer> customers = customerService.list(new QueryWrapper<BaseCustomer>()
|
|
|
.eq("org_id", orgId)
|
|
|
.and(w -> w.eq("del_flag", "0").or().isNull("del_flag")));
|
|
|
- Map<String, String> customerNameMap = customers.stream()
|
|
|
- .filter(c -> StringUtils.isNotBlank(c.getCustomerNum()))
|
|
|
- .collect(Collectors.toMap(BaseCustomer::getCustomerNum,
|
|
|
- c -> c.getCustomerName() != null ? c.getCustomerName() : "",
|
|
|
- (a, b) -> a, LinkedHashMap::new));
|
|
|
+ Map<String, String> customerNameMap = buildCustomerNumToNameMap(customers);
|
|
|
|
|
|
- Map<String, List<RelCustomerMarket>> relsByLineAndMarket = new LinkedHashMap<String, List<RelCustomerMarket>>();
|
|
|
- for (RelCustomerMarket r : allRels) {
|
|
|
- if (StringUtils.isBlank(r.getLineNum()) || StringUtils.isBlank(r.getMarketNum())) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- String key = r.getLineNum().trim() + "\0" + r.getMarketNum().trim();
|
|
|
- relsByLineAndMarket.computeIfAbsent(key, k -> new ArrayList<RelCustomerMarket>()).add(r);
|
|
|
- }
|
|
|
-
|
|
|
- List<Map<String, Object>> tree = new ArrayList<Map<String, Object>>();
|
|
|
- for (BaseLine line : lines) {
|
|
|
- String lineNum = line.getLineNum() == null ? "" : line.getLineNum().trim();
|
|
|
- Map<String, Object> lineNode = new LinkedHashMap<String, Object>();
|
|
|
- lineNode.put("id", "line:" + lineNum + ":" + line.getId());
|
|
|
- lineNode.put("label", StringUtils.isNotBlank(line.getLineName()) ? line.getLineName() : lineNum);
|
|
|
- lineNode.put("type", "line");
|
|
|
- lineNode.put("lineNum", lineNum);
|
|
|
- lineNode.put("lineName", line.getLineName());
|
|
|
-
|
|
|
- List<Map<String, Object>> marketChildren = new ArrayList<Map<String, Object>>();
|
|
|
- List<BaseMarket> markets = marketsByLineNum.getOrDefault(lineNum, new ArrayList<BaseMarket>());
|
|
|
- for (BaseMarket market : markets) {
|
|
|
- String marketNum = market.getMarketNum() == null ? "" : market.getMarketNum().trim();
|
|
|
- Map<String, Object> marketNode = new LinkedHashMap<String, Object>();
|
|
|
- marketNode.put("id", "market:" + lineNum + ":" + marketNum + ":" + market.getId());
|
|
|
- marketNode.put("label", StringUtils.isNotBlank(market.getMarketName()) ? market.getMarketName() : marketNum);
|
|
|
- marketNode.put("type", "market");
|
|
|
- marketNode.put("lineNum", lineNum);
|
|
|
- marketNode.put("marketNum", marketNum);
|
|
|
- marketNode.put("marketName", market.getMarketName());
|
|
|
-
|
|
|
- String relKey = lineNum + "\0" + marketNum;
|
|
|
- List<RelCustomerMarket> rels = relsByLineAndMarket.getOrDefault(relKey, new ArrayList<RelCustomerMarket>());
|
|
|
- Set<String> seenCustomer = new LinkedHashSet<String>();
|
|
|
- List<Map<String, Object>> customerChildren = new ArrayList<Map<String, Object>>();
|
|
|
- for (RelCustomerMarket rel : rels) {
|
|
|
- String customerNum = rel.getCustomerNum() == null ? "" : rel.getCustomerNum().trim();
|
|
|
- if (StringUtils.isBlank(customerNum) || !seenCustomer.add(customerNum)) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- String customerName = StringUtils.isNotBlank(rel.getCustomerName())
|
|
|
- ? rel.getCustomerName()
|
|
|
- : customerNameMap.getOrDefault(customerNum, customerNum);
|
|
|
- Map<String, Object> custNode = new LinkedHashMap<String, Object>();
|
|
|
- custNode.put("id", "customer:" + lineNum + ":" + marketNum + ":" + customerNum + ":" + rel.getId());
|
|
|
- custNode.put("label", customerName);
|
|
|
- custNode.put("type", "customer");
|
|
|
- custNode.put("lineNum", lineNum);
|
|
|
- custNode.put("marketNum", marketNum);
|
|
|
- custNode.put("customerNum", customerNum);
|
|
|
- custNode.put("customerName", customerName);
|
|
|
- custNode.put("relId", rel.getId());
|
|
|
- custNode.put("leaf", true);
|
|
|
- customerChildren.add(custNode);
|
|
|
- }
|
|
|
- marketNode.put("children", customerChildren);
|
|
|
- marketChildren.add(marketNode);
|
|
|
- }
|
|
|
- lineNode.put("children", marketChildren);
|
|
|
- tree.add(lineNode);
|
|
|
- }
|
|
|
- return success(tree);
|
|
|
+ Map<String, List<RelCustomerMarket>> relsByLineAndMarket = groupRelsByLineAndMarket(allRels);
|
|
|
+ return success(buildLineMarketCustomerElTree(lines, marketsByLineNum, relsByLineAndMarket, customerNameMap, null, null, null));
|
|
|
}
|
|
|
|
|
|
- @ApiOperation("物流线-市场-客户三级树(按销售日期和产品类型统计goodsCount)")
|
|
|
+ @ApiOperation("物流线-市场-客户三级树(白条分配),按销售日期和产品类型统计goodsCount")
|
|
|
@GetMapping("/lineMarketCustomerStats")
|
|
|
public AjaxResult lineMarketCustomerStats(
|
|
|
@ApiParam(value = "销售日期(yyyy-MM-dd)", required = true)
|
|
|
@RequestParam("saleDate")
|
|
|
- @DateTimeFormat(pattern = "yyyy-MM-dd") Date saleDate,
|
|
|
+ @DateTimeFormat(pattern = "yyyy-MM-dd") String saleDate,
|
|
|
@ApiParam(value = "产品类型(productType),不传默认002")
|
|
|
@RequestParam(value = "productType", required = false) String productType,
|
|
|
HttpServletRequest request) {
|
|
|
if (saleDate == null) {
|
|
|
return AjaxResult.error("销售日期不能为空");
|
|
|
}
|
|
|
- String statProductType = StringUtils.isBlank(productType) ? "002" : productType.trim();
|
|
|
+ List<String> productTypeList = new ArrayList<>();
|
|
|
+ productTypeList.add(StringUtils.isBlank(productType) ? "002" : productType.trim());
|
|
|
String orgId = tokenService.getLoginOrgId(request);
|
|
|
|
|
|
- List<SalesOrder> saleDateOrders = salesOrderService.list(new QueryWrapper<SalesOrder>()
|
|
|
- .eq("org_id", orgId)
|
|
|
- .eq("del_flag", "0")
|
|
|
- .eq("sale_date", saleDate)
|
|
|
- .orderByDesc("id"));
|
|
|
- if (saleDateOrders == null || saleDateOrders.isEmpty()) {
|
|
|
- return success(new ArrayList<Map<String, Object>>());
|
|
|
- }
|
|
|
- Set<String> orderNums = saleDateOrders.stream()
|
|
|
- .map(SalesOrder::getOrderNum)
|
|
|
- .filter(StringUtils::isNotBlank)
|
|
|
- .map(String::trim)
|
|
|
- .collect(Collectors.toCollection(LinkedHashSet::new));
|
|
|
- if (orderNums.isEmpty()) {
|
|
|
- return success(new ArrayList<Map<String, Object>>());
|
|
|
- }
|
|
|
- Map<String, String> customerByOrderNum = saleDateOrders.stream()
|
|
|
- .filter(o -> StringUtils.isNotBlank(o.getOrderNum()) && StringUtils.isNotBlank(o.getCustomerNum()))
|
|
|
- .collect(Collectors.toMap(o -> o.getOrderNum().trim(), o -> o.getCustomerNum().trim(), (a, b) -> a, LinkedHashMap::new));
|
|
|
- Set<String> orderCustomers = new LinkedHashSet<String>(customerByOrderNum.values());
|
|
|
- if (orderCustomers.isEmpty()) {
|
|
|
+ Set<String> lineNumSet = new HashSet<String>();
|
|
|
+ Set<String> marketNumSet = new HashSet<String>();
|
|
|
+ Set<String> customerNumSet = new HashSet<String>();
|
|
|
+ Map<String, BigDecimal> lineAssNumCountMap = new HashMap<String, BigDecimal>();
|
|
|
+ Map<String, BigDecimal> marketAssNumCountMap = new HashMap<String, BigDecimal>();
|
|
|
+ Map<String, BigDecimal> customerAssNumCountMap = new HashMap<String, BigDecimal>();
|
|
|
+ List<Map<String, Object>> list = salesOrderGoodsMapper.listLineMarketCustomerByOrders(orgId, saleDate, productTypeList);
|
|
|
+ collectLineMarketCustomerFromOrderRows(list, lineNumSet, marketNumSet, customerNumSet,
|
|
|
+ lineAssNumCountMap, marketAssNumCountMap, customerAssNumCountMap);
|
|
|
+ if (lineNumSet.isEmpty() || marketNumSet.isEmpty() || customerNumSet.isEmpty()) {
|
|
|
return success(new ArrayList<Map<String, Object>>());
|
|
|
}
|
|
|
|
|
|
- List<SalesOrderGoods> orderGoodsList = new ArrayList<SalesOrderGoods>();
|
|
|
- for (List<String> batch : partitionList(new ArrayList<String>(orderNums), SQL_IN_BATCH_SIZE)) {
|
|
|
- orderGoodsList.addAll(salesOrderGoodsService.list(new QueryWrapper<SalesOrderGoods>()
|
|
|
- .eq("org_id", orgId)
|
|
|
- .eq("del_flag", "0")
|
|
|
- .in("order_num", batch)));
|
|
|
- }
|
|
|
- Set<String> goodsNums = orderGoodsList.stream()
|
|
|
- .map(SalesOrderGoods::getGoodsNum)
|
|
|
- .filter(StringUtils::isNotBlank)
|
|
|
- .map(String::trim)
|
|
|
- .collect(Collectors.toCollection(LinkedHashSet::new));
|
|
|
- Set<String> allowedGoodsNums = new LinkedHashSet<String>();
|
|
|
- if (!goodsNums.isEmpty()) {
|
|
|
- List<String> goodsNumList = new ArrayList<String>(goodsNums);
|
|
|
- for (List<String> batch : partitionList(goodsNumList, SQL_IN_BATCH_SIZE)) {
|
|
|
- List<BaseMaterial> materials = baseMaterialService.list(new QueryWrapper<BaseMaterial>()
|
|
|
- .eq("org_id", orgId)
|
|
|
- .eq("del_flag", "0")
|
|
|
- .eq("product_type", statProductType)
|
|
|
- .in("goods_num", batch));
|
|
|
- for (BaseMaterial m : materials) {
|
|
|
- if (m != null && StringUtils.isNotBlank(m.getGoodsNum())) {
|
|
|
- allowedGoodsNums.add(m.getGoodsNum().trim());
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+ LineMarketCustomerTreeContext ctx = loadLineMarketCustomerTreeContext(orgId, lineNumSet, marketNumSet, customerNumSet);
|
|
|
+ return success(buildLineMarketCustomerElTree(ctx.lines, ctx.marketsByLineNum, ctx.relsByLineAndMarket, ctx.customerNameMap,
|
|
|
+ lineAssNumCountMap, marketAssNumCountMap, customerAssNumCountMap));
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @ApiOperation("物流线-市场-客户三级树(分割品副产品分配)")
|
|
|
+ @PostMapping("/segmentedProductsCustomerTree")
|
|
|
+ public AjaxResult segmentedProductsCustomerTree(@RequestBody(required = false) Map<String, String> params,
|
|
|
+ HttpServletRequest request) throws Exception {
|
|
|
+ if (params == null) {
|
|
|
+ params = Collections.emptyMap();
|
|
|
}
|
|
|
|
|
|
- Map<String, BigDecimal> customerGoodsCountMap = new LinkedHashMap<String, BigDecimal>();
|
|
|
- for (String customerNum : orderCustomers) {
|
|
|
- customerGoodsCountMap.put(customerNum, BigDecimal.ZERO);
|
|
|
+ String productionDate = params.get("productionDate");
|
|
|
+ if (StringUtils.isBlank(productionDate)) {
|
|
|
+ throw new Exception("生产日期不能为空");
|
|
|
}
|
|
|
- for (SalesOrderGoods goods : orderGoodsList) {
|
|
|
- if (goods == null || StringUtils.isBlank(goods.getOrderNum()) || StringUtils.isBlank(goods.getGoodsNum())) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- String goodsNum = goods.getGoodsNum().trim();
|
|
|
- if (!allowedGoodsNums.contains(goodsNum)) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- String customerNum = customerByOrderNum.get(goods.getOrderNum().trim());
|
|
|
- if (StringUtils.isBlank(customerNum)) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- BigDecimal qty = parseMoney(goods.getAssNum());
|
|
|
- customerGoodsCountMap.put(customerNum, customerGoodsCountMap.getOrDefault(customerNum, BigDecimal.ZERO).add(qty == null ? BigDecimal.ZERO : qty));
|
|
|
+ List<String> productTypeList = parseCommaSeparatedList(trimOrNull(params.get("productTypes")));
|
|
|
+ if (!StringUtils.isNotEmpty(productTypeList)) {
|
|
|
+ throw new Exception("产品类型不能为空");
|
|
|
}
|
|
|
|
|
|
- List<RelCustomerMarket> allRels = new ArrayList<RelCustomerMarket>();
|
|
|
- List<String> customerList = new ArrayList<String>(orderCustomers);
|
|
|
- for (List<String> batch : partitionList(customerList, SQL_IN_BATCH_SIZE)) {
|
|
|
- allRels.addAll(relCustomerMarketService.list(new QueryWrapper<RelCustomerMarket>()
|
|
|
- .eq("org_id", orgId)
|
|
|
- .and(w -> w.eq("del_flag", "0").or().isNull("del_flag"))
|
|
|
- .in("customer_num", batch)
|
|
|
- .orderByDesc("id")));
|
|
|
- }
|
|
|
- if (allRels.isEmpty()) {
|
|
|
+ String orgId = tokenService.getLoginOrgId(request);
|
|
|
+
|
|
|
+ Set<String> lineNumSet = new HashSet<String>();
|
|
|
+ Set<String> marketNumSet = new HashSet<String>();
|
|
|
+ Set<String> customerNumSet = new HashSet<String>();
|
|
|
+ List<Map<String, Object>> list = salesOrderGoodsMapper.listLineMarketCustomerByOrders(orgId, productionDate, productTypeList);
|
|
|
+ collectLineMarketCustomerFromOrderRows(list, lineNumSet, marketNumSet, customerNumSet, null, null, null);
|
|
|
+ if (lineNumSet.isEmpty() || marketNumSet.isEmpty() || customerNumSet.isEmpty()) {
|
|
|
return success(new ArrayList<Map<String, Object>>());
|
|
|
}
|
|
|
|
|
|
- LinkedHashSet<String> relLineNums = new LinkedHashSet<String>();
|
|
|
- HashSet<String> relPairs = new HashSet<String>();
|
|
|
- for (RelCustomerMarket r : allRels) {
|
|
|
- if (r == null || StringUtils.isBlank(r.getLineNum()) || StringUtils.isBlank(r.getMarketNum())) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- String ln = r.getLineNum().trim();
|
|
|
- String mn = r.getMarketNum().trim();
|
|
|
- relLineNums.add(ln);
|
|
|
- relPairs.add(ln + "\0" + mn);
|
|
|
+ LineMarketCustomerTreeContext ctx = loadLineMarketCustomerTreeContext(orgId, lineNumSet, marketNumSet, customerNumSet);
|
|
|
+ return success(buildLineMarketCustomerElTree(ctx.lines, ctx.marketsByLineNum, ctx.relsByLineAndMarket, ctx.customerNameMap, null, null, null));
|
|
|
+ }
|
|
|
+
|
|
|
+ @ApiOperation("分割品副产品订单货品明细(销售日期 sale_date、物流线/市场/客户、产品类型;并附白条分配最大发货日期)")
|
|
|
+ @PostMapping("/segmentedProductGoodsDetailList")
|
|
|
+ public AjaxResult segmentedProductGoodsDetailList(@RequestBody(required = false) Map<String, String> params,
|
|
|
+ HttpServletRequest request) throws Exception {
|
|
|
+ if (params == null) {
|
|
|
+ params = Collections.emptyMap();
|
|
|
}
|
|
|
- if (relLineNums.isEmpty()) {
|
|
|
- return success(new ArrayList<Map<String, Object>>());
|
|
|
+ String productionDate = params.get("productionDate");
|
|
|
+ if (StringUtils.isBlank(productionDate)) {
|
|
|
+ throw new Exception("销售日期不能为空");
|
|
|
}
|
|
|
-
|
|
|
- List<BaseLine> lines = new ArrayList<BaseLine>();
|
|
|
- Map<String, BaseLine> lineByNum = new LinkedHashMap<String, BaseLine>();
|
|
|
- for (List<String> batch : partitionList(new ArrayList<String>(relLineNums), SQL_IN_BATCH_SIZE)) {
|
|
|
- List<BaseLine> chunk = baseLineService.list(new QueryWrapper<BaseLine>()
|
|
|
- .eq("org_id", orgId)
|
|
|
- .in("line_num", batch)
|
|
|
- .and(w -> w.eq("del_flag", "0").or().isNull("del_flag"))
|
|
|
- .orderByAsc("line_num")
|
|
|
- .orderByAsc("id"));
|
|
|
- for (BaseLine line : chunk) {
|
|
|
- if (line != null && StringUtils.isNotBlank(line.getLineNum())) {
|
|
|
- String k = line.getLineNum().trim();
|
|
|
- lineByNum.putIfAbsent(k, line);
|
|
|
- }
|
|
|
- }
|
|
|
+ String orgId = tokenService.getLoginOrgId(request);
|
|
|
+ String lineNum = trimOrNull(params.get("lineNum"));
|
|
|
+ String marketNum = trimOrNull(params.get("marketNum"));
|
|
|
+ String customerNum = trimOrNull(params.get("customerNum"));
|
|
|
+ List<String> productTypeList = parseCommaSeparatedList(trimOrNull(params.get("productTypes")));
|
|
|
+ if (!StringUtils.isNotEmpty(productTypeList)) {
|
|
|
+ throw new Exception("产品类型不能为空");
|
|
|
}
|
|
|
- lines.addAll(lineByNum.values());
|
|
|
- lines.sort(Comparator.comparing(l -> l.getLineNum() == null ? "" : l.getLineNum().trim()));
|
|
|
|
|
|
- Map<String, BaseMarket> marketDedupe = new LinkedHashMap<String, BaseMarket>();
|
|
|
- for (List<String> batch : partitionList(new ArrayList<String>(relLineNums), SQL_IN_BATCH_SIZE)) {
|
|
|
- List<BaseMarket> chunk = baseMarketService.list(new QueryWrapper<BaseMarket>()
|
|
|
- .eq("org_id", orgId)
|
|
|
- .in("line_num", batch)
|
|
|
- .and(w -> w.eq("del_flag", "0").or().isNull("del_flag"))
|
|
|
- .orderByAsc("market_num")
|
|
|
- .orderByAsc("id"));
|
|
|
- for (BaseMarket m : chunk) {
|
|
|
- if (m == null || StringUtils.isBlank(m.getLineNum()) || StringUtils.isBlank(m.getMarketNum())) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- String ln = m.getLineNum().trim();
|
|
|
- String mn = m.getMarketNum().trim();
|
|
|
- if (!relPairs.contains(ln + "\0" + mn)) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- String mk = ln + "\0" + mn;
|
|
|
- marketDedupe.putIfAbsent(mk, m);
|
|
|
- }
|
|
|
+ List<Map<String, Object>> list = salesOrderGoodsMapper.listSegmentedProductOrderGoodsDetail(
|
|
|
+ orgId, productionDate.trim(), lineNum, marketNum, customerNum, productTypeList);
|
|
|
+ attachMaxDeliveryDatePerGoodsLine(orgId, list);
|
|
|
+ return success(list);
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 市场按所属物流线分组(保留插入顺序)。 */
|
|
|
+ private static Map<String, List<BaseMarket>> groupMarketsByLineNum(List<BaseMarket> allMarkets) {
|
|
|
+ if (allMarkets == null || allMarkets.isEmpty()) {
|
|
|
+ return new LinkedHashMap<String, List<BaseMarket>>();
|
|
|
}
|
|
|
- Map<String, List<BaseMarket>> marketsByLineNum = marketDedupe.values().stream()
|
|
|
+ return allMarkets.stream()
|
|
|
.filter(m -> StringUtils.isNotBlank(m.getLineNum()))
|
|
|
.collect(Collectors.groupingBy(m -> m.getLineNum().trim(), LinkedHashMap::new, Collectors.toList()));
|
|
|
+ }
|
|
|
|
|
|
- List<BaseCustomer> customers = new ArrayList<BaseCustomer>();
|
|
|
- for (List<String> batch : partitionList(customerList, SQL_IN_BATCH_SIZE)) {
|
|
|
- customers.addAll(customerService.list(new QueryWrapper<BaseCustomer>()
|
|
|
- .eq("org_id", orgId)
|
|
|
- .and(w -> w.eq("del_flag", "0").or().isNull("del_flag"))
|
|
|
- .in("customer_num", batch)));
|
|
|
- }
|
|
|
- Map<String, String> customerNameMap = customers.stream()
|
|
|
- .filter(c -> StringUtils.isNotBlank(c.getCustomerNum()))
|
|
|
- .collect(Collectors.toMap(BaseCustomer::getCustomerNum,
|
|
|
- c -> c.getCustomerName() != null ? c.getCustomerName() : "",
|
|
|
- (a, b) -> a, LinkedHashMap::new));
|
|
|
-
|
|
|
+ /** 客户关系按 line_num + market_num 分组。 */
|
|
|
+ private static Map<String, List<RelCustomerMarket>> groupRelsByLineAndMarket(List<RelCustomerMarket> allRels) {
|
|
|
Map<String, List<RelCustomerMarket>> relsByLineAndMarket = new LinkedHashMap<String, List<RelCustomerMarket>>();
|
|
|
+ if (allRels == null || allRels.isEmpty()) {
|
|
|
+ return relsByLineAndMarket;
|
|
|
+ }
|
|
|
for (RelCustomerMarket r : allRels) {
|
|
|
- if (StringUtils.isBlank(r.getLineNum()) || StringUtils.isBlank(r.getMarketNum())) {
|
|
|
+ if (r == null || StringUtils.isBlank(r.getLineNum()) || StringUtils.isBlank(r.getMarketNum())) {
|
|
|
continue;
|
|
|
}
|
|
|
String key = r.getLineNum().trim() + "\0" + r.getMarketNum().trim();
|
|
|
relsByLineAndMarket.computeIfAbsent(key, k -> new ArrayList<RelCustomerMarket>()).add(r);
|
|
|
}
|
|
|
+ return relsByLineAndMarket;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static Map<String, String> buildCustomerNumToNameMap(List<BaseCustomer> customers) {
|
|
|
+ if (customers == null || customers.isEmpty()) {
|
|
|
+ return new LinkedHashMap<String, String>();
|
|
|
+ }
|
|
|
+ return customers.stream()
|
|
|
+ .filter(c -> StringUtils.isNotBlank(c.getCustomerNum()))
|
|
|
+ .collect(Collectors.toMap(BaseCustomer::getCustomerNum,
|
|
|
+ c -> c.getCustomerName() != null ? c.getCustomerName() : "",
|
|
|
+ (a, b) -> a, LinkedHashMap::new));
|
|
|
+ }
|
|
|
|
|
|
+ /**
|
|
|
+ * 物流线 → 市场 → 客户 三级 el-tree 节点(与 rel、客户名称补充逻辑一致)。
|
|
|
+ */
|
|
|
+ private static List<Map<String, Object>> buildLineMarketCustomerElTree(
|
|
|
+ List<BaseLine> lines,
|
|
|
+ Map<String, List<BaseMarket>> marketsByLineNum,
|
|
|
+ Map<String, List<RelCustomerMarket>> relsByLineAndMarket,
|
|
|
+ Map<String, String> customerNameMap,
|
|
|
+ Map<String, BigDecimal> lineAssNumCountMap,
|
|
|
+ Map<String, BigDecimal> marketAssNumCountMap,
|
|
|
+ Map<String, BigDecimal> customerAssNumCountMap) {
|
|
|
List<Map<String, Object>> tree = new ArrayList<Map<String, Object>>();
|
|
|
+ if (lines == null || lines.isEmpty()) {
|
|
|
+ return tree;
|
|
|
+ }
|
|
|
+ Map<String, String> nameMap = customerNameMap != null ? customerNameMap : new LinkedHashMap<String, String>();
|
|
|
+ if (lineAssNumCountMap == null) {
|
|
|
+ lineAssNumCountMap = new HashMap<>();
|
|
|
+ }
|
|
|
+ if (marketAssNumCountMap == null) {
|
|
|
+ marketAssNumCountMap = new HashMap<>();
|
|
|
+ }
|
|
|
+ if (customerAssNumCountMap == null) {
|
|
|
+ customerAssNumCountMap = new HashMap<>();
|
|
|
+ }
|
|
|
for (BaseLine line : lines) {
|
|
|
+ if (line == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
String lineNum = line.getLineNum() == null ? "" : line.getLineNum().trim();
|
|
|
Map<String, Object> lineNode = new LinkedHashMap<String, Object>();
|
|
|
lineNode.put("id", "line:" + lineNum + ":" + line.getId());
|
|
|
@@ -674,11 +867,16 @@ public class SalesOrderController {
|
|
|
lineNode.put("type", "line");
|
|
|
lineNode.put("lineNum", lineNum);
|
|
|
lineNode.put("lineName", line.getLineName());
|
|
|
+ lineNode.put("goodsCount", lineAssNumCountMap.getOrDefault(lineNum, BigDecimal.ZERO));
|
|
|
|
|
|
- BigDecimal lineGoodsCount = BigDecimal.ZERO;
|
|
|
List<Map<String, Object>> marketChildren = new ArrayList<Map<String, Object>>();
|
|
|
- List<BaseMarket> markets = marketsByLineNum.getOrDefault(lineNum, new ArrayList<BaseMarket>());
|
|
|
+ List<BaseMarket> markets = marketsByLineNum == null
|
|
|
+ ? new ArrayList<BaseMarket>()
|
|
|
+ : marketsByLineNum.getOrDefault(lineNum, new ArrayList<BaseMarket>());
|
|
|
for (BaseMarket market : markets) {
|
|
|
+ if (market == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
String marketNum = market.getMarketNum() == null ? "" : market.getMarketNum().trim();
|
|
|
Map<String, Object> marketNode = new LinkedHashMap<String, Object>();
|
|
|
marketNode.put("id", "market:" + lineNum + ":" + marketNum + ":" + market.getId());
|
|
|
@@ -687,21 +885,25 @@ public class SalesOrderController {
|
|
|
marketNode.put("lineNum", lineNum);
|
|
|
marketNode.put("marketNum", marketNum);
|
|
|
marketNode.put("marketName", market.getMarketName());
|
|
|
+ marketNode.put("goodsCount", marketAssNumCountMap.getOrDefault(lineNum + "\0" + marketNum, BigDecimal.ZERO));
|
|
|
|
|
|
- BigDecimal marketGoodsCount = BigDecimal.ZERO;
|
|
|
String relKey = lineNum + "\0" + marketNum;
|
|
|
- List<RelCustomerMarket> rels = relsByLineAndMarket.getOrDefault(relKey, new ArrayList<RelCustomerMarket>());
|
|
|
+ List<RelCustomerMarket> rels = relsByLineAndMarket == null
|
|
|
+ ? new ArrayList<RelCustomerMarket>()
|
|
|
+ : relsByLineAndMarket.getOrDefault(relKey, new ArrayList<RelCustomerMarket>());
|
|
|
Set<String> seenCustomer = new LinkedHashSet<String>();
|
|
|
List<Map<String, Object>> customerChildren = new ArrayList<Map<String, Object>>();
|
|
|
for (RelCustomerMarket rel : rels) {
|
|
|
+ if (rel == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
String customerNum = rel.getCustomerNum() == null ? "" : rel.getCustomerNum().trim();
|
|
|
if (StringUtils.isBlank(customerNum) || !seenCustomer.add(customerNum)) {
|
|
|
continue;
|
|
|
}
|
|
|
- BigDecimal customerGoodsCount = customerGoodsCountMap.getOrDefault(customerNum, BigDecimal.ZERO);
|
|
|
String customerName = StringUtils.isNotBlank(rel.getCustomerName())
|
|
|
? rel.getCustomerName()
|
|
|
- : customerNameMap.getOrDefault(customerNum, customerNum);
|
|
|
+ : nameMap.getOrDefault(customerNum, customerNum);
|
|
|
Map<String, Object> custNode = new LinkedHashMap<String, Object>();
|
|
|
custNode.put("id", "customer:" + lineNum + ":" + marketNum + ":" + customerNum + ":" + rel.getId());
|
|
|
custNode.put("label", customerName);
|
|
|
@@ -711,27 +913,112 @@ public class SalesOrderController {
|
|
|
custNode.put("customerNum", customerNum);
|
|
|
custNode.put("customerName", customerName);
|
|
|
custNode.put("relId", rel.getId());
|
|
|
- custNode.put("goodsCount", customerGoodsCount);
|
|
|
custNode.put("leaf", true);
|
|
|
+ custNode.put("goodsCount", customerAssNumCountMap.getOrDefault(lineNum + "\0" + marketNum + "\0" + customerNum, BigDecimal.ZERO));
|
|
|
customerChildren.add(custNode);
|
|
|
- marketGoodsCount = marketGoodsCount.add(customerGoodsCount);
|
|
|
- }
|
|
|
- if (customerChildren.isEmpty()) {
|
|
|
- continue;
|
|
|
}
|
|
|
- marketNode.put("goodsCount", marketGoodsCount);
|
|
|
marketNode.put("children", customerChildren);
|
|
|
marketChildren.add(marketNode);
|
|
|
- lineGoodsCount = lineGoodsCount.add(marketGoodsCount);
|
|
|
}
|
|
|
- if (marketChildren.isEmpty()) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- lineNode.put("goodsCount", lineGoodsCount);
|
|
|
lineNode.put("children", marketChildren);
|
|
|
tree.add(lineNode);
|
|
|
}
|
|
|
- return success(tree);
|
|
|
+ return tree;
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 线-市场-客户树:主数据与 rel 分组结果(供 {@link #loadLineMarketCustomerTreeContext} 使用)。 */
|
|
|
+ private static final class LineMarketCustomerTreeContext {
|
|
|
+ final List<BaseLine> lines;
|
|
|
+ final Map<String, List<BaseMarket>> marketsByLineNum;
|
|
|
+ final Map<String, List<RelCustomerMarket>> relsByLineAndMarket;
|
|
|
+ final Map<String, String> customerNameMap;
|
|
|
+
|
|
|
+ LineMarketCustomerTreeContext(List<BaseLine> lines,
|
|
|
+ Map<String, List<BaseMarket>> marketsByLineNum,
|
|
|
+ Map<String, List<RelCustomerMarket>> relsByLineAndMarket,
|
|
|
+ Map<String, String> customerNameMap) {
|
|
|
+ this.lines = lines;
|
|
|
+ this.marketsByLineNum = marketsByLineNum;
|
|
|
+ this.relsByLineAndMarket = relsByLineAndMarket;
|
|
|
+ this.customerNameMap = customerNameMap;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 从 {@code listLineMarketCustomerByOrders} 结果收集线/市场/客户编号;
|
|
|
+ * 三张 ass 汇总 Map 均非 null 时按 {@code ass_num} 累加(否则仅收集编号)。
|
|
|
+ */
|
|
|
+ private void collectLineMarketCustomerFromOrderRows(List<Map<String, Object>> rows,
|
|
|
+ Set<String> lineNumSet,
|
|
|
+ Set<String> marketNumSet,
|
|
|
+ Set<String> customerNumSet,
|
|
|
+ Map<String, BigDecimal> lineAssNumCountMap,
|
|
|
+ Map<String, BigDecimal> marketAssNumCountMap,
|
|
|
+ Map<String, BigDecimal> customerAssNumCountMap) {
|
|
|
+ if (StringUtils.isEmpty(rows)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ boolean sumAss = lineAssNumCountMap != null && marketAssNumCountMap != null && customerAssNumCountMap != null;
|
|
|
+ for (Map<String, Object> map : rows) {
|
|
|
+ if (map == null) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ String lineNum = map.get("line_num") == null ? null : String.valueOf(map.get("line_num")).trim();
|
|
|
+ String marketNum = map.get("market_num") == null ? null : String.valueOf(map.get("market_num")).trim();
|
|
|
+ String customerNum = map.get("customer_num") == null ? null : String.valueOf(map.get("customer_num")).trim();
|
|
|
+ if (StringUtils.isAnyBlank(lineNum, marketNum, customerNum)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ lineNumSet.add(lineNum);
|
|
|
+ marketNumSet.add(marketNum);
|
|
|
+ customerNumSet.add(customerNum);
|
|
|
+ if (sumAss) {
|
|
|
+ BigDecimal assNum = toBigDecimal(map.get("ass_num"));
|
|
|
+ lineAssNumCountMap.merge(lineNum, assNum, BigDecimal::add);
|
|
|
+ marketAssNumCountMap.merge(lineNum + "\0" + marketNum, assNum, BigDecimal::add);
|
|
|
+ customerAssNumCountMap.merge(lineNum + "\0" + marketNum + "\0" + customerNum, assNum, BigDecimal::add);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 按编号集合加载物流线、市场、客户关系与客户名称(树组装共用)。
|
|
|
+ */
|
|
|
+ private LineMarketCustomerTreeContext loadLineMarketCustomerTreeContext(String orgId,
|
|
|
+ Set<String> lineNumSet,
|
|
|
+ Set<String> marketNumSet,
|
|
|
+ Set<String> customerNumSet) {
|
|
|
+ QueryWrapper<BaseLine> lineQw = new QueryWrapper<BaseLine>()
|
|
|
+ .eq("org_id", orgId)
|
|
|
+ .in("line_num", new ArrayList<String>(lineNumSet))
|
|
|
+ .and(w -> w.eq("del_flag", "0").or().isNull("del_flag"))
|
|
|
+ .orderByAsc("line_name");
|
|
|
+ List<BaseLine> lines = baseLineService.list(lineQw);
|
|
|
+
|
|
|
+ QueryWrapper<BaseMarket> marketQw = new QueryWrapper<BaseMarket>()
|
|
|
+ .eq("org_id", orgId)
|
|
|
+ .in("market_num", new ArrayList<String>(marketNumSet))
|
|
|
+ .and(w -> w.eq("del_flag", "0").or().isNull("del_flag"))
|
|
|
+ .orderByAsc("market_name");
|
|
|
+ List<BaseMarket> allMarkets = baseMarketService.list(marketQw);
|
|
|
+ Map<String, List<BaseMarket>> marketsByLineNum = groupMarketsByLineNum(allMarkets);
|
|
|
+
|
|
|
+ QueryWrapper<RelCustomerMarket> relQw = new QueryWrapper<RelCustomerMarket>()
|
|
|
+ .eq("org_id", orgId)
|
|
|
+ .in("customer_num", new ArrayList<String>(customerNumSet))
|
|
|
+ .and(w -> w.eq("del_flag", "0").or().isNull("del_flag"))
|
|
|
+ .orderByDesc("id");
|
|
|
+ List<RelCustomerMarket> allRels = relCustomerMarketService.list(relQw);
|
|
|
+
|
|
|
+ List<BaseCustomer> allCustomers = customerService.list(new QueryWrapper<BaseCustomer>()
|
|
|
+ .eq("org_id", orgId)
|
|
|
+ .in("customer_num", new ArrayList<String>(customerNumSet))
|
|
|
+ .and(w -> w.eq("del_flag", "0").or().isNull("del_flag"))
|
|
|
+ .orderByAsc("customer_name"));
|
|
|
+ Map<String, String> customerNameMap = buildCustomerNumToNameMap(allCustomers);
|
|
|
+
|
|
|
+ Map<String, List<RelCustomerMarket>> relsByLineAndMarket = groupRelsByLineAndMarket(allRels);
|
|
|
+ return new LineMarketCustomerTreeContext(lines, marketsByLineNum, relsByLineAndMarket, customerNameMap);
|
|
|
}
|
|
|
|
|
|
private static <T> List<List<T>> partitionList(List<T> list, int batchSize) {
|
|
|
@@ -1068,6 +1355,18 @@ public class SalesOrderController {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private BigDecimal toBigDecimal(Object value) {
|
|
|
+ if (value == null) {
|
|
|
+ return BigDecimal.ZERO;
|
|
|
+ }
|
|
|
+ if (value instanceof BigDecimal) {
|
|
|
+ return (BigDecimal) value;
|
|
|
+ }
|
|
|
+ String s = String.valueOf(value);
|
|
|
+ BigDecimal n = parseMoney(s);
|
|
|
+ return n == null ? BigDecimal.ZERO : n;
|
|
|
+ }
|
|
|
+
|
|
|
private String formatMoney(BigDecimal n) {
|
|
|
if (n == null) {
|
|
|
return null;
|