Initial commit; basic proof of concept showing trainwreck data

This commit is contained in:
Lance Edgar 2021-12-16 21:39:58 -06:00
commit 1531ad1879
12 changed files with 1101 additions and 0 deletions

29
rattail_dash/__init__.py Normal file
View file

@ -0,0 +1,29 @@
# -*- coding: utf-8; -*-
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2021 Lance Edgar
#
# This file is part of Rattail.
#
# Rattail 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.
#
# Rattail 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
# Rattail. If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
"""
Dash App Interface
"""
from __future__ import unicode_literals, absolute_import
from ._version import __version__

3
rattail_dash/_version.py Normal file
View file

@ -0,0 +1,3 @@
# -*- coding: utf-8; -*-
__version__ = u'0.1.0'

45
rattail_dash/commands.py Normal file
View file

@ -0,0 +1,45 @@
# -*- coding: utf-8; -*-
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2021 Lance Edgar
#
# This file is part of Rattail.
#
# Rattail 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.
#
# Rattail 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
# Rattail. If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
"""
Rattail Commands
"""
from __future__ import unicode_literals, absolute_import
from rattail import commands
class RunDashApp(commands.Subcommand):
"""
Run a Dash web app
"""
name = 'run-dashapp'
description = __doc__.strip()
def run(self, args):
# TODO: let command line or config determine which app to run;
# also whether it should run in debug mode etc.
from rattail_dash.dashapp.sample import sample_dash_app
dashapp = sample_dash_app(self.config)
dashapp.run_server(debug=True)

View file

View file

@ -0,0 +1,85 @@
# -*- coding: utf-8; -*-
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2021 Lance Edgar
#
# This file is part of Rattail.
#
# Rattail 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.
#
# Rattail 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
# Rattail. If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
"""
Dash App "Base"
"""
from __future__ import unicode_literals, absolute_import
import datetime
import six
import dash
import pandas as pd
def make_basic_dash_app(config):
"""
Make and return a simple Dash app.
:param config: Rattail config object.
"""
dashapp = dash.Dash(__name__)
# dashapp.rattail_config = config
return dashapp
def make_trainwreck_dataframe(config, date):
"""
Make and return a simple dataframe for use with a Dash app,
containing data from Trainwreck.
:param date: Either a ``datetime.date`` object, or a string in
YYYY-MM-DD format.
"""
app = config.get_app()
if not isinstance(date, datetime.date):
date = datetime.datetime.strptime(date, '%Y-%m-%d').date()
start_time = datetime.datetime.combine(date, datetime.time(0))
start_time = app.localtime(start_time)
end_time = datetime.datetime.combine(date + datetime.timedelta(days=1),
datetime.time(0))
end_time = app.localtime(end_time)
# TODO: maybe inspect date and use different year engine
trainwreck_engine = config.trainwreck_engine
# TODO: should transform timezone after fetch? this is surely quicker though
df = pd.read_sql(
"""
SELECT end_time AT TIME ZONE 'UTC' AT TIME ZONE %(timezone)s as end_time,
terminal_id, subtotal
FROM transaction
WHERE end_time >= %(start_time)s AT TIME ZONE 'UTC' AT TIME ZONE %(timezone)s
AND end_time < %(end_time)s AT TIME ZONE 'UTC' AT TIME ZONE %(timezone)s
ORDER BY end_time, terminal_id
""",
trainwreck_engine,
params={'timezone': six.text_type(app.get_timezone()),
'start_time': start_time,
'end_time': end_time})
return df

View file

@ -0,0 +1,126 @@
# -*- coding: utf-8; -*-
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2021 Lance Edgar
#
# This file is part of Rattail.
#
# Rattail 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.
#
# Rattail 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
# Rattail. If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
"""
Sample Dash App
"""
from __future__ import unicode_literals, absolute_import
import pandas as pd
from dash import dcc, html
from dash.dependencies import Input, Output
import plotly.express as px
from . import base
def sample_dash_app(config):
"""
Make and return a "complete" sample Dash app. Just for sake of a
basic demo at this point.
"""
app = config.get_app()
dashapp = base.make_basic_dash_app(config)
# colors = {
# # 'background': '#111111',
# 'background': '#333333',
# 'text': '#7FDBFF'
# }
# this date will be initially displayed, by default
date = app.localtime().date()
empty_frame = pd.DataFrame(columns=['end_time',
'terminal_id',
'subtotal'])
fig = px.bar(empty_frame, x="terminal_id", y="subtotal",
barmode="group")
fig2 = px.line(empty_frame, x='end_time', y='subtotal')
dashapp.layout = html.Div([
html.H1("Hello {}".format(config.app_title()),
style={
'textAlign': 'center',
# 'color': colors['text']
}),
html.Div([
html.P([
html.Span("""
This is just a sample dashboard (feature preview) built
with Dash + Rattail. (
"""),
html.A('https://dash.plot.ly/', href='https://dash.plot.ly/'),
html.Span(' )'),
],
# style={'color': colors['text']},
),
html.P([
html.Span("Below we are showing some transaction data from: "),
# html.Span(app.render_date(date)),
html.Span(id='current-date'),
]),
], style={'textAlign': 'center',
# 'color': colors['text'],
}),
dcc.DatePickerSingle(id='mydatepicker',
initial_visible_month=date,
date=date.strftime('%Y-%m-%d')),
dcc.Graph(
id='example-graph',
figure=fig
),
dcc.Graph(
id='example-graph2',
figure=fig2
),
],
# style={'backgroundColor': colors['background']},
)
@dashapp.callback(Output('current-date', 'children'),
Input('mydatepicker', 'date'))
def update_date_display(date):
return date
@dashapp.callback(Output('example-graph', 'figure'),
Output('example-graph2', 'figure'),
Input('mydatepicker', 'date'))
def update_fig1(date):
df = base.make_trainwreck_dataframe(config, date)
fig = px.bar(df, x="terminal_id", y="subtotal",
barmode="group")
fig2 = px.line(df, x='end_time', y='subtotal')
return fig, fig2
return dashapp