package com.lemans.ds import com.lemans.ds.part.Part import com.lemans.services.LemansService import grails.transaction.Transactional @Transactional(readOnly = true) class PartService extends LemansService { static final List SEARCH_COLUMNSET = [ 'partNumber', 'punctuatedPartNumber', 'partStatusCode', 'partStatusDescr', 'vendorPartNumber', 'brandName', 'partDescr', 'brandCode', 'vendorName', 'vendorId', 'subComCode', 'categoryId', 'subComCodeId', 'productCode', 'mediaUrl', 'extension', 'version' ].asImmutable() private static final List SEARCHABLE_PROPERTIES = [ 'partNumber', 'partDescr', 'brandCode', 'brandName', 'vendorId', 'vendorName', 'vendorPartNumber' ].asImmutable() private static final List META_DATA = ['partSpecificText', 'internalNotes', 'relatedParts', 'relatedProducts', 'footnotes', 'certificationUS', 'certificationEU', 'oemPartNumber'] private static final Map COLUMN_SETS = [_search: SEARCH_COLUMNSET].asImmutable() private static final Integer MAX_SEARCH_RECORDS = 1000 /** * Find a Part by partNumber. * * @param criteria containing partNumber * * @return part */ Map findPartByPartNumber(Map criteria) { Map partData = dqx(criteria).executeOneFrom('dbo.vwPart', ['partNumber = :partNumber'])?.results[0] Map partMetadata = dqx(criteria).executeOneFrom('dbo.vwPartMetadata', ['partNumber = :partNumber'])?.results[0] if (partMetadata) { partMetadata = transformMetadataClobToText(partMetadata) mergeMetaDataWithPart(partData, partMetadata) } else if (partData) { mergeMetaDataAsNull(partData) } partData } private void mergeMetaDataWithPart(Map partData, Map partMetaData) { META_DATA.each { String metaData -> partData."$metaData" = partMetaData."$metaData" } } private void mergeMetaDataAsNull(Map partData) { partData.identity { partSpecificText = null internalNotes = null relatedParts = null relatedProducts = null footnotes = null certificationUS = null certificationEU = null oemPartNumber = null } } @SuppressWarnings('ParameterReassignment') Map transformMetadataClobToText(Map partMetadata) { partMetadata.collectEntries { k, v -> if (v?.class?.simpleName == 'ClobImpl') { v = v.characterStream.text } [k, v] } } /** * Find if a Part by partNumber exists. * * @param partNumber * * @return true if part exists */ boolean partWithPartNumberExists(String partNumber) { sql().rows('SELECT * FROM vwPart WHERE partNumber = ?', [partNumber])[0] } /** * Find Parts matching the filter criteria. * * @param criteria containing filter criteria * filters: * partStatusCode - exact * subComCode - exact/multiple * productId - exact/multiple * partNumber - like * partDescr - like * brandCode - like * brandName - like * vendorId - like * vendorName - like * vendorPartNumber - like * q - like (without client supplied wildcards) on partNumber and partNumber * * @return Map with results containing parts that match the filter criteria */ Map findParts(Map criteria) { criteria.sorting = criteria.sorting ?: 'partNumber+ASC' criteria.columns = criteria.columns ?: '_search' if (criteria.pageSize > MAX_SEARCH_RECORDS) { criteria.pageSize = MAX_SEARCH_RECORDS } dqx(criteria).executeFrom('dbo.vwPart', searchClauses(criteria), COLUMN_SETS) } Map findPartsByLocale(Map criteria) { List clauses = ['partNumber = :partNumber', 'locale = :locale'] Map partLocale = dqx(criteria).executeOneFrom('dbo.vwPartLocale', clauses)?.results[0] if (partLocale) { transformMetadataClobToText(partLocale) } } private List searchClauses(Map criteria) { List clauses = [] if (criteria.partStatusCode) { clauses << 'partStatusCode = :partStatusCode' } Integer categoryId = criteria.categoryId if (categoryId != null) { if (categoryId == Part.UNASSIGNED_CATEGORY_ID) { clauses << 'categoryId IS NULL' } else { clauses << 'categoryId = :categoryId' } } if (criteria.productId) { if (criteria.productId == Part.UNASSIGNED_PRODUCT_ID) { clauses << 'primaryProductId IS NULL' } else { List productIdList = criteria.productId?.split(',') String productIds = productIdList.collect { it }.join(',') clauses << "primaryProductId IN ($productIds)" } } if (criteria.subComCode) { List subComCodeList = criteria.subComCode?.split(',') String subComCodes = subComCodeList.collect { String unquoted -> "'$unquoted'" }.join(',') clauses << "subComCode IN ($subComCodes)" } if (criteria.q) { criteria.qLike = "%$criteria.q%" as String clauses << '(partNumber LIKE :qLike OR partDescr LIKE :qLike)' } clauses + wildcardClauses(criteria, SEARCHABLE_PROPERTIES) } }