Compare commits
2 Commits
afe89cfb03
...
b5039f6468
| Author | SHA1 | Date | |
|---|---|---|---|
| b5039f6468 | |||
| 65ecfcd919 |
@@ -12,6 +12,8 @@ from account.models import Account
|
|||||||
from account.resource import AccountResource
|
from account.resource import AccountResource
|
||||||
|
|
||||||
from db import SessionDep
|
from db import SessionDep
|
||||||
|
from transaction.models import TransactionRead
|
||||||
|
from transaction.resource import TransactionResource
|
||||||
from user.manager import get_current_user
|
from user.manager import get_current_user
|
||||||
|
|
||||||
|
|
||||||
@@ -55,6 +57,13 @@ def read_account(account_id: UUID, session: SessionDep, current_user=Depends(get
|
|||||||
raise HTTPException(status_code=404, detail="Account not found")
|
raise HTTPException(status_code=404, detail="Account not found")
|
||||||
return account
|
return account
|
||||||
|
|
||||||
|
@router.get("/{account_id}/opening_state")
|
||||||
|
def read_account_opening_state(account_id: UUID, session: SessionDep, current_user=Depends(get_current_user)) -> TransactionRead:
|
||||||
|
transaction = TransactionResource.get_opening_transaction(session, account_id)
|
||||||
|
if not transaction:
|
||||||
|
raise HTTPException(status_code=404, detail="Account not found")
|
||||||
|
return transaction
|
||||||
|
|
||||||
@router.put("/{account_id}")
|
@router.put("/{account_id}")
|
||||||
def update_account(account_id: UUID, account: AccountUpdate, session: SessionDep, current_user=Depends(get_current_user)) -> AccountRead:
|
def update_account(account_id: UUID, account: AccountUpdate, session: SessionDep, current_user=Depends(get_current_user)) -> AccountRead:
|
||||||
db_account = AccountResource.get(session, account_id)
|
db_account = AccountResource.get(session, account_id)
|
||||||
|
|||||||
@@ -100,15 +100,7 @@ class AccountResource:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def select(cls):
|
def select(cls):
|
||||||
split_filter = aliased(Split)
|
return select(Account)
|
||||||
account_filter = aliased(Account)
|
|
||||||
columns = [Account.id, Account.name, Account.parent_account_id, Account.family, Account.type, Account.path,
|
|
||||||
Split.amount.label("opening_balance"), literal_column('"1970-01-01"').label("opening_date")]
|
|
||||||
return (select(*columns)
|
|
||||||
.join(Split)
|
|
||||||
.join(Transaction)
|
|
||||||
.join(split_filter)
|
|
||||||
.join(account_filter, account_filter.id == split_filter.account_id and Account.path == "/Equity/"))
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def list(cls, filters):
|
def list(cls, filters):
|
||||||
|
|||||||
@@ -21,8 +21,7 @@ class AccountBaseId(AccountBase):
|
|||||||
path: str = Field(index=True)
|
path: str = Field(index=True)
|
||||||
|
|
||||||
class AccountRead(AccountBaseId):
|
class AccountRead(AccountBaseId):
|
||||||
opening_date: date = Field()
|
pass
|
||||||
opening_balance: Decimal = Field(decimal_places=2, default=0)
|
|
||||||
|
|
||||||
class BaseAccountWrite(AccountBase):
|
class BaseAccountWrite(AccountBase):
|
||||||
path: SkipJsonSchema[str] = Field(default="")
|
path: SkipJsonSchema[str] = Field(default="")
|
||||||
@@ -39,11 +38,10 @@ class AccountWrite(BaseAccountWrite):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
opening_date: date = Field()
|
|
||||||
opening_balance: MonetaryAmount = Field()
|
|
||||||
|
|
||||||
class AccountCreate(AccountWrite):
|
class AccountCreate(AccountWrite):
|
||||||
pass
|
opening_date: date = Field()
|
||||||
|
opening_balance: MonetaryAmount = Field()
|
||||||
|
|
||||||
class AccountUpdate(AccountWrite):
|
class AccountUpdate(AccountWrite):
|
||||||
pass
|
pass
|
||||||
@@ -63,11 +61,9 @@ class CategoryWrite(BaseAccountWrite):
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
class CategoryCreate(CategoryWrite):
|
||||||
opening_date: SkipJsonSchema[date] = Field(default=date(1970, 1, 1))
|
opening_date: SkipJsonSchema[date] = Field(default=date(1970, 1, 1))
|
||||||
opening_balance: SkipJsonSchema[Decimal] = Field(default=0)
|
opening_balance: SkipJsonSchema[Decimal] = Field(default=0)
|
||||||
|
|
||||||
class CategoryCreate(CategoryWrite):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class CategoryUpdate(CategoryWrite):
|
class CategoryUpdate(CategoryWrite):
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ class SplitBaseId(SplitBase):
|
|||||||
|
|
||||||
class SplitRead(SplitBaseId):
|
class SplitRead(SplitBaseId):
|
||||||
account: AccountRead
|
account: AccountRead
|
||||||
payee: PayeeRead
|
payee: PayeeRead | None
|
||||||
|
|
||||||
class TransactionRead(TransactionBaseId):
|
class TransactionRead(TransactionBaseId):
|
||||||
splits: list[SplitRead]
|
splits: list[SplitRead]
|
||||||
|
|||||||
53
api/app/transaction/resource.py
Normal file
53
api/app/transaction/resource.py
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
from decimal import Decimal
|
||||||
|
from typing import Optional
|
||||||
|
from uuid import UUID, uuid4
|
||||||
|
|
||||||
|
from sqlalchemy.orm import aliased
|
||||||
|
from sqlmodel import Field, SQLModel, select, Relationship
|
||||||
|
from pydantic import Field as PydField
|
||||||
|
|
||||||
|
from account.models import Account
|
||||||
|
from account.schemas import AccountRead
|
||||||
|
from transaction.models import Transaction, Split
|
||||||
|
from payee.models import Payee, PayeeRead
|
||||||
|
|
||||||
|
class TransactionResource:
|
||||||
|
@classmethod
|
||||||
|
def create(cls, transaction, session):
|
||||||
|
transaction_db = Transaction.model_validate(transaction)
|
||||||
|
session.add(transaction_db)
|
||||||
|
session.commit()
|
||||||
|
session.refresh(transaction_db)
|
||||||
|
|
||||||
|
return transaction_db
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def list(cls):
|
||||||
|
return select(Transaction).join(Split).join(Account)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get(cls, session, transaction_id):
|
||||||
|
return session.get(Transaction, transaction_id)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_opening_transaction(cls, session, account_id):
|
||||||
|
split_account = aliased(Split)
|
||||||
|
split_equity = aliased(Split)
|
||||||
|
account_filter = aliased(Account)
|
||||||
|
return session.exec(select(Transaction)
|
||||||
|
.join(split_account, split_account.account_id == account_id)
|
||||||
|
.join(split_equity)
|
||||||
|
.join(account_filter, account_filter.id == split_equity.account_id and Account.path == "/Equity/")).first()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def update(cls, session, transaction_db, transaction_data):
|
||||||
|
transaction_db.sqlmodel_update(Transaction.model_validate(transaction_data))
|
||||||
|
session.add(transaction_db)
|
||||||
|
session.commit()
|
||||||
|
session.refresh(transaction_db)
|
||||||
|
return transaction_db
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def delete(cls, session, transaction):
|
||||||
|
session.delete(transaction)
|
||||||
|
session.commit()
|
||||||
@@ -6,10 +6,17 @@ export const AccountEdit: React.FC = () => {
|
|||||||
const { id } = useParams()
|
const { id } = useParams()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CrudForm
|
<div>
|
||||||
schemaName={"AccountUpdate"}
|
<CrudForm
|
||||||
resource={"accounts"}
|
schemaName={"AccountUpdate"}
|
||||||
id={id}
|
resource={"accounts"}
|
||||||
/>
|
id={id}
|
||||||
|
/>
|
||||||
|
<CrudForm
|
||||||
|
schemaName={"AccountUpdate"}
|
||||||
|
resource={`accounts/${id}/opening`}
|
||||||
|
id={id}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user