Add initial support for Open Ring

This commit is contained in:
Lance Edgar 2023-10-11 18:40:11 -05:00
parent fb4206e5a9
commit 2c9f3cd41a
4 changed files with 139 additions and 14 deletions

View file

@ -0,0 +1,67 @@
# -*- coding: utf-8; -*-
################################################################################
#
# WuttaPOS -- Pythonic Point of Sale System
# Copyright © 2023 Lance Edgar
#
# This file is part of WuttaPOS.
#
# WuttaPOS is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# WuttaPOS is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# WuttaPOS. If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
"""
WuttaPOS - department lookup control
"""
from .lookup import WuttaLookup
class WuttaDepartmentLookup(WuttaLookup):
def __init__(self, *args, **kwargs):
# nb. this forces first query
kwargs.setdefault('initial_search', '')
kwargs.setdefault('allow_empty_query', True)
super().__init__(*args, **kwargs)
def get_results_columns(self):
return [
"Number",
"Name",
]
def get_results(self, session, entry):
model = self.app.model
query = session.query(model.Department)\
.order_by(model.Department.number)
if entry:
query = query.filter(model.Department.name.ilike(f'%{entry}%'))
departments = []
for dept in query:
departments.append({
'uuid': dept.uuid,
'number': str(dept.number),
'name': dept.name,
})
return departments
def make_result_row(self, dept):
return [
dept['number'],
dept['name'],
]

View file

@ -41,6 +41,7 @@ class WuttaLookup(WuttaControl):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.initial_search = kwargs.pop('initial_search', None) self.initial_search = kwargs.pop('initial_search', None)
self.allow_empty_query = kwargs.pop('allow_empty_query', False)
self.on_select = kwargs.pop('on_select', None) self.on_select = kwargs.pop('on_select', None)
self.on_cancel = kwargs.pop('on_cancel', None) self.on_cancel = kwargs.pop('on_cancel', None)
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
@ -165,7 +166,7 @@ class WuttaLookup(WuttaControl):
raise NotImplementedError raise NotImplementedError
def did_mount(self): def did_mount(self):
if self.initial_search: if self.initial_search is not None:
self.searchbox.value = self.initial_search self.searchbox.value = self.initial_search
self.initial_search = None # only do it once self.initial_search = None # only do it once
self.update() self.update()
@ -201,11 +202,11 @@ class WuttaLookup(WuttaControl):
raise NotImplementedError raise NotImplementedError
def make_result_row(self, obj): def make_result_row(self, obj):
raise NotImplementedError return obj
def lookup(self, e=None): def lookup(self, e=None):
entry = self.searchbox.value entry = self.searchbox.value
if not entry: if not entry and not self.allow_empty_query:
self.searchbox.focus() self.searchbox.focus()
self.update() self.update()
return return

View file

