Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Expand
titleapi/CustomerPortal/fetchGeneralAddressCode
Code Block
const fetchGeneralAddressCode = async (organisationId, extendedModels, params, options = {}) => {

    const { searchType, queryString } = params;
    ** searchType is hardcoded at frontend and sent in the body**
    if (!searchType) {
        throw helper.wrongInputError('Location Key should be present');
    }

    const metaData = await addressHierarchy.getAddressMetadata(extendedModels, organisationId);
    if (!metaData) {
        throw helper.wrongInputError('Metadata not found');
    }
    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');
    }
    const parentMetaDataArr = [];
    let searchTypeNodeFound = false;
    if (Array.isArray(hierarchy) && hierarchy.length > 0) {
        for (let i = 0; i < (hierarchy.length - 1); i++) {
            if (searchTypeNodeFound || helper.sanitizeStringCode(hierarchy[i].location_key) === helper.sanitizeStringCode(searchType)) {
                searchTypeNodeFound = true;
                parentMetaDataArr.push(hierarchy[i + 1]);
            }
        }
    }

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

    const toRet = {};
    toRet.data = {};
    queryParameters.push(organisationId);
    queryParameters.push(heirarchyId);
    queryParameters.push(nodeCode);

    const selectPart = 'SELECT addressNode.id as node_id,addressNode.code as node_code,addressNode.name as node_name,addressNode.hierarchy_id as hierarchy_id';
    const fromPart = ' FROM addressNode';
    let extendedSelectPart = '';
    let joinPart = '';
    const wherePart = ' WHERE addressNode.organisation_id = $1 and addressNode.hierarchy_id = $2 and addressNode.code = $3';

    if (parentMetaDataArr.length) {
        extendedSelectPart = ',addressNode.parent_node_id as parent_node_id,parentAddressNode.code as parent_code,parentAddressNode.name as parent_name';
        joinPart = ' JOIN addressNode AS parentAddressNode on addressNode.parent_node_id = parentAddressNode.id';
    }
    const queryToExecute = selectPart + extendedSelectPart + fromPart + joinPart + wherePart;
    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;
            if (i === (parentMetaDataArr.length - 1)) {
                const lastNodeQueryResult = selectPart + fromPart + wherePart;
                nextNodesResult = await helper.executeQueryAsync(extendedModels.AddressNode, lastNodeQueryResult, queryParameters, options);
            } else {
                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) {
            //do nothing
        }
    }
    return toRet;
};
Code Block
//success response
{
    "data": {
        "pincode": "DAM",
        "city": "Z1",
        "state": "DAMMAM"
    }
}
Expand
titleApi's Body:
Code Block
{
    "searchType": "pincode",
    "queryString": "DAM"
}

...

Updated filter logic:

Code Block
if (shouldSearchByName) { 				conditions.and.push({ name: ilike: queryString });
			} else if (shouldSearchByBothNameAndCode) {
				condition.and.push({
					or: [
						{ name: { ilike: queryString } },
						{ code: { ilike: queryString } }
					]
				});
			} else {
				conditions.and.push({ code: { ilike: queryString } });
			}

Frontend changes:

  1. Changes are to be done at 3 places

    1. Add Consignment modal (src/components/pages/details/AddDetails.tsx )

    2. Counter Booking → Add Address ( src/components/pages/OpsDashboard/Manage/counterBooking/AddAddress2.tsx )

    3. Customer-Portalsrc/components/address/create-address.tsx

  2. List to be populated in dropdown will be fetched after entering atleast 3 characters in the input field for corresponding node( pincode, city, state, country).

  3. Debouncing will be implemented at all places wherever we are fetching list to be populated in the dropdown. (500ms)

  4. In case allowOverrideHierarchy is false , we will let user only enter values from dropdown only.

  5. In case allowOverrideHierarchy is true: user can either select from dropdown or enter other values too.

  6. Only those fields will be disabled for which data is fetched, only when allow override hierarchy is false

...

  • It fetches data from AddressNode table on basis of address hierarchy setup, and returns data for current and higher nodes to populate.

  • It also handle the logic to either disbale the higher level nodes based on whether their value is fetched and allow_override_hierarchy is false.

  • It also update (auto populate) the value of higher nodes.

  • Drop down only on those fields which are in hierarchy

