Евгений Колесников 11 сар өмнө
parent
commit
036337f5c9

+ 301 - 0
articles/testing_lab_ws23.md

@@ -0,0 +1,301 @@
+# Разработка библиотеки по расчету заработной платы
+
+Разработайте библиотеку, которая позволит рассчитать заработную плату сотрудников.
+
+Необходимо обязательно следовать правилам именования библиотек, классов и методов в них. В случае ошибок в рамках именования ваша работа не может быть проверена и ваш результат не будет зачтен. Классы и методы должны содержать модификатор `public` (если это реализуемо в рамках платформы), чтобы внешние приложения могли получить к ним доступ. 
+
+По трудовому законодательству базовый объем рабочей недели составляет 40 часов и рассчитывается как 5 рабочих дней по 8 часов. Для работников предполагается премирование за сверхурочную работу.
+
+## Алгоритм расчета премии:
+
+* за каждый переработанный час в рабочие дни (учитываются только рабочие дни)  работнику оплачиваются сверхурочные в размере 2 процентов от оклада,
+* работа по выходным также премируется, процент премии рассчитывается пропорционально указанному выше алгоритму - за отработанный час 2 процента от оклада, при расчете отработанных часов на выходных не учитываются недоработки в будни. То есть даже если сотрудник отработал в будни 26 часов, что меньше базового объема работы на 14 часов, работа в выходные будет оплачиваться как премиальные, а не как доработка 14 часов до базового объема недельной работы;
+* максимальный процент премии в месяц составляет 60 процентов от оклада,
+* при превышении максимального процента время переносится на отгулы в соотношении 8 часов = 1 отгул, не целая часть от деления количества часов на количество дней отгулов обнуляется и не переносится на следующий месяц;
+* если задача завершена раньше крайнего срока исполнения, то исполнитель получает премию 2 процента от оклада, расчет ведется по каждой выполняемой задаче сотрудника;
+* если сотрудник брал больничный, то базовый объем часов считается не за календарную неделю, а за отработанные дни из расчета 8 часов в день,
+* в случае болезни сотрудник получает пособие по больничному листу, размер которого определяется как средняя оплата за 1 рабочий день по предыдущему месяцу работы, умноженному на количество дней больничного листа, и выплачивается в месяц закрытия больничного листа. Если есть данные про предыдущему месяцу работы, то расчет ведется по среднему значению оплаты, если сотрудник только устроился на работу и данных по предыдущему месяцу работы нет, то среднее значение оплаты за 1 рабочий день принимается за 400 руб.
+
+## Штрафы:
+
+На работника начисляются штрафы за невыполненную в срок задачу, за каждый рабочий день просрочки 1 процент от оклада. При этом размер штрафов не может снизить общую сумму выплат меньше минимального размера оплаты труда – 16 242 рубля. Сумма штрафов на следующий месяц не переносится.
+
+## Вход: 
+
+* табель учета рабочего времени одного конкретного сотрудника (пример табелей разных сотрудников есть в [Timesheets.xlsx](../data/Timesheets.xlsx)),
+* отчет по просроченным задачам (пример отчета можно найти [ReportOnOverdueTasks.xlsx](../data/ReportOnOverdueTasks.xlsx)),
+* оклад сотрудника (список сотрудников с окладами содержится в [EmployeeSalary.xlsx](../data/EmployeeSalary.xlsx)).
+
+## Выход:
+
+Cписок заработной платы по конкретному сотруднику (сумма выплат за месяц, общая выплата/премия/штрафы/выплаты по листу нетрудоспособности/отгулы).
+
+## Требования к именованиям и форматам
+  | C# | Java | Python
+-------|----|------|--------
+Библиотека классов | SalaryAccountingLib.dll | SalaryAccountingLib.jar | SalaryAccountingLib
+Название класса | Salary | Salary | Salary
+Название метода | CalculationSalary() | CalculationSalary() | CalculationSalary()
+Статичность метода | да | да | да
+Входящие обязательные параметры | `List<WorkingDay> workingDays`,<br/>`List<Task> tasks`,<br/>`double salary` | `List<WorkingDay> workingDays`,<br/>`List<Task> tasks`,<br/>`double salary` | `workingDays: List[WorkingDay]`,<br/>`tasks: List[task]`,<br/>`salary: float`<br/>
+Возвращаемые параметры | `double[]` | `doublel[]` | `List[float]`
+
+### Класс Models/Employee
+
+C#:
+
+```cs
+public class Employee
+{
+    [JsonPropertyName("Position")]
+    public string Position { get; set; }
+    [JsonPropertyName("Salary")]
+    public double Salary { get; set; }
+    [JsonPropertyName("Tasks")]
+    public List<TaskDTO> Tasks { get; set; }
+    [JsonPropertyName("WorkingDays")]
+    public List<WorkingDay> WorkingDays { get; set; }
+}
+```
+
+Java:
+
+```java
+public class Employee
+{
+    @JsonSetter("Position")
+    public String Position ;
+    @JsonSetter("Salary")
+    public double Salary ;
+    @JsonSetter("Tasks")
+    public List<TaskDTO> Tasks ;
+    @JsonSetter("WorkingDays")
+    public List<WorkingDay> WorkingDays ;
+}
+```
+
+Python:
+
+```py
+@dataclass
+class employee:
+    Position: str
+    Salary: int
+    WorkingDays: List[WorkingDay]
+    Tasks: List[TaskDTO]
+
+    @staticmethod
+    def from_dict(obj: Any) -> 'Employee':
+        _Position = str(obj.get("Position"))
+        _Salary = int(obj.get("Salary"))
+        _WorkingDays = [WorkingDay.from_dict(y) for y in obj.get("WorkingDays")]
+        _Tasks = [TaskDTO.from_dict(y) for y in obj.get("TasksDTO")]
+        return employee(_Position, _Salary, _WorkingDays, _Tasks)
+```
+
+### Перечисление Models/StatusDay
+
+C#:
+
+```cs
+public enum StatusDay
+{
+    Working,// Рабочий день
+    PreWorking,// Праздничный день
+    SickLeave,// Больничный
+    DisrespectfulSash,// Отсутвие по неуважительной причине
+    Holiday// Отпуск
+}
+```
+
+Java:
+
+```java
+@JsonFormat(shape = JsonFormat.Shape.NUMBER)
+public enum StatusDay{
+    Working,            // Рабочий день
+    PreWorking,         // Предпраздничный день
+    SickLeave,          // Больничный
+    DisrespectfulSash,  // Отсутвие по неуважительной причине
+    Holiday;           // Отпуск или выходной нерабочий день
+}
+```
+
+Python:
+
+```py
+class StatusDay(IntEnum):
+    Working = 0
+    PreWorking = 1
+    SickLeave = 2
+    DisrespectfulSash = 3
+    Holiday = 4
+```
+
+### Класс Models/TaskDTO:
+
+C#:
+
+```cs
+public class TaskDTO
+{
+    [JsonPropertyName("FullTitle")]
+    public string FullTitle { get; set; }
+    [JsonPropertyName("Deadline")]
+    public DateTime Deadline { get; set; }
+    [JsonPropertyName("FinishActualTime")]
+    public DateTime FinishActualTime { get; set; }
+}
+```
+
+Java:
+
+```java
+public class TaskDTO {
+    @JsonSetter("FullTitle")
+    public String FullTitle ;
+    @JsonSetter("Deadline")
+    public LocalDateTime Deadline ;
+    @JsonSetter("FinishActualTime")
+    public LocalDateTime  FinishActualTime ;
+}
+```
+
+Python:
+
+```py
+@dataclass
+class TaskDTO:
+    FullTitle: str
+    Deadline: str
+    СompletionDate: str
+
+    @staticmethod
+    def from_dict(obj: Any) -> 'TaskDTO':
+        _FullTitle = str(obj.get("FullTitle"))
+        _Deadline = str(obj.get("Deadline"))
+        _СompletionDate = str(obj.get("СompletionDate"))
+        return TaskDTO(_FullTitle, _Deadline, _СompletionDate)
+```
+
+### Класс Models/WorkingDay:
+
+C#:
+
+```cs
+public class WorkingDay
+{
+    [JsonPropertyName("Date")]
+    public DateOnly Date { get; set; }
+    private int hours;
+    [JsonPropertyName("Value")]
+    public string Hours
+    {
+        get =>  hours.ToString();
+        set => hours = (value!="б" )?Convert.ToInt32(value):-1;
+    }
+    [JsonPropertyName("Status")]
+    public StatusDay Status { get; set; }
+}
+```
+
+Java:
+
+```java
+public class WorkingDay {
+    @JsonSetter("Date")
+    public java.util.Date Date;
+    private int hours;
+    @JsonSetter("Value")
+    public String Hours;
+    @JsonSetter("Status")
+    public StatusDay Status;
+    public String getHours() {
+        if (Status == StatusDay.Working|| Status == StatusDay.PreWorking)
+        {
+            return ""+hours;
+        }
+        else {
+            return ""+0;
+        }
+    }
+    public void setHours(String value) {
+        if (Status == StatusDay.Working && value!="б" || Status == StatusDay.PreWorking && value!="б")
+        {
+            hours = Integer.parseInt(value);
+        }
+        else if (value=="б")
+        {
+            hours = -1;
+        }
+        else
+        {
+            hours = 0;
+        }
+    }
+}
+```
+
+Python:
+
+```py
+@dataclass
+class WorkingDay:
+    Date: str
+    Status: StatusDay
+    Value: str
+
+    @staticmethod
+    def from_dict(obj: Any) -> 'WorkingDay':
+        _Date = str(obj.get("Date"))
+        _Status = int(obj.get("Status"))
+        _Value = str(obj.get("Value"))
+        return WorkingDay(_Date, _Status, _Value)
+```
+
+
+### Пример:
+
+Если для некоторой должности `X`, месячная оплата труда которой составляет 100000 руб. за 160 рабочих часов и месячный табель рабочего времени соответствует табл. 1. и выполненные задачи в табл. 2.
+
+![](../img/test_003.png)
+
+ЗП по табелю = 625 руб * 184 = 115 000 руб, где 625 руб - стоимость 1 часа (100 000/160)
+
+Исполнитель | Задача | Дедлайн | Дата завершения задачи
+------------|--------|---------|-----------------------
+Инженер-программист | Ввод связанных документов Заявки, Приказы, Экзаменационные ведомости, Протоколы | 14.05.2023 0:00 | 31.05.2023 0:00
+
+При нарушении сроков выполнения хотя бы одной задачи сотрудник лишается премии, даже при выполнении других задач вовремя. 
+
+Так как задача не была выполнена в срок, то:
+
+```
+Штраф = (Дата завершения задачи - Дедлайн - Выходные/Праздничные дни) * (оклад * 1%) = (31 - 14 - 4) * (100 000 руб * 0,01) = 13 000 руб.
+
+ЗП с учетом доплат и взысканий  = ЗП по табелю + Премия - Штраф = 102 000 руб.
+```
+
+Метод должен вернуть массив следующих значений:
+
+```
+[ЗП с учетом доплат и взысканий, Премия, Штрафы, Выплаты по листу нетрудоспособности, Отгулы ] = [102000, 0, 13000, 0, 0]
+```
+
+## Разработка библиотеки
+
+Разработайте библиотеку для расчета заработной платы сотрудников с учетом выполненных задач в срок, больничных листов, окладов и прочих факторов. 
+Необходимо обязательно следовать правилам именования библиотек, классов и методов в них. В случае ошибок в рамках именования ваша работа не может быть проверена и ваш результат не будет зачтен. Классы и методы должны содержать модификатор `public` (если это реализуемо в рамках платформы), чтобы внешние приложения могли получить к ним доступ. 
+
+Описание входных/выходных параметров, методику и примеры расчета, а также тестовые данные для тестирования библиотеки можно найти в ресурсах к заданию.
+
+## Модульное тестирование 
+
+Реализуйте 5 unit-тестов для библиотеки по расчету заработной платы сотрудников, функционал которой описан выше. Важно, чтобы тестовые данные предусматривали различные ситуации: 
+
+1. наличие премии за выход на праздниках и выходные дни;
+1. наличие штрафа  за просроченные задачи;
+1. наличие больничного листа для сотрудника, отработавшего более 3-х месяцев;
+1. наличие больничного листа для нового сотрудника, отработавшего меньше месяца;
+1. превышение общей суммы штрафов суммы возможной выплаты.

