Add initial support for Open Ring
This commit is contained in:
parent
fb4206e5a9
commit
2c9f3cd41a
67
wuttapos/controls/deptlookup.py
Normal file
67
wuttapos/controls/deptlookup.py
Normal 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'],
|
||||
]
|
|
@ -41,6 +41,7 @@ class WuttaLookup(WuttaControl):
|
|||
|
||||
def __init__(self, *args, **kwargs):
|
||||
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_cancel = kwargs.pop('on_cancel', None)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
@ -165,7 +166,7 @@ class WuttaLookup(WuttaControl):
|
|||
raise NotImplementedError
|
||||
|
||||
def did_mount(self):
|
||||
if self.initial_search:
|
||||
if self.initial_search is not None:
|
||||
self.searchbox.value = self.initial_search
|
||||
self.initial_search = None # only do it once
|
||||
self.update()
|
||||
|
@ -201,11 +202,11 @@ class WuttaLookup(WuttaControl):
|
|||
raise NotImplementedError
|
||||
|
||||
def make_result_row(self, obj):
|
||||
raise NotImplementedError
|
||||
return obj
|
||||
|
||||
def lookup(self, e=None):
|
||||
entry = self.searchbox.value
|
||||
if not entry:
|
||||
if not entry and not self.allow_empty_query:
|
||||
self.searchbox.focus()
|
||||
self.update()
|
||||
return
|
||||
|
|
|
@ -48,7 +48,8 @@ class WuttaTxnItem(WuttaControl):
|
|||
self.minor_style = ft.TextStyle(size=int(self.font_size * 0.8),
|
||||
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()
|
||||
|
||||
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.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.txn_price.text = self.app.render_currency(self.row.txn_price)
|
||||
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.weight = None
|
||||
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'
|
||||
else:
|
||||
self.sales_total_style.color = None
|
||||
|
|
|
@ -34,6 +34,7 @@ from .base import WuttaView
|
|||
from wuttapos.controls.loginform import WuttaLoginForm
|
||||
from wuttapos.controls.custlookup import WuttaCustomerLookup
|
||||
from wuttapos.controls.itemlookup import WuttaProductLookup
|
||||
from wuttapos.controls.deptlookup import WuttaDepartmentLookup
|
||||
from wuttapos.controls.txnitem import WuttaTxnItem
|
||||
from wuttapos.controls.tenkey import WuttaTenkeyMenu
|
||||
|
||||
|
@ -168,8 +169,7 @@ class POSView(WuttaView):
|
|||
bgcolor='yellow')
|
||||
|
||||
else:
|
||||
self.add_row_item(row)
|
||||
self.items.scroll_to(offset=-1, duration=100)
|
||||
self.add_row_item(row, scroll=True)
|
||||
self.refresh_totals(batch)
|
||||
self.reset()
|
||||
|
||||
|
@ -657,15 +657,16 @@ class POSView(WuttaView):
|
|||
),
|
||||
ft.Row(
|
||||
[
|
||||
meta_button("Adjust\nPrice", font_size=30, bgcolor='yellow',
|
||||
on_click=self.adjust_price_click),
|
||||
meta_button("OPEN RING", font_size=32, bgcolor='blue',
|
||||
on_click=self.open_ring_click),
|
||||
meta_button("NO SALE", bgcolor='yellow', on_click=self.nosale_click),
|
||||
],
|
||||
spacing=0,
|
||||
),
|
||||
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,
|
||||
font_size=24, data={'error': True}),
|
||||
],
|
||||
|
@ -856,6 +857,54 @@ class POSView(WuttaView):
|
|||
self.show_snackbar(text, bgcolor='yellow')
|
||||
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):
|
||||
|
||||
if not len(self.items.controls):
|
||||
|
@ -1014,10 +1063,11 @@ class POSView(WuttaView):
|
|||
self.show_snackbar("TODO: Drawer Kick", bgcolor='yellow')
|
||||
self.page.update()
|
||||
|
||||
def add_row_item(self, row):
|
||||
def add_row_item(self, row, scroll=False):
|
||||
|
||||
# TODO: row types ugh
|
||||
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_CHANGE_BACK):
|
||||
return
|
||||
|
@ -1032,6 +1082,9 @@ class POSView(WuttaView):
|
|||
key=row.uuid,
|
||||
))
|
||||
|
||||
if scroll:
|
||||
self.items.scroll_to(offset=-1, duration=100)
|
||||
|
||||
def list_item_click(self, e):
|
||||
self.select_txn_item(e.control)
|
||||
|
||||
|
@ -1142,7 +1195,8 @@ class POSView(WuttaView):
|
|||
# cannot void an already void line
|
||||
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'
|
||||
self.show_snackbar("LINE DOES NOT ALLOW VOID", bgcolor='yellow')
|
||||
|
||||
|
@ -1275,7 +1329,7 @@ class POSView(WuttaView):
|
|||
|
||||
# update screen to reflect new items/balance
|
||||
for row in rows:
|
||||
self.add_row_item(row)
|
||||
self.add_row_item(row, scroll=True)
|
||||
self.refresh_totals(batch)
|
||||
|
||||
# executed batch means txn was finalized
|
||||
|
|
Loading…
Reference in a new issue