@jinnyzor
Here you go
df['year'] = pd.to_datetime(df['Date'], format = '%d/%m/%Y', errors='coerce').dt.year
df['date'] = pd.to_datetime(df['Date'], format = '%Y-%m-%d', errors='coerce')
df['date1'] = pd.to_datetime(df['Date'], format = '%Y-%m-%d', errors='coerce').dt.date
df['day'] = pd.to_datetime(df['Date'], format = '%Y-%m-%d', errors='coerce').dt.day
month_labels = {1: 'Jan', 2: 'Feb', 3: 'Mar', 4: 'Apr', 5: 'May', 6: 'Jun', 7: 'Jul', 8: 'Aug',9: 'Sep', 10: 'Oct', 11: 'Nov', 12: 'Dec'}
df['month'] = pd.to_datetime(df['Date'], format = '%Y-%m-%d', errors='coerce').dt.month
df['monthname']= df['month'].apply(lambda x: month_labels[x])
df.sort_values(by= ['year', 'month', Date', 'Product'], inplace = True)
month_cat = list(df['monthname'].unique())
sort_mm = sorted(month_cat, key=lambda m: datetime.strptime(m, "%b"))
df["pdate"] = df.date.apply(lambda x: (x - pd.DateOffset(months=1)))
df2 = df.copy()
final_df = pd.merge(left = df,right = df2, how="left", left_on=['pdate','Product'], right_on=['date','Product'])
df[['Date', 'Product', 'Sale'
, 'year' ,'month'
,'monthname', 'date'
,'date1', 'day'
, 'mtd' , 'pdate', 'lsale'
, 'lmtdsale']] = final_df[['Date_x', 'Product', 'Sale_x', 'year_x' ,'month_x' ,'monthname_x', 'date_x','date1_x'
, 'day_x' , 'mtd_x', 'pdate_x', 'Sale_y' ,'mtd_y']].fillna(0)
df['Sale1']=df['Sale'].map('{:,.2f}'.format)
df['mtd1']=df['mtd'].map('{:,.2f}'.format)
df['lmtdsale1']=df['lmtdsale'].map('{:,.2f}'.format)
dbc.Col([
html.Table([
html.Td('Sub', id = '',style = header_column_cell_style),
html.Td('', id = 'subtotal', style = body_column_cell_style)
]),
dash_table.DataTable(id='table',
columns=[
{'name': 'Today', "id": 'Date'},
{'name': 'Product', "id": 'Product'},
{'name': 'Sale', "id": 'Sale1'},
{'name': 'Current MTD Sale', "id": 'mtd1'},
{'name': 'Last MTD Sale', 'id': 'lmtdtpv2'},
],
sort_action= 'native',
sort_mode="multi",
filter_action = "native",
row_selectable = 'multi',
),
])
@app.callback(
Output('table', 'data'),
Input('date_dd', 'value')
)
def update_table(selection):
if len (selection) == 0 :
return dash.no_updates
else:
selection = datetime.strptime(selection, '%Y-%m-%d').date()
dff = df[df['date1'] == selection]
current_mtd_start = selection - pd.tseries.offsets.MonthBegin(1)
current_mtd_end = selection
last_mtd_start = current_mtd_start - pd.DateOffset(months=1)
last_mtd_end = current_mtd_end - pd.DateOffset(months=1)
last_mtd_end = pd.to_datetime(last_mtd_end, format='%Y-%m-%d')
new_df1 = df[(df['date'].dt.month==last_mtd_end.month)
& (df['date'].dt.year==last_mtd_end.year)
& (df['date']<=last_mtd_end)
]
rename = {'Sale':'sale'}
dk = new_df1.groupby(['Product','Acquirer'])[['Sale']].agg('sum').reset_index().rename(columns=rename)
df2 = pd.merge(left = dff,right = dk, how="left", left_on=['Product'], right_on=[ 'Product'])
df2['lmtdsale2']=df2['sale'].map('{:,.2f}'.format)
columns = df2[['Date', 'Product', Sale1', 'mtd1', 'lmtdtpv2' ]]
data= columns.to_dict('records')
return data
operators = [['ge ', '>='],
['le ', '<='],
['lt ', '<'],
['gt ', '>'],
['ne ', '!='],
['eq ', '='],
['contains '],
['datestartswith ']]
def split_filter_part(filter_part):
for operator_type in operators:
for operator in operator_type:
if operator in filter_part:
name_part, value_part = filter_part.split(operator, 1)
name = name_part[name_part.find('{') + 1: name_part.rfind('}')]
value_part = value_part.strip()
v0 = value_part[0]
if (v0 == value_part[-1] and v0 in ("'", '"', '`')):
value = value_part[1: -1].replace('\\' + v0, v0)
else:
try:
value = float(value_part)
except ValueError:
value = value_part
# word operators need spaces after them in the filter string,
# but we don't want these later
return name, operator_type[0].strip(), value
return [None] * 3
@app.callback(
Output('subtotal','children'),
Input('table', "filter_query"),
State('table','data')
)
def update_table(filter, df):
dff = pd.DataFrame.from_dict(df2)
if filter:
filtering_expressions = filter.split(' && ')
for filter_part in filtering_expressions:
col_name, operator, filter_value = split_filter_part(filter_part)
if operator in ('eq', 'ne', 'lt', 'le', 'gt', 'ge'):
# these operators match pandas series operator method names
dff = dff.loc[getattr(dff[col_name], operator)(filter_value)]
elif operator == 'contains':
dff = dff.loc[dff[col_name].str.contains(filter_value)]
elif operator == 'datestartswith':
# this is a simplification of the front-end filtering logic,
# only works with complete fields in standard format
dff = dff.loc[dff[col_name].str.startswith(filter_value)]
return df2['Sale1'].sum()