Initial commit: TrueConf Chatbot КЛЕВЕР
This commit is contained in:
@@ -0,0 +1,322 @@
|
||||
# /opt/trueconf_bot/lk/payslip_service.py
|
||||
import calendar
|
||||
import tempfile
|
||||
from itertools import zip_longest
|
||||
from weasyprint import HTML
|
||||
import config.config as config
|
||||
|
||||
# Перевод английских системных месяцев в русские наименования для бланка PDF
|
||||
ENG_TO_RU_MONTHS = {
|
||||
"January": "Январь", "February": "Февраль", "March": "Март",
|
||||
"April": "Апрель", "May": "Май", "June": "Июнь",
|
||||
"July": "Июль", "August": "Август", "September": "Сентябрь",
|
||||
"October": "Октябрь", "November": "Ноябрь", "December": "Декабрь"
|
||||
}
|
||||
|
||||
def format_currency(summa):
|
||||
try:
|
||||
if summa is None:
|
||||
return "0,00"
|
||||
f_summa = float(summa)
|
||||
return f"{f_summa:,.2f}".replace(",", " ").replace(".", ",")
|
||||
except:
|
||||
return str(summa)
|
||||
|
||||
def translate_period(period_str):
|
||||
if not period_str:
|
||||
return ""
|
||||
for eng, ru in ENG_TO_RU_MONTHS.items():
|
||||
if eng in period_str:
|
||||
return period_str.replace(eng, ru)
|
||||
return period_str
|
||||
|
||||
def get_latest_payslip_months(cursor, card_id: str) -> list:
|
||||
query = """
|
||||
SELECT DISTINCT TOP 6 (t.TYEAR * 12 + t.TMONTH) as CMONTH
|
||||
FROM UOV_SELFSERVICE_PR_EMP e
|
||||
JOIN UOV_SELFSERVICE_PR_CARD c on c.ID = e.CARD_ID
|
||||
JOIN UOV_SELFSERVICE_SL_YTAX t on t.CARD_ID = e.CARD_ID
|
||||
JOIN UOV_SELFSERVICE_PR_TRANS tr on tr.EMP_ID = e.ID
|
||||
JOIN UOV_SELFSERVICE_ST_APPOINT a on a.ID = tr.APPOINT_ID
|
||||
JOIN UOV_SELFSERVICE_HR_FIRM f on f.ID = e.FIRM_ID
|
||||
WHERE c.ID = %s
|
||||
ORDER BY CMONTH DESC
|
||||
"""
|
||||
cursor.execute(query, (card_id,))
|
||||
months = cursor.fetchall()
|
||||
if not months:
|
||||
raise Exception("Отсутствуют расчетные периоды.")
|
||||
return [m[0] for m in months]
|
||||
|
||||
def create_payslip_pdf(month_name, target_tyear,
|
||||
header_sys, header_wage, header_deduct, header_base,
|
||||
earnings_rows, deductions_rows, noncash_rows, payout_rows,
|
||||
total_earned, total_withheld, total_noncash, total_payouts,
|
||||
debt_comp_start, debt_emp_start, debt_comp_end, debt_emp_end, net_pay):
|
||||
tbody_html = ""
|
||||
tbody_html += f"""
|
||||
<tr>
|
||||
<td colspan="6" class="section-title">1. Начислено</td>
|
||||
<td colspan="4" class="section-title">2. Удержано</td>
|
||||
</tr>
|
||||
"""
|
||||
|
||||
for earn, ded in zip_longest(earnings_rows, deductions_rows):
|
||||
if earn:
|
||||
earn_name = str(earn[0]).strip()
|
||||
earn_days = f"{earn[1]:g}".replace('.', ',') if earn[1] else ""
|
||||
earn_hours = f"{earn[2]:g}".replace('.', ',') if earn[2] else ""
|
||||
earn_prc = f"{earn[3]:g}" if earn[3] else ""
|
||||
earn_period = translate_period(earn[4] or "")
|
||||
earn_summa = format_currency(earn[5])
|
||||
earn_html = f'<td class="left-align">{earn_name}</td><td class="center-align">{earn_days}</td><td class="center-align">{earn_hours}</td><td class="center-align">{earn_prc}</td><td class="center-align">{earn_period}</td><td>{earn_summa}</td>'
|
||||
else:
|
||||
earn_html = '<td style="border-bottom: none; border-left: none;"></td><td style="border-bottom: none;"></td><td style="border-bottom: none;"></td><td style="border-bottom: none;"></td><td style="border-bottom: none;"></td><td style="border-bottom: none; border-right: none;"></td>'
|
||||
|
||||
if ded:
|
||||
ded_name = str(ded[0]).strip()
|
||||
ded_prc = f"{ded[1]:.0f}" if ded[1] else ""
|
||||
ded_period = translate_period(ded[2] or "")
|
||||
ded_summa = format_currency(ded[3])
|
||||
ded_html = f'<td class="left-align">{ded_name}</td><td class="center-align">{ded_prc}</td><td class="center-align">{ded_period}</td><td>{ded_summa}</td>'
|
||||
else:
|
||||
ded_html = '<td style="border-bottom: none; border-left: none; border-right: none;" colspan="4"></td>'
|
||||
|
||||
tbody_html += f"<tr>{earn_html}{ded_html}</tr>"
|
||||
|
||||
tbody_html += f"""
|
||||
<tr class="totals">
|
||||
<td class="left-align" colspan="5">Всего начислено</td><td>{format_currency(total_earned)}</td>
|
||||
<td class="left-align" colspan="3">Всего удержано</td><td>{format_currency(total_withheld)}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="6" class="section-title">3. Доходы в неденежной форме</td>
|
||||
<td colspan="4" class="section-title">4. Выплачено</td>
|
||||
</tr>
|
||||
"""
|
||||
|
||||
for nc, pay in zip_longest(noncash_rows, payout_rows):
|
||||
if nc:
|
||||
nc_name = str(nc[0]).strip()
|
||||
nc_period = translate_period(nc[1] or "")
|
||||
nc_summa = format_currency(nc[2])
|
||||
nc_html = f'<td class="left-align" colspan="4">{nc_name}</td><td class="center-align">{nc_period}</td><td>{nc_summa}</td>'
|
||||
else:
|
||||
nc_html = '<td style="border-top: none; border-bottom: none; border-left: none;"></td><td style="border-top: none; border-bottom: none;"></td><td style="border-top: none; border-bottom: none;"></td><td style="border-top: none; border-bottom: none;"></td><td style="border-top: none; border-bottom: none;"></td><td style="border-top: none; border-bottom: none; border-right: none;"></td>'
|
||||
|
||||
if pay:
|
||||
pay_name = str(pay[0]).strip()
|
||||
pay_period = translate_period(pay[1] or "")
|
||||
pay_summa = format_currency(pay[2])
|
||||
pay_html = f'<td class="left-align" colspan="2">{pay_name}</td><td class="center-align">{pay_period}</td><td>{pay_summa}</td>'
|
||||
else:
|
||||
pay_html = '<td style="border-top: none; border-bottom: none; border-left: none; border-right: none;" colspan="4"></td>'
|
||||
|
||||
tbody_html += f"<tr>{nc_html}{pay_html}</tr>"
|
||||
|
||||
tbody_html += f"""
|
||||
<tr class="totals">
|
||||
<td class="left-align" colspan="5">Всего доходов в неденежной форме</td><td>{format_currency(total_noncash)}</td>
|
||||
<td class="left-align" colspan="3">Всего выплачено</td><td>{format_currency(total_payouts)}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="left-align" colspan="5">Долг за предприятием на начало месяца</td><td>{format_currency(debt_comp_start)}</td>
|
||||
<td class="left-align" colspan="3">Долг за предприятием на конец месяца</td><td>{format_currency(debt_comp_end)}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="left-align" colspan="5">Долг за работником на начало месяца</td><td>{format_currency(debt_emp_start)}</td>
|
||||
<td class="left-align" colspan="3">Долг за работником на конец месяца</td><td>{format_currency(debt_emp_end)}</td>
|
||||
</tr>
|
||||
<tr class="totals">
|
||||
<td colspan="6" class="empty-cell"></td>
|
||||
<td class="left-align section-title" colspan="3"><b>5. Выплачено денежными средствами</b></td><td class="section-title"><b>{format_currency(net_pay)}</b></td>
|
||||
</tr>
|
||||
"""
|
||||
|
||||
html_template = f"""
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<style>
|
||||
@page {{ size: A4 landscape; margin: 15mm; background-color: #ffffff; }}
|
||||
body {{ font-family: Arial, sans-serif; font-size: 11px; color: #333; margin: 0; padding: 0; }}
|
||||
h2 {{ text-align: center; margin-bottom: 15px; font-size: 16px; font-weight: normal; }}
|
||||
table {{ width: 100%; border-collapse: collapse; margin-bottom: 10px; }}
|
||||
th, td {{ border: 1px solid #a0a0a0; padding: 5px 8px; text-align: right; vertical-align: middle; }}
|
||||
th {{ background-color: #f2f2f2; text-align: center; font-weight: normal; color: #555; }}
|
||||
.header-table td {{ border: 1px solid #a0a0a0; text-align: left; background-color: #fcfcfc; }}
|
||||
.left-align {{ text-align: left; }}
|
||||
.center-align {{ text-align: center; }}
|
||||
.section-title {{ background-color: #fcfcfc; font-weight: bold; text-align: left; padding-top: 10px; padding-bottom: 10px; }}
|
||||
.totals {{ background-color: #fcfcfc; font-weight: bold; }}
|
||||
.empty-cell {{ border: none; }}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h2><b>Расчетный лист за {month_name} {target_tyear} г.</b></h2>
|
||||
<table class="header-table" style="margin-bottom: 15px;">
|
||||
<tr><td style="width: 60%;">Система оплаты: {header_sys}</td><td style="width: 40%;">Оклад: {format_currency(header_wage)}</td></tr>
|
||||
<tr><td colspan="2">Стандартные вычеты за месяц: {format_currency(header_deduct)}</td></tr>
|
||||
<tr><td colspan="2">Облагаемая база по ставке 13%: {format_currency(header_base)}</td></tr>
|
||||
</table>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 20%;">Вид</th><th>Дни</th><th>Часы</th><th>%</th><th>Период</th><th>Сумма</th>
|
||||
<th style="width: 20%;">Вид</th><th>%</th><th>Период</th><th>Сумма</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{tbody_html}
|
||||
</tbody>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
temp_pdf = tempfile.NamedTemporaryFile(delete=False, suffix='.pdf')
|
||||
HTML(string=html_template).write_pdf(temp_pdf.name)
|
||||
return temp_pdf.name
|
||||
|
||||
def build_payslip_data(cursor, card_id: str, target_cmonth: int) -> tuple:
|
||||
tyear = (target_cmonth - 1) // 12
|
||||
tmonth = (target_cmonth - 1) % 12 + 1
|
||||
_, last_day = calendar.monthrange(tyear, tmonth)
|
||||
|
||||
date_start = f"{tyear}-{tmonth:02d}-01"
|
||||
date_end = f"{tyear}-{tmonth:02d}-{last_day:02d}"
|
||||
date_params = (date_start, date_start, date_end, date_end, date_end)
|
||||
|
||||
months_ru = {1: "Январь", 2: "Февраль", 3: "Март", 4: "Апрель", 5: "Май", 6: "Июнь",
|
||||
7: "Июль", 8: "Август", 9: "Сентябрь", 10: "Октябрь", 11: "Ноябрь", 12: "Декабрь"}
|
||||
month_name = months_ru.get(tmonth, f"{tmonth:02d}")
|
||||
|
||||
# FIRM_ID по c.ID
|
||||
q_firm = """
|
||||
select e.FIRM_ID, f.SNAME from (select e.id, e.FIRM_ID from UOV_SELFSERVICE_PR_EMP e
|
||||
join UOV_SELFSERVICE_PR_CARD c on c.ID=e.CARD_ID where c.ID = %s
|
||||
group by e.ID, e.FIRM_ID ) as e
|
||||
join UOV_SELFSERVICE_PR_TRANS t on t.EMP_ID = e.ID
|
||||
join UOV_SELFSERVICE_HR_FIRM f on f.ID = e.FIRM_ID
|
||||
where ((t.D_FROM <= %s and t.D_TO >= %s) or (t.D_FROM <= %s and t.D_TO >= %s) or (t.D_FROM <= %s and t.D_TO = '1999-12-31'))
|
||||
group by e.FIRM_ID, f.SNAME
|
||||
"""
|
||||
cursor.execute(q_firm, (card_id, *date_params))
|
||||
firm_row = cursor.fetchone()
|
||||
if not firm_row:
|
||||
raise Exception("Не удалось определить FIRM_ID для сотрудника в указанном периоде.")
|
||||
firm_id = firm_row[0]
|
||||
|
||||
# ШАПКА по c.ID
|
||||
q_header = """
|
||||
select s.NAME as [NAME], ROUND(t.WAGE, 2), isnull(sum(yt.u21 + yt.u30), 0), ROUND(isnull(sum(yt.n200 + yt.n5100 - yt.u21 - yt.u30 - yt.u42 - yt.u99), 0), 2)
|
||||
from (select e.ID, e.FIRM_ID, e.CARD_ID from UOV_SELFSERVICE_PR_EMP e join UOV_SELFSERVICE_PR_CARD c on c.ID=e.CARD_ID
|
||||
where c.ID = %s and e.FIRM_ID=%s group by e.ID, e.FIRM_ID, e.CARD_ID ) as e
|
||||
join UOV_SELFSERVICE_pr_trans t on t.EMP_ID = e.ID join UOV_SELFSERVICE_hr_syspay s on s.ID = t.SYSPAY_ID
|
||||
join UOV_SELFSERVICE_sl_ytax yt on yt.CARD_ID = e.CARD_ID and yt.FIRM_ID = e.FIRM_ID
|
||||
where e.FIRM_ID = %s and yt.tmonth = %s and yt.tyear = %s
|
||||
and ((t.D_FROM <= %s and t.D_TO >= %s) or (t.D_FROM <= %s and t.D_TO >= %s) or (t.D_FROM <= %s and t.D_TO = '1999-12-31'))
|
||||
and t.tp_abbr='CUR' group by s.NAME, t.WAGE, t.D_FROM order by t.D_FROM desc
|
||||
"""
|
||||
cursor.execute(q_header, (card_id, firm_id, firm_id, tmonth, tyear, *date_params))
|
||||
h_row = cursor.fetchone()
|
||||
header_sys = str(h_row[0]) if h_row else "Неизвестная система"
|
||||
header_wage = float(h_row[1]) if h_row and h_row[1] else 0.0
|
||||
header_deduct = float(h_row[2]) if h_row and h_row[2] else 0.0
|
||||
header_base = float(h_row[3]) if h_row and h_row[3] else 0.0
|
||||
|
||||
# НАЧИСЛЕНО по c.ID
|
||||
q_earn = """
|
||||
select p.NAME AS [NAME], ROUND(l.days, 1), ROUND(l.hours, 1), CAST(l.prc as INT), convert(varchar, i.D_FROM,104)+'-'+convert(varchar, i.D_TO,104), ROUND(l.summa, 2)
|
||||
from (select e.id, e.FIRM_ID from UOV_SELFSERVICE_PR_EMP e join UOV_SELFSERVICE_PR_CARD c on c.ID=e.CARD_ID where c.ID = %s and e.FIRM_ID=%s group by e.ID, FIRM_ID ) as e
|
||||
join UOV_SELFSERVICE_sl_lic l on l.EMP_ID = e.ID join UOV_SELFSERVICE_sl_pay p on p.ID = l.PAY_ID join UOV_SELFSERVICE_pr_ill i on i.ID=l.ID_MAIN
|
||||
join (select MAX(id) as id, EMP_ID from UOV_SELFSERVICE_pr_trans t where ((t.D_FROM <= %s and t.D_TO >= %s) or (t.D_FROM <= %s and t.D_TO >= %s) or (t.D_FROM <= %s and t.D_TO = '1999-12-31')) group by EMP_ID) tr on tr.EMP_ID = e.ID
|
||||
where l.t_pay = 1 and l.pay_id not in (264,301,262) and l.n_dirm = 6 and l.cmonth = %s
|
||||
UNION ALL
|
||||
select max(p.NAME) AS [NAME], sum(l.days), ROUND(sum(l.hours), 1), CAST(l.prc as INT), (DateName(month, DateAdd(month, l.TMONTH, 0) - 1) +' '+ cast(l.TYEAR as varchar)), ROUND(isnull(sum(l.summa),0), 2)
|
||||
from(select e.id, e.FIRM_ID from UOV_SELFSERVICE_PR_EMP e join UOV_SELFSERVICE_PR_CARD c on c.ID=e.CARD_ID where c.ID = %s and e.FIRM_ID=%s group by e.ID, FIRM_ID ) as e
|
||||
join (select MAX(id) as id, EMP_ID from UOV_SELFSERVICE_pr_trans t where ((t.D_FROM <= %s and t.D_TO >= %s) or (t.D_FROM <= %s and t.D_TO >= %s) or (t.D_FROM <= %s and t.D_TO = '1999-12-31')) group by EMP_ID) tr on tr.EMP_ID = e.ID
|
||||
join UOV_SELFSERVICE_sl_lic l on l.EMP_ID = e.ID join UOV_SELFSERVICE_sl_pay p on p.ID = l.PAY_ID
|
||||
where l.t_pay = 1 and l.pay_id not in (264,301,262) and l.n_dirm <> 6 and l.cmonth = %s
|
||||
group by l.emp_id,l.pay_id,l.tmonth,l.prc, case l.PAY_ID when 17 then l.id else 0 end, l.TYEAR order by 6 DESC
|
||||
"""
|
||||
cursor.execute(q_earn, (card_id, firm_id, *date_params, target_cmonth, card_id, firm_id, *date_params, target_cmonth))
|
||||
earnings_rows = cursor.fetchall()
|
||||
|
||||
# УДЕРЖАНО по c.ID
|
||||
q_deduct = """
|
||||
select max(p.NAME) AS [NAME], CAST(l.prc as INT), ISNULL(DATENAME(month, DATEADD(month, l.tmonth, 0) - 1) + ' ' + CAST(NULLIF(l.TYEAR, 0) AS varchar), ''), ROUND(isnull(sum(l.summa),0), 2)
|
||||
from (select e.id, e.FIRM_ID from UOV_SELFSERVICE_PR_EMP e join UOV_SELFSERVICE_PR_CARD c on c.ID=e.CARD_ID where c.ID = %s and e.FIRM_ID=%s group by e.ID, FIRM_ID ) as e
|
||||
JOIN UOV_SELFSERVICE_sl_lic l ON l.EMP_ID = e.ID JOIN UOV_SELFSERVICE_sl_pay p ON p.ID = l.PAY_ID
|
||||
join (select MAX(id) as id, EMP_ID from UOV_SELFSERVICE_pr_trans t where ((t.D_FROM <= %s and t.D_TO >= %s) or (t.D_FROM <= %s and t.D_TO >= %s) or (t.D_FROM <= %s and t.D_TO = '1999-12-31')) group by EMP_ID) tr on tr.EMP_ID = e.ID
|
||||
where l.t_pay=2 and l.pay_id not in (301,490) and l.pay_id not in (305, 308, 316, 328, 360, 364) and l.cmonth = %s
|
||||
group by l.emp_id,l.pay_id,l.tmonth,l.prc, l.id, l.TYEAR order by 4 DESC
|
||||
"""
|
||||
cursor.execute(q_deduct, (card_id, firm_id, *date_params, target_cmonth))
|
||||
deductions_rows = cursor.fetchall()
|
||||
|
||||
# ДОЛГИ по c.ID
|
||||
q_debts = """
|
||||
select l.pay_id, ROUND(isnull(sum(l.summa),0), 2) from (select e.ID, e.FIRM_ID from UOV_SELFSERVICE_PR_EMP e join UOV_SELFSERVICE_PR_CARD c on c.ID=e.CARD_ID where c.ID = %s and e.FIRM_ID=%s group by e.ID, FIRM_ID ) as e
|
||||
join UOV_SELFSERVICE_sl_lic l on l.EMP_ID = e.id join (select MAX(id) as id, EMP_ID from UOV_SELFSERVICE_pr_trans t where ((t.D_FROM <= %s and t.D_TO >= %s) or (t.D_FROM <= %s and t.D_TO >= %s) or (t.D_FROM <= %s and t.D_TO = '1999-12-31')) group by EMP_ID) tr on tr.EMP_ID = e.ID
|
||||
where l.cmonth = %s and l.pay_id in (264, 301, 490) group by l.pay_id
|
||||
"""
|
||||
cursor.execute(q_debts, (card_id, firm_id, *date_params, target_cmonth))
|
||||
debt_rows = cursor.fetchall()
|
||||
debt_comp_start, debt_emp_start, debt_emp_end = 0.0, 0.0, 0.0
|
||||
for r in debt_rows:
|
||||
if r[0] == 264: debt_comp_start = float(r[1])
|
||||
elif r[0] == 301: debt_emp_start = float(r[1])
|
||||
elif r[0] == 490: debt_emp_end = float(r[1])
|
||||
|
||||
# НЕ ДЕНЕЖНЫЕ по c.ID
|
||||
q_noncash = """
|
||||
select t.NAME AS [NAME], (DateName(month, CAST(%s as date)) +' '+ DateName(YEAR, CAST(%s as date))), ROUND(isnull(p.summa, 0), 2)
|
||||
from (select e.id, e.FIRM_ID from UOV_SELFSERVICE_PR_EMP e join UOV_SELFSERVICE_PR_CARD c on c.ID=e.CARD_ID where c.ID = %s and e.FIRM_ID=%s group by e.ID, FIRM_ID ) as e
|
||||
join UOV_SELFSERVICE_sl_profit p on p.EMP_ID = e.ID join UOV_SELFSERVICE_sl_tprofit t on t.ID = p.TPROFIT_ID
|
||||
join (select MAX(id) as id, EMP_ID from UOV_SELFSERVICE_pr_trans tr where ((tr.D_FROM <= %s and tr.D_TO >= %s) or (tr.D_FROM <= %s and tr.D_TO >= %s) or (tr.D_FROM <= %s and tr.D_TO = '1999-12-31')) group by EMP_ID) tr2 on tr2.EMP_ID = e.ID
|
||||
where p.cmonth = %s and t.id != 9999
|
||||
"""
|
||||
cursor.execute(q_noncash, (date_start, date_start, card_id, firm_id, *date_params, target_cmonth))
|
||||
noncash_rows = cursor.fetchall()
|
||||
|
||||
# ВЫПЛАЧЕНО по c.ID
|
||||
q_payout = """
|
||||
select p.NAME AS [NAME], (DateName(month, DateAdd(month, l.TMONTH, 0) - 1) +' '+ cast(l.TYEAR as varchar)), ROUND(sum(isnull(l.summa, 0)), 2)
|
||||
from (select e.id, e.FIRM_ID from UOV_SELFSERVICE_PR_EMP e join UOV_SELFSERVICE_PR_CARD c on c.ID=e.CARD_ID where c.ID = %s and e.FIRM_ID=%s group by e.ID, FIRM_ID ) as e
|
||||
join UOV_SELFSERVICE_sl_lic l on l.EMP_ID = e.ID join UOV_SELFSERVICE_sl_pay p on p.ID =l.PAY_ID
|
||||
join (select MAX(id) as id, EMP_ID from UOV_SELFSERVICE_pr_trans tr where ((tr.D_FROM <= %s and tr.D_TO >= %s) or (tr.D_FROM <= %s and tr.D_TO >= %s) or (tr.D_FROM <= %s and tr.D_TO = '1999-12-31')) group by EMP_ID) tr2 on tr2.EMP_ID = e.ID
|
||||
where l.t_pay = 2 and l.cmonth = %s and l.pay_id in (305, 308, 316, 328, 360, 364) group by p.NAME, l.TMONTH, l.TYEAR
|
||||
"""
|
||||
cursor.execute(q_payout, (card_id, firm_id, *date_params, target_cmonth))
|
||||
payout_rows = cursor.fetchall()
|
||||
|
||||
total_earned = sum(float(r[5]) for r in earnings_rows if r[5])
|
||||
total_withheld = sum(float(r[3]) for r in deductions_rows if r[3])
|
||||
total_noncash = sum(float(r[2]) for r in noncash_rows if r[2])
|
||||
total_payouts = sum(float(r[2]) for r in payout_rows if r[2])
|
||||
|
||||
# Расчет долга по формуле СибЦема
|
||||
debt_comp_end = total_earned - total_withheld - total_payouts
|
||||
net_pay = total_earned - total_withheld
|
||||
|
||||
response = f"💰 <b>Расчетный листок за {month_name} {tyear} г.</b>\n\n<b>1. Начислено</b>\n"
|
||||
for row in earnings_rows:
|
||||
time_spent = f" ({float(row[1]):g} дн. / {float(row[2]):g} ч.)" if (row[1] or row[2]) else ""
|
||||
response += f"🔹 {str(row[0]).strip()}{time_spent}: <b>{format_currency(row[5])} руб.</b>\n"
|
||||
response += f"<b>Всего начислено: {format_currency(total_earned)} руб.</b>\n\n<b>2. Удержано</b>\n"
|
||||
for row in deductions_rows:
|
||||
prc_str = f" ({int(row[1])}%)" if row[1] else ""
|
||||
response += f"🔹 {str(row[0]).strip()}{prc_str}: <b>{format_currency(row[3])} руб.</b>\n"
|
||||
response += f"<b>Всего удержано: {format_currency(total_withheld)} руб.</b>\n\n<b>3. Доходы в неденежной форме:</b> {format_currency(total_noncash)} руб.\n\n<b>4. Выплачено</b>\n"
|
||||
for row in payout_rows:
|
||||
response += f"🔹 {str(row[0]).strip()}: <b>{format_currency(row[2])} руб.</b>\n"
|
||||
response += f"<b>Всего выплачено: {format_currency(total_payouts)} руб.</b>\n\n<i>Долг за предприятием на конец месяца: {format_currency(debt_comp_end)} руб.</i>\n<i>Долг за работником на конец месяца: {format_currency(debt_emp_end)} руб.</i>\n\n<b>5. Выплачено денежными средствами: {format_currency(net_pay)} руб.</b>"
|
||||
|
||||
pdf_path = create_payslip_pdf(
|
||||
month_name, tyear, header_sys, header_wage, header_deduct, header_base,
|
||||
earnings_rows, deductions_rows, noncash_rows, payout_rows,
|
||||
total_earned, total_withheld, total_noncash, total_payouts,
|
||||
debt_comp_start, debt_emp_start, debt_comp_end, debt_emp_end, net_pay
|
||||
)
|
||||
return response, pdf_path
|
||||
Reference in New Issue
Block a user