Update staffing management to enhance payroll and hiring functionalities
ci / server (push) Failing after 3m39s
ci / client (push) Successful in 14s

- Increased the `MonthlyPayrollCap` from 10,000 to 40,000, allowing for greater flexibility in hiring and subject assignments.
- Revised payroll calculation logic to ensure that staff members are compensated based on their actual weekly hours, with a minimum payment reflecting one full rate.
- Updated documentation to clarify the new payroll structure and its implications for hiring and subject assignments.
- Enhanced tests to validate the new payroll cap and ensure proper functionality in staffing scenarios, including the handling of uncovered subjects.
- Improved localization strings to reflect changes in staffing and payroll terminology.
This commit is contained in:
Leonid Pershin
2026-08-19 12:51:38 +03:00
parent d61240d5c1
commit 25ce26064d
20 changed files with 376 additions and 112 deletions
+4
View File
@@ -142,6 +142,8 @@ const ru = {
staffColSkills: 'Навыки',
staffColPosition: 'Должность',
staffColSubjects: 'Предметы',
staffColHours: 'Часов',
staffHours: '{n} ч/нед',
staffColPay: 'В месяц',
staffAsk: '{hourly}/ч · {monthly}/мес',
staffSubjectRange: '{label} ({min}{max})',
@@ -331,6 +333,8 @@ const en: Messages = {
staffColSkills: 'Skills',
staffColPosition: 'Position',
staffColSubjects: 'Subjects',
staffColHours: 'Hours',
staffHours: '{n} h/wk',
staffColPay: 'Monthly',
staffAsk: '{hourly}/h · {monthly}/mo',
staffSubjectRange: '{label} ({min}{max})',
+1
View File
@@ -320,6 +320,7 @@ export interface StaffMember {
readonly position: string;
readonly positionLabel: string;
readonly hourlyWageAsk: number;
readonly weeklyHours: number;
readonly monthlyPay: number;
readonly subjects: readonly DefLabel[];
}
@@ -338,6 +338,7 @@ export class ManagementPanel {
el('th', { text: t('staffColName') }),
el('th', { text: t('staffColPosition') }),
el('th', { text: t('staffColSubjects') }),
el('th', { text: t('staffColHours') }),
el('th', { text: t('staffColPay') }),
),
),
@@ -360,6 +361,7 @@ export class ManagementPanel {
name,
el('td', { text: member.positionLabel }),
el('td', { text: member.subjects.map((subject) => subject.label).join(', ') || '—' }),
el('td', { text: t('staffHours', { n: formatHours(member.weeklyHours) }) }),
el('td', { text: formatMoney(member.monthlyPay) }),
);
body.append(row);
@@ -668,6 +670,10 @@ function fillSelect(
}
}
function formatHours(value: number): string {
return new Intl.NumberFormat(intlTag(), { maximumFractionDigits: 1 }).format(value);
}
function formatMoney(value: number): string {
return new Intl.NumberFormat(intlTag(), { maximumFractionDigits: 2 }).format(value);
}