mirror of
https://github.com/netlight/my-finance-pal-backend.git
synced 2024-11-10 00:51:56 +01:00
Add MongoDb connection and refactor to consistent package structure
This commit is contained in:
parent
aaa607a40c
commit
879862dfad
33 changed files with 409 additions and 116 deletions
186
api/my-finance-pal.yml
Normal file
186
api/my-finance-pal.yml
Normal file
|
@ -0,0 +1,186 @@
|
|||
openapi: 3.0.1
|
||||
info:
|
||||
version: 1.0.0
|
||||
title: My Finance Pal
|
||||
description: API of the personal finance budgeting app My Finance Pal
|
||||
|
||||
paths:
|
||||
/budgets:
|
||||
post:
|
||||
description: Create a new budget
|
||||
operationId: createBudget
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/NewBudget"
|
||||
responses:
|
||||
201:
|
||||
description: Budget created
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Budget"
|
||||
400:
|
||||
description: Invalid budget
|
||||
get:
|
||||
description: Get all budgets
|
||||
operationId: getBudgets
|
||||
responses:
|
||||
200:
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/Budget"
|
||||
/budgets/{budgetId}:
|
||||
get:
|
||||
description: Get a budget for a given ID
|
||||
operationId: getBudget
|
||||
parameters:
|
||||
- in: path
|
||||
name: budgetId
|
||||
required: true
|
||||
description: The UUID of the budget
|
||||
schema:
|
||||
$ref: "#/components/schemas/BudgetId"
|
||||
responses:
|
||||
200:
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Budget"
|
||||
404:
|
||||
description: Budget not found
|
||||
delete:
|
||||
description: Delete a budget including all transactions
|
||||
operationId: deleteBudget
|
||||
parameters:
|
||||
- in: path
|
||||
name: budgetId
|
||||
required: true
|
||||
description: The UUID of the budget
|
||||
schema:
|
||||
$ref: "#/components/schemas/BudgetId"
|
||||
responses:
|
||||
204:
|
||||
description: Budget successfully deleted
|
||||
404:
|
||||
description: Budget not found
|
||||
|
||||
components:
|
||||
schemas:
|
||||
BudgetId:
|
||||
type: string
|
||||
format: uuid
|
||||
description: Unique identifier of one budget
|
||||
example: 850963b9-a04d-4698-b767-c0a0096b37c5
|
||||
Budget:
|
||||
type: object
|
||||
description: Planned money to be available for tracking expenses related to a certain purpose over a period of time
|
||||
required:
|
||||
- id
|
||||
- name
|
||||
- amount
|
||||
- transactions
|
||||
properties:
|
||||
id:
|
||||
$ref: "#/components/schemas/BudgetId"
|
||||
name:
|
||||
type: string
|
||||
description: The name of the budget
|
||||
example: Takeout
|
||||
amount:
|
||||
type: number
|
||||
minimum: 0
|
||||
description: The total amount available for the budget
|
||||
example: 250
|
||||
startDate:
|
||||
type: string
|
||||
format: date
|
||||
description: Date marking the start of the budget period
|
||||
example: 2023-04-01
|
||||
endDate:
|
||||
type: string
|
||||
format: date
|
||||
description: Date marking the end of the budget period
|
||||
example: 2023-04-30
|
||||
transactions:
|
||||
type: array
|
||||
description: All transactions of the budget
|
||||
items:
|
||||
$ref: "#/components/schemas/Transaction"
|
||||
NewBudget:
|
||||
type: object
|
||||
description: Budget to be created
|
||||
required:
|
||||
- name
|
||||
- amount
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
description: The name of the budget
|
||||
example: Takeout
|
||||
amount:
|
||||
type: number
|
||||
minimum: 0
|
||||
description: The total amount available for the budget
|
||||
example: 250
|
||||
startDate:
|
||||
type: string
|
||||
format: date
|
||||
description: Date marking the start of the budget period
|
||||
example: 2023-04-01
|
||||
endDate:
|
||||
type: string
|
||||
format: date
|
||||
description: Date marking the end of the budget period
|
||||
example: 2023-04-30
|
||||
Transaction:
|
||||
type: object
|
||||
description: An expense or income related to a single budget
|
||||
required:
|
||||
- id
|
||||
- description
|
||||
- amount
|
||||
- date
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
format: uuid
|
||||
description: Unique identifier of a transaction
|
||||
example: cfd3b0b7-bf5e-43d4-8341-940d5e07487d
|
||||
description:
|
||||
type: string
|
||||
description: Description of the transaction
|
||||
example: Healthy breakfast at Five Guys
|
||||
amount:
|
||||
type: number
|
||||
description: Amount of money contained in the transaction
|
||||
example: 23.94
|
||||
date:
|
||||
type: string
|
||||
format: date
|
||||
NewTransaction:
|
||||
type: object
|
||||
description: A new transaction to be created
|
||||
required:
|
||||
- description
|
||||
- amount
|
||||
- date
|
||||
properties:
|
||||
description:
|
||||
type: string
|
||||
description: Description of the transaction
|
||||
example: Healthy breakfast at Five Guys
|
||||
amount:
|
||||
type: number
|
||||
description: Amount of money contained in the transaction
|
||||
example: 23.94
|
||||
date:
|
||||
type: string
|
||||
format: date
|
|
@ -1,11 +1,10 @@
|
|||
version: "3.8"
|
||||
|
||||
services:
|
||||
mongo:
|
||||
restart: always
|
||||
image: mongo:6.0.4
|
||||
expose:
|
||||
- 27017
|
||||
ports:
|
||||
- "27017:27017"
|
||||
volumes:
|
||||
- mongo_volume:/data/db
|
||||
|
3
env/development.env
vendored
3
env/development.env
vendored
|
@ -1,3 +1,4 @@
|
|||
## Server ##
|
||||
PORT=3000
|
||||
NODE_ENV=development
|
||||
NODE_ENV=development
|
||||
DATABASE_CONNECTION_STRING=mongodb://localhost:27017
|
|
@ -24,20 +24,22 @@
|
|||
"envalid": "^7.3.1",
|
||||
"express": "^4.18.2",
|
||||
"express-async-errors": "^3.1.1",
|
||||
"express-async-handler": "^1.2.0",
|
||||
"express-winston": "^4.2.0",
|
||||
"helmet": "^6.0.1",
|
||||
"http-status-codes": "^2.2.0",
|
||||
"mongoose": "^7.0.2",
|
||||
"openapi-typescript": "^6.2.0",
|
||||
"ts-command-line-args": "^2.4.2",
|
||||
"uuid": "^9.0.0",
|
||||
"winston": "^3.8.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/uuid": "^9.0.1",
|
||||
"@types/eslint": "^8.21.1",
|
||||
"@types/express": "^4.17.17",
|
||||
"@types/morgan": "^1.9.4",
|
||||
"@types/node": "^18.15.0",
|
||||
"@types/uuid": "^9.0.1",
|
||||
"@typescript-eslint/eslint-plugin": "^5.54.1",
|
||||
"eslint": "^8.36.0",
|
||||
"eslint-config-prettier": "^8.7.0",
|
||||
|
|
14
src/app.ts
14
src/app.ts
|
@ -1,11 +1,11 @@
|
|||
import express from "express";
|
||||
import helmet from "helmet";
|
||||
import environment from "./config/environment.js";
|
||||
import expressLogger from "./logging/express-logger.js";
|
||||
import ApiRouter from "./routes/ApiRouter.js";
|
||||
import BudgetUseCases from "./usecase/budget/BudgetUseCases.js";
|
||||
import BudgetMongoRepository from "./repository/budget/BudgetMongoRepository.js";
|
||||
import { errorHandler } from "./middleware/error-handler.js";
|
||||
import expressLogger from "./logging/expressLogger.js";
|
||||
import ApiRouter from "./routes/apiRouter.js";
|
||||
import BudgetService from "./usecase/budget/budgetService.js";
|
||||
import BudgetMongoRepository from "./repository/budget/budgetMongoRepository.js";
|
||||
import { errorHandler } from "./middleware/errorHandler.js";
|
||||
|
||||
const app = express();
|
||||
const API_ROOT = "/api";
|
||||
|
@ -18,11 +18,9 @@ if (environment.isProd) {
|
|||
app.use(helmet());
|
||||
}
|
||||
|
||||
const budgetRepository = new BudgetMongoRepository();
|
||||
const budgetUseCases = new BudgetUseCases(budgetRepository);
|
||||
const budgetUseCases = BudgetService(BudgetMongoRepository());
|
||||
app.use(API_ROOT, ApiRouter(budgetUseCases));
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
app.use(errorHandler);
|
||||
|
||||
export default app;
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import { cleanEnv, port, str } from "envalid";
|
||||
import { cleanEnv, port, str, url } from "envalid";
|
||||
import * as process from "process";
|
||||
|
||||
const env = cleanEnv(process.env, {
|
||||
PORT: port(),
|
||||
LOG_LEVEL: str({ default: "info" }),
|
||||
DATABASE_CONNECTION_STRING: url(),
|
||||
});
|
||||
|
||||
export default env;
|
||||
|
|
8
src/config/mongoDb.ts
Normal file
8
src/config/mongoDb.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
import mongoose from "mongoose";
|
||||
import environment from "./environment.js";
|
||||
|
||||
const connect = async (): Promise<void> => {
|
||||
await mongoose.connect(environment.DATABASE_CONNECTION_STRING);
|
||||
};
|
||||
|
||||
export default { connect };
|
|
@ -1,11 +1,11 @@
|
|||
import { v4 as uuidv4 } from "uuid";
|
||||
import { type Transaction } from "./Transaction.js";
|
||||
import { type Transaction } from "./transaction.js";
|
||||
|
||||
export class BudgetId {
|
||||
uuid: string;
|
||||
|
||||
constructor() {
|
||||
this.uuid = uuidv4();
|
||||
constructor(uuid?: string) {
|
||||
this.uuid = uuid ?? uuidv4();
|
||||
}
|
||||
}
|
||||
|
|
@ -3,8 +3,8 @@ import { v4 as uuidv4 } from "uuid";
|
|||
export class TransactionId {
|
||||
uuid: string;
|
||||
|
||||
constructor() {
|
||||
this.uuid = uuidv4();
|
||||
constructor(uuid?: string) {
|
||||
this.uuid = uuid ?? uuidv4();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
import type BudgetRepository from "./BudgetRepository.js";
|
||||
import insertBudget from "./lib/insert-budget.js";
|
||||
|
||||
class BudgetMongoRepository implements BudgetRepository {
|
||||
insertBudget: BudgetRepository["insertBudget"];
|
||||
|
||||
constructor() {
|
||||
this.insertBudget = insertBudget();
|
||||
}
|
||||
}
|
||||
|
||||
export default BudgetMongoRepository;
|
18
src/repository/budget/budgetMongoRepository.ts
Normal file
18
src/repository/budget/budgetMongoRepository.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
import type BudgetRepository from "./budgetRepository.js";
|
||||
import { BudgetConverter } from "./entity/converters.js";
|
||||
import { BudgetModel } from "./models.js";
|
||||
|
||||
export const insertBudget: BudgetRepository["insertBudget"] = async (
|
||||
budget
|
||||
) => {
|
||||
const entity = BudgetConverter.toEntity(budget);
|
||||
const model = new BudgetModel(entity);
|
||||
const saved = await model.save();
|
||||
return BudgetConverter.toDomain(saved);
|
||||
};
|
||||
|
||||
const BudgetMongoRepository: () => BudgetRepository = () => ({
|
||||
insertBudget,
|
||||
});
|
||||
|
||||
export default BudgetMongoRepository;
|
|
@ -1,4 +1,4 @@
|
|||
import { type Budget } from "../../models/Budget.js";
|
||||
import { type Budget } from "../../domain/budget.js";
|
||||
|
||||
interface BudgetRepository {
|
||||
insertBudget: (budget: Budget) => Promise<Budget>;
|
12
src/repository/budget/entity/budgetEntity.ts
Normal file
12
src/repository/budget/entity/budgetEntity.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
import type TransactionEntity from "./transactionEntity.js";
|
||||
|
||||
interface BudgetEntity {
|
||||
id: string;
|
||||
name: string;
|
||||
amount: number;
|
||||
startDate?: Date;
|
||||
endDate?: Date;
|
||||
transactions: TransactionEntity[];
|
||||
}
|
||||
|
||||
export default BudgetEntity;
|
41
src/repository/budget/entity/converters.ts
Normal file
41
src/repository/budget/entity/converters.ts
Normal file
|
@ -0,0 +1,41 @@
|
|||
import {
|
||||
type Transaction,
|
||||
TransactionId,
|
||||
} from "../../../domain/transaction.js";
|
||||
import type TransactionEntity from "./transactionEntity.js";
|
||||
import { type Budget, BudgetId } from "../../../domain/budget.js";
|
||||
import type BudgetEntity from "./budgetEntity.js";
|
||||
|
||||
export const TransactionConverter = {
|
||||
toEntity: (domain: Transaction): TransactionEntity => ({
|
||||
id: domain.id.uuid,
|
||||
description: domain.description,
|
||||
amount: domain.amount,
|
||||
date: domain.date,
|
||||
}),
|
||||
toDomain: (entity: TransactionEntity): Transaction => ({
|
||||
id: new TransactionId(entity.id),
|
||||
description: entity.description,
|
||||
amount: entity.amount,
|
||||
date: entity.date,
|
||||
}),
|
||||
};
|
||||
|
||||
export const BudgetConverter = {
|
||||
toEntity: (domain: Budget): BudgetEntity => ({
|
||||
id: domain.id.uuid,
|
||||
name: domain.name,
|
||||
amount: domain.amount,
|
||||
startDate: domain.startDate,
|
||||
endDate: domain.endDate,
|
||||
transactions: domain.transactions.map(TransactionConverter.toEntity),
|
||||
}),
|
||||
toDomain: (entity: BudgetEntity): Budget => ({
|
||||
id: new BudgetId(entity.id),
|
||||
name: entity.name,
|
||||
amount: entity.amount,
|
||||
startDate: entity.startDate,
|
||||
endDate: entity.endDate,
|
||||
transactions: entity.transactions.map(TransactionConverter.toDomain),
|
||||
}),
|
||||
};
|
8
src/repository/budget/entity/transactionEntity.ts
Normal file
8
src/repository/budget/entity/transactionEntity.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
interface TransactionEntity {
|
||||
id: string;
|
||||
description: string;
|
||||
amount: number;
|
||||
date: Date;
|
||||
}
|
||||
|
||||
export default TransactionEntity;
|
|
@ -1,9 +0,0 @@
|
|||
import { type Budget } from "../../../models/Budget.js";
|
||||
|
||||
const insertBudget =
|
||||
() =>
|
||||
async (budget: Budget): Promise<Budget> => {
|
||||
return budget;
|
||||
};
|
||||
|
||||
export default insertBudget;
|
11
src/repository/budget/models.ts
Normal file
11
src/repository/budget/models.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
import mongoose from "mongoose";
|
||||
import budgetSchema from "./schema/budgetSchema.js";
|
||||
import transactionSchema from "./schema/transactionSchema.js";
|
||||
import type BudgetEntity from "./entity/budgetEntity.js";
|
||||
import type TransactionEntity from "./entity/transactionEntity.js";
|
||||
|
||||
export const BudgetModel = mongoose.model<BudgetEntity>("Budget", budgetSchema);
|
||||
export const TransactionModel = mongoose.model<TransactionEntity>(
|
||||
"Transaction",
|
||||
transactionSchema
|
||||
);
|
16
src/repository/budget/schema/budgetSchema.ts
Normal file
16
src/repository/budget/schema/budgetSchema.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
import mongoose, { Schema } from "mongoose";
|
||||
import transactionSchema from "./transactionSchema.js";
|
||||
import type BudgetEntity from "../entity/budgetEntity.js";
|
||||
|
||||
const Types = Schema.Types;
|
||||
|
||||
const budgetSchema = new mongoose.Schema<BudgetEntity>({
|
||||
id: Types.UUID,
|
||||
name: Types.String,
|
||||
amount: Types.Number,
|
||||
startDate: Types.Date,
|
||||
endDate: Types.Date,
|
||||
transactions: [transactionSchema],
|
||||
});
|
||||
|
||||
export default budgetSchema;
|
13
src/repository/budget/schema/transactionSchema.ts
Normal file
13
src/repository/budget/schema/transactionSchema.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
import mongoose, { Schema } from "mongoose";
|
||||
import type TransactionEntity from "../entity/transactionEntity.js";
|
||||
|
||||
const Types = Schema.Types;
|
||||
|
||||
const transactionSchema = new mongoose.Schema<TransactionEntity>({
|
||||
id: Types.UUID,
|
||||
description: Types.String,
|
||||
amount: Types.Number,
|
||||
date: Types.Date,
|
||||
});
|
||||
|
||||
export default transactionSchema;
|
|
@ -1,6 +1,6 @@
|
|||
import { Router } from "express";
|
||||
import type BudgetUseCases from "../usecase/budget/BudgetUseCases.js";
|
||||
import BudgetRouter from "./budget/BudgetRouter.js";
|
||||
import BudgetRouter from "./budget/budgetRouter.js";
|
||||
import type BudgetUseCases from "../usecase/budget/budgetUseCases.js";
|
||||
|
||||
const paths = {
|
||||
BUDGETS: "/budgets",
|
|
@ -1,17 +0,0 @@
|
|||
import { Router } from "express";
|
||||
import type BudgetUseCases from "../../usecase/budget/BudgetUseCases.js";
|
||||
import createBudget from "./create-budget.js";
|
||||
|
||||
const paths = {
|
||||
CREATE_BUDGET: "/",
|
||||
};
|
||||
|
||||
const BudgetRouter = (budgetUseCases: BudgetUseCases): Router => {
|
||||
const router = Router();
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
router.post(paths.CREATE_BUDGET, createBudget(budgetUseCases));
|
||||
|
||||
return router;
|
||||
};
|
||||
|
||||
export default BudgetRouter;
|
39
src/routes/budget/budgetRouter.ts
Normal file
39
src/routes/budget/budgetRouter.ts
Normal file
|
@ -0,0 +1,39 @@
|
|||
import {
|
||||
type NextFunction,
|
||||
type Request,
|
||||
type Response,
|
||||
Router,
|
||||
} from "express";
|
||||
import type BudgetUseCases from "../../usecase/budget/budgetUseCases.js";
|
||||
import asyncHandler from "express-async-handler";
|
||||
import { BudgetConverter, NewBudgetConverter, type NewBudgetDto } from "./dto/budget.js";
|
||||
import { StatusCodes } from "http-status-codes";
|
||||
|
||||
const paths = {
|
||||
CREATE_BUDGET: "/",
|
||||
};
|
||||
|
||||
export const createBudget =
|
||||
(budgetUseCases: BudgetUseCases) =>
|
||||
async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||
try {
|
||||
const dto: NewBudgetDto = req.body;
|
||||
const newBudget = NewBudgetConverter.toDomain(dto);
|
||||
const createdBudget = await budgetUseCases.createBudget(newBudget);
|
||||
|
||||
res
|
||||
.status(StatusCodes.CREATED)
|
||||
.json(BudgetConverter.toDto(createdBudget));
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
const BudgetRouter = (budgetUseCases: BudgetUseCases): Router => {
|
||||
const router = Router();
|
||||
router.post(paths.CREATE_BUDGET, asyncHandler(createBudget(budgetUseCases)));
|
||||
|
||||
return router;
|
||||
};
|
||||
|
||||
export default BudgetRouter;
|
|
@ -1,20 +0,0 @@
|
|||
import { type NextFunction, type Request, type Response } from "express";
|
||||
import type BudgetUseCases from "../../usecase/budget/BudgetUseCases.js";
|
||||
import { NewBudgetConverter, type NewBudgetDto } from "./dto/budget.js";
|
||||
import { StatusCodes } from "http-status-codes";
|
||||
|
||||
const createBudget =
|
||||
(budgetUseCases: BudgetUseCases) =>
|
||||
async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||
try {
|
||||
const dto: NewBudgetDto = req.body;
|
||||
const newBudget = NewBudgetConverter.toDomain(dto);
|
||||
const createdBudget = await budgetUseCases.createBudget(newBudget);
|
||||
|
||||
res.status(StatusCodes.CREATED).json(createdBudget);
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
export default createBudget;
|
|
@ -1,5 +1,5 @@
|
|||
import { type components } from "../../../../generated/api.js";
|
||||
import { Budget, type NewBudget } from "../../../models/Budget.js";
|
||||
import { type Budget, type NewBudget } from "../../../domain/budget.js";
|
||||
import { toDate } from "../../../util/date.js";
|
||||
import { TransactionConverter } from "./transaction.js";
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { type components } from "../../../../generated/api.js";
|
||||
import { type Transaction } from "../../../models/Transaction.js";
|
||||
import { type Transaction } from "../../../domain/transaction.js";
|
||||
|
||||
export type TransactionDto = components["schemas"]["Transaction"];
|
||||
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
import "./pre-start.js";
|
||||
import "./preStart.js";
|
||||
import * as http from "http";
|
||||
import app from "./app.js";
|
||||
import { listenToErrorEvents } from "./middleware/error-handler.js";
|
||||
import { listenToErrorEvents } from "./middleware/errorHandler.js";
|
||||
import logger from "./logging/logger.js";
|
||||
import environment from "./config/environment.js";
|
||||
import mongoDb from "./config/mongoDb.js";
|
||||
|
||||
await mongoDb.connect();
|
||||
|
||||
const onListening = (server: http.Server) => (): void => {
|
||||
const addr = server.address();
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
import createBudget from "./lib/create-budget.js";
|
||||
import { type Budget, type NewBudget } from "../../models/Budget.js";
|
||||
import type BudgetRepository from "../../repository/budget/BudgetRepository.js";
|
||||
|
||||
class BudgetUseCases {
|
||||
createBudget: (budget: NewBudget) => Promise<Budget>;
|
||||
|
||||
constructor(budgetRepository: BudgetRepository) {
|
||||
this.createBudget = createBudget(budgetRepository);
|
||||
}
|
||||
}
|
||||
|
||||
export default BudgetUseCases;
|
20
src/usecase/budget/budgetService.ts
Normal file
20
src/usecase/budget/budgetService.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
import { type Budget, BudgetId } from "../../domain/budget.js";
|
||||
import type BudgetRepository from "../../repository/budget/budgetRepository.js";
|
||||
import type BudgetUseCases from "./budgetUseCases.js";
|
||||
|
||||
export const createBudget: (
|
||||
repo: BudgetRepository
|
||||
) => BudgetUseCases["createBudget"] = (repo) => async (newBudget) => {
|
||||
const budget: Budget = {
|
||||
id: new BudgetId(),
|
||||
transactions: [],
|
||||
...newBudget,
|
||||
};
|
||||
return await repo.insertBudget(budget);
|
||||
};
|
||||
|
||||
const BudgetService: (repo: BudgetRepository) => BudgetUseCases = (repo) => ({
|
||||
createBudget: createBudget(repo),
|
||||
});
|
||||
|
||||
export default BudgetService;
|
7
src/usecase/budget/budgetUseCases.ts
Normal file
7
src/usecase/budget/budgetUseCases.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
import { type Budget, type NewBudget } from "../../domain/budget.js";
|
||||
|
||||
interface BudgetUseCases {
|
||||
createBudget: (newBudget: NewBudget) => Promise<Budget>;
|
||||
}
|
||||
|
||||
export default BudgetUseCases;
|
|
@ -1,19 +0,0 @@
|
|||
import type BudgetRepository from "../../../repository/budget/BudgetRepository.js";
|
||||
import {
|
||||
type Budget,
|
||||
BudgetId,
|
||||
type NewBudget,
|
||||
} from "../../../models/Budget.js";
|
||||
|
||||
const createBudget =
|
||||
(repo: BudgetRepository) =>
|
||||
async (newBudget: NewBudget): Promise<Budget> => {
|
||||
const budget: Budget = {
|
||||
id: new BudgetId(),
|
||||
transactions: [],
|
||||
...newBudget,
|
||||
};
|
||||
return await repo.insertBudget(budget);
|
||||
};
|
||||
|
||||
export default createBudget;
|
Loading…
Reference in a new issue