Compare commits

...

4 Commits

Author SHA1 Message Date
Docker Config Backup
06a7e65340 fix: negative PMS (práce mimo směnu) hours count in FPD totals
Web FPD check: PMS hours keep their sign (getPmsHours) instead of being
dropped when negative. Month Excel FPD column: PMS was not counted at
all; it now adds the signed PMS hours like the web.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-30 08:52:13 +02:00
Docker Config Backup
c220956146 feat: month Excel FPD column matches the web FPD check for N and O
Restores the rule from 707e18c: a working-day N or O is credited as a
worked day (8 h) in the FPD column of the Excel exported by the
"Excel" button, the same as the web FPD check. Reverts e2da33b.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-22 09:42:16 +02:00
Docker Config Backup
e2da33bc44 revert: month Excel FPD column counts N/O as 0 h again
The Excel FPD column is meant to differ from the web FPD check; only
O should behave like N, which it already did. Keeps the D-like colour
for O.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-22 09:36:18 +02:00
Docker Config Backup
575164d8a1 fix: name is Kopáček Ondřej (second correction)
Rename Kópáček → Kopáček in default data, both Excel templates and the
export rosters; the server fix-up map now maps both earlier spellings
to the correct one.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-22 09:34:41 +02:00
8 changed files with 30 additions and 8 deletions

Binary file not shown.

View File

