import com.dderp.common.api.BusinessExecutor import com.dderp.common.api.SupplierInitService import com.dderp.common.datas.ERPModule import com.dderp.common.datas.ESKeys import com.dderp.common.datas.ReadOrderOption import com.dderp.common.entity.base.ProcessSearchOptionsItem import com.dderp.common.entity.order.OrderRefundRequest import com.dderp.common.tool.ERPUtils import com.dySweetFishPlugin.elasticsearch.ESClient import com.dySweetFishPlugin.tool.lang.DateUtil import com.sweetfish.convert.json.JsonConvert import com.sweetfish.service.RetResult import org.apache.commons.lang3.StringUtils import org.apache.logging.log4j.LogManager import org.apache.logging.log4j.Logger import org.elasticsearch.action.search.SearchResponse import org.elasticsearch.index.query.BoolQueryBuilder import org.elasticsearch.index.query.Operator import org.elasticsearch.index.query.QueryBuilder import org.elasticsearch.index.query.QueryBuilders import org.elasticsearch.join.query.JoinQueryBuilders import org.elasticsearch.search.aggregations.AggregationBuilders import org.elasticsearch.search.aggregations.metrics.sum.InternalSum import org.elasticsearch.search.aggregations.metrics.valuecount.ValueCount import org.elasticsearch.search.sort.SortBuilders import org.elasticsearch.search.sort.SortOrder import org.rex.RMap import javax.annotation.Resource import java.math.RoundingMode @SuppressWarnings(["rawtypes"]) class BE_ERP_OrderRefundRequest_Search implements BusinessExecutor, OrderRefundRequest> { protected final Logger logger = LogManager.getLogger(this.getClass().getSimpleName()) @Resource SupplierInitService supplierService @Resource ESClient esClient @Resource JsonConvert jsonConvert @Override String scriptName() { return "ERP-订单退款申请-查询" } @Override ERPModule module() { return ERPModule.ERP_ORDER_SEARCH } def readOrderOptions(List requestList, String dataSourceId, long supplierCode, ReadOrderOption... options) { long[] idOrders = requestList*.id.toArray() as long[] if ((options != null) && (options.length > 0) && (idOrders.length > 0)) { //防止搞坏事,options传重复数据过来,先去重 options.toUnique().each { opt -> switch (opt) { } } } } def readOrderOptions(OrderRefundRequest refundRequest, String dataSourceId, long supplierCode, ReadOrderOption... options) { if ((options != null) && (options.length > 0)) { //防止搞坏事,options传重复数据过来,先去重 options.toUnique().each { opt -> switch (opt) { } } } } def readOrderTotal(RMap searchData, String dataSourceId, long supplierCode, ReadOrderOption... options) { if (!(ReadOrderOption.ORDER_TOTAL in options)) { return null } //这里的查询需要和主表一致 BoolQueryBuilder bqb = search(searchData) .byRequestStatus() .byKeyWord() .byRequestStatus() .byOrderCode() .byBeginTime_Create() .byEndTime_Create() .byIdOrder() .byIdStore() .byIdStorePlatform() .byPlatformCode() .byPlatformType() .byOutAfterSaleId() .build() //合计金额,所以主表从orderMoney中开始 SearchResponse searchResponse = esClient.getClient() .prepareSearch(supplierService.getDateYearESIndex(supplierCode, ESKeys.ES_DELIVER_BUSINESS_ORDER_INDEX, 1)) .setQuery(bqb) .addAggregation(AggregationBuilders.count("sub_count").field("id")) .addAggregation(AggregationBuilders.sum("deliveryFee_Sum").field("deliveryFee")) .addAggregation(AggregationBuilders.sum("refundFee_Sum").field("refundFee")) .addAggregation(AggregationBuilders.sum("refundProdCount_Sum").field("refundProdCount")) .execute().actionGet() ValueCount requestCountSum = searchResponse.getAggregations().get("sub_count") InternalSum deliveryFeeSum = searchResponse.getAggregations().get("deliveryFee_Sum") InternalSum refundFeeSum = searchResponse.getAggregations().get("refundFee_Sum") InternalSum refundProdCountSum = searchResponse.getAggregations().get("refundProdCount_Sum") RMap collectionData = new RMap<>() collectionData.put("requestCountSum", requestCountSum.getValue()) collectionData.put("deliveryFeeSum", BigDecimal.valueOf(deliveryFeeSum.getValue()).setScale(2, RoundingMode.HALF_UP)) collectionData.put("refundFeeSum", BigDecimal.valueOf(refundFeeSum.getValue()).setScale(2, RoundingMode.HALF_UP)) collectionData.put("refundProdCountSum", BigDecimal.valueOf(refundProdCountSum.getValue()).setScale(2, RoundingMode.HALF_UP)) return collectionData } private RetResult> queryByConditions(ProcessSearchOptionsItem source) { String orderByField = "createTimeLong" String orderBySort = "desc" if (StringUtils.isNotBlank(source.orderBy)) { orderByField = source.orderBy.split(",")[0].trim() orderBySort = source.orderBy.split(",")[1].trim().toLowerCase() } List orderList = ESList. getESList() .esClient(esClient) .jsonConvert(jsonConvert) .clazz(OrderRefundRequest.class) .queryBuilder({ return search(source.searchData) .byRequestStatus() .byKeyWord() .byRequestStatus() .byOrderCode() .byBeginTime_Create() .byEndTime_Create() .byIdOrder() .byIdStore() .byIdStorePlatform() .byPlatformCode() .byPlatformType() .byOutAfterSaleId() .build() }) .index(supplierService.getDateYearESIndex(source.supplierCode, ESKeys.ES_DELIVER_ORDER_REFUND_REQUEST_INDEX, 1)) .sortBuilder({ switch (orderBySort) { case 'asc': return SortBuilders.fieldSort(orderByField).order(SortOrder.ASC) case 'desc': return SortBuilders.fieldSort(orderByField).order(SortOrder.DESC) } }) .dataExecutor(null) .executePage(source.pageFlipper) readOrderOptions(orderList, source.dataSourceId, source.supplierCode, source.options) RMap collectionData = readOrderTotal(source.searchData, source.dataSourceId, source.supplierCode, source.options) return RetResult.> successT().result(orderList).page(source.pageFlipper).attachRMap(collectionData) } private RetResult> queryByIds(ProcessSearchOptionsItem source) { if (!ERPUtils.mapContainKey(source.searchData, ERPUtils.PARAM_SEARCH_IDS)) { return RetResult.> errorT().retinfo("无效的ids参数") } String[] idOrders = source.searchData.get(ERPUtils.PARAM_SEARCH_IDS) //ES规定,addIds或者terms中的数据长度好像是1024个限制,这里为了安全,把list拆分一下 //待测试下,collate分隔之后的类型,不行的话还是得List> //测试后,结果是List>,不明白数组为什么转成List List> idOrderArrayList = idOrders.collate(500) List orderList = new ArrayList<>() idOrderArrayList.each { l -> List subOrderList = ESList. getESList() .esClient(esClient) .jsonConvert(jsonConvert) .clazz(OrderRefundRequest.class) .queryBuilder({ return search(source.searchData) .byIds(l.toArray(String[]::new)) .build() }) .index(supplierService.getDateYearESIndex(source.supplierCode, ESKeys.ES_DELIVER_ORDER_REFUND_REQUEST_INDEX, 1)) .executeNonePage() readOrderOptions(subOrderList, source.dataSourceId, source.supplierCode, source.options) if (!subOrderList.isEmpty()) { orderList.addAll(subOrderList) } } return RetResult.> successT().result(orderList) } private RetResult queryById(ProcessSearchOptionsItem source) { if (!ERPUtils.mapContainKey(source.searchData, ERPUtils.PARAM_SEARCH_ID)) { return RetResult. errorT().retinfo("无效的id参数") } long idOrder = source.searchData.getLong(ERPUtils.PARAM_SEARCH_ID) OrderRefundRequest businessOrder = ESOne. getESOneInfo() .esClient(esClient) .jsonConvert(jsonConvert) .clazz(OrderRefundRequest.class) .queryBuilder({ //获取完成的数据情况 ESConditionBuilder qb = search(null).byId(idOrder) //这里还需要判断数据权限 return qb.build() }) .index(supplierService.getDateYearESIndex(source.supplierCode, ESKeys.ES_DELIVER_ORDER_REFUND_REQUEST_INDEX, 1)) .execute() if (businessOrder == null) { return RetResult. errorT().retinfo("无效的订单") } readOrderOptions(businessOrder, source.dataSourceId, source.supplierCode, source.options) return RetResult. successT().result(businessOrder) } private RetResult queryByCode(ProcessSearchOptionsItem source) { if (!ERPUtils.mapContainKey(source.searchData, ERPUtils.PARAM_SEARCH_CODE)) { return RetResult. errorT().retinfo("无效的id参数") } String orderCode = source.searchData.getString(ERPUtils.PARAM_SEARCH_CODE) OrderRefundRequest businessOrder = ESOne. getESOneInfo() .esClient(esClient) .jsonConvert(jsonConvert) .clazz(OrderRefundRequest.class) .queryBuilder({ //获取完成的数据情况 return search(null).byOrderCode(orderCode).build() }) .index(supplierService.getDateYearESIndex(source.supplierCode, ESKeys.ES_DELIVER_ORDER_REFUND_REQUEST_INDEX, 1)) .execute() if (businessOrder == null) { return RetResult. errorT().retinfo("无效的订单") } readOrderOptions(businessOrder, source.dataSourceId, source.supplierCode, source.options) return RetResult. successT().result(businessOrder) } @Override RetResult execute(ProcessSearchOptionsItem source) { //可以参考一些都能运的代码,但那个硬编码需要多一些,这里直接判断搜索条件里面都有没有对应的条件 if (ERPUtils.mapContainKey(source.searchData, ERPUtils.PARAM_SEARCH_ID)) { return queryById(source) } else if (ERPUtils.mapContainKey(source.searchData, ERPUtils.PARAM_SEARCH_CODE)) { return queryByCode(source) } return RetResult. errorT().retinfo("无效的查询方式execute,查多数据应该使用executeList") } @Override RetResult> executeList(ProcessSearchOptionsItem source) { if (ERPUtils.mapContainKey(source.searchData, ERPUtils.PARAM_SEARCH_IDS)) { return queryByIds(source) } else { return queryByConditions(source) } } //region 条件构造 //groovy没法用java中类似SendOrderESConditionBuilder的静态方法构造内部类,强制编译不报错,运行还是报错无适配的构造函数,但用常规的类好使,估计是内部类有什么说法 ESConditionBuilder search(RMap searchData) { return new ESConditionBuilder(searchData, QueryBuilders.boolQuery().must(QueryBuilders.typeQuery(ESKeys.ES_DELIVER_ORDER_REFUND_REQUEST_TYPE))) } //这里是做一个示例,表示通过查部件子表查询订单 ESConditionBuilder searchByOrderRider(RMap searchData) { return new ESConditionBuilder(searchData, QueryBuilders.boolQuery().must(QueryBuilders.typeQuery(ESKeys.ES_ERP_ORDER_PART_TYPE))) } //endregion class ESConditionBuilder { RMap searchData BoolQueryBuilder qb ESConditionBuilder() { } ESConditionBuilder(RMap searchData) { this.searchData = searchData } ESConditionBuilder(RMap searchData, BoolQueryBuilder qb) { this.searchData = searchData this.qb = qb } //上面没法用java类似的静态方法返回条件,运行期还是报错没有适配的构造函数 //注意这里如果定义成闭包,不能用this做流式写法,参考https://groovy-lang.org/closures.html#closure-owner //但是用了owner,返回的类型是Object,还得做转换,所以这里直接用java的写法 ESConditionBuilder byIds(String[] ids) { if (ids.length > 0) { qb = qb.must(QueryBuilders.idsQuery(ESKeys.ES_DELIVER_ORDER_REFUND_REQUEST_TYPE).addIds(ids)) } return this } ESConditionBuilder byIds(List ids) { if (!ids.isEmpty()) { qb = qb.must(QueryBuilders.idsQuery(ESKeys.ES_DELIVER_ORDER_REFUND_REQUEST_TYPE).addIds(ERPUtils.longArrayToStrArray(ERPUtils.longListToArray(ids)))) } return this } ESConditionBuilder byId(long id) { //这里不要判断idOrder是否大于0,防止条件漏了 qb = qb.must(QueryBuilders.idsQuery(ESKeys.ES_DELIVER_ORDER_REFUND_REQUEST_TYPE).addIds(String.valueOf(id))) return this } ESConditionBuilder byKeyWord() { if (ERPUtils.mapContainKey(searchData, "keyWord")) { String keyWord = searchData.getString("keyWord") QueryBuilder qbKeyWord = QueryBuilders.boolQuery() .should(QueryBuilders.termQuery("orderCode", keyWord.toLowerCase())) .should(QueryBuilders.matchQuery("orderName", keyWord).operator(Operator.AND)) qb = qb.must(qbKeyWord) } return this } ESConditionBuilder byRequestStatus() { if (ERPUtils.mapContainKey(searchData, "requestStatus")) { String orderStates = searchData.getString("requestStatus") qb = qb.must(QueryBuilders.termsQuery("requestStatus", orderStates.split(","))) } return this } ESConditionBuilder byRequestStatus(String requestStatus) { qb = qb.must(QueryBuilders.termsQuery("requestStatus", requestStatus.split(","))) return this } ESConditionBuilder byRequestStatus(int requestStatus) { qb = qb.must(QueryBuilders.termQuery("requestStatus", requestStatus)) return this } ESConditionBuilder byOrderCode() { if (ERPUtils.mapContainKey(searchData, "orderCode")) { String orderCode = searchData.getString("orderCode") qb = qb.must(QueryBuilders.termQuery("orderCode", orderCode.toLowerCase())) } return this } ESConditionBuilder byOrderCode(String orderCode) { qb = qb.must(QueryBuilders.termQuery("orderCode", orderCode.toLowerCase())) return this } ESConditionBuilder byBeginTime_Create() { if (ERPUtils.mapContainKey(searchData, "beginTime")) { String beginTimeStr = searchData.getString("beginTime") long beginTime if (beginTimeStr.contains("-")) { beginTime = DateUtil.getStartOfDay(DateUtil.asDate(beginTimeStr, "yyyy-MM-dd")).getTime() } else { beginTime = DateUtil.getStartOfDay(new Date(searchData.getLong("beginTime"))).getTime() } qb = qb.must(QueryBuilders.rangeQuery("createTimeLong").gte(beginTime)) } return this } ESConditionBuilder byEndTime_Create() { if (ERPUtils.mapContainKey(searchData, "endTime")) { String endTimeStr = searchData.getString("endTime") long endTime if (endTimeStr.contains("-")) { endTime = DateUtil.getEndOfDay(DateUtil.asDate(endTimeStr, "yyyy-MM-dd")).getTime() } else { endTime = DateUtil.getEndOfDay(new Date(searchData.getLong("endTime"))).getTime() } qb = qb.must(QueryBuilders.rangeQuery("createTimeLong").lte(endTime)) } return this } ESConditionBuilder byIdOrder() { if (ERPUtils.mapContainKey(searchData, "idOrder")) { long idOrder = searchData.getLong("idOrder") //这里不管是否大于0,都查询 qb = qb.must(QueryBuilders.termQuery("idOrder", idOrder)) } return this } ESConditionBuilder byIdStore() { if (ERPUtils.mapContainKey(searchData, "idStore")) { long idStore = searchData.getLong("idStore") //这里不管是否大于0,都查询 qb = qb.must(QueryBuilders.termQuery("idStore", idStore)) } return this } ESConditionBuilder byIdStorePlatform() { if (ERPUtils.mapContainKey(searchData, "idStorePlatform")) { long idStorePlatform = searchData.getLong("idStorePlatform") //这里不管是否大于0,都查询 qb = qb.must(QueryBuilders.termQuery("idStorePlatform", idStorePlatform)) } return this } ESConditionBuilder byPlatformCode() { if (ERPUtils.mapContainKey(searchData, "platformCode")) { String platformCode = searchData.getString("platformCode") qb = qb.must(QueryBuilders.termQuery("platformCode", platformCode.toLowerCase())) } return this } ESConditionBuilder byPlatformType() { if (ERPUtils.mapContainKey(searchData, "platformType")) { long platformType = searchData.getLong("platformType") //这里不管是否大于0,都查询 qb = qb.must(QueryBuilders.termQuery("platformType", platformType)) } return this } ESConditionBuilder byOutAfterSaleId() { if (ERPUtils.mapContainKey(searchData, "outAfterSaleId")) { String outAfterSaleId = searchData.getString("outAfterSaleId") qb = qb.must(QueryBuilders.termQuery("outAfterSaleId", outAfterSaleId.toLowerCase())) } return this } BoolQueryBuilder build() { return qb } } }