Initial commit MKD fixes
This commit is contained in:
153
backend/paymentInvoiceWorkflow.js
Executable file
153
backend/paymentInvoiceWorkflow.js
Executable file
@@ -0,0 +1,153 @@
|
||||
/**
|
||||
* Модуль для управления workflow согласования счетов на оплату
|
||||
*/
|
||||
|
||||
const WORKFLOW_STAGES = {
|
||||
draft: {
|
||||
next: 'pending_manager_approval',
|
||||
role: null,
|
||||
description: 'Черновик'
|
||||
},
|
||||
pending_manager_approval: {
|
||||
next: 'pending_finance_manager_approval',
|
||||
role: 'manager',
|
||||
description: 'На согласовании у руководителя'
|
||||
},
|
||||
pending_finance_manager_approval: {
|
||||
next: 'approved',
|
||||
role: 'finance_manager',
|
||||
description: 'На согласовании у финансового руководителя'
|
||||
},
|
||||
approved: {
|
||||
next: 'scheduled',
|
||||
role: 'financier',
|
||||
description: 'Согласован, ожидает постановки в график'
|
||||
},
|
||||
scheduled: {
|
||||
next: 'paid',
|
||||
role: null,
|
||||
description: 'В графике платежей'
|
||||
},
|
||||
paid: {
|
||||
next: null,
|
||||
role: null,
|
||||
description: 'Оплачен'
|
||||
},
|
||||
postponed: {
|
||||
next: 'scheduled',
|
||||
role: null,
|
||||
description: 'Отложен'
|
||||
},
|
||||
cancelled: {
|
||||
next: null,
|
||||
role: null,
|
||||
description: 'Отменен'
|
||||
},
|
||||
rejected: {
|
||||
next: 'draft',
|
||||
role: null,
|
||||
description: 'Отклонен'
|
||||
},
|
||||
completed: {
|
||||
next: null,
|
||||
role: null,
|
||||
description: 'Выполнено'
|
||||
}
|
||||
};
|
||||
|
||||
// Роли высшего звена, которые пропускают этап manager
|
||||
const TOP_MANAGEMENT_ROLES = ['finance_director', 'director', 'top_management'];
|
||||
|
||||
/**
|
||||
* Определяет следующий статус для счета
|
||||
* @param {string} currentStatus - текущий статус
|
||||
* @param {string[]} userRoles - роли пользователя
|
||||
* @returns {string|null} следующий статус
|
||||
*/
|
||||
function getNextStatus(currentStatus, userRoles = []) {
|
||||
const stage = WORKFLOW_STAGES[currentStatus];
|
||||
if (!stage) return null;
|
||||
|
||||
// Если текущий статус pending_manager_approval и пользователь из высшего звена
|
||||
// пропускаем этап manager и идем сразу на finance_manager
|
||||
if (currentStatus === 'pending_manager_approval' &&
|
||||
userRoles.some(role => TOP_MANAGEMENT_ROLES.includes(role))) {
|
||||
return 'pending_finance_manager_approval';
|
||||
}
|
||||
|
||||
return stage.next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Определяет, может ли пользователь согласовать счет на текущем этапе
|
||||
* @param {string} currentStatus - текущий статус счета
|
||||
* @param {string[]} userRoles - роли пользователя
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function canApprove(currentStatus, userRoles = []) {
|
||||
const stage = WORKFLOW_STAGES[currentStatus];
|
||||
if (!stage || !stage.role) return false;
|
||||
|
||||
// Если требуется роль manager, но пользователь из высшего звена - может согласовать
|
||||
if (stage.role === 'manager' &&
|
||||
userRoles.some(role => TOP_MANAGEMENT_ROLES.includes(role))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return userRoles.includes(stage.role);
|
||||
}
|
||||
|
||||
/**
|
||||
* Определяет роль следующего согласующего
|
||||
* @param {string} currentStatus - текущий статус
|
||||
* @param {string[]} userRoles - роли пользователя (для определения пропуска этапа)
|
||||
* @returns {string|null}
|
||||
*/
|
||||
function getNextApproverRole(currentStatus, userRoles = []) {
|
||||
const nextStatus = getNextStatus(currentStatus, userRoles);
|
||||
if (!nextStatus) return null;
|
||||
|
||||
const nextStage = WORKFLOW_STAGES[nextStatus];
|
||||
return nextStage ? nextStage.role : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Создает запись в истории согласования
|
||||
* @param {string} userId - ID пользователя
|
||||
* @param {string} userRole - роль пользователя
|
||||
* @param {string} action - действие (approve, reject, etc.)
|
||||
* @param {string} comment - комментарий
|
||||
* @returns {object}
|
||||
*/
|
||||
function createApprovalHistoryEntry(userId, userRole, action, comment = '') {
|
||||
return {
|
||||
userId,
|
||||
userRole,
|
||||
action,
|
||||
comment,
|
||||
date: new Date().toISOString()
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Генерирует номер счета
|
||||
* @param {Date} date - дата создания
|
||||
* @returns {string}
|
||||
*/
|
||||
function generateInvoiceNumber(date = new Date()) {
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
const timestamp = Date.now().toString().slice(-6);
|
||||
return `INV-${year}${month}${day}-${timestamp}`;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
WORKFLOW_STAGES,
|
||||
TOP_MANAGEMENT_ROLES,
|
||||
getNextStatus,
|
||||
canApprove,
|
||||
getNextApproverRole,
|
||||
createApprovalHistoryEntry,
|
||||
generateInvoiceNumber
|
||||
};
|
||||
Reference in New Issue
Block a user