Skip to end of banner
Go to start of banner

Autofill address fields based on address hierarchy

Skip to end of metadata
Go to start of metadata

You are viewing an old version of this content. View the current version.

Compare with Current Restore this Version View Version History

« Previous Version 2 Next »

Developing new API which is completely driven by address hierarchy and uses AddressNode psql table to get required nodes data

const fetchGeneralAddressCode = async (organisationId, extendedModels, params, options = {}) => {

    const { searchType, queryString } = params;
    if (!searchType) {
        throw helper.wrongInputError('Location Key should be present');
    }

    const metaData = await addressHierarchy.getAddressMetadata(extendedModels, organisationId);
    const hierarchy = metaData.hierarchy || [];
    const nodeHierarchyMetaData = hierarchy.find(obj => helper.sanitizeStringCode(obj.location_key) === helper.sanitizeStringCode(searchType)) || {};
    if(!nodeHierarchyMetaData){
        throw helper.wrongInputError('Invalid Location Key');
    }
    let parentMetaDataArr = [];
    let searchTypeNodeFound = false;
    if (Array.isArray(hierarchy) && hierarchy.length > 0) {
        for (let i = 0; i < hierarchy.length; i++) {
            if (searchTypeNodeFound || helper.sanitizeStringCode(hierarchy[i].location_key) === helper.sanitizeStringCode(searchType)) {
                searchTypeNodeFound = true;
                parentMetaDataArr.push(hierarchy[i + 1]);
            }
        }
    }

    const queryParameters = [];
    const whereParts = [];
    let heirarchyId = nodeHierarchyMetaData.id;
    let nodeCode = helper.sanitizeStringCode(queryString);

    const toRet = {};
    toRet.data = {};

    whereParts.push(`addressNode.organisation_id = $${(queryParameters.length + 1)}`);
    queryParameters.push(organisationId);

    whereParts.push(`addressNode.hierarchy_id = $${(queryParameters.length + 1)}`);
    queryParameters.push(heirarchyId);

    whereParts.push(`addressNode.code = $${(queryParameters.length + 1)}`);
    queryParameters.push(nodeCode);

    const queryToExecute = `SELECT 
                            addressNode.id as node_id,addressNode.code as node_code,addressNode.name as node_name,addressNode.hierarchy_id as hierarchy_id,
                            addressNode.parent_node_id as parent_node_id,parentAddressNode.code as parent_code,parentAddressNode.name as parent_name
                            FROM addressNode 
                            JOIN addressNode AS parentAddressNode on addressNode.parent_node_id = parentAddressNode.id   
                            WHERE ${whereParts.join(' AND ')}`;

    const result = await helper.executeQueryAsync(extendedModels.AddressNode, queryToExecute, queryParameters, options);

    if (result[0] && result[0].node_name) {
        toRet.data[searchType] = result[0].node_name;
    } else {
        throw helper.wrongInputError('Data not found for this location key');
    }

    let nextNodesResult = result;
    for (let i = 0; i < parentMetaDataArr.length; i++) {
        try {
            heirarchyId = parentMetaDataArr[i].id;
            nodeCode = nextNodesResult[0].parent_code;
            const locationKey = parentMetaDataArr[i].location_key;

            queryParameters[1] = heirarchyId;
            queryParameters[2] = nodeCode;
            nextNodesResult = await helper.executeQueryAsync(extendedModels.AddressNode, queryToExecute, queryParameters, options);
            if (nextNodesResult[0] && nextNodesResult[0].node_name) {
                toRet.data[locationKey] = nextNodesResult[0].node_name;
            }
        } catch (err) {
          ***********************************
          // to be decided what to do if any of middle hierarchy nodedata is missing
          // is it possible in prod db to occur
          ***********************************
        }
    }
    
    return toRet;
};

success response type will be like

{
    "data": {
        "pincode": "DAM",
        "city": "Z1",
        "state": "DAMMAM"
    }
}

Point to consider for better efficiency of this api(lesser load on db):

  1. on loading page on frontend side fetch all possible node values for each address field (in useEffect)

  2. on selecting any of value from dropdown of any field this api will be called by passing queryString=selectedValue of node and searchType=type of selected field

  3. Frontend changes to be done in add consignment(crm) alongwith customer-portal and counter-booking(crm). (@saarthak to confirm all screens(frontend) where this change has to be done).

  4. What to do if any of middle node in hierarchy data is not found commented in above code snippet in catch block because it will hinder fetching data of other higher level (is it possible to occur in prod DB)

  5. Should disable all highe level nodes irrespective of the case that their value is fetched or not OR disable only those fields for which value is fetched. @saarthak