nuzhno-sdelat-sayt-ya-buhgal/data.js

261 lines
7.1 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Хранилище данных (localStorage + экспорт/импорт)
const DB_VERSION = 1;
const defaultData = {
employees: [],
decrees: [],
payments: [],
currentPeriod: '2026-08',
operations: []
};
let db = loadData();
function loadData() {
try {
const saved = localStorage.getItem('executive_sheets_db');
if (saved) {
const parsed = JSON.parse(saved);
return { ...defaultData, ...parsed };
}
} catch (e) {
console.error('Ошибка загрузки данных:', e);
}
return { ...defaultData };
}
function saveData() {
try {
localStorage.setItem('executive_sheets_db', JSON.stringify(db));
} catch (e) {
console.error('Ошибка сохранения данных:', e);
showToast('Ошибка сохранения данных', 'error');
}
}
function addEmployee(emp) {
const existing = db.employees.find(e => e.tabNum === emp.tabNum);
if (existing) {
existing.name = emp.name;
existing.iin = emp.iin;
existing.salary = parseFloat(emp.salary) || 0;
existing.updatedAt = new Date().toISOString();
} else {
db.employees.push({
...emp,
id: Date.now(),
salary: parseFloat(emp.salary) || 0,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString()
});
}
saveData();
logOperation('employee', 'create', `Сотрудник ${emp.name} (таб. ${emp.tabNum})`);
}
function updateEmployee(id, updates) {
const emp = db.employees.find(e => e.id === id);
if (emp) {
Object.assign(emp, updates);
emp.updatedAt = new Date().toISOString();
saveData();
logOperation('employee', 'update', `Сотрудник ${emp.name}`);
}
}
function deleteEmployee(id) {
const idx = db.employees.findIndex(e => e.id === id);
if (idx !== -1) {
const name = db.employees[idx].name;
db.employees.splice(idx, 1);
saveData();
logOperation('employee', 'delete', `Сотрудник ${name}`);
}
}
function addDecree(decree) {
decree.id = Date.now();
decree.status = 'active';
decree.paidAmount = 0;
decree.createdAt = new Date().toISOString();
db.decrees.push(decree);
saveData();
logOperation('decree', 'create', `Постановление ${decree.number}`);
}
function updateDecree(id, updates) {
const d = db.decrees.find(d => d.id === id);
if (d) {
Object.assign(d, updates);
d.updatedAt = new Date().toISOString();
saveData();
logOperation('decree', 'update', `Постановление ${d.number}`);
}
}
function deleteDecree(id) {
const idx = db.decrees.findIndex(d => d.id === id);
if (idx !== -1) {
const num = db.decrees[idx].number;
db.decrees.splice(idx, 1);
saveData();
logOperation('decree', 'delete', `Постановление ${num}`);
}
}
function addPayment(payment) {
payment.id = Date.now();
payment.status = 'processed';
payment.createdAt = new Date().toISOString();
db.payments.push(payment);
const decree = db.decrees.find(d => d.id === payment.decreeId);
if (decree) {
decree.paidAmount = (decree.paidAmount || 0) + parseFloat(payment.amount);
if (decree.paidAmount >= decree.amount) {
decree.status = 'closed';
}
saveData();
}
logOperation('payment', 'create', `Выплата по ${payment.decreeNumber}`);
}
function getEmployees() {
return db.employees;
}
function getDecrees(filter = 'all') {
if (filter === 'all') return db.decrees;
if (filter === 'alimony') return db.decrees.filter(d => d.type === 'alimony');
if (filter === 'other') return db.decrees.filter(d => d.type === 'other');
if (filter === 'closed') return db.decrees.filter(d => d.status === 'closed');
return db.decrees;
}
function getDecreesForEmployee(empId) {
return db.decrees.filter(d => d.employeeId === empId && d.status === 'active');
}
function getPayments() {
return db.payments;
}
function getCurrentPeriod() {
return db.currentPeriod;
}
function setCurrentPeriod(period) {
db.currentPeriod = period;
saveData();
}
function logOperation(type, action, description) {
db.operations.unshift({
id: Date.now(),
type,
action,
description,
timestamp: new Date().toISOString()
});
if (db.operations.length > 100) {
db.operations = db.operations.slice(0, 100);
}
saveData();
}
function getRecentOperations(limit = 5) {
return db.operations.slice(0, limit);
}
function getStats() {
const activeDecrees = db.decrees.filter(d => d.status === 'active');
const totalDebt = activeDecrees.reduce((sum, d) => sum + (d.amount - (d.paidAmount || 0)), 0);
const currentPeriod = getCurrentPeriod();
const paidThisMonth = db.payments
.filter(p => p.period === currentPeriod)
.reduce((sum, p) => sum + parseFloat(p.amount), 0);
return {
employees: db.employees.length,
activeDecrees: activeDecrees.length,
totalDebt,
paidThisMonth,
closedDecrees: db.decrees.filter(d => d.status === 'closed').length
};
}
function calculateDeductionsForEmployee(employee) {
const decrees = getDecreesForEmployee(employee.id);
if (decrees.length === 0) return null;
const maxDeduction = employee.salary * 0.5;
const alimonyDecrees = decrees.filter(d => d.type === 'alimony');
const otherDecrees = decrees.filter(d => d.type === 'other');
let totalAllocated = 0;
const allocation = [];
alimonyDecrees.forEach(d => {
const remaining = d.amount - (d.paidAmount || 0);
allocation.push({
decree: d,
allocated: Math.min(remaining, maxDeduction * 0.5)
});
totalAllocated += allocation[allocation.length - 1].allocated;
});
const remainingForOther = maxDeduction - totalAllocated;
if (remainingForOther > 0 && otherDecrees.length > 0) {
const perOther = remainingForOther / otherDecrees.length;
otherDecrees.forEach(d => {
const remaining = d.amount - (d.paidAmount || 0);
allocation.push({
decree: d,
allocated: Math.min(remaining, perOther)
});
});
}
return {
employee,
maxDeduction,
allocation,
totalAllocated,
remaining: employee.salary - maxDeduction
};
}
function exportToCSV(data, filename) {
if (!data || data.length === 0) {
showToast('Нет данных для экспорта', 'error');
return;
}
const headers = Object.keys(data[0]);
const csv = [
headers.join(';'),
...data.map(row =>
headers.map(h => {
const val = row[h] !== null && row[h] !== undefined ? String(row[h]) : '';
return '"' + val.replace(/"/g, '""') + '"';
}).join(';')
)
].join('\n');
const blob = new Blob(['\uFEFF' + csv], { type: 'text/csv;charset=utf-8;' });
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = filename;
link.click();
showToast('Файл скачан: ' + filename, 'success');
}
function clearAllData() {
if (confirm('Вы уверены? Все данные будут удалены безвозвратно.')) {
localStorage.removeItem('executive_sheets_db');
db = { ...defaultData };
showToast('Все данные удалены', 'success');
location.reload();
}
}