Make PartialTXN flag a string

This commit is contained in:
2026-01-05 19:39:39 +10:00
parent c7d32520c4
commit 3b37c62f17
4 changed files with 76 additions and 59 deletions

View File

@@ -16,6 +16,7 @@ class PartialPosting(ABCPosting):
""" """
Partial posting object, potentially without an account name. Partial posting object, potentially without an account name.
""" """
account: Optional[str] = None account: Optional[str] = None
def upgrade(self, default_account: Optional[str] = None) -> TXNPosting: def upgrade(self, default_account: Optional[str] = None) -> TXNPosting:
@@ -30,7 +31,7 @@ class PartialPosting(ABCPosting):
total_cost=self.total_cost, total_cost=self.total_cost,
price=self.price, price=self.price,
flag=self.flag, flag=self.flag,
comment=self.comment comment=self.comment,
) )
@property @property
@@ -54,14 +55,15 @@ class PartialTXN:
TODO: REPR TODO: REPR
""" """
date: dt.date date: dt.date
flag: TXNFlag = TXNFlag.INCOMPLETE flag: str = TXNFlag.INCOMPLETE.value
payee: str = '' payee: str = ""
narration: str = '' narration: str = ""
comment: Optional[str] = None comment: Optional[str] = None
document: Optional[str] = None document: Optional[str] = None
tags: str = '' tags: str = ""
links: str = '' links: str = ""
source_posting: PartialPosting source_posting: PartialPosting
source_fee_asset_posting: Optional[PartialPosting] = None source_fee_asset_posting: Optional[PartialPosting] = None
source_fee_expense_posting: Optional[PartialPosting] = None source_fee_expense_posting: Optional[PartialPosting] = None
@@ -71,25 +73,25 @@ class PartialTXN:
# Exposing set of fields which may be updated (e.g. from rules) # Exposing set of fields which may be updated (e.g. from rules)
# Map field name -> display name # Map field name -> display name
fields = { fields = {
'flag': 'Flag', "flag": "Flag",
'payee': 'Payee', "payee": "Payee",
'narration': 'Narration', "narration": "Narration",
'comment': "Comment", "comment": "Comment",
'document': "Document", "document": "Document",
'tags': "Tags", "tags": "Tags",
'links': "Links", "links": "Links",
'source_account': "Source Account", "source_account": "Source Account",
'source_fee_asset_account': "Source Fee Asset Account", "source_fee_asset_account": "Source Fee Asset Account",
'source_fee_expense_account': "Source Fee Expense Account", "source_fee_expense_account": "Source Fee Expense Account",
'target_account': "Target Account", "target_account": "Target Account",
'target_fee_expense_account': "Target Fee Expense Account", "target_fee_expense_account": "Target Fee Expense Account",
} }
posting_fields = { posting_fields = {
'source_posting': 'source_account', "source_posting": "source_account",
'source_fee_asset_posting': 'source_fee_asset_account', "source_fee_asset_posting": "source_fee_asset_account",
'source_fee_expense_posting': 'source_fee_expense_account', "source_fee_expense_posting": "source_fee_expense_account",
'target_posting': 'target_account', "target_posting": "target_account",
'target_fee_expense_posting': 'target_fee_expense_account', "target_fee_expense_posting": "target_fee_expense_account",
} }
@property @property
@@ -118,7 +120,9 @@ class PartialTXN:
if (posting := self.source_fee_asset_posting) is not None: if (posting := self.source_fee_asset_posting) is not None:
posting.account = value posting.account = value
else: else:
raise ValueError("This TXN does not have a source fee asset posting to set.") raise ValueError(
"This TXN does not have a source fee asset posting to set."
)
@property @property
def source_fee_expense_account(self): def source_fee_expense_account(self):
@@ -130,7 +134,9 @@ class PartialTXN:
if (posting := self.source_fee_expense_posting) is not None: if (posting := self.source_fee_expense_posting) is not None:
posting.account = value posting.account = value
else: else:
raise ValueError("This TXN does not have a source fee expense posting to set.") raise ValueError(
"This TXN does not have a source fee expense posting to set."
)
@property @property
def target_fee_expense_account(self): def target_fee_expense_account(self):
@@ -142,7 +148,9 @@ class PartialTXN:
if (posting := self.target_fee_expense_posting) is not None: if (posting := self.target_fee_expense_posting) is not None:
posting.account = value posting.account = value
else: else:
raise ValueError("This TXN does not have a target fee expense posting to set.") raise ValueError(
"This TXN does not have a target fee expense posting to set."
)
@property @property
def postings(self): def postings(self):
@@ -180,7 +188,7 @@ class PartialTXN:
we_dont_have = set(self.posting_fields.keys()).difference(we_have) we_dont_have = set(self.posting_fields.keys()).difference(we_have)
with_defaults.update( with_defaults.update(
overwrite=False, overwrite=False,
**{k: v for k, v in defaults.items() if k not in we_dont_have} **{k: v for k, v in defaults.items() if k not in we_dont_have},
) )
upgraded = with_defaults.upgrade() upgraded = with_defaults.upgrade()
elif self.partial: elif self.partial:
@@ -188,14 +196,14 @@ class PartialTXN:
else: else:
upgraded = Transaction( upgraded = Transaction(
date=self.date, date=self.date,
flag=self.flag, flag=TXNFlag(self.flag),
payee=self.payee, payee=self.payee,
narration=self.narration, narration=self.narration,
comments=[self.comment] if self.comment else [], comments=[self.comment] if self.comment else [],
document=[self.document] if self.document else [], document=[self.document] if self.document else [],
tags=self.tags.split(), tags=self.tags.split(),
links=self.links.split(), links=self.links.split(),
postings=[p.upgrade() for p in self.postings.values()] postings=[p.upgrade() for p in self.postings.values()],
) )
return upgraded return upgraded
@@ -219,17 +227,16 @@ class PartialTXN:
# Don't include posting accounts which aren't there # Don't include posting accounts which aren't there
continue continue
match name: match name:
case 'flag': case "flag":
value = self.flag.value value = self.flag
case _: case _:
value = getattr(self, name) value = getattr(self, name)
value = str(value) if value is not None else '' value = str(value) if value is not None else ""
fields.append(TXNField( fields.append(
name=name, TXNField(
display_name=display_name, name=name, display_name=display_name, value=value, matchable=True
value=value, )
matchable=True )
))
return fields return fields
@@ -243,26 +250,26 @@ class PartialTXN:
userstr = userstr.strip() userstr = userstr.strip()
# TODO: Each of these cases needs custom validation # TODO: Each of these cases needs custom validation
match name: match name:
case 'flag': case "flag":
if userstr == '!': if userstr == "!":
updater['flag'] = TXNFlag.INCOMPLETE updater["flag"] = TXNFlag.INCOMPLETE.value
elif userstr == '*': elif userstr == "*":
updater['flag'] = TXNFlag.COMPLETE updater["flag"] = TXNFlag.COMPLETE.value
else: else:
raise UserInputError( raise UserInputError(
"Transaction flag must be either '*' or '!'" "Transaction flag must be either '*' or '!'"
) )
case 'payee' | 'narration' | 'tags' | 'links': case "payee" | "narration" | "tags" | "links":
updater[name] = userstr updater[name] = userstr
case 'comment' | 'document': case "comment" | "document":
updater[name] = userstr or None updater[name] = userstr or None
case 'source_account' | 'target_account': case "source_account" | "target_account":
updater[name] = userstr updater[name] = userstr
case 'source_fee_asset_account': case "source_fee_asset_account":
updater[name] = userstr updater[name] = userstr
case 'source_fee_expense_account': case "source_fee_expense_account":
updater[name] = userstr updater[name] = userstr
case 'target_fee_expense_account': case "target_fee_expense_account":
updater[name] = userstr updater[name] = userstr
case _: case _:
raise ValueError(f"Unknown field {name} passed to TXN parser.") raise ValueError(f"Unknown field {name} passed to TXN parser.")

