From 9268d939eb2faa3bc0bb3874d4e6975add2c476d Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sun, 1 Oct 2023 17:39:02 -0500 Subject: [PATCH] Show tender line items on screen; add "change back" alert --- wuttapos/controls/base.py | 1 + wuttapos/controls/txnitem.py | 51 ++++++++++++++----- wuttapos/views/base.py | 5 +- wuttapos/views/pos.py | 95 ++++++++++++++++++++++++++++-------- 4 files changed, 120 insertions(+), 32 deletions(-) diff --git a/wuttapos/controls/base.py b/wuttapos/controls/base.py index 6810c44..b7d7e0e 100644 --- a/wuttapos/controls/base.py +++ b/wuttapos/controls/base.py @@ -34,6 +34,7 @@ class WuttaControl(ft.UserControl): super().__init__(*args, **kwargs) self.config = config self.app = config.get_app() + self.enum = self.app.enum def informed_refresh(self, **kwargs): pass diff --git a/wuttapos/controls/txnitem.py b/wuttapos/controls/txnitem.py index 71310aa..1550030 100644 --- a/wuttapos/controls/txnitem.py +++ b/wuttapos/controls/txnitem.py @@ -55,22 +55,26 @@ class WuttaTxnItem(WuttaControl): italic=True, **kw) + if self.row.row_type == self.enum.POS_ROW_TYPE_SELL: + return self.build_item_sell() + + elif self.row.row_type in (self.enum.POS_ROW_TYPE_TENDER, + self.enum.POS_ROW_TYPE_CHANGE_BACK): + return self.build_item_tender() + + def build_item_sell(self): quantity = self.app.render_quantity(self.row.quantity) pretty_price = self.app.render_currency(self.row.txn_price) - return ft.Row( [ - ft.Row([ - - ft.Text( - spans=[ - ft.TextSpan(f"{self.row.description}", - style=self.major_style), - ft.TextSpan(f"× {quantity} @ {pretty_price}", - style=self.minor_style), - ], - ), - ]), + ft.Text( + spans=[ + ft.TextSpan(f"{self.row.description}", + style=self.major_style), + ft.TextSpan(f"× {quantity} @ {pretty_price}", + style=self.minor_style), + ], + ), ft.Text( spans=[ ft.TextSpan(self.app.render_currency(self.row.sales_total), @@ -82,8 +86,31 @@ class WuttaTxnItem(WuttaControl): alignment=ft.MainAxisAlignment.SPACE_BETWEEN, ) + def build_item_tender(self): + return ft.Row( + [ + ft.Text( + spans=[ + ft.TextSpan(f"{self.row.description}", + style=self.major_style), + ], + ), + ft.Text( + spans=[ + ft.TextSpan(self.app.render_currency(self.row.tender_total), + style=self.major_style), + ], + ), + + ], + alignment=ft.MainAxisAlignment.SPACE_BETWEEN, + ) + def mark_void(self): + # TODO: how to properly handle this restriction? + assert self.row.row_type == self.enum.POS_ROW_TYPE_SELL + self.major_style.color = 'red' self.major_style.decoration = ft.TextDecoration.LINE_THROUGH diff --git a/wuttapos/views/base.py b/wuttapos/views/base.py index 5536a26..8576dad 100644 --- a/wuttapos/views/base.py +++ b/wuttapos/views/base.py @@ -31,7 +31,7 @@ from rattail.files import resource_path import flet as ft from wuttapos.controls.header import WuttaHeader -from wuttapos.util import get_pos_batch_handler +from wuttapos.util import get_pos_batch_handler, make_button class WuttaView(ft.View): @@ -66,6 +66,9 @@ class WuttaView(ft.View): def get_batch_handler(self): return get_pos_batch_handler(self.config) + def make_button(self, *args, **kwargs): + return make_button(*args, **kwargs) + def reset(self, *args, **kwargs): pass diff --git a/wuttapos/views/pos.py b/wuttapos/views/pos.py index e329e52..99f2666 100644 --- a/wuttapos/views/pos.py +++ b/wuttapos/views/pos.py @@ -917,7 +917,9 @@ class POSView(WuttaView): def add_row_item(self, row): # TODO: row types ugh - if row.row_type not in ('sell',): + if row.row_type not in (self.enum.POS_ROW_TYPE_SELL, + self.enum.POS_ROW_TYPE_TENDER, + self.enum.POS_ROW_TYPE_CHANGE_BACK): return self.items.controls.append( @@ -955,7 +957,28 @@ class POSView(WuttaView): # void line row = self.selected_item.data['row'] - if not row.void: + if row.void: + # cannot void an already void line + self.page.snack_bar = ft.SnackBar(ft.Text("LINE ALREADY VOID", + color='black', + size=20, + weight=ft.FontWeight.BOLD), + bgcolor='yellow', + duration=1500) + self.page.snack_bar.open = True + + elif row.row_type != self.enum.POS_ROW_TYPE_SELL: + # cannot void line unless of type 'sell' + self.page.snack_bar = ft.SnackBar(ft.Text("LINE DOES NOT ALLOW VOID", + color='black', + size=20, + weight=ft.FontWeight.BOLD), + bgcolor='yellow', + duration=1500) + self.page.snack_bar.open = True + + else: + # okay, void the line row = session.get(row.__class__, row.uuid) handler.void_row(row, user) self.selected_item.data['row'] = row @@ -966,17 +989,6 @@ class POSView(WuttaView): # update screen to reflect new balance self.txn_total.value = self.app.render_currency(batch.get_balance()) - - else: - self.page.snack_bar = ft.SnackBar(ft.Text("LINE ALREADY VOID", - color='black', - size=20, - weight=ft.FontWeight.BOLD), - bgcolor='yellow', - duration=1500) - self.page.snack_bar.open = True - - else: # void txn handler.void_batch(batch, user) @@ -1147,13 +1159,58 @@ class POSView(WuttaView): else: session.commit() - # TODO: maybe shouldn't clear screen so immediately? - if batch.executed: - self.clear_all() + # update screen to reflect new items/balance + for row in rows: + self.add_row_item(row) + self.txn_total.value = self.app.render_currency(batch.get_balance()) - else: - # update screen to reflect new balance - self.txn_total.value = self.app.render_currency(batch.get_balance()) + # executed batch means txn was finalized + if batch.executed: + + # look for "change back" row, if found then show alert + last_row = rows[-1] + if last_row.row_type == self.enum.POS_ROW_TYPE_CHANGE_BACK: + + def close_bs(e): + # user dismissed the change back alert; clear screen + bs.open = False + bs.update() + self.clear_all() + self.page.update() + + bs = ft.BottomSheet( + ft.Container( + ft.Column( + [ + ft.Text("Change Back", size=24, + weight=ft.FontWeight.BOLD), + ft.Divider(), + ft.Text("Please give customer change back:", + size=20), + ft.Text(self.app.render_currency(last_row.tender_total), + size=32, weight=ft.FontWeight.BOLD), + ft.Container( + content=self.make_button("Dismiss", on_click=close_bs, + height=80, width=120), + alignment=ft.alignment.center, + expand=1, + ), + ], + ), + bgcolor='green', + padding=20, + ), + open=True, + dismissible=False, + ) + + # show change back alert + # nb. we do *not* clear screen yet + self.page.overlay.append(bs) + + else: + # txn finalized but no change back; clear screen + self.clear_all() finally: session.close()