From 44b3b437e3ca91db1182116b1e9dc73a9b5d6757 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Wed, 27 Sep 2023 20:35:28 -0500 Subject: [PATCH] Cleanup tender logic a bit; require amount --- wuttapos/views/pos.py | 128 ++++++++++++++++++++++++++++++++---------- 1 file changed, 99 insertions(+), 29 deletions(-) diff --git a/wuttapos/views/pos.py b/wuttapos/views/pos.py index 21932ff..f6cad59 100644 --- a/wuttapos/views/pos.py +++ b/wuttapos/views/pos.py @@ -138,7 +138,7 @@ class POSView(WuttaView): session.commit() self.add_row_item(row) self.items.scroll_to(offset=-1, duration=250) - self.txn_total.value = self.app.render_currency(batch.sales_total) + self.txn_total.value = self.app.render_currency(batch.get_balance()) self.reset() else: @@ -251,7 +251,16 @@ class POSView(WuttaView): bgcolor='yellow', visible=different, ), - ft.Markdown(info), + ft.Divider(), + ft.Container( + theme_mode=ft.ThemeMode.SYSTEM, + theme=ft.Theme(text_theme=ft.TextTheme( + body_medium=ft.TextStyle( + size=24, + color='black', + ))), + content=ft.Markdown(info), + ), ], height=500, width=500, @@ -400,7 +409,7 @@ class POSView(WuttaView): title=ft.Text("Remove Customer"), content=ft.Text("Really remove the customer from this transaction?", size=20), actions=[ - ft.Container(content=ft.Text("Remove", + ft.Container(content=ft.Text("Yes, Remove", size=font_size, weight=ft.FontWeight.BOLD), height=self.default_button_size, @@ -711,25 +720,13 @@ class POSView(WuttaView): border_radius=ft.border_radius.all(5), bgcolor='orange') - cash = { - 'tender_code': self.tender_cash.code if self.tender_cash else 'CA', - 'tender_name': self.tender_cash.name if self.tender_cash else "Cash", - } - - check = { - 'tender_code': self.tender_check.code if self.tender_check else 'CK', - 'tender_name': self.tender_check.name if self.tender_check else "Check", - } - self.context_menu = ft.Container( content=ft.Column( [ ft.Row( [ - context_button(cash['tender_name'], data=cash, - on_click=self.tender_click), - context_button(check['tender_name'], data=check, - on_click=self.tender_click), + self.make_cash_button(), + self.make_check_button(), ], spacing=0, ), @@ -786,6 +783,41 @@ class POSView(WuttaView): kwargs.setdefault('size', 24) return ft.Text(*args, **kwargs) + def make_tender_button(self, tender, **kwargs): + if isinstance(tender, self.model.Tender): + info = {'tender_code': tender.code, + 'tender_name': tender.name} + else: + info = tender + + font_size = kwargs.pop('font_size', self.default_font_size) + text = ft.Text(info['tender_name'], + size=font_size, + weight=ft.FontWeight.BOLD) + + kw = { + 'height': self.default_button_size, + 'width': self.default_button_size * 2, + 'on_click': self.tender_click, + 'alignment': ft.alignment.center, + 'border': ft.border.all(1, 'black'), + 'border_radius': ft.border_radius.all(5), + 'bgcolor': 'orange', + } + kw.update(kwargs) + kw['data'] = info + return ft.Container(content=text, **kw) + + def make_cash_button(self, **kwargs): + cash = self.tender_cash or {'tender_code': 'CA', + 'tender_name': "Cash"} + return self.make_tender_button(cash, **kwargs) + + def make_check_button(self, **kwargs): + check = self.tender_check or {'tender_code': 'CK', + 'tender_name': "Check"} + return self.make_tender_button(check, **kwargs) + def get_current_user(self, session): uuid = self.page.session.get('user_uuid') if uuid: @@ -820,7 +852,7 @@ class POSView(WuttaView): self.add_row_item(row) self.items.scroll_to(offset=-1, duration=100) - self.txn_total.value = self.app.render_currency(batch.sales_total) + self.txn_total.value = self.app.render_currency(batch.get_balance()) else: self.page.session.set('txn_display', None) @@ -954,9 +986,10 @@ class POSView(WuttaView): user = self.get_current_user(session) batch = self.get_current_batch(session, user=user, create=False) + # nothing to do if no transaction if not batch: session.close() - self.page.snack_bar = ft.SnackBar(ft.Text(f"NO TRANSACTION", + self.page.snack_bar = ft.SnackBar(ft.Text("NO TRANSACTION", color='black', size=20, weight=ft.FontWeight.BOLD), @@ -966,9 +999,38 @@ class POSView(WuttaView): self.reset() return + # nothing to do if zero sales if not batch.get_balance(): session.close() - self.page.snack_bar = ft.SnackBar(ft.Text(f"NO SALES", + self.page.snack_bar = ft.SnackBar(ft.Text("NO SALES", + color='black', + size=20, + weight=ft.FontWeight.BOLD), + bgcolor='yellow', + duration=1500) + self.page.snack_bar.open = True + self.reset() + return + + # nothing to do if no amount provided + if not self.main_input.value: + session.close() + self.page.snack_bar = ft.SnackBar(ft.Text("MUST SPECIFY AMOUNT", + color='black', + size=20, + weight=ft.FontWeight.BOLD), + bgcolor='yellow', + duration=1500) + self.page.snack_bar.open = True + self.reset() + return + + # nothing to do if amount not valid + try: + amount = decimal.Decimal(self.main_input.value) + except: + session.close() + self.page.snack_bar = ft.SnackBar(ft.Text(f"AMOUNT NOT VALID: {self.main_input.value}", color='black', size=20, weight=ft.FontWeight.BOLD), @@ -981,13 +1043,16 @@ class POSView(WuttaView): # tender / execute batch code = e.control.data['tender_code'] tender = handler.get_tender(session, code) - amount = -batch.get_balance() try: - # TODO: should prompt user for amount - # TODO: also should display the tender item somehow, - # unless that finalized txn in which case..?? - row = handler.apply_tender(batch, user, tender or code, amount) + # TODO: still need support for the following: + # - if balance remains, update display (i.e. show this tender) + # - if this tender overpays, how to handle change back? + + # apply tender amount to batch + # nb. this *may* execute the batch! + # nb. we negate the amount supplied by user + rows = handler.apply_tender(batch, user, tender or code, -amount) except Exception as error: session.rollback() @@ -1003,13 +1068,18 @@ class POSView(WuttaView): else: session.commit() + + # TODO: maybe shouldn't clear screen so immediately? + if batch.executed: + self.clear_all() + + else: + # update screen to reflect new balance + self.txn_total.value = self.app.render_currency(batch.get_balance()) + finally: session.close() - # TODO: maybe shouldn't clear screen so immediately? - if batch.executed: - self.clear_all() - self.reset() def clear_all(self):