2020-12-19 - Category Tree Standard - Functions
Jump to navigation
Jump to search
Service - Category Tree Standard
Lambda Functions
CategoryNode/Create
/**
* Create a categoryNode in the category tree
* @param {string} catalogId
* @param {string} categoryId
* @param {string} [parentCategoryNodeId = ""] - if empty will be top level for this catalog
* @param {string} searchType - sellOffer|product|variantProduct
* @param {boolean} searchTypeMatchParent
* @param {object} [filter={}]
* @param {string} filterMatchParent - none|match|append
* @param {object} [requiredData={}]
* @param {string} requiredDataMatchParent - none|match|append
* @param {string} userId
*
* @returns {string} vertexId
*/
Authorizer
- Catalog level
- Checks user has authorization to create a categoryNode for the submitted catalogId, so need to check in logic if parentCategoryNodeId, it's catalogId must match
HdrApi
- Validator: (standard)
handler logic
- userId = ?_izContext.authorized/signedInUser..?
logic
Expects categoryVertexId to already exist in the graph, might need to check this first or work into Graph Handler process somehow.
Currently any category can be added, if we want to restrict which CategoryServiceNameTags can be added to a Category Tree Standard hierarchy we could do so here
- const catalogGraphServiceName = {from Config table: CatalogGraphServiceName}
- // find the parentCategory details
- const parentNodeVertexTag = null
- const parentNodeVertexUniqueId = null
- if parentCategoryNodeId
- parentNodeVertexTag = NPM module - izara-market-shared#CategoryTreeStandardLib.categoryNodeGraphTag
- parentNodeVertexUniqueId = parentCategoryNodeId
- else
- parentNodeVertexTag = NPM module - izara-market-shared#CategoryTreeStandardLib.catalogNodeGraphTag
- parentNodeVertexUniqueId = catalogId
- // get parentNode and validate
- const parentNode = NPM module - izara-shared#graphSharedLib.getVertexByVertexTagAndVertexUniqueId
- graphServiceName: catalogGraphServiceName
- vertexTag: parentNodeVertexTag
- vertexUniqueId: parentNodeVertexUniqueId
- if parentNode not found
- throw error to client "unrecognized parentCategoryNodeId"
- if parentNode.catalogId != catalogId
- throw error to client "parentCategoryNodeId and catalogId mismatch"
- // get category to make sure exists
- const category = NPM module - izara-shared#graphSharedLib.getVertexByVertexTagAndVertexUniqueId
- graphServiceName: catalogGraphServiceName
- vertexTag: NPM module - izara-market-shared#CategoryStandardLib.categoryGraphTag
- vertexUniqueId: categoryId
- check if categoryId exists (could add additional restrictions on CategoryServiceNameTag here)
- if not maybe retry, or throw error?
- // get parentNode Settings
- const parentNodeSettings = NPM module - izara-shared#graphSharedLib.getCurrentVersionedDataByVertexTagAndVertexUniqueId
- graphServiceName: catalogGraphServiceName
- vertexTag: parentNodeVertexTag
- vertexUniqueId: parentNodeVertexUniqueId
- versionedDataTag: NPM module - izara-shared#graphSharedLib.settingsVersionedDataTag
- // prepare values ready for creating categoryNode child and versioned settings
- const categoryNodeId = #categoryNodeLib.createCategoryNodeId
- catalogId: catalogId
- categoryId: categoryId
- uuid: {random uuid})
- // categoryNodeSetting's vertex properties
- const categoryNodeSettingsProperties =
- searchType: searchType
- searchTypeMatchParent: searchTypeMatchParent
- filter: filter
- filterMatchParent: filterMatchParent
- requiredData: requiredData
- requiredDataMatchParent: requiredDataMatchParent
// categoryNode's vertex properties
- const categoryNodeProperties = #categoryNodeLib.calculateCategoryNodeProperties
- searchType: searchType
- searchTypeMatchParent: searchTypeMatchParent
- filter: filter
- filterMatchParent: filterMatchParent
- requiredData: requiredData
- requiredDataMatchParent: requiredDataMatchParent
- parentNodeSettings: parentNodeSettings
- categoryNodeProperties.catalogId = catalogId
- // create a timestamp for the edge, this can be used to protect against race conditions when recalculating categoryNode settings
- const edgeTimestamp = current timestamp
- // create the new node vertex and settings
- publish message to catalogGraphServiceName InCreateChildNodeWithVersionedDataAndRelationship topic:
- subjectVertexTag: parentNodeVertexTag
- subjectVertexUniqueId: parentNodeVertexUniqueId
- vertexTag: NPM module - izara-market-shared#CategoryTreeStandardLib.categoryNodeGraphTag
- vertexUniqueId: categoryNodeId
- createdByUserId: userId
- versionedDataTag: NPM module - izara-shared#graphSharedLib.settingsVersionedDataTag
- dataVertexProperties: categoryNodeSettingsProperties
- edgeLabel: NPM module - izara-market-shared#CategoryTreeStandardLib.hasChildCategoryNodeEdgeLabel
- vertexProperties: categoryNodeProperties
- edgeProperties: {
- edgeTimestamp: edgeTimestamp
- // create an edge connecting the new categoryNodeId to its category node
- publish message to catalogGraphServiceName In(?..CreateEdgeFromVertexTagsAndUniqueIds) topic:
- subjectVertexTag: NPM module - izara-market-shared#CategoryTreeStandardLib.categoryNodeGraphTag
- subjectVertexUniqueId: categoryNodeId
- edgeLabel: NPM module - izara-market-shared#CategoryTreeStandardLib.isCategoryEdgeLabel
- objectVertexTag: NPM module - izara-market-shared#CategoryStandardLib.categoryGraphTag
- objectVertexUniqueId categoryId
- // create an SQS message to recalculate parents filter
- send message to own InRecalculateCategoryNodeFilter topic:
- vertexTag = parentNodeVertexTag
- vertexUniqueId: parentNodeVertexUniqueId
- // **** start process to rebuild/regenerate other nodes according to this new node, eg parent's filters, not yet worked out how to do this serverless and avoid race conditions
- // report the new category tree node
- send message to own OutCatalogCreated topic:
- catalogId: catalogId
- categoryId: categoryId
- vertexTag: NPM module - izara-market-shared#CategoryTreeStandardLib.categoryNodeGraphTag
- vertexUniqueId: categoryNodeId
- userId: userId
CategoryNode/BuildBrowseRequest
/**
* Builds a complete request ready to be sent to Search Result service
* @param {string} catalogId
* @param {string} [categoryNodeId=""] - empty means no category specified, top level catalog browse
* @param {string} [searchType=""] - overwrite default searchType
* @param {Object} [filter={}] - complex filter object, adds additional filters
* @param {Object} [requiredData={}] - overwrite default requiredData
*
* @returns {Object} searchResultRequest
*/
HdrInv
- Validator: (standard)
handler logic
- (standard)
logic
- const catalogGraphServiceName = {from Config table: CatalogGraphServiceName}
- // find the category/catalog node identified
- const nodeVertexTag = null
- const nodeVertexUniqueId = null
- if categoryNodeId
- nodeVertexTag = NPM module - izara-market-shared#CategoryTreeStandardLib.categoryNodeGraphTag
- nodeVertexUniqueId = categoryNodeId
- else
- nodeVertexTag = NPM module - izara-market-shared#CategoryTreeStandardLib.catalogNodeGraphTag
- nodeVertexUniqueId = catalogId
- const categoryNode = NPM module - izara-shared#graphSharedLib.getVertexByVertexTagAndVertexUniqueId
- graphServiceName: catalogGraphServiceName
- vertexTag: nodeVertexTag
- vertexUniqueId: nodeVertexUniqueId
- if no record found return error
- const browseRequest = {
- searchType: use searchType in params if set, else use categoryNode.searchType
- filter: if filter empty use categoryNode.filter, otherwise group both into their own blocks and join with an AND logical
- requiredData: use requiredData in params if set, else use categoryNode.requiredData
- return browseRequest
CategoryNode/UpdateSettings
/**
* Set a categoryNode to be enabled or disabled, will do nothing if setting same as current setting
* @param {string} catalogId
* @param {string} categoryNodeId
* @param {string} setting - enabled|disabled
* @param {string} userId
* @param {string} searchType - sellOffer|product|variantProduct
* @param {boolean} searchTypeMatchParent
* @param {object} [filter={}]
* @param {string} filterMatchParent - none|match|append
* @param {object} [requiredData={}]
* @param {string} requiredDataMatchParent - none|match|append
*
*/
Authorizer
- Catalog level
- Checks user has authorization to update categoryNode for the submitted catalogId, so need to check in logic categoryNodeId's catalogId matches
HdrApi
- Validator: (standard)
handler logic
- userId = ?_izContext.authorized/signedInUser..?
logic
- const catalogGraphServiceName = {from Config table: CatalogGraphServiceName}
- // find the categoryNode
- const categoryNode = NPM module - izara-shared#graphSharedLib.getVertexByVertexTagAndVertexUniqueId
- graphServiceName: catalogGraphServiceName
- vertexTag: NPM module - izara-market-shared#CategoryTreeStandardLib.categoryNodeGraphTag
- vertexUniqueId: categoryNodeId
- // validate request
- if no record found return error
- if categoryNode.catalogId != catalogId
- throw error to client "categoryNodeId and catalogId mismatch"
- // create a timestamp for the new Settings edge, this can be used to protect against race conditions when recalculating categoryNode settings
- const edgeTimestamp = current timestamp
// get the parentNode
- const parentNode = NPM module - izara-shared#graphSharedLib.getVertexInEdgesAndVerticesByVertexTagAndVertexUniqueId
- graphServiceName: catalogGraphServiceName
- objectVertexTag: NPM module - izara-market-shared#CategoryTreeStandardLib.categoryNodeGraphTag
- objectVertexUniqueId: categoryNodeId
- edgeLabel: NPM module - izara-market-shared#CategoryTreeStandardLib.hasChildCategoryNodeEdgeLabel
- // get parentNode Settings, parent node might be catalog or categoryNode so use the vertexId
- const parentNodeSettings = NPM module - izara-shared#graphSharedLib.getCurrentVersionedDataByVertexId
- graphServiceName: catalogGraphServiceName
- vertexId: parentNode.vertexId
- versionedDataTag: NPM module - izara-shared#graphSharedLib.settingsVersionedDataTag
- // categoryNodeSetting's vertex properties
- const categoryNodeSettingsProperties =
- searchType: searchType
- searchTypeMatchParent: searchTypeMatchParent
- filter: filter
- filterMatchParent: filterMatchParent
- requiredData: requiredData
- requiredDataMatchParent: requiredDataMatchParent
- // create new versionedData vertex
- publish message to catalogGraphServiceName InCreateVersionedData topic:
- vertexTag: NPM module - izara-market-shared#CategoryTreeStandardLib.categoryNodeGraphTag
- vertexUniqueId: categoryNodeId
- createdByUserId: userId
- versionedDataTag: NPM module - izara-shared#graphSharedLib.settingsVersionedDataTag
- dataVertexProperties: categoryNodeSettingsProperties
- timestamp: edgeTimestamp
// categoryNode's vertex properties
- const categoryNodeProperties = #categoryNodeLib.calculateCategoryNodeProperties
- searchType: searchType
- searchTypeMatchParent: searchTypeMatchParent
- filter: filter
- filterMatchParent: filterMatchParent
- requiredData: requiredData
- requiredDataMatchParent: requiredDataMatchParent
- parentNodeSettings: parentNodeSettings
// update categoryNode's vertex properties
- publish message to catalogGraphServiceName InUpdateNodeProperties topic:
- vertexTag: NPM module - izara-market-shared#CategoryTreeStandardLib.categoryNodeGraphTag
- vertexUniqueId: categoryNodeId
- vertexProperties: categoryNodeProperties
- // **** start process to rebuild/regenerate parent/child node filters etc, not yet worked out how to do this serverless and avoid race conditions
- // report the action
- send message to own OutCategoryNodeSettingsUpdated topic:
- categoryNodeId
- userId
CategoryNode/EnableDisable
/**
* Set a categoryNode to be enabled or disabled, will do nothing if setting same as current setting
* @param {string} catalogId
* @param {string} categoryNodeId
* @param {string} setting - enabled|disabled
* @param {string} userId
*
*/
Authorizer
- Catalog level
- Checks user has authorization to create a categoryNode for the submitted catalogId, so need to check in logic categoryNodeId's catalogId matches
HdrApi
- Validator: (standard)
handler logic
- userId = ?_izContext.authorized/signedInUser..?
logic
- const catalogGraphServiceName = {from Config table: CatalogGraphServiceName}
- // find the categoryNode
- const categoryNode = NPM module - izara-shared#graphSharedLib.getVertexByVertexTagAndVertexUniqueId
- graphServiceName: catalogGraphServiceName
- vertexTag: NPM module - izara-market-shared#CategoryTreeStandardLib.categoryNodeGraphTag
- vertexUniqueId: categoryNodeId
- // validate request
- if no record found return error
- if categoryNode.catalogId != catalogId
- throw error to client "categoryNodeId and catalogId mismatch"
- // prepare edge change
- const fromEdgeLabel = null
- const toEdgeLabel = null
- const replacedByEdgeLabel = null
- const msgTagText = ""
- if(setting == "disabled")
- fromEdgeLabel = NPM module - izara-market-shared#CategoryTreeStandardLib.hasChildCategoryNodeEdgeLabel
- toEdgeLabel = NPM module - izara-market-shared#CategoryTreeStandardLib.hasDisabledChildCategoryNodeEdgeLabel
- replacedByEdgeLabel = NPM module - izara-market-shared#CategoryTreeStandardLib.disabledByEdgeLabel
- msgTagText = "Disabled"
- else
- fromEdgeLabel = NPM module - izara-market-shared#CategoryTreeStandardLib.hasDisabledChildCategoryNodeEdgeLabel
- toEdgeLabel = NPM module - izara-market-shared#CategoryTreeStandardLib.hasChildCategoryNodeEdgeLabel
- replacedByEdgeLabel = NPM module - izara-market-shared#CategoryTreeStandardLib.enabledByEdgeLabel
- msgTagText = "Enabled"
- // get existing edge label
- const existingEdgeAndParentNode = NPM module - izara-shared#graphSharedLib.getVertexInEdgesAndVerticesByVertexTagAndVertexUniqueId
- graphServiceName: catalogGraphServiceName
- objectVertexTag: NPM module - izara-market-shared#CategoryTreeStandardLib.categoryNodeGraphTag
- objectVertexUniqueId: categoryNodeId
- edgeLabel: fromEdgeLabel
- // check not already set to toEdgeLabel
- if(!existingEdgeAndParentNode)
- throw error to client "categoryNodeId already setting"
- // create a timestamp for the edge, this can be used to protect against race conditions when recalculating categoryNode settings
- const edgeTimestamp = current timestamp
- // swap the edges
- publish message to catalogGraphServiceName InReplaceRelationship topic:
- fromEdgeId: existingEdgeAndParentNode.edge.edgeId
- toEdgeLabel: toEdgeLabel
- replacedByUserId: userId
- replacedByEdgeLabel: replacedByEdgeLabel
- toEdgeProperties: {edgeTimestamp: edgeTimestamp}
- // **** start process to rebuild/regenerate parent node filter if disabled, child then parent nodes if enabled, not yet worked out how to do this serverless and avoid race conditions
- // report the action
- send message to own Out (...?) "CategoryNode" + msgTagText topic:
- catalogId
- categoryNodeId
- userId
CategoryNode/RecalculateCategoryNodeFilter
/**
* Create a new vertex for the subject of translations
* @param {string} vertexTag
* @param {string} vertexUniqueId
*
*/
HdrSqs
- Triggered from InRecalculateCategoryNodeFilter topic:
- Validator: (standard)
handler logic
- (standard)
logic
... need to work out how to mitigate race conditions
- .. need to pull filters of all children and combine with own filter
Functions
categoryNodeLib.createCategoryNodeId
/**
* @param {string} catalogId
* @param {string} categoryId
* @param {string} uuid
*
* @returns {string} categoryNodeVertexId
*/
logic
- return catalogId + '_' + categoryId + '_' + uuid
categoryNodeLib.calculateCategoryNodeProperties
/**
* @param {string} searchType
* @param {boolean} searchTypeMatchParent
* @param {object} [filter={}]
* @param {string} filterMatchParent
* @param {object} [requiredData={}]
* @param {string} requiredDataMatchParent
* @param {object} parentNodeSettings
*
* @returns {object} categoryNodeProperties
*/
logic
- // create the new categoryNode's calculated settings, defaulting to submitted values (no parent matching)
- const categoryNodeProperties =
- searchType: searchType
- filter: filter
- requiredData: requiredData
- // calculate searchType value
- if searchTypeMatchParent == none
- categoryNodeProperties.searchType = searchType
- elseif searchTypeMatchParent == match
- categoryNodeProperties.searchType = parentNodeSettings.searchType
- // calculate filter value
- if filterMatchParent == match
- categoryNodeProperties.filter = parentNodeSettings.filter
- elseif filterMatchParent == append
- categoryNodeProperties.filter = {wrap parentNodeSettings.filter in level + AND element + wrap filter in level}
- // calculate requiredData value
- if requiredDataMatchParent == none
- if requiredData empty
- throw error "requiredData cannot be empty if not matching parent setting"
- if requiredData empty
- elseif requiredDataMatchParent == match
- categoryNodeProperties.requiredData = parentNodeSettings.requiredData
- elseif requiredDataMatchParent == append
- categoryNodeProperties.requiredData = {join parentNodeSettings.requiredData and requiredData, removing any duplicates}
- return categoryNodeProperties