Hello there,
Iāve made some decent progress on this, but am hitting a wall with my update_print_grid_content callback, as well as that print modal. If everything were to work perfectly, these would be the ideal steps:
- Page is loaded
- Query is ran
- Totals row updates with currently shown totals of the four columns
- User filters the data they need (for a specific product or location)
- User hits āPrint Reportā
- The print modal pops up
- The print modal shows only what theyāve filtered + the Total row in a printer friendly format
- They hit the āPrintā button
- Their browser printing prompt opens and they print their filtered data/total
- Off to the warehouse with the sheet they need to mark off
Step 7 is where Iāve been getting hung up. Have been going over this documentation for the past couple days: Printing | Dash for Python Documentation | Plotly but the modal isnāt showing the total row with the proper calculation. At some point the update_print_grid_content was showing the rows filtered, just not the correct total row calculation, but thatās not working now either.
Is the update_print_grid_content the culprit here? And if so, what am I missing? Relatively new to all this so thanks in advance for any advice!
import os
import pyodbc
import dash_html_components as html
import dash_ag_grid as dag
import pandas as pd
from dash.dependencies import Input, Output, State
from django_plotly_dash import DjangoDash
import dash_core_components as dcc
from dash.exceptions import PreventUpdate
import dash_bootstrap_components as dbc
app = DjangoDash('finished_goods_inventory', add_bootstrap_links=True)
def get_data():
conn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};'
f'SERVER={os.getenv("INNOVA_SERVER")};'
'DATABASE=ClearView;'
f'UID={os.getenv("CLEARVIEW_SQL_USER")};'
f'PWD={os.getenv("CLEARVIEW_SQL_PASSWORD")}')
query = "EXEC sp_in_selectFinishedInventory"
df = pd.read_sql(query, conn)
conn.close()
df['inventoryLocation'] = df['inventoryLocation'].str.replace('--', '-')
df['inventoryLocation'] = df['inventoryLocation'].str.replace('Henningsen TF', 'Cedar Grove')
df['packCount'] = df['packCount'].astype(int)
df['packPounds'] = df['packPounds'].astype(int)
df = df.sort_values(by='receivedDate')
return df
def calculate_totals(data):
sum_values = data[["packCount", "packPounds"]].sum()
return {"inventoryLocation": "Total",
"packCount": sum_values["packCount"],
"packPounds": sum_values["packPounds"]}
columnDefs = [
{"headerName": "Pallet", "field": "palletNumber", "rowGroup": True, "filter": True, "suppressColumnsToolPanel": True},
{"headerName": "Item #", "field": "materialName", "rowGroup": True, "filter": True},
{"field": "inventoryLocation", "sortable": True, "filter": True},
{"headerName": "Total Cases", "field": "packCount", "sortable": True, "filter": True, "aggFunc": "sum"},
{"headerName": "Total Pounds", "field": "packPounds", "sortable": True, "filter": True, "aggFunc": "sum"},
{"field": "lotName", "sortable": True, "filter": True},
{"field": "receivedDate", "sortable": True, "filter": True},
]
print_grid = html.Div(
[
html.Hr(),
html.H1('sadfasdf'),
dcc.Store(id="fgi-data-store", storage_type="memory", data={"data": None, "filter_model": None}),
dag.AgGrid(
id="grid-modal-print",
defaultColDef=dict(
resizable=True,
sortable=True,
filter=True
),
columnDefs=columnDefs,
enableEnterpriseModules=True,
dashGridOptions={
'pinnedBottomRowData': [calculate_totals(get_data())],
'groupDefaultExpanded': 2,
"domLayout": "print"
},
style={"height": 'calc(100vh - 210px)', 'margin-bottom': '10px'},
)
]
)
print_layout = html.Div(
[
dbc.ModalHeader(dbc.Button("Print", id="grid-browser-print-btn")),
dbc.ModalBody(
[
print_grid,
],
id="grid-print-area",
),
html.Div(id="dummy"),
]
)
print_grid = html.Div(
[
html.Hr(),
dcc.Store(id="fgi-data-store", storage_type="memory", data={"data": None, "filter_model": None}),
html.Div(id="print-grid-content"), # Placeholder for print grid content
]
)
app.layout = html.Div(
[
html.H1("Finished Goods Inventory"),
dbc.Button("Print Report", id="grid-modal-print-btn"),
dbc.Modal(print_layout, id="modal-print-container", is_open=False, size='xl'),
html.Hr(),
dcc.Store(id="fgi-data-store", storage_type="memory", data={"data": None, "filter_model": None}),
dag.AgGrid(
id="fgi-grid",
defaultColDef=dict(
resizable=True,
sortable=True,
filter=True
),
columnDefs=columnDefs,
csvExportParams={"fileName": "finished_goods_inventory.csv"},
enableEnterpriseModules=True,
dashGridOptions={
'pinnedBottomRowData': [calculate_totals(get_data())],
'groupDefaultExpanded': 2,
},
style={"height": 'calc(100vh - 210px)', 'margin-bottom': '10px'},
)
]
)
@app.callback(
[Output("fgi-data-store", "data"),
Output('fgi-grid', 'pinnedBottomRowData')],
[Input("fgi-grid", "filterModel")]
)
def update_data_store(filter_model):
if filter_model is None:
raise PreventUpdate
if filter_model == {}:
data = get_data().to_dict("records")
else:
data = None
data_store = {"data": data, "filter_model": filter_model}
filtered_data = pd.DataFrame(data) if data else get_data()
for column, filter_options in filter_model.items():
values = filter_options.get('values', [])
if values:
filtered_data = filtered_data[filtered_data[column].isin(values)]
totals = calculate_totals(filtered_data)
return data_store, [totals]
@app.callback(
Output('fgi-grid', 'rowData'),
[Input("fgi-data-store", "data")]
)
def update_output(data_store):
if data_store["data"] is None:
raise PreventUpdate
filtered_data = pd.DataFrame(data_store["data"])
filter_model = data_store["filter_model"]
if filter_model:
for column, filter_options in filter_model.items():
values = filter_options.get('values', [])
if values:
filtered_data = filtered_data[filtered_data[column].isin(values)]
return filtered_data.to_dict("records")
@app.callback(
Output("grid-modal-print", "columnState"),
Output("grid-modal-print", "filterModel"),
Output("modal-print-container", "is_open"),
Input("grid-modal-print-btn", "n_clicks"),
State("fgi-grid", "columnState"),
State("fgi-grid", "filterModel"),
prevent_initial_call=True,
)
def open_print_modal(_, col_state, filter_model):
return col_state, filter_model, True
@app.callback(
#Output('fgi-data-store', 'data'),
Output("grid-modal-print", "rowData"),
Output('grid-modal-print', 'pinnedBottomRowData'),
Input("grid-modal-print-btn", "n_clicks"),
State("fgi-data-store", "data"),
prevent_initial_call=True,
)
def update_print_grid_content(n_clicks, data_store):
if n_clicks is None:
raise PreventUpdate
if data_store is None or data_store["data"] is None:
raise PreventUpdate
filtered_data = pd.DataFrame(data_store["data"])
totals = [calculate_totals(filtered_data)]
return data_store["data"] + totals
if __name__ == '__main__':
app.run_server(debug=True)