package com.vincent.rsf.openApi.service.phyz.impl;
|
|
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONObject;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.cfg.CoercionAction;
|
import com.fasterxml.jackson.databind.cfg.CoercionInputShape;
|
import com.vincent.rsf.framework.exception.CoolException;
|
import com.vincent.rsf.openApi.config.PlatformProperties;
|
import com.vincent.rsf.openApi.entity.app.OpenApiOrder;
|
import com.vincent.rsf.openApi.entity.app.OpenApiOrderItem;
|
import com.vincent.rsf.openApi.entity.app.OpenApiOrderItemMap;
|
import com.vincent.rsf.openApi.entity.app.OpenApiOrderReportEvent;
|
import com.vincent.rsf.openApi.entity.constant.WmsConstant;
|
import com.vincent.rsf.openApi.entity.dto.CommonResponse;
|
import com.vincent.rsf.openApi.entity.phyz.*;
|
import com.vincent.rsf.openApi.entity.params.ReportDataParam;
|
import com.vincent.rsf.openApi.entity.params.ReportParams;
|
import com.vincent.rsf.openApi.mapper.OpenApiOrderItemMapMapper;
|
import com.vincent.rsf.openApi.mapper.OpenApiOrderItemMapper;
|
import com.vincent.rsf.openApi.mapper.OpenApiOrderMapper;
|
import com.vincent.rsf.openApi.mapper.OpenApiOrderReportEventMapper;
|
import com.vincent.rsf.openApi.service.WmsErpService;
|
import com.vincent.rsf.openApi.service.phyz.ErpReportService;
|
import com.vincent.rsf.openApi.utils.ParamsMapUtils;
|
import com.vincent.rsf.openApi.utils.SslUtils;
|
import lombok.extern.slf4j.Slf4j;
|
import org.apache.commons.lang3.StringUtils;
|
import org.apache.http.client.methods.HttpPost;
|
import org.apache.http.entity.StringEntity;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.http.impl.client.HttpClients;
|
import org.apache.http.util.EntityUtils;
|
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
import org.apache.http.client.config.RequestConfig;
|
import org.springframework.http.HttpEntity;
|
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpMethod;
|
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.client.ClientHttpResponse;
|
import org.springframework.stereotype.Service;
|
import org.springframework.web.client.RestTemplate;
|
|
import jakarta.annotation.PostConstruct;
|
import jakarta.annotation.Resource;
|
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.TrustManager;
|
import javax.net.ssl.X509TrustManager;
|
import java.lang.reflect.Field;
|
import java.security.cert.X509Certificate;
|
import java.io.IOException;
|
import java.io.UnsupportedEncodingException;
|
import java.math.BigDecimal;
|
import java.math.RoundingMode;
|
import java.security.MessageDigest;
|
import java.security.NoSuchAlgorithmException;
|
import java.util.*;
|
import java.util.stream.Collectors;
|
|
@Slf4j
|
@Service
|
public class ErpReportServiceImpl implements ErpReportService {
|
|
private static String ERP_REPORT_URL;
|
|
private CloseableHttpClient httpClient;
|
|
@Resource
|
private PlatformProperties.ErpApi erpApi;
|
@Resource
|
private PlatformProperties.WmsApi wmsApi;
|
@Resource
|
private WmsErpService wmsErpService;
|
@Resource
|
private RestTemplate restTemplate;
|
@Resource
|
private OpenApiOrderMapper openApiOrderMapper;
|
@Resource
|
private OpenApiOrderItemMapper openApiOrderItemMapper;
|
@Resource
|
private OpenApiOrderItemMapMapper openApiOrderItemMapMapper;
|
@Resource
|
private OpenApiOrderReportEventMapper openApiOrderReportEventMapper;
|
|
private static final BigDecimal ZERO = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
|
|
|
@PostConstruct
|
public void init() {
|
ERP_REPORT_URL = erpApi.getErpUrl();
|
}
|
|
@Override
|
public String syncMaterial(List<Material> materialList){
|
if (materialList.isEmpty()) {
|
throw new CoolException("参数不能为空!!");
|
}
|
/**WMS基础配置链接*/
|
String wmsUrl = wmsApi.getHost() + ":" + wmsApi.getPort() + WmsConstant.SYNC_MATNRS;
|
HttpHeaders headers = new HttpHeaders();
|
headers.add("Content-Type", "application/json");
|
headers.add("api-version", "v2.0");
|
// Material -> BaseMatParms 字段一一对应后再下发
|
List<Map<String, Object>> baseMatParamsList = materialToBaseMatParams(materialList);
|
HttpEntity httpEntity2 = new HttpEntity<>(baseMatParamsList, headers);//cs
|
// sync/warehouse
|
ResponseEntity<String> exchange = restTemplate.exchange(wmsUrl, HttpMethod.POST, httpEntity2, String.class);//cs
|
log.info("同步物料信息返回结果: {}", exchange);
|
if (Objects.isNull(exchange.getBody())) {
|
throw new CoolException("查询失败!!");
|
} else {
|
ObjectMapper objectMapper = new ObjectMapper();
|
objectMapper.coercionConfigDefaults().setCoercion(CoercionInputShape.EmptyString, CoercionAction.AsEmpty);
|
try {
|
CommonResponse result = objectMapper.readValue(exchange.getBody(), CommonResponse.class);
|
if (result.getCode() == 200) {
|
// JSONObject object = JSONObject.parseObject(JSONObject.toJSONString(result.getData()));
|
return "200";
|
} else {
|
return result.getMsg();
|
// throw new CoolException("查询失败!!");
|
}
|
} catch (JsonProcessingException e) {
|
return e.getMessage();
|
// throw new CoolException(e.getMessage());
|
}
|
}
|
}
|
|
/**
|
* Material 字段映射为 server 端 BaseMatParms 字段
|
*/
|
private List<Map<String, Object>> materialToBaseMatParams(List<Material> materialList) {
|
List<Map<String, Object>> mappedList = new ArrayList<>();
|
for (Material material : materialList) {
|
if (Objects.isNull(material)) {
|
continue;
|
}
|
Map<String, Object> map = new HashMap<>();
|
map.put("maktx", material.getMakTx());
|
map.put("matnr", material.getMatNr());
|
map.put("groupName", material.getGroupName());
|
map.put("model", material.getModel());
|
map.put("weight", material.getWeight() == null ? null : material.getWeight().toString());
|
map.put("color", material.getColor());
|
map.put("size", material.getSize());
|
map.put("spec", material.getSpec());
|
map.put("describle", material.getDescribe());
|
map.put("unit", material.getUnit());
|
map.put("operateType", material.getOperateType());
|
mappedList.add(map);
|
}
|
return mappedList;
|
}
|
|
@Override
|
public String syncWareHouse(List<Warehouse> warehouseList){
|
if (warehouseList.isEmpty()) {
|
throw new CoolException("参数不能为空!!");
|
}
|
/**WMS基础配置链接*/
|
String wmsUrl = wmsApi.getHost() + ":" + wmsApi.getPort() + WmsConstant.SYNC_WAREHOUSE;
|
HttpHeaders headers = new HttpHeaders();
|
headers.add("Content-Type", "application/json");
|
headers.add("api-version", "v2.0");
|
// Warehouse -> WarehouseParams 字段一一对应后再下发
|
List<Map<String, Object>> warehouseParamsList = warehouseToWarehouseParams(warehouseList);
|
HttpEntity httpEntity2 = new HttpEntity<>(warehouseParamsList, headers);//cs
|
// sync/warehouse
|
ResponseEntity<String> exchange = restTemplate.exchange(wmsUrl, HttpMethod.POST, httpEntity2, String.class);//cs
|
log.info("同步仓库信息返回结果: {}", exchange);
|
if (Objects.isNull(exchange.getBody())) {
|
throw new CoolException("查询失败!!");
|
} else {
|
ObjectMapper objectMapper = new ObjectMapper();
|
objectMapper.coercionConfigDefaults().setCoercion(CoercionInputShape.EmptyString, CoercionAction.AsEmpty);
|
try {
|
CommonResponse result = objectMapper.readValue(exchange.getBody(), CommonResponse.class);
|
if (result.getCode() == 200) {
|
// JSONObject object = JSONObject.parseObject(JSONObject.toJSONString(result.getData()));
|
return "200";
|
} else {
|
return result.getMsg();
|
// throw new CoolException("查询失败!!");
|
}
|
} catch (JsonProcessingException e) {
|
return e.getMessage();
|
// throw new CoolException(e.getMessage());
|
}
|
}
|
}
|
@Override
|
public String syncCustomer(List<Customer> customerList){
|
if (customerList.isEmpty()) {
|
throw new CoolException("参数不能为空!!");
|
}
|
/**WMS基础配置链接*/
|
String wmsUrl = wmsApi.getHost() + ":" + wmsApi.getPort() + WmsConstant.SYNC_COMPANIES;
|
HttpHeaders headers = new HttpHeaders();
|
headers.add("Content-Type", "application/json");
|
headers.add("api-version", "v2.0");
|
// Customer -> CompaniesParam 字段一一对应后再下发
|
List<Map<String, Object>> companiesParamsList = customerToCompaniesParams(customerList);
|
HttpEntity httpEntity2 = new HttpEntity<>(companiesParamsList, headers);//cs
|
ResponseEntity<String> exchange = restTemplate.exchange(wmsUrl, HttpMethod.POST, httpEntity2, String.class);//cs
|
log.info("同步客户信息返回结果: {}", exchange);
|
if (Objects.isNull(exchange.getBody())) {
|
throw new CoolException("查询失败!!");
|
} else {
|
ObjectMapper objectMapper = new ObjectMapper();
|
objectMapper.coercionConfigDefaults().setCoercion(CoercionInputShape.EmptyString, CoercionAction.AsEmpty);
|
try {
|
CommonResponse result = objectMapper.readValue(exchange.getBody(), CommonResponse.class);
|
if (result.getCode() == 200) {
|
return "200";
|
} else {
|
return result.getMsg();
|
}
|
} catch (JsonProcessingException e) {
|
return e.getMessage();
|
}
|
}
|
}
|
|
@Override
|
public String syncSupplier(List<Supplier> supplierList){
|
if (supplierList.isEmpty()) {
|
throw new CoolException("参数不能为空!!");
|
}
|
/**WMS基础配置链接*/
|
String wmsUrl = wmsApi.getHost() + ":" + wmsApi.getPort() + WmsConstant.SYNC_COMPANIES;
|
HttpHeaders headers = new HttpHeaders();
|
headers.add("Content-Type", "application/json");
|
headers.add("api-version", "v2.0");
|
// Supplier -> supplierParams 字段一一对应后再下发
|
List<Map<String, Object>> supplierParamsList = customerToSupplierParams(supplierList);
|
HttpEntity httpEntity2 = new HttpEntity<>(supplierParamsList, headers);//cs
|
ResponseEntity<String> exchange = restTemplate.exchange(wmsUrl, HttpMethod.POST, httpEntity2, String.class);//cs
|
log.info("同步客户信息返回结果: {}", exchange);
|
if (Objects.isNull(exchange.getBody())) {
|
throw new CoolException("查询失败!!");
|
} else {
|
ObjectMapper objectMapper = new ObjectMapper();
|
objectMapper.coercionConfigDefaults().setCoercion(CoercionInputShape.EmptyString, CoercionAction.AsEmpty);
|
try {
|
CommonResponse result = objectMapper.readValue(exchange.getBody(), CommonResponse.class);
|
if (result.getCode() == 200) {
|
return "200";
|
} else {
|
return result.getMsg();
|
}
|
} catch (JsonProcessingException e) {
|
return e.getMessage();
|
}
|
}
|
}
|
|
/**
|
* Warehouse 字段映射为 server 端 WarehouseParams 字段
|
*/
|
private List<Map<String, Object>> warehouseToWarehouseParams(List<Warehouse> warehouseList) {
|
List<Map<String, Object>> mappedList = new ArrayList<>();
|
for (Warehouse warehouse : warehouseList) {
|
if (Objects.isNull(warehouse)) {
|
continue;
|
}
|
Map<String, Object> map = new HashMap<>();
|
map.put("name", warehouse.getWareHouseName());
|
map.put("code", warehouse.getWareHouseId());
|
map.put("factory", warehouse.getUseOrgName());
|
map.put("factoryId", warehouse.getUseOrgId());
|
map.put("address", warehouse.getAddress());
|
map.put("type", null);
|
map.put("longitude", null);
|
map.put("latitude", null);
|
map.put("operateType", warehouse.getOperateType());
|
mappedList.add(map);
|
}
|
return mappedList;
|
}
|
|
/**
|
* Customer 字段映射为 server 端 CompaniesParam 字段
|
*/
|
private List<Map<String, Object>> customerToCompaniesParams(List<Customer> customerList) {
|
List<Map<String, Object>> mappedList = new ArrayList<>();
|
int rowNum = 0;
|
for (Customer customer : customerList) {
|
rowNum++;
|
if (Objects.isNull(customer)) {
|
continue;
|
}
|
if (StringUtils.isBlank(customer.getCustomerId())) {
|
throw new CoolException("客户同步失败:第" + rowNum + "行客户编码为空");
|
}
|
if (StringUtils.isBlank(customer.getCustomerName())) {
|
throw new CoolException("客户同步失败:第" + rowNum + "行客户名称为空");
|
}
|
Map<String, Object> map = new HashMap<>();
|
map.put("name", customer.getCustomerName());
|
map.put("nameEn", null);
|
map.put("breifCode", customer.getCustomerNickName());
|
// server 端类型转换使用中文描述
|
map.put("type", "客户");
|
map.put("contact", customer.getContact());
|
map.put("tel", customer.getTelephone());
|
map.put("email", customer.getEmail());
|
map.put("pcode", null);
|
map.put("city", customer.getCustomerGroup());
|
map.put("province", null);
|
map.put("address", customer.getAddress());
|
map.put("code", customer.getCustomerId());
|
map.put("operateType", customer.getOperateType());
|
mappedList.add(map);
|
}
|
return mappedList;
|
}
|
|
/**
|
* Customer 字段映射为 server 端 CompaniesParam 字段
|
*/
|
private List<Map<String, Object>> customerToSupplierParams(List<Supplier> supplierList) {
|
List<Map<String, Object>> mappedList = new ArrayList<>();
|
for (Supplier supplier : supplierList) {
|
if (Objects.isNull(supplier)) {
|
continue;
|
}
|
Map<String, Object> map = new HashMap<>();
|
map.put("name", supplier.getSupplierName());
|
map.put("nameEn", null);
|
map.put("breifCode", supplier.getSupplierName());
|
// server 端类型转换使用中文描述
|
map.put("type", supplier.getType());
|
map.put("contact", supplier.getContact());
|
map.put("tel", supplier.getTelephone());
|
map.put("email", supplier.getEmail());
|
map.put("pcode", null);
|
map.put("city", supplier.getSupplierGroup());
|
map.put("province", null);
|
map.put("address", supplier.getAddress());
|
map.put("code", supplier.getSupplierId());
|
map.put("operateType", supplier.getOperateType());
|
mappedList.add(map);
|
}
|
return mappedList;
|
}
|
|
@Override
|
public String addOrderToServer(Order order) {
|
if (Objects.isNull(order.getOrderNo()) || order.getOrderNo().isEmpty()) {
|
throw new CoolException("订单号不能为空!!");
|
}
|
/**WMS基础配置链接*/
|
String wmsUrl = wmsApi.getHost() + ":" + wmsApi.getPort() + WmsConstant.MODIFY_ORDER_DETLS;
|
HttpHeaders headers = new HttpHeaders();
|
headers.add("Content-Type", "application/json");
|
headers.add("api-version", "v2.0");
|
|
List<Map<String, Object>> maps = new ArrayList<>();
|
Map<String, Object> mapParams = new HashMap<>();
|
// mapParams.put("orderNo", params.getOrderNo());
|
// mapParams.put("anfme", params.getAnfme());
|
// mapParams.put("type", params.getType());
|
// mapParams.put("wkType", params.getWkType());
|
// mapParams.put("exceStatus", params.getExceStatus());
|
// mapParams.put("orderItems", params.getOrderItems());
|
// maps.add(mapParams);
|
|
JSONObject params = JSONObject.parseObject(JSON.toJSONString(order));
|
JSONObject mappedData = ParamsMapUtils.apiMaps("erp", "orderId", params);
|
mappedData.put("updateBy", "erp");
|
mapParams = objectToMap(mappedData);
|
maps.add(mapParams);
|
log.info("修改订单信息及状态: {}, 请求参数: {}", wmsUrl, JSONArray.toJSONString(maps));
|
HttpEntity<List<Map<String, Object>>> httpEntity = new HttpEntity<>(maps, headers);
|
ArrayList<Order> orders = new ArrayList<>();
|
orders.add(order);
|
HttpEntity httpEntity2 = new HttpEntity<>(orders, headers);//cs
|
// asnOrder/items/save
|
ResponseEntity<String> exchange = restTemplate.exchange(wmsUrl, HttpMethod.POST, httpEntity2, String.class);//cs
|
log.info("订单修改返回结果: {}", exchange);
|
if (Objects.isNull(exchange.getBody())) {
|
throw new CoolException("查询失败!!");
|
} else {
|
ObjectMapper objectMapper = new ObjectMapper();
|
objectMapper.coercionConfigDefaults().setCoercion(CoercionInputShape.EmptyString, CoercionAction.AsEmpty);
|
try {
|
CommonResponse result = objectMapper.readValue(exchange.getBody(), CommonResponse.class);
|
if (result.getCode() == 200) {
|
// JSONObject object = JSONObject.parseObject(JSONObject.toJSONString(result.getData()));
|
return "200";
|
} else {
|
return result.getMsg();
|
// throw new CoolException("查询失败!!");
|
}
|
} catch (JsonProcessingException e) {
|
return e.getMessage();
|
// throw new CoolException(e.getMessage());
|
}
|
}
|
|
|
// ErpOpParams erpOpParams = new ErpOpParams();
|
// erpOpParams.set
|
//
|
// wmsErpService.updateOrderDetl(ErpOpParams params);
|
|
// CommonResponse updateOrderDetl()
|
//
|
// asnOrderService.saveOrderAndItems(params, getLoginUserId());
|
}
|
|
@Override
|
public String addOrderToServerNew(Order order) {
|
if (Objects.isNull(order) || StringUtils.isBlank(order.getOrderNo())) {
|
throw new CoolException("订单号不能为空!!");
|
}
|
if (Objects.isNull(order.getOrderItems()) || order.getOrderItems().isEmpty()) {
|
throw new CoolException("订单明细不能为空!!");
|
}
|
|
OpenApiOrder persistedOrder = saveOpenApiOrder(order);
|
List<OpenApiOrderItem> persistedItems = saveOpenApiOrderItems(persistedOrder, order.getOrderItems());
|
saveOpenApiOrderItemMappings(persistedOrder, persistedItems);
|
|
Order mergedOrder = buildMergedOrder(order);
|
String dispatchResult = addOrderToServer(mergedOrder);
|
if (!"200".equals(dispatchResult)) {
|
return dispatchResult;
|
}
|
return "200";
|
}
|
|
@Override
|
public CommonResponse reportOrderNew(Object params) {
|
if (Objects.isNull(params)) {
|
throw new CoolException("参数不能为空!!");
|
}
|
JSONObject root = JSONObject.parseObject(JSON.toJSONString(params));
|
|
String eventId = pickString(root, "eventId", "EventId");
|
String taskNo = pickString(root, "taskNo", "TaskNo");
|
String reportNo = pickString(root, "reportNo", "ReportNo");
|
if (StringUtils.isBlank(eventId) && StringUtils.isBlank(taskNo) && StringUtils.isBlank(reportNo)) {
|
throw new CoolException("幂等键不能为空(eventId/taskNo/reportNo)");
|
}
|
|
if (existsReportEvent(eventId, taskNo, reportNo)) {
|
return CommonResponse.ok("重复回传已忽略");
|
}
|
OpenApiOrderReportEvent reportEvent = saveReportEvent(eventId, taskNo, reportNo, pickString(root, "orderNo", "WMSNO"), root.toJSONString());
|
|
JSONArray dataArray = pickArray(root, "Data", "data");
|
if (Objects.isNull(dataArray) || dataArray.isEmpty()) {
|
return CommonResponse.error("回传明细为空");
|
}
|
|
int allocateCount = 0;
|
int erpReportCount = 0;
|
List<String> errors = new ArrayList<>();
|
|
for (int i = 0; i < dataArray.size(); i++) {
|
JSONObject row = dataArray.getJSONObject(i);
|
String orderNo = pickString(row, "WMSNO", "wmsNo", "orderNo", "OrderNo");
|
String matnrCode = pickString(row, "ItemCode", "itemCode", "matNr", "MatNr");
|
String batch = pickString(row, "Batch", "batch", "GoodsNO", "goodsNo");
|
BigDecimal doneQty = pickDecimal(row, "qty", "doneQty", "InQty", "OutQty");
|
if (StringUtils.isBlank(orderNo) || StringUtils.isBlank(matnrCode) || doneQty.compareTo(ZERO) <= 0) {
|
errors.add("第" + (i + 1) + "行缺少必要字段(WMSNO/ItemCode/数量)");
|
continue;
|
}
|
doneQty = doneQty.setScale(2, RoundingMode.HALF_UP);
|
|
try {
|
int singleAllocated = allocateMergedDoneQty(orderNo, matnrCode, batch, doneQty);
|
allocateCount += singleAllocated;
|
erpReportCount += reportReadyLinesToErp(orderNo);
|
refreshOrderFinishStatus(orderNo);
|
} catch (Exception e) {
|
log.error("处理回传失败,orderNo={}, matnr={}, batch={}", orderNo, matnrCode, batch, e);
|
errors.add("第" + (i + 1) + "行处理失败:" + e.getMessage());
|
}
|
}
|
|
if (!errors.isEmpty()) {
|
reportEvent.setStatus(2);
|
openApiOrderReportEventMapper.updateById(reportEvent);
|
return CommonResponse.error("处理完成,但存在异常:" + String.join(" | ", errors));
|
}
|
reportEvent.setStatus(1);
|
openApiOrderReportEventMapper.updateById(reportEvent);
|
|
Map<String, Object> result = new HashMap<>();
|
result.put("allocatedCount", allocateCount);
|
result.put("erpReportCount", erpReportCount);
|
return CommonResponse.ok(result);
|
}
|
|
private OpenApiOrder saveOpenApiOrder(Order order) {
|
OpenApiOrder existing = openApiOrderMapper.selectOne(new LambdaQueryWrapper<OpenApiOrder>()
|
.eq(OpenApiOrder::getCode, order.getOrderNo())
|
.last("limit 1"));
|
|
BigDecimal totalQty = sumOrderItemQty(order.getOrderItems());
|
Date businessTime = toDate(order.getBusinessTime());
|
OpenApiOrder target = Objects.isNull(existing) ? new OpenApiOrder() : existing;
|
target.setCode(order.getOrderNo())
|
.setType(order.getType())
|
.setWkType(order.getWkType())
|
.setAnfme(totalQty)
|
.setQty(ZERO)
|
.setWorkQty(ZERO)
|
.setExceStatus(0)
|
.setStatus(1)
|
.setBusinessTime(businessTime)
|
.setOrderInternalCode(order.getOrderInternalCode())
|
.setStationId(order.getStationId())
|
.setStockDirect(order.getStockDirect())
|
.setCustomerId(order.getCustomerId())
|
.setCustomerName(order.getCustomerName())
|
.setSupplierId(order.getSupplierId())
|
.setSupplierName(order.getSupplierName())
|
.setStockOrgId(order.getStockOrgId())
|
.setStockOrgName(order.getStockOrgName())
|
.setPurchaseOrgId(order.getPurchaseOrgId())
|
.setPurchaseOrgName(order.getPurchaseOrgName())
|
.setPurchaseUserId(order.getPurchaseUserId())
|
.setPurchaseUserName(order.getPurchaseUserName())
|
.setPrdOrgId(order.getPrdOrgId())
|
.setPrdOrgName(order.getPrdOrgName())
|
.setSaleOrgId(order.getSaleOrgId())
|
.setSaleOrgName(order.getSaleOrgName())
|
.setSaleUserId(order.getSaleUserId())
|
.setSaleUserName(order.getSaleUserName());
|
|
if (Objects.isNull(existing)) {
|
openApiOrderMapper.insert(target);
|
} else {
|
openApiOrderMapper.updateById(target);
|
openApiOrderItemMapper.delete(new LambdaQueryWrapper<OpenApiOrderItem>().eq(OpenApiOrderItem::getOrderId, target.getId()));
|
openApiOrderItemMapMapper.delete(new LambdaQueryWrapper<OpenApiOrderItemMap>().eq(OpenApiOrderItemMap::getOrderId, target.getId()));
|
}
|
return target;
|
}
|
|
private List<OpenApiOrderItem> saveOpenApiOrderItems(OpenApiOrder order, List<OrderItem> orderItems) {
|
List<OpenApiOrderItem> saved = new ArrayList<>();
|
for (OrderItem src : orderItems) {
|
OpenApiOrderItem target = new OpenApiOrderItem()
|
.setOrderId(order.getId())
|
.setOrderCode(order.getCode())
|
.setPlatItemId(src.getLineId())
|
.setPlatWorkCode(src.getPlanNo())
|
.setMatnrCode(src.getMatNr())
|
.setMaktx(src.getMakTx())
|
.setModel(src.getModel())
|
.setSpec(src.getSpec())
|
.setAnfme(toDecimal(src.getAnfme()))
|
.setStockUnit(src.getUnit())
|
.setWorkQty(ZERO)
|
.setQty(ZERO)
|
.setBatch(src.getBatch())
|
.setMemo(src.getMemo())
|
.setTargetWarehouseId(src.getTargetWarehouseId())
|
.setSourceWarehouseId(src.getSourceWarehouseId())
|
.setOwnerId(src.getOwnerId())
|
.setBaseUnit(src.getBaseUnit())
|
.setUseOrgId(src.getUseOrgId())
|
.setUseOrgName(src.getUseOrgName())
|
.setErpClsId(src.getErpClsId())
|
.setPriceUnitId(src.getPriceUnitId())
|
.setInStockType(src.getInStockType())
|
.setOwnerTypeId(src.getOwnerTypeId())
|
.setOwnerName(src.getOwnerName())
|
.setKeeperTypeId(src.getKeeperTypeId())
|
.setKeeperId(src.getKeeperId())
|
.setKeeperName(src.getKeeperName())
|
.setStatus(1)
|
.setDeleted(0);
|
openApiOrderItemMapper.insert(target);
|
saved.add(target);
|
}
|
return saved;
|
}
|
|
private void saveOpenApiOrderItemMappings(OpenApiOrder order, List<OpenApiOrderItem> items) {
|
Map<String, List<OpenApiOrderItem>> grouped = items.stream().collect(Collectors.groupingBy(i -> mergeKey(i.getMatnrCode(), i.getBatch())));
|
for (List<OpenApiOrderItem> sameGroupItems : grouped.values()) {
|
sameGroupItems.sort(Comparator.comparing(OpenApiOrderItem::getId));
|
for (int i = 0; i < sameGroupItems.size(); i++) {
|
OpenApiOrderItem item = sameGroupItems.get(i);
|
OpenApiOrderItemMap map = new OpenApiOrderItemMap()
|
.setOrderId(order.getId())
|
.setOrderCode(order.getCode())
|
.setSourceItemId(item.getId())
|
.setSourceLineId(item.getPlatItemId())
|
.setMergeMatnrCode(defaultString(item.getMatnrCode()))
|
.setMergeBatch(defaultString(item.getBatch()))
|
.setSeqNo(i + 1)
|
.setSourceQty(defaultQty(item.getAnfme()))
|
.setAllocatedQty(ZERO)
|
.setReportedQty(ZERO)
|
.setStatus(1)
|
.setDeleted(0);
|
openApiOrderItemMapMapper.insert(map);
|
}
|
}
|
}
|
|
private Order buildMergedOrder(Order source) {
|
Order merged = new Order()
|
.setOrderNo(source.getOrderNo())
|
.setOrderInternalCode(source.getOrderInternalCode())
|
.setWkType(source.getWkType())
|
.setCreateTime(source.getCreateTime())
|
.setBusinessTime(source.getBusinessTime())
|
.setStockDirect(source.getStockDirect())
|
.setStationId(source.getStationId())
|
.setCustomerId(source.getCustomerId())
|
.setCustomerName(source.getCustomerName())
|
.setSupplierId(source.getSupplierId())
|
.setSupplierName(source.getSupplierName())
|
.setStockOrgId(source.getStockOrgId())
|
.setStockOrgName(source.getStockOrgName())
|
.setPurchaseOrgId(source.getPurchaseOrgId())
|
.setPurchaseOrgName(source.getPurchaseOrgName())
|
.setPurchaseUserId(source.getPurchaseUserId())
|
.setPurchaseUserName(source.getPurchaseUserName())
|
.setPrdOrgId(source.getPrdOrgId())
|
.setPrdOrgName(source.getPrdOrgName())
|
.setSaleOrgId(source.getSaleOrgId())
|
.setSaleOrgName(source.getSaleOrgName())
|
.setSaleUserId(source.getSaleUserId())
|
.setSaleUserName(source.getSaleUserName());
|
merged.setType(source.getType());
|
Map<String, List<OrderItem>> grouped = source.getOrderItems().stream().collect(Collectors.groupingBy(i -> mergeKey(i.getMatNr(), i.getBatch())));
|
List<OrderItem> mergedItems = new ArrayList<>();
|
int idx = 1;
|
for (List<OrderItem> groupItems : grouped.values()) {
|
OrderItem first = groupItems.get(0);
|
BigDecimal qty = groupItems.stream()
|
.map(i -> toDecimal(i.getAnfme()))
|
.reduce(ZERO, BigDecimal::add)
|
.setScale(2, RoundingMode.HALF_UP);
|
OrderItem mergedItem = new OrderItem()
|
.setLineId("M" + idx++)
|
.setPlanNo(first.getPlanNo())
|
.setMatNr(first.getMatNr())
|
.setMakTx(first.getMakTx())
|
.setModel(first.getModel())
|
.setAnfme(qty.doubleValue())
|
.setBatch(first.getBatch())
|
.setUnit(first.getUnit())
|
.setBaseUnit(first.getBaseUnit())
|
.setPriceUnitId(first.getPriceUnitId())
|
.setPalletId(first.getPalletId())
|
.setTargetWarehouseId(first.getTargetWarehouseId())
|
.setSourceWarehouseId(first.getSourceWarehouseId())
|
.setInStockType(first.getInStockType())
|
.setOwnerTypeId(first.getOwnerTypeId())
|
.setOwnerId(first.getOwnerId())
|
.setOwnerName(first.getOwnerName())
|
.setKeeperTypeId(first.getKeeperTypeId())
|
.setKeeperId(first.getKeeperId())
|
.setKeeperName(first.getKeeperName())
|
.setMemo(first.getMemo())
|
.setUseOrgId(first.getUseOrgId())
|
.setUseOrgName(first.getUseOrgName())
|
.setErpClsId(first.getErpClsId());
|
mergedItem.setSpec(first.getSpec());
|
mergedItems.add(mergedItem);
|
}
|
merged.setOrderItems(mergedItems);
|
return merged;
|
}
|
|
private boolean existsReportEvent(String eventId, String taskNo, String reportNo) {
|
return openApiOrderReportEventMapper.selectCount(new LambdaQueryWrapper<OpenApiOrderReportEvent>()
|
.eq(OpenApiOrderReportEvent::getEventId, defaultString(eventId))
|
.eq(OpenApiOrderReportEvent::getTaskNo, defaultString(taskNo))
|
.eq(OpenApiOrderReportEvent::getReportNo, defaultString(reportNo))
|
.eq(OpenApiOrderReportEvent::getStatus, 1)) > 0;
|
}
|
|
private OpenApiOrderReportEvent saveReportEvent(String eventId, String taskNo, String reportNo, String orderCode, String payload) {
|
OpenApiOrderReportEvent event = new OpenApiOrderReportEvent()
|
.setEventId(defaultString(eventId))
|
.setTaskNo(defaultString(taskNo))
|
.setReportNo(defaultString(reportNo))
|
.setOrderCode(orderCode)
|
.setPayload(payload)
|
.setStatus(0);
|
openApiOrderReportEventMapper.insert(event);
|
return event;
|
}
|
|
private int allocateMergedDoneQty(String orderNo, String matnrCode, String batch, BigDecimal mergedDoneQty) {
|
OpenApiOrder order = openApiOrderMapper.selectOne(new LambdaQueryWrapper<OpenApiOrder>()
|
.eq(OpenApiOrder::getCode, orderNo)
|
.last("limit 1"));
|
if (Objects.isNull(order)) {
|
throw new CoolException("未找到订单:" + orderNo);
|
}
|
|
LambdaQueryWrapper<OpenApiOrderItemMap> queryWrapper = new LambdaQueryWrapper<OpenApiOrderItemMap>()
|
.eq(OpenApiOrderItemMap::getOrderId, order.getId())
|
.eq(OpenApiOrderItemMap::getMergeMatnrCode, defaultString(matnrCode))
|
.orderByAsc(OpenApiOrderItemMap::getSeqNo)
|
.orderByAsc(OpenApiOrderItemMap::getId);
|
if (StringUtils.isNotBlank(batch)) {
|
queryWrapper.eq(OpenApiOrderItemMap::getMergeBatch, batch);
|
}
|
List<OpenApiOrderItemMap> mappingRows = openApiOrderItemMapMapper.selectList(queryWrapper);
|
if (mappingRows.isEmpty()) {
|
throw new CoolException("未找到映射关系,订单:" + orderNo + ",物料:" + matnrCode);
|
}
|
|
BigDecimal remaining = mergedDoneQty;
|
int allocateRows = 0;
|
for (OpenApiOrderItemMap row : mappingRows) {
|
if (remaining.compareTo(ZERO) <= 0) {
|
break;
|
}
|
BigDecimal sourceQty = defaultQty(row.getSourceQty());
|
BigDecimal allocatedQty = defaultQty(row.getAllocatedQty());
|
BigDecimal canAllocate = sourceQty.subtract(allocatedQty);
|
if (canAllocate.compareTo(ZERO) <= 0) {
|
continue;
|
}
|
BigDecimal toAllocate = remaining.min(canAllocate).setScale(2, RoundingMode.HALF_UP);
|
if (toAllocate.compareTo(ZERO) <= 0) {
|
continue;
|
}
|
|
row.setAllocatedQty(allocatedQty.add(toAllocate).setScale(2, RoundingMode.HALF_UP));
|
openApiOrderItemMapMapper.updateById(row);
|
openApiOrderItemMapper.update(null, new LambdaUpdateWrapper<OpenApiOrderItem>()
|
.eq(OpenApiOrderItem::getId, row.getSourceItemId())
|
.setSql("qty = IFNULL(qty,0) + " + toAllocate));
|
remaining = remaining.subtract(toAllocate).setScale(2, RoundingMode.HALF_UP);
|
allocateRows++;
|
}
|
if (remaining.compareTo(ZERO) > 0) {
|
log.warn("回传数量超过未分配数量,orderNo={}, matnr={}, batch={}, overflow={}", orderNo, matnrCode, batch, remaining);
|
}
|
return allocateRows;
|
}
|
|
private int reportReadyLinesToErp(String orderNo) {
|
OpenApiOrder order = openApiOrderMapper.selectOne(new LambdaQueryWrapper<OpenApiOrder>()
|
.eq(OpenApiOrder::getCode, orderNo)
|
.last("limit 1"));
|
if (Objects.isNull(order)) {
|
return 0;
|
}
|
|
List<OpenApiOrderItemMap> mappings = openApiOrderItemMapMapper.selectList(new LambdaQueryWrapper<OpenApiOrderItemMap>()
|
.eq(OpenApiOrderItemMap::getOrderId, order.getId())
|
.orderByAsc(OpenApiOrderItemMap::getSeqNo)
|
.orderByAsc(OpenApiOrderItemMap::getId));
|
int successCount = 0;
|
|
for (OpenApiOrderItemMap mapping : mappings) {
|
BigDecimal allocatedQty = defaultQty(mapping.getAllocatedQty());
|
BigDecimal reportedQty = defaultQty(mapping.getReportedQty());
|
BigDecimal delta = allocatedQty.subtract(reportedQty).setScale(2, RoundingMode.HALF_UP);
|
if (delta.compareTo(ZERO) <= 0) {
|
continue;
|
}
|
|
OpenApiOrderItem item = openApiOrderItemMapper.selectById(mapping.getSourceItemId());
|
if (Objects.isNull(item)) {
|
continue;
|
}
|
|
ReportParams params = buildLineReportParams(order, item, delta);
|
CommonResponse erpResp = wmsErpService.reportOrders(params);
|
if (Objects.nonNull(erpResp) && Objects.equals(erpResp.getCode(), 200)) {
|
mapping.setReportedQty(reportedQty.add(delta).setScale(2, RoundingMode.HALF_UP));
|
openApiOrderItemMapMapper.updateById(mapping);
|
successCount++;
|
} else {
|
String msg = Objects.isNull(erpResp) ? "ERP响应为空" : erpResp.getMsg();
|
log.warn("ERP行上报失败,orderNo={}, itemId={}, msg={}", orderNo, item.getId(), msg);
|
}
|
}
|
return successCount;
|
}
|
|
private ReportParams buildLineReportParams(OpenApiOrder order, OpenApiOrderItem item, BigDecimal deltaQty) {
|
ReportDataParam dataParam = new ReportDataParam()
|
.setWMSNO(order.getCode())
|
.setPONO(order.getPoCode())
|
.setOrderNO(item.getPlatWorkCode())
|
.setGoodsNO(item.getBatch())
|
.setItemCode(item.getMatnrCode())
|
.setEditUser("open-api")
|
.setEditDate(new Date())
|
.setMemoDtl("lineId=" + defaultString(item.getPlatItemId()));
|
|
if ("in".equalsIgnoreCase(order.getType())) {
|
dataParam.setInQty(deltaQty.doubleValue());
|
} else {
|
dataParam.setOutQty(deltaQty.doubleValue());
|
}
|
|
return new ReportParams().setOrderType(order.getType()).setAction("Update").setData(Collections.singletonList(dataParam));
|
}
|
|
private void refreshOrderFinishStatus(String orderNo) {
|
OpenApiOrder order = openApiOrderMapper.selectOne(new LambdaQueryWrapper<OpenApiOrder>()
|
.eq(OpenApiOrder::getCode, orderNo)
|
.last("limit 1"));
|
if (Objects.isNull(order)) {
|
return;
|
}
|
List<OpenApiOrderItem> items = openApiOrderItemMapper.selectList(new LambdaQueryWrapper<OpenApiOrderItem>()
|
.eq(OpenApiOrderItem::getOrderId, order.getId()));
|
BigDecimal totalPlan = items.stream().map(i -> defaultQty(i.getAnfme())).reduce(ZERO, BigDecimal::add);
|
BigDecimal totalDone = items.stream().map(i -> defaultQty(i.getQty())).reduce(ZERO, BigDecimal::add);
|
|
int exceStatus = 0;
|
if (totalDone.compareTo(ZERO) > 0 && totalDone.compareTo(totalPlan) < 0) {
|
exceStatus = 1;
|
} else if (totalDone.compareTo(totalPlan) >= 0 && totalPlan.compareTo(ZERO) > 0) {
|
exceStatus = 2;
|
}
|
|
order.setQty(totalDone.setScale(2, RoundingMode.HALF_UP))
|
.setWorkQty(totalDone.setScale(2, RoundingMode.HALF_UP))
|
.setExceStatus(exceStatus);
|
openApiOrderMapper.updateById(order);
|
}
|
|
private BigDecimal sumOrderItemQty(List<OrderItem> orderItems) {
|
return orderItems.stream()
|
.filter(Objects::nonNull)
|
.map(i -> toDecimal(i.getAnfme()))
|
.reduce(ZERO, BigDecimal::add)
|
.setScale(2, RoundingMode.HALF_UP);
|
}
|
|
private BigDecimal toDecimal(Double value) {
|
if (Objects.isNull(value)) {
|
return ZERO;
|
}
|
return BigDecimal.valueOf(value).setScale(2, RoundingMode.HALF_UP);
|
}
|
|
private BigDecimal defaultQty(BigDecimal value) {
|
return Objects.isNull(value) ? ZERO : value.setScale(2, RoundingMode.HALF_UP);
|
}
|
|
private Date toDate(Long timestampSeconds) {
|
if (Objects.isNull(timestampSeconds) || timestampSeconds <= 0L) {
|
return null;
|
}
|
return new Date(timestampSeconds * 1000);
|
}
|
|
private String mergeKey(String matnr, String batch) {
|
return defaultString(matnr) + "@@" + defaultString(batch);
|
}
|
|
private String defaultString(String value) {
|
return StringUtils.trimToEmpty(value);
|
}
|
|
private String pickString(JSONObject object, String... candidates) {
|
if (Objects.isNull(object) || Objects.isNull(candidates)) {
|
return "";
|
}
|
for (String key : candidates) {
|
Object value = object.get(key);
|
if (Objects.nonNull(value) && StringUtils.isNotBlank(String.valueOf(value))) {
|
return String.valueOf(value).trim();
|
}
|
}
|
return "";
|
}
|
|
private JSONArray pickArray(JSONObject object, String... candidates) {
|
if (Objects.isNull(object) || Objects.isNull(candidates)) {
|
return new JSONArray();
|
}
|
for (String key : candidates) {
|
Object value = object.get(key);
|
if (value instanceof JSONArray) {
|
return (JSONArray) value;
|
}
|
if (value instanceof List) {
|
return JSONArray.parseArray(JSON.toJSONString(value));
|
}
|
if (value instanceof String && ((String) value).trim().startsWith("[")) {
|
return JSONArray.parseArray((String) value);
|
}
|
}
|
return new JSONArray();
|
}
|
|
private BigDecimal pickDecimal(JSONObject object, String... candidates) {
|
if (Objects.isNull(object) || Objects.isNull(candidates)) {
|
return ZERO;
|
}
|
for (String key : candidates) {
|
Object value = object.get(key);
|
if (Objects.isNull(value)) {
|
continue;
|
}
|
try {
|
return new BigDecimal(String.valueOf(value)).abs().setScale(2, RoundingMode.HALF_UP);
|
} catch (Exception ignore) {
|
// ignore invalid value
|
}
|
}
|
return ZERO;
|
}
|
|
public static Map<String, Object> objectToMap(Object obj) {
|
Map<String, Object> map = new HashMap<>();
|
Field[] fields = obj.getClass().getDeclaredFields();
|
for (Field field : fields) {
|
field.setAccessible(true); // 设置私有字段也可以访问
|
try {
|
map.put(field.getName(), field.get(obj));
|
} catch (IllegalAccessException e) {
|
e.printStackTrace();
|
}
|
}
|
return map;
|
}
|
|
|
|
/**
|
* 入/出库任务完成上报
|
*
|
* @param params
|
* @return
|
*/
|
public CommonResponse reportInOrOutBound(Object params) {
|
if (Objects.isNull(params)) {
|
throw new CoolException("入/出库任务信息参数不能为空!!");
|
}
|
|
// TODO:参数转换
|
ErpReportParams erpReportParams = new ErpReportParams();
|
if (params instanceof ErpReportParams) {
|
erpReportParams = (ErpReportParams) params;
|
} else if (params instanceof java.util.Map) {
|
java.util.Map<String, Object> paramMap = (java.util.Map<String, Object>) params;
|
|
// 设置基本属性
|
erpReportParams.setFDate((String) paramMap.get("FDate"));
|
erpReportParams.setF_OHDL_BillnoType((String) paramMap.get("F_OHDL_BillnoType"));
|
erpReportParams.setFStockOrgId(paramMap.get("FStockOrgId"));
|
erpReportParams.setFPrdOrgId(paramMap.get("FPrdOrgId"));
|
erpReportParams.setF_OHDL_ProPlan((String) paramMap.get("F_OHDL_ProPlan"));
|
|
// 处理FEntity列表
|
Object fEntityObj = paramMap.get("FEntity");
|
if (fEntityObj instanceof java.util.List) {
|
java.util.List<?> fEntityList = (java.util.List<?>) fEntityObj;
|
java.util.List<ErpReportParams.FEntityItem> entityItems = new java.util.ArrayList<>();
|
|
for (Object item : fEntityList) {
|
if (item instanceof java.util.Map) {
|
java.util.Map<String, Object> itemMap = (java.util.Map<String, Object>) item;
|
ErpReportParams.FEntityItem entityItem = new ErpReportParams.FEntityItem();
|
|
// 使用反射设置属性值
|
try {
|
// 使用反射直接访问字段并设置值
|
java.lang.reflect.Field field;
|
|
field = entityItem.getClass().getDeclaredField("FMaterialId");
|
field.setAccessible(true);
|
field.set(entityItem, itemMap.get("FMaterialId"));
|
|
field = entityItem.getClass().getDeclaredField("FUnitID");
|
field.setAccessible(true);
|
field.set(entityItem, itemMap.get("FUnitID"));
|
|
// 处理数值类型
|
Object fAppQty = itemMap.get("FAppQty");
|
if (fAppQty instanceof Number) {
|
field = entityItem.getClass().getDeclaredField("FAppQty");
|
field.setAccessible(true);
|
field.set(entityItem, ((Number) fAppQty).doubleValue());
|
} else if (fAppQty != null) {
|
field = entityItem.getClass().getDeclaredField("FAppQty");
|
field.setAccessible(true);
|
field.set(entityItem, Double.parseDouble(fAppQty.toString()));
|
}
|
|
Object fActualQty = itemMap.get("FActualQty");
|
if (fActualQty instanceof Number) {
|
field = entityItem.getClass().getDeclaredField("FActualQty");
|
field.setAccessible(true);
|
field.set(entityItem, ((Number) fActualQty).doubleValue());
|
} else if (fActualQty != null) {
|
field = entityItem.getClass().getDeclaredField("FActualQty");
|
field.setAccessible(true);
|
field.set(entityItem, Double.parseDouble(fActualQty.toString()));
|
}
|
|
field = entityItem.getClass().getDeclaredField("FStockId");
|
field.setAccessible(true);
|
field.set(entityItem, itemMap.get("FStockId"));
|
|
field = entityItem.getClass().getDeclaredField("F_OHDL_BworkShop");
|
field.setAccessible(true);
|
field.set(entityItem, itemMap.get("F_OHDL_BworkShop"));
|
|
field = entityItem.getClass().getDeclaredField("F_OHDL_Pallet");
|
field.setAccessible(true);
|
field.set(entityItem, (String) itemMap.get("F_OHDL_Pallet"));
|
|
field = entityItem.getClass().getDeclaredField("F_OHDL_ConPoint");
|
field.setAccessible(true);
|
field.set(entityItem, (String) itemMap.get("F_OHDL_ConPoint"));
|
|
field = entityItem.getClass().getDeclaredField("F_OHDL_PlanNo");
|
field.setAccessible(true);
|
field.set(entityItem, (String) itemMap.get("F_OHDL_PlanNo"));
|
|
field = entityItem.getClass().getDeclaredField("F_OHDL_MONo");
|
field.setAccessible(true);
|
field.set(entityItem, (String) itemMap.get("F_OHDL_MONo"));
|
|
field = entityItem.getClass().getDeclaredField("F_OHDL_MOId");
|
field.setAccessible(true);
|
field.set(entityItem, (String) itemMap.get("F_OHDL_MOId"));
|
|
field = entityItem.getClass().getDeclaredField("F_OHDL_MOLine");
|
field.setAccessible(true);
|
field.set(entityItem, (String) itemMap.get("F_OHDL_MOLine"));
|
|
field = entityItem.getClass().getDeclaredField("F_OHDL_MOLineId");
|
field.setAccessible(true);
|
field.set(entityItem, (String) itemMap.get("F_OHDL_MOLineId"));
|
} catch (Exception e) {
|
log.error("设置FEntityItem属性时发生错误: " + e.getMessage());
|
throw new CoolException("设置FEntityItem属性失败: " + e.getMessage());
|
}
|
|
entityItems.add(entityItem);
|
} else if (item instanceof ErpReportParams.FEntityItem) {
|
entityItems.add((ErpReportParams.FEntityItem) item);
|
}
|
}
|
erpReportParams.setFEntity(entityItems);
|
}
|
} else {
|
throw new CoolException("无法处理的参数类型: " + params.getClass().getName());
|
}
|
|
JSONObject model = new JSONObject();
|
model.put("Model", erpReportParams);
|
JSONObject data = new JSONObject();
|
data.put("data", model);
|
data.put("formid", "ke3d5adc0bbe64eceafd5891400adf40e");
|
|
try {
|
JSONObject loginResult = loginBySign();
|
if (loginResult.getInteger("LoginResultType") == 1) {
|
String erpUrl = ERP_REPORT_URL + "/Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Save.common.kdsvc";
|
log.info("Erp入/出库任务完成上报: {}, 请求参数: {}", erpUrl, JSONObject.toJSONString(data));
|
|
String result2 = httpPostExample(erpUrl, data.toJSONString());
|
JSONObject jsonObject = JSONObject.parseObject(result2);
|
log.info("Erp入/出库任务完成上报返回" + jsonObject.toJSONString());
|
boolean sendSuccess = jsonObject.getJSONObject("Result").getJSONObject("ResponseStatus").getBoolean("IsSuccess");
|
|
// TODO:转换后返回
|
if (sendSuccess) {
|
return CommonResponse.ok();
|
} else {
|
JSONArray errors = jsonObject.getJSONObject("Result").getJSONObject("ResponseStatus").getJSONArray("Errors");
|
String errorMsg = "";
|
for (int i = 0; i < errors.size(); i++) {
|
errorMsg += errors.getJSONObject(i).getString("Message") + " ";
|
}
|
return CommonResponse.error(errorMsg);
|
}
|
}
|
} catch (Exception e) {
|
log.error("loginBySign", e);
|
}
|
|
|
// try {
|
// JSONObject jsonObject = postRequest(erpUrl, data, true);
|
// log.info(jsonObject.toJSONString());
|
// boolean sendSuccess = jsonObject.getJSONObject("Result").getJSONObject("ResponseStatus").getBoolean("IsSuccess");
|
//
|
// // TODO:转换后返回
|
// if (sendSuccess) {
|
// return CommonResponse.ok();
|
// } else {
|
// JSONArray errors = jsonObject.getJSONObject("Result").getJSONObject("ResponseStatus").getJSONArray("Errors");
|
// String errorMsg = "";
|
// for (int i = 0; i < errors.size(); i++) {
|
// errorMsg += errors.getJSONObject(i).getString("Message") + " ";
|
// }
|
// return CommonResponse.error(errorMsg);
|
// }
|
// } catch (Exception e) {
|
// log.error("Erp入/出库任务上报响应失败", e);
|
// throw new CoolException("Erp解析响应失败:" + e.getMessage());
|
// }
|
|
return null;
|
}
|
|
|
// 其他入/出库主动上报
|
|
|
// 盘点结果上报
|
|
|
// region 登录
|
/**
|
* 登录,登录参数依次为账套ID、用户名、应用ID、时间戳、签名信息、语言ID
|
*
|
* @throws UnsupportedEncodingException
|
* @throws NoSuchAlgorithmException
|
*/
|
public JSONObject loginBySign() throws UnsupportedEncodingException, NoSuchAlgorithmException {
|
String url = ERP_REPORT_URL + "/Kingdee.BOS.WebApi.ServicesStub.AuthService.LoginBySign.common.kdsvc";
|
JSONObject params = new JSONObject();
|
params.put("parameters", loginParams());
|
String result = httpPostExample(url, params.toJSONString());
|
return JSONObject.parseObject(result);
|
}
|
|
/**
|
* 登录参数整理
|
*
|
* @return
|
* @throws UnsupportedEncodingException
|
* @throws NoSuchAlgorithmException
|
*/
|
private Object[] loginParams() throws UnsupportedEncodingException, NoSuchAlgorithmException {
|
//时间戳
|
long timestamp = System.currentTimeMillis() / 1000;
|
//数据中心ID
|
String dbId = "69368c1051a322";
|
//用户名称
|
String userName = "楼坚伟";
|
//第三方系统应用Id
|
String appId = "330678_w2eBwdkp0oCW2XxuW16D4w/NRhTaTPKp";
|
//第三方系统应用秘钥
|
String appSecret = "31c9e5da6472456193e0c8a7dd2160d9";
|
//将账套ID、用户名、应用ID、应用秘钥、时间戳 放到数组里面
|
String[] arr = new String[] { dbId, userName, appId, appSecret, String.valueOf(timestamp) };
|
//生成签名信息
|
String sign = getSha256(arr);
|
|
return new Object[] { dbId, userName, appId, String.valueOf(timestamp), sign, 2052};
|
}
|
|
public static String getSha256(String[] input) throws UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchAlgorithmException {
|
Arrays.sort(input);
|
//SHA1加密的话改成MessageDigest.getInstance("SHA-1");
|
MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
|
for (String str : input) {
|
sha256.update(str.getBytes("UTF-8"));
|
}
|
byte[] hashBytes = sha256.digest();
|
StringBuilder hashString = new StringBuilder();
|
for (byte b : hashBytes) {
|
String hex = Integer.toHexString(0xff & b);
|
if (hex.length() == 1) {
|
hashString.append('0');
|
}
|
hashString.append(hex);
|
}
|
return hashString.toString();
|
}
|
// endregion
|
|
/**
|
* 通用HTTP POST请求方法
|
*
|
* @param url 请求URL
|
* @param params 请求参数
|
* @return 响应结果
|
*/
|
public JSONObject postRequest(String url, Object params) {
|
if (StringUtils.isBlank(url)) {
|
throw new CoolException("请求URL不能为空!!");
|
}
|
if (Objects.isNull(params)) {
|
throw new CoolException("请求参数不能为空!!");
|
}
|
|
log.info("Erp POST请求: {}, 请求参数: {}", url, JSONObject.toJSONString(params));
|
|
HttpHeaders headers = new HttpHeaders();
|
headers.add("Content-Type", "application/json;charset=utf-8");
|
|
HttpEntity<Object> httpEntity = new HttpEntity<>(params, headers);
|
|
// 创建支持忽略SSL证书验证的RestTemplate
|
RestTemplate sslRestTemplate = SslUtils.createIgnoreSSLRestTemplate();
|
|
// 设置错误处理器,不抛出异常,而是返回响应体
|
sslRestTemplate.setErrorHandler(new org.springframework.web.client.DefaultResponseErrorHandler() {
|
@Override
|
public boolean hasError(ClientHttpResponse response) throws IOException {
|
// 不管状态码如何,都不视为错误
|
return false;
|
}
|
});
|
|
ResponseEntity<String> exchange = sslRestTemplate.exchange(url, HttpMethod.POST, httpEntity, String.class);
|
log.info("Erp POST请求响应结果: {}", exchange);
|
|
if (Objects.isNull(exchange.getBody())) {
|
throw new CoolException("请求失败!!");
|
}
|
|
try {
|
ObjectMapper objectMapper = new ObjectMapper();
|
objectMapper.coercionConfigDefaults().setCoercion(CoercionInputShape.EmptyString, CoercionAction.AsEmpty);
|
return objectMapper.readValue(exchange.getBody(), JSONObject.class);
|
} catch (JsonProcessingException e) {
|
log.error("Erp解析响应失败", e);
|
throw new CoolException("Erp解析响应失败:" + e.getMessage());
|
}
|
}
|
|
|
|
/**
|
* HTTP POST请求示例 - 支持HTTPS
|
*
|
* @param url 请求URL
|
* @param params 请求参数
|
* @return 响应结果
|
*/
|
public String httpPostExample(String url, String params) {
|
if (httpClient == null) {
|
httpClient = createHttpsClient();
|
}
|
HttpPost httpPost = new HttpPost(url);
|
try {
|
StringEntity entity = new StringEntity(params, "UTF-8");
|
httpPost.setEntity(entity);
|
httpPost.setHeader("Content-type", "application/json;charset=utf-8");
|
httpPost.setHeader("Accept", "application/json");
|
return EntityUtils.toString(httpClient.execute(httpPost).getEntity());
|
} catch (Exception e) {
|
log.error("HTTP POST请求失败: {}", e.getMessage(), e);
|
throw new CoolException("HTTP POST请求失败: " + e.getMessage());
|
}
|
}
|
|
/**
|
* 使用RestTemplate的HTTPS POST请求示例
|
*
|
* @param url 请求URL
|
* @param params 请求参数
|
* @return 响应结果
|
*/
|
public String httpsPostWithRestTemplate(String url, String params) {
|
try {
|
log.info("HTTPS POST请求: {}, 请求参数: {}", url, params);
|
|
HttpHeaders headers = new HttpHeaders();
|
headers.add("Content-Type", "application/json;charset=utf-8");
|
headers.add("Accept", "application/json");
|
|
HttpEntity<String> httpEntity = new HttpEntity<>(params, headers);
|
|
// 使用项目中已有的SSL工具类创建忽略SSL证书验证的RestTemplate
|
RestTemplate sslRestTemplate = SslUtils.createIgnoreSSLRestTemplate();
|
|
// 设置错误处理器,不抛出异常,而是返回响应体
|
sslRestTemplate.setErrorHandler(new org.springframework.web.client.DefaultResponseErrorHandler() {
|
@Override
|
public boolean hasError(ClientHttpResponse response) throws IOException {
|
// 不管状态码如何,都不视为错误
|
return false;
|
}
|
});
|
|
ResponseEntity<String> exchange = sslRestTemplate.exchange(url, HttpMethod.POST, httpEntity, String.class);
|
log.info("HTTPS POST请求响应结果: {}", exchange);
|
|
if (Objects.isNull(exchange.getBody())) {
|
throw new CoolException("请求失败!!");
|
}
|
|
return exchange.getBody();
|
} catch (Exception e) {
|
log.error("HTTPS POST请求失败: {}", e.getMessage(), e);
|
throw new CoolException("HTTPS POST请求失败: " + e.getMessage());
|
}
|
}
|
|
/**
|
* 创建支持HTTPS的HttpClient
|
*
|
* @return CloseableHttpClient实例
|
*/
|
private CloseableHttpClient createHttpsClient() {
|
try {
|
// 创建信任所有证书的TrustManager
|
TrustManager[] trustAllCerts = new TrustManager[] {
|
new X509TrustManager() {
|
public X509Certificate[] getAcceptedIssuers() { return null; }
|
public void checkClientTrusted(X509Certificate[] certs, String authType) { }
|
public void checkServerTrusted(X509Certificate[] certs, String authType) { }
|
}
|
};
|
|
// 初始化SSLContext
|
SSLContext sslContext = SSLContext.getInstance("TLS");
|
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
|
|
// 创建SSL连接管理器
|
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
|
sslContext,
|
(hostname, session) -> true // 允许所有主机名
|
);
|
|
// 创建HttpClientBuilder并设置SSL配置
|
RequestConfig config = RequestConfig.custom()
|
.setConnectTimeout(30000) // 连接超时时间
|
.setSocketTimeout(60000) // 读取超时时间
|
.build();
|
|
return HttpClients.custom()
|
.setSSLSocketFactory(sslsf)
|
.setDefaultRequestConfig(config)
|
.build();
|
} catch (Exception e) {
|
log.error("创建HTTPS客户端失败: {}", e.getMessage(), e);
|
return HttpClients.createDefault(); // 回退到默认客户端
|
}
|
}
|
|
// /**
|
// * 示例:如何使用HTTPS POST方法
|
// *
|
// * @param url 目标URL
|
// * @param jsonData JSON数据
|
// * @return 响应结果
|
// */
|
// public String exampleUsage(String url, String jsonData) {
|
// log.info("开始调用HTTPS POST请求示例");
|
//
|
// try {
|
// // 方法1: 使用Apache HttpClient
|
// String result1 = httpPostExample(url, jsonData);
|
// log.info("使用HttpClient的POST请求结果: {}", result1);
|
//
|
// // 方法2: 使用RestTemplate
|
// String result2 = httpsPostWithRestTemplate(url, jsonData);
|
// log.info("使用RestTemplate的POST请求结果: {}", result2);
|
//
|
// // 根据实际需要选择返回结果
|
// return result1;
|
// } catch (Exception e) {
|
// log.error("HTTPS POST请求示例执行失败: {}", e.getMessage(), e);
|
// throw e;
|
// }
|
// }
|
|
}
|