Skip to content

Commit

Permalink
On DB layer, replace Entity model usage with DB models
Browse files Browse the repository at this point in the history
  • Loading branch information
joel-jeremy committed Feb 24, 2025
1 parent 857e2f3 commit ac8fded
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 13 deletions.
4 changes: 3 additions & 1 deletion packages/loot-core/src/server/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import * as cloudStorage from './cloud-storage';
import { type RemoteFile } from './cloud-storage';
import * as db from './db';
import { APIError } from './errors';
import { categoryGroupModel as serverCategoryGroupModel } from './models';
import { runMutator } from './mutators';
import * as prefs from './prefs';
import * as sheet from './sheet';
Expand Down Expand Up @@ -354,7 +355,8 @@ handlers['api/budget-month'] = async function ({ month }) {
checkFileOpen();
await validateMonth(month);

const groups = await db.getCategoriesGrouped();
const dbGroups = await db.getCategoriesGrouped();
const groups = dbGroups.map(serverCategoryGroupModel.fromDb);
const sheetName = monthUtils.sheetForMonth(month);

function value(name) {
Expand Down
10 changes: 7 additions & 3 deletions packages/loot-core/src/server/budget/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { CategoryEntity, CategoryGroupEntity } from '../../types/models';
import { createApp } from '../app';
import * as db from '../db';
import { APIError } from '../errors';
import { categoryGroupModel, categoryModel } from '../models';
import { mutator } from '../mutators';
import * as sheet from '../sheet';
import { resolveName } from '../spreadsheet/util';
Expand Down Expand Up @@ -132,10 +133,11 @@ app.method('category-group-move', mutator(undoable(moveCategoryGroup)));
app.method('category-group-delete', mutator(undoable(deleteCategoryGroup)));
app.method('must-category-transfer', isCategoryTransferRequired);

// Server must return AQL entities not the raw DB data
async function getCategories() {
return {
grouped: await db.getCategoriesGrouped(),
list: await db.getCategories(),
grouped: await getCategoryGroups(),
list: (await db.getCategories()).map(categoryModel.fromDb),
};
}

Expand Down Expand Up @@ -346,8 +348,10 @@ async function deleteCategory({
return result;
}

// Server must return AQL entities not the raw DB data
async function getCategoryGroups() {
return await db.getCategoriesGrouped();
const categoryGroups = await db.getCategoriesGrouped();
return categoryGroups.map(categoryGroupModel.fromDb);
}

async function createCategoryGroup({
Expand Down
15 changes: 6 additions & 9 deletions packages/loot-core/src/server/db/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import * as fs from '../../platform/server/fs';
import * as sqlite from '../../platform/server/sqlite';
import * as monthUtils from '../../shared/months';
import { groupById } from '../../shared/util';
import { CategoryEntity, CategoryGroupEntity } from '../../types/models';
import {
schema,
schemaConfig,
Expand Down Expand Up @@ -310,19 +309,17 @@ export function updateWithSchema(table, fields) {
// Data-specific functions. Ideally this would be split up into
// different files

// TODO: Fix return type. This should returns a DbCategory[].
export async function getCategories(
ids?: Array<DbCategory['id']>,
): Promise<CategoryEntity[]> {
): Promise<DbCategory[]> {
const whereIn = ids ? `c.id IN (${toSqlQueryParameters(ids)}) AND` : '';
const query = `SELECT c.* FROM categories c WHERE ${whereIn} c.tombstone = 0 ORDER BY c.sort_order, c.id`;
return ids ? await all(query, [...ids]) : await all(query);
}

// TODO: Fix return type. This should returns a [DbCategoryGroup, ...DbCategory].
export async function getCategoriesGrouped(
ids?: Array<DbCategoryGroup['id']>,
): Promise<Array<CategoryGroupEntity>> {
): Promise<Array<DbCategoryGroup & { categories: DbCategory[] }>> {
const categoryGroupWhereIn = ids
? `cg.id IN (${toSqlQueryParameters(ids)}) AND`
: '';
Expand Down Expand Up @@ -353,7 +350,7 @@ export async function getCategoriesGrouped(

export async function insertCategoryGroup(
group,
): Promise<CategoryGroupEntity['id']> {
): Promise<DbCategoryGroup['id']> {
// Don't allow duplicate group
const existingGroup = await first(
`SELECT id, name, hidden FROM category_groups WHERE UPPER(name) = ? and tombstone = 0 LIMIT 1`,
Expand All @@ -374,7 +371,7 @@ export async function insertCategoryGroup(
...categoryGroupModel.validate(group),
sort_order,
};
const id: CategoryGroupEntity['id'] = await insertWithUUID(
const id: DbCategoryGroup['id'] = await insertWithUUID(
'category_groups',
group,
);
Expand Down Expand Up @@ -411,10 +408,10 @@ export async function deleteCategoryGroup(group, transferId?: string) {
export async function insertCategory(
category,
{ atEnd } = { atEnd: undefined },
): Promise<CategoryEntity['id']> {
): Promise<DbCategory['id']> {
let sort_order;

let id_: CategoryEntity['id'];
let id_: DbCategory['id'];
await batchMessages(async () => {
// Dont allow duplicated names in groups
const existingCatInGroup = await first(
Expand Down
57 changes: 57 additions & 0 deletions packages/loot-core/src/server/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ import {
PayeeEntity,
} from '../types/models';

import {
convertForInsert,
convertForUpdate,
convertFromSelect,
schema,
schemaConfig,
} from './aql';
import { DbCategory, DbCategoryGroup } from './db';
import { ValidationError } from './errors';

export function requiredFields<T extends object, K extends keyof T>(
Expand Down Expand Up @@ -74,6 +82,22 @@ export const categoryModel = {
const { sort_order, ...rest } = category;
return { ...rest, hidden: rest.hidden ? 1 : 0 };
},
toDb(
category: CategoryEntity,
{ update }: { update?: boolean } = {},
): DbCategory {
return update

Check failure on line 89 in packages/loot-core/src/server/models.ts

View workflow job for this annotation

GitHub Actions / typecheck

Type '{ [k: string]: any; }' is missing the following properties from type 'DbCategory': id, name, is_income, cat_group, and 3 more.
? convertForUpdate(schema, schemaConfig, 'categories', category)
: convertForInsert(schema, schemaConfig, 'categories', category);
},
fromDb(category: DbCategory): CategoryEntity {
return convertFromSelect(
schema,
schemaConfig,
'categories',
category,
) as CategoryEntity;
},
};

export const categoryGroupModel = {
Expand All @@ -91,6 +115,39 @@ export const categoryGroupModel = {
const { sort_order, ...rest } = categoryGroup;
return { ...rest, hidden: rest.hidden ? 1 : 0 };
},
toDb(
categoryGroup: CategoryGroupEntity,
{ update }: { update?: boolean } = {},
): DbCategoryGroup {
return update

Check failure on line 122 in packages/loot-core/src/server/models.ts

View workflow job for this annotation

GitHub Actions / typecheck

Type '{ [k: string]: any; }' is missing the following properties from type 'DbCategoryGroup': id, name, is_income, sort_order, and 2 more.
? convertForUpdate(schema, schemaConfig, 'category_groups', categoryGroup)
: convertForInsert(
schema,
schemaConfig,
'category_groups',
categoryGroup,
);
},
fromDb(
categoryGroup: DbCategoryGroup & {
categories: DbCategory[];
},
): CategoryGroupEntity {
const { categories, ...rest } = categoryGroup;
const categoryGroupEntity = convertFromSelect(
schema,
schemaConfig,
'category_groups',
rest,
) as CategoryGroupEntity;

return {
...categoryGroupEntity,
categories: categories
.filter(category => category.cat_group === categoryGroup.id)
.map(categoryModel.fromDb),
};
},
};

export const payeeModel = {
Expand Down

0 comments on commit ac8fded

Please sign in to comment.