View File

@@ -110,10 +110,16 @@ class CBAConverter(Converter[CBARecord, CBAConfig]):
args = {} args = {}
args["date"] = record.date args["date"] = record.date
if "flag" in fields:
args["flag"] = TXNFlag(fields["flag"])
for name in {"payee", "narration", "comment", "document", "tags", "links"}: for name in {
"payee",
"narration",
"comment",
"document",
"tags",
"links",
"flag",
}:
if name in fields: if name in fields:
args[name] = fields[name] args[name] = fields[name]

View File

@@ -254,12 +254,16 @@ class WiseConverter(Converter[WiseRecord, WiseConfig]):
args = {} args = {}
args["date"] = record.date args["date"] = record.date
# Convert string flag if it exists
if "flag" in fields:
args["flag"] = TXNFlag(fields["flag"])
# Copy string fields over directly # Copy string fields over directly
for name in {"payee", "narration", "comment", "document", "tags", "links"}: for name in {
"payee",
"narration",
"comment",
"document",
"tags",
"links",
"flag",
}:
if name in fields: if name in fields:
args[name] = fields[name] args[name] = fields[name]

View File

@@ -266,7 +266,7 @@ class RowTree(ttk.Frame):
for col in self.columns: for col in self.columns:
match col.split(".", maxsplit=1): match col.split(".", maxsplit=1):
case ["txn", "flag"]: case ["txn", "flag"]:
value = txn.flag.value value = txn.flag
case ["txn", field]: case ["txn", field]:
value = getattr(txn, field) value = getattr(txn, field)
case ["record", "date"]: case ["record", "date"]: