app/api/routers/income_statement.py CHANGED
@@ -7,6 +7,9 @@ from app.schema.index import IncomeStatementCreateRequest, IncomeStatementRespon
7
  from app.engine.postgresdb import get_db_session
8
  from app.service.income_statement import call_llm_to_create_income_statement
9
 
 
 
 
10
  income_statement_router = r = APIRouter(prefix="/api/v1/income_statement", tags=["income_statement"])
11
 
12
 
@@ -48,6 +51,30 @@ async def get_income_statements(
48
  return result
49
 
50
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  @r.get(
52
  "/report/{report_id}",
53
  response_model=IncomeStatementResponse,
 
7
  from app.engine.postgresdb import get_db_session
8
  from app.service.income_statement import call_llm_to_create_income_statement
9
 
10
+ from app.service.query_rag import answer_query, fetch_income_statement_documents
11
+
12
+
13
  income_statement_router = r = APIRouter(prefix="/api/v1/income_statement", tags=["income_statement"])
14
 
15
 
 
51
  return result
52
 
53
 
54
+ @r.get(
55
+ "/answer/{user_id}/{query}",
56
+ responses={
57
+ 200: {"description": "Query answered"},
58
+ 500: {"description": "Internal server error"},
59
+ },
60
+ )
61
+ async def answer_transactions_query(user_id: int, query: str, db: AsyncSession = Depends(get_db_session)):
62
+ """
63
+ Answer queries based on income statements
64
+ """
65
+ try:
66
+ result = await IncomeStatementModel.get_by_user(db, user_id)
67
+ if len(result) == 0:
68
+ raise HTTPException(status_code=500, detail="No transactions found for this user")
69
+ document_splits = await fetch_income_statement_documents(result)
70
+ answer = await answer_query(document_splits, query, user_id)
71
+ return answer
72
+
73
+ except Exception as e:
74
+ raise HTTPException(status_code=500, detail=f"/answer endpoint error: {str(e)}")
75
+
76
+
77
+
78
  @r.get(
79
  "/report/{report_id}",
80
  response_model=IncomeStatementResponse,
app/api/routers/transaction.py CHANGED
@@ -6,6 +6,10 @@ from app.model.transaction import Transaction as TransactionModel
6
  from app.schema.index import TransactionResponse
7
  from app.engine.postgresdb import get_db_session
8
 
 
 
 
 
9
  transaction_router = r = APIRouter(prefix="/api/v1/transactions", tags=["transactions"])
10
 
11
 
@@ -46,3 +50,27 @@ async def get_transactions(user_id: int, db: AsyncSession = Depends(get_db_sessi
46
  }
47
  results.append(result)
48
  return results
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  from app.schema.index import TransactionResponse
7
  from app.engine.postgresdb import get_db_session
8
 
9
+ from app.service.query_rag import answer_query, fetch_transaction_documents
10
+
11
+ import pandas as pd
12
+
13
  transaction_router = r = APIRouter(prefix="/api/v1/transactions", tags=["transactions"])
14
 
15
 
 
50
  }
51
  results.append(result)
52
  return results
53
+
54
+
55
+ @r.get(
56
+ "/answer/{user_id}/{query}",
57
+ responses={
58
+ 200: {"description": "Query answered"},
59
+ 500: {"description": "Internal server error"},
60
+ },
61
+ )
62
+ async def answer_transactions_query(user_id: int, query: str, db: AsyncSession = Depends(get_db_session)):
63
+ """
64
+ Answer queries based on transactions.
65
+ """
66
+ try:
67
+ result = await TransactionModel.get_by_user(db, user_id)
68
+ all_rows = result.all()
69
+ if len(all_rows) == 0:
70
+ raise HTTPException(status_code=500, detail="No transactions found for this user")
71
+ document_splits = await fetch_transaction_documents(all_rows)
72
+ answer = await answer_query(document_splits, query, user_id)
73
+ return answer
74
+
75
+ except Exception as e:
76
+ raise HTTPException(status_code=500, detail=f"/answer endpoint error: {str(e)}")
app/api/routers/user.py CHANGED
@@ -6,6 +6,10 @@ from app.engine.postgresdb import get_db_session
6
  from app.schema.index import UserCreate, User as UserSchema, UserResponse, UserUpdate
7
  from app.model.user import User as UserModel
8
 
 
 
 
 
9
 
10
  user_router = r = APIRouter(prefix="/api/v1/users", tags=["users"])
11
  logger = logging.getLogger(__name__)
@@ -24,12 +28,21 @@ logger = logging.getLogger(__name__)
24
  async def create_user(user: UserCreate, db: AsyncSession = Depends(get_db_session)):
25
  try:
26
  db_user = await UserModel.get(db, email=user.email)
 
27
  if db_user and not db_user.is_deleted:
28
  raise HTTPException(status_code=409, detail="User already exists")
29
 
30
  await UserModel.create(db, **user.model_dump())
31
  user = await UserModel.get(db, email=user.email)
 
 
 
 
 
 
 
32
  return user
 
33
  except Exception as e:
34
  raise HTTPException(status_code=500, detail=str(e))
35
 
 
6
  from app.schema.index import UserCreate, User as UserSchema, UserResponse, UserUpdate
7
  from app.model.user import User as UserModel
8
 
9
+ from app.model.transaction import Transaction as TransactionModel
10
+
11
+ from tests.utils import get_fake_transactions
12
+
13
 
14
  user_router = r = APIRouter(prefix="/api/v1/users", tags=["users"])
15
  logger = logging.getLogger(__name__)
 
28
  async def create_user(user: UserCreate, db: AsyncSession = Depends(get_db_session)):
29
  try:
30
  db_user = await UserModel.get(db, email=user.email)
31
+ print(f"db_user: {db_user}")
32
  if db_user and not db_user.is_deleted:
33
  raise HTTPException(status_code=409, detail="User already exists")
34
 
35
  await UserModel.create(db, **user.model_dump())
36
  user = await UserModel.get(db, email=user.email)
37
+ print(f"user: {user}")
38
+
39
+ # Supply fake transactions data when creating user to have data to query
40
+ fake_transactions = get_fake_transactions(user.id)
41
+ await TransactionModel.bulk_create(db, fake_transactions)
42
+ print(f"fake_transactions: {fake_transactions}")
43
+
44
  return user
45
+
46
  except Exception as e:
47
  raise HTTPException(status_code=500, detail=str(e))
48
 
app/model/transaction.py CHANGED
@@ -23,6 +23,15 @@ class Transaction(Base, BaseModel):
23
 
24
  def __str__(self) -> str:
25
  return f"{self.transaction_date}, {self.category}, {self.name_description}, {self.amount}, {self.type}"
 
 
 
 
 
 
 
 
 
26
 
27
  @classmethod
28
  async def create(cls: "type[Transaction]", db: AsyncSession, **kwargs) -> "Transaction":
 
23
 
24
  def __str__(self) -> str:
25
  return f"{self.transaction_date}, {self.category}, {self.name_description}, {self.amount}, {self.type}"
26
+
27
+ def to_dict(self):
28
+ return {
29
+ 'transaction_date': self.transaction_date,
30
+ 'category': self.category,
31
+ 'name_description': self.name_description,
32
+ 'amount': self.amount,
33
+ 'type': self.type
34
+ }
35
 
36
  @classmethod
37
  async def create(cls: "type[Transaction]", db: AsyncSession, **kwargs) -> "Transaction":
app/schema/index.py CHANGED
@@ -53,6 +53,8 @@ class TransactionCreate(TransactionResponse):
53
  class Transaction(TransactionResponse):
54
  user: User
55
 
 
 
56
 
57
  class FileUploadCreate(PydanticBaseModel):
58
  source: str
 
53
  class Transaction(TransactionResponse):
54
  user: User
55
 
56
+ class TransactionRagResponse(PydanticBaseModel):
57
+ answer: str
58
 
59
  class FileUploadCreate(PydanticBaseModel):
60
  source: str
app/service/query_rag.py ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pinecone import Pinecone, ServerlessSpec
2
+ from langchain.text_splitter import RecursiveCharacterTextSplitter, CharacterTextSplitter
3
+ from langchain_openai import OpenAIEmbeddings, ChatOpenAI
4
+ from langchain_pinecone import PineconeVectorStore
5
+ from langchain.vectorstores import Chroma
6
+ from langchain.chains import RetrievalQA
7
+ from langchain.prompts import PromptTemplate
8
+ from langchain_core.documents import Document
9
+
10
+ from fastapi import HTTPException
11
+
12
+ from typing import List
13
+ from app.model.transaction import Transaction
14
+ from app.model.income_statement import IncomeStatement
15
+
16
+ import os
17
+
18
+ async def fetch_transaction_documents(transactions: List[Transaction]) -> List[Document]:
19
+ try:
20
+ document = ''.join(str(row)+'\n' for row in transactions)
21
+
22
+ page_splitter = CharacterTextSplitter(chunk_size=100, chunk_overlap=0)
23
+ pages = page_splitter.split_text(document)
24
+
25
+ text_splitter = RecursiveCharacterTextSplitter(chunk_size=100, chunk_overlap=10)
26
+ document_splits = text_splitter.create_documents(pages)
27
+
28
+ return document_splits
29
+ except Exception as e:
30
+ raise HTTPException(status_code = 500, detail=f"fetch_transaction_documents error: {str(e)}")
31
+
32
+
33
+ async def fetch_income_statement_documents(income_statements: List[IncomeStatement]) -> List[Document]:
34
+ try:
35
+ document = ''.join(str(row)+'\n' for row in income_statements)
36
+
37
+ page_splitter = CharacterTextSplitter(chunk_size=100, chunk_overlap=0)
38
+ pages = page_splitter.split_text(document)
39
+
40
+ text_splitter = RecursiveCharacterTextSplitter(chunk_size=100, chunk_overlap=10)
41
+ document_splits = text_splitter.create_documents(pages)
42
+
43
+ return document_splits
44
+ except Exception as e:
45
+ raise HTTPException(status_code = 500, detail=f"fetch_income_statement_documents error: {str(e)}")
46
+
47
+
48
+ async def answer_query(document_splits: List[Document], query: str, user_id: int) -> str:
49
+ """Creates an embedding of the transactions table and then returns the answer for the given query.
50
+ Args:
51
+ df (pd.DataFrame): DataFrame containing the transactions that a user has entered
52
+ query (str): The query the user will ask against said embedding
53
+
54
+ Returns:
55
+ str: Response to query
56
+ """
57
+ try:
58
+ openai_api_key = os.environ['OPENAI_API_KEY']
59
+
60
+ embeddings = OpenAIEmbeddings(
61
+ model="text-embedding-3-small",
62
+ openai_api_key=openai_api_key
63
+ )
64
+
65
+ print(f"answer_transactions_query: \n document_splits: {type(document_splits)}\n")
66
+
67
+ llm = ChatOpenAI(
68
+ openai_api_key=openai_api_key,
69
+ model_name="gpt-3.5-turbo",
70
+ temperature=0.0
71
+ )
72
+
73
+ prompt_template = """
74
+ Use the following pieces of context to answer the question at the end.
75
+ If you don't know the answer, please think rationally answer from your own knowledge base
76
+
77
+ {context}
78
+
79
+ Question: {question}
80
+ """
81
+ prompt = PromptTemplate(
82
+ template=prompt_template, input_variables=["context", "question"]
83
+ )
84
+
85
+ chain_type_kwargs = {"prompt": prompt}
86
+
87
+ vectorestore = Chroma.from_documents(documents=document_splits,embedding=embeddings)
88
+
89
+ qa = RetrievalQA.from_chain_type(
90
+ llm=llm,
91
+ retriever=vectorestore.as_retriever(),
92
+ chain_type_kwargs=chain_type_kwargs
93
+ )
94
+
95
+ print(f"answer_transactions_query: \n qa: {qa}\n")
96
+
97
+ answer = qa({"query": query})
98
+
99
+ print(f"answer_transactions_query: \n answer: {answer['result']}\n")
100
+
101
+ result_split = answer['result'].split("\n")
102
+ result = ''.join(item for item in result_split)
103
+
104
+ return result
105
+
106
+ except Exception as e:
107
+ raise HTTPException(status_code = 500, detail=f"answer_query error: {str(e)}")
108
+
109
+
110
+ # Note: Attempted to use Pinecone however it failed to learn from documents so settled for Chroma
111
+
112
+ # batch_limit = 20
113
+
114
+ # pinecone_api_key = os.environ['PINECONE_API_KEY']
115
+
116
+ # namespace = "transactionsvector"
117
+ # index_name = "transactionsrag"
118
+
119
+ # pc = Pinecone(api_key=pinecone_api_key)
120
+ # if index_name in pc.list_indexes().names():
121
+ # pc.delete_index(index_name)
122
+
123
+ # pc.create_index(
124
+ # name=index_name,
125
+ # dimension=1536,
126
+ # metric="cosine",
127
+ # spec=ServerlessSpec(
128
+ # cloud="aws", region="us-east-1"
129
+ # )
130
+ # )
131
+
132
+ # index = pc.Index(index_name)
133
+ # transactions_search = PineconeVectorStore.from_documents(
134
+ # documents=document_splits,
135
+ # index_name=index_name,
136
+ # embedding=embeddings,
137
+ # namespace=namespace
138
+ # )
139
+
140
+ # print(f"answer_transactions_query: \n transactions_search: {transactions_search}\n")
141
+
142
+ # for ids in index.list(namespace=namespace):
143
+ # query_item = index.query(
144
+ # id=ids[0],
145
+ # namespace=namespace,
146
+ # top_k=1,
147
+ # include_values=True,
148
+ # include_metadata=True
149
+ # )
150
+ # print(f"answer_transactions_query: \n query_item: {query_item}\n")
151
+
152
+ # qa = RetrievalQA.from_chain_type(
153
+ # llm=llm,
154
+ # chain_type="stuff",
155
+ # retriever=transactions_search.as_retriever(),
156
+ # chain_type_kwargs=chain_type_kwargs
157
+ # )
158
+
tests/test_transactions.py CHANGED
@@ -1,9 +1,15 @@
 
 
 
1
  from fastapi.testclient import TestClient
2
  import pytest
3
 
4
  from app.model.transaction import Transaction
5
- from app.model.user import User
 
6
  from sqlalchemy.ext.asyncio import AsyncSession
 
 
7
  from tests.utils import get_fake_transactions
8
 
9
 
@@ -11,12 +17,11 @@ from tests.utils import get_fake_transactions
11
  async def test_transactions(client: TestClient, get_db_session_fixture: AsyncSession) -> None:
12
 
13
  session_override = get_db_session_fixture
14
-
15
  # 1. Create a user
16
  user = await User.create(session_override, name="user", email="email", hashed_password="password")
17
 
18
- # 2. Create a bunch of transactions
19
  fake_transactions = get_fake_transactions(user.id)
 
20
  await Transaction.bulk_create(session_override, fake_transactions)
21
 
22
  # 3. Verify that the transactions are returned
 
1
+ from datetime import datetime
2
+ from typing import List
3
+ from fastapi import Depends
4
  from fastapi.testclient import TestClient
5
  import pytest
6
 
7
  from app.model.transaction import Transaction
8
+ from app.schema.index import TransactionType, TransactionCreate
9
+
10
  from sqlalchemy.ext.asyncio import AsyncSession
11
+ from app.engine.postgresdb import get_db_session
12
+ from app.model.user import User
13
  from tests.utils import get_fake_transactions
14
 
15
 
 
17
  async def test_transactions(client: TestClient, get_db_session_fixture: AsyncSession) -> None:
18
 
19
  session_override = get_db_session_fixture
 
20
  # 1. Create a user
21
  user = await User.create(session_override, name="user", email="email", hashed_password="password")
22
 
 
23
  fake_transactions = get_fake_transactions(user.id)
24
+ # 2. Create a bunch of transactions
25
  await Transaction.bulk_create(session_override, fake_transactions)
26
 
27
  # 3. Verify that the transactions are returned
tests/utils.py CHANGED
@@ -8,80 +8,240 @@ def get_fake_transactions(user_id: int) -> List[TransactionCreate]:
8
  TransactionCreate(
9
  user_id=user_id,
10
  transaction_date=datetime(2022, 1, 1),
11
- category="category1",
12
- name_description="name_description",
13
- amount=1.0,
14
  type=TransactionType.EXPENSE,
15
  ),
16
  TransactionCreate(
17
  user_id=user_id,
18
  transaction_date=datetime(2022, 1, 2),
19
- category="category2",
20
- name_description="name_description",
21
- amount=2.0,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  type=TransactionType.EXPENSE,
23
  ),
24
  TransactionCreate(
25
  user_id=user_id,
26
  transaction_date=datetime(2022, 1, 3),
27
- category="category3",
28
- name_description="name_description",
29
  amount=3.0,
30
  type=TransactionType.INCOME,
31
  ),
32
  TransactionCreate(
33
  user_id=user_id,
34
  transaction_date=datetime(2022, 1, 4),
35
- category="category1",
36
- name_description="name_description",
37
  amount=4.0,
38
  type=TransactionType.INCOME,
39
  ),
40
  TransactionCreate(
41
  user_id=user_id,
42
  transaction_date=datetime(2022, 1, 5),
43
- category="category2",
44
- name_description="name_description",
45
  amount=5.0,
46
  type=TransactionType.EXPENSE,
47
  ),
48
  TransactionCreate(
49
  user_id=user_id,
50
  transaction_date=datetime(2022, 1, 6),
51
- category="category3",
52
- name_description="name_description",
53
  amount=6.0,
54
  type=TransactionType.EXPENSE,
55
  ),
56
  TransactionCreate(
57
  user_id=user_id,
58
  transaction_date=datetime(2022, 1, 7),
59
- category="category1",
60
- name_description="name_description",
61
  amount=7.0,
62
  type=TransactionType.INCOME,
63
  ),
64
  TransactionCreate(
65
  user_id=user_id,
66
  transaction_date=datetime(2022, 1, 8),
67
- category="category2",
68
- name_description="name_description",
69
  amount=8.0,
70
  type=TransactionType.INCOME,
71
  ),
72
  TransactionCreate(
73
  user_id=user_id,
74
  transaction_date=datetime(2022, 1, 9),
75
- category="category3",
76
- name_description="name_description",
77
  amount=9.0,
78
  type=TransactionType.EXPENSE,
79
  ),
80
  TransactionCreate(
81
  user_id=user_id,
82
  transaction_date=datetime(2022, 1, 10),
83
- category="category1",
84
- name_description="name_description",
85
  amount=10.0,
86
  type=TransactionType.EXPENSE,
87
  ),
 
8
  TransactionCreate(
9
  user_id=user_id,
10
  transaction_date=datetime(2022, 1, 1),
11
+ category="shopping",
12
+ name_description="Amazon",
13
+ amount=11.0,
14
  type=TransactionType.EXPENSE,
15
  ),
16
  TransactionCreate(
17
  user_id=user_id,
18
  transaction_date=datetime(2022, 1, 2),
19
+ category="Streaming",
20
+ name_description="Netflix",
21
+ amount=4.0,
22
+ type=TransactionType.EXPENSE,
23
+ ),
24
+ TransactionCreate(
25
+ user_id=user_id,
26
+ transaction_date=datetime(2022, 1, 3),
27
+ category="Other",
28
+ name_description="Consulting",
29
+ amount=3.0,
30
+ type=TransactionType.INCOME,
31
+ ),
32
+ TransactionCreate(
33
+ user_id=user_id,
34
+ transaction_date=datetime(2022, 1, 4),
35
+ category="Other",
36
+ name_description="Selling Paintings",
37
+ amount=4.0,
38
+ type=TransactionType.INCOME,
39
+ ),
40
+ TransactionCreate(
41
+ user_id=user_id,
42
+ transaction_date=datetime(2022, 1, 5),
43
+ category="Gym",
44
+ name_description="Gym membership",
45
+ amount=5.0,
46
+ type=TransactionType.EXPENSE,
47
+ ),
48
+ TransactionCreate(
49
+ user_id=user_id,
50
+ transaction_date=datetime(2022, 1, 6),
51
+ category="Transportation",
52
+ name_description="Uber Taxi",
53
+ amount=6.0,
54
+ type=TransactionType.EXPENSE,
55
+ ),
56
+ TransactionCreate(
57
+ user_id=user_id,
58
+ transaction_date=datetime(2022, 1, 7),
59
+ category="Other",
60
+ name_description="Freelancing",
61
+ amount=7.0,
62
+ type=TransactionType.INCOME,
63
+ ),
64
+ TransactionCreate(
65
+ user_id=user_id,
66
+ transaction_date=datetime(2022, 1, 8),
67
+ category="Income",
68
+ name_description="Salary",
69
+ amount=8.0,
70
+ type=TransactionType.INCOME,
71
+ ),
72
+ TransactionCreate(
73
+ user_id=user_id,
74
+ transaction_date=datetime(2022, 1, 9),
75
+ category="Shopping",
76
+ name_description="Amazon Lux",
77
+ amount=9.0,
78
+ type=TransactionType.EXPENSE,
79
+ ),
80
+ TransactionCreate(
81
+ user_id=user_id,
82
+ transaction_date=datetime(2022, 1, 10),
83
+ category="Taxes",
84
+ name_description="CA Property Tax",
85
+ amount=10.0,
86
+ type=TransactionType.EXPENSE,
87
+ ),
88
+ TransactionCreate(
89
+ user_id=user_id,
90
+ transaction_date=datetime(2022, 1, 1),
91
+ category="shopping",
92
+ name_description="Amazon",
93
+ amount=11.0,
94
+ type=TransactionType.EXPENSE,
95
+ ),
96
+ TransactionCreate(
97
+ user_id=user_id,
98
+ transaction_date=datetime(2022, 1, 2),
99
+ category="Streaming",
100
+ name_description="Netflix",
101
+ amount=4.0,
102
+ type=TransactionType.EXPENSE,
103
+ ),
104
+ TransactionCreate(
105
+ user_id=user_id,
106
+ transaction_date=datetime(2022, 1, 3),
107
+ category="Other",
108
+ name_description="Consulting",
109
+ amount=3.0,
110
+ type=TransactionType.INCOME,
111
+ ),
112
+ TransactionCreate(
113
+ user_id=user_id,
114
+ transaction_date=datetime(2022, 1, 4),
115
+ category="Other",
116
+ name_description="Selling Paintings",
117
+ amount=4.0,
118
+ type=TransactionType.INCOME,
119
+ ),
120
+ TransactionCreate(
121
+ user_id=user_id,
122
+ transaction_date=datetime(2022, 1, 5),
123
+ category="Gym",
124
+ name_description="Gym membership",
125
+ amount=5.0,
126
+ type=TransactionType.EXPENSE,
127
+ ),
128
+ TransactionCreate(
129
+ user_id=user_id,
130
+ transaction_date=datetime(2022, 1, 6),
131
+ category="Transportation",
132
+ name_description="Uber Taxi",
133
+ amount=6.0,
134
+ type=TransactionType.EXPENSE,
135
+ ),
136
+ TransactionCreate(
137
+ user_id=user_id,
138
+ transaction_date=datetime(2022, 1, 7),
139
+ category="Other",
140
+ name_description="Freelancing",
141
+ amount=7.0,
142
+ type=TransactionType.INCOME,
143
+ ),
144
+ TransactionCreate(
145
+ user_id=user_id,
146
+ transaction_date=datetime(2022, 1, 8),
147
+ category="Income",
148
+ name_description="Salary",
149
+ amount=8.0,
150
+ type=TransactionType.INCOME,
151
+ ),
152
+ TransactionCreate(
153
+ user_id=user_id,
154
+ transaction_date=datetime(2022, 1, 9),
155
+ category="Shopping",
156
+ name_description="Amazon Lux",
157
+ amount=9.0,
158
+ type=TransactionType.EXPENSE,
159
+ ),
160
+ TransactionCreate(
161
+ user_id=user_id,
162
+ transaction_date=datetime(2022, 1, 10),
163
+ category="Taxes",
164
+ name_description="CA Property Tax",
165
+ amount=10.0,
166
+ type=TransactionType.EXPENSE,
167
+ ),
168
+ TransactionCreate(
169
+ user_id=user_id,
170
+ transaction_date=datetime(2022, 1, 1),
171
+ category="shopping",
172
+ name_description="Amazon",
173
+ amount=11.0,
174
+ type=TransactionType.EXPENSE,
175
+ ),
176
+ TransactionCreate(
177
+ user_id=user_id,
178
+ transaction_date=datetime(2022, 1, 2),
179
+ category="Streaming",
180
+ name_description="Netflix",
181
+ amount=4.0,
182
  type=TransactionType.EXPENSE,
183
  ),
184
  TransactionCreate(
185
  user_id=user_id,
186
  transaction_date=datetime(2022, 1, 3),
187
+ category="Other",
188
+ name_description="Consulting",
189
  amount=3.0,
190
  type=TransactionType.INCOME,
191
  ),
192
  TransactionCreate(
193
  user_id=user_id,
194
  transaction_date=datetime(2022, 1, 4),
195
+ category="Other",
196
+ name_description="Selling Paintings",
197
  amount=4.0,
198
  type=TransactionType.INCOME,
199
  ),
200
  TransactionCreate(
201
  user_id=user_id,
202
  transaction_date=datetime(2022, 1, 5),
203
+ category="Gym",
204
+ name_description="Gym membership",
205
  amount=5.0,
206
  type=TransactionType.EXPENSE,
207
  ),
208
  TransactionCreate(
209
  user_id=user_id,
210
  transaction_date=datetime(2022, 1, 6),
211
+ category="Transportation",
212
+ name_description="Uber Taxi",
213
  amount=6.0,
214
  type=TransactionType.EXPENSE,
215
  ),
216
  TransactionCreate(
217
  user_id=user_id,
218
  transaction_date=datetime(2022, 1, 7),
219
+ category="Other",
220
+ name_description="Freelancing",
221
  amount=7.0,
222
  type=TransactionType.INCOME,
223
  ),
224
  TransactionCreate(
225
  user_id=user_id,
226
  transaction_date=datetime(2022, 1, 8),
227
+ category="Income",
228
+ name_description="Salary",
229
  amount=8.0,
230
  type=TransactionType.INCOME,
231
  ),
232
  TransactionCreate(
233
  user_id=user_id,
234
  transaction_date=datetime(2022, 1, 9),
235
+ category="Shopping",
236
+ name_description="Amazon Lux",
237
  amount=9.0,
238
  type=TransactionType.EXPENSE,
239
  ),
240
  TransactionCreate(
241
  user_id=user_id,
242
  transaction_date=datetime(2022, 1, 10),
243
+ category="Taxes",
244
+ name_description="CA Property Tax",
245
  amount=10.0,
246
  type=TransactionType.EXPENSE,
247
  ),