Pre/post processing (classical mapping)

Viewed 33

How to perform pre and post-processing to ensure the domain model is uploaded correctly using SQLAlchemy?

The domain model:

@dataclass
class Posting:
    id: uuid.UUID
    date: datetime.date
    description: str
    debit: float
    credit: float

class Account:
    def __init__(self, id, name, parent, postings):
        self.id: uuid.UUID = id
        self.name: str = name
        self.parent: "Account" = parent
        self.postings: list[Posting] = postings

    def add_posting(self, posting: Posting):
        self.postings.append(posting)

The mapping (based on SQLAlchemy documentation):

mapper_registry = registry()

account = Table(
    'account',
    mapper_registry.metadata,
    Column('id', String(255), primary_key=True),
    Column('name', String(255)),
    Column('parent_id', String(255), ForeignKey('account.id')))

posting = Table(
    'posting',
    mapper_registry.metadata,
    Column('id', String(255), primary_key=True),
    Column('date', Date),
    Column('description', String(1023)),
    Column('account_id', String(255), ForeignKey('account.id')),
    Column('debit', Float),
    Column('credit', Float))

mapper_registry.map_imperatively(Account, account, properties={
    'parent_account': relationship(Account, primaryjoin=account.c.id == account.c.parent_id)})

mapper_registry.map_imperatively(Posting, posting, properties={
    'posting_account': relationship(Account, primaryjoin=posting.c.id == account.c.id)})

engine = create_engine("sqlite:///path_to_db.db")
mapper_registry.metadata.create_all(engine)

The calls I'd like to make to insert data into the database:

with Session(engine) as session:
    parent_account = Account(uuid.uuid4(), "Assets", None, None)
    child_account = Account(uuid.uuid4(), "Current Assets", parent_account, None)
    child_account.add_posting(Posting(uuid.uuid4(), datetime.date(2023, 9, 24), "Add current asset", 60, 0))
    child_account.add_posting(Posting(uuid.uuid4(), datetime.date(2023, 9, 25), "Subtract current asset", 0, 20))

    session.add_all([child_account, parent_account])
    session.add_all(child_account.postings)
    session.commit()

There are two issues:

  1. With account referencing itself, it can't get the id of the parent class. I thought you could use some pre-processing to get the id of the parent class and then insert that into the database. Post-processing would do the reverse of that.
  2. There would also have to be something done so that when an account is queried, all the postings would be loaded as well.

How to go about this?

0 Answers
Related