BIN
data/EmployeeSalary.xlsx


BIN
data/ReportOnOverdueTasks.xlsx


BIN
data/Timesheets.xlsx


BIN
img/test_003.png


+ 11 - 10
readme.md

@@ -477,18 +477,19 @@ tablayout
 
 **Лабораторнo-практические работы**
 
-1. [Создание проекта по индивидуальному заданию. Разработка Unit-тестов для проекта](./articles/5_3_1_10_unit_test_lab.md)
+<!-- 1. [Создание проекта по индивидуальному заданию. Разработка Unit-тестов для проекта](./articles/5_3_1_10_unit_test_lab.md) -->
 1. [Реализация тестов для прошлых чемпионатов (WS22)](./articles/testing_lab.md)
+1. [Реализация тестов для прошлых чемпионатов (WS23)](./articles/testing_lab_ws23.md)
 1. [Реализация тестов для прошлых чемпионатов (DE21)](./articles/testing_lab_de21.md)
-2. [Лабораторная работа «Разработка тестовых пакетов»](./articles/rest_booking.md)
-3. Лабораторная работа «Использование инструментария анализа качества»
-4. Лабораторная работа «Анализ и обеспечение обработки исключительных ситуаций»
-5. Лабораторная работа «Функциональное тестирование»
-6. Лабораторная работа «Тестирование безопасности»
-7. Лабораторная работа «Нагрузочное тестирование, стрессовое тестирование»
-8. Лабораторная работа «Тестирование интеграции»
-9. Лабораторная работа «Конфигурационное тестирование»
-10. Лабораторная работа «Тестирование установки»
+1. [Лабораторная работа «Разработка тестовых пакетов»](./articles/rest_booking.md)
+<!-- 1. Лабораторная работа «Использование инструментария анализа качества»
+1. Лабораторная работа «Анализ и обеспечение обработки исключительных ситуаций»
+1. Лабораторная работа «Функциональное тестирование»
+1. Лабораторная работа «Тестирование безопасности»
+1. Лабораторная работа «Нагрузочное тестирование, стрессовое тестирование»
+1. Лабораторная работа «Тестирование интеграции»
+1. Лабораторная работа «Конфигурационное тестирование»
+1. Лабораторная работа «Тестирование установки» -->
 
 
 ## Практика №2, разработка web-приложений