|
@@ -5,7 +5,8 @@
|
|
#
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED AS IS WITHOUT WARRANTY
|
|
# THIS SOFTWARE IS PROVIDED AS IS WITHOUT WARRANTY
|
|
import itertools
|
|
import itertools
|
|
-from typing import Callable, List, Union
|
|
|
|
|
|
+from decimal import Decimal, InvalidOperation
|
|
|
|
+from typing import Callable, Union
|
|
from urwid import (
|
|
from urwid import (
|
|
connect_signal,
|
|
connect_signal,
|
|
AttrMap,
|
|
AttrMap,
|
|
@@ -18,10 +19,9 @@ from urwid import (
|
|
Pile,
|
|
Pile,
|
|
Text,
|
|
Text,
|
|
)
|
|
)
|
|
-from app.activities import ActivityManager
|
|
|
|
-from app.db_utils import QueryManager
|
|
|
|
|
|
|
|
from .. import COPYRIGHT
|
|
from .. import COPYRIGHT
|
|
|
|
+from ..db_utils import QueryManager
|
|
from ..widgets import (
|
|
from ..widgets import (
|
|
AutoCompleteEdit,
|
|
AutoCompleteEdit,
|
|
AutoCompleteFloatEdit,
|
|
AutoCompleteFloatEdit,
|
|
@@ -29,7 +29,8 @@ from ..widgets import (
|
|
AutoCompletePopUp,
|
|
AutoCompletePopUp,
|
|
NoTabCheckBox
|
|
NoTabCheckBox
|
|
)
|
|
)
|
|
-
|
|
|
|
|
|
+from . import ActivityManager
|
|
|
|
+from .Rating import Rating
|
|
|
|
|
|
class TransactionEditor(FocusWidget):
|
|
class TransactionEditor(FocusWidget):
|
|
|
|
|
|
@@ -108,8 +109,31 @@ class TransactionEditor(FocusWidget):
|
|
date or None, store or None
|
|
date or None, store or None
|
|
) else ''
|
|
) else ''
|
|
)
|
|
)
|
|
|
|
+ self.update_historic_prices(self.data)
|
|
return self
|
|
return self
|
|
|
|
|
|
|
|
+ def update_historic_prices(self, data):
|
|
|
|
+ organic = None if data['organic'] == 'mixed' else data['organic']
|
|
|
|
+ #sort = '$/unit' if self.buttons['sort_price'].state else 'ts'
|
|
|
|
+ product, unit = data['product'] or None, data['unit'] or None
|
|
|
|
+ try:
|
|
|
|
+ price = Decimal(data['price'])
|
|
|
|
+ except InvalidOperation:
|
|
|
|
+ price = None
|
|
|
|
+
|
|
|
|
+ try:
|
|
|
|
+ quantity = Decimal(data['quantity'])
|
|
|
|
+ except InvalidOperation:
|
|
|
|
+ quantity = None
|
|
|
|
+
|
|
|
|
+ if None in (product, unit):
|
|
|
|
+ return
|
|
|
|
+
|
|
|
|
+ df = self.query_manager.get_historic_prices_data(unit, product=product, organic=organic)
|
|
|
|
+ _avg, _min, _max = [ x for x in df[['avg','min','max']].iloc[0].apply(float) ]
|
|
|
|
+ self.rating.update_rating(_avg, _min, _max, unit, price=price, quantity=quantity),
|
|
|
|
+
|
|
|
|
+
|
|
def focus_on_product(self):
|
|
def focus_on_product(self):
|
|
path = self.container.get_focus_path()
|
|
path = self.container.get_focus_path()
|
|
while path != [2,0,1,0,0]:
|
|
while path != [2,0,1,0,0]:
|
|
@@ -145,8 +169,15 @@ class TransactionEditor(FocusWidget):
|
|
'organic': NoTabCheckBox(('bg', "Organic"), state='mixed'),
|
|
'organic': NoTabCheckBox(('bg', "Organic"), state='mixed'),
|
|
}
|
|
}
|
|
self.text_fields = {
|
|
self.text_fields = {
|
|
- 'dbview': Text('')
|
|
|
|
|
|
+ 'dbview': Text(''),
|
|
|
|
+ 'rating': Text(''),
|
|
|
|
+ 'spread': Text(''),
|
|
|
|
+ 'marker': Text(''),
|
|
}
|
|
}
|
|
|
|
+ self.rating = Rating(dict(filter(
|
|
|
|
+ lambda x: x[0] in ('spread','rating','marker'),
|
|
|
|
+ self.text_fields.items()
|
|
|
|
+ )))
|
|
self.organic_checkbox = self.checkboxes['organic']
|
|
self.organic_checkbox = self.checkboxes['organic']
|
|
connect_signal(self.organic_checkbox, 'postchange', lambda _,v: self.update())
|
|
connect_signal(self.organic_checkbox, 'postchange', lambda _,v: self.update())
|
|
layout = [
|
|
layout = [
|
|
@@ -163,9 +194,18 @@ class TransactionEditor(FocusWidget):
|
|
'description',
|
|
'description',
|
|
'dbview',
|
|
'dbview',
|
|
]
|
|
]
|
|
|
|
+ badge = [
|
|
|
|
+ 'rating',
|
|
|
|
+ 'spread',
|
|
|
|
+ 'marker',
|
|
|
|
+ ]
|
|
self.clear()
|
|
self.clear()
|
|
- widgets = dict()
|
|
|
|
- widgets.update({
|
|
|
|
|
|
+ _widgets = dict(itertools.chain(*[
|
|
|
|
+ [(k, v) for k,v in x] for x in map(lambda x: x.items(), [
|
|
|
|
+ self.edit_fields, self.text_fields, self.checkboxes
|
|
|
|
+ ])
|
|
|
|
+ ]))
|
|
|
|
+ _widgets.update({
|
|
'dbview': LineBox(
|
|
'dbview': LineBox(
|
|
AttrMap(self.text_fields['dbview'], 'streak'),
|
|
AttrMap(self.text_fields['dbview'], 'streak'),
|
|
title="Session Data",
|
|
title="Session Data",
|
|
@@ -176,7 +216,7 @@ class TransactionEditor(FocusWidget):
|
|
connect_signal(ef, 'postchange', lambda _,v: self.update())
|
|
connect_signal(ef, 'postchange', lambda _,v: self.update())
|
|
connect_signal(ef, 'apply', lambda w, name: autocomplete_cb(w, name, self.data))
|
|
connect_signal(ef, 'apply', lambda w, name: autocomplete_cb(w, name, self.data))
|
|
|
|
|
|
- widgets.update(dict([
|
|
|
|
|
|
+ _widgets.update(dict([
|
|
(k, LineBox(
|
|
(k, LineBox(
|
|
AttrMap(AutoCompletePopUp(
|
|
AttrMap(AutoCompletePopUp(
|
|
self.edit_fields[k],
|
|
self.edit_fields[k],
|
|
@@ -188,10 +228,27 @@ class TransactionEditor(FocusWidget):
|
|
header = Text(u'Fill Transaction', 'center')
|
|
header = Text(u'Fill Transaction', 'center')
|
|
_copyright = Text(COPYRIGHT, 'center')
|
|
_copyright = Text(COPYRIGHT, 'center')
|
|
|
|
|
|
- components = dict()
|
|
|
|
- components['bottom_pane'] = Columns(
|
|
|
|
- [(8, self.buttons['done']), Divider(), (9, self.buttons['clear'])]
|
|
|
|
- )
|
|
|
|
|
|
+ components = {
|
|
|
|
+ 'bottom_button_bar': Columns(
|
|
|
|
+ [(8, self.buttons['done']), Divider(), (9, self.buttons['clear'])]
|
|
|
|
+ ),
|
|
|
|
+ 'badge': Pile(map(
|
|
|
|
+ lambda x: _widgets[x] if x is not None else Divider,
|
|
|
|
+ badge
|
|
|
|
+ )),
|
|
|
|
+ }
|
|
|
|
+ components.update({
|
|
|
|
+ 'bottom_pane': Columns([
|
|
|
|
+ Pile(map(
|
|
|
|
+ lambda x: _widgets[x] if x is not None else Divider(),
|
|
|
|
+ bottom_pane
|
|
|
|
+ )),
|
|
|
|
+ (50, Pile([LineBox(
|
|
|
|
+ AttrMap(components['badge'], 'badge'),
|
|
|
|
+ title="Current Price", title_align='left',
|
|
|
|
+ )])),
|
|
|
|
+ ])
|
|
|
|
+ })
|
|
connect_signal(self.buttons['done'], 'click', lambda _: save_and_clear_cb())
|
|
connect_signal(self.buttons['done'], 'click', lambda _: save_and_clear_cb())
|
|
connect_signal(self.buttons['clear'], 'click', lambda _: self.clear())
|
|
connect_signal(self.buttons['clear'], 'click', lambda _: self.clear())
|
|
|
|
|
|
@@ -200,7 +257,7 @@ class TransactionEditor(FocusWidget):
|
|
Padding(_copyright, 'center', width=('relative', 100)),
|
|
Padding(_copyright, 'center', width=('relative', 100)),
|
|
])
|
|
])
|
|
banner = AttrMap(banner, 'banner')
|
|
banner = AttrMap(banner, 'banner')
|
|
- widgets.update({
|
|
|
|
|
|
+ _widgets.update({
|
|
'product': LineBox(Columns([
|
|
'product': LineBox(Columns([
|
|
AttrMap(AutoCompletePopUp(
|
|
AttrMap(AutoCompletePopUp(
|
|
self.edit_fields['product'],
|
|
self.edit_fields['product'],
|
|
@@ -211,30 +268,32 @@ class TransactionEditor(FocusWidget):
|
|
], dividechars=2), title='Product', title_align='left')
|
|
], dividechars=2), title='Product', title_align='left')
|
|
})
|
|
})
|
|
|
|
|
|
- side_pane_widget = (12, Pile([
|
|
|
|
- widgets[r] if r is not None else Divider() for r in side_pane
|
|
|
|
|
|
+ components['side_pane'] = (12, Pile([
|
|
|
|
+ _widgets[r] if r is not None else Divider() for r in side_pane
|
|
]))
|
|
]))
|
|
- main_pane_widgets = []
|
|
|
|
- for i, r in enumerate(layout):
|
|
|
|
- _widgets = []
|
|
|
|
|
|
+ components['main_pane'] = []
|
|
|
|
+ for _, r in enumerate(layout):
|
|
|
|
+ col = []
|
|
for c in r:
|
|
for c in r:
|
|
if c is not None:
|
|
if c is not None:
|
|
if c == 'organic':
|
|
if c == 'organic':
|
|
continue
|
|
continue
|
|
- _widgets.append(widgets[c])
|
|
|
|
|
|
+ col.append(_widgets[c])
|
|
else:
|
|
else:
|
|
- _widgets.append(Divider())
|
|
|
|
- main_pane_widgets.append(Columns(_widgets))
|
|
|
|
|
|
+ col.append(Divider())
|
|
|
|
+ components['main_pane'].append(Columns(col))
|
|
|
|
|
|
|
|
+ components['main_pane'] = Pile(components['main_pane'])
|
|
|
|
+
|
|
widget = Pile([
|
|
widget = Pile([
|
|
banner,
|
|
banner,
|
|
Divider(),
|
|
Divider(),
|
|
Columns([
|
|
Columns([
|
|
- Pile(main_pane_widgets), side_pane_widget
|
|
|
|
|
|
+ components['main_pane'], components['side_pane']
|
|
], dividechars=2),
|
|
], dividechars=2),
|
|
- *[ widgets[c] if c is not None else Divider() for c in bottom_pane ],
|
|
|
|
|
|
+ components['bottom_pane'],
|
|
Divider(),
|
|
Divider(),
|
|
- components['bottom_pane']
|
|
|
|
|
|
+ components['bottom_button_bar']
|
|
])
|
|
])
|
|
widget = Filler(widget, 'top')
|
|
widget = Filler(widget, 'top')
|
|
widget = AttrMap(widget, 'bg')
|
|
widget = AttrMap(widget, 'bg')
|