package com.lemans.ds.solr import com.lemans.services.LemansService import org.apache.commons.lang3.concurrent.BasicThreadFactory import org.apache.solr.client.solrj.SolrQuery import org.apache.solr.client.solrj.request.QueryRequest import org.apache.solr.client.solrj.response.FacetField import org.apache.solr.client.solrj.response.QueryResponse import org.apache.solr.common.util.NamedList import org.apache.solr.common.util.SimpleOrderedMap import org.codehaus.groovy.runtime.InvokerHelper import java.time.LocalDate import java.time.temporal.WeekFields import java.util.concurrent.CompletableFuture import java.util.concurrent.Executor import java.util.concurrent.ExecutorService import java.util.concurrent.Executors import java.util.concurrent.Future import java.util.function.Supplier import java.util.stream.Collectors @SuppressWarnings(['MethodCount', 'UnusedVariable', 'CyclomaticComplexity', 'LineLength']) class SolrQueryService extends LemansService { private static final List VALID_FQ_FIELDS = ['categoryId', 'brandId', 'vendorId', 'derivedPartStatusId', 'userName'] private static final List VALID_FQ_DATE_FIELDS = ['goliveDate'] private static final String QUEUE_COUNT = 'SELECT * FROM [QueueWeeklyCountHistory] WHERE weekEndDate = ? AND dateDeleted IS NULL' def dsQueueSolrClient private final ExecutorService pool = Executors.newFixedThreadPool(3, new BasicThreadFactory.Builder() .namingPattern('DS-SOLR-OVERVIEW-%d') .build()) List userOverView(QueuePayload payload) { List futures = [ queueCountsForPartsWithOutCategory(payload, pool), queueCountsForPartsWithOutPrimaryImage(payload, pool), queueCountsForPartsWithOutProduct(payload, pool), queueCountsForPartsWithOutAttributeValue(payload, pool), queueCountsForProductsWithOutPrimaryImage(payload, pool), queueCountsForProductsWithOutFeatureText(payload, pool), queueCountsForSplitProduct(payload, pool), queueCountsForPartsWithoutFitment(payload, pool), queueCountsForPartsWithTentativeFitment(payload, pool), queueCountsForPartImagesToReview(payload, pool), queueCountsForPartNeedMDChangeFlag(payload, pool), queueCountsForPartsNotStarted(payload, pool), queueCountsForPartsSomeInProgress(payload, pool), queueCountsForPartsAllInProgress(payload, pool), queueCountsForPartsDone(payload, pool), queueCountsForPartsWithChangedDescription(payload, pool), queueCountsForProductsNotStarted(payload, pool), queueCountsForProductsSomeInProgress(payload, pool), queueCountsForProductsAllInProgress(payload, pool), queueCountsForProductsDone(payload, pool), categoryFacetsForParts(payload, pool), categoryFacetsForProducts(payload, pool) ] List response = futures.stream().map { CompletableFuture future -> future.join() }.collect(Collectors.toList()) Map partFacets = response.find { it.type == QueueType.CATEGORY_FACETS_BY_PARTS.name() } Map productFacets = response.find { it.type == QueueType.CATEGORY_FACETS_BY_PRODUCTS.name() } List modifiedResponse = [] response.each { QueueType queueType = it.type as QueueType if (queueType.getmode() == QueueMode.PART) { modifiedResponse << combineTotalValues(it, partFacets) } else if (queueType.getmode() == QueueMode.PRODUCT) { modifiedResponse << combineTotalValues(it, productFacets) } } modifiedResponse } private UserQueue combineTotalValues(Map filtered, Map unFiltered) { UserQueue userQueue = new UserQueue() userQueue.unFilteredCount = unFiltered.count userQueue.count = filtered.count userQueue.type = filtered.type userQueue.displayName = filtered.displayName userQueue.drillDowns = unFiltered.drillDowns.collect { unFilteredCategory -> Map filteredDrillDown = filtered.drillDowns.find { it.categoryId == unFilteredCategory.categoryId } DrillDown drillDown = new DrillDown() drillDown.count = filteredDrillDown?.count ?: 0 drillDown.categoryId = unFilteredCategory.categoryId drillDown.unFilteredCount = unFilteredCategory.count drillDown } userQueue } List adminOverview(QueuePayload payload) { List futures = [ queueCountsForPartsWithOutCategory(payload, pool), queueCountsForPartsWithOutPrimaryImage(payload, pool), queueCountsForPartsWithOutProduct(payload, pool), queueCountsForPartsWithOutAttributeValue(payload, pool), queueCountsForProductsWithOutPrimaryImage(payload, pool), queueCountsForProductsWithOutFeatureText(payload, pool), queueCountsForSplitProduct(payload, pool), queueCountsForPartsNotStarted(payload, pool), queueCountsForPartsSomeInProgress(payload, pool), queueCountsForPartsAllInProgress(payload, pool), queueCountsForProductsNotStarted(payload, pool), queueCountsForProductsSomeInProgress(payload, pool), queueCountsForProductsAllInProgress(payload, pool), queueCountsForProductsDone(payload, pool), queueCountsForPartsDone(payload, pool), queueCountsForPartsWithChangedDescription(payload, pool), queueCountsForPartsWithImagesAndNoPrimaryImage(payload, pool), queueCountsForProductsWithImagesAndNoPrimaryImage(payload, pool), queueCountsForProductsWithOutPubCats(payload, pool), queueCountsForPartsWithOutFutureDate(payload, pool), queueCountsForPartImagesToReview(payload, pool), queueCountsForPartNeedMDChangeFlag(payload, pool), partsFacetedByUser(payload, pool), queueCountsForPartsWithComCodesNotAssociatedToCategory(payload, pool), queueCountsForQcPartPendingApproval(payload, pool), queueCountsForQcPartRejected(payload, pool), queueCountsForQCProductPendingApproval(payload, pool), queueCountsForQCProductRejected(payload, pool), latestGoliveDate(payload, pool), earliestGoliveDate(payload, pool), partLastUpdated(payload, pool), productLastUpdated(payload, pool) ] List queueCounts = futures.stream().map { CompletableFuture future -> future.join() }.collect(Collectors.toList()) injectPastWeekCounts(queueCounts) queueCounts } private void injectPastWeekCounts(List queueCounts) { List pastWeekCounts = pastWeekTotals() queueCounts.each { Map queueCount -> queueCount.pastWeekCount = pastWeekCounts.find { it.queueName == queueCount.type }?.queueCount ?: 0 } queueCounts.find { it.type == 'USER_FACETS_BY_PARTS' }?.pastWeekCount = pastWeekCounts.find { it.queueName == 'TOTAL_PARTS' }?.queueCount ?: 0 } private List pastWeekTotals() { java.sql.Date date = java.sql.Date.valueOf(LocalDate.now().with(WeekFields.of(Locale.default).dayOfWeek(), 1)) sql().rows(QUEUE_COUNT, [date]) } private CompletableFuture categoryFacetsForParts(QueuePayload payload, Executor executor) { CompletableFuture.supplyAsync(new Supplier() { @Override Map get() { QueuePayload queuePayload = copyWithQueueType(payload, QueueType.CATEGORY_FACETS_BY_PARTS) SolrQuery query = new SolrQuery() QueryResponse queryResponse = dsQueueSolrClient.query(buildFacetQuery(query, queuePayload)) buildResponse(queryResponse, queuePayload) } }, executor) } private CompletableFuture partsFacetedByUser(QueuePayload payload, Executor executor) { CompletableFuture.supplyAsync(new Supplier() { @Override Map get() { QueuePayload queuePayload = copyWithQueueType(payload, QueueType.USER_FACETS_BY_PARTS) SolrQuery query = new SolrQuery() QueryResponse queryResponse = dsQueueSolrClient.query(buildFacetQuery(query, queuePayload)) buildResponse(queryResponse, queuePayload) } }, executor) } private CompletableFuture queueCountsForPartsWithComCodesNotAssociatedToCategory(QueuePayload payload, Executor executor) { CompletableFuture.supplyAsync(new Supplier() { @Override Map get() { QueuePayload queuePayload = copyWithQueueType(payload, QueueType.PARTS_WITH_COM_CODES_NOT_ASSOCIATED_TO_CATEGORY) SolrQuery query = new SolrQuery() .addFilterQuery('(hasSubComCodeNotAssociatedToCategory:true)') .addFilterQuery('(categoryId:[* TO *])') QueryResponse queryResponse = dsQueueSolrClient.query(buildFacetQuery(query, queuePayload)) buildResponse(queryResponse, queuePayload) } }, executor) } private CompletableFuture queueCountsForQcPartPendingApproval(QueuePayload payload, Executor executor) { CompletableFuture.supplyAsync(new Supplier() { @Override Map get() { QueuePayload queuePayload = copyWithQueueType(payload, QueueType.QC_PART_PENDING_APPROVAL) SolrQuery query = new SolrQuery() .addFilterQuery('(qcStatusCode:13001)') QueryResponse queryResponse = dsQueueSolrClient.query(buildFacetQuery(query, queuePayload)) buildResponse(queryResponse, queuePayload) } }, executor) } private CompletableFuture queueCountsForQcPartRejected(QueuePayload payload, Executor executor) { CompletableFuture.supplyAsync(new Supplier() { @Override Map get() { QueuePayload queuePayload = copyWithQueueType(payload, QueueType.QC_PART_REJECTED) SolrQuery query = new SolrQuery() .addFilterQuery('(qcStatusCode:13003)') QueryResponse queryResponse = dsQueueSolrClient.query(buildFacetQuery(query, queuePayload)) buildResponse(queryResponse, queuePayload) } }, executor) } private CompletableFuture queueCountsForQCProductPendingApproval(QueuePayload payload, Executor executor) { CompletableFuture.supplyAsync(new Supplier() { @Override Map get() { QueuePayload queuePayload = copyWithQueueType(payload, QueueType.QC_PRODUCT_PENDING_APPROVAL) SolrQuery query = new SolrQuery() .addFilterQuery('(qcProductStatusCode:13001)') QueryResponse queryResponse = dsQueueSolrClient.query(buildFacetQuery(query, queuePayload)) buildResponse(queryResponse, queuePayload) } }, executor) } private CompletableFuture queueCountsForQCProductRejected(QueuePayload payload, Executor executor) { CompletableFuture.supplyAsync(new Supplier() { @Override Map get() { QueuePayload queuePayload = copyWithQueueType(payload, QueueType.QC_PRODUCT_REJECTED) SolrQuery query = new SolrQuery() .addFilterQuery('(qcProductStatusCode:13003)') QueryResponse queryResponse = dsQueueSolrClient.query(buildFacetQuery(query, queuePayload)) buildResponse(queryResponse, queuePayload) } }, executor) } private CompletableFuture latestGoliveDate(QueuePayload payload, Executor executor) { CompletableFuture.supplyAsync(new Supplier() { @Override Map get() { QueuePayload queuePayload = copyWithQueueType(payload, QueueType.PART_LATEST_GO_LIVE_DATE) SolrQuery query = new SolrQuery() .addFilterQuery('(qcStatusCode:13001)') query.add('json.facet', '{uniqueVals:{type:terms,field:userName,missing:true,mincount:1,limit:-1,facet:{date:"min(goliveDate)"}}}') addFacetFilters(query, queuePayload) buildResponseDate(dsQueueSolrClient.request(new QueryRequest(query)), queuePayload) } }, executor) } private CompletableFuture earliestGoliveDate(QueuePayload payload, Executor executor) { CompletableFuture.supplyAsync(new Supplier() { @Override Map get() { QueuePayload queuePayload = copyWithQueueType(payload, QueueType.PART_EARLIEST_GO_LIVE_DATE) SolrQuery query = new SolrQuery() .addFilterQuery('(qcStatusCode:13001)') query.add('json.facet', '{uniqueVals:{type:terms,field:userName,missing:true,mincount:1,limit:-1,facet:{date:"max(goliveDate)"}}}') addFacetFilters(query, queuePayload) buildResponseDate(dsQueueSolrClient.request(new QueryRequest(query)), queuePayload)} }, executor) } private CompletableFuture partLastUpdated(QueuePayload payload, Executor executor) { CompletableFuture.supplyAsync(new Supplier() { @Override Map get() { QueuePayload queuePayload = copyWithQueueType(payload, QueueType.PART_LAST_UPDATED) SolrQuery query = new SolrQuery() .addFilterQuery('(qcStatusCode:13001)') query.add('json.facet', '{uniqueVals:{type:terms,field:userName,missing:true,limit:-1,facet:{date:"max(qcPartLastUpdated)"}}}') addFacetFilters(query, queuePayload) buildResponseDate(dsQueueSolrClient.request(new QueryRequest(query)), queuePayload) } }, executor) } private CompletableFuture productLastUpdated(QueuePayload payload, Executor executor) { CompletableFuture.supplyAsync(new Supplier() { @Override Map get() { QueuePayload queuePayload = copyWithQueueType(payload, QueueType.PRODUCT_LAST_UPDATED) SolrQuery query = new SolrQuery() .addFilterQuery('(qcProductStatusCode:13001)') query.add('json.facet', '{uniqueVals:{type:terms,field:userName,missing:true,limit:-1,facet:{date:"max(qcProductLastUpdated)"}}}') addFacetFilters(query, queuePayload) buildResponseDate(dsQueueSolrClient.request(new QueryRequest(query)), queuePayload) } }, executor) } private CompletableFuture categoryFacetsForProducts(QueuePayload payload, Executor executor) { CompletableFuture.supplyAsync(new Supplier() { @Override Map get() { QueuePayload queuePayload = copyWithQueueType(payload, QueueType.CATEGORY_FACETS_BY_PRODUCTS) SolrQuery query = new SolrQuery() buildResponse(dsQueueSolrClient.request(new QueryRequest(buildCardinalityQuery(query, queuePayload))), queuePayload) } }, executor) } private CompletableFuture queueCountsForPartsWithOutCategory(QueuePayload payload, Executor executor) { CompletableFuture.supplyAsync(new Supplier() { @Override Map get() { QueuePayload queuePayload = copyWithQueueType(payload, QueueType.PARTS_WITH_OUT_CATEGORY) SolrQuery query = new SolrQuery() .addFilterQuery('(*:* NOT categoryId:[* TO *])') .addFilterQuery('(assignableCategoryId:[* TO *])') if (payload.viewType == ViewType.USER) { query.addFacetField('assignableCategoryId') } QueryResponse queryResponse = dsQueueSolrClient.query(buildFacetQuery(query, queuePayload)) buildResponse(queryResponse, queuePayload) } }, executor) } private CompletableFuture queueCountsForPartsWithOutPrimaryImage(QueuePayload payload, Executor executor) { CompletableFuture.supplyAsync(new Supplier() { @Override Map get() { QueuePayload queuePayload = copyWithQueueType(payload, QueueType.PARTS_WITH_OUT_PRIMARY_IMAGE) SolrQuery query = new SolrQuery() .addFilterQuery('(*:* NOT partPrimaryMediaId:[* TO *])') .addFilterQuery('(categoryId:[* TO *])') QueryResponse queryResponse = dsQueueSolrClient.query(buildFacetQuery(query, queuePayload)) buildResponse(queryResponse, queuePayload) } }, executor) } private CompletableFuture queueCountsForPartsWithImagesAndNoPrimaryImage(QueuePayload payload, Executor executor) { CompletableFuture.supplyAsync(new Supplier() { @Override Map get() { QueuePayload queuePayload = copyWithQueueType(payload, QueueType.PARTS_WITH_IMAGES_AND_NO_PRIMARY_IMAGE) SolrQuery query = new SolrQuery() .addFilterQuery('(*:* NOT partPrimaryMediaId:[* TO *])') .addFilterQuery('(hasPartImage:true)') .addFilterQuery('(categoryId:[* TO *])') QueryResponse queryResponse = dsQueueSolrClient.query(buildFacetQuery(query, queuePayload)) buildResponse(queryResponse, queuePayload) } }, executor) } private CompletableFuture queueCountsForPartsWithOutProduct(QueuePayload payload, Executor executor) { CompletableFuture.supplyAsync(new Supplier() { @Override Map get() { QueuePayload queuePayload = copyWithQueueType(payload, QueueType.PARTS_WITH_OUT_PRODUCT) SolrQuery query = new SolrQuery() .addFilterQuery('(*:* NOT productId:[* TO *])') .addFilterQuery('(brandId:[* TO *])') .addFilterQuery('(categoryId:[* TO *])') QueryResponse queryResponse = dsQueueSolrClient.query(buildFacetQuery(query, queuePayload)) buildResponse(queryResponse, queuePayload) } }, executor) } private CompletableFuture queueCountsForPartsWithOutAttributeValue(QueuePayload payload, Executor executor) { CompletableFuture.supplyAsync(new Supplier() { @Override Map get() { QueuePayload queuePayload = copyWithQueueType(payload, QueueType.PARTS_WITH_OUT_ATTRIBUTE_VALUE) SolrQuery query = new SolrQuery() .addFilterQuery('(hasPartAttributeValues:false)') .addFilterQuery('(categoryId:[* TO *])') QueryResponse queryResponse = dsQueueSolrClient.query(buildFacetQuery(query, queuePayload)) buildResponse(queryResponse, queuePayload) } }, executor) } private CompletableFuture queueCountsForProductsWithOutPrimaryImage(QueuePayload payload, Executor executor) { CompletableFuture.supplyAsync(new Supplier() { @Override Map get() { QueuePayload queuePayload = copyWithQueueType(payload, QueueType.PRODUCTS_WITH_OUT_PRIMARY_IMAGE) SolrQuery query = new SolrQuery() .addFilterQuery('(*:* NOT productPrimaryMediaId:[* TO *])') .addFilterQuery('(categoryId:[* TO *])') buildResponse(dsQueueSolrClient.request(new QueryRequest(buildCardinalityQuery(query, queuePayload))), queuePayload) } }, executor) } private CompletableFuture queueCountsForProductsWithOutFeatureText(QueuePayload payload, Executor executor) { CompletableFuture.supplyAsync(new Supplier() { @Override Map get() { QueuePayload queuePayload = copyWithQueueType(payload, QueueType.PRODUCTS_WITH_OUT_FEATURE_TEXT) SolrQuery query = new SolrQuery() .addFilterQuery('(hasProductFeature:false)') .addFilterQuery('(categoryId:[* TO *])') buildResponse(dsQueueSolrClient.request(new QueryRequest(buildCardinalityQuery(query, queuePayload))), queuePayload) } }, executor) } private CompletableFuture queueCountsForPartsWithOutFutureDate(QueuePayload payload, Executor executor) { CompletableFuture.supplyAsync(new Supplier() { @Override Map get() { QueuePayload queuePayload = copyWithQueueType(payload, QueueType.FUTURE_PARTS_WITH_NO_DATE) SolrQuery query = new SolrQuery() .addFilterQuery('(*:* NOT goliveDate:[* TO *])') .addFilterQuery('(partStatusCode:5)') .addFilterQuery('(categoryId:[* TO *])') QueryResponse queryResponse = dsQueueSolrClient.query(buildFacetQuery(query, queuePayload)) buildResponse(queryResponse, queuePayload) } }, executor) } private CompletableFuture queueCountsForProductsWithOutPubCats(QueuePayload payload, Executor executor) { CompletableFuture.supplyAsync(new Supplier() { @Override Map get() { QueuePayload queuePayload = copyWithQueueType(payload, QueueType.PRODUCTS_WITH_OUT_PUB_CATS) SolrQuery query = new SolrQuery() .addFilterQuery('(hasProductPubCat:false)') .addFilterQuery('(categoryId:[* TO *])') buildResponse(dsQueueSolrClient.request(new QueryRequest(buildCardinalityQuery(query, queuePayload))), queuePayload) } }, executor) } private CompletableFuture queueCountsForProductsWithImagesAndNoPrimaryImage(QueuePayload payload, Executor executor) { CompletableFuture.supplyAsync(new Supplier() { @Override Map get() { QueuePayload queuePayload = copyWithQueueType(payload, QueueType.PRODUCTS_WITH_IMAGES_AND_NO_PRIMARY_IMAGE) SolrQuery query = new SolrQuery() .addFilterQuery('(*:* NOT productPrimaryMediaId:[* TO *])') .addFilterQuery('(hasProductImageExcludingSizeChart:true)') .addFilterQuery('(categoryId:[* TO *])') buildResponse(dsQueueSolrClient.request(new QueryRequest(buildCardinalityQuery(query, queuePayload))), queuePayload) } }, executor) } private CompletableFuture queueCountsForSplitProduct(QueuePayload payload, Executor executor) { CompletableFuture.supplyAsync(new Supplier() { @Override Map get() { QueuePayload queuePayload = copyWithQueueType(payload, QueueType.SPLIT_PRODUCT) SolrQuery query = new SolrQuery() .addFilterQuery('(productFlag:splitValidation)') .addFilterQuery('(categoryId:[* TO *])') buildResponse(dsQueueSolrClient.request(new QueryRequest(buildCardinalityQuery(query, queuePayload))), queuePayload) } }, executor) } private CompletableFuture queueCountsForPartsWithoutFitment(QueuePayload payload, Executor executor) { CompletableFuture.supplyAsync(new Supplier() { @Override Map get() { QueuePayload queuePayload = copyWithQueueType(payload, QueueType.PARTS_WITH_OUT_FITMENT) SolrQuery query = new SolrQuery() .addFilterQuery('(hasFitment:false)') .addFilterQuery('(categoryId:[* TO *])') QueryResponse queryResponse = dsQueueSolrClient.query(buildFacetQuery(query, queuePayload)) buildResponse(queryResponse, queuePayload) } }, executor) } private CompletableFuture queueCountsForPartsWithTentativeFitment(QueuePayload payload, Executor executor) { CompletableFuture.supplyAsync(new Supplier() { @Override Map get() { QueuePayload queuePayload = copyWithQueueType(payload, QueueType.PARTS_WITH_TENTATIVE_FITMENT) SolrQuery query = new SolrQuery() .addFilterQuery('(hasTentativeFitment:true)') .addFilterQuery('(categoryId:[* TO *])') query.add('json.facet', '{uniqueVals:{type:terms,field:categoryId,missing:true,mincount:1,limit:-1,facet:{uniqueCount:"sum(tentativeFitmentCount)"}}}') addFacetFilters(query, queuePayload) buildResponse(dsQueueSolrClient.request(new QueryRequest(query)), queuePayload) } }, executor) } private CompletableFuture queueCountsForPartImagesToReview(QueuePayload payload, Executor executor) { CompletableFuture.supplyAsync(new Supplier() { @Override Map get() { QueuePayload queuePayload = copyWithQueueType(payload, QueueType.PARTS_IMAGES_TO_REVIEW) SolrQuery query = new SolrQuery() .addFilterQuery('(hasPartImagesToReview:true)') .addFilterQuery('(categoryId:[* TO *])') QueryResponse queryResponse = dsQueueSolrClient.query(buildFacetQuery(query, queuePayload)) buildResponse(queryResponse, queuePayload) } }, executor) } private CompletableFuture queueCountsForPartNeedMDChangeFlag(QueuePayload payload, Executor executor) { CompletableFuture.supplyAsync(new Supplier() { @Override Map get() { QueuePayload queuePayload = copyWithQueueType(payload, QueueType.PARTS_NEED_MARKETING_DESCR_CHANGE) SolrQuery query = new SolrQuery() .addFilterQuery('(hasPartNeedMDChangeFlag:true)') .addFilterQuery('(categoryId:[* TO *])') QueryResponse queryResponse = dsQueueSolrClient.query(buildFacetQuery(query, queuePayload)) buildResponse(queryResponse, queuePayload) } }, executor) } private CompletableFuture queueCountsForPartsNotStarted(QueuePayload payload, Executor executor) { CompletableFuture.supplyAsync(new Supplier() { @Override Map get() { QueuePayload queuePayload = copyWithQueueType(payload, QueueType.PART_ATTR_RESEARCH_VALUE_NONE) SolrQuery query =new SolrQuery() .addFilterQuery('partAttribute:("*" NOT ("Research Value|Reviewed" OR "Research Value|Level 1" OR "Research Value|Level 2" OR "Research Value|Finalized"))') .addFilterQuery('categoryId:[* TO *]') QueryResponse queryResponse = dsQueueSolrClient.query(buildFacetQuery(query, queuePayload)) buildResponse(queryResponse, queuePayload) } }, executor) } private CompletableFuture queueCountsForPartsSomeInProgress(QueuePayload payload, Executor executor) { CompletableFuture.supplyAsync(new Supplier() { @Override Map get() { QueuePayload queuePayload = copyWithQueueType(payload, QueueType.PART_ATTR_RESEARCH_VALUE_LEVEL1) SolrQuery query = new SolrQuery() .addFilterQuery('(partAttribute:"Research Value|Level 1")') .addFilterQuery('(categoryId:[* TO *])') QueryResponse queryResponse = dsQueueSolrClient.query(buildFacetQuery(query, queuePayload)) buildResponse(queryResponse, queuePayload) } }, executor) } private CompletableFuture queueCountsForPartsAllInProgress(QueuePayload payload, Executor executor) { CompletableFuture.supplyAsync(new Supplier() { @Override Map get() { QueuePayload queuePayload = copyWithQueueType(payload, QueueType.PART_ATTR_RESEARCH_VALUE_LEVEL2) SolrQuery query = new SolrQuery() .addFilterQuery('((partAttribute:("Research Value|Level 2")) OR (partAttribute:("Research Value|Reviewed")))') .addFilterQuery('(categoryId:[* TO *])') QueryResponse queryResponse = dsQueueSolrClient.query(buildFacetQuery(query, queuePayload)) buildResponse(queryResponse, queuePayload) } }, executor) } private CompletableFuture queueCountsForPartsDone(QueuePayload payload, Executor executor) { CompletableFuture.supplyAsync(new Supplier() { @Override Map get() { QueuePayload queuePayload = copyWithQueueType(payload, QueueType.PART_ATTR_RESEARCH_VALUE_FINALIZED) SolrQuery query = new SolrQuery() .addFilterQuery('(partAttribute:"Research Value|Finalized")') .addFilterQuery('(categoryId:[* TO *])') QueryResponse queryResponse = dsQueueSolrClient.query(buildFacetQuery(query, queuePayload)) buildResponse(queryResponse, queuePayload) } }, executor) } private CompletableFuture queueCountsForPartsWithChangedDescription(QueuePayload payload, Executor executor) { CompletableFuture.supplyAsync(new Supplier() { @Override Map get() { QueuePayload queuePayload = copyWithQueueType(payload, QueueType.PARTS_WITH_DESCRIPTION_CHANGE) SolrQuery query = new SolrQuery() .addFilterQuery('(partFlag:"DescriptionChange")') .addFilterQuery('(categoryId:[* TO *])') QueryResponse queryResponse = dsQueueSolrClient.query(buildFacetQuery(query, queuePayload)) buildResponse(queryResponse, queuePayload) } }, executor) } private CompletableFuture queueCountsForProductsNotStarted(QueuePayload payload, Executor executor) { CompletableFuture.supplyAsync(new Supplier() { @Override Map get() { QueuePayload queuePayload = copyWithQueueType(payload, QueueType.PRODUCTS_NOT_STARTED) SolrQuery query = new SolrQuery() .addFilterQuery('(productFlag:partsNotStarted)') .addFilterQuery('(categoryId:[* TO *])') buildResponse(dsQueueSolrClient.request(new QueryRequest(buildCardinalityQuery(query, queuePayload))), queuePayload) } }, executor) } private CompletableFuture queueCountsForProductsSomeInProgress(QueuePayload payload, Executor executor) { CompletableFuture.supplyAsync(new Supplier() { @Override Map get() { QueuePayload queuePayload = copyWithQueueType(payload, QueueType.PRODUCTS_SOME_IN_PROGRESS) SolrQuery query = new SolrQuery() .addFilterQuery('(productFlag:partsSomeInProgress)') .addFilterQuery('(categoryId:[* TO *])') buildResponse(dsQueueSolrClient.request(new QueryRequest(buildCardinalityQuery(query, queuePayload))), queuePayload) } }, executor) } private CompletableFuture queueCountsForProductsAllInProgress(QueuePayload payload, Executor executor) { CompletableFuture.supplyAsync(new Supplier() { @Override Map get() { QueuePayload queuePayload = copyWithQueueType(payload, QueueType.PRODUCTS_ALL_IN_PROGRESS) SolrQuery query = new SolrQuery() .addFilterQuery('(productFlag:partsAllInProgress)') .addFilterQuery('(categoryId:[* TO *])') buildResponse(dsQueueSolrClient.request(new QueryRequest(buildCardinalityQuery(query, queuePayload))), queuePayload) } }, executor) } private CompletableFuture queueCountsForProductsDone(QueuePayload payload, Executor executor) { CompletableFuture.supplyAsync(new Supplier() { @Override Map get() { QueuePayload queuePayload = copyWithQueueType(payload, QueueType.PRODUCTS_DONE) SolrQuery query = new SolrQuery() .addFilterQuery('(productFlag:partsDone)') .addFilterQuery('(categoryId:[* TO *])') buildResponse(dsQueueSolrClient.request(new QueryRequest(buildCardinalityQuery(query, queuePayload))), queuePayload) } }, executor) } private QueuePayload copyWithQueueType(QueuePayload payload, QueueType queueType) { QueuePayload queuePayload = new QueuePayload() use(InvokerHelper) { queuePayload.properties = payload.properties queuePayload.queueType = queueType } queuePayload } private Map buildResponse(NamedList response, QueuePayload payload) { SimpleOrderedMap facets = response.get('facets') SimpleOrderedMap uniqueVals = facets ? facets.get('uniqueVals') : [:] SimpleOrderedMap missing = uniqueVals?.get('missing') List buckets = uniqueVals?.get('buckets') List values = populateCardinalityValues(buckets, missing, payload) Integer totalCount = values?.stream()?.mapToInt { a -> (Integer) a.count }?.sum() [type: payload.queueType.name(), displayName: payload.queueType.value, drillDowns: values ?: [], count: totalCount ?: 0] } private List populateCardinalityValues(List buckets, SimpleOrderedMap missing, QueuePayload payload) { List values if (payload.viewType == ViewType.ADMIN) { values = buckets?.findAll { it.get('count') > 0 }?.collect { SimpleOrderedMap fieldStatsInfo -> [userName: fieldStatsInfo.get('val'), count: fieldStatsInfo.get('uniqueCount')] } if (missing?.get('uniqueCount')) { values.add([userName: 'No User Assigned', count: missing.get('uniqueCount')]) } } else { values = buckets?.findAll { it.get('count') > 0 }?.collect { SimpleOrderedMap fieldStatsInfo -> [categoryId: (fieldStatsInfo.get('val') ?: '')?.toInteger(), count: fieldStatsInfo.get('uniqueCount')] } if (missing?.get('uniqueCount')) { values.add([categoryId: -1, count: missing.get('uniqueCount')]) } } values } private Map buildResponseDate(NamedList response, QueuePayload payload) { SimpleOrderedMap facets = response.get('facets') SimpleOrderedMap uniqueVals = facets ? facets.get('uniqueVals') : [:] SimpleOrderedMap missing = uniqueVals?.get('missing') List buckets = uniqueVals?.get('buckets') List values = populateCardinalityValuesForDate(buckets, missing, payload) Optional> optionalResult = values?.stream() ?.max{ obj1, obj2 -> if (obj1?.date == null && obj2?.date == null) { return 0 } else if (obj1?.date == null) { return 1 } else if (obj2?.date == null) { return -1 } else { return obj1?.date.compareTo(obj2?.date) } }?.orElse(null) Date totalDate = optionalResult?.isPresent() ? optionalResult?.get()['date'] : null [type: payload.queueType.name(), displayName: payload.queueType.value, drillDowns: values ?: [], date: totalDate] } private List populateCardinalityValuesForDate(List buckets, SimpleOrderedMap missing, QueuePayload payload) { List values if (payload.viewType == ViewType.ADMIN) { values = buckets?.collect { SimpleOrderedMap fieldStatsInfo -> [userName: fieldStatsInfo.get('val'), date: fieldStatsInfo.get('date')] } if (missing?.get('date')) { values.add([userName: 'No User Assigned', date: missing.get('date')]) } } else { values = buckets?.collect { SimpleOrderedMap fieldStatsInfo -> [categoryId: (fieldStatsInfo.get('val') ?: '')?.toInteger(), date: fieldStatsInfo.get('date')] } if (missing?.get('date')) { values.add([categoryId: -1, date: missing.get('date')]) } } values } private Map buildResponse(QueryResponse response, QueuePayload payload) { Map facets = response.facetFields.collectEntries { FacetField facetField -> String key = treatedName(facetField.name) [(key): [values: populateValues(facetField.values, payload)]] } if (payload.viewType == ViewType.ADMIN) { [type: payload.queueType.name(), displayName: payload.queueType.value, drillDowns: facets.userName.values, count: response.results.numFound] } else if (payload.queueType == QueueType.PARTS_WITH_OUT_CATEGORY) { [type: payload.queueType.name(), displayName: payload.queueType.value, drillDowns: facets.assignableCategoryId.values, count: response.results.numFound] } else { [type: payload.queueType.name(), displayName: payload.queueType.value, drillDowns: facets.categoryId.values, count: response.results.numFound] } } private String treatedName(String facetFieldName) { facetFieldName.contains('_FC') ? facetFieldName.replace('_FC', '') : facetFieldName } private List populateValues(List facetCounts, QueuePayload payload) { if (payload.viewType == ViewType.ADMIN) { collectUserFacetValues(facetCounts) } else if (payload.queueType == QueueType.PARTS_WITH_OUT_CATEGORY) { collectAssignableCategoryFacetValues(facetCounts) } else { collectCategoryFacetValues(facetCounts) } } private List collectAssignableCategoryFacetValues(List facetCounts) { facetCounts.findAll { it.count > 0 }.collect { FacetField.Count facetFieldCount -> if (facetFieldCount.name) { [categoryId: facetFieldCount.name?.toInteger(), count: facetFieldCount.count] } else { [categoryId: -1, count: facetFieldCount.count] } } } private List collectUserFacetValues(List facetCounts) { facetCounts.findAll { it.count > 0 }.collect { FacetField.Count facetFieldCount -> if (facetFieldCount.name) { [userName: facetFieldCount.name, count: facetFieldCount.count] } else { [userName: 'No User Assigned', count: facetFieldCount.count] } } } private List collectCategoryFacetValues(List facetCounts) { facetCounts.findAll { it.count > 0 }.collect { FacetField.Count facetFieldCount -> if (facetFieldCount.name && facetFieldCount.name != 'null') { [categoryId: facetFieldCount.name?.toInteger(), count: facetFieldCount.count] } else { [categoryId: -1, count: facetFieldCount.count] } } } private SolrQuery buildFacetQuery(SolrQuery query, QueuePayload payload) { query.rows = 0 query.query = '*:*' addFacets(query, payload) addFQFilters(query, payload) log.error(payload.queueType.toString() + ' ' + query.toQueryString()) query } private void addFacets(SolrQuery query, QueuePayload payload) { query.addFacetField(facetField(payload)) query.facetMissing = true query.facetMinCount = 1 query.facetLimit = -1 } private String facetField(QueuePayload payload) { payload.viewType == ViewType.ADMIN ? 'userName' : 'categoryId' } private void addFQFilters(SolrQuery query, QueuePayload payload) { VALID_FQ_FIELDS.each { List ids = payload.filters?.getProperty(it) if (ids != null && !ids.isEmpty()) { query.addFilterQuery("(${it}:(${ids.join(' OR ')}))") } } VALID_FQ_DATE_FIELDS.each { List dateRanges = payload.filters?.getProperty(it) if (dateRanges) { query.addFilterQuery("(${it}:(${dateRanges.collect { "[${it.start.toInstant().toString()} TO ${it.end.toInstant().toString()}]" }.join(' OR ')}))") } } } private SolrQuery buildCardinalityQuery(SolrQuery query, QueuePayload payload) { cardinalityFacet(query, payload) addFacetFilters(query, payload) query } private SolrQuery addFacetFilters(SolrQuery query, QueuePayload payload) { query.rows = 0 query.query = '*:*' addFQFilters(query, payload) log.error(payload.queueType.toString() + ' ' + query.toQueryString()) query } private void cardinalityFacet(SolrQuery query, QueuePayload payload) { query.add('json.facet', (payload.viewType == ViewType.ADMIN ? '{uniqueVals:{type: terms,field:userName,missing:true,mincount:1,limit:-1,facet:{uniqueCount:"unique(productId)"}}}' : '{uniqueVals:{type: terms, field:productCategoryId,missing:true,mincount:1,limit:-1,facet:{uniqueCount:"unique(productId)"}}}' ) ) } }