streamlit_python / Homepage.py
thanhpham0704's picture
Update Homepage.py
6f3e496
import streamlit as st
import requests
import plotly.express as px
import pandas as pd
from datetime import datetime, timedelta
from pathlib import Path
import pickle
import streamlit_authenticator as stauth
import numpy as np
import calendar
# names = ["Phạm Tấn Thành", "Phạm Minh Tâm", "Vận hành"]
# usernames = ["thanhpham", "tampham", "vietopvanhanh"]
# passwords = ['thanhpham0704', 'tampham1234', 'vanhanh2023']
# hashed_passwords = stauth.Hasher(passwords).generate()
# file_path = Path(__file__).parent / "hashed_pw.pkl"
# with file_path.open("wb") as file:
# pickle.dump(hashed_passwords, file)
page_title = "Lương và thực thu"
page_icon = ":chart_with_upwards_trend:"
layout = "wide"
st.set_page_config(page_title=page_title, page_icon=page_icon, layout=layout)
# ----------------------------------------
names = ["Phạm Tấn Thành", "Phạm Minh Tâm", "Vận hành"]
usernames = ["thanhpham", "tampham", "vietopvanhanh"]
# Load hashed password
file_path = Path(__file__).parent / 'hashed_pw.pkl'
with file_path.open("rb") as file:
hashed_passwords = pickle.load(file)
authenticator = stauth.Authenticate(names, usernames, hashed_passwords,
"sales_dashboard", "abcdef", cookie_expiry_days=1)
name, authentication_status, username = authenticator.login("Login", "main")
if authentication_status == False:
st.error("Username/password is incorrect")
if authentication_status == None:
st.warning("Please enter your username and password")
if authentication_status:
authenticator.logout("logout", "main")
# Add CSS styling to position the button on the top right corner of the page
st.markdown(
"""
<style>
.stButton button {
position: absolute;
top: 0px;
right: 0px;
}
</style>
""",
unsafe_allow_html=True
)
st.title(page_title + " " + page_icon)
#----------------------#
# Filter
now = datetime.now()
DEFAULT_START_DATE = datetime(now.year, now.month, 1)
DEFAULT_END_DATE = datetime(now.year, now.month, 1) + timedelta(days=32)
DEFAULT_END_DATE = DEFAULT_END_DATE.replace(day=1) - timedelta(days=1)
# Create a form to get the date range filters
with st.form(key='date_filter_form'):
col1, col2 = st.columns(2)
ketoan_start_time = col1.date_input(
"Select start date", value=DEFAULT_START_DATE)
ketoan_end_time = col2.date_input(
"Select end date", value=DEFAULT_END_DATE)
submit_button = st.form_submit_button(
label='Filter')
# the duration between 2 dates exclude Sunday
duration = sum(1 for i in range((ketoan_end_time - ketoan_start_time).days)
if (ketoan_start_time + timedelta(i)).weekday() != 6)
# the number of days in a month exclude Sunday
days_in_month = calendar.monthrange(
ketoan_start_time.year, ketoan_start_time.month)[1]
sundays_in_month = sum(1 for day in range(1, days_in_month + 1) if datetime(
ketoan_start_time.year, ketoan_start_time.month, day).weekday() == 6)
days_excluding_sundays = days_in_month - sundays_in_month
#----------------------#
@st.cache(ttl = timedelta(days = 1))
def collect_data(link):
return(pd.DataFrame((requests.get(link).json())))
@st.cache
def rename_lop(dataframe, column_name):
dataframe[column_name] = dataframe[column_name].replace(
{1: "Hoa Cúc", 2: "Gò Dầu", 3: "Lê Quang Định", 5: "Lê Hồng Phong"})
return dataframe
@st.cache
def grand_total(dataframe, column):
# create a new row with the sum of each numerical column
totals = dataframe.select_dtypes(include=[float, int]).sum()
totals[column] = "Grand total"
# append the new row to the dataframe
dataframe = dataframe.append(totals, ignore_index=True)
return dataframe
# "---------------" Thông tin lương giáo viên
users = collect_data('https://vietop.tech/api/get_data/users')
# Thong tin luong
import gspread
sa = gspread.service_account(
filename='taichinh-380507-b8f84e9ee681.json')
sh = sa.open("Nhân sự")
worksheet = sh.worksheet("Giáo viên")
salary = pd.DataFrame(worksheet.get_all_records())
salary = salary.replace("", np.nan).dropna(subset='Mã giáo viên')
salary = salary.replace('\.', '', regex=True)
salary = salary.astype({'Lương theo hợp đông': 'float', 'Thâm niên': 'float',
'Chức danh': "float", 'Tổng lương': 'float', 'date_affected': 'datetime64[ns]'})
# salary.info()
# salary = salary.sort_values("date_affected", ascending=False)\
# .drop_duplicates(subset='id_gg')
salary = salary.sort_values("date_affected", ascending=False)\
.query("date_affected <= @ketoan_end_time")\
.drop_duplicates("id_gg")
salary.fillna(0, inplace=True)
# Thong tin luong
salary['salary_ngay_cong'] = round(
salary['Tổng lương'] * duration/days_excluding_sundays, 0)
salary.fillna(0, inplace=True)
salary.drop(['STT', 'Mã giáo viên', 'Tổng lương'], axis=1, inplace=True)
salary.rename(columns={"Lương theo hợp đông": "hopdong", "Thâm niên": "thamnien",
'Chức danh': 'chucdanh', 'Ngày': 'ngay', 'Tối': 'toi', 'Cuối tuần': 'cuoituan',
'Trợ giảng': 'trogiang', 'BHXH': 'bhxh', 'Chế độ': 'working_status', 'Bậc giáo viên': 'level', 'Tổng ngày nghỉ phép': 'ngaynghi_total',
'Tổng ngày công thực tế': 'ngaycong_real_total'}, inplace=True)
# "------------------"
gv_diemdanh = collect_data('https://vietop.tech/api/get_data/diemdanh')
gv_diemdanh['date_created'] = pd.to_datetime(gv_diemdanh['date_created'])
gv_diemdanh = gv_diemdanh.query(
"date_created >= @ketoan_start_time and date_created <= @ketoan_end_time")
# Ca hoc table
cahoc = {'cahoc': ['ca1', 'ca2', 'ca3', 'ca4', 'ca5', 'ca6'],
'start_time': ['08:30:00', '10:30:00', '13:30:00', '15:30:00', '18:00:00', '19:45:00'],
'end_time': ['10:30:00', '12:30:00', '15:30:00', '17:30:00', '19:45:00', '21:30:00']}
cahoc = pd.DataFrame(cahoc)
# --------------- GET DATA FROM API
sh = sa.open("Nhân sự")
worksheet = sh.worksheet("Overtime")
offline_overtime = pd.DataFrame(worksheet.get_all_records())
offline_overtime['date_affected'] = pd.to_datetime(
offline_overtime['date_affected'])
offline_overtime = offline_overtime.sort_values("date_affected", ascending=False)\
.drop_duplicates(subset='Họ và tên')
offline_overtime.drop("date_affected", axis=1, inplace=True)
# Define the start and end times of the day
start_time = pd.to_datetime('2000-01-01 06:00:00').time()
end_time = pd.to_datetime('2000-01-01 18:00:00').time()
ca1 = pd.to_datetime('2000-01-01 06:30:00').time()
ca2 = pd.to_datetime('2000-01-01 10:30:00').time()
ca3 = pd.to_datetime('2000-01-01 13:30:00').time()
ca4 = pd.to_datetime('2000-01-01 15:30:00').time()
ca5 = pd.to_datetime('2000-01-01 18:00:00').time()
# tren office khong cos 19:45
ca6 = pd.to_datetime('2000-01-01 19:30:00').time()
# Create a function that takes a time and returns "Morning" or "Evening" depending on whether the time falls within the specified range
@st.cache
def time_of_day(time):
if (time >= start_time) & (time < end_time):
return "Sáng"
else:
return "Tối"
# Create a function that takes a time and returns "Morning" or "Evening" depending on whether the time falls within the specified range
@st.cache
def day_of_week(day):
if (day == 5) | (day == 6):
return "weekend"
else:
return "weekdays"
# Create a function that takes a time and returns "Morning" or "Evening" depending on whether the time falls within the specified range
@st.cache
def cahoc_converter(ca):
if (ca >= ca1) & (ca < ca2):
return 1
elif (ca >= ca2) & (ca < ca3):
return 2
elif (ca >= ca3) & (ca < ca4):
return 3
elif (ca >= ca4) & (ca < ca5):
return 4
elif (ca >= ca5) & (ca < ca6):
return 5
elif (ca >= ca6):
return 6
# "---------------" Bảng lương giáo viên
overtime_melt = offline_overtime.melt(
id_vars=['id_gg', 'Họ và tên', 'WORKING_STATUS'], var_name='Column Name', value_name='overtime_status')
overtime_melt['day_of_week'], overtime_melt['cahoc'] = overtime_melt['Column Name'].str.split(
'Ca ', 1).str
overtime_melt['day_of_week'].replace(
{'T2': 0, 'T3': 1, 'T4': 2, 'T5': 3, 'T6': 4, 'T7': 5, 'T8': 6}, inplace=True)
overtime_melt['overtime_status'].replace(
{0: 'in', 'a': 'out'}, inplace=True)
# Convert 5 and 6 into "Cuối tuần"
overtime_melt['weekend_or_not'] = overtime_melt['day_of_week'].apply(
day_of_week)
# Convert ca into Sáng or Tối
overtime_melt['time_of_day'] = ['Sáng' if i in [
'1', '2', '3', '4'] else 'Tối' for i in overtime_melt['cahoc']]
# Drop unnecessary columns
overtime_melt.drop(
['Column Name'], axis=1, inplace=True)
overtime_melt['cahoc'] = overtime_melt['cahoc'].astype(int)
overtime_melt.rename(
columns={'WORKING_STATUS': 'working_status'}, inplace=True)
# "---------------" Lương overtime của giáo viên
lophoc = collect_data('https://vietop.tech/api/get_data/lophoc')
diemdanh = gv_diemdanh.merge(users[['fullname', 'id']], left_on='giaovien', right_on='id', how='inner')\
.sort_values("created_at", ascending=False)
# diemdanh['cahoc'].replace({0: 'không học', 1: 'ca1', 2: 'ca2', 3: 'ca3', 4:'ca4', 5:'ca5', 6:'ca6', 7:'ca 1.5 giờ', 8: 'ca 2.5 giờ', 9: 'ca 3.0 giờ', 10: 'ca 1 giờ', 11: 'ca 1.75 giờ', 12: 'ca 2 giờ'}, inplace = True)
diemdanh = diemdanh[['lop_id', 'sogio', 'cahoc', 'phanloai',
'date_created', 'created_by', 'id',
'updated_by', 'created_at', 'fullname']]
# Convert the date column to datetime
diemdanh['created_at'] = pd.to_datetime(diemdanh['created_at'])
# Extract the time component of each datetime value
diemdanh['created_at_time'] = diemdanh['created_at'].dt.time
# Create a new column that indicates the day of the week
diemdanh['day_of_week'] = diemdanh['created_at'].dt.dayofweek
# Create a boolean mask that indicates whether each time is within the specified time frame
diemdanh["time_of_day"] = diemdanh['created_at_time'].apply(time_of_day)
# Convert 5 and 6 into "Cuối tuần"
diemdanh['weekend_or_not'] = diemdanh["day_of_week"].apply(day_of_week)
diemdanh = diemdanh[['id', 'fullname', 'sogio', 'cahoc', 'phanloai',
'created_at', 'day_of_week', 'created_at_time', 'time_of_day', 'weekend_or_not', 'date_created',
'lop_id']]
diemdanh['cahoc'] = diemdanh['created_at_time'].apply(cahoc_converter)
# Sum giohoc according to fullname, time of day and weekend or not
diemdanh_sum_giohoc = diemdanh.groupby(
["id", "fullname", "cahoc", 'phanloai', 'day_of_week', "time_of_day", "weekend_or_not", 'lop_id'], as_index=False)['sogio'].sum()
# Get lopcn from lophoc
diemdanh_lop_cn = diemdanh_sum_giohoc.merge(
lophoc[['lop_id', 'lop_cn']], on='lop_id')
# "---------------"
sal_diem = diemdanh_lop_cn.merge(
salary, left_on='id', right_on='id_gg')
# Merge diemdanh and overtime
sal_diem_over = sal_diem\
.merge(overtime_melt, on=['id_gg', 'Họ và tên', 'cahoc', 'day_of_week', 'time_of_day', 'weekend_or_not'], how='inner', validate='many_to_many')
# Drop duplicates
sal_diem_over.drop_duplicates(inplace=True)
# Fill na
sal_diem_over.fillna(0, inplace=True)
# Calculate luong ngay cong
empty = []
for index, value in sal_diem_over.iterrows():
if value['weekend_or_not'] == 'weekend' and value['overtime_status'] == 'out':
empty.append(value['cuoituan'] * value['sogio'])
elif value['time_of_day'] == 'Tối' and value['overtime_status'] == 'out':
empty.append(value['toi'] * value['sogio'])
elif value['time_of_day'] == 'Sáng' and value['overtime_status'] == 'out':
empty.append(value['ngay'] * value['sogio'])
elif value['phanloai'] == 0:
empty.append(value['trogiang'] * value['sogio'])
else:
empty.append(0)
sal_diem_over['salary_gio_cong'] = empty
# Slicing columns
sal_diem_over = sal_diem_over.loc[:, ['lop_cn', 'id_gg', 'Họ và tên', 'working_status_x', 'cahoc', 'phanloai', 'overtime_status',
'time_of_day', 'day_of_week', 'weekend_or_not', 'sogio',
'ngay', 'toi', 'cuoituan', 'trogiang', 'salary_gio_cong', 'salary_ngay_cong']]
sal_diem_over_group_lop = sal_diem_over.groupby(['id_gg', 'Họ và tên', 'lop_cn', 'working_status_x', 'overtime_status', 'salary_ngay_cong'], as_index=False)['sogio', 'salary_gio_cong'].sum()\
.query("overtime_status == 'out'")
# Sum luong_gio_cong according to fullname
sal_diem_over_group = sal_diem_over.groupby(['id_gg', 'Họ và tên', 'working_status_x', 'overtime_status', 'salary_ngay_cong'], as_index=False)['sogio', 'salary_gio_cong'].sum()\
.query("overtime_status == 'out'").sort_values("salary_gio_cong", ascending=False)
sal_diem_over_details = sal_diem_over.drop('salary_ngay_cong', axis=1)\
.query("overtime_status == 'out'")\
# ----------------------# Phân phối lương cứng theo chi nhánh
df = sal_diem_over.groupby(['lop_cn', 'id_gg', 'Họ và tên', 'working_status_x', 'overtime_status',
'salary_ngay_cong'], as_index=False)['sogio', 'salary_gio_cong'].sum()
df = df.query('overtime_status == "in"')
df_sum = df.groupby('Họ và tên', as_index=False)['sogio'].sum()
df_proportion = df_sum.merge(df, on='Họ và tên')
df_proportion['proportion_sogio'] = df_proportion['sogio_y'] / \
df_proportion['sogio_x']
df_proportion['salary_ngay_cong_divided'] = df_proportion['proportion_sogio'] * \
df_proportion['salary_ngay_cong']
# Giáo viên ngoại trừ phòng đào tạo
df_proportion_nodaotao = df_proportion[~df_proportion['Họ và tên'].isin(
['Mai Minh Trung', 'Trần Thị Thanh Nga', 'Nguyễn Thị Thu Hà', 'Huỳnh Trương Hồng Châu Long', 'Nguyễn Huy Hoàng', 'Đỗ Nguyễn Đăng Khoa'])]
# Subset
df_proportion_nodaotao = df_proportion_nodaotao[[
'id_gg', 'Họ và tên', 'lop_cn', 'salary_ngay_cong_divided']]
# Riêng phòng đào tạo
df_proportion_daotao = salary[salary['Họ và tên'].isin(
['Phạm Tấn Thành', 'Mai Minh Trung', 'Trần Thị Thanh Nga', 'Nguyễn Thị Thu Hà', 'Huỳnh Trương Hồng Châu Long', 'Nguyễn Huy Hoàng', 'Đỗ Nguyễn Đăng Khoa'])]
df_proportion_daotao['1'] = 0.26 * df_proportion_daotao['salary_ngay_cong']
df_proportion_daotao['2'] = 0.26 * df_proportion_daotao['salary_ngay_cong']
df_proportion_daotao['3'] = 0.18 * df_proportion_daotao['salary_ngay_cong']
df_proportion_daotao['5'] = 0.30 * df_proportion_daotao['salary_ngay_cong']
# Subset
df_proportion_daotao = df_proportion_daotao.loc[:, [
'id_gg', 'Họ và tên', '1', '2', '3', '5']]
# Lương đào tạo sau khi phân phối
df_proportion_daotao = pd.melt(df_proportion_daotao, id_vars=[
'id_gg', 'Họ và tên'], var_name='lop_cn', value_name='salary_ngay_cong_divided')
df_proportion_daotao['lop_cn'] = df_proportion_daotao['lop_cn'].astype(
'int64')
# Concat luong đào tạo and lương giáo viên
salary_gv_dt = pd.concat([df_proportion_daotao, df_proportion_nodaotao])
salary_gv_dt['salary_ngay_cong_divided'] = round(
salary_gv_dt['salary_ngay_cong_divided'], 2)
salary_gv_dt = salary_gv_dt.sort_values(
"salary_ngay_cong_divided", ascending=False)
# ----------------------# Thực thu
orders = collect_data(
'https://vietop.tech/api/get_data/orders').query("deleted_at.isnull()")
lophoc = collect_data('https://vietop.tech/api/get_data/lophoc')
hocvien = collect_data(
'https://vietop.tech/api/get_data/hocvien').query("hv_id != 737 and deleted_at.isnull()")
# hv đang họccd Au
hocvien_danghoc = hocvien.merge(orders, on='hv_id')\
.query("ketoan_active == 1")\
.groupby('ketoan_coso', as_index=False).size().rename(columns={"size": "total_students"})
hocvien_danghoc = rename_lop(hocvien_danghoc, 'ketoan_coso')
@st.cache
def plotly_chart(df, yvalue, xvalue, text, title, y_title, x_title, color=None, discrete_sequence=None, map=None):
fig = px.bar(df, y=yvalue,
x=xvalue, text=text, color=color, color_discrete_sequence=discrete_sequence, color_discrete_map=map)
fig.update_layout(
title=title,
yaxis_title=y_title,
xaxis_title=x_title,
)
fig.update_traces(textposition='auto')
return fig
fig5 = plotly_chart(hocvien_danghoc, 'ketoan_coso', 'total_students', 'total_students',
'Tổng học viên đang học theo chi nhánh', 'Chi nhánh', 'Học viên')
# Lop dang hoc
lop_danghoc = lophoc.query(
"(lop_status == 2 or lop_status == 4) and deleted_at.isnull()")\
.groupby('lop_cn', as_index=False).size().rename(columns={"size": "total_classes"})
lop_danghoc.lop_cn = lop_danghoc.lop_cn.replace(
{1: "Hoa Cúc", 2: "Gò Dầu", 3: "Lê Quang Định", 5: "Lê Hồng Phong"})
fig6 = plotly_chart(lop_danghoc, 'lop_cn', 'total_classes', 'total_classes',
"Tổng lớp đang học theo chi nhánh", 'Chi nhánh', 'Lớp học')
""
# "------------------"
# Define a function
@st.cache
def csv_reader(file):
df = pd.read_csv(file)
df = df.query("phanloai == 1") # Filter lop chính
df['date_created'] = pd.to_datetime(df['date_created'])
return df
@st.cache
def collect_filtered_data(table, date_column='', start_time='', end_time=''):
link = f"https://vietop.tech/api/get_data/{table}?column={date_column}&date_start={start_time}&date_end={end_time}"
df = pd.DataFrame((requests.get(link).json()))
df[date_column] = pd.to_datetime(df[date_column])
return df
df = csv_reader("diemdanh_details.csv")
df1 = collect_filtered_data(table='diemdanh_details', date_column='date_created',
start_time='2023-01-01', end_time='2025-01-01')
diemdanh_details = pd.concat([df, df1])
thucthu = diemdanh_details.query(
'date_created >= @ketoan_start_time and date_created <= @ketoan_end_time')\
.groupby(['ketoan_id', 'lop_id', 'gv_id', 'date_created'], as_index=False)['giohoc'].sum()\
.merge(orders, on='ketoan_id')\
.merge(lophoc, on='lop_id')\
.merge(users[['fullname', 'id']], left_on='gv_id', right_on='id')
thucthu_all = diemdanh_details.query("date_created > '2023-01-01'")\
.groupby(['ketoan_id', 'lop_id', 'gv_id', 'date_created'], as_index=False)['giohoc'].sum()\
.merge(orders, on='ketoan_id')\
.merge(lophoc, on='lop_id')\
.merge(users[['fullname', 'id']], left_on='gv_id', right_on='id')
thucthu['thucthu'] = thucthu['giohoc'] * thucthu['ketoan_tientrengio']
thucthu['date_created_month'] = thucthu['date_created'].dt.month_name()
thucthu_all['thucthu'] = thucthu_all['giohoc'] * \
thucthu_all['ketoan_tientrengio']
thucthu_all['date_created_month'] = thucthu_all['date_created'].dt.month_name()
new_order = ['January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October', 'November', 'December']
# Reorder months
thucthu_all['date_created_month'] = pd.Categorical(
thucthu_all['date_created_month'], categories=new_order, ordered=True)
# Groupby giaovien
thucthu_gv = thucthu.groupby(['id', 'fullname'], as_index=False)[
'thucthu'].sum()
# Groupby cn
thucthu_cn = thucthu.groupby(['lop_cn'], as_index=False)['thucthu'].sum()
thucthu_cn_rename = thucthu.groupby(
['lop_cn'], as_index=False)['thucthu'].sum()
thucthu_cn_rename = rename_lop(thucthu_cn_rename, 'lop_cn')
# Thực thu theo giáo viên và chi nhánh
thucthu_details = thucthu.groupby(
['id', 'fullname', 'lop_cn'], as_index=False)['thucthu'].sum()
# "_______________"
@st.cache
def thucthu_time(dataframe, column):
df = dataframe.groupby(['lop_cn', column], as_index=False)[
'thucthu'].sum()
df.lop_cn = df.lop_cn.replace(
{1: "Hoa Cúc", 2: "Gò Dầu", 3: "Lê Quang Định", 5: "Lê Hồng Phong"})
return df
thucthu_diemdanh_ngay = thucthu_time(thucthu, 'date_created')
thucthu_diemdanh_ngay = thucthu_diemdanh_ngay.pivot(
index='date_created', columns='lop_cn', values='thucthu')
thucthu_diemdanh_month = thucthu_time(thucthu_all, 'date_created_month')
# Thực thu điểm danh theo ngày và tháng
fig9 = px.bar(thucthu_diemdanh_ngay, x=thucthu_diemdanh_ngay.index, y=thucthu_diemdanh_ngay.columns, barmode='stack',
color_discrete_sequence=['#07a203', '#ffc107', '#e700aa', '#2196f3'])
fig10 = px.bar(thucthu_diemdanh_month, x="date_created_month",
y="thucthu", color="lop_cn", barmode="group", color_discrete_sequence=['#ffc107', '#07a203', '#2196f3', '#e700aa'], text="thucthu")
# update the chart layout
fig9.update_layout(title='Thực thu điểm danh theo ngày',
xaxis_title='Ngày', yaxis_title='Thực thu điểm danh')
fig10.update_layout(title='Thực thu điểm danh theo tháng trong năm 2023',
xaxis_title='Tháng', yaxis_title='Thực thu', showlegend=True)
fig10.update_traces(
hovertemplate="Thực thu điểm danh: %{y:,.0f}<extra></extra>")
# "_______________"
fig1 = plotly_chart(thucthu_cn_rename, 'lop_cn', 'thucthu', thucthu_cn_rename['thucthu'].apply(lambda x: format(x, ',')),
"Thực thu theo chi nhánh", 'Chi nhánh', 'Thực thu')
# "_______________" Tính tổng lương
fixed_salary_cn = salary_gv_dt.groupby("lop_cn", as_index=False)[
'salary_ngay_cong_divided'].sum()
overtime_salary_cn = sal_diem_over_group_lop.groupby("lop_cn", as_index=False)[
'salary_gio_cong'].sum()
overtime_fixed_salary_cn = fixed_salary_cn.merge(
overtime_salary_cn, on='lop_cn')
overtime_fixed_salary_cn['fixed_overtime'] = overtime_fixed_salary_cn['salary_ngay_cong_divided'] + \
overtime_fixed_salary_cn['salary_gio_cong']
salary_thucthu = overtime_fixed_salary_cn.merge(thucthu_cn, on='lop_cn')
# Create grand total
salary_thucthu_grand_total = grand_total(salary_thucthu, 'lop_cn')
# Create percent
salary_thucthu_grand_total['percent'] = salary_thucthu_grand_total.fixed_overtime / \
salary_thucthu_grand_total.thucthu * 100
salary_thucthu_grand_total['percent'] = round(
salary_thucthu_grand_total['percent'], 2)
salary_thucthu_grand_total = rename_lop(
salary_thucthu_grand_total, 'lop_cn')
salary_thucthu_grand_total.columns = ['Chi nhánh', 'Tổng lương ngày công',
'Tổng lương giờ công', 'Tổng lương giáo viên', 'Thực thu điểm danh', 'Tổng lương / thực thu']
# "_______________"
# Create a barplot for Tỷ lệ tổng lương / thực thu theo chi nhánh
fig2 = plotly_chart(salary_thucthu_grand_total, 'Tổng lương / thực thu', 'Chi nhánh', salary_thucthu_grand_total["Tổng lương / thực thu"].apply(
lambda x: '{:.2%}'.format(x/100)),
"Tỷ lệ tổng lương / thực thu theo chi nhánh", 'Chi nhánh', 'Tổng lương / thực thu', color='Chi nhánh', map={
'Hoa Cúc': '#ffc107',
'Gò Dầu': '#07a203',
'Lê Quang Định': '#2196f3',
'Lê Hồng Phong': '#e700aa',
'Grand total': 'white'
})
fig2.update_layout(font=dict(size=17), xaxis={
'categoryorder': 'total descending'})
# "_______________"
thucthu_hocvien_lop = thucthu_cn_rename.merge(
hocvien_danghoc, left_on='lop_cn', right_on='ketoan_coso')\
.merge(lop_danghoc, on='lop_cn')
thucthu_hocvien_lop['thucthu_div_hocvien'] = round(
thucthu_hocvien_lop['thucthu'] / thucthu_hocvien_lop['total_students'], 0)
thucthu_hocvien_lop['thucthu_div_lophoc'] = round(
thucthu_hocvien_lop['thucthu'] / thucthu_hocvien_lop['total_classes'], 0)
# fig7 = plotly_chart(thucthu_hocvien_lop, 'lop_cn', 'thucthu_div_hocvien', thucthu_hocvien_lop['thucthu_div_hocvien'].apply(lambda x: format(x, ',')),
# "Trung bình thực thu 1 học viên", 'Chi nhánh', 'Thực thu / học viên')
# fig8 = plotly_chart(thucthu_hocvien_lop, 'lop_cn', 'thucthu_div_lophoc', thucthu_hocvien_lop['thucthu_div_lophoc'].apply(lambda x: format(x, ',')),
# "Trung bình thực thu 1 lớp học", 'Chi nhánh', 'Thực thu / lớp học')
# "_______________"
overtime_salary_cn_gv = sal_diem_over_group_lop.groupby(
['id_gg', 'Họ và tên', "lop_cn", "working_status_x"], as_index=False)['salary_gio_cong'].sum()
df = overtime_salary_cn_gv.merge(
salary_gv_dt, on=['lop_cn', 'Họ và tên', 'id_gg'], how='outer')
df.fillna(0, inplace=True)
df['fixed_overtime'] = df['salary_gio_cong'] + \
df['salary_ngay_cong_divided']
gv_thucthu_cs = df.merge(thucthu_cn, on='lop_cn')
gv_thucthu_cs['percent'] = round(gv_thucthu_cs['fixed_overtime'] /
gv_thucthu_cs['thucthu'] * 100, 2)
# "_______________"
# salary_merge = st.session_state['salary_merge']
gv_thucthu_gv = gv_thucthu_cs.groupby(['id_gg', 'Họ và tên'], as_index=False)['fixed_overtime'].sum()\
.merge(thucthu_gv, left_on='id_gg', right_on='id', how='left')
gv_thucthu_gv['percent'] = round(gv_thucthu_gv['fixed_overtime'] /
gv_thucthu_gv['thucthu'] * 100, 2)
gv_thucthu_gv = gv_thucthu_gv.merge(salary, left_on='id', right_on='id_gg')
# Fulltime
df = gv_thucthu_gv
df1 = df[df["working_status"] == "Fulltime"].sort_values(
by="percent", ascending=True)
df1['fullname'] = df1['fullname'] + " (" + df['level'] + ")"
# Parttime
df2 = df[df["working_status"] == "Partime"].sort_values(
by="percent", ascending=True)
df2['fullname'] = df2['fullname'] + " (" + df['level'] + ")"
# Plotly graphs
fig3 = plotly_chart(df1.sort_values(
"percent", ascending=True), 'fullname', 'percent', df1["percent"].apply(
lambda x: '{:.2%}'.format(x/100)),
"Fulltime - Tỷ lệ tổng lương / thực thu", '', 'Tỷ lệ')
fig3.update_layout(
height=1000, # set the height of the plot to 600 pixels
width=800)
# Plotly graphs
fig3_1 = plotly_chart(df2.sort_values(
"percent", ascending=True), 'fullname', 'percent', df2["percent"].apply(
lambda x: '{:.2%}'.format(x/100)),
"Parttime - Tỷ lệ tổng lương / thực thu", '', 'Tỷ lệ')
fig3_1.update_layout(
height=1000, # set the height of the plot to 600 pixels
width=800)
# "_______________" thực thu chuyển phí
hv_status = collect_data('https://vietop.tech/api/get_data/hv_status')
# Filter orders
orders_chuyenphi = orders.query("ketoan_active == 5")[["ketoan_id", "hv_id", "ketoan_details", "ketoan_coso", "ketoan_sogio", "ketoan_price",
"ketoan_tientrengio", "remaining_time", "kh_id"]]
# Filter hv_status
hv_status_chuyenphi = hv_status[['ketoan_id', 'status', 'lop_id', 'note', 'is_price', 'created_at']]\
.query("status ==7")
# Filter hocvien
hocvien_chuyenphi = hocvien[['hv_id', 'hv_fullname']]
# Merge hv_status and orders
chuyenphi = hv_status_chuyenphi.merge(
orders_chuyenphi, on='ketoan_id', how='left')
# Merge hocvien_chuyephi
chuyenphi = chuyenphi.merge(hocvien_chuyenphi, on='hv_id', how='left')
chuyenphi = chuyenphi[['created_at', 'hv_fullname',
'ketoan_coso', 'note', 'is_price']]
# Add column Phi Chuyen
chuyenphi['phí chuyển'] = chuyenphi.is_price * 0.1
# Add column Tien con lai sau phi
chuyenphi['thực thu chuyển phí'] = chuyenphi.is_price - \
chuyenphi['phí chuyển']
# Change data type
chuyenphi = chuyenphi.astype(
{'created_at': 'datetime64[ns]'})
# Sort
chuyenphi = chuyenphi.sort_values(by='created_at', ascending=False)
chuyenphi = chuyenphi.query(
"created_at >= @ketoan_start_time and created_at <= @ketoan_end_time")
# Rename columns
# chuyenphi.columns = [["created_at", "Họ tên", "ketoan_coso", "Ghi chú", "Học phí chuyển", "Phí chuyển", "Còn lại sau phí"]]
chuyenphi = chuyenphi.groupby('ketoan_coso', as_index=False)[
'thực thu chuyển phí'].sum()
chuyenphi = rename_lop(chuyenphi, 'ketoan_coso')
# "_______________" Thực thu kết thúc
# Filter ketthuc
orders_ketthuc = orders.query("ketoan_active == 5 and deleted_at.isnull()")
# Merge orders_ketthuc and diemdanh_details
df = diemdanh_details[['ketoan_id', 'giohoc']]\
.merge(orders_ketthuc, on='ketoan_id', how='right').groupby(
['ketoan_id', 'ketoan_coso', 'remaining_time', 'ketoan_tientrengio', 'date_end'], as_index=False).giohoc.sum()
# Add 2 more columns
df['gio_con_lai'] = df.remaining_time - df.giohoc
df['thực thu kết thúc'] = df.gio_con_lai * df.ketoan_tientrengio
# Convert to datetime
df['date_end'] = pd.to_datetime(df['date_end'])
# Filter gioconlai > 0 and time
thucthu_ketthuc = df.query("gio_con_lai > 0")\
.query("date_end >= @ketoan_start_time and date_end <= @ketoan_end_time")
thucthu_ketthuc = thucthu_ketthuc.merge(
orders[['hv_id', 'ketoan_id']], on='ketoan_id')
thucthu_ketthuc = thucthu_ketthuc.groupby("ketoan_coso", as_index=False)[
'thực thu kết thúc'].sum()
thucthu_ketthuc = rename_lop(thucthu_ketthuc, 'ketoan_coso')
# "_______________"
overtime_salary = sal_diem_over_group.query('working_status_x != "Ngoài giờ"')\
.merge(salary[['Họ và tên', 'working_status']], left_on='Họ và tên', right_on='Họ và tên')
overtime_salary['out_div_total'] = overtime_salary['salary_gio_cong'] / \
(overtime_salary['salary_ngay_cong'] +
overtime_salary['salary_gio_cong'])
overtime_salary = overtime_salary[[
'Họ và tên', 'salary_ngay_cong', 'salary_gio_cong', 'out_div_total']]
overtime_salary['out_div_total'] = round(
overtime_salary['out_div_total'] * 100, 2)
overtime_salary_fulltime = overtime_salary.query("salary_ngay_cong != 0")
# "_______________" thucthu điểm danh and chuyen phi
thucthu_hocvien_lop = thucthu_hocvien_lop.merge(
chuyenphi, left_on='ketoan_coso', right_on='ketoan_coso', how='left')\
.merge(thucthu_ketthuc, left_on='ketoan_coso', right_on='ketoan_coso')
# Renam thucthu => thuc thu diem danh
thucthu_hocvien_lop = thucthu_hocvien_lop.rename(
columns={'thucthu': "thực thu điểm danh"})
# Fillna with 0
thucthu_hocvien_lop.fillna(0, inplace=True)
# Add all thucthu
thucthu_hocvien_lop['tổng thực thu'] = thucthu_hocvien_lop['thực thu chuyển phí'] + \
thucthu_hocvien_lop['thực thu kết thúc'] + \
thucthu_hocvien_lop['thực thu điểm danh']
# Add ty lệ thực thu
thucthu_hocvien_lop['tỷ trọng tổng thực thu'] = thucthu_hocvien_lop['tổng thực thu'].apply(
lambda x: round(x/thucthu_hocvien_lop['tổng thực thu'].sum()*100, 2))
# create a new row with the sum of each numerical column
totals = thucthu_hocvien_lop.select_dtypes(include=[float, int]).sum()
totals["lop_cn"] = "Grand total"
# append the new row to the dataframe
thucthu_hocvien_lop = thucthu_hocvien_lop.append(totals, ignore_index=True)
# Add % in tỷ trọng tổng thực thu
thucthu_hocvien_lop["tỷ trọng tổng thực thu"] = thucthu_hocvien_lop["tỷ trọng tổng thực thu"].apply(
lambda x: '{:.2%}'.format(x/100))
salary_thucthu_grand_total['Tổng lương / thực thu'] = salary_thucthu_grand_total['Tổng lương / thực thu'].apply(
lambda x: '{:.2%}'.format(x/100))
# define a function
@ st.cache
def thousands_divider(df, col):
df[col] = df[col].apply(
lambda x: '{:,.0f}'.format(x))
return df
thucthu_hocvien_lop = thousands_divider(
thucthu_hocvien_lop, 'tổng thực thu')
thucthu_hocvien_lop = thousands_divider(
thucthu_hocvien_lop, 'thực thu điểm danh')
thucthu_hocvien_lop = thousands_divider(
thucthu_hocvien_lop, 'thực thu chuyển phí')
thucthu_hocvien_lop = thousands_divider(
thucthu_hocvien_lop, 'thực thu kết thúc')
thucthu_hocvien_lop = thucthu_hocvien_lop.set_index("lop_cn")
thucthu_hocvien_lop.index.names = ['Chi nhánh']
# Show tables
st.plotly_chart(fig2, use_container_width=True)
st.subheader("Thưc thu theo chi nhánh")
st.dataframe(thucthu_hocvien_lop.drop(["ketoan_coso", "total_students", "total_classes", "thucthu_div_hocvien", "thucthu_div_lophoc"],
axis=1).style.background_gradient().set_precision(0), use_container_width=True)
# Show Chi nhanh by 2 columns
st.plotly_chart(fig10, use_container_width=True)
st.plotly_chart(fig9, use_container_width=True)
# left_column, right_column = st.columns([1, 2])
# left_column.plotly_chart(fig10, use_container_width=True)
# right_column.plotly_chart(fig9, use_container_width=True)
# left_column, right_column = st.columns(2)
# left_column.plotly_chart(fig7, use_container_width=True)
# right_column.plotly_chart(fig8, use_container_width=True)
# left_column, right_column = st.columns(2)
# left_column.plotly_chart(fig5, use_container_width=True)
# right_column.plotly_chart(fig6, use_container_width=True)
# left_column, right_column = st.columns(2)
# left_column.plotly_chart(fig1, use_container_width=True)
# right_column.plotly_chart(fig2, use_container_width=True)
left_column, right_column = st.columns(2)
left_column.plotly_chart(fig3, use_container_width=True)
right_column.plotly_chart(fig3_1, use_container_width=True)
""
fig4 = plotly_chart(overtime_salary_fulltime[['Họ và tên', 'out_div_total']].sort_values(
"out_div_total", ascending=True), "Họ và tên", 'out_div_total', 'out_div_total',
"Tỷ lệ lương ngoài giờ / trong giờ của giáo viên fulltime", '', 'Tỷ lệ')
fig4.update_layout(height=800, width=800)
st.plotly_chart(fig4)