usawa

Signed, immutable accounting.
Log | Files | Refs | Submodules | LICENSE

commit 832660672712dc9125afa48ef353f6571e545f6f
parent 3c27703eecd05143eb8c1d1dab1dd1429d904835
Author: Carlosokumu <carlosokumu254@gmail.com>
Date:   Mon, 13 Jul 2026 12:16:26 +0300

pass ctx as an argument for ledger  retrieval downstream

Diffstat:
Mdummy/usawa/gui/controllers/entry_controller.py | 11++++++-----
Mdummy/usawa/gui/views/create_entry_view.py | 19++++++-------------
Mdummy/usawa/gui/views/entry_list_view.py | 14++++++++------
Mdummy/usawa/storage/entry_mapper.py | 34+++++++++-------------------------
4 files changed, 29 insertions(+), 49 deletions(-)

diff --git a/dummy/usawa/gui/controllers/entry_controller.py b/dummy/usawa/gui/controllers/entry_controller.py @@ -9,16 +9,17 @@ logg = logging.getLogger("gui.entry_controller") class EntryController: - """Handles entry creation logic""" - def __init__(self, entry_service: EntryService): + def __init__(self, ctx, entry_service: EntryService): self.entry_service = entry_service self._entry_created_listeners = [] + self.ctx = ctx def collect_entry_data(self, view) -> Optional[LedgerEntry]: - """Collect data from the view and create an entry""" tx_date_str = view.date_entry.get_text().strip() tx_time_str = view.time_entry.get_text().strip() + unit = self.ctx.store.ledger.uidx.base + try: if tx_time_str: for fmt in ("%Y-%m-%d %H:%M:%S", "%Y-%m-%d %H:%M"): @@ -41,11 +42,11 @@ class EntryController: external_reference=view.ref_entry.get_text().strip() or None, description=view.desc_entry.get_text().strip() or None, amount=float(view.amount_entry.get_text() or "0"), - source_unit="BTC", + source_unit=unit, tx_date=tx_date, source_type=view.get_source_type(), source_path=view.source_path_entry.get_text().strip(), - dest_unit="BTC", + dest_unit=unit, dest_type=view.get_dest_type(), dest_path=view.dest_path_entry.get_text().strip(), ) diff --git a/dummy/usawa/gui/views/create_entry_view.py b/dummy/usawa/gui/views/create_entry_view.py @@ -7,22 +7,19 @@ import mimetypes logg = logging.getLogger("gui.create_entry_view") -def create_entry_page(nav_view, controller, account_list=None): - """Create a new entry page""" +def create_entry_page(ctx, nav_view, controller, account_list=None): page = Adw.NavigationPage(title="Create New Entry", tag="create-entry") - view = CreateEntryView(nav_view, controller, account_list=account_list) + view = CreateEntryView(ctx, nav_view, controller, account_list=account_list) page.set_child(view) - return page class CreateEntryView(Gtk.Box): - """Create entry view - UI ONLY""" - def __init__(self, nav_view, controller, account_list=None): + def __init__(self, ctx, nav_view, controller, account_list=None): super().__init__(orientation=Gtk.Orientation.VERTICAL, spacing=0) - + self.ctx = ctx self.nav_view = nav_view self.controller = controller self.account_list = account_list @@ -31,7 +28,6 @@ class CreateEntryView(Gtk.Box): self._build_ui(nav_view) def _build_ui(self, nav_view): - """Build the UI""" header = self._create_header(nav_view=nav_view) self.append(header) @@ -65,7 +61,6 @@ class CreateEntryView(Gtk.Box): self.append(action_bar) def _create_header(self, nav_view): - """Create the header with back button and serial number""" header_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=12) header_box.set_margin_top(12) header_box.set_margin_bottom(12) @@ -95,7 +90,6 @@ class CreateEntryView(Gtk.Box): return header_box def _create_basic_section(self): - """Create basic details section - UI ONLY""" section_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=12) header = Gtk.Label(label="BASIC DETAILS") @@ -303,9 +297,9 @@ class CreateEntryView(Gtk.Box): unit_label.add_css_class("caption") fields.append(unit_label) + unit = self.ctx.store.ledger.uidx.base units = Gtk.StringList() - units.append("Bitcoin(BTC)") - + units.append(unit) unit_dropdown = Gtk.DropDown(model=units) unit_dropdown.set_selected(0) fields.append(unit_dropdown) @@ -439,7 +433,6 @@ class CreateEntryView(Gtk.Box): ) def _on_files_selected(self, dialog, result): - """Handle multiple file selection""" try: files = dialog.open_multiple_finish(result) diff --git a/dummy/usawa/gui/views/entry_list_view.py b/dummy/usawa/gui/views/entry_list_view.py @@ -10,10 +10,10 @@ logg = logging.getLogger("gui.entrylist") class EntryListView(Gtk.Box): - """The entry list view with filters, table, and FAB""" def __init__( self, + ctx, nav_view, entry_controller, toast_overlay, @@ -31,6 +31,7 @@ class EntryListView(Gtk.Box): self.toast_overlay = toast_overlay self.account_list = account_list self.active_filter = None + self.ctx = ctx overlay = Gtk.Overlay() self.append(overlay) @@ -308,15 +309,17 @@ class EntryListView(Gtk.Box): dialog.destroy() def on_sort_changed(self, button, sort_type): - """Handle sort option changes""" if button.get_active(): logg.info(f"Sort changed to: {sort_type}") self._sort_and_reload(sort_type) def on_fab_clicked(self, button): - logg.info("FAB clicked - opening create entry window") - - create_page = create_entry_page(self.nav_view, self.entry_controller, account_list=self.account_list) + create_page = create_entry_page( + self.ctx, + self.nav_view, + self.entry_controller, + account_list=self.account_list, + ) self.nav_view.push(create_page) def refresh_data(self): @@ -372,7 +375,6 @@ class EntryListView(Gtk.Box): return False def _create_table_section(self): - """Create the entry list table with all columns""" table_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=0) self.entry_store = Gio.ListStore.new(EntryItem) diff --git a/dummy/usawa/storage/entry_mapper.py b/dummy/usawa/storage/entry_mapper.py @@ -15,20 +15,7 @@ class EntryMapper: """Maps between domain model (LedgerEntry) and storage model (Entry)""" @staticmethod - def to_entry(domain: LedgerEntry, ledger, unitindex=UnitIndex("BTC")): - """ - Convert LedgerEntry (domain) to Entry (storage) - - :param domain: Domain model entry - :type domain: LedgerEntry - :param ledger: The ledger object (for parent digest) - :type ledger: usawa.Ledger - :param unitindex: UnitIndex for validation - :type unitindex: UnitIndex - :return: Storage model entry - :rtype: Entry - """ - + def to_entry(domain: LedgerEntry, ledger): if domain.tx_date is None: raise ValueError("Transaction date is required for storage") @@ -36,6 +23,8 @@ class EntryMapper: if isinstance(tx_date, date) and not isinstance(tx_date, datetime): tx_date = datetime.combine(tx_date, datetime.min.time()) + unitindex = UnitIndex(base=domain.dest_unit) + parent = ledger.current() if ledger else None ref = domain.transaction_ref if domain.transaction_ref else None @@ -45,33 +34,28 @@ class EntryMapper: parent=parent, description=domain.description or "", ref=ref, - unitindex=unitindex, + unitindex=UnitIndex(domain.dest_unit), ) - source_amount = unitindex.from_floatstring( - unitindex.default_unit, str(domain.amount) - ) + source_amount = unitindex.from_floatstring(unitindex.base, str(domain.amount)) dest_amount = -source_amount - account = Account(unitindex.default_unit, domain.source_type.lower(), domain.source_path) + account = Account( + unitindex.base, domain.source_type.lower(), domain.source_path + ) source_part = EntryPart( - #unitindex.default_unit, - #domain.source_type.lower(), - #domain.source_path, account, source_amount, debit=True, ) - #entry.add_part(source_part, debit=True) entry.add_part(source_part) - account = Account(unitindex.default_unit, domain.dest_type.lower(), domain.dest_path) + account = Account(unitindex.base, domain.dest_type.lower(), domain.dest_path) dest_part = EntryPart( account, dest_amount, debit=False, ) - #entry.add_part(dest_part, debit=False) entry.add_part(dest_part) return entry