@@ -38,7 +38,7 @@ TEMPLATE_NAMES = [
'Vörös Pavel', 'Vörös Pavel',
'Janouš Petr', 'Janouš Petr',
'Dvořák Václav', 'Dvořák Václav',
'Kópáček Ondřej', 'Kopáček Ondřej',
'Toman Milan', 'Toman Milan',
'Hanzlík Marek', 'Hanzlík Marek',
'Vondrák Pavel', 'Vondrák Pavel',
@@ -52,7 +52,7 @@ PERSON_DATA = {
'Žemlička Miroslav': {'auto': 'AUS', 'km_tkb': 40, 'km_sat': 0}, 'Žemlička Miroslav': {'auto': 'AUS', 'km_tkb': 40, 'km_sat': 0},
'Franek Lukáš': {'auto': 'AUS', 'km_tkb': 40, 'km_sat': 0}, 'Franek Lukáš': {'auto': 'AUS', 'km_tkb': 40, 'km_sat': 0},
'Dvořák Václav': {'auto': 'AUS', 'km_tkb': 0, 'km_sat': 0}, 'Dvořák Václav': {'auto': 'AUS', 'km_tkb': 0, 'km_sat': 0},
'Kópáček Ondřej': {'auto': 'AUS', 'km_tkb': 0, 'km_sat': 0}, # TODO confirm auto/km 'Kopáček Ondřej': {'auto': 'AUS', 'km_tkb': 0, 'km_sat': 0}, # TODO confirm auto/km
'Toman Milan': {'auto': 'AUS', 'km_tkb': 0, 'km_sat': 0}, 'Toman Milan': {'auto': 'AUS', 'km_tkb': 0, 'km_sat': 0},
'Kohl David': {'auto': 'AUS', 'km_tkb': 0, 'km_sat': 0}, 'Kohl David': {'auto': 'AUS', 'km_tkb': 0, 'km_sat': 0},
'Milisavljevič Jovica':{'auto': 'AUS', 'km_tkb': 0, 'km_sat': 0}, 'Milisavljevič Jovica':{'auto': 'AUS', 'km_tkb': 0, 'km_sat': 0},

View File

@@ -36,7 +36,7 @@ CZECH_DAYS = ['Pondělí', 'Úterý', 'Středa', 'Čtvrtek', 'Pátek', 'Sobota',
TKB_ROWS = { TKB_ROWS = {
'Pauzer Libor': 7, 'Vörös Pavel': 8, 'Janouš Petr': 9, 'Pauzer Libor': 7, 'Vörös Pavel': 8, 'Janouš Petr': 9,
'Franek Lukáš': 10, 'Svoboda Daniel': 11, 'Dvořák Václav': 12, 'Franek Lukáš': 10, 'Svoboda Daniel': 11, 'Dvořák Václav': 12,
'Kópáček Ondřej': 13, 'Kopáček Ondřej': 13,
'Vondrák Pavel': 14, 'Čeleda Olda': 15, 'Hanzlík Marek': 16, 'Vondrák Pavel': 14, 'Čeleda Olda': 15, 'Hanzlík Marek': 16,
'Kohl David': 17, 'Dittrich Vladimír': 18, 'Toman Milan': 19, 'Kohl David': 17, 'Dittrich Vladimír': 18, 'Toman Milan': 19,
'Zábranský Petr': 20, 'Žemlička Miroslav': 21, 'Teslík Hynek': 22, 'Zábranský Petr': 20, 'Žemlička Miroslav': 21, 'Teslík Hynek': 22,
@@ -87,6 +87,17 @@ def czech_holidays(year):
return out return out
def pms_hours(value):
"""PMS (práce mimo směnu) hours — like hours_for, but negative values keep
their sign (hours taken off). Matches getPmsHours in FpdCheck.tsx."""
if value in ('A', 'B'):
return 12
try:
return float(value)
except (ValueError, TypeError):
return 0
def hours_for(value): def hours_for(value):
"""Match webapp's getHoursForValue (FpdCheck.tsx): """Match webapp's getHoursForValue (FpdCheck.tsx):
A and B count as 12 hours; numeric values as themselves; A and B count as 12 hours; numeric values as themselves;
@@ -463,6 +474,10 @@ def main():
collect(cd.get('nightValue'), is_workday) collect(cd.get('nightValue'), is_workday)
else: else:
collect(cd.get('v'), is_workday) collect(cd.get('v'), is_workday)
# PMS (práce mimo směnu) counts as worked hours, positive or negative (as in FpdCheck.tsx)
pms_v = (person['data'].get(str(-month)) or {}).get('v')
if pms_v:
worked += pms_hours(pms_v)
person_fpd = month_fpd - vacation person_fpd = month_fpd - vacation
diff = worked - person_fpd diff = worked - person_fpd
dst = ws.cell(row, 72) dst = ws.cell(row, 72)

View File

@@ -42,8 +42,8 @@ HALF_TIME_NAMES = {'Dittrich Vladimír'}
ROSTER = [ ROSTER = [
('Dvořák Václav (VN)', 'TKB', 1247, 'Dvořák Václav'), ('Dvořák Václav (VN)', 'TKB', 1247, 'Dvořák Václav'),
# Kópáček Ondřej — part-time student, not in CIS (no personal number); add here # Kopáček Ondřej — part-time student, not in CIS (no personal number); add here
# if he joins full time: ('Kópáček Ondřej', 'TKB', <osobní číslo>, 'Kópáček Ondřej'), # if he joins full time: ('Kopáček Ondřej', 'TKB', <osobní číslo>, 'Kopáček Ondřej'),
('Vondrák Pavel (NN)', 'TKB', 454, 'Vondrák Pavel'), ('Vondrák Pavel (NN)', 'TKB', 454, 'Vondrák Pavel'),
('Čeleda Olda (NN)', 'TKB', 463, 'Čeleda Olda'), ('Čeleda Olda (NN)', 'TKB', 463, 'Čeleda Olda'),
('Hanzlík Marek (VN)', 'TKB', 1366, 'Hanzlík Marek'), ('Hanzlík Marek (VN)', 'TKB', 1366, 'Hanzlík Marek'),

Binary file not shown.

View File

@@ -96,7 +96,7 @@ function fileMeta(file) {
// People renamed after data already existed: fix the name wherever it is stored // People renamed after data already existed: fix the name wherever it is stored
// (files on disk at startup, and every incoming save from a client that still has the old name) // (files on disk at startup, and every incoming save from a client that still has the old name)
const PERSON_RENAMES = { 'Kropáček Ondřej': 'Kópáček Ondřej' } const PERSON_RENAMES = { 'Kropáček Ondřej': 'Kopáček Ondřej', 'Kópáček Ondřej': 'Kopáček Ondřej' }
function normalizePeople(data) { function normalizePeople(data) {
let changed = false let changed = false

View File

@@ -23,6 +23,12 @@ interface FpdResult {
infoOnly: boolean // contractor — never warn on shortfall infoOnly: boolean // contractor — never warn on shortfall
} }
function getPmsHours(v: string): number {
if (v === 'A' || v === 'B') return 12
const num = parseFloat(v)
return isNaN(num) ? 0 : num
}
function getHoursForValue(v: string): number { function getHoursForValue(v: string): number {
if (v === 'A' || v === 'B') return 12 if (v === 'A' || v === 'B') return 12
const num = parseFloat(v) const num = parseFloat(v)
@@ -81,8 +87,9 @@ export function computeFpd(
} }
} }
// PMS (práce mimo směnu) is stored at day-index -month; counts as worked hours. // PMS (práce mimo směnu) is stored at day-index -month; counts as worked hours.
// Unlike day cells it may be negative (hours taken off), so keep the sign.
const pms = person.data[String(-month)]?.v const pms = person.data[String(-month)]?.v
if (pms) workedHours += getHoursForValue(pms) if (pms) workedHours += getPmsHours(pms)
const personFpd = workDays * dailyHours - vacationHours const personFpd = workDays * dailyHours - vacationHours
const diff = workedHours - personFpd const diff = workedHours - personFpd
results.push({ results.push({

View File

@@ -2965,7 +2965,7 @@
}, },
{ {
"id": "tkb-kropacek", "id": "tkb-kropacek",
"name": "Kópáček Ondřej", "name": "Kopáček Ondřej",
"group": "TKB", "group": "TKB",
"data": {} "data": {}
}, },