@ -48,7 +48,8 @@ class WuttaTxnItem(WuttaControl):
self.minor_style = ft.TextStyle(size=int(self.font_size * 0.8), self.minor_style = ft.TextStyle(size=int(self.font_size * 0.8),
italic=True) italic=True)
if self.row.row_type == self.enum.POS_ROW_TYPE_SELL: if self.row.row_type in (self.enum.POS_ROW_TYPE_SELL,
self.enum.POS_ROW_TYPE_OPEN_RING):
return self.build_item_sell() return self.build_item_sell()
elif self.row.row_type in (self.enum.POS_ROW_TYPE_TENDER, elif self.row.row_type in (self.enum.POS_ROW_TYPE_TENDER,
@ -129,7 +130,8 @@ class WuttaTxnItem(WuttaControl):
self.minor_style.color = None self.minor_style.color = None
self.minor_style.decoration = None self.minor_style.decoration = None
if self.row.row_type == self.enum.POS_ROW_TYPE_SELL: if self.row.row_type in (self.enum.POS_ROW_TYPE_SELL,
self.enum.POS_ROW_TYPE_OPEN_RING):
self.quantity.text = self.app.render_quantity(self.row.quantity) self.quantity.text = self.app.render_quantity(self.row.quantity)
self.txn_price.text = self.app.render_currency(self.row.txn_price) self.txn_price.text = self.app.render_currency(self.row.txn_price)
self.sales_total.text = self.app.render_currency(self.row.sales_total) self.sales_total.text = self.app.render_currency(self.row.sales_total)
@ -140,7 +142,8 @@ class WuttaTxnItem(WuttaControl):
self.sales_total_style.decoration = ft.TextDecoration.LINE_THROUGH self.sales_total_style.decoration = ft.TextDecoration.LINE_THROUGH
self.sales_total_style.weight = None self.sales_total_style.weight = None
else: else:
if self.row.txn_price < self.row.reg_price: if (self.row.row_type == self.enum.POS_ROW_TYPE_SELL
and self.row.txn_price < self.row.reg_price):
self.sales_total_style.color = 'blue' self.sales_total_style.color = 'blue'
else: else:
self.sales_total_style.color = None self.sales_total_style.color = None

View file

@ -34,6 +34,7 @@ from .base import WuttaView
from wuttapos.controls.loginform import WuttaLoginForm from wuttapos.controls.loginform import WuttaLoginForm
from wuttapos.controls.custlookup import WuttaCustomerLookup from wuttapos.controls.custlookup import WuttaCustomerLookup
from wuttapos.controls.itemlookup import WuttaProductLookup from wuttapos.controls.itemlookup import WuttaProductLookup
from wuttapos.controls.deptlookup import WuttaDepartmentLookup
from wuttapos.controls.txnitem import WuttaTxnItem from wuttapos.controls.txnitem import WuttaTxnItem
from wuttapos.controls.tenkey import WuttaTenkeyMenu from wuttapos.controls.tenkey import WuttaTenkeyMenu
@ -168,8 +169,7 @@ class POSView(WuttaView):
bgcolor='yellow') bgcolor='yellow')
else: else:
self.add_row_item(row) self.add_row_item(row, scroll=True)
self.items.scroll_to(offset=-1, duration=100)
self.refresh_totals(batch) self.refresh_totals(batch)
self.reset() self.reset()
@ -657,15 +657,16 @@ class POSView(WuttaView):
), ),
ft.Row( ft.Row(
[ [
meta_button("Adjust\nPrice", font_size=30, bgcolor='yellow', meta_button("OPEN RING", font_size=32, bgcolor='blue',
on_click=self.adjust_price_click), on_click=self.open_ring_click),
meta_button("NO SALE", bgcolor='yellow', on_click=self.nosale_click), meta_button("NO SALE", bgcolor='yellow', on_click=self.nosale_click),
], ],
spacing=0, spacing=0,
), ),
ft.Row( ft.Row(
[ [
meta_button("TODO", bgcolor='blue', on_click=self.not_supported), meta_button("Adjust\nPrice", font_size=30, bgcolor='yellow',
on_click=self.adjust_price_click),
meta_button("(TEST ERROR)", bgcolor='red', on_click=self.not_supported, meta_button("(TEST ERROR)", bgcolor='red', on_click=self.not_supported,
font_size=24, data={'error': True}), font_size=24, data={'error': True}),
], ],
@ -856,6 +857,54 @@ class POSView(WuttaView):
self.show_snackbar(text, bgcolor='yellow') self.show_snackbar(text, bgcolor='yellow')
self.page.update() self.page.update()
def open_ring_click(self, e):
value = self.main_input.value or None
if not value:
self.show_snackbar("Must first enter an amount")
self.reset()
return
try:
amount = decimal.Decimal(value)
except decimal.InvalidOperation:
self.show_snackbar("Amount is not valid")
self.reset()
return
def select(uuid):
session = self.app.make_session()
user = self.get_current_user(session)
batch = self.get_current_batch(session, user=user)
handler = self.get_batch_handler()
quantity = 1
if self.set_quantity.data is not None:
quantity = self.set_quantity.data
row = handler.add_open_ring(batch, uuid, amount, quantity=quantity, user=user)
session.commit()
self.add_row_item(row, scroll=True)
self.refresh_totals(batch)
session.close()
dlg.open = False
self.reset()
def cancel(e):
dlg.open = False
self.reset(clear_quantity=False)
dlg = ft.AlertDialog(
modal=True,
title=ft.Text(f"Department Lookup - for {self.app.render_currency(amount)} OPEN RING"),
content=WuttaDepartmentLookup(self.config, on_select=select, on_cancel=cancel),
)
self.page.dialog = dlg
dlg.open = True
self.page.update()
def adjust_price_click(self, e): def adjust_price_click(self, e):
if not len(self.items.controls): if not len(self.items.controls):
@ -1014,10 +1063,11 @@ class POSView(WuttaView):
self.show_snackbar("TODO: Drawer Kick", bgcolor='yellow') self.show_snackbar("TODO: Drawer Kick", bgcolor='yellow')
self.page.update() self.page.update()
def add_row_item(self, row): def add_row_item(self, row, scroll=False):
# TODO: row types ugh # TODO: row types ugh
if row.row_type not in (self.enum.POS_ROW_TYPE_SELL, if row.row_type not in (self.enum.POS_ROW_TYPE_SELL,
self.enum.POS_ROW_TYPE_OPEN_RING,
self.enum.POS_ROW_TYPE_TENDER, self.enum.POS_ROW_TYPE_TENDER,
self.enum.POS_ROW_TYPE_CHANGE_BACK): self.enum.POS_ROW_TYPE_CHANGE_BACK):
return return
@ -1032,6 +1082,9 @@ class POSView(WuttaView):
key=row.uuid, key=row.uuid,
)) ))
if scroll:
self.items.scroll_to(offset=-1, duration=100)
def list_item_click(self, e): def list_item_click(self, e):
self.select_txn_item(e.control) self.select_txn_item(e.control)
@ -1142,7 +1195,8 @@ class POSView(WuttaView):
# cannot void an already void line # cannot void an already void line
self.show_snackbar("LINE ALREADY VOID", bgcolor='yellow') self.show_snackbar("LINE ALREADY VOID", bgcolor='yellow')
elif row.row_type != self.enum.POS_ROW_TYPE_SELL: elif row.row_type not in (self.enum.POS_ROW_TYPE_SELL,
self.enum.POS_ROW_TYPE_OPEN_RING):
# cannot void line unless of type 'sell' # cannot void line unless of type 'sell'
self.show_snackbar("LINE DOES NOT ALLOW VOID", bgcolor='yellow') self.show_snackbar("LINE DOES NOT ALLOW VOID", bgcolor='yellow')
@ -1275,7 +1329,7 @@ class POSView(WuttaView):
# update screen to reflect new items/balance # update screen to reflect new items/balance
for row in rows: for row in rows:
self.add_row_item(row) self.add_row_item(row, scroll=True)
self.refresh_totals(batch) self.refresh_totals(batch)
# executed batch means txn was finalized # executed batch means txn was finalized