Expand
titlesaveAddressUsingAddressHierarchy code snippet called on onChange
Code Block
const saveAddressUsingAddressHierarchy = async (nodeValue: string, nodeType: string) => {
        if (!isKeyOfNewAddress(nodeType) || !nodeValue) return;
        setLoading(true);

        const fetchLocality = await fetchAddressUsingAddressHierarchy({ queryString: nodeValue, searchType: nodeType });

        if (!fetchLocality.isSuccess) {
            setNewAddress({
                ...newAddress,
                city: '',
                state: '',
                country: '',
            });
            setDisableLocality(false);
        } else {
            let nodeFound = false;
            const parentLevelNodes = [];
            for (let i = 0; i < hierarchyData?.length; i += 1) {
                const curNode = hierarchyData[i].location_key.toLowerCase();
                if ((nodeFound || curNode === nodeType.toLocaleLowerCase()) && curNode in fetchLocality?.data) {
                    nodeFound = true;
                    parentLevelNodes.push({ key: hierarchyData[i].location_key, value: fetchLocality?.data[curNode] });
                }
            }
            const fetchedAddressFieldsObj = parentLevelNodes?.reduce((acc, curr) => {
                if (isKeyOfNewAddress(curr.key)) {
                    acc[curr.key] = curr.value || null;
                    if (curr.key !== nodeType && (!isAddressMappingAllowed && curr.value)) {
                        setDisableLocality(true, curr.key);
                    } else {
                        setDisableLocality(false, curr.key);
                    }
                }
                return acc;
            }, {} as { [key: string]: string | null });
            setNewAddress({
                ...newAddress,
                ...fetchedAddressFieldsObj,
            });
        }

        setLoading(false);
    };

...

Expand
titleRendering snippet for address fields
Code Block
    const renderPincodeBox = () => {
        if (isAddressHierarchyPresent && isAddressMappingAllowed && hierarchyFieldsArr.include('pincode')) {
            return (
                <AutoComplete
                    value={newAddress.pincode}
                    className={classes.pincodeInput}
                    dropdownClassName={classes.pincodeInputDropdown}
                    options={
                        localityPincodesList.map((pincode: any) => {
                            return {
                                label: `${pincode.name} (${pincode.code})`,
                                value: pincode.code,
                            };
                        })
                    }
                    onSearch={loadPincodes}
                    onSelect={(e) => saveAddressUsingAddressHierarchy(e, 'pincode')}
                    onChange={(value) => updateAddressFieldWithValidations('pincode', value)}
                    style={{ textAlign: 'left' }}
                    allowClear
                >
                    <Input
                        className={classes.autoCompleteInputBox}
                        allowClear
                        placeholder={t('address_pincode')}
                    />
                </AutoComplete>
            );
        } else
        if (isAddressHierarchyPresent && !isAddressMappingAllowed && hierarchyFieldsArr.include('pincode')) {
            return (
                <Form.Item
                    className={classes.pincodeWithExtra}
                    name="pincode"
                    extra={samplePincode ? `Ex. ${samplePincode}` : undefined}
                >
                    <Select
                        value={newAddress.pincode}
                        dropdownClassName={classes.pincodeInputDropdown}
                        placeholder={t('address_pincode')}
                        onChange={(e) => {
                            updateAddressFieldWithValidations('pincode', e);
                            const isValid = isValidPincode(e);
                            if (isValid !== validPincode) {
                                setValidPincode(isValid);
                            }
                        }}
                        options={
                            localityPincodesList.map((pincode: any) => {
                                return {
                                    label: `${pincode.name} (${pincode.code})`,
                                    value: pincode.code,
                                };
                            })
                        }
                        onSelect={(e) => saveAddressUsingAddressHierarchy(e, 'pincode')}
                        defaultActiveFirstOption={false}
                        filterOption={false}
                        onSearch={loadPincodes}
                        showSearch
                        allowClear
                        style={validPincode ? {} : { borderColor: 'red' }}
                    />
                </Form.Item>
            );
        }
        else {
   
        return (
  
             <Input
                    value={newAddress.pincode}
  
                 className={classes.pincodeInput}
 
                  placeholder={t('address_citypincode')}
   
                onChange={(e) => updateAddressFieldWithValidations('pincodeInputpincode', e.target.value)}

               />
   
        );
   
    }
    };

Additional Details:

Changes in src/network/pickup.api.ts

...