Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -180,9 +180,9 @@ def load_data():
|
|
| 180 |
|
| 181 |
for emp in data['employees']:
|
| 182 |
if 'pin' not in emp: emp['pin'] = '0000'
|
| 183 |
-
if 'daily_rate' not in emp: emp['daily_rate'] =
|
| 184 |
-
if 'target_amount' not in emp: emp['target_amount'] =
|
| 185 |
-
if 'bonus_percentage' not in emp: emp['bonus_percentage'] =
|
| 186 |
|
| 187 |
if not os.path.exists(DATA_FILE):
|
| 188 |
try:
|
|
@@ -1196,7 +1196,7 @@ SALARY_TEMPLATE = '''
|
|
| 1196 |
label { display: block; margin-bottom: 5px; color: var(--text-muted); font-size: 0.85rem; font-weight: 600; }
|
| 1197 |
|
| 1198 |
.rep-table { width: 100%; border-collapse: collapse; font-size: 0.9rem; }
|
| 1199 |
-
.rep-table th, .rep-table td { padding: 8px 5px; border-bottom: 1px solid var(--border); text-align: left; }
|
| 1200 |
.rep-table th { color: var(--text-muted); font-weight: normal; }
|
| 1201 |
|
| 1202 |
@media (max-width: 600px) {
|
|
@@ -1211,50 +1211,36 @@ SALARY_TEMPLATE = '''
|
|
| 1211 |
<h1><i class="fas fa-money-bill-wave"></i> Отчет по ЗП</h1>
|
| 1212 |
<a href="/admin" class="btn btn-dark"><i class="fas fa-arrow-left"></i> Назад в админку</a>
|
| 1213 |
</div>
|
| 1214 |
-
|
| 1215 |
<div class="report-section">
|
| 1216 |
-
<h3 style="color:var(--primary); margin-top:0;">
|
| 1217 |
-
<form method="POST" style="display:flex; gap:10px; flex-wrap:wrap;
|
| 1218 |
<input type="hidden" name="action" value="add_fine">
|
| 1219 |
-
<
|
| 1220 |
-
<
|
| 1221 |
-
|
| 1222 |
-
|
| 1223 |
-
|
| 1224 |
-
|
| 1225 |
-
|
| 1226 |
-
<
|
| 1227 |
-
<
|
| 1228 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1229 |
</form>
|
| 1230 |
-
<div style="overflow-x:auto;">
|
| 1231 |
-
<table class="rep-table">
|
| 1232 |
-
<tr><th>Дата</th><th>Сотрудник</th><th>Причина</th><th>Сумма</th><th>Действие</th></tr>
|
| 1233 |
-
{% for fine in fines|sort(attribute='date', reverse=True) %}
|
| 1234 |
-
<tr>
|
| 1235 |
-
<td>{{ fine.date }}</td>
|
| 1236 |
-
<td>
|
| 1237 |
-
{% for emp in employees %}
|
| 1238 |
-
{% if emp.id == fine.employee_id %}{{ emp.name }}{% endif %}
|
| 1239 |
-
{% endfor %}
|
| 1240 |
-
</td>
|
| 1241 |
-
<td>{{ fine.reason }}</td>
|
| 1242 |
-
<td>{{ fine.amount }} {{ currency_code }}</td>
|
| 1243 |
-
<td>
|
| 1244 |
-
<form method="POST" onsubmit="return confirm('Удалить штраф?');" style="margin:0;">
|
| 1245 |
-
<input type="hidden" name="action" value="delete_fine">
|
| 1246 |
-
<input type="hidden" name="fine_id" value="{{ fine.id }}">
|
| 1247 |
-
<button type="submit" class="btn btn-dark" style="padding:5px 10px; font-size:0.8rem;"><i class="fas fa-trash" style="color:var(--danger);"></i></button>
|
| 1248 |
-
</form>
|
| 1249 |
-
</td>
|
| 1250 |
-
</tr>
|
| 1251 |
-
{% endfor %}
|
| 1252 |
-
</table>
|
| 1253 |
-
</div>
|
| 1254 |
</div>
|
| 1255 |
-
|
| 1256 |
<div class="report-section">
|
| 1257 |
-
<h3 style="color:var(--primary); margin-top:0;">Расчет зарплаты</h3>
|
| 1258 |
<div class="form-row" style="margin-bottom: 20px; align-items: flex-end;">
|
| 1259 |
<div>
|
| 1260 |
<label>Дата начала</label>
|
|
@@ -1270,13 +1256,19 @@ SALARY_TEMPLATE = '''
|
|
| 1270 |
<table class="rep-table" id="tableSalary"></table>
|
| 1271 |
</div>
|
| 1272 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1273 |
</div>
|
| 1274 |
|
| 1275 |
<script>
|
| 1276 |
const allOrders = {{ orders_json|safe }};
|
| 1277 |
-
const workdays = {{ workdays_json|safe }};
|
| 1278 |
const employees = {{ employees_json|safe }};
|
| 1279 |
-
const
|
| 1280 |
const currencyCode = '{{ currency_code }}';
|
| 1281 |
|
| 1282 |
function getLocalDateStr(d) {
|
|
@@ -1289,7 +1281,6 @@ SALARY_TEMPLATE = '''
|
|
| 1289 |
const firstDay = new Date(today.getFullYear(), today.getMonth(), 1);
|
| 1290 |
document.getElementById('salStart').value = getLocalDateStr(firstDay);
|
| 1291 |
document.getElementById('salEnd').value = todayStr;
|
| 1292 |
-
document.getElementById('fineDate').value = todayStr;
|
| 1293 |
generateSalaryReport();
|
| 1294 |
}
|
| 1295 |
|
|
@@ -1309,12 +1300,45 @@ SALARY_TEMPLATE = '''
|
|
| 1309 |
empSales[o.employee_id][oDate] += o.total_price;
|
| 1310 |
}
|
| 1311 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1312 |
|
| 1313 |
employees.forEach(emp => {
|
| 1314 |
let daysWorked = 0;
|
| 1315 |
let fixedSal = 0;
|
| 1316 |
let bonusSal = 0;
|
| 1317 |
-
let employeeFines = 0;
|
| 1318 |
|
| 1319 |
let currDate = new Date(start);
|
| 1320 |
const endDate = new Date(end);
|
|
@@ -1325,16 +1349,10 @@ SALARY_TEMPLATE = '''
|
|
| 1325 |
|
| 1326 |
if (dailySales > 0) {
|
| 1327 |
daysWorked++;
|
|
|
|
| 1328 |
|
| 1329 |
-
|
| 1330 |
-
|
| 1331 |
-
fixedSal += rate;
|
| 1332 |
-
|
| 1333 |
-
let target = parseFloat(emp.target_amount);
|
| 1334 |
-
if (isNaN(target) || target === 0) target = 1500000;
|
| 1335 |
-
|
| 1336 |
-
let pct = parseFloat(emp.bonus_percentage);
|
| 1337 |
-
if (isNaN(pct) || pct === 0) pct = 10;
|
| 1338 |
|
| 1339 |
if (pct > 0 && dailySales > target) {
|
| 1340 |
bonusSal += (dailySales - target) * (pct / 100);
|
|
@@ -1342,22 +1360,18 @@ SALARY_TEMPLATE = '''
|
|
| 1342 |
}
|
| 1343 |
currDate.setDate(currDate.getDate() + 1);
|
| 1344 |
}
|
| 1345 |
-
|
| 1346 |
-
fines.forEach(f => {
|
| 1347 |
-
if (f.employee_id === emp.id && f.date >= start && f.date <= end) {
|
| 1348 |
-
employeeFines += parseFloat(f.amount);
|
| 1349 |
-
}
|
| 1350 |
-
});
|
| 1351 |
|
| 1352 |
-
const
|
| 1353 |
-
|
|
|
|
|
|
|
| 1354 |
html += `<tr>
|
| 1355 |
<td>${emp.name}</td>
|
| 1356 |
<td>${daysWorked}</td>
|
| 1357 |
<td>${fixedSal.toFixed(2)} ${currencyCode}</td>
|
| 1358 |
<td>${bonusSal.toFixed(2)} ${currencyCode}</td>
|
| 1359 |
-
<td style="color:var(--danger);">${
|
| 1360 |
-
<td style="font-weight:bold; color:var(--success);">${total.toFixed(2)} ${currencyCode}</td>
|
| 1361 |
</tr>`;
|
| 1362 |
}
|
| 1363 |
});
|
|
@@ -1516,9 +1530,9 @@ ADMIN_TEMPLATE = '''
|
|
| 1516 |
<input type="hidden" name="action" value="add_employee">
|
| 1517 |
<div style="flex:1; min-width:150px;"><label>Имя</label><input type="text" name="employee_name" required autocomplete="off"></div>
|
| 1518 |
<div style="flex:1; min-width:100px;"><label>PIN (4 цифры)</label><input type="text" name="pin" pattern="\\d{4}" required autocomplete="off"></div>
|
| 1519 |
-
<div style="flex:1; min-width:100px;"><label>Ставка за день</label><input type="number" name="daily_rate" value="
|
| 1520 |
-
<div style="flex:1; min-width:100px;"><label>Цель (n сумма)</label><input type="number" name="target_amount" value="
|
| 1521 |
-
<div style="flex:1; min-width:100px;"><label>Бонус (%)</label><input type="number" name="bonus_percentage" value="
|
| 1522 |
<button type="submit" class="btn btn-dark" style="width:100%; margin-top:10px;"><i class="fas fa-plus"></i> Добавить</button>
|
| 1523 |
</form>
|
| 1524 |
</div>
|
|
@@ -1958,14 +1972,18 @@ def admin_salary():
|
|
| 1958 |
if request.method == 'POST':
|
| 1959 |
action = request.form.get('action')
|
| 1960 |
if action == 'add_fine':
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1961 |
if 'fines' not in data:
|
| 1962 |
data['fines'] = []
|
| 1963 |
data['fines'].append({
|
| 1964 |
'id': uuid4().hex,
|
| 1965 |
-
'employee_id':
|
| 1966 |
-
'
|
| 1967 |
-
'
|
| 1968 |
-
'reason':
|
| 1969 |
})
|
| 1970 |
save_data(data)
|
| 1971 |
elif action == 'delete_fine':
|
|
@@ -1977,17 +1995,15 @@ def admin_salary():
|
|
| 1977 |
|
| 1978 |
orders = data.get('orders', {})
|
| 1979 |
employees = data.get('employees', [])
|
| 1980 |
-
workdays = data.get('workdays', {})
|
| 1981 |
fines = data.get('fines', [])
|
| 1982 |
|
| 1983 |
return render_template_string(
|
| 1984 |
SALARY_TEMPLATE,
|
| 1985 |
orders_json=json.dumps(list(orders.values())),
|
| 1986 |
employees_json=json.dumps(employees),
|
| 1987 |
-
workdays_json=json.dumps(workdays),
|
| 1988 |
fines_json=json.dumps(fines),
|
| 1989 |
employees=employees,
|
| 1990 |
-
|
| 1991 |
currency_code=CURRENCY_CODE
|
| 1992 |
)
|
| 1993 |
|
|
@@ -2016,12 +2032,12 @@ def admin():
|
|
| 2016 |
elif action == 'add_employee':
|
| 2017 |
emp_name = request.form.get('employee_name', '').strip()
|
| 2018 |
pin = request.form.get('pin', '0000').strip()
|
| 2019 |
-
try: daily_rate = float(request.form.get('daily_rate',
|
| 2020 |
-
except: daily_rate =
|
| 2021 |
-
try: target_amount = float(request.form.get('target_amount',
|
| 2022 |
-
except: target_amount =
|
| 2023 |
-
try: bonus_percentage = float(request.form.get('bonus_percentage',
|
| 2024 |
-
except: bonus_percentage =
|
| 2025 |
|
| 2026 |
if emp_name:
|
| 2027 |
employees.append({
|
|
@@ -2041,12 +2057,12 @@ def admin():
|
|
| 2041 |
if e.get('id') == emp_id:
|
| 2042 |
e['name'] = request.form.get('name', '').strip()
|
| 2043 |
e['pin'] = request.form.get('pin', '0000').strip()
|
| 2044 |
-
try: e['daily_rate'] = float(request.form.get('daily_rate',
|
| 2045 |
-
except: e['daily_rate'] =
|
| 2046 |
-
try: e['target_amount'] = float(request.form.get('target_amount',
|
| 2047 |
-
except: e['target_amount'] =
|
| 2048 |
-
try: e['bonus_percentage'] = float(request.form.get('bonus_percentage',
|
| 2049 |
-
except: e['bonus_percentage'] =
|
| 2050 |
break
|
| 2051 |
data['employees'] = employees
|
| 2052 |
save_data(data)
|
|
|
|
| 180 |
|
| 181 |
for emp in data['employees']:
|
| 182 |
if 'pin' not in emp: emp['pin'] = '0000'
|
| 183 |
+
if 'daily_rate' not in emp: emp['daily_rate'] = 0
|
| 184 |
+
if 'target_amount' not in emp: emp['target_amount'] = 0
|
| 185 |
+
if 'bonus_percentage' not in emp: emp['bonus_percentage'] = 0
|
| 186 |
|
| 187 |
if not os.path.exists(DATA_FILE):
|
| 188 |
try:
|
|
|
|
| 1196 |
label { display: block; margin-bottom: 5px; color: var(--text-muted); font-size: 0.85rem; font-weight: 600; }
|
| 1197 |
|
| 1198 |
.rep-table { width: 100%; border-collapse: collapse; font-size: 0.9rem; }
|
| 1199 |
+
.rep-table th, .rep-table td { padding: 8px 5px; border-bottom: 1px solid var(--border); text-align: left; vertical-align: middle; }
|
| 1200 |
.rep-table th { color: var(--text-muted); font-weight: normal; }
|
| 1201 |
|
| 1202 |
@media (max-width: 600px) {
|
|
|
|
| 1211 |
<h1><i class="fas fa-money-bill-wave"></i> Отчет по ЗП</h1>
|
| 1212 |
<a href="/admin" class="btn btn-dark"><i class="fas fa-arrow-left"></i> Назад в админку</a>
|
| 1213 |
</div>
|
| 1214 |
+
|
| 1215 |
<div class="report-section">
|
| 1216 |
+
<h3 style="color:var(--primary); margin-top:0;">Добавить штраф</h3>
|
| 1217 |
+
<form method="POST" style="display:flex; gap:10px; flex-wrap:wrap; align-items:flex-end;">
|
| 1218 |
<input type="hidden" name="action" value="add_fine">
|
| 1219 |
+
<div style="flex:1; min-width:150px;">
|
| 1220 |
+
<label>Сотрудник</label>
|
| 1221 |
+
<select name="employee_id" required>
|
| 1222 |
+
{% for emp in employees %}
|
| 1223 |
+
<option value="{{ emp.id }}">{{ emp.name }}</option>
|
| 1224 |
+
{% endfor %}
|
| 1225 |
+
</select>
|
| 1226 |
+
</div>
|
| 1227 |
+
<div style="flex:1; min-width:100px;">
|
| 1228 |
+
<label>Сумма</label>
|
| 1229 |
+
<input type="number" name="amount" required min="0" step="0.01">
|
| 1230 |
+
</div>
|
| 1231 |
+
<div style="flex:1; min-width:150px;">
|
| 1232 |
+
<label>Дата</label>
|
| 1233 |
+
<input type="date" name="date" required value="{{ current_date }}">
|
| 1234 |
+
</div>
|
| 1235 |
+
<div style="flex:2; min-width:200px;">
|
| 1236 |
+
<label>Причина</label>
|
| 1237 |
+
<input type="text" name="reason">
|
| 1238 |
+
</div>
|
| 1239 |
+
<button type="submit" class="btn btn-danger" style="height:44px;"><i class="fas fa-minus-circle"></i> Штраф</button>
|
| 1240 |
</form>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1241 |
</div>
|
| 1242 |
+
|
| 1243 |
<div class="report-section">
|
|
|
|
| 1244 |
<div class="form-row" style="margin-bottom: 20px; align-items: flex-end;">
|
| 1245 |
<div>
|
| 1246 |
<label>Дата начала</label>
|
|
|
|
| 1256 |
<table class="rep-table" id="tableSalary"></table>
|
| 1257 |
</div>
|
| 1258 |
</div>
|
| 1259 |
+
|
| 1260 |
+
<div class="report-section" style="margin-top: 20px;">
|
| 1261 |
+
<h3 style="color:var(--danger); margin-top:0;">История штрафов за период</h3>
|
| 1262 |
+
<div style="overflow-x:auto;">
|
| 1263 |
+
<table class="rep-table" id="tableFines"></table>
|
| 1264 |
+
</div>
|
| 1265 |
+
</div>
|
| 1266 |
</div>
|
| 1267 |
|
| 1268 |
<script>
|
| 1269 |
const allOrders = {{ orders_json|safe }};
|
|
|
|
| 1270 |
const employees = {{ employees_json|safe }};
|
| 1271 |
+
const allFines = {{ fines_json|safe }};
|
| 1272 |
const currencyCode = '{{ currency_code }}';
|
| 1273 |
|
| 1274 |
function getLocalDateStr(d) {
|
|
|
|
| 1281 |
const firstDay = new Date(today.getFullYear(), today.getMonth(), 1);
|
| 1282 |
document.getElementById('salStart').value = getLocalDateStr(firstDay);
|
| 1283 |
document.getElementById('salEnd').value = todayStr;
|
|
|
|
| 1284 |
generateSalaryReport();
|
| 1285 |
}
|
| 1286 |
|
|
|
|
| 1300 |
empSales[o.employee_id][oDate] += o.total_price;
|
| 1301 |
}
|
| 1302 |
});
|
| 1303 |
+
|
| 1304 |
+
let empFines = {};
|
| 1305 |
+
let finesHtml = '<tr><th>Дата</th><th>Сотрудник</th><th>Сумма</th><th>Причина</th><th>Действие</th></tr>';
|
| 1306 |
+
let hasFines = false;
|
| 1307 |
+
|
| 1308 |
+
allFines.forEach(f => {
|
| 1309 |
+
if (f.date >= start && f.date <= end) {
|
| 1310 |
+
hasFines = true;
|
| 1311 |
+
if (!empFines[f.employee_id]) empFines[f.employee_id] = 0;
|
| 1312 |
+
empFines[f.employee_id] += parseFloat(f.amount);
|
| 1313 |
+
|
| 1314 |
+
const emp = employees.find(e => e.id === f.employee_id);
|
| 1315 |
+
const empName = emp ? emp.name : 'Удален';
|
| 1316 |
+
|
| 1317 |
+
finesHtml += `<tr>
|
| 1318 |
+
<td>${f.date}</td>
|
| 1319 |
+
<td>${empName}</td>
|
| 1320 |
+
<td style="color:var(--danger);">${parseFloat(f.amount).toFixed(2)} ${currencyCode}</td>
|
| 1321 |
+
<td>${f.reason}</td>
|
| 1322 |
+
<td>
|
| 1323 |
+
<form method="POST" style="margin:0;" onsubmit="return confirm('Удалить штраф?');">
|
| 1324 |
+
<input type="hidden" name="action" value="delete_fine">
|
| 1325 |
+
<input type="hidden" name="fine_id" value="${f.id}">
|
| 1326 |
+
<button type="submit" class="btn btn-danger" style="padding:4px 8px; font-size:0.8rem; border-radius:6px;"><i class="fas fa-trash"></i></button>
|
| 1327 |
+
</form>
|
| 1328 |
+
</td>
|
| 1329 |
+
</tr>`;
|
| 1330 |
+
}
|
| 1331 |
+
});
|
| 1332 |
+
|
| 1333 |
+
if (!hasFines) {
|
| 1334 |
+
finesHtml += '<tr><td colspan="5">Нет штрафов за выбранный период</td></tr>';
|
| 1335 |
+
}
|
| 1336 |
+
document.getElementById('tableFines').innerHTML = finesHtml;
|
| 1337 |
|
| 1338 |
employees.forEach(emp => {
|
| 1339 |
let daysWorked = 0;
|
| 1340 |
let fixedSal = 0;
|
| 1341 |
let bonusSal = 0;
|
|
|
|
| 1342 |
|
| 1343 |
let currDate = new Date(start);
|
| 1344 |
const endDate = new Date(end);
|
|
|
|
| 1349 |
|
| 1350 |
if (dailySales > 0) {
|
| 1351 |
daysWorked++;
|
| 1352 |
+
fixedSal += parseFloat(emp.daily_rate || 0);
|
| 1353 |
|
| 1354 |
+
const target = parseFloat(emp.target_amount || 0);
|
| 1355 |
+
const pct = parseFloat(emp.bonus_percentage || 0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1356 |
|
| 1357 |
if (pct > 0 && dailySales > target) {
|
| 1358 |
bonusSal += (dailySales - target) * (pct / 100);
|
|
|
|
| 1360 |
}
|
| 1361 |
currDate.setDate(currDate.getDate() + 1);
|
| 1362 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1363 |
|
| 1364 |
+
const totalFines = empFines[emp.id] || 0;
|
| 1365 |
+
const total = fixedSal + bonusSal - totalFines;
|
| 1366 |
+
|
| 1367 |
+
if (daysWorked > 0 || total !== 0 || totalFines > 0) {
|
| 1368 |
html += `<tr>
|
| 1369 |
<td>${emp.name}</td>
|
| 1370 |
<td>${daysWorked}</td>
|
| 1371 |
<td>${fixedSal.toFixed(2)} ${currencyCode}</td>
|
| 1372 |
<td>${bonusSal.toFixed(2)} ${currencyCode}</td>
|
| 1373 |
+
<td style="color:var(--danger);">${totalFines > 0 ? '-' + totalFines.toFixed(2) : '0.00'} ${currencyCode}</td>
|
| 1374 |
+
<td style="font-weight:bold; color:${total >= 0 ? 'var(--success)' : 'var(--danger)'};">${total.toFixed(2)} ${currencyCode}</td>
|
| 1375 |
</tr>`;
|
| 1376 |
}
|
| 1377 |
});
|
|
|
|
| 1530 |
<input type="hidden" name="action" value="add_employee">
|
| 1531 |
<div style="flex:1; min-width:150px;"><label>Имя</label><input type="text" name="employee_name" required autocomplete="off"></div>
|
| 1532 |
<div style="flex:1; min-width:100px;"><label>PIN (4 цифры)</label><input type="text" name="pin" pattern="\\d{4}" required autocomplete="off"></div>
|
| 1533 |
+
<div style="flex:1; min-width:100px;"><label>Ставка за день</label><input type="number" name="daily_rate" value="0" required></div>
|
| 1534 |
+
<div style="flex:1; min-width:100px;"><label>Цель (n сумма)</label><input type="number" name="target_amount" value="0" required></div>
|
| 1535 |
+
<div style="flex:1; min-width:100px;"><label>Бонус (%)</label><input type="number" name="bonus_percentage" value="0" step="0.1" required></div>
|
| 1536 |
<button type="submit" class="btn btn-dark" style="width:100%; margin-top:10px;"><i class="fas fa-plus"></i> Добавить</button>
|
| 1537 |
</form>
|
| 1538 |
</div>
|
|
|
|
| 1972 |
if request.method == 'POST':
|
| 1973 |
action = request.form.get('action')
|
| 1974 |
if action == 'add_fine':
|
| 1975 |
+
emp_id = request.form.get('employee_id')
|
| 1976 |
+
amount = float(request.form.get('amount', 0))
|
| 1977 |
+
date = request.form.get('date', get_current_date())
|
| 1978 |
+
reason = request.form.get('reason', '')
|
| 1979 |
if 'fines' not in data:
|
| 1980 |
data['fines'] = []
|
| 1981 |
data['fines'].append({
|
| 1982 |
'id': uuid4().hex,
|
| 1983 |
+
'employee_id': emp_id,
|
| 1984 |
+
'amount': amount,
|
| 1985 |
+
'date': date,
|
| 1986 |
+
'reason': reason
|
| 1987 |
})
|
| 1988 |
save_data(data)
|
| 1989 |
elif action == 'delete_fine':
|
|
|
|
| 1995 |
|
| 1996 |
orders = data.get('orders', {})
|
| 1997 |
employees = data.get('employees', [])
|
|
|
|
| 1998 |
fines = data.get('fines', [])
|
| 1999 |
|
| 2000 |
return render_template_string(
|
| 2001 |
SALARY_TEMPLATE,
|
| 2002 |
orders_json=json.dumps(list(orders.values())),
|
| 2003 |
employees_json=json.dumps(employees),
|
|
|
|
| 2004 |
fines_json=json.dumps(fines),
|
| 2005 |
employees=employees,
|
| 2006 |
+
current_date=get_current_date(),
|
| 2007 |
currency_code=CURRENCY_CODE
|
| 2008 |
)
|
| 2009 |
|
|
|
|
| 2032 |
elif action == 'add_employee':
|
| 2033 |
emp_name = request.form.get('employee_name', '').strip()
|
| 2034 |
pin = request.form.get('pin', '0000').strip()
|
| 2035 |
+
try: daily_rate = float(request.form.get('daily_rate', 0))
|
| 2036 |
+
except: daily_rate = 0
|
| 2037 |
+
try: target_amount = float(request.form.get('target_amount', 0))
|
| 2038 |
+
except: target_amount = 0
|
| 2039 |
+
try: bonus_percentage = float(request.form.get('bonus_percentage', 0))
|
| 2040 |
+
except: bonus_percentage = 0
|
| 2041 |
|
| 2042 |
if emp_name:
|
| 2043 |
employees.append({
|
|
|
|
| 2057 |
if e.get('id') == emp_id:
|
| 2058 |
e['name'] = request.form.get('name', '').strip()
|
| 2059 |
e['pin'] = request.form.get('pin', '0000').strip()
|
| 2060 |
+
try: e['daily_rate'] = float(request.form.get('daily_rate', 0))
|
| 2061 |
+
except: e['daily_rate'] = 0
|
| 2062 |
+
try: e['target_amount'] = float(request.form.get('target_amount', 0))
|
| 2063 |
+
except: e['target_amount'] = 0
|
| 2064 |
+
try: e['bonus_percentage'] = float(request.form.get('bonus_percentage', 0))
|
| 2065 |
+
except: e['bonus_percentage'] = 0
|
| 2066 |
break
|
| 2067 |
data['employees'] = employees
|
| 2068 |
save_data(data)
|