Alright, try this, this should reload upon refresh:
'''
*** Projeto dentro da pasta ProjetoDash ***
pip install openpyxl
pip3 install psycopg2
pip3 install peewee
pip3 install dash
pip3 install pandas
pip install dash-bootstrap-components
pip install dash-bootstrap-templates
https://docs.microsoft.com/en-GB/cpp/windows/latest-supported-vc-redist?view=msvc-170
No PowerShell rode o comando:
Set-ExecutionPolicy Unrestricted
'''
import plotly.graph_objs as go
import dash
from dash import html, dcc, Input, Output, State
from dash import html, dash_table
import dash_bootstrap_components as dbc
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import pandas as pd
from dash_bootstrap_templates import ThemeSwitchAIO
# Importei meu dataframe do arquivo movimento_geral.py
from movimento_geral import df_dados_gerais # , df_pivot
# Formatação das tabelas
formatted = {'specifier': ',.2f', 'locale': {'group': '.', 'decimal': ',', }}
# Note que são muitos os dados, isso deve ser fitrado por ANO mas por enquanto limito o número de linhas com .head(15)
# este não é um gráfico adequado para mostrar nomes de produtos.
# print(df_dados_gerais_bar.head(15))
# import theme changer
from dash_bootstrap_templates import ThemeSwitchAIO
# ================================================================== #
from flask import Flask
dbc_css = "https://cdn.jsdelivr.net/gh/AnnMarieW/dash-bootstrap-templates/dbc.min.css"
server = Flask(__name__)
app = dash.Dash(__name__, server=server, suppress_callback_exceptions=True,
external_stylesheets=[dbc.themes.BOOTSTRAP, dbc_css])
# ============================Styles================================ #
tab_card = {'height': '100%'}
main_config = {
'hovermode': 'x unified',
'legend': {
'yanchor': 'top',
'y': 0.9,
'xanchor': 'left',
'x': 0.1,
'title': {'text': None},
'font': {'color': 'white'},
'bgcolor': 'rgba(0,0,0,0.0)'},
'margin': {'l': 0, 'r': 0, 't': 20, 'b': 0}
}
# Aparência do sistema, cuidado com a ordem do Template_theme1 e 2
# em relação a url_teme
template_theme1 = 'cyborg'
template_theme2 = 'spacelab'
url_theme1 = dbc.themes.CYBORG
url_theme2 = dbc.themes.SPACELAB
def layout():
# Separando Cidades + Global
s1_cidade_bairros = df_dados_gerais.groupby(['CIDADE', 'BAIRRO'])['TOTAL_OPERACAO'].sum().reset_index()
s2_todos = pd.DataFrame()
s2_todos['CIDADE'] = ['TODAS']
s2_todos['BAIRRO'] = ['TODOS']
s2_todos['TOTAL_OPERACAO'] = [0]
cidade_bairros = pd.concat([s1_cidade_bairros, s2_todos], ignore_index=True)
# To dict - Para salvar no dcc.store
df_store = df_dados_gerais.to_dict()
graficos = [
# Row 1
# Row 4
# Row Single Card
dbc.Row([
dbc.Col([
dbc.Card([
dbc.CardBody([
dcc.Graph(id='graph0', className='dbc', config={"displayModeBar": False, "showTips": False})
])
], style=tab_card)
], sm=12, lg=12)
], className='g-2 my-auto', style={'margin-top': '7px'}),
# Row 3
dbc.Row([
dbc.Col([
dbc.Card([
dbc.CardBody([
html.H4("Top 10 em valor de venda, em Reais", style={"font-weight": "bold"}),
dcc.Graph(id='graph1', className='dbc', config={"displayModeBar": False, "showTips": False})
])
], style=tab_card)
], sm=12, lg=4, style={'margin-top': '7px'}),
# Card 2
dbc.Col([
dbc.Row([
dbc.Col([
dbc.Card([
dbc.CardBody([
dcc.Graph(id='graph2', className='dbc', config={"displayModeBar": False, "showTips": False})
])
], style=tab_card)
])
]),
dbc.Row([
dbc.Col([
dbc.Card([
dbc.Row([
dbc.Col([
dcc.Graph(id='graph3', className='dbc',
config={"displayModeBar": False, "showTips": False})
])
])
], style=tab_card)
], sm=12, lg=4),
dbc.Col([
dbc.Card([
dbc.Row([
dbc.Col([
dcc.Graph(id='graph4', className='dbc',
config={"displayModeBar": False, "showTips": False})
])
])
], style=tab_card)
], sm=12, lg=4),
dbc.Col([
dbc.Card([
dbc.CardBody([
# dbc.Row([
# dbc.Col([
# html.H5('Filtro por Gênero'),
# dcc.Graph(id='graph44', className='dbc', config={"displayModeBar": False, "showTips": False})
# ])
# ])
])
], style=tab_card)
], sm=12, lg=4)
], className='g-2 my-auto')
], sm=12, lg=8)
], justify='center', className='g-2 my-auto'),
]
tabelas = html.Div(
[
dash_table.DataTable(
id='datatable-data',
editable=True,
filter_action="native",
sort_action="native",
# style_cell={'textAlign': 'left'},
# style_cell={
# 'minWidth': 95, 'maxWidth': 95, 'width': 95
# },
fixed_rows={'headers': True},
style_cell_conditional=[
{
'if': {'column_id': 'CODIGO'},
'textAlign': 'left'
},
{
'if': {'column_id': 'CODIGO'},
'width': '80px'
},
{
'if': {'column_id': 'ESTOQUE'},
'width': '130px'
},
{
'if': {'column_id': 'UNIDADE'},
'width': '80px'
},
{
'if': {'column_id': 'DESCRICAO'},
'textAlign': 'left', 'width': '230px'
},
{
'if': {'column_id': 'GRUPO'},
'textAlign': 'left'
},
{
'if': {'column_id': 'FAMILIA'},
'textAlign': 'left'
},
{
'if': {'column_id': 'UNIDADE'},
'textAlign': 'left'
},
],
style_data={
'color': 'black',
'backgroundColor': 'white'
},
style_data_conditional=[
{
'if': {'row_index': 'odd'},
'backgroundColor': 'rgb(220, 220, 220)',
}
],
# 'backgroundColor': 'white',
style_header={'textAlign': 'center',
'backgroundColor': 'rgb(210, 210, 210)',
'color': 'black',
'fontWeight': 'bold'},
style_table={'height': '300px', 'overflowY': 'auto'},
page_size=100,
)
], className="dbc dbc-row-selectable"
)
return dbc.Container([
dcc.Store(id='dataset', data=df_store),
dbc.Row([
dbc.Col([
dbc.Card([
dbc.CardBody([
dbc.Row([
dbc.Col([
html.Legend("Bag Sales Metrics")
], sm=9),
# dbc.Col([
# html.I(className='fa fa-gamepad', style={'font-size': '300%'})
# ], sm=3, align="left")
]),
dbc.Row([
dbc.Col([
ThemeSwitchAIO(aio_id="theme", themes=[url_theme1, url_theme2]),
html.Legend("Rika Embalagens")
])
], style={'margin-top': '10px'}),
dbc.Row([
dbc.Button("Visite o Site", href="https://ajuda.alterdata.com.br/suporteexpress",
target="_blank")
], style={'margin-top': '10px'})
])
], style=tab_card)
], sm=12, lg=3),
dbc.Col([
dbc.Row([
dbc.Col([
dbc.Card([
dbc.CardBody([
dbc.Col([
# html.H5('Escolha o ano da sua pesquisa.', style={"font-weight": "bold"}),
dbc.Label("Escolha o ano da sua pesquisa."),
dcc.Slider(id='year-slider',
min=int(df_dados_gerais['ANO'][1]),
max=int(df_dados_gerais['ANO'].max()),
marks={str(year): str(year) for year in
sorted(df_dados_gerais['ANO'].unique())},
value=int(df_dados_gerais['ANO'].max()) - 1,
step=None,
tooltip={'always_visible': False, 'placement': 'bottom'},
className="mb-2"),
], sm=12, style={'margin-top': '7px'}),
])
], style=tab_card)
])
]),
dbc.Row([
dbc.Col([
dbc.Card([
dbc.CardBody([
dbc.Col([
dbc.Label("Marque os mezes de sua pesquisa."),
dbc.Checklist(
options=[
{"label": "JAN", "value": 1},
{"label": "FEV", "value": 2},
{"label": "MAR", "value": 3},
{"label": "ABR", "value": 4},
{"label": "MAI", "value": 5},
{"label": "JUN", "value": 6},
{"label": "JUL", "value": 7},
{"label": "AGO", "value": 8},
{"label": "SET", "value": 9},
{"label": "OUT", "value": 10},
{"label": "NOV", "value": 11},
{"label": "DEZ", "value": 12},
],
value=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
id="check-inline-mes",
inline=True,
# switch=True,
),
], style={'margin-top': '7px'})
])
], style=tab_card)
], sm=12, lg=12),
], className='g-2 my-auto')
], sm=12, lg=9)
], className='g-2 my-auto', style={'margin-top': '7px'}),
# Row 2
dbc.Row([
dbc.Col([
dbc.Card([
dbc.CardBody([
dbc.Row([
dbc.Col([
html.H5('Filtro por Cidade', style={"font-weight": "bold"}),
dcc.Dropdown(id='drop-cidade', multi=True, value=['TODAS', ],
options=[{'label': name, 'value': name} for name in
cidade_bairros['CIDADE'].unique()], className='dbc'),
])
])
])
], style=tab_card)
], sm=12, lg=6),
dbc.Col([
dbc.Card([
dbc.CardBody([
dbc.Row([
dbc.Col([
html.H5('Filtro por Bairro', style={"font-weight": "bold"}),
dcc.Dropdown(id='drop-bairro', multi=True, value=['TODOS', ], className='dbc'),
])
])
])
], style=tab_card)
], sm=12, lg=6),
], className='g-2 my-auto', style={'margin-top': '7px'}),
dbc.Row([
dbc.Col([
dbc.Tabs(
[
dbc.Tab(
label="Gráficos", activeTabClassName="fw-bold fst-italic",
# active_tab_style={"textTransform": "uppercase"},
children=html.Div(graficos, className="p-4 border"),
),
dbc.Tab(
label="Tabelas", activeTabClassName="fw-bold fst-italic",
# active_tab_style={"textTransform": "uppercase"},
# label="tab 2", active_label_style={"color": "#FB79B3"}
children=html.Div(tabelas, className="p-4 border"),
),
], className="dbc",
),
], sm=12, lg=12)
], className='g-2 my-auto', style={'margin-top': '7px'})
], fluid=True, style={'height': '100vh'})
# Layout
app.layout = layout()
# * * * * * A FAZER * * * * *
# 1 - Adicionar filtro de canceladas.
# 2 - Adicionar check "Marca todas" nos meses.
# 3 - Adicionar Painel de valores:
# a) Vendas
# b) Devolução
# c) Compras
# a) Entradas
# ======== Callbacks ========== #
@app.callback(
Output('drop-bairro', 'options'),
Input('drop-cidade', 'value'))
def set_cities_options(selected_country):
mask = cidade_bairros['CIDADE'].isin(selected_country)
df_cidade_bairros = cidade_bairros.loc[mask]
return [{'label': i, 'value': i} for i in df_cidade_bairros['BAIRRO'].unique()]
# Pie Charts
@app.callback(
Output('graph0', 'figure'),
Input('year-slider', 'value'),
Input('drop-cidade', 'value'),
Input('check-inline-mes', 'value'),
Input(ThemeSwitchAIO.ids.switch("theme"), "value"),
Input('drop-bairro', 'value')
)
def graph0(date, dropdown_cidade, mes, toggle, dropdown_bairro):
template = template_theme1 if toggle else template_theme2
if 'TODAS' in dropdown_cidade:
mask = (df_dados_gerais['ANO'] == date) & (df_dados_gerais['MES'].isin(mes)) & (
df_dados_gerais['CANCELADO'] != '*')
else:
mask = (df_dados_gerais['ANO'] == date) & (df_dados_gerais['CIDADE'].isin(dropdown_cidade)) & \
(df_dados_gerais['BAIRRO'].isin(dropdown_bairro)) & (df_dados_gerais['MES'].isin(mes)) & (
df_dados_gerais['CANCELADO'] != '*')
df_subplot = df_dados_gerais.loc[mask]
# Cria o mask de df_dados_gerais e faz os filtros
# procura em df_dados_gerais as cidades do dropdown
# cria novo objeto df_subplot recebendo o que aparecer de df_dados_gerais.loc[mask]
df_groups_v = df_subplot[df_subplot['OPERACAO'] == 'V'].groupby(['GRUPO'])[['TOTAL_OPERACAO']].sum()
df_groups_v = df_groups_v.reset_index()
df_groups_v.sort_values(by=['TOTAL_OPERACAO'], ascending=False, inplace=True)
# df_subplot.to_excel('C:/Users/EliasPai/Desktop/df_groups.xlsx')
df_groups_s = df_subplot[df_subplot['OPERACAO'] == 'S'].groupby(['GRUPO'])[['TOTAL_OPERACAO']].sum()
df_groups_s = df_groups_s.reset_index()
df_groups_s.sort_values(by=['TOTAL_OPERACAO'], ascending=False, inplace=True)
df_groups_c = df_subplot[df_subplot['OPERACAO'] == 'C'].groupby(['GRUPO'])[['TOTAL_OPERACAO']].sum()
df_groups_c = df_groups_c.reset_index()
df_groups_c.sort_values(by=['TOTAL_OPERACAO'], ascending=False, inplace=True)
df_groups_e = df_subplot[df_subplot['OPERACAO'] == 'E'].groupby(['GRUPO'])[['TOTAL_OPERACAO']].sum()
df_groups_e = df_groups_e.reset_index()
df_groups_e.sort_values(by=['TOTAL_OPERACAO'], ascending=False, inplace=True)
subplot_topgames = make_subplots(rows=1, cols=4,
specs=[[{"type": "pie"}, {"type": "pie"}, {"type": "pie"}, {"type": "pie"}]],
subplot_titles=(
"<b>Vendas</b>", "<b>Saídas</b>", "<b>Compras</b>", "<b>Entradas</b>"))
values_v = df_groups_v['TOTAL_OPERACAO']
subplot_topgames.add_trace(go.Pie(
labels=df_groups_v['GRUPO'], values=values_v, hole=.2), row=1, col=1)
subplot_topgames.add_trace(go.Pie(
labels=df_groups_s['GRUPO'], values=df_groups_s['TOTAL_OPERACAO'], hole=.2), row=1, col=2)
subplot_topgames.add_trace(go.Pie(
labels=df_groups_c['GRUPO'], values=df_groups_c['TOTAL_OPERACAO'], hole=.2), row=1, col=3)
subplot_topgames.add_trace(go.Pie(
labels=df_groups_e['GRUPO'], values=df_groups_e['TOTAL_OPERACAO'], hole=.2), row=1, col=4)
subplot_topgames.update_layout(margin={"l": 0, "r": 0, "t": 20, "b": 0}, height=200, template=template)
return subplot_topgames
# --------------------------------------------------------------------------------------------
# Graph1 - Horizontal Bars
@app.callback(
Output('graph1', 'figure'),
Input('year-slider', 'value'),
Input('drop-cidade', 'value'),
Input('check-inline-mes', 'value'),
Input(ThemeSwitchAIO.ids.switch("theme"), "value"),
Input('drop-bairro', 'value')
)
def fig1(date, dropdown_cidade, mes, toggle, dropdown_bairro):
template = template_theme1 if toggle else template_theme2
if 'TODAS' in dropdown_cidade:
mask = (df_dados_gerais['ANO'] == date) & (df_dados_gerais['OPERACAO'] == 'V') & \
(df_dados_gerais['MES'].isin(mes)) & (df_dados_gerais['CANCELADO'] != '*')
else:
mask = (df_dados_gerais['ANO'] == date) & (df_dados_gerais['OPERACAO'] == 'V') & \
(df_dados_gerais['CIDADE'].isin(dropdown_cidade)) & (df_dados_gerais['BAIRRO'].isin(dropdown_bairro)) & \
(df_dados_gerais['MES'].isin(mes)) & (df_dados_gerais['CANCELADO'] != '*')
df_topglobal = df_dados_gerais.loc[mask]
df_topglobal = df_topglobal.groupby(['DESCRICAO'])[['TOTAL_OPERACAO']].sum()
df_topglobal = df_topglobal.reset_index()
df_topglobal.sort_values(by=['TOTAL_OPERACAO'], ascending=False, inplace=True)
df_topglobal = df_topglobal.head(10).sort_values(by=['TOTAL_OPERACAO'])
# df_topglobal.to_excel('C:/Users/EliasPai/Desktop/2021.xlsx')
text = [f'{x} - R${y:_.2f} '.replace('.', ',').replace('_', '.') for x, y in
zip(df_topglobal['DESCRICAO'].unique(), df_topglobal['TOTAL_OPERACAO'].unique())]
fig = go.Figure(go.Bar(x=df_topglobal['TOTAL_OPERACAO'], y=df_topglobal['DESCRICAO'], orientation='h', text=text))
fig.update_layout(main_config, height=310, xaxis={'title': None, 'showticklabels': False},
yaxis={'title': None, 'showticklabels': False}, template=template)
return fig
# Graph 2 - Line Chart
@app.callback(
Output('graph2', 'figure'),
Input('year-slider', 'value'),
Input('drop-cidade', 'value'),
Input('check-inline-mes', 'value'),
Input(ThemeSwitchAIO.ids.switch("theme"), "value"),
Input('drop-bairro', 'value')
)
def long(date, dropdown_cidade, mes, toggle, dropdown_bairro):
template = template_theme1 if toggle else template_theme2
if 'TODAS' in dropdown_cidade:
mask = (df_dados_gerais['ANO'] == date) & (df_dados_gerais['OPERACAO'] == 'V') & \
(df_dados_gerais['MES'].isin(mes)) & (df_dados_gerais['CANCELADO'] != '*')
else:
mask = (df_dados_gerais['ANO'] == date) & (df_dados_gerais['OPERACAO'] == 'V') & \
(df_dados_gerais['CIDADE'].isin(dropdown_cidade)) & (df_dados_gerais['BAIRRO'].isin(dropdown_bairro)) & \
(df_dados_gerais['MES'].isin(mes)) & (df_dados_gerais['CANCELADO'] != '*')
df_anos = df_dados_gerais.loc[mask]
trace = df_anos.groupby('MES')['TOTAL_OPERACAO'].sum().reset_index()
trace['MES'] = trace['MES'].map({1: 'JAN',
2: 'FEV',
3: 'MAR',
4: 'ABR',
5: 'MAI',
6: 'JUN',
7: 'JUL',
8: 'AGO',
9: 'SET',
10: 'OUT',
11: 'NOV',
12: 'DEZ'},
na_action=None)
fig_anos = go.Figure(go.Scatter(x=trace['MES'], y=trace['TOTAL_OPERACAO'], mode='lines+markers', fill='tonexty',
name='Global Sales'))
fig_anos.update_layout(main_config, height=200, xaxis={'title': 'None'}, yaxis={'title': None}, template=template)
fig_anos.add_annotation(text=f'Vendas em Reais de {date}',
xref="paper", yref="paper",
font=dict(
size=20,
color='white'
),
align="center", bgcolor="rgba(0,0,0,0.8)", opacity=0.8,
x=0.5, y=0.5, showarrow=False)
return fig_anos
# Indicator 1 and 2
@app.callback(
Output('graph3', 'figure'),
Output('graph4', 'figure'),
Input('year-slider', 'value'),
Input('drop-cidade', 'value'),
Input('check-inline-mes', 'value'),
Input(ThemeSwitchAIO.ids.switch("theme"), "value"),
Input('drop-bairro', 'value')
)
def ind1(date, dropdown_cidade, mes, toggle, dropdown_bairro):
template = template_theme1 if toggle else template_theme2
if 'TODAS' in dropdown_cidade:
mask = (df_dados_gerais['ANO'] == date) & (df_dados_gerais['OPERACAO'] == 'V') & \
(df_dados_gerais['MES'].isin(mes)) & (df_dados_gerais['CANCELADO'] != '*')
else:
mask = (df_dados_gerais['ANO'] == date) & (df_dados_gerais['OPERACAO'] == 'V') & \
(df_dados_gerais['CIDADE'].isin(dropdown_cidade)) & (df_dados_gerais['BAIRRO'].isin(dropdown_bairro)) & \
(df_dados_gerais['MES'].isin(mes)) & (df_dados_gerais['CANCELADO'] != '*')
df_graph3 = df_graph4 = df_dados_gerais.loc[mask]
df_graph3 = df_graph3.groupby('MES')['TOTAL_OPERACAO'].sum().reset_index()
df_graph4 = df_graph4.groupby('CIDADE')['TOTAL_OPERACAO'].sum().reset_index()
value1 = df_graph3['TOTAL_OPERACAO'].max()
name1 = df_graph3.loc[df_graph3['TOTAL_OPERACAO'].idxmax()]['MES']
value2 = df_graph4['TOTAL_OPERACAO'].max()
name2 = df_graph4.loc[df_graph4['TOTAL_OPERACAO'].idxmax()]['CIDADE']
fig1 = go.Figure()
fig2 = go.Figure()
# R${y:_.2f} '.replace('.', ',').replace('_', '.') ***** FORMATO DOS NÚMEROS *****
fig1.add_trace(go.Indicator(
mode="number",
title={
"text": f"<span style='font-size:100%'>{name1} - Melhor venda</span><br><span style='font-size:70%'>Em Reais</span><br><span style='font-size:0.7em'>{df_dados_gerais['ANO'][1]} - {df_dados_gerais['ANO'].max()}</span>"},
value=value1,
number={'valueformat': '.2f'}
))
fig2.add_trace(go.Indicator(
mode="number",
title={
"text": f"<span style='font-size:100%'>{name2} - Melhor Grupo</span><br><span style='font-size:70%'>Em Reais</span><br><span style='font-size:0.7em'>{df_dados_gerais['ANO'][1]} - {df_dados_gerais['ANO'].max()}</span>"},
value=value2,
number={'valueformat': '.2f'}
))
fig1.update_layout(main_config, height=273, template=template)
fig2.update_layout(main_config, height=273, template=template)
return fig1, fig2
@app.callback(
Output('datatable-data', 'data'),
Output('datatable-data', 'columns'),
Input('year-slider', 'value'),
Input('drop-cidade', 'value'),
Input('check-inline-mes', 'value'),
Input(ThemeSwitchAIO.ids.switch("theme"), "value"),
Input('drop-bairro', 'value'))
def update_table(date, dropdown_cidade, mes, toggle, dropdown_bairro):
template = template_theme1 if toggle else template_theme2
if ('TODAS' in dropdown_cidade):
mask = (df_dados_gerais['ANO'] == date) & (df_dados_gerais['OPERACAO'] == 'V') & \
(df_dados_gerais['MES'].isin(mes)) & (df_dados_gerais['CANCELADO'] != '*')
else:
mask = (df_dados_gerais['ANO'] == date) & (df_dados_gerais['OPERACAO'] == 'V') & \
(df_dados_gerais['CIDADE'].isin(dropdown_cidade)) & (df_dados_gerais['BAIRRO'].isin(dropdown_bairro)) & \
(df_dados_gerais['MES'].isin(mes)) & (df_dados_gerais['CANCELADO'] != '*')
df = df_dados_gerais.loc[mask]
# 'QT_PRATELEIRA', 'QT_DEPOSITO',
df_pivot = pd.pivot_table(
df_dados_gerais.loc[mask], index=['CODIGO', 'DESCRICAO',
'ESTOQUE', 'GRUPO',
'FAMILIA', 'UNIDADE', ],
values='QUANTIDADE',
columns='MES',
aggfunc=sum).reset_index().fillna(0)
df_pivot = df_pivot.rename(
{1: 'JAN', 2: 'FEV', 3: 'MAR', 4: 'ABR', 5: 'MAI', 6: 'JUN',
7: 'JUL', 8: 'AGO', 9: 'SET', 10: 'OUT', 11: 'NOV', 12: 'DEZ'}, axis=1)
cols = []
textCols = ['CODIGO', 'DESCRICAO', 'GRUPO', 'FAMILIA', 'UNIDADE']
for i in df_pivot.columns:
if i not in textCols:
cols.append({"name": str(i),
"id": str(i),
"type": "numeric",
"format": formatted})
else:
cols.append({"name": str(i),
"id": str(i),
"type": "text"})
return df_pivot.to_dict('records'), cols
if __name__ == '__main__':
app.run_server(debug=False)