async function createOrUpdateAccount()

in api/v1/src/accounts/dataManager.js [286:380]


async function createOrUpdateAccount(projectId, accountId, data) {
    console.log(`createOrUpdateAccount called with accountId: ${accountId} and data: ${JSON.stringify(data)}`);
    let _accountId = accountId;

    // If provided policies is not a string array, re-format it to string array
    // TODO: Clean up format before passing from UI to eliminate this conversion
    // From here policies are handled as an array until they're formatted for saving in BQ
    let policies = data.policies || [];
    if (policies && typeof policies[0] !== 'string') {
        data.policies = policies.map(p => { return p.policyId });
    }

    let impactedPolicies = data.policies ? Array.from(data.policies) : [];
    const currentAccount = await getAccount(projectId, accountId, data.email, data.emailType);
    console.log(`currentAccount response: ${JSON.stringify(currentAccount)}`);
    if (currentAccount) {
        // Update logic
        if (data.rowId && currentAccount.rowId !== data.rowId) {
            // If user is updating an existing record, compare the rowId to ensure they're making updates from the latest record.
            return { success: false, code: 500, errors: ["STALE"] };
        }
        else if (accountId) {
            // Only merge the existing policies if user is updating an existing row.
            // If user is re-instating a deleted record, ignore the old policies.
            impactedPolicies = underscore.union(impactedPolicies, currentAccount.policies.map(p => p.policyId));
        }
        // In case getAccount was found based on email and emailType from a previously deleted record.
        _accountId = currentAccount.accountId;
    }
    else {
        _accountId = uuidv4();
    }

    console.log(`Impacted policies is: ${JSON.stringify(impactedPolicies, null, 3)}`);

    const rowId = uuidv4();
    const isDeleted = false;
    const createdAt = new Date().toISOString();

    let fields = [...cfg.cdsAccountTableFields], values = [...cfg.cdsAccountTableFields];

    // reformat policies object for saving
    if (policies.length === 0) {
        // If there are no supplied policies, remove policies column field and value from insert statement.
        delete data.policies;
        const index = fields.indexOf('policies');
        if (index > -1) {
            fields.splice(index, 1);
            values.splice(index, 1);
        }
    } else {
        // String array is passed in reformat for storing as dictionaries
        // Reformat for storing into BQ
        data.policies = data.policies.map(p => { return { policyId: p }; });
    }

    let marketplace = data.marketplace || [];
    if (marketplace.length === 0) {
        // If there are no supplied marketplace, remove marketplace column field and value from insert statement.
        delete data.marketplace;
        const index = fields.indexOf('marketplace');
        if (index > -1) {
            fields.splice(index, 1);
            values.splice(index, 1);
        }
    }

    fields = Array.from(fields).join();
    values = Array.from(values).map(i => '@' + i).join();

    // merge the data and extra values together
    data = {
        ...data,
        ...{
            rowId: rowId,
            accountId: _accountId,
            isDeleted: isDeleted,
            createdAt: createdAt,
            accountType: 'consumer'
        }
    };
    console.log(JSON.stringify(data));
    const [rows] = await _insertData(projectId, fields, values, data);
    if (rows.length === 0) {
        try {
            await metaManager.performPolicyUpdates(projectId, impactedPolicies, false);
        } catch (err) {
            return { success: false, code: 500, errors: [err.message] };
        }
        return { success: true, data: data };
    } else {
        const message = `Account did not create with data values: '${data}'`;
        return { success: false, code: 500, errors: [message] };
    }
}