How to transform flat array to a list of hierarchical trees based on a field with a list of enums denoting the level

I’m trying to transform a flat list of account balances to a list of hierarchical account trees based on a list of unique codes. I’m struggling with how to solve this as I can’t see what steps to take.

If you think of an excel sheet then the account balance would be a row and the codes field denotes the columns for how many levels the row has been broken down into. This effectively means that the the first codes[0] is the first level and codes[1] would be the next so on and so forth. By transforming the account balances to an account tree I want to sum the amountOut correctly for each level (codeType and code) and then add it as an account tree in the subAccounts array.

Below I’ve added all the types used as well as provided an example of the input and output.

interface AccountBalance {
    id: string
    codes: Code[]
    amountOut: number
}

type Code = {
    id: string
    codeType: CodeTypes
    code: string
    description: string
}

enum CodeTypes {
    account = "account",
    responsible = "responsible",
    project = "project",
    object = "object",
    counterPart = "counterPart",
    free = "free",
}

type AccountTree = {
    id: string
    name: string
    code: string
    amountOut: number
    subAccounts: AccountTree[]
}

Input example:

const accountBalances: AccountBalance[] = [
            {
                id: "671769fbd36fcd6c2c7f2d9b",
                codes: [
                    {
                        id: "671769fbd36fcd6c2c7f2c2d",
                        codeType: codeTypeEnum.account,
                        code: "1250",
                        description: "Column A",
                    },
                    {
                        id: "671769fbd36fcd6c2c7f2bd5",
                        codeType: codeTypeEnum.responsible,
                        code: "17",
                        description: "Column B",
                    },
                    {
                        id: "671769fbd36fcd6c2c7f2bf7",
                        codeType: codeTypeEnum.counterPart,
                        code: "20",
                        description: "Column C",
                    },
                ],
                amountOut: 24510549,
            },
            {
                id: "671769fbd36fcd6c2c7f2d9c",
                codes: [
                    {
                        id: "671769fbd36fcd6c2c7f2c2d",
                        codeType: codeTypeEnum.account,
                        code: "1250",
                        description: "Column A",
                    },
                    {
                        id: "671769fbd36fcd6c2c7f2bee",
                        codeType: codeTypeEnum.responsible,
                        code: "40",
                        description: "Column B",
                    },
                    {
                        id: "671769fbd36fcd6c2c7f2c08",
                        codeType: codeTypeEnum.counterPart,
                        code: "S3",
                        description: "Column C",
                    },
                ],
                amountOut: 0,
            },
            {
                id: "671769fbd36fcd6c2c7f2d9d",
                codes: [
                    {
                        id: "671769fbd36fcd6c2c7f2c2d",
                        codeType: codeTypeEnum.account,
                        code: "1250",
                        description: "Column A",
                    },
                    {
                        id: "671769fbd36fcd6c2c7f2bdb",
                        codeType: codeTypeEnum.responsible,
                        code: "80",
                        description: "Column B",
                    },
                    {
                        id: "671769fbd36fcd6c2c7f2bdc",
                        codeType: codeTypeEnum.counterPart,
                        code: "52",
                        description: "Column C",
                    },
                ],
                amountOut: 6381398,
            },
        ]

Output I want, example:

const expected: AccountTree = {
            id: "671769fbd36fcd6c2c7f2c2d",
            name: "Column A",
            code: "1250",
            amountOut: 30891947,
            subAccounts: [
                {
                    id: "671769fbd36fcd6c2c7f2bd5",
                    name: "Column B",
                    code: "17",
                    amountOut: 24510549,
                    subAccounts: [
                        {
                            id: "671769fbd36fcd6c2c7f2bf7",
                            name: "Column C",
                            code: "20",
                            amountOut: 24510549,
                            subAccounts: [],
                        },
                    ],
                },
                {
                    id: "671769fbd36fcd6c2c7f2bee",
                    name: "Column B",
                    code: "40",
                    amountOut: 0,
                    subAccounts: [
                        {
                            id: "671769fbd36fcd6c2c7f2c08",
                            name: "Column C",
                            code: "S3",
                            amountOut: 0,
                            subAccounts: [],
                        },
                    ],

                },
                {
                    id: "671769fbd36fcd6c2c7f2bdb",
                    name: "Column B",
                    code: "80",
                    amountOut: 6381398,
                    subAccounts: [
                        {
                            id: "671769fbd36fcd6c2c7f2bdc",
                            name: "Column C",
                            code: "52",
                            amountOut: 6381398,
                            subAccounts: [],
                        },
                    ],
                },
            ],
        }

What I’ve gotten so far is this

const uniqueCodeTypes = [
        ...new Set(
            accountBalances.reduce<CodeTypes[]>(
                (acc, balance) => [
                    ...acc,
                    ...balance.codes.flatMap((code) => code.codeType),
                ],
                [],
            ),
        ),
    ]

    const uniqueCodesForCodeType = uniqueCodeTypes.map((codeType) => {
        const uniqueCodesForCodeType = [
            ...new Map(
                accountBalances.reduce<Code[]>((acc, balance) => {
                    const code = balance.codes.find(
                        (code) => code.codeType === codeType,
                    )
                    return code ? [...acc, code] : acc
                }, []).map((code) => [code.code, code])
            ).values(),
        ]
        return uniqueCodesForCodeType
    })

But I’m unsure of how to proceed after this.

2

In plain Javascript, you could search for id at the same level and add object if not exists.

const
    codeTypeEnum = { account: "account", responsible: "responsible", project: "project", object: "object", counterPart: "counterPart", free: "free"},
    accountBalances = [{ id: "671769fbd36fcd6c2c7f2d9b", codes: [{ id: "671769fbd36fcd6c2c7f2c2d", codeType: codeTypeEnum.account, code: "1250", description: "Column A" }, { id: "671769fbd36fcd6c2c7f2bd5", codeType: codeTypeEnum.responsible, code: "17", description: "Column B" }, { id: "671769fbd36fcd6c2c7f2bf7", codeType: codeTypeEnum.counterPart, code: "20", description: "Column C" }], amountOut: 24510549 }, { id: "671769fbd36fcd6c2c7f2d9c", codes: [{ id: "671769fbd36fcd6c2c7f2c2d", codeType: codeTypeEnum.account, code: "1250", description: "Column A" }, { id: "671769fbd36fcd6c2c7f2bee", codeType: codeTypeEnum.responsible, code: "40", description: "Column B" }, { id: "671769fbd36fcd6c2c7f2c08", codeType: codeTypeEnum.counterPart, code: "S3", description: "Column C" }], amountOut: 0 }, { id: "671769fbd36fcd6c2c7f2d9d", codes: [{ id: "671769fbd36fcd6c2c7f2c2d", codeType: codeTypeEnum.account, code: "1250", description: "Column A" }, { id: "671769fbd36fcd6c2c7f2bdb", codeType: codeTypeEnum.responsible, code: "80", description: "Column B" }, { id: "671769fbd36fcd6c2c7f2bdc", codeType: codeTypeEnum.counterPart, code: "52", description: "Column C" }], amountOut: 6381398 }],
    result = accountBalances.reduce((r, { amountOut, codes }) => {
        codes.reduce((level, o) => {
            let target = level.find(({ id, codeType }) => id === o.id && codeType === o.codeType);
            if (!target) {
                target = { ...o, amountOut: 0, subAccounts: [] };
                level.push(target);
            }
            target.amountOut += amountOut;
            return target.subAccounts;
        }, r);

        return r;
    }, []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

3

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật