Добавление проектов
Добавили возможность создавания разных проектов.
This commit is contained in:
241
backend/app/class/enity/class_project.php
Normal file
241
backend/app/class/enity/class_project.php
Normal file
@@ -0,0 +1,241 @@
|
||||
<?php
|
||||
|
||||
class Project extends BaseEntity {
|
||||
|
||||
protected $db_name = 'project';
|
||||
|
||||
// Свойства проекта
|
||||
public $id;
|
||||
public $id_order;
|
||||
public $name;
|
||||
public $id_ready;
|
||||
|
||||
// Валидация данных
|
||||
protected function validate() {
|
||||
static::$error_message = [];
|
||||
|
||||
if (!$this->id) {
|
||||
$this->addError('id', 'ID проекта не указан');
|
||||
}
|
||||
if (!$this->name) {
|
||||
$this->addError('name', 'Название проекта не может быть пустым');
|
||||
}
|
||||
|
||||
return $this->getErrors();
|
||||
}
|
||||
|
||||
// Валидация данных (для create)
|
||||
protected function validateCreate() {
|
||||
static::$error_message = [];
|
||||
|
||||
if (!$this->name) {
|
||||
$this->addError('name', 'Название проекта не может быть пустым');
|
||||
}
|
||||
|
||||
return $this->getErrors();
|
||||
}
|
||||
|
||||
// Создание проекта
|
||||
public function create() {
|
||||
// Валидация
|
||||
if ($errors = $this->validateCreate()) {
|
||||
return $errors;
|
||||
}
|
||||
|
||||
// Получаем максимальный order
|
||||
$maxOrder = Database::max($this->db_name, 'id_order') ?? 0;
|
||||
|
||||
// Вставляем в базу
|
||||
Database::insert($this->db_name, [
|
||||
'name' => $this->name,
|
||||
'id_order' => $maxOrder + 1,
|
||||
'id_ready' => $this->id_ready
|
||||
]);
|
||||
|
||||
$this->id = Database::id();
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'id' => $this->id
|
||||
];
|
||||
}
|
||||
|
||||
// Обновление проекта
|
||||
public function update() {
|
||||
// Валидация
|
||||
if ($errors = $this->validate()) {
|
||||
return $errors;
|
||||
}
|
||||
|
||||
// Проверка что проект существует
|
||||
$project = Database::get($this->db_name, ['id'], ['id' => $this->id]);
|
||||
if (!$project) {
|
||||
$this->addError('project', 'Проект не найден');
|
||||
return $this->getErrors();
|
||||
}
|
||||
|
||||
// Формируем данные для обновления
|
||||
$update_data = [
|
||||
'name' => $this->name
|
||||
];
|
||||
|
||||
// id_ready обновляем только если передан
|
||||
if ($this->id_ready !== null) {
|
||||
$update_data['id_ready'] = $this->id_ready;
|
||||
}
|
||||
|
||||
// id_order обновляем только если передан
|
||||
if ($this->id_order !== null) {
|
||||
$update_data['id_order'] = $this->id_order;
|
||||
}
|
||||
|
||||
// Обновляем в БД
|
||||
Database::update($this->db_name, $update_data, [
|
||||
'id' => $this->id
|
||||
]);
|
||||
|
||||
return ['success' => true];
|
||||
}
|
||||
|
||||
// Удаление проекта
|
||||
public static function delete($id) {
|
||||
// Проверка что проект существует
|
||||
$project = self::checkProject($id);
|
||||
if (!$project) {
|
||||
return ['success' => false, 'errors' => ['project' => 'Проект не найден']];
|
||||
}
|
||||
|
||||
// Удаляем все связанные данные
|
||||
// Удаляем задачи проекта (и их файлы)
|
||||
$tasks = Database::select('cards_task', ['id'], ['id_project' => $id]);
|
||||
foreach ($tasks as $task) {
|
||||
Task::delete($task['id']);
|
||||
}
|
||||
|
||||
// Удаляем колонки проекта
|
||||
Database::delete('columns', ['id_project' => $id]);
|
||||
|
||||
// Удаляем отделы проекта
|
||||
Database::delete('departments', ['id_project' => $id]);
|
||||
|
||||
// Удаляем сам проект
|
||||
Database::delete('project', ['id' => $id]);
|
||||
|
||||
return ['success' => true];
|
||||
}
|
||||
|
||||
// Получение всех проектов
|
||||
public function getAll() {
|
||||
return Database::select($this->db_name, [
|
||||
'id',
|
||||
'id_order',
|
||||
'name',
|
||||
'id_ready'
|
||||
], [
|
||||
'ORDER' => ['id_order' => 'ASC']
|
||||
]);
|
||||
}
|
||||
|
||||
// Получение одного проекта
|
||||
public static function get($id) {
|
||||
return Database::get('project', [
|
||||
'id',
|
||||
'id_order',
|
||||
'name',
|
||||
'id_ready'
|
||||
], ['id' => $id]);
|
||||
}
|
||||
|
||||
// Получение id_ready (ID колонки "Готово") по ID проекта
|
||||
public static function getReadyColumnId($project_id) {
|
||||
$project = Database::get('project', ['id_ready'], ['id' => $project_id]);
|
||||
return $project ? (int)$project['id_ready'] : null;
|
||||
}
|
||||
|
||||
// Установка id_ready для проекта
|
||||
public static function setReadyColumn($project_id, $column_id) {
|
||||
// Проверка что проект существует
|
||||
$project = self::checkProject($project_id);
|
||||
if (!$project) {
|
||||
return ['success' => false, 'errors' => ['project' => 'Проект не найден']];
|
||||
}
|
||||
|
||||
// Проверка что колонка существует и принадлежит этому проекту
|
||||
$column = Database::get('columns', ['id', 'id_project'], ['id' => $column_id]);
|
||||
if (!$column || (int)$column['id_project'] !== (int)$project_id) {
|
||||
return ['success' => false, 'errors' => ['column' => 'Колонка не найдена или не принадлежит проекту']];
|
||||
}
|
||||
|
||||
// Обновляем id_ready
|
||||
Database::update('project', [
|
||||
'id_ready' => $column_id
|
||||
], [
|
||||
'id' => $project_id
|
||||
]);
|
||||
|
||||
return ['success' => true, 'id_ready' => $column_id];
|
||||
}
|
||||
|
||||
// Получение колонок проекта
|
||||
public static function getColumns($project_id) {
|
||||
return Database::select('columns', [
|
||||
'id',
|
||||
'name_columns',
|
||||
'color',
|
||||
'id_order'
|
||||
], [
|
||||
'id_project' => $project_id,
|
||||
'ORDER' => ['id_order' => 'ASC']
|
||||
]);
|
||||
}
|
||||
|
||||
// Получение отделов проекта
|
||||
public static function getDepartments($project_id) {
|
||||
return Database::select('departments', [
|
||||
'id',
|
||||
'name_departments',
|
||||
'color'
|
||||
], [
|
||||
'id_project' => $project_id
|
||||
]);
|
||||
}
|
||||
|
||||
// Получение всех данных проекта (проект + колонки + отделы + метки)
|
||||
public static function getProjectData($project_id) {
|
||||
$project = self::get($project_id);
|
||||
if (!$project) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Получаем метки (глобальные)
|
||||
$labels = Database::select('labels', [
|
||||
'id',
|
||||
'name_labels',
|
||||
'icon',
|
||||
'color'
|
||||
]);
|
||||
|
||||
return [
|
||||
'project' => $project,
|
||||
'columns' => self::getColumns($project_id),
|
||||
'departments' => self::getDepartments($project_id),
|
||||
'labels' => $labels
|
||||
];
|
||||
}
|
||||
|
||||
// Проверка и получение проекта
|
||||
public static function checkProject($project_id) {
|
||||
return Database::get('project', '*', ['id' => $project_id]);
|
||||
}
|
||||
|
||||
// Проверка проекта с ответом (при ошибке — сразу ответ и exit)
|
||||
public static function check($project_id) {
|
||||
$project = self::checkProject($project_id);
|
||||
if (!$project_id || !$project) {
|
||||
RestApi::response(['success' => false, 'errors' => ['project' => 'Проект не найден']], 400);
|
||||
}
|
||||
return $project;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -6,6 +6,7 @@ class Task extends BaseEntity {
|
||||
|
||||
// Свойства задачи
|
||||
public $id;
|
||||
public $id_project;
|
||||
public $id_department;
|
||||
public $id_label;
|
||||
public $order;
|
||||
@@ -45,6 +46,9 @@ class Task extends BaseEntity {
|
||||
if (!$this->id_department) {
|
||||
$this->addError('id_department', 'Департамент не указан');
|
||||
}
|
||||
if (!$this->id_project) {
|
||||
$this->addError('id_project', 'Проект не указан');
|
||||
}
|
||||
|
||||
return $this->getErrors();
|
||||
}
|
||||
@@ -58,6 +62,7 @@ class Task extends BaseEntity {
|
||||
|
||||
// Вставляем в базу
|
||||
Database::insert($this->db_name, [
|
||||
'id_project' => $this->id_project,
|
||||
'id_department' => $this->id_department,
|
||||
'id_label' => $this->id_label,
|
||||
'order' => $this->order ?? 0,
|
||||
@@ -101,7 +106,7 @@ class Task extends BaseEntity {
|
||||
}
|
||||
|
||||
// Проверка что задача существует и получаем текущие данные
|
||||
$task = Database::get($this->db_name, ['id', 'column_id', 'order'], ['id' => $this->id]);
|
||||
$task = Database::get($this->db_name, ['id', 'column_id', 'order', 'id_project'], ['id' => $this->id]);
|
||||
if (!$task) {
|
||||
$this->addError('task', 'Задача не найдена');
|
||||
return $this->getErrors();
|
||||
@@ -113,6 +118,9 @@ class Task extends BaseEntity {
|
||||
// Если column_id не передан — оставляем текущий
|
||||
$new_column_id = $this->column_id !== null ? (int)$this->column_id : $old_column_id;
|
||||
|
||||
// Получаем id_ready (колонка "Готово") из проекта
|
||||
$done_column_id = Project::getReadyColumnId($task['id_project']);
|
||||
|
||||
// Формируем данные для обновления
|
||||
$update_data = [
|
||||
'id_department' => $this->id_department,
|
||||
@@ -127,9 +135,9 @@ class Task extends BaseEntity {
|
||||
];
|
||||
|
||||
// Обновляем date_closed при смене колонки
|
||||
if ($new_column_id === COLUMN_DONE_ID && $old_column_id !== COLUMN_DONE_ID) {
|
||||
if ($done_column_id && $new_column_id === $done_column_id && $old_column_id !== $done_column_id) {
|
||||
$update_data['date_closed'] = date('Y-m-d H:i:s');
|
||||
} elseif ($old_column_id === COLUMN_DONE_ID && $new_column_id !== COLUMN_DONE_ID) {
|
||||
} elseif ($done_column_id && $old_column_id === $done_column_id && $new_column_id !== $done_column_id) {
|
||||
$update_data['date_closed'] = null;
|
||||
}
|
||||
|
||||
@@ -173,6 +181,9 @@ class Task extends BaseEntity {
|
||||
$new_column_id = (int)$column_id;
|
||||
$archive = (int)$task['archive'];
|
||||
|
||||
// Получаем id_ready (колонка "Готово") из проекта
|
||||
$done_column_id = Project::getReadyColumnId($task['id_project']);
|
||||
|
||||
// Получаем все карточки целевой колонки с тем же статусом архивации (кроме перемещаемой)
|
||||
$cards = Database::select('cards_task', ['id', 'order'], [
|
||||
'column_id' => $column_id,
|
||||
@@ -192,13 +203,13 @@ class Task extends BaseEntity {
|
||||
];
|
||||
|
||||
// Только для перемещаемой карточки обновляем date_closed
|
||||
if ($card['id'] == $id) {
|
||||
if ($card['id'] == $id && $done_column_id) {
|
||||
// Перемещаем В колонку "Готово" — устанавливаем дату закрытия
|
||||
if ($new_column_id === COLUMN_DONE_ID && $old_column_id !== COLUMN_DONE_ID) {
|
||||
if ($new_column_id === $done_column_id && $old_column_id !== $done_column_id) {
|
||||
$update_data['date_closed'] = date('Y-m-d H:i:s');
|
||||
}
|
||||
// Перемещаем ИЗ колонки "Готово" — обнуляем дату
|
||||
elseif ($old_column_id === COLUMN_DONE_ID && $new_column_id !== COLUMN_DONE_ID) {
|
||||
elseif ($old_column_id === $done_column_id && $new_column_id !== $done_column_id) {
|
||||
$update_data['date_closed'] = null;
|
||||
}
|
||||
}
|
||||
@@ -211,16 +222,20 @@ class Task extends BaseEntity {
|
||||
return ['success' => true];
|
||||
}
|
||||
|
||||
// Получение всех задач
|
||||
// Получение всех задач проекта
|
||||
// $id_project: ID проекта (обязательный)
|
||||
// $archive: 0 = неархивные, 1 = архивные, null = все
|
||||
public function getAll($archive = 0) {
|
||||
$where = [];
|
||||
public function getAll($id_project, $archive = 0) {
|
||||
$where = [
|
||||
'id_project' => $id_project
|
||||
];
|
||||
if ($archive !== null) {
|
||||
$where['archive'] = $archive ? 1 : 0;
|
||||
}
|
||||
|
||||
$tasks = Database::select($this->db_name, [
|
||||
'id',
|
||||
'id_project',
|
||||
'id_department',
|
||||
'id_label',
|
||||
'id_account',
|
||||
@@ -238,7 +253,7 @@ class Task extends BaseEntity {
|
||||
|
||||
// Декодируем JSON и получаем avatar_url из accounts
|
||||
return array_map(function($task) {
|
||||
$task['file_img'] = json_decode($task['file_img'], true) ?? [];
|
||||
$task['file_img'] = $task['file_img'] ? json_decode($task['file_img'], true) : [];
|
||||
|
||||
// Получаем avatar_url из accounts по id_account
|
||||
if ($task['id_account']) {
|
||||
@@ -252,21 +267,27 @@ class Task extends BaseEntity {
|
||||
}, $tasks);
|
||||
}
|
||||
|
||||
// Получение всех колонок
|
||||
public function getColumns() {
|
||||
// Получение колонок проекта
|
||||
public function getColumns($id_project) {
|
||||
return Database::select('columns', [
|
||||
'id',
|
||||
'name_columns',
|
||||
'color'
|
||||
'color',
|
||||
'id_order'
|
||||
], [
|
||||
'id_project' => $id_project,
|
||||
'ORDER' => ['id_order' => 'ASC']
|
||||
]);
|
||||
}
|
||||
|
||||
// Получение всех департаментов
|
||||
public function getDepartments() {
|
||||
// Получение отделов проекта
|
||||
public function getDepartments($id_project) {
|
||||
return Database::select('departments', [
|
||||
'id',
|
||||
'name_departments',
|
||||
'color'
|
||||
], [
|
||||
'id_project' => $id_project
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -294,8 +315,11 @@ class Task extends BaseEntity {
|
||||
// Проверка что задача существует
|
||||
$task = self::check_task($id);
|
||||
|
||||
// Получаем id_ready (колонка "Готово") из проекта
|
||||
$done_column_id = Project::getReadyColumnId($task['id_project']);
|
||||
|
||||
// Архивировать можно только задачи в колонке "Готово"
|
||||
if ($archive && (int)$task['column_id'] !== COLUMN_DONE_ID) {
|
||||
if ($archive && $done_column_id && (int)$task['column_id'] !== $done_column_id) {
|
||||
RestApi::response([
|
||||
'success' => false,
|
||||
'errors' => ['column' => 'Архивировать можно только задачи из колонки "Готово"']
|
||||
@@ -308,8 +332,8 @@ class Task extends BaseEntity {
|
||||
];
|
||||
|
||||
// При разархивировании — возвращаем в колонку "Готово"
|
||||
if (!$archive) {
|
||||
$update_data['column_id'] = COLUMN_DONE_ID;
|
||||
if (!$archive && $done_column_id) {
|
||||
$update_data['column_id'] = $done_column_id;
|
||||
}
|
||||
|
||||
// Обновляем в БД
|
||||
|
||||
@@ -81,7 +81,7 @@ class TaskImage {
|
||||
$file_size = strlen($file_data);
|
||||
|
||||
// Обновляем file_img в базе
|
||||
$current_files = json_decode($task['file_img'], true) ?? [];
|
||||
$current_files = $task['file_img'] ? json_decode($task['file_img'], true) : [];
|
||||
$current_files[] = [
|
||||
'url' => $file_url,
|
||||
'name' => $final_name,
|
||||
@@ -115,7 +115,7 @@ class TaskImage {
|
||||
}
|
||||
|
||||
// Получаем текущие файлы
|
||||
$current_files = json_decode($task['file_img'], true) ?? [];
|
||||
$current_files = $task['file_img'] ? json_decode($task['file_img'], true) : [];
|
||||
$upload_dir = __DIR__ . '/../../../public/task/' . $task_id;
|
||||
$deleted = [];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user