Files
ezbookkeeping/src/models/transaction_category.ts
T

234 lines
7.3 KiB
TypeScript

import { entries } from '@/core/base.ts';
import type { ColorValue } from '@/core/color.ts';
import { CategoryType } from '@/core/category.ts';
import { DEFAULT_CATEGORY_ICON_ID } from '@/consts/icon.ts';
import { DEFAULT_CATEGORY_COLOR } from '@/consts/color.ts';
export class TransactionCategory implements TransactionCategoryInfoResponse {
public id: string;
public name: string;
public parentId: string;
public type: CategoryType;
public icon: string;
public color: ColorValue;
public comment: string;
public displayOrder: number;
public visible: boolean;
public subCategories?: TransactionCategory[];
private constructor(id: string, name: string, parentId: string, type: CategoryType, icon: string, color: ColorValue, comment: string, displayOrder: number, visible: boolean, subCategories?: TransactionCategory[]) {
this.id = id;
this.name = name;
this.parentId = parentId;
this.type = type;
this.icon = icon;
this.color = color;
this.comment = comment;
this.displayOrder = displayOrder;
this.visible = visible;
if (subCategories) {
this.subCategories = subCategories;
} else if (!subCategories && (!parentId || parentId === '0')) {
this.subCategories = [];
}
}
public get hidden(): boolean {
return !this.visible;
}
public equals(other: TransactionCategory): boolean {
const isEqual = this.id === other.id &&
this.name === other.name &&
this.parentId === other.parentId &&
this.type === other.type &&
this.icon === other.icon &&
this.color === other.color &&
this.comment === other.comment &&
this.displayOrder === other.displayOrder &&
this.visible === other.visible;
if (!isEqual) {
return false;
}
if (this.subCategories && other.subCategories) {
if (this.subCategories.length !== other.subCategories.length) {
return false;
}
for (let i = 0; i < this.subCategories.length; i++) {
if (!(this.subCategories[i] as TransactionCategory).equals(other.subCategories[i] as TransactionCategory)) {
return false;
}
}
} else if ((this.subCategories && this.subCategories.length) || (other.subCategories && other.subCategories.length)) {
return false;
}
return true;
}
public fillFrom(other: TransactionCategory): void {
this.id = other.id;
this.name = other.name;
this.parentId = other.parentId;
this.type = other.type;
this.icon = other.icon;
this.color = other.color;
this.comment = other.comment;
this.visible = other.visible;
}
public clone(): TransactionCategory {
return new TransactionCategory(
this.id,
this.name,
this.parentId,
this.type,
this.icon,
this.color,
this.comment,
this.displayOrder,
this.visible
);
}
public toCreateRequest(clientSessionId: string): TransactionCategoryCreateRequest {
return {
name: this.name,
type: this.type,
parentId: this.parentId,
icon: this.icon,
color: this.color,
comment: this.comment,
clientSessionId: clientSessionId
};
}
public toModifyRequest(): TransactionCategoryModifyRequest {
return {
id: this.id,
name: this.name,
parentId: this.parentId,
icon: this.icon,
color: this.color,
comment: this.comment,
hidden: !this.visible
};
}
public static of(categoryResponse: TransactionCategoryInfoResponse): TransactionCategory {
return new TransactionCategory(
categoryResponse.id,
categoryResponse.name,
categoryResponse.parentId,
categoryResponse.type,
categoryResponse.icon,
categoryResponse.color,
categoryResponse.comment,
categoryResponse.displayOrder,
!categoryResponse.hidden,
categoryResponse.subCategories ? TransactionCategory.ofMulti(categoryResponse.subCategories) : undefined
);
}
public static ofMulti(categoryResponses: TransactionCategoryInfoResponse[]): TransactionCategory[] {
const categories: TransactionCategory[] = [];
for (const categoryResponse of categoryResponses) {
categories.push(TransactionCategory.of(categoryResponse));
}
return categories;
}
public static ofMap(categoriesByType: Record<number, TransactionCategoryInfoResponse[]>): Record<number, TransactionCategory[]> {
const ret: Record<number, TransactionCategory[]> = {};
for (const [categoryType, categories] of entries(categoriesByType)) {
ret[parseInt(categoryType)] = TransactionCategory.ofMulti(categories);
}
return ret;
}
public static findNameById(categories: TransactionCategory[], id: string): string | null {
for (const category of categories) {
if (category.id === id) {
return category.name;
}
}
return null;
}
public static createNewCategory(type?: CategoryType, parentId?: string): TransactionCategory {
return new TransactionCategory('', '', parentId || '0', type || CategoryType.Income, DEFAULT_CATEGORY_ICON_ID, DEFAULT_CATEGORY_COLOR, '', 0, true);
}
}
export interface TransactionCategoryCreateRequest {
readonly name: string;
readonly type: number;
readonly parentId: string;
readonly icon: string;
readonly color: string;
readonly comment: string;
readonly clientSessionId: string;
}
export interface TransactionCategoryCreateBatchRequest {
readonly categories: TransactionCategoryCreateWithSubCategories[];
}
export interface TransactionCategoryCreateWithSubCategories {
readonly name: string;
readonly type: CategoryType;
readonly icon: string;
readonly color: ColorValue;
readonly subCategories: TransactionCategoryCreateRequest[];
}
export interface TransactionCategoryModifyRequest {
readonly id: string;
readonly name: string;
readonly parentId: string;
readonly icon: string;
readonly color: string;
readonly comment: string;
readonly hidden: boolean;
}
export interface TransactionCategoryHideRequest {
readonly id: string;
readonly hidden: boolean;
}
export interface TransactionCategoryMoveRequest {
readonly newDisplayOrders: TransactionCategoryNewDisplayOrderRequest[];
}
export interface TransactionCategoryNewDisplayOrderRequest {
readonly id: string;
readonly displayOrder: number;
}
export interface TransactionCategoryDeleteRequest {
readonly id: string;
}
export interface TransactionCategoryInfoResponse {
readonly id: string;
readonly name: string;
readonly parentId: string;
readonly type: number;
readonly icon: string;
readonly color: string;
readonly comment: string;
readonly displayOrder: number;
readonly hidden: boolean;
readonly subCategories?: TransactionCategoryInfoResponse[];
}