Auslastungsberechung angepasst
This commit is contained in:
1 parent
eb71a9160f
commit
eeb2e63f89
12 files changed
+646
-297
No files matched your search
@@ -1,133 +1,132 @@
|
|||||||
# AGENTS.md
|
# AGENTS.md
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Single-page app for tracking engineering projects across weekly sessions
|
||||||
|
("Sitzungen"). Vanilla JS/HTML/CSS frontend + Node.js/Express server. No build
|
||||||
|
step, no bundler, no tests. Data is persisted as semicolon-separated CSVs
|
||||||
|
under `sessions/`.
|
||||||
|
|
||||||
|
Two HTML entrypoints, both served statically by Express:
|
||||||
|
- `Test.html` — the main app (tabs: Projektboard, Auslastung, Projekte,
|
||||||
|
Projektbeteiligte). Served at `/`.
|
||||||
|
- `project-plan.html` — per-project Gantt/TODO planning view, opened in a new
|
||||||
|
tab via `openProjectPlan()` in `main.v2.js:2358`. Loads `main.v2.js` first,
|
||||||
|
then `project-plan.js`.
|
||||||
|
|
||||||
|
All UI strings/comments/CSV content are German. Preserve German in
|
||||||
|
user-facing text.
|
||||||
|
|
||||||
## File structure
|
## File structure
|
||||||
|
|
||||||
```
|
```
|
||||||
.
|
.
|
||||||
├── server.js # Express server with API endpoints
|
├── server.js # Express server + CSV API
|
||||||
├── package.json # Dependencies (express, cors)
|
├── package.json # deps: express, cors only
|
||||||
|
├── docker-compose.yml # at repo ROOT; build context ., dockerfile Docker/Dockerfile
|
||||||
|
├── Docker/Dockerfile # node:20-alpine
|
||||||
|
├── .dockerignore
|
||||||
|
├── .vscode/extensions.json
|
||||||
├── public/
|
├── public/
|
||||||
│ ├── Test.html # Root HTML file (served at /)
|
│ ├── Test.html # main app (served at /)
|
||||||
│ ├── main.v2.js # Complete frontend client app
|
│ ├── main.v2.js # entire main client app (~3200 lines)
|
||||||
│ └── styles.css # UI styles
|
│ ├── project-plan.html # Gantt/TODO planning view
|
||||||
├── Docker/
|
│ ├── project-plan.js # planning logic (~1500 lines)
|
||||||
│ └── Dockerfile # Node.js Alpine image
|
│ ├── styles.css
|
||||||
├── docker-compose.yml # Docker service definition
|
│ └── dein_bild.ico
|
||||||
└── sessions/ # Data directory (bind-mounted in Docker)
|
└── sessions/ # data; bind-mounted into Docker container
|
||||||
├── ELT/ # Elektro department
|
├── ELT/ HLS/ ARCH/ # one folder per department
|
||||||
├── HLS/ # HLS department
|
|
||||||
└── ARCH/ # Architektur department
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
Single-page app for tracking engineering projects across weekly sessions
|
|
||||||
("Sitzungen"). Vanilla JS/HTML/CSS frontend (`public/`) + Node.js/Express server
|
|
||||||
(`server.js`). No build step, no bundler. Data is persisted as CSV files under
|
|
||||||
`sessions/`.
|
|
||||||
|
|
||||||
## Running
|
## Running
|
||||||
|
|
||||||
- `npm install` then `npm start` (executes `node server.js`).
|
|
||||||
- Or with Docker: `docker compose -f Docker/docker-compose.yml up --build`.
|
|
||||||
- Server runs on `PORT` env var or defaults to `3003`; serves `public/Test.html`
|
|
||||||
as root and API under `/load-all`, `/save-csv`, `/delete-csv`.
|
|
||||||
- Frontend assumes the API lives at `window.location.origin`, falling back to
|
|
||||||
`http://localhost:3003` when opened as a local file. Opening `Test.html`
|
|
||||||
directly without a server will load seed/demo data.
|
|
||||||
|
|
||||||
## Operations
|
|
||||||
|
|
||||||
### Local
|
|
||||||
```bash
|
```bash
|
||||||
npm install
|
npm install
|
||||||
npm start
|
npm start # http://localhost:3003, or PORT=3004 if occupied
|
||||||
|
docker compose up --build # Docker variant (compose file is at repo root)
|
||||||
```
|
```
|
||||||
Access at `http://localhost:3003` (or `PORT=3004` if occupied).
|
|
||||||
|
|
||||||
### Docker
|
- PORT env var overrides default 3003 in `server.js`.
|
||||||
```bash
|
- Frontend must be served over HTTP: `baseUrl()` in `main.v2.js` uses
|
||||||
docker compose -f Docker/docker-compose.yml up --build
|
`window.location.origin` or falls back to `http://localhost:3003` when opened
|
||||||
```
|
via `file://` (then only seed/demo data loads).
|
||||||
Access at `http://localhost:3003` (or override with `PORT=3004`).
|
- Check `/health` returns `{ok:true}` after starting.
|
||||||
|
|
||||||
|
## Server API (`server.js`)
|
||||||
|
|
||||||
|
- `GET /` → `Test.html`; `GET /health`.
|
||||||
|
- `GET /load-all?department=` → `{sessions:[{filename,content}], people}` with
|
||||||
|
`_people.csv` content in `people`; sessions sorted by filename.
|
||||||
|
- `POST /save-csv {filename, csv, department}` → writes UTF-8 BOM CSV.
|
||||||
|
- `POST /delete-csv {filename, department}`.
|
||||||
|
- Valid departments hard-coded as `ELT|HLS|ARCH` in `server.js`
|
||||||
|
(`VALID_DEPARTMENTS`); anything else silently falls back to `ELT`. Same set in
|
||||||
|
`DEPARTMENTS` in `main.v2.js`.
|
||||||
|
- `safeName()` strictly validates filenames (path traversal protection);
|
||||||
|
static assets get `Cache-Control: no-store`.
|
||||||
|
- JSON body limit is 2 MB.
|
||||||
|
|
||||||
## CSV format
|
## CSV format
|
||||||
|
|
||||||
- Delimiter: semicolon (`;`)
|
- Delimiter `;`, UTF-8 with BOM. Hand-editing is possible but risky; the parser
|
||||||
- Encoding: UTF-8 with BOM (`\ufeff`)
|
reconstructs objects from the fixed column layout.
|
||||||
- Structure:
|
- Week files `<Label>.csv` (e.g. `KW_30___2026.csv` — `filenameForWeek()`
|
||||||
- `sessions/<DEPT>/` contains department data
|
replaces non-word chars with `_`). Row layout is positional:
|
||||||
- Week files: `<Label>.csv` (e.g., `KW_30___2026.csv`)
|
`WOCHE` (label, date, locked flag) → `PERSONEN` (`name|role|fullName` per
|
||||||
- Global people: `_people.csv` with columns `NAME;Rollen;Voller Name`
|
column) → header row → `ANWESENHEIT` → one row per project.
|
||||||
|
- `_people.csv` per department: `NAME;Rollen;Voller Name;E-Mail;Abwesenheiten`
|
||||||
|
(absences as JSON). People are global per department; new people are copied
|
||||||
|
into the current week. Historical weeks keep their own person copies, so
|
||||||
|
deleting a global person leaves old sessions unaffected no matter what.
|
||||||
|
- Don't change the column layout without updating both `weekToCsv()` and
|
||||||
|
`parseSessionCsv()` (`main.v2.js`), which must stay inverse of each other.
|
||||||
|
|
||||||
## Data layout
|
## Frontend architecture
|
||||||
- Data is split by department: `sessions/ELT/`, `sessions/HLS/`, `sessions/ARCH/`.
|
|
||||||
Valid departments are hard-coded in `server.js` (`VALID_DEPARTMENTS`) and
|
|
||||||
`main.v2.js` (`DEPARTMENTS`). Unknown department values fall back to `ELT`.
|
|
||||||
- Each week is one CSV file named `<Label>.csv` with `;` delimiter and UTF-8 BOM.
|
|
||||||
- Each department has a global people list in `_people.csv` with columns
|
|
||||||
`NAME;Rollen;Voller Name`. New people are added globally and copied into the
|
|
||||||
current week. Historical weeks keep their own person copies so deleted global
|
|
||||||
people remain visible in old sessions.
|
|
||||||
- The app reads CSVs on startup via `/load-all`; `localStorage` is used only
|
|
||||||
for the last-selected department/tab UI state. Do not store data in
|
|
||||||
`localStorage`.
|
|
||||||
- Editing CSVs by hand is possible but risky; prefer the UI.
|
|
||||||
|
|
||||||
## Architecture notes
|
- `main.v2.js` is loaded as a classic non-module `<script>`; **all functions are
|
||||||
|
globals on `window`** and shared across both pages. Edit functions in place;
|
||||||
- Frontend is in `public/` (`Test.html`, `main.v2.js`, `styles.css`).
|
the file is one large script with German section-header comments.
|
||||||
- `main.v2.js` is the entire client app loaded as a classic non-module `<script>`;
|
- State: `let db = { weeks, currentWeek, globalPeople }` (in-memory only).
|
||||||
all functions are globals on `window`.
|
- Project IDs are regenerated on every CSV load, so projects are addressed
|
||||||
- State lives in `let db = { weeks: [], currentWeek, globalPeople: {} }`.
|
cross-page by `department` + week `label` + `projNr` + `projName` via URL
|
||||||
- Each week object has `projects` (with `assign`, `lph`, `group`, `status`,
|
params (`openProjectPlan`, `findProjectForPlan`).
|
||||||
`order`) and `people` with session-local copies.
|
- Person IDs are stable across reloads via `personIdForName(name)` →
|
||||||
- `save()` schedules `syncAllToServer()` debounced by 500 ms; this writes **all**
|
`p_<lowercased alnum>`.
|
||||||
weeks plus the global `_people.csv` to the server, not just the changed one.
|
- `save()` debounces 500 ms then `syncAllToServer()` writes **all** weeks plus
|
||||||
- Weeks are sorted by calendar week extracted from the label (`KW XX / YYYY`),
|
`_people.csv` — not just the changed week. Exception: `project-plan.js`
|
||||||
not alphabetically.
|
`savePlan()` bypasses `save()` and writes only the current week's CSV directly
|
||||||
|
via `sendCsvToServer()`.
|
||||||
|
- Weeks are sorted by calendar week extracted from the label (`KW XX / YYYY`)
|
||||||
|
via `weekSortKey()`, not alphabetically/by filename.
|
||||||
- `applyAutoLock()` locks every week except the chronologically last one after
|
- `applyAutoLock()` locks every week except the chronologically last one after
|
||||||
load/clone/new-week, so historical weeks are read-only unless explicitly
|
load/clone/new-week; `localStorage` UI state is not restored for locked tabs.
|
||||||
unlocked.
|
- `localStorage` keys: `projuebersicht_v1` (department only — tab is never
|
||||||
- Person IDs are derived from the person's abbreviation/name to stay stable
|
restored), `projuebersicht-theme`, header-collapse key. Do **not** store data
|
||||||
across reloads (`personIdForName` in `main.v2.js`).
|
in `localStorage`; it is UI state only.
|
||||||
|
|
||||||
|
## Auth / security quirk
|
||||||
|
|
||||||
|
- The `projects` and `people` tabs, week deletion, and week unlock are gated by
|
||||||
|
a password modal comparing `CryptoJS.SHA256(input)` to
|
||||||
|
`PROTECTED_PASSWORD_HASH` (`main.v2.js`). Client-side only — not real
|
||||||
|
security. CryptoJS and pdfmake (PDF export) are loaded from
|
||||||
|
`cdnjs.cloudflare.com` in `Test.html`, so those features need internet access
|
||||||
|
and won't work offline. `project-plan.html` loads neither.
|
||||||
|
- User-provided status HTML is sanitized on render via a small whitelist
|
||||||
|
(`sanitizeStatusHtml` in `main.v2.js`) to mitigate XSS.
|
||||||
|
|
||||||
## Docker
|
## Docker
|
||||||
|
|
||||||
- Dockerfile uses `node:20-alpine` as base image.
|
- `docker compose up --build` from the repo root. Compose maps `3003:3003`,
|
||||||
- Copies only `package.json/package-lock.json` first (`npm ci --production`), then server files.
|
bind-mounts `./sessions:/app/sessions`, `restart: unless-stopped`.
|
||||||
- Excludes `Docker/`, `node_modules/`, `.git`, `.gitignore` via `.dockerignore`.
|
- Dockerfile: `node:20-alpine`, `npm ci --production`, runs as non-root `node`,
|
||||||
- Runs as non-root `node` user; `/app/sessions` bind-mounted from host `./sessions`.
|
HEALTHCHECK on `/health`. `.dockerignore` excludes `Docker/*` (except
|
||||||
- HEALTHCHECK on `/health` endpoint; service restarts on failure (`unless-stopped`).
|
`Docker/Dockerfile`), `node_modules/`, `.git`, `npm-debug.log`.
|
||||||
- Frontend must be served via HTTP (not `file://`) for CORS to work.
|
|
||||||
|
|
||||||
## Security / auth quirk
|
## Conventions & verification
|
||||||
|
|
||||||
- `projects` and `people` tabs plus week deletion are gated by a password modal.
|
- Git repo; commits are German (e.g. "PDF Export von A4 auf A3 …"). Remote:
|
||||||
The check compares `CryptoJS.SHA256(input)` to `PROTECTED_PASSWORD_HASH` in
|
`http://192.168.3.187:3000/erik/projektuebersicht.git`.
|
||||||
`main.v2.js`. This is client-side only and **not real security**. CryptoJS is
|
- No linter, formatter, typecheck, or test suite. Manual verification only:
|
||||||
loaded from a CDN (`cdnjs.cloudflare.com`) in `Test.html`, so the password
|
start server, open `http://localhost:3003`, exercises the relevant tab,
|
||||||
gate needs internet access.
|
confirm CSV changes in `sessions/`.
|
||||||
- User-provided status HTML is sanitized on render (small tag/attribute
|
|
||||||
whitelist) to mitigate XSS while keeping formatting options.
|
|
||||||
- Filenames sent to `/save-csv` and `/delete-csv` are strictly validated server
|
|
||||||
side to prevent path traversal.
|
|
||||||
|
|
||||||
## Conventions
|
|
||||||
|
|
||||||
- UI strings, comments, and CSV content are German. Preserve German in
|
|
||||||
user-facing text.
|
|
||||||
- No linter, formatter, typecheck, or test suite is configured. Verify changes
|
|
||||||
by running the server and exercising the relevant tab in the browser.
|
|
||||||
- This is **not** a git repo. Don't assume git workflows.
|
|
||||||
- Edit `main.v2.js` functions in place; the file is intentionally one large script
|
|
||||||
with German header comments per section. Match that style.
|
|
||||||
|
|
||||||
## Testing & verification
|
|
||||||
|
|
||||||
- No automated test suite exists. Manual verification only:
|
|
||||||
- Start server (`npm start` or Docker)
|
|
||||||
- Open `http://localhost:3003`
|
|
||||||
- Check `/health` endpoint returns `{ok:true}`
|
|
||||||
- Exercise relevant tab in browser (Board, Projects, People)
|
|
||||||
- Verify CSV persistence in `sessions/` directory
|
|
||||||
+55
-10
@@ -106,7 +106,7 @@
|
|||||||
<option value="current">Aktuelle Sitzung</option>
|
<option value="current">Aktuelle Sitzung</option>
|
||||||
<option value="all">Alle Sitzungen (Historie)</option>
|
<option value="all">Alle Sitzungen (Historie)</option>
|
||||||
</select>
|
</select>
|
||||||
<span class="hint">Zählt Projektzuordnungen (Haupt=1 · Optional=0,5 · Kleine Projekte=0,3 · In Anbahnung wird nicht gezählt).</span>
|
<span class="hint">Auswertung über den rollenspezifischen Gewichtungsfaktor je Leistungsphase.</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="load-grid" id="loadGrid"></div>
|
<div class="load-grid" id="loadGrid"></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -115,15 +115,7 @@
|
|||||||
<div id="projects" style="display:none">
|
<div id="projects" style="display:none">
|
||||||
<div class="section-title">Projekte verwalten</div>
|
<div class="section-title">Projekte verwalten</div>
|
||||||
<div class="toolbar" style="margin-bottom:12px">
|
<div class="toolbar" style="margin-bottom:12px">
|
||||||
<input type="text" id="newProjNr" placeholder="Projekt-Nr. (z.B. 26-4001)">
|
<button onclick="openNewProjModal()">+ Neues Projekt</button>
|
||||||
<input type="text" id="newProjName" placeholder="Projektbezeichnung">
|
|
||||||
<select id="newProjGroup">
|
|
||||||
<option>Aktive Projekte</option>
|
|
||||||
<option>Kleine Projekte</option>
|
|
||||||
<option>In Anbahnung</option>
|
|
||||||
<option>Allgemein</option>
|
|
||||||
</select>
|
|
||||||
<button onclick="addProjectToList()">+ Projekt hinzufügen</button>
|
|
||||||
</div>
|
</div>
|
||||||
<div id="projectsList"></div>
|
<div id="projectsList"></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -162,6 +154,59 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Aufwand je Leistungsphase Modal -->
|
||||||
|
<div class="modal-bg" id="lpModal" style="display:none">
|
||||||
|
<div class="modal">
|
||||||
|
<h2>Aufwand je Leistungsphase</h2>
|
||||||
|
<p style="color:#888;margin-bottom:6px" id="lpModalProject"></p>
|
||||||
|
<p class="hint" style="margin-bottom:10px">
|
||||||
|
Rollenbezogene Gewichtungsfaktoren je Leistungsphase (Standard 1,0).
|
||||||
|
Die amtierende Leistungsphase wird pro Projekt im Tab „Projekte" gewählt.
|
||||||
|
</p>
|
||||||
|
<div id="lpModalRows"></div>
|
||||||
|
<div class="toolbar" style="margin-top:12px">
|
||||||
|
<button onclick="saveLpModal()">Speichern</button>
|
||||||
|
<button class="secondary" onclick="closeLpModal()">Abbrechen</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Neues Projekt Modal (inkl. LP-Aufwand) -->
|
||||||
|
<div class="modal-bg" id="newProjModal" style="display:none">
|
||||||
|
<div class="modal">
|
||||||
|
<h2>Neues Projekt</h2>
|
||||||
|
<div class="form-row">
|
||||||
|
<label>Projekt-Nr.</label>
|
||||||
|
<input type="text" id="newProjNr" placeholder="z. B. 26-4001" style="width:100%">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label>Bezeichnung</label>
|
||||||
|
<input type="text" id="newProjName" placeholder="Projektbezeichnung" style="width:100%">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label>Gruppe</label>
|
||||||
|
<select id="newProjGroup" style="width:100%">
|
||||||
|
<option>Aktive Projekte</option>
|
||||||
|
<option>Kleine Projekte</option>
|
||||||
|
<option>In Anbahnung</option>
|
||||||
|
<option>Allgemein</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label>Aktive Leistungsphase</label>
|
||||||
|
<select id="newProjActiveLP" style="width:100%"></select>
|
||||||
|
</div>
|
||||||
|
<p class="hint" style="margin:8px 0 10px">
|
||||||
|
Rollenbezogener Gewichtungsfaktor je Leistungsphase (Standard 1,0).
|
||||||
|
</p>
|
||||||
|
<div id="newProjLpRows"></div>
|
||||||
|
<div class="toolbar" style="margin-top:12px">
|
||||||
|
<button onclick="saveNewProj()">Anlegen</button>
|
||||||
|
<button class="secondary" onclick="closeNewProjModal()">Abbrechen</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<script src="main.v2.js"></script>
|
<script src="main.v2.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
+334
-89
@@ -610,9 +610,9 @@ function weekToCsv(w){
|
|||||||
// Der volle Name wird immer als dritter Teil gespeichert (auch leer),
|
// Der volle Name wird immer als dritter Teil gespeichert (auch leer),
|
||||||
// damit er beim Bearbeiten nicht versehentlich verloren geht.
|
// damit er beim Bearbeiten nicht versehentlich verloren geht.
|
||||||
const peopleMeta = allPeople.map(e => `${e.person.name}|${e.role}|${e.person.fullName || ''}`);
|
const peopleMeta = allPeople.map(e => `${e.person.name}|${e.role}|${e.person.fullName || ''}`);
|
||||||
rows.push(['PERSONEN', '', '', ...peopleMeta, ...LPHS.map(() => ''), '','']);
|
rows.push(['PERSONEN', '', '', ...peopleMeta, ...LPHS.map(() => ''), '','','','','']);
|
||||||
rows.push(['Pr.-Nr.','Bezeichnung','Status', ...allPeople.map(e => e.person.name), ...LPHS, 'Gruppe','Index','Plan']);
|
rows.push(['Pr.-Nr.','Bezeichnung','Status', ...allPeople.map(e => e.person.name), ...LPHS, 'Gruppe','Index','Plan','Aufwand','Aktive Phasen']);
|
||||||
rows.push(['ANWESENHEIT','', ...allPeople.map(e => w.attendance && w.attendance[e.person.id] ? 'X' : ''), ...LPHS.map(() => ''),'','','']);
|
rows.push(['ANWESENHEIT','', ...allPeople.map(e => w.attendance && w.attendance[e.person.id] ? 'X' : ''), ...LPHS.map(() => ''),'','','','','']);
|
||||||
w.projects.forEach(p => {
|
w.projects.forEach(p => {
|
||||||
const arr = [p.nr || '', p.name || '', p.status || ''];
|
const arr = [p.nr || '', p.name || '', p.status || ''];
|
||||||
allPeople.forEach(entry => {
|
allPeople.forEach(entry => {
|
||||||
@@ -626,6 +626,8 @@ function weekToCsv(w){
|
|||||||
arr.push(p.group || '');
|
arr.push(p.group || '');
|
||||||
arr.push(p.order !== undefined ? String(p.order) : '');
|
arr.push(p.order !== undefined ? String(p.order) : '');
|
||||||
arr.push(p.plan ? JSON.stringify(p.plan) : '');
|
arr.push(p.plan ? JSON.stringify(p.plan) : '');
|
||||||
|
arr.push(p.aufwandProLP ? JSON.stringify(p.aufwandProLP) : '');
|
||||||
|
arr.push(p.aktuelleLP ? JSON.stringify(p.aktuelleLP) : '');
|
||||||
rows.push(arr);
|
rows.push(arr);
|
||||||
});
|
});
|
||||||
return '\ufeff' + rows.map(r => r.map(csvEscape).join(';')).join('\n');
|
return '\ufeff' + rows.map(r => r.map(csvEscape).join(';')).join('\n');
|
||||||
@@ -736,6 +738,8 @@ function parseSessionCsv(filename, rows){
|
|||||||
const groupIdx = header.indexOf('Gruppe');
|
const groupIdx = header.indexOf('Gruppe');
|
||||||
const orderIdx = header.indexOf('Index');
|
const orderIdx = header.indexOf('Index');
|
||||||
const planIdx = header.indexOf('Plan');
|
const planIdx = header.indexOf('Plan');
|
||||||
|
const aufwandIdx = header.indexOf('Aufwand');
|
||||||
|
const aktiveIdx = header.indexOf('Aktive Phasen');
|
||||||
const peopleCols = header.slice(3, lphStart === -1 ? header.length : lphStart);
|
const peopleCols = header.slice(3, lphStart === -1 ? header.length : lphStart);
|
||||||
|
|
||||||
const people = [];
|
const people = [];
|
||||||
@@ -831,7 +835,28 @@ function parseSessionCsv(filename, rows){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
projects.push({ id: uid(), nr, name, status, group, lph, assign, order, plan });
|
let aufwandProLP;
|
||||||
|
if(aufwandIdx >= 0 && row[aufwandIdx]){
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(row[aufwandIdx]);
|
||||||
|
if(parsed && typeof parsed === 'object') aufwandProLP = parsed;
|
||||||
|
} catch(e) {
|
||||||
|
console.warn('LP-Aufwand für Projekt konnten nicht geparst werden:', nr, name, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let aktuelleLP;
|
||||||
|
if(aktiveIdx >= 0 && row[aktiveIdx]){
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(row[aktiveIdx]);
|
||||||
|
if(Array.isArray(parsed)) aktuelleLP = parsed;
|
||||||
|
else if(typeof parsed === 'string') aktuelleLP = [parsed];
|
||||||
|
} catch(e) {
|
||||||
|
console.warn('Aktive Phasen für Projekt konnten nicht geparst werden:', nr, name, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
projects.push({ id: uid(), nr, name, status, group, lph, assign, order, plan, aufwandProLP, aktuelleLP });
|
||||||
}
|
}
|
||||||
|
|
||||||
const attendance = {};
|
const attendance = {};
|
||||||
@@ -896,7 +921,7 @@ function seed(){
|
|||||||
|
|
||||||
// demoProj: Helfer zum Erzeugen eines Projekt-Objekts (für seed/Tests)
|
// demoProj: Helfer zum Erzeugen eines Projekt-Objekts (für seed/Tests)
|
||||||
function demoProj(nr,name,group,status,lph){
|
function demoProj(nr,name,group,status,lph){
|
||||||
return {id:uid(), nr, name, group, status, lph: {...lph}, assign:{}, plan: null};
|
return {id:uid(), nr, name, group, status, lph: {...lph}, assign:{}, plan: null, aufwandProLP: undefined, aktuelleLP: undefined};
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------- Week management ----------
|
// ---------- Week management ----------
|
||||||
@@ -1173,11 +1198,14 @@ function renderBoard(){
|
|||||||
body += `<td class="person-cell ${roleClass(entry.role)} ${cls} ${locked ? 'locked-cell' : ''}" ${click}>${txt}</td>`;
|
body += `<td class="person-cell ${roleClass(entry.role)} ${cls} ${locked ? 'locked-cell' : ''}" ${click}>${txt}</td>`;
|
||||||
});
|
});
|
||||||
|
|
||||||
// LPH-Spalten mit Prozentwerten und Fortschrittsbalken
|
// LPH-Spalten mit Prozentwerten und Fortschrittsbalken;
|
||||||
|
// die amtierende Leistungsphase (Tab "Projekte") wird farblich markiert.
|
||||||
|
const aktLp = lpActiveList(p)[0];
|
||||||
LPHS.forEach(l=>{
|
LPHS.forEach(l=>{
|
||||||
const v = (p.lph[l]!==undefined && p.lph[l]!="") ? p.lph[l] : "";
|
const v = (p.lph[l]!==undefined && p.lph[l]!="") ? p.lph[l] : "";
|
||||||
|
const aktiv = l === aktLp;
|
||||||
const inputAttr = locked ? 'readonly tabindex="-1"' : `onchange="editLph('${p.id}','${l}',this.value)"`;
|
const inputAttr = locked ? 'readonly tabindex="-1"' : `onchange="editLph('${p.id}','${l}',this.value)"`;
|
||||||
body += `<td class="lph-cell ${locked ? 'locked-cell' : ''}"><input type="text" value="${v}" ${inputAttr} placeholder="-">`;
|
body += `<td class="lph-cell ${locked ? 'locked-cell' : ''}${aktiv ? ' lp-aktiv' : ''}"${aktiv ? ' title="Aktive Leistungsphase"' : ''}><input type="text" value="${v}" ${inputAttr} placeholder="-">`;
|
||||||
if(v!=""){ const pct = Math.min(100, parseFloat(v)||0);
|
if(v!=""){ const pct = Math.min(100, parseFloat(v)||0);
|
||||||
body += `<div class="bar"><div style="width:${pct}%;background:${getProgressColor(pct)}"></div></div>`; }
|
body += `<div class="bar"><div style="width:${pct}%;background:${getProgressColor(pct)}"></div></div>`; }
|
||||||
body += `</td>`;
|
body += `</td>`;
|
||||||
@@ -1611,23 +1639,6 @@ function reorderPeople(){
|
|||||||
|
|
||||||
// ---------- Projekte (Listen-Ansicht) ----------
|
// ---------- Projekte (Listen-Ansicht) ----------
|
||||||
|
|
||||||
// addProjectToList: fügt ein Projekt über Eingabefelder in die aktuelle Sitzung
|
|
||||||
function addProjectToList(){
|
|
||||||
if(guardWeekLocked()) return;
|
|
||||||
const nr = document.getElementById('newProjNr').value.trim();
|
|
||||||
const name = document.getElementById('newProjName').value.trim();
|
|
||||||
if(!name){ alert("Bitte Projektbezeichnung eingeben."); return; }
|
|
||||||
const group = document.getElementById('newProjGroup').value;
|
|
||||||
const w = currentWeek();
|
|
||||||
const nextOrder = w.projects
|
|
||||||
.filter(p=>p.group===group)
|
|
||||||
.reduce((max,p)=> Math.max(max, p.order!==undefined ? p.order : 0), -1) + 1;
|
|
||||||
w.projects.push({id:uid(),nr,name,group,status:'',lph:{},assign:{}, statusState: undefined, order: nextOrder, plan: null});
|
|
||||||
document.getElementById('newProjNr').value='';
|
|
||||||
document.getElementById('newProjName').value='';
|
|
||||||
save(); renderProjects(); renderBoard();
|
|
||||||
}
|
|
||||||
|
|
||||||
// delProjectFromList: löscht ein Projekt in der Listen-Ansicht
|
// delProjectFromList: löscht ein Projekt in der Listen-Ansicht
|
||||||
function delProjectFromList(id){
|
function delProjectFromList(id){
|
||||||
if(guardWeekLocked()) return;
|
if(guardWeekLocked()) return;
|
||||||
@@ -1644,6 +1655,16 @@ function editProjectField(id,field,val){
|
|||||||
if(p){ p[field]=val; save(); renderProjects(); renderBoard(); }
|
if(p){ p[field]=val; save(); renderProjects(); renderBoard(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// editProjectActiveLP: setzt/hebt die amtierende Leistungsphase eines Projekts auf.
|
||||||
|
function editProjectActiveLP(id, value){
|
||||||
|
if(guardWeekLocked()) return;
|
||||||
|
const p = currentWeek().projects.find(x=>x.id===id);
|
||||||
|
if(!p) return;
|
||||||
|
if(value) p.aktuelleLP = [value];
|
||||||
|
else delete p.aktuelleLP;
|
||||||
|
save(); renderProjects(); renderBoard(); renderLoad();
|
||||||
|
}
|
||||||
|
|
||||||
// renderProjects: baut die HTML-Liste der Projekte (gruppiert nach group, mit Drag-and-Drop)
|
// renderProjects: baut die HTML-Liste der Projekte (gruppiert nach group, mit Drag-and-Drop)
|
||||||
function renderProjects(){
|
function renderProjects(){
|
||||||
const w = currentWeek();
|
const w = currentWeek();
|
||||||
@@ -1669,6 +1690,11 @@ function renderProjects(){
|
|||||||
<option ${p.group==='In Anbahnung'?'selected':''}>In Anbahnung</option>
|
<option ${p.group==='In Anbahnung'?'selected':''}>In Anbahnung</option>
|
||||||
<option ${p.group==='Allgemein'?'selected':''}>Allgemein</option>
|
<option ${p.group==='Allgemein'?'selected':''}>Allgemein</option>
|
||||||
</select>
|
</select>
|
||||||
|
<select onchange="editProjectActiveLP('${p.id}',this.value)" title="Aktive Leistungsphase wählen">
|
||||||
|
<option value="" ${lpActiveList(p).length===0?'selected':''}>Aktive LP: keine</option>
|
||||||
|
${AUFWAND_LPS.map(l => `<option value="${l}" ${lpActiveList(p)[0]===l?'selected':''}>${l}</option>`).join('')}
|
||||||
|
</select>
|
||||||
|
<button class="secondary small" onclick="openLpModal('${p.id}')">✎ LP-Aufwand</button>
|
||||||
<button class="danger small" onclick="delProjectFromList('${p.id}')">Löschen</button>
|
<button class="danger small" onclick="delProjectFromList('${p.id}')">Löschen</button>
|
||||||
</div>`;
|
</div>`;
|
||||||
});
|
});
|
||||||
@@ -1746,10 +1772,246 @@ function reorderProjects(){
|
|||||||
|
|
||||||
// ---------- Auslastung (Load) ----------
|
// ---------- Auslastung (Load) ----------
|
||||||
|
|
||||||
// renderLoad: berechnet die Belastung der Personen (Haupt=1, Optional=0,5)
|
// ---------- Aufwand je Leistungsphase (LP) ----------
|
||||||
// und zeigt eine einfache Visualisierung pro Rolle
|
//
|
||||||
|
// Datenmodell je Projekt (rollen- und leistungsphasenspezifisch):
|
||||||
|
// pr.aufwandProLP = {
|
||||||
|
// 'LPH 1': { Planung: 0.4, Projektleitung: 0.6, Bauüberwachung: 0.0 },
|
||||||
|
// ...
|
||||||
|
// } // Gewichtungsfaktor je Rolle (0.0–1.0)
|
||||||
|
// pr.aktuelleLP = ['LPH 6'] // aktuell amtierende Phase (max. 1)
|
||||||
|
//
|
||||||
|
// Es zählt genau eine amtierende Phase je Projekt ("Nur amtierende Einzelphase",
|
||||||
|
// Absprache mit dem Auftraggeber). Altdaten mit mehreren aktiven Phasen
|
||||||
|
// verwenden deterministisch die erste aktive Phase der Liste.
|
||||||
|
//
|
||||||
|
// Berechnungslogik:
|
||||||
|
// Auslastung(Mitarbeiter) = Σ Faktor der amtierenden LP je Projekt,
|
||||||
|
// in dem der Mitarbeiter (in seiner Rolle) zugewiesen ist.
|
||||||
|
// Der Faktor zählt 1:1 – die Zuordnungsart (Haupt/Optional) skaliert nicht.
|
||||||
|
// Leere Matrix-Felder zählen bei gesetzter aktiver LP mit dem Standard-Faktor
|
||||||
|
// 1,0; ohne gesetzte aktive LP zählt das Projekt 0 (nicht eingerechnet).
|
||||||
|
// "In Anbahnung" wird nicht eingerechnet.
|
||||||
|
//
|
||||||
|
// HINWEIS (Fachplaner-Fragen, bewusst NICHT eigenständig entschieden):
|
||||||
|
// - Ampel-Schwellen (50 % / 75 % des Maximalwerts) sind PLATZHALTER und müssen
|
||||||
|
// fachlich abgestimmt werden.
|
||||||
|
// - Mitarbeiterkapazität (Teilzeit/Vollzeit) existiert nicht – offener Punkt.
|
||||||
|
//
|
||||||
|
// AUFWAND_LPS: Phasen des Aufwandsmodells (LPH 1–8; "W+M" ist bewusst nicht
|
||||||
|
// enthalten, entspricht der Entscheidung "LP-Schema: lp1-8"). Es gibt keine
|
||||||
|
// Default-Vorlage: neue Projekte starten leer und zählen bei gesetzter aktiver
|
||||||
|
// LP je Rolle zu 1,0; ohne aktive LP zu 0.
|
||||||
|
const AUFWAND_LPS = LPHS.slice(0, 8);
|
||||||
|
|
||||||
|
// PLATZHALTER! Ampel-Schwellen als Anteil des Maximalwerts LOAD_BAR_MAX
|
||||||
|
// (gelb ab 50 %, rot ab 75 %). Müssen vom Fachplaner bestätigt werden.
|
||||||
|
const THRESHOLD_RATIO_CRITICAL = 0.75;
|
||||||
|
const THRESHOLD_RATIO_ELEVATED = 0.50;
|
||||||
|
|
||||||
|
function lpActiveList(pr){
|
||||||
|
const a = pr && pr.aktuelleLP;
|
||||||
|
if(Array.isArray(a)) return a.filter(l => AUFWAND_LPS.includes(l));
|
||||||
|
if(typeof a === 'string' && AUFWAND_LPS.includes(a)) return [a];
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// aufwandMatrixWert: Rollenwert eines Projekts für eine Leistungsphase
|
||||||
|
// (Gewichtungsfaktor, 0,0–1,0). Liefert null, wenn keine (rollenspezifische) Matrix
|
||||||
|
// bzw. kein Wert für diese Phase/Rolle hinterlegt ist. 0 ist ein gültiger Wert.
|
||||||
|
function aufwandMatrixWert(projekt, lp, rolle){
|
||||||
|
const m = projekt && projekt.aufwandProLP;
|
||||||
|
const entry = (m && typeof m === 'object') ? m[lp] : undefined;
|
||||||
|
if(!entry || typeof entry !== 'object' || Array.isArray(entry)) return null;
|
||||||
|
const v = parseFloat(entry[rolle]);
|
||||||
|
return isNaN(v) ? null : v;
|
||||||
|
}
|
||||||
|
|
||||||
|
// berechneAuslastung: zentrale Auslastungsberechnung einer Zuordnung
|
||||||
|
// (Person/Rolle) zu einem Projekt für die amtierende Leistungsphase.
|
||||||
|
// Ohne gesetzte aktive LP zählt das Projekt 0 (nicht eingerechnet).
|
||||||
|
// Mit aktiver LP: Liegt aufwandProLP[aktuelleLP][rolle] vor, zählt dieser
|
||||||
|
// Faktor 1:1 – die Zuordnungsart (Haupt/Optional) skaliert bewusst nicht mehr.
|
||||||
|
// Fehlt der Matrix-Wert, gilt der Standard-Faktor 1,0.
|
||||||
|
// "In Anbahnung" wird nicht eingerechnet.
|
||||||
|
function berechneAuslastung(mitarbeiter, projekt, aktuelleLP, rolle, status){
|
||||||
|
if(!projekt || projekt.group === 'In Anbahnung') return { load: 0, anbahnung: true };
|
||||||
|
if(!aktuelleLP) return { load: 0 };
|
||||||
|
const wert = aufwandMatrixWert(projekt, aktuelleLP, rolle);
|
||||||
|
if(wert !== null) return { load: wert };
|
||||||
|
return { load: 1.0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
// faktorFormat: formatiert einen Auslastungs-Faktor in deutscher Notation
|
||||||
|
// (Komma, max. 2 Nachkommastellen), z. B. 1.1 → "1,10". 1,0 = 100 % Kapazität.
|
||||||
|
function faktorFormat(x){
|
||||||
|
const n = Math.round((x || 0) * 100) / 100;
|
||||||
|
return n.toFixed(2).replace('.', ',');
|
||||||
|
}
|
||||||
|
|
||||||
|
// loadAmpelColor: Ampel-Farbe relativ zum Maximalwert (gelb ab 50 %,
|
||||||
|
// rot ab 75 % von LOAD_BAR_MAX; PLATZHALTER).
|
||||||
|
function loadAmpelColor(x){
|
||||||
|
return x >= LOAD_BAR_MAX * THRESHOLD_RATIO_CRITICAL ? '#c53030' : x >= LOAD_BAR_MAX * THRESHOLD_RATIO_ELEVATED ? '#d69e2e' : '#2f855a';
|
||||||
|
}
|
||||||
|
function pdfLoadAmpelColor(x){
|
||||||
|
return x >= LOAD_BAR_MAX * THRESHOLD_RATIO_CRITICAL ? '#D70015' : x >= LOAD_BAR_MAX * THRESHOLD_RATIO_ELEVATED ? '#B25000' : '#248A3D';
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- LP-Aufwand Eingabemaske ----------
|
||||||
|
|
||||||
|
let lpModalProjectId = null;
|
||||||
|
|
||||||
|
// lpRowsHtml: erzeugt die Aufwand-Maske als Matrix-Tabelle.
|
||||||
|
// Zeilen = Leistungsphasen (LPH 1–8), Spalten = Rollen (Planung/Projektleitung/
|
||||||
|
// Bauüberwachung). Die amtierende Leistungsphase wird pro Projekt im Tab
|
||||||
|
// "Projekte" gewählt (renderProjects / editProjectActiveLP).
|
||||||
|
// prefix: 'lp' = Bearbeiten-Modal, 'np' = Neues-Projekt-Modal (eindeutige IDs).
|
||||||
|
// Die Feld-IDs bleiben identisch, damit collectLpRows() unverändert funkioniert.
|
||||||
|
function lpRowsHtml(p, prefix){
|
||||||
|
const head = ROLES.map(r => `<th>${esc(r)}</th>`).join('');
|
||||||
|
const rows = AUFWAND_LPS.map(l => {
|
||||||
|
const idx = l.replace(/[^\d]/g,'');
|
||||||
|
const row = (p.aufwandProLP && typeof p.aufwandProLP[l] === 'object') ? p.aufwandProLP[l] : {};
|
||||||
|
const cells = ROLES.map((r, ri) => {
|
||||||
|
const raw = row[r];
|
||||||
|
const val = (raw !== undefined && raw !== null && raw !== '')
|
||||||
|
? String(parseFloat(raw)).replace('.', ',') : '';
|
||||||
|
return `<td><input type="text" inputmode="decimal" id="${prefix}Val${idx}R${ri}" value="${val}" placeholder="1,0"></td>`;
|
||||||
|
}).join('');
|
||||||
|
return `<tr><th class="lp-lph">${l}</th>${cells}</tr>`;
|
||||||
|
}).join('');
|
||||||
|
return `<table class="lp-matrix">
|
||||||
|
<thead><tr><th class="lp-lph">Leistungsphase</th>${head}</tr></thead>
|
||||||
|
<tbody>${rows}</tbody>
|
||||||
|
</table>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// collectLpRows: liest die Aufwand-Maske aus und validiert die Werte (0–1).
|
||||||
|
// Rückgabe: { aufwand, hasValue } oder null bei Eingabefehler.
|
||||||
|
function collectLpRows(prefix){
|
||||||
|
const aufwand = {};
|
||||||
|
let hasValue = false;
|
||||||
|
for(const l of AUFWAND_LPS){
|
||||||
|
const idx = l.replace(/[^\d]/g,'');
|
||||||
|
const entry = {};
|
||||||
|
let rowHasValue = false;
|
||||||
|
let invalid = false;
|
||||||
|
for(let ri = 0; ri < ROLES.length; ri++){
|
||||||
|
const r = ROLES[ri];
|
||||||
|
const input = document.getElementById(prefix + 'Val' + idx + 'R' + ri);
|
||||||
|
if(!input) continue;
|
||||||
|
const raw = input.value.trim().replace(',', '.');
|
||||||
|
if(raw === '') continue;
|
||||||
|
const v = parseFloat(raw);
|
||||||
|
if(isNaN(v) || v < 0 || v > 1){
|
||||||
|
alert('Bitte Werte zwischen 0 und 1 eintragen (z. B. 0,4) – oder das Feld leer lassen. (' + l + ', ' + r + ')');
|
||||||
|
invalid = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
entry[r] = v;
|
||||||
|
rowHasValue = true;
|
||||||
|
}
|
||||||
|
if(invalid) return null;
|
||||||
|
if(rowHasValue){ aufwand[l] = entry; hasValue = true; }
|
||||||
|
}
|
||||||
|
return { aufwand, hasValue };
|
||||||
|
}
|
||||||
|
|
||||||
|
// applyLpRows: übernimmt das Ergebnis von collectLpRows auf ein Projekt.
|
||||||
|
// Ohne gepflegte Rollen-Matrix (leer) zählt bei gesetzter aktiver LP später der
|
||||||
|
// Standard-Faktor 1,0; ohne aktive LP zählt das Projekt 0.
|
||||||
|
// Die amtierende Leistungsphase wird separat über den Tab "Projekte" gesetzt.
|
||||||
|
function applyLpRows(p, lp){
|
||||||
|
if(!lp) return false;
|
||||||
|
p.aufwandProLP = lp.hasValue ? lp.aufwand : undefined;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function openLpModal(pid){
|
||||||
|
if(guardWeekLocked()) return;
|
||||||
|
const p = currentWeek().projects.find(x=>x.id===pid);
|
||||||
|
if(!p) return;
|
||||||
|
lpModalProjectId = pid;
|
||||||
|
const titleEl = document.getElementById('lpModalProject');
|
||||||
|
if(titleEl) titleEl.textContent = (p.nr ? p.nr + ' – ' : '') + (p.name || '');
|
||||||
|
const rowsEl = document.getElementById('lpModalRows');
|
||||||
|
if(rowsEl) rowsEl.innerHTML = lpRowsHtml(p, 'lp');
|
||||||
|
document.getElementById('lpModal').style.display = 'flex';
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeLpModal(){
|
||||||
|
document.getElementById('lpModal').style.display = 'none';
|
||||||
|
lpModalProjectId = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveLpModal(){
|
||||||
|
if(guardWeekLocked()) return;
|
||||||
|
const p = currentWeek().projects.find(x=>x.id===lpModalProjectId);
|
||||||
|
if(!p) return;
|
||||||
|
const lp = collectLpRows('lp');
|
||||||
|
if(lp === null) return;
|
||||||
|
if(applyLpRows(p, lp)) save();
|
||||||
|
renderBoard(); renderProjects(); renderLoad();
|
||||||
|
closeLpModal();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------- Neues Projekt (mit LP-Aufwand beim Anlegen) ----------
|
||||||
|
|
||||||
|
function openNewProjModal(){
|
||||||
|
if(guardWeekLocked()) return;
|
||||||
|
document.getElementById('newProjNr').value = '';
|
||||||
|
document.getElementById('newProjName').value = '';
|
||||||
|
document.getElementById('newProjGroup').value = 'Aktive Projekte';
|
||||||
|
const lpSel = document.getElementById('newProjActiveLP');
|
||||||
|
if(lpSel){
|
||||||
|
lpSel.innerHTML = '<option value="">Keine</option>' + AUFWAND_LPS.map(l => `<option value="${l}">${l}</option>`).join('');
|
||||||
|
lpSel.value = '';
|
||||||
|
}
|
||||||
|
const rowsEl = document.getElementById('newProjLpRows');
|
||||||
|
if(rowsEl) rowsEl.innerHTML = lpRowsHtml({ aufwandProLP: {}, aktuelleLP: [] }, 'np');
|
||||||
|
document.getElementById('newProjModal').style.display = 'flex';
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeNewProjModal(){
|
||||||
|
document.getElementById('newProjModal').style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveNewProj(){
|
||||||
|
if(guardWeekLocked()) return;
|
||||||
|
const nr = document.getElementById('newProjNr').value.trim();
|
||||||
|
const name = document.getElementById('newProjName').value.trim();
|
||||||
|
if(!name){ alert("Bitte Projektbezeichnung eingeben."); return; }
|
||||||
|
const group = document.getElementById('newProjGroup').value;
|
||||||
|
const activeLP = document.getElementById('newProjActiveLP').value;
|
||||||
|
const lp = collectLpRows('np');
|
||||||
|
if(lp === null) return;
|
||||||
|
const w = currentWeek();
|
||||||
|
const nextOrder = w.projects
|
||||||
|
.filter(p=>p.group===group)
|
||||||
|
.reduce((max,p)=> Math.max(max, p.order!==undefined ? p.order : 0), -1) + 1;
|
||||||
|
const pr = {id:uid(),nr,name,group,status:'',lph:{},assign:{}, statusState: undefined, order: nextOrder, plan: null};
|
||||||
|
if(activeLP) pr.aktuelleLP = [activeLP];
|
||||||
|
applyLpRows(pr, lp);
|
||||||
|
w.projects.push(pr);
|
||||||
|
save(); renderProjects(); renderBoard();
|
||||||
|
closeNewProjModal();
|
||||||
|
}
|
||||||
|
|
||||||
|
// LOAD_BAR_MAX: Maximalwert der Balken-Skala im Auslastungs-Tab (und im
|
||||||
|
// PDF-Export). 1,0 = 100 % Kapazität; Werte > 1,0 = Überlastung (rot).
|
||||||
|
const LOAD_BAR_MAX = 8;
|
||||||
|
|
||||||
|
// renderLoad: berechnet die Belastung der Personen auf Basis des
|
||||||
|
// rollenspezifischen LP-Gewichtungsfaktors je amtierender Phase (0,0–1,0,
|
||||||
|
// Standard 1,0). Leere Matrix-Werte zählen bei gesetzter aktiver LP als 1,0;
|
||||||
|
// ohne gesetzte aktive LP zählt das Projekt 0 (nicht eingerechnet).
|
||||||
|
// Ampel: Schwellen relativ zum Maximalwert LOAD_BAR_MAX
|
||||||
|
// (gelb ab 50 %, rot ab 75 % – PLATZHALTER).
|
||||||
|
// Balken: Skala auf das feste Maximum LOAD_BAR_MAX (Standard 8).
|
||||||
function renderLoad(){
|
function renderLoad(){
|
||||||
const scope = document.getElementById('loadScope').value;
|
const scope = document.getElementById('loadScope').value;
|
||||||
|
const barMax = LOAD_BAR_MAX;
|
||||||
const selectedWeek = currentWeek();
|
const selectedWeek = currentWeek();
|
||||||
const weeks = scope==='all' ? db.weeks : (selectedWeek ? [selectedWeek] : []);
|
const weeks = scope==='all' ? db.weeks : (selectedWeek ? [selectedWeek] : []);
|
||||||
if(weeks.length === 0){
|
if(weeks.length === 0){
|
||||||
@@ -1760,41 +2022,35 @@ function renderLoad(){
|
|||||||
const stats = {};
|
const stats = {};
|
||||||
ROLES.forEach(r=>{
|
ROLES.forEach(r=>{
|
||||||
grouped[r].forEach(entry=>{
|
grouped[r].forEach(entry=>{
|
||||||
stats[assignKey(entry.person.id, r)] = {main:0,opt:0,kleine:0,projects:{},anbahnung:0};
|
stats[assignKey(entry.person.id, r)] = {load:0,projects:{},anbahnung:0};
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
weeks.forEach(w=>{
|
weeks.forEach(w=>{
|
||||||
w.projects.forEach(pr=>{
|
w.projects.forEach(pr=>{
|
||||||
const isAnbahnung = pr.group === 'In Anbahnung';
|
const aktivePhase = lpActiveList(pr)[0];
|
||||||
const isKleine = pr.group === 'Kleine Projekte';
|
|
||||||
Object.keys(pr.assign).forEach(aKey=>{
|
Object.keys(pr.assign).forEach(aKey=>{
|
||||||
if(!stats[aKey]) return;
|
const s = stats[aKey];
|
||||||
if(isAnbahnung){
|
if(!s) return;
|
||||||
if(pr.assign[aKey]===1 || pr.assign[aKey]===2) stats[aKey].anbahnung++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const st = pr.assign[aKey];
|
const st = pr.assign[aKey];
|
||||||
if(isKleine){
|
const rolle = aKey.slice(aKey.indexOf('|') + 1);
|
||||||
if(st===1 || st===2){
|
const al = berechneAuslastung(null, pr, aktivePhase, rolle, st);
|
||||||
stats[aKey].kleine = (stats[aKey].kleine||0) + 1;
|
if(al.anbahnung){
|
||||||
const key = pr.name;
|
if(st===1 || st===2) s.anbahnung++;
|
||||||
stats[aKey].projects[key]=(stats[aKey].projects[key]||0)+1;
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(st===1) stats[aKey].main++;
|
if(al.load > 0){
|
||||||
else if(st===2) stats[aKey].opt++;
|
s.load += al.load;
|
||||||
const key = pr.name;
|
s.projects[pr.name] = (s.projects[pr.name]||0)+1;
|
||||||
stats[aKey].projects[key]=(stats[aKey].projects[key]||0)+1;
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Bestimme Maximalwert für Skalierung
|
// Hochgerechnete Auslastung: durchschnittliche Wochenlast als Faktor
|
||||||
let maxLoad=1;
|
// der Kapazität (1,0 = 100 %). Werte > 1,0 = Überlastung.
|
||||||
Object.keys(stats).forEach(k=>{ const l=stats[k].main+stats[k].opt*0.5+(stats[k].kleine||0)*0.3; if(l>maxLoad)maxLoad=l; });
|
const nWeeks = Math.max(1, weeks.length);
|
||||||
|
const weekAvg = k => stats[k].load / nWeeks;
|
||||||
let html="";
|
let html="";
|
||||||
ROLES.forEach(r=>{
|
ROLES.forEach(r=>{
|
||||||
html += `<div class="load-row"><div class="load-row-title">${r}</div>`;
|
html += `<div class="load-row"><div class="load-row-title">${r}</div>`;
|
||||||
@@ -1803,15 +2059,17 @@ function renderLoad(){
|
|||||||
}
|
}
|
||||||
grouped[r].forEach(entry=>{
|
grouped[r].forEach(entry=>{
|
||||||
const s = stats[assignKey(entry.person.id, r)];
|
const s = stats[assignKey(entry.person.id, r)];
|
||||||
const load = s.main + s.opt*0.5 + (s.kleine||0)*0.3;
|
const avg = weekAvg(assignKey(entry.person.id, r));
|
||||||
const pct = Math.round(load/maxLoad*100);
|
// Balken relativ zur einstellbaren Skala (Standard 8); Überlastung > 1,0
|
||||||
|
// bleibt über die Ampel-Farbe sichtbar, der Zahlenwert bleibt ungedeckelt.
|
||||||
|
const pct = Math.min(100, Math.round(avg / barMax * 100));
|
||||||
const detail = Object.keys(s.projects).map(k=>`<div><span>${esc(k)}</span><b>${s.projects[k]}×</b></div>`).join('') || '<div class="hint">keine Zuordnung</div>';
|
const detail = Object.keys(s.projects).map(k=>`<div><span>${esc(k)}</span><b>${s.projects[k]}×</b></div>`).join('') || '<div class="hint">keine Zuordnung</div>';
|
||||||
const anbahnungBadge = (s.anbahnung && s.anbahnung>0) ? `<span style="font-size:11px;color:#3182ce;font-weight:normal;margin-left:0px">(${s.anbahnung} in Anbahnung)</span>` : '';
|
const anbahnungBadge = (s.anbahnung && s.anbahnung>0) ? `<span style="font-size:11px;color:#3182ce;font-weight:normal;margin-left:0px">(${s.anbahnung} in Anbahnung)</span>` : '';
|
||||||
html += `<div class="load-card">
|
html += `<div class="load-card">
|
||||||
<h3>${esc(entry.person.fullName)} <span style="font-size:11px;color:#888;font-weight:normal">(${r})</span></h3>
|
<h3>${esc(entry.person.fullName)} <span style="font-size:11px;color:#888;font-weight:normal">(${r})</span></h3>
|
||||||
<h3>${anbahnungBadge}</h3>
|
<h3>${anbahnungBadge}</h3>
|
||||||
<div class="load-num">${load.toString().replace('.',',')}</div>
|
<div class="load-num">${faktorFormat(avg)}</div>
|
||||||
<div class="bar" style="height:10px;margin-top:6px"><div style="width:${pct}%;background:${pct>75?'#c53030':pct>45?'#d69e2e':'#2f855a'}"></div></div>
|
<div class="bar" style="height:10px;margin-top:6px" title="Skala: 0 – ${faktorFormat(barMax)}"><div style="width:${pct}%;background:${loadAmpelColor(avg)}"></div></div>
|
||||||
<div class="load-detail">${detail}</div>
|
<div class="load-detail">${detail}</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
});
|
});
|
||||||
@@ -2584,71 +2842,58 @@ function pdfAttendanceBlock(w){
|
|||||||
function pdfLoadSection(w, grouped){
|
function pdfLoadSection(w, grouped){
|
||||||
const stats = {};
|
const stats = {};
|
||||||
ROLES.forEach(r => (grouped[r] || []).forEach(e => {
|
ROLES.forEach(r => (grouped[r] || []).forEach(e => {
|
||||||
stats[assignKey(e.person.id, r)] =
|
stats[assignKey(e.person.id, r)] = { load:0, anbahnung:0, projects:{} };
|
||||||
{ main:0, opt:0, kleine:0, anbahnung:0, projects:{} };
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
(w.projects || []).forEach(pr => {
|
(w.projects || []).forEach(pr => {
|
||||||
const isAnbahnung = pr.group === 'In Anbahnung';
|
const aktivePhase = lpActiveList(pr)[0];
|
||||||
const isKleine = pr.group === 'Kleine Projekte';
|
|
||||||
Object.keys(pr.assign || {}).forEach(aKey => {
|
Object.keys(pr.assign || {}).forEach(aKey => {
|
||||||
const s = stats[aKey];
|
const s = stats[aKey];
|
||||||
if(!s) return;
|
if(!s) return;
|
||||||
const st = pr.assign[aKey];
|
const st = pr.assign[aKey];
|
||||||
if(isAnbahnung){
|
const rolle = aKey.slice(aKey.indexOf('|') + 1);
|
||||||
if(st === 1 || st === 2) s.anbahnung++;
|
const al = berechneAuslastung(null, pr, aktivePhase, rolle, st);
|
||||||
|
if(al.anbahnung){
|
||||||
|
s.anbahnung++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(isKleine){
|
if(al.load > 0){
|
||||||
if(st === 1 || st === 2){
|
s.load += al.load;
|
||||||
s.kleine++;
|
|
||||||
s.projects[pr.name] = (s.projects[pr.name] || 0) + 1;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(st === 1) s.main++;
|
|
||||||
else if(st === 2) s.opt++;
|
|
||||||
if(st === 1 || st === 2){
|
|
||||||
s.projects[pr.name] = (s.projects[pr.name] || 0) + 1;
|
s.projects[pr.name] = (s.projects[pr.name] || 0) + 1;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const loadOf = s => s.main + s.opt * 0.5 + s.kleine * 0.3;
|
|
||||||
let maxLoad = 1;
|
|
||||||
Object.keys(stats).forEach(k => {
|
|
||||||
const l = loadOf(stats[k]);
|
|
||||||
if(l > maxLoad) maxLoad = l;
|
|
||||||
});
|
|
||||||
|
|
||||||
const BAR_W = 140;
|
const BAR_W = 140;
|
||||||
|
const barMax = LOAD_BAR_MAX;
|
||||||
const body = [[
|
const body = [[
|
||||||
{ text: 'Rolle', style: 'th' },
|
{ text: 'Rolle', style: 'th' },
|
||||||
{ text: 'Kürzel', style: 'th' },
|
{ text: 'Kürzel', style: 'th' },
|
||||||
{ text: 'Punkte', style: 'th' },
|
{ text: 'Auslastung', style: 'th' },
|
||||||
{ text: 'Auslastung', style: 'th' },
|
{ text: 'Auslastung (Faktor)',style: 'th' },
|
||||||
{ text: 'Projektdetails', style: 'th' }
|
{ text: 'Projektdetails', style: 'th' }
|
||||||
]];
|
]];
|
||||||
|
|
||||||
ROLES.forEach(r => (grouped[r] || []).forEach(entry => {
|
ROLES.forEach(r => (grouped[r] || []).forEach(entry => {
|
||||||
const s = stats[assignKey(entry.person.id, r)];
|
const s = stats[assignKey(entry.person.id, r)];
|
||||||
const load = loadOf(s);
|
const load = s.load; // aktuelle Sitzung = 1 Woche
|
||||||
const pct = Math.round(load / maxLoad * 100);
|
// Balken relativ zur einstellbaren Skala (Standard 8); die Ampel-Farbe
|
||||||
const col = pct > 75 ? '#D70015' : pct > 45 ? '#B25000' : '#248A3D';
|
// und der Zahlenwert bleiben ungedeckelt (Überlastung > 1,0).
|
||||||
|
const col = pdfLoadAmpelColor(load);
|
||||||
const det = Object.keys(s.projects)
|
const det = Object.keys(s.projects)
|
||||||
.map(k => k + ' (' + s.projects[k] + '\u00D7)').join(', ') || '—';
|
.map(k => k + ' (' + s.projects[k] + '\u00D7)').join(', ') || '—';
|
||||||
|
|
||||||
body.push([
|
body.push([
|
||||||
{ text: r, style: 'td' },
|
{ text: r, style: 'td' },
|
||||||
{ text: entry.person.name, style: 'td', bold: true },
|
{ text: entry.person.name, style: 'td', bold: true },
|
||||||
{ text: String(load).replace('.', ','), style: 'tdCenter' },
|
{ text: faktorFormat(load), style: 'tdCenter' },
|
||||||
{ stack: [
|
{ stack: [
|
||||||
{ canvas: [
|
{ canvas: [
|
||||||
{ type:'rect', x:0, y:0, w:BAR_W, h:7, color:'#F0F0F0' },
|
{ type:'rect', x:0, y:0, w:BAR_W, h:7, color:'#F0F0F0' },
|
||||||
{ type:'rect', x:0, y:0, w:Math.max(0, BAR_W * pct / 100),
|
{ type:'rect', x:0, y:0, w:Math.max(0, BAR_W * Math.min(1, load / barMax)),
|
||||||
h:7, color:col }
|
h:7, color:col }
|
||||||
]},
|
]},
|
||||||
{ text: pct + '%', fontSize: 6, color: '#6E6E73',
|
{ text: faktorFormat(load), fontSize: 6, color: '#6E6E73',
|
||||||
alignment: 'right', width: BAR_W, margin: [0, 1, 0, 0] }
|
alignment: 'right', width: BAR_W, margin: [0, 1, 0, 0] }
|
||||||
], margin: [3, 3, 3, 3] },
|
], margin: [3, 3, 3, 3] },
|
||||||
{ text: s.anbahnung
|
{ text: s.anbahnung
|
||||||
@@ -2661,10 +2906,10 @@ function pdfLoadSection(w, grouped){
|
|||||||
return [
|
return [
|
||||||
{ text: 'Auslastung der Projektbeteiligten (aktuelle Sitzung)',
|
{ text: 'Auslastung der Projektbeteiligten (aktuelle Sitzung)',
|
||||||
style: 'h2', margin: [0, 0, 0, 6] },
|
style: 'h2', margin: [0, 0, 0, 6] },
|
||||||
{ table: { headerRows: 1, widths: [80, 40, 35, BAR_W + 6, '*'], body },
|
{ table: { headerRows: 1, widths: [80, 40, 45, BAR_W + 6, '*'], body },
|
||||||
layout: pdfTableLayout() },
|
layout: pdfTableLayout() },
|
||||||
{ text: 'Haupt = 1 · Optional = 0,5 · Kleine Projekte = 0,3 · '
|
{ text: 'Rollenbezogener Gewichtungsfaktor je Leistungsphase. Aktueller Wert: '
|
||||||
+ '„In Anbahnung" wird nicht in die Punktzahl eingerechnet.',
|
+ faktorFormat(LOAD_BAR_MAX),
|
||||||
fontSize: 6.5, color: '#6E6E73', margin: [0, 4, 0, 0] }
|
fontSize: 6.5, color: '#6E6E73', margin: [0, 4, 0, 0] }
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -155,7 +155,7 @@
|
|||||||
.gantt-row.gantt-todo.dragging,
|
.gantt-row.gantt-todo.dragging,
|
||||||
.gantt-row.gantt-milestone-row.dragging { opacity: .5; }
|
.gantt-row.gantt-milestone-row.dragging { opacity: .5; }
|
||||||
.gantt-todo-drag:active { cursor: grabbing; }
|
.gantt-todo-drag:active { cursor: grabbing; }
|
||||||
.gantt-row.gantt-milestone-row .gantt-todo-drag { color: var(--red); }
|
.gantt-row.gantt-milestone-row .gantt-todo-drag { color: var(--text-subtle); }
|
||||||
|
|
||||||
@media (max-width: 900px) {
|
@media (max-width: 900px) {
|
||||||
.plan-body { flex-direction: column; overflow: auto; }
|
.plan-body { flex-direction: column; overflow: auto; }
|
||||||
|
|||||||
@@ -856,6 +856,17 @@ th.role-bauüberwachung { color: var(--text); }
|
|||||||
transition: width .3s var(--ease);
|
transition: width .3s var(--ease);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Markierung der amtierenden Leistungsphase (gesetzt im Tab "Projekte") */
|
||||||
|
.lph-cell.lp-aktiv {
|
||||||
|
background: var(--accent-soft);
|
||||||
|
box-shadow: inset 0 2px 0 var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.lph-cell.lp-aktiv input {
|
||||||
|
border-color: var(--accent);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
.section-title {
|
.section-title {
|
||||||
font-size: 17px;
|
font-size: 17px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
@@ -983,6 +994,55 @@ th.role-bauüberwachung { color: var(--text); }
|
|||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* === LP-Aufwand-Maske als Matrix-Tabelle ===
|
||||||
|
Zeilen = Leistungsphasen, Spalten = Rollen + "amtierend" (Radio). */
|
||||||
|
.lp-matrix {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin: 6px 0 12px;
|
||||||
|
}
|
||||||
|
.lp-matrix thead th {
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--text-muted);
|
||||||
|
text-align: left;
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-bottom: 1px solid var(--line-soft);
|
||||||
|
}
|
||||||
|
.lp-matrix th.lp-lph {
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
text-align: left;
|
||||||
|
padding: 6px 8px;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.lp-matrix td {
|
||||||
|
padding: 3px 8px;
|
||||||
|
}
|
||||||
|
.lp-matrix td input[type=text] {
|
||||||
|
width: 64px;
|
||||||
|
padding: 4px 7px;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
.lp-matrix tbody th.lp-lph,
|
||||||
|
.lp-matrix tbody td {
|
||||||
|
border-bottom: 1px solid var(--line-soft);
|
||||||
|
}
|
||||||
|
.lp-matrix tbody tr:last-child th.lp-lph,
|
||||||
|
.lp-matrix tbody tr:last-child td {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
.lp-matrix tbody tr:nth-child(even) th.lp-lph,
|
||||||
|
.lp-matrix tbody tr:nth-child(even) td {
|
||||||
|
background: var(--surface-alt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LP-Aufwand- und Neues-Projekt-Modal etwas breiter für die Matrix-Tabelle */
|
||||||
|
#lpModal .modal,
|
||||||
|
#newProjModal .modal {
|
||||||
|
max-width: 640px;
|
||||||
|
}
|
||||||
|
|
||||||
.person-list-item,
|
.person-list-item,
|
||||||
.person-card {
|
.person-card {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
Vendored
BIN
Binary file not shown.
@@ -1,9 +1,9 @@
|
|||||||
WOCHE;KW 30 / 2026;2026-07-24;1
|
WOCHE;KW 30 / 2026;2026-07-24;1
|
||||||
PERSONEN;;;AP|Planung|AP;SK|Planung|SK;AK|Planung|AK;ED|Planung|ED;SE|Planung|SE;THK|Planung|THK;SP|Planung|SP;SG|Planung|SG;TW|Planung|TW;RR|Planung|RR;MK|Planung|MK;HR|Planung|HR;;;;;;;;;;;
|
PERSONEN;;;AP|Planung|AP;SK|Planung|SK;AK|Planung|AK;ED|Planung|ED;SE|Planung|SE;THK|Planung|THK;SP|Planung|SP;SG|Planung|SG;TW|Planung|TW;RR|Planung|RR;MK|Planung|MK;HR|Planung|HR;;;;;;;;;;;;;;
|
||||||
Pr.-Nr.;Bezeichnung;Status;AP;SK;AK;ED;SE;THK;SP;SG;TW;RR;MK;HR;LPH 1;LPH 2;LPH 3;LPH 4;LPH 5;LPH 6;LPH 7;LPH 8;W+M;Gruppe;Index;Plan
|
Pr.-Nr.;Bezeichnung;Status;AP;SK;AK;ED;SE;THK;SP;SG;TW;RR;MK;HR;LPH 1;LPH 2;LPH 3;LPH 4;LPH 5;LPH 6;LPH 7;LPH 8;W+M;Gruppe;Index;Plan;Aufwand;Aktive Phasen
|
||||||
ANWESENHEIT;;;;;;;;;;;;;;;;;;;;;;;;;
|
ANWESENHEIT;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
18-4007;Janusz-Korczak-Gesamtsch. Bottrop;LPH5 als Vorabzug raus. NW-Räume vorauss. August.;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;95%;;Aktive Projekte;0;
|
18-4007;Janusz-Korczak-Gesamtsch. Bottrop;LPH5 als Vorabzug raus. NW-Räume vorauss. August.;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;95%;;Aktive Projekte;0;;;
|
||||||
21-4030;NSHV Köln Immobilienprüfung in Hof;Thorsten W. klärt und übernimmt Schriftverkehr. LV liegt zur Sichtung bei T.W.;;;;;;;;;;;;;100%;100%;100%;;100%;100%;;;;Aktive Projekte;1;
|
21-4030;NSHV Köln Immobilienprüfung in Hof;Thorsten W. klärt und übernimmt Schriftverkehr. LV liegt zur Sichtung bei T.W.;;;;;;;;;;;;;100%;100%;100%;;100%;100%;;;;Aktive Projekte;1;;;
|
||||||
22-4056;Gymnasium Hemer;;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;90%;;Aktive Projekte;2;
|
22-4056;Gymnasium Hemer;;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;90%;;Aktive Projekte;2;;;
|
||||||
22-4066;DSW 21 – Umbau E-Mobilität;Elt-Montagen ab KW 33.;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;20%;;Aktive Projekte;3;
|
22-4066;DSW 21 – Umbau E-Mobilität;Elt-Montagen ab KW 33.;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;20%;;Aktive Projekte;3;;;
|
||||||
24-4043;S-K ODL-Heim Sanierung Krefeld;Voraussichtlich LV-Abgabe.;;;;;;;;;;;;;100%;100%;100%;;100%;;;;;Aktive Projekte;4;
|
24-4043;S-K ODL-Heim Sanierung Krefeld;Voraussichtlich LV-Abgabe.;;;;;;;;;;;;;100%;100%;100%;;100%;;;;;Aktive Projekte;4;;;
|
||||||
|
@@ -1,33 +1,33 @@
|
|||||||
WOCHE;KW 31 / 2026;2026-07-29;1
|
WOCHE;KW 31 / 2026;2026-07-29;1
|
||||||
PERSONEN;;;AP|Planung|Alexander Plum;AK|Planung|Alexander Kenne;ED|Planung|Erik Dunin;SK|Planung|Simon Kunigk;SE|Planung|Steven Esche;WS|Planung|Winfried Sältzer;ED|Projektleitung|Erik Dunin;SP|Projektleitung|Sebastian Pöttinger;THK|Projektleitung|Thorsten Kramp;RR|Projektleitung|Robert Röllecke;MK|Projektleitung|Maximilian Kriener;TW|Projektleitung|Thorsten Werner;SG|Projektleitung|Steffen Gaida;ED|Bauüberwachung|Erik Dunin;SK|Bauüberwachung|Simon Kunigk;SP|Bauüberwachung|Sebastian Pöttinger;THK|Bauüberwachung|Thorsten Kramp;HR|Bauüberwachung|Hermann Rollecke;;;;;;;;;;;
|
PERSONEN;;;AP|Planung|Alexander Plum;AK|Planung|Alexander Kenne;ED|Planung|Erik Dunin;SK|Planung|Simon Kunigk;SE|Planung|Steven Esche;WS|Planung|Winfried Sältzer;ED|Projektleitung|Erik Dunin;SP|Projektleitung|Sebastian Pöttinger;THK|Projektleitung|Thorsten Kramp;RR|Projektleitung|Robert Röllecke;MK|Projektleitung|Maximilian Kriener;TW|Projektleitung|Thorsten Werner;SG|Projektleitung|Steffen Gaida;ED|Bauüberwachung|Erik Dunin;SK|Bauüberwachung|Simon Kunigk;SP|Bauüberwachung|Sebastian Pöttinger;THK|Bauüberwachung|Thorsten Kramp;HR|Bauüberwachung|Hermann Rollecke;;;;;;;;;;;;;;
|
||||||
Pr.-Nr.;Bezeichnung;Status;AP;AK;ED;SK;SE;WS;ED;SP;THK;RR;MK;TW;SG;ED;SK;SP;THK;HR;LPH 1;LPH 2;LPH 3;LPH 4;LPH 5;LPH 6;LPH 7;LPH 8;W+M;Gruppe;Index;Plan
|
Pr.-Nr.;Bezeichnung;Status;AP;AK;ED;SK;SE;WS;ED;SP;THK;RR;MK;TW;SG;ED;SK;SP;THK;HR;LPH 1;LPH 2;LPH 3;LPH 4;LPH 5;LPH 6;LPH 7;LPH 8;W+M;Gruppe;Index;Plan;Aufwand;Aktive Phasen
|
||||||
ANWESENHEIT;;X;X;;X;X;X;;X;X;;;;X;;X;X;X;;;;;;;;;;;;;
|
ANWESENHEIT;;X;X;;X;X;X;;X;X;;;;X;;X;X;X;;;;;;;;;;;;;;;
|
||||||
18-4007;Janusz-Korczak-Gesamtsch. Bottrop;- KW 35 NW Raum Planung <div>- KW 44 Möbel </div>;;;;;;;;;;;;;;;;;;;100%;100%;100%;;90%;;;;;Aktive Projekte;0;"{""start"":"""",""end"":"""",""milestones"":[],""people"":[],""progress"":0}"
|
18-4007;Janusz-Korczak-Gesamtsch. Bottrop;- KW 35 NW Raum Planung <div>- KW 44 Möbel </div>;;;;;;;;;;;;;;;;;;;100%;100%;100%;;90%;;;;;Aktive Projekte;0;"{""start"":"""",""end"":"""",""milestones"":[],""people"":[],""progress"":0}";;
|
||||||
21-4030;NSHV Köln Immobilienprüfung in Hof;- Thorsten W. klärt und übernimmt Schriftverkehr - LV liegt zur Sichtung bei T.W.;;;;;;;;;;;;;;;;;;;100%;100%;100%;;100%;100%;;;;Aktive Projekte;2;
|
21-4030;NSHV Köln Immobilienprüfung in Hof;- Thorsten W. klärt und übernimmt Schriftverkehr - LV liegt zur Sichtung bei T.W.;;;;;;;;;;;;;;;;;;;100%;100%;100%;;100%;100%;;;;Aktive Projekte;2;;;
|
||||||
22-4066;DSW 21, Umbau E-Mobilität;"- Elt-Montagen ab <font color=""#c53030""><b>KW 33</b></font>.";;;;;;;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;20%;;Aktive Projekte;6;
|
22-4066;DSW 21, Umbau E-Mobilität;"- Elt-Montagen ab <font color=""#c53030""><b>KW 33</b></font>.";;;;;;;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;20%;;Aktive Projekte;6;;;
|
||||||
24-4043;S-K ODL-Heim Sanierung Krefeld;- Vorraussichtlich LV-Abgabe XX.XX<div>- LPH5 mündlich freigegeben <div>- Neuer EG Grundriss mit diversen Änderungen kommt noch von Architekten</div></div>;;;;;;;;;;;;;;;;;;;100%;100%;100%;;100%;;;;;Aktive Projekte;10;
|
24-4043;S-K ODL-Heim Sanierung Krefeld;- Vorraussichtlich LV-Abgabe XX.XX<div>- LPH5 mündlich freigegeben <div>- Neuer EG Grundriss mit diversen Änderungen kommt noch von Architekten</div></div>;;;;;;;;;;;;;;;;;;;100%;100%;100%;;100%;;;;;Aktive Projekte;10;;;
|
||||||
21-4001;Feuerwehrgeräteh. Rodenkirchen;"- KNX muß noch programmiert werden. <font color=""#c53030"">Abnahme 27.07</font> <div><font color=""#c53030""><b>- Fertigstellung Ende Juli</b></font><div><font color=""#c53030""><b>- Abnahmen laufen bis Ende KW31</b></font></div><div><font color=""#c53030""><b>- Blackbuilding Test 26.07</b></font></div></div>";;X;;;;;;;;;;;X;;;;;;;;;;100%;100%;100%;;;Aktive Projekte;1;"{""start"":"""",""end"":"""",""milestones"":[{""id"":""mslrv3i1edl08"",""name"":""SV Abnahme"",""date"":""2026-08-18""},{""id"":""mslrvh7hjau1e"",""name"":""Test"",""date"":""2026-09-05""}],""people"":[""p_ap"",""p_ak"",""p_sk"",""p_sg""],""progress"":""0"",""todos"":[{""id"":""msluufbp114g1"",""title"":""Test"",""start"":""2026-08-09"",""end"":""2026-08-13"",""done"":false},{""id"":""mslv6h76cmx8k"",""title"":""iuguzgv"",""start"":""2026-08-23"",""end"":""2026-09-06"",""done"":false},{""id"":""mslw4l3qp1v18"",""title"":""Hallo"",""start"":""2026-11-29"",""end"":""2027-04-30"",""done"":false}]}"
|
21-4001;Feuerwehrgeräteh. Rodenkirchen;"- KNX muß noch programmiert werden. <font color=""#c53030"">Abnahme 27.07</font> <div><font color=""#c53030""><b>- Fertigstellung Ende Juli</b></font><div><font color=""#c53030""><b>- Abnahmen laufen bis Ende KW31</b></font></div><div><font color=""#c53030""><b>- Blackbuilding Test 26.07</b></font></div></div>";;X;;;;;;;;;;;X;;;;;;;;;;100%;100%;100%;;;Aktive Projekte;1;"{""start"":"""",""end"":"""",""milestones"":[{""id"":""mslrv3i1edl08"",""name"":""SV Abnahme"",""date"":""2026-08-18""},{""id"":""mslrvh7hjau1e"",""name"":""Test"",""date"":""2026-09-05""}],""people"":[""p_ap"",""p_ak"",""p_sk"",""p_sg""],""progress"":""0"",""todos"":[{""id"":""msluufbp114g1"",""title"":""Test"",""start"":""2026-08-09"",""end"":""2026-08-13"",""done"":false},{""id"":""mslv6h76cmx8k"",""title"":""iuguzgv"",""start"":""2026-08-23"",""end"":""2026-09-06"",""done"":false},{""id"":""mslw4l3qp1v18"",""title"":""Hallo"",""start"":""2026-11-29"",""end"":""2027-04-30"",""done"":false}]}";;
|
||||||
22-4027;Sporthalle Soest;- SV und VOB Abnahme erfolgt.<div>- Nachprüfung VOB 24.07</div><div>- Keine Infos über Nachprüfung</div>;;;;;;;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;90%;;Aktive Projekte;3;
|
22-4027;Sporthalle Soest;- SV und VOB Abnahme erfolgt.<div>- Nachprüfung VOB 24.07</div><div>- Keine Infos über Nachprüfung</div>;;;;;;;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;90%;;Aktive Projekte;3;;;
|
||||||
22-4056;Gymnasium Hemer;;;;;;;;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;90%;;Aktive Projekte;4;
|
22-4056;Gymnasium Hemer;;;;;;;;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;90%;;Aktive Projekte;4;;;
|
||||||
22-4056-1;Gymnasium Hemer (Deckensanierung);- Beginn der Arbeiten vorraussichtlich KW 30 (KW 32 Kickoff);;;;;;;;;;;;;;;;;;;;;100%;;100%;100%;;;;Aktive Projekte;5;
|
22-4056-1;Gymnasium Hemer (Deckensanierung);- Beginn der Arbeiten vorraussichtlich KW 30 (KW 32 Kickoff);;;;;;;;;;;;;;;;;;;;;100%;;100%;100%;;;;Aktive Projekte;5;;;
|
||||||
23-4042;GWK Neufelder Straße;"- Nachweis für E-30 Leitungen notwendig. Rechnungen wurden nicht anerkannt. <div><font color=""#c53030"">- 22.07 Aufschaltung BMA und Amok</font></div><div><font color=""#c53030"">- KW 31 VOB Abnahme</font></div>";;;;;;;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;95%;;Aktive Projekte;7;
|
23-4042;GWK Neufelder Straße;"- Nachweis für E-30 Leitungen notwendig. Rechnungen wurden nicht anerkannt. <div><font color=""#c53030"">- 22.07 Aufschaltung BMA und Amok</font></div><div><font color=""#c53030"">- KW 31 VOB Abnahme</font></div>";;;;;;;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;95%;;Aktive Projekte;7;;;
|
||||||
23-4070;Umbau Bürogebäude NEW, MV10;"- neue NSHV anbieten(Warten auf Infos), <div>- 28.07 Sachverständiger Abnahme ELT&SiBe </div><div>- 30.07 Sachverständigen Abnahme BMA</div>";;;;;;;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;90%;;Aktive Projekte;8;
|
23-4070;Umbau Bürogebäude NEW, MV10;"- neue NSHV anbieten(Warten auf Infos), <div>- 28.07 Sachverständiger Abnahme ELT&SiBe </div><div>- 30.07 Sachverständigen Abnahme BMA</div>";;;;;;;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;90%;;Aktive Projekte;8;;;
|
||||||
23-4072;S-K OGS-Kaldenkirchen Schulanbau;"- Feininstallation beginnt, Fertigstellung voraussichtlich <font color=""#c53030"">01.08</font>";;;;;;;;;;;;;;;;;;;;;;;;;;70%;;Aktive Projekte;9;
|
23-4072;S-K OGS-Kaldenkirchen Schulanbau;"- Feininstallation beginnt, Fertigstellung voraussichtlich <font color=""#c53030"">01.08</font>";;;;;;;;;;;;;;;;;;;;;;;;;;70%;;Aktive Projekte;9;;;
|
||||||
24-4049;BMA Remscheid;"- Feuerwehrabnahme organisiert die Errichterfirma. <div>- SV-Abnahmen 15 & 16.07: nicht abgenommen</div>";;;;;;;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;90%;;Aktive Projekte;11;
|
24-4049;BMA Remscheid;"- Feuerwehrabnahme organisiert die Errichterfirma. <div>- SV-Abnahmen 15 & 16.07: nicht abgenommen</div>";;;;;;;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;90%;;Aktive Projekte;11;;;
|
||||||
24-4069;S-K Erw. GS Blankenheim Neubau;- nur backup;;;;;;;;;;;;;;;;;;;;;;;100%;100%;;;;Kleine Projekte;0;
|
24-4069;S-K Erw. GS Blankenheim Neubau;- nur backup;;;;;;;;;;;;;;;;;;;;;;;100%;100%;;;;Kleine Projekte;0;;;
|
||||||
24-4096;Umbau Wohngebäude Kirchhoff;"- Position HA wird von uns bestimmt. - Notwendiges Leerrohr für Leuchten im Vordach ist zu klären.<div><font color=""#c53030"">- Abgabe Kostenberechnung bis Ende KW29</font></div><div><font color=""#c53030"">- LV Fertig bis Ende KW 32 </font> </div>";;;;(X);;;;;;;;;;;;;;;100%;100%;100%;;95%;85%;0%;;;Aktive Projekte;12;
|
24-4096;Umbau Wohngebäude Kirchhoff;"- Position HA wird von uns bestimmt. - Notwendiges Leerrohr für Leuchten im Vordach ist zu klären.<div><font color=""#c53030"">- Abgabe Kostenberechnung bis Ende KW29</font></div><div><font color=""#c53030"">- LV Fertig bis Ende KW 32 </font> </div>";;;;(X);;;;;;;;;;;;;;;100%;100%;100%;;95%;85%;0%;;;Aktive Projekte;12;;;
|
||||||
25-4003;Märkische Bank Boele;- Feininstallation<div>- Ab KW30 Einbringung Tresore</div>;;;;;;;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;80%;;Aktive Projekte;13;
|
25-4003;Märkische Bank Boele;- Feininstallation<div>- Ab KW30 Einbringung Tresore</div>;;;;;;;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;80%;;Aktive Projekte;13;;;
|
||||||
25-4028;TenBrinke, Amprion, Wietmarschen;;;;;;;;;;;;;;;;;;;;100%;100%;100%;;95%;;;;;Aktive Projekte;14;
|
25-4028;TenBrinke, Amprion, Wietmarschen;;;;;;;;;;;;;;;;;;;;100%;100%;100%;;95%;;;;;Aktive Projekte;14;;;
|
||||||
25-4028-1;TenBrinke, Amprion, Meerbusch;;;;;;;;;;;;;;;;;;;;100%;100%;100%;;95%;;;;;Aktive Projekte;15;
|
25-4028-1;TenBrinke, Amprion, Meerbusch;;;;;;;;;;;;;;;;;;;;100%;100%;100%;;95%;;;;;Aktive Projekte;15;;;
|
||||||
25-4028-2;TenBrinke, Amprion, Gelsenkirchen;;;;;;;;;;;;;;;;;;;;100%;100%;100%;;95%;;;;;Aktive Projekte;16;
|
25-4028-2;TenBrinke, Amprion, Gelsenkirchen;;;;;;;;;;;;;;;;;;;;100%;100%;100%;;95%;;;;;Aktive Projekte;16;;;
|
||||||
26-4018;TUI Immobilien GmbH Salzgitter;;;;;;;;;;;;;;;;;;;;50%;;;;;;;;;Aktive Projekte;17;
|
26-4018;TUI Immobilien GmbH Salzgitter;;;;;;;;;;;;;;;;;;;;50%;;;;;;;;;Aktive Projekte;17;;;
|
||||||
26-4023;HA Rettungsw. Nahmer Gasst. - Los 1;;;;X;;;;;;;;;;;;;;;;;;;;;;;;;In Anbahnung;0;
|
26-4023;HA Rettungsw. Nahmer Gasst. - Los 1;;;;X;;;;;;;;;;;;;;;;;;;;;;;;;In Anbahnung;0;;;
|
||||||
26-4024;HA Rettungsw. Dahl Am Obergr. - Los 2;;;;X;;;;;;;;;;;;;;;;;;;;;;;;;In Anbahnung;1;
|
26-4024;HA Rettungsw. Dahl Am Obergr. - Los 2;;;;X;;;;;;;;;;;;;;;;;;;;;;;;;In Anbahnung;1;;;
|
||||||
26-4025;HA, SeePark Hengstey;- LPH2 erfolgt, weitere Arbeiten folgen.;;;;;;;;;;;;;;;;;;;100%;100%;;;;;;;;Aktive Projekte;18;
|
26-4025;HA, SeePark Hengstey;- LPH2 erfolgt, weitere Arbeiten folgen.;;;;;;;;;;;;;;;;;;;100%;100%;;;;;;;;Aktive Projekte;18;;;
|
||||||
26-4026;Stadt Hemer, Anbau OGS Oesetalschule;"<font color=""#1a1a1a"">- Bearbeitung LPH3 in Absprache mit Achitektur S+D</font>";;;;;;;;;;;;;;;;;;;100%;100%;;;;;;;;Aktive Projekte;19;
|
26-4026;Stadt Hemer, Anbau OGS Oesetalschule;"<font color=""#1a1a1a"">- Bearbeitung LPH3 in Absprache mit Achitektur S+D</font>";;;;;;;;;;;;;;;;;;;100%;100%;;;;;;;;Aktive Projekte;19;;;
|
||||||
26-4046;AXA Außenbeleuchtung;- Warten auf Unterlagen (Grundlagen & Vorplanung);;;;;;;;;;;;;;;;;;;10%;;;;;;;;;Aktive Projekte;20;
|
26-4046;AXA Außenbeleuchtung;- Warten auf Unterlagen (Grundlagen & Vorplanung);;;;;;;;;;;;;;;;;;;10%;;;;;;;;;Aktive Projekte;20;;;
|
||||||
;KFW Köln/Bonn Sicherheitskonzept;- Auftrag erhalten;;;;;;;;;;;;;;;;;;;;;;;;;;;;In Anbahnung;2;
|
;KFW Köln/Bonn Sicherheitskonzept;- Auftrag erhalten;;;;;;;;;;;;;;;;;;;;;;;;;;;;In Anbahnung;2;;;
|
||||||
;Swisstal;;;;;;;;;;;;;;;;;;;;;;;;;;;;;In Anbahnung;3;"{""start"":"""",""end"":"""",""milestones"":[],""people"":[],""progress"":0}"
|
;Swisstal;;;;;;;;;;;;;;;;;;;;;;;;;;;;;In Anbahnung;3;"{""start"":"""",""end"":"""",""milestones"":[],""people"":[],""progress"":0}";;
|
||||||
;Plancodierung/Benennung;- Von Rieke erstellt. Info folgt ? KW31?;;;;;;;;;;;;;;;;;;;;;;;;;;;;Allgemein;0;
|
;Plancodierung/Benennung;- Von Rieke erstellt. Info folgt ? KW31?;;;;;;;;;;;;;;;;;;;;;;;;;;;;Allgemein;0;;;
|
||||||
;Ordnerstruktur;- in Projekthilfen _Ordnerstruktur abgelegt, ist in Anlehnung an Leitfaden aufgebaut;;;;;;;;;;;;;;;;;;;;;;;;;;;;Allgemein;1;
|
;Ordnerstruktur;- in Projekthilfen _Ordnerstruktur abgelegt, ist in Anlehnung an Leitfaden aufgebaut;;;;;;;;;;;;;;;;;;;;;;;;;;;;Allgemein;1;;;
|
||||||
26-4042;Zanderstraße 7, PV-Anlage;- 82 kWp Anlage angefragt. Preisschätzung wird angefertigt;;;;;;;;;;;;;;;;;;;100%;80%;;;;80%;;;;Kleine Projekte;1;
|
26-4042;Zanderstraße 7, PV-Anlage;- 82 kWp Anlage angefragt. Preisschätzung wird angefertigt;;;;;;;;;;;;;;;;;;;100%;80%;;;;80%;;;;Kleine Projekte;1;;;
|
||||||
|
@@ -1,33 +1,33 @@
|
|||||||
WOCHE;KW 33 / 2026;2026-08-09;
|
WOCHE;KW 33 / 2026;2026-08-09;
|
||||||
PERSONEN;;;AP|Planung|Alexander Plum;AK|Planung|Alex Kenne;ED|Planung|Erik Dunin;SK|Planung|Simon Kunigk;SE|Planung|Steven Esche;WS|Planung|Winfried Sältzer;ED|Projektleitung|Erik Dunin;SP|Projektleitung|Sebastian Pöttinger;THK|Projektleitung|Thorsten Kramp;RR|Projektleitung|Robert Röllecke;MK|Projektleitung|Maximilian Kriener;TW|Projektleitung|Thorsten Werner;SG|Projektleitung|Steffen Gaida;ED|Bauüberwachung|Erik Dunin;SK|Bauüberwachung|Simon Kunigk;SP|Bauüberwachung|Sebastian Pöttinger;THK|Bauüberwachung|Thorsten Kramp;HR|Bauüberwachung|Hermann Rollecke;;;;;;;;;;;
|
PERSONEN;;;AP|Planung|Alexander Plum;AK|Planung|Alex Kenne;ED|Planung|Erik Dunin;SK|Planung|Simon Kunigk;SE|Planung|Steven Esche;WS|Planung|Winfried Sältzer;ED|Projektleitung|Erik Dunin;SP|Projektleitung|Sebastian Pöttinger;THK|Projektleitung|Thorsten Kramp;RR|Projektleitung|Robert Röllecke;MK|Projektleitung|Maximilian Kriener;TW|Projektleitung|Thorsten Werner;SG|Projektleitung|Steffen Gaida;ED|Bauüberwachung|Erik Dunin;SK|Bauüberwachung|Simon Kunigk;SP|Bauüberwachung|Sebastian Pöttinger;THK|Bauüberwachung|Thorsten Kramp;HR|Bauüberwachung|Hermann Rollecke;;;;;;;;;;;;;;
|
||||||
Pr.-Nr.;Bezeichnung;Status;AP;AK;ED;SK;SE;WS;ED;SP;THK;RR;MK;TW;SG;ED;SK;SP;THK;HR;LPH 1;LPH 2;LPH 3;LPH 4;LPH 5;LPH 6;LPH 7;LPH 8;W+M;Gruppe;Index;Plan
|
Pr.-Nr.;Bezeichnung;Status;AP;AK;ED;SK;SE;WS;ED;SP;THK;RR;MK;TW;SG;ED;SK;SP;THK;HR;LPH 1;LPH 2;LPH 3;LPH 4;LPH 5;LPH 6;LPH 7;LPH 8;W+M;Gruppe;Index;Plan;Aufwand;Aktive Phasen
|
||||||
ANWESENHEIT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
ANWESENHEIT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
18-4007;Janusz-Korczak-Gesamtsch. Bottrop;- KW 35 NW Raum Planung <div>- KW 44 Möbel </div>;;;;;;;;;;;;;;;;;;;100%;100%;100%;;90%;;;;;Aktive Projekte;0;"{""start"":"""",""end"":"""",""milestones"":[],""people"":[],""progress"":0}"
|
18-4007;Janusz-Korczak-Gesamtsch. Bottrop;- KW 35 NW Raum Planung <div>- KW 44 Möbel </div>;;;;;;;;;;;;;;;;;;;100%;100%;100%;;90%;;;;;Aktive Projekte;0;"{""start"":"""",""end"":"""",""milestones"":[],""people"":[],""progress"":0}";"{""LPH 5"":{""Planung"":0.6},""LPH 8"":{""Planung"":0,""Projektleitung"":0.2}}";
|
||||||
21-4030;NSHV Köln Immobilienprüfung in Hof;- Thorsten W. klärt und übernimmt Schriftverkehr <div>- LV liegt zur Sichtung bei T.W.</div>;;;;;;;;;;;;;;;;;;;100%;100%;100%;;100%;100%;;;;Aktive Projekte;2;
|
21-4030;NSHV Köln Immobilienprüfung in Hof;- Thorsten W. klärt und übernimmt Schriftverkehr <div>- LV liegt zur Sichtung bei T.W.</div>;X;;;;;;;;;;;;;;;;;;100%;100%;100%;;100%;100%;;;;Aktive Projekte;2;;;
|
||||||
22-4066;DSW 21, Umbau E-Mobilität;- Elt-Montagen ab <font><b>KW 33</b></font>.;;;;;;;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;20%;;Aktive Projekte;6;
|
22-4066;DSW 21, Umbau E-Mobilität;- Elt-Montagen ab <font><b>KW 33</b></font>.;;;;;;;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;20%;;Aktive Projekte;6;;;
|
||||||
24-4043;S-K ODL-Heim Sanierung Krefeld;- Vorraussichtlich LV-Abgabe XX.XX<div>- LPH5 mündlich freigegeben <div>- Neuer EG Grundriss mit diversen Änderungen kommt noch von Architekten</div></div>;;;;;;;;;;;;;;;;;;;100%;100%;100%;;100%;;;;;Aktive Projekte;10;
|
24-4043;S-K ODL-Heim Sanierung Krefeld;- Vorraussichtlich LV-Abgabe XX.XX<div>- LPH5 mündlich freigegeben <div>- Neuer EG Grundriss mit diversen Änderungen kommt noch von Architekten</div></div>;;;;;;;;;;;;;;;;;;;100%;100%;100%;;100%;;;;;Aktive Projekte;10;;;
|
||||||
21-4001;Feuerwehrgeräteh. Rodenkirchen;- KNX muß noch programmiert werden. <font>Abnahme 27.07</font> <div><font><b>- Fertigstellung Ende Juli</b></font><div><font><b>- Abnahmen laufen bis Ende KW31</b></font></div><div><font><b>- Blackbuilding Test 26.07</b></font></div></div>;X;;X;;;;X;X;;;;;;X;;;;;;;;;100%;100%;100%;;;Aktive Projekte;1;"{""start"":"""",""end"":"""",""milestones"":[{""id"":""mslrvh7hjau1e"",""name"":""Übergabe"",""date"":""2026-09-12"",""dependsOn"":[""mslv6h76cmx8k""],""position"":""after:mslv6h76cmx8k""}],""people"":[""p_ap"",""p_ak"",""p_sk"",""p_sg""],""progress"":""0"",""todos"":[{""id"":""msluufbp114g1"",""title"":""Test"",""start"":""2026-08-10"",""end"":""2026-08-14"",""done"":false,""dependsOn"":[],""assignees"":[""p_ap"",""p_ed""],""progress"":0},{""id"":""mslv6h76cmx8k"",""title"":""Test 2"",""start"":""2026-08-24"",""end"":""2026-09-04"",""done"":false,""dependsOn"":[""msluufbp114g1""],""assignees"":[""p_ap""],""progress"":41},{""id"":""mslw4l3qp1v18"",""title"":""Test 3"",""start"":""2026-09-14"",""end"":""2026-09-22"",""done"":false,""dependsOn"":[""m_mslrvh7hjau1e""],""assignees"":[],""progress"":0},{""id"":""msoltaa1itx48"",""title"":""Gehen"",""start"":""2026-09-23"",""end"":""2026-09-25"",""done"":false,""progress"":0,""dependsOn"":[""mslw4l3qp1v18""],""assignees"":[""p_ws""]}]}"
|
21-4001;Feuerwehrgeräteh. Rodenkirchen;- KNX muß noch programmiert werden. <font>Abnahme 27.07</font> <div><font><b>- Fertigstellung Ende Juli</b></font><div><font><b>- Abnahmen laufen bis Ende KW31</b></font></div><div><font><b>- Blackbuilding Test 26.07</b></font></div></div>;X;;X;;;;X;X;;;;;;X;;;;;;;;;100%;100%;100%;;;Aktive Projekte;1;"{""start"":"""",""end"":"""",""milestones"":[{""id"":""mslrvh7hjau1e"",""name"":""Übergabe"",""date"":""2026-09-12"",""dependsOn"":[""mslv6h76cmx8k""],""position"":""after:mslv6h76cmx8k""}],""people"":[""p_ap"",""p_ak"",""p_sk"",""p_sg""],""progress"":""0"",""todos"":[{""id"":""msluufbp114g1"",""title"":""Test"",""start"":""2026-08-10"",""end"":""2026-08-14"",""done"":false,""dependsOn"":[],""assignees"":[""p_ap"",""p_ed""],""progress"":0},{""id"":""mslv6h76cmx8k"",""title"":""Test 2"",""start"":""2026-08-24"",""end"":""2026-09-04"",""done"":false,""dependsOn"":[""msluufbp114g1""],""assignees"":[""p_ap""],""progress"":41},{""id"":""mslw4l3qp1v18"",""title"":""Test 3"",""start"":""2026-09-14"",""end"":""2026-09-22"",""done"":false,""dependsOn"":[""m_mslrvh7hjau1e""],""assignees"":[],""progress"":0},{""id"":""msoltaa1itx48"",""title"":""Gehen"",""start"":""2026-09-23"",""end"":""2026-09-25"",""done"":false,""progress"":0,""dependsOn"":[""mslw4l3qp1v18""],""assignees"":[""p_ws""]}]}";"{""LPH 1"":{""Planung"":0.8},""LPH 2"":{""Planung"":0.8},""LPH 3"":{""Planung"":0.8},""LPH 4"":{""Planung"":0.8},""LPH 5"":{""Planung"":0.8}}";"[""LPH 3""]"
|
||||||
22-4027;Sporthalle Soest;- SV und VOB Abnahme erfolgt.<div>- Nachprüfung VOB 24.07</div><div>- Keine Infos über Nachprüfung</div>;;;;;;;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;90%;;Aktive Projekte;3;
|
22-4027;Sporthalle Soest;- SV und VOB Abnahme erfolgt.<div>- Nachprüfung VOB 24.07</div><div>- Keine Infos über Nachprüfung</div>;X;;;;;;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;90%;;Aktive Projekte;3;;;"[""LPH 5""]"
|
||||||
22-4056;Gymnasium Hemer;;;;;;;;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;90%;;Aktive Projekte;4;
|
22-4056;Gymnasium Hemer;;;;;;;;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;90%;;Aktive Projekte;4;;;
|
||||||
22-4056-1;Gymnasium Hemer (Deckensanierung);- Beginn der Arbeiten vorraussichtlich KW 30 (KW 32 Kickoff);;;;;;;;;;;;;;;;;;;;;100%;;100%;100%;;;;Aktive Projekte;5;
|
22-4056-1;Gymnasium Hemer (Deckensanierung);- Beginn der Arbeiten vorraussichtlich KW 30 (KW 32 Kickoff);;;;;;;;;;;;;;;;;;;;;100%;;100%;100%;;;;Aktive Projekte;5;;;
|
||||||
23-4042;GWK Neufelder Straße;- Nachweis für E-30 Leitungen notwendig. Rechnungen wurden nicht anerkannt. <div><font>- 22.07 Aufschaltung BMA und Amok</font></div><div><font>- KW 31 VOB Abnahme</font></div>;;;;;;;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;95%;;Aktive Projekte;7;
|
23-4042;GWK Neufelder Straße;- Nachweis für E-30 Leitungen notwendig. Rechnungen wurden nicht anerkannt. <div><font>- 22.07 Aufschaltung BMA und Amok</font></div><div><font>- KW 31 VOB Abnahme</font></div>;;;;;;;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;95%;;Aktive Projekte;7;;;
|
||||||
23-4070;Umbau Bürogebäude NEW, MV10;"- neue NSHV anbieten(Warten auf Infos), <div>- 28.07 Sachverständiger Abnahme ELT&SiBe </div><div>- 30.07 Sachverständigen Abnahme BMA</div>";;;;;;;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;90%;;Aktive Projekte;8;
|
23-4070;Umbau Bürogebäude NEW, MV10;"- neue NSHV anbieten(Warten auf Infos), <div>- 28.07 Sachverständiger Abnahme ELT&SiBe </div><div>- 30.07 Sachverständigen Abnahme BMA</div>";;;;;;;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;90%;;Aktive Projekte;8;;;
|
||||||
23-4072;S-K OGS-Kaldenkirchen Schulanbau;- Feininstallation beginnt, Fertigstellung voraussichtlich <font>01.08</font>;;;;;;;;;;;;;;;;;;;;;;;;;;70%;;Aktive Projekte;9;
|
23-4072;S-K OGS-Kaldenkirchen Schulanbau;- Feininstallation beginnt, Fertigstellung voraussichtlich <font>01.08</font>;;;;;;;;;;;;;;;;;;;;;;;;;;70%;;Aktive Projekte;9;;;
|
||||||
24-4049;BMA Remscheid;"- Feuerwehrabnahme organisiert die Errichterfirma. <div>- SV-Abnahmen 15 & 16.07: nicht abgenommen</div>";;;;;;;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;90%;;Aktive Projekte;11;
|
24-4049;BMA Remscheid;"- Feuerwehrabnahme organisiert die Errichterfirma. <div>- SV-Abnahmen 15 & 16.07: nicht abgenommen</div>";;;;;;;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;90%;;Aktive Projekte;11;;;
|
||||||
24-4069;S-K Erw. GS Blankenheim Neubau;- nur backup;;;;;;;;;;;;;;;;;;;;;;;100%;100%;;;;Kleine Projekte;0;
|
24-4069;S-K Erw. GS Blankenheim Neubau;- nur backup;;;;;;;;;;;;;;;;;;;;;;;100%;100%;;;;Kleine Projekte;0;;;
|
||||||
24-4096;Umbau Wohngebäude Kirchhoff;- Position HA wird von uns bestimmt. <div>- Notwendiges Leerrohr für Leuchten im Vordach ist zu klären.<div><font>- Abgabe Kostenberechnung bis Ende KW29</font></div><div><font>- LV Fertig bis Ende KW 32 </font> </div></div>;;;;;;;;;;;;;;;;;;;100%;100%;100%;;95%;85%;0%;;;Aktive Projekte;12;
|
24-4096;Umbau Wohngebäude Kirchhoff;- Position HA wird von uns bestimmt. <div>- Notwendiges Leerrohr für Leuchten im Vordach ist zu klären.<div><font>- Abgabe Kostenberechnung bis Ende KW29</font></div><div><font>- LV Fertig bis Ende KW 32 </font> </div></div>;;;;;;;;;;;;;;;;;;;100%;100%;100%;;95%;85%;0%;;;Aktive Projekte;12;;;
|
||||||
25-4003;Märkische Bank Boele;- Feininstallation<div>- Ab KW30 Einbringung Tresore</div>;;;;;;;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;80%;;Aktive Projekte;13;
|
25-4003;Märkische Bank Boele;- Feininstallation<div>- Ab KW30 Einbringung Tresore</div>;;;;;;;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;80%;;Aktive Projekte;13;;;
|
||||||
25-4028;TenBrinke, Amprion, Wietmarschen;;;;;;;;;;;;;;;;;;;;100%;100%;100%;;95%;;;;;Aktive Projekte;14;
|
25-4028;TenBrinke, Amprion, Wietmarschen;;;;;;;;;;;;;;;;;;;;100%;100%;100%;;95%;;;;;Aktive Projekte;14;;;
|
||||||
25-4028-1;TenBrinke, Amprion, Meerbusch;;;;;;;;;;;;;;;;;;;;100%;100%;100%;;95%;;;;;Aktive Projekte;15;
|
25-4028-1;TenBrinke, Amprion, Meerbusch;;;;;;;;;;;;;;;;;;;;100%;100%;100%;;95%;;;;;Aktive Projekte;15;;;
|
||||||
25-4028-2;TenBrinke, Amprion, Gelsenkirchen;;;;;;;;;;;;;;;;;;;;100%;100%;100%;;95%;;;;;Aktive Projekte;16;
|
25-4028-2;TenBrinke, Amprion, Gelsenkirchen;;;;;;;;;;;;;;;;;;;;100%;100%;100%;;95%;;;;;Aktive Projekte;16;;;
|
||||||
26-4018;TUI Immobilien GmbH Salzgitter;;;;;;;;;;;;;;;;;;;;50%;;;;;;;;;Aktive Projekte;17;
|
26-4018;TUI Immobilien GmbH Salzgitter;;;;;;;;;;;;;;;;;;;;50%;;;;;;;;;Aktive Projekte;17;;;
|
||||||
26-4023;HA Rettungsw. Nahmer Gasst. - Los 1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;In Anbahnung;0;
|
26-4023;HA Rettungsw. Nahmer Gasst. - Los 1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;In Anbahnung;0;;;
|
||||||
26-4024;HA Rettungsw. Dahl Am Obergr. - Los 2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;In Anbahnung;1;
|
26-4024;HA Rettungsw. Dahl Am Obergr. - Los 2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;In Anbahnung;1;;;
|
||||||
26-4025;HA, SeePark Hengstey;- LPH2 erfolgt, weitere Arbeiten folgen.;;;;;;;;;;;;;;;;;;;100%;100%;;;;;;;;Aktive Projekte;18;
|
26-4025;HA, SeePark Hengstey;- LPH2 erfolgt, weitere Arbeiten folgen.;;;;;;;;;;;;;;;;;;;100%;100%;;;;;;;;Aktive Projekte;18;;;
|
||||||
26-4026;Stadt Hemer, Anbau OGS Oesetalschule;"<font color=""#1a1a1a"">- Bearbeitung LPH3 in Absprache mit Achitektur S+D</font>";;;;;;;;;;;;;;;;;;;100%;100%;;;;;;;;Aktive Projekte;19;
|
26-4026;Stadt Hemer, Anbau OGS Oesetalschule;"<font color=""#1a1a1a"">- Bearbeitung LPH3 in Absprache mit Achitektur S+D</font>";;;;;;;;;;;;;;;;;;;100%;100%;;;;;;;;Aktive Projekte;19;;;
|
||||||
26-4046;AXA Außenbeleuchtung;- Warten auf Unterlagen (Grundlagen & Vorplanung);;;;;;;;;;;;;;;;;;;10%;;;;;;;;;Aktive Projekte;20;
|
26-4046;AXA Außenbeleuchtung;- Warten auf Unterlagen (Grundlagen & Vorplanung);;;;;;;;;;;;;;;;;;;10%;;;;;;;;;Aktive Projekte;20;;;
|
||||||
;KFW Köln/Bonn Sicherheitskonzept;- Auftrag erhalten;;;;;;;;;;;;;;;;;;;;;;;;;;;;In Anbahnung;2;
|
;KFW Köln/Bonn Sicherheitskonzept;- Auftrag erhalten;;;;;;;;;;;;;;;;;;;;;;;;;;;;In Anbahnung;2;;;
|
||||||
;Swisstal;;;;;;;;;;;;;;;;;;;;;;;;;;;;;In Anbahnung;3;"{""start"":"""",""end"":"""",""milestones"":[],""people"":[],""progress"":0}"
|
;Swisstal;;;;;;;;;;;;;;;;;;;;;;;;;;;;;In Anbahnung;3;"{""start"":"""",""end"":"""",""milestones"":[],""people"":[],""progress"":0}";;
|
||||||
;Plancodierung/Benennung;- Von Rieke erstellt. Info folgt ? KW31?;;;;;;;;;;;;;;;;;;;;;;;;;;;;Allgemein;0;
|
;Plancodierung/Benennung;- Von Rieke erstellt. Info folgt ? KW31?;;;;;;;;;;;;;;;;;;;;;;;;;;;;Allgemein;0;;;
|
||||||
;Ordnerstruktur;- in Projekthilfen _Ordnerstruktur abgelegt, ist in Anlehnung an Leitfaden aufgebaut;;;;;;;;;;;;;;;;;;;;;;;;;;;;Allgemein;1;
|
;Ordnerstruktur;- in Projekthilfen _Ordnerstruktur abgelegt, ist in Anlehnung an Leitfaden aufgebaut;;;;;;;;;;;;;;;;;;;;;;;;;;;;Allgemein;1;;;
|
||||||
26-4042;Zanderstraße 7, PV-Anlage;- 82 kWp Anlage angefragt. Preisschätzung wird angefertigt;;;;;;;;;;;;;;;;;;;100%;80%;;;;80%;;;;Kleine Projekte;1;
|
26-4042;Zanderstraße 7, PV-Anlage;- 82 kWp Anlage angefragt. Preisschätzung wird angefertigt;;;;;;;;;;;;;;;;;;;100%;80%;;;;80%;;;;Kleine Projekte;1;;;
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
WOCHE;KW 30 / 2026;2026-07-24;1
|
WOCHE;KW 30 / 2026;2026-07-24;1
|
||||||
PERSONEN;;;AP|Planung|AP;SK|Planung|SK;AK|Planung|AK;ED|Planung|ED;SE|Planung|SE;THK|Planung|THK;SP|Planung|SP;SG|Planung|SG;TW|Planung|TW;RR|Planung|RR;MK|Planung|MK;HR|Planung|HR;;;;;;;;;;;
|
PERSONEN;;;AP|Planung|AP;SK|Planung|SK;AK|Planung|AK;ED|Planung|ED;SE|Planung|SE;THK|Planung|THK;SP|Planung|SP;SG|Planung|SG;TW|Planung|TW;RR|Planung|RR;MK|Planung|MK;HR|Planung|HR;;;;;;;;;;;;;;
|
||||||
Pr.-Nr.;Bezeichnung;Status;AP;SK;AK;ED;SE;THK;SP;SG;TW;RR;MK;HR;LPH 1;LPH 2;LPH 3;LPH 4;LPH 5;LPH 6;LPH 7;LPH 8;W+M;Gruppe;Index;Plan
|
Pr.-Nr.;Bezeichnung;Status;AP;SK;AK;ED;SE;THK;SP;SG;TW;RR;MK;HR;LPH 1;LPH 2;LPH 3;LPH 4;LPH 5;LPH 6;LPH 7;LPH 8;W+M;Gruppe;Index;Plan;Aufwand;Aktive Phasen
|
||||||
ANWESENHEIT;;;;;;;;;;;;;;;;;;;;;;;;;
|
ANWESENHEIT;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
18-4007;Janusz-Korczak-Gesamtsch. Bottrop;LPH5 als Vorabzug raus. NW-Räume vorauss. August.;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;95%;;Aktive Projekte;0;
|
18-4007;Janusz-Korczak-Gesamtsch. Bottrop;LPH5 als Vorabzug raus. NW-Räume vorauss. August.;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;95%;;Aktive Projekte;0;;;
|
||||||
21-4030;NSHV Köln Immobilienprüfung in Hof;Thorsten W. klärt und übernimmt Schriftverkehr. LV liegt zur Sichtung bei T.W.;;;;;;;;;;;;;100%;100%;100%;;100%;100%;;;;Aktive Projekte;1;
|
21-4030;NSHV Köln Immobilienprüfung in Hof;Thorsten W. klärt und übernimmt Schriftverkehr. LV liegt zur Sichtung bei T.W.;;;;;;;;;;;;;100%;100%;100%;;100%;100%;;;;Aktive Projekte;1;;;
|
||||||
22-4056;Gymnasium Hemer;;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;90%;;Aktive Projekte;2;
|
22-4056;Gymnasium Hemer;;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;90%;;Aktive Projekte;2;;;
|
||||||
22-4066;DSW 21 – Umbau E-Mobilität;Elt-Montagen ab KW 33.;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;20%;;Aktive Projekte;3;
|
22-4066;DSW 21 – Umbau E-Mobilität;Elt-Montagen ab KW 33.;;;;;;;;;;;;;100%;100%;100%;;100%;100%;100%;20%;;Aktive Projekte;3;;;
|
||||||
24-4043;S-K ODL-Heim Sanierung Krefeld;Voraussichtlich LV-Abgabe.;;;;;;;;;;;;;100%;100%;100%;;100%;;;;;Aktive Projekte;4;
|
24-4043;S-K ODL-Heim Sanierung Krefeld;Voraussichtlich LV-Abgabe.;;;;;;;;;;;;;100%;100%;100%;;100%;;;;;Aktive Projekte;4;;;
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
WOCHE;KW 32 / 2026;2026-08-05;
|
WOCHE;KW 32 / 2026;2026-08-05;
|
||||||
PERSONEN;;;MZ|Planung|Markus Zimmermann;FP|Planung|Frank Pietruschka;TK|Planung|Tim Küppers;RR|Projektleitung|Robert Röllecke;AS|Bauüberwachung|Andreas Simon;SL|Bauüberwachung|Steffan Licata;;;;;;;;;;;
|
PERSONEN;;;MZ|Planung|Markus Zimmermann;FP|Planung|Frank Pietruschka;TK|Planung|Tim Küppers;RR|Projektleitung|Robert Röllecke;AS|Bauüberwachung|Andreas Simon;SL|Bauüberwachung|Steffan Licata;;;;;;;;;;;;;;
|
||||||
Pr.-Nr.;Bezeichnung;Status;MZ;FP;TK;RR;AS;SL;LPH 1;LPH 2;LPH 3;LPH 4;LPH 5;LPH 6;LPH 7;LPH 8;W+M;Gruppe;Index;Plan
|
Pr.-Nr.;Bezeichnung;Status;MZ;FP;TK;RR;AS;SL;LPH 1;LPH 2;LPH 3;LPH 4;LPH 5;LPH 6;LPH 7;LPH 8;W+M;Gruppe;Index;Plan;Aufwand;Aktive Phasen
|
||||||
ANWESENHEIT;;;;;;;;;;;;;;;;;;;
|
ANWESENHEIT;;;;;;;;;;;;;;;;;;;;;
|
||||||
24-4101;Krankenhaus Köln, Heizungsmodernisierung;- Austausch Kesselhaus geplant;;;;;;;100%;100%;100%;;100%;100%;;90%;;Aktive Projekte;0;"{""start"":"""",""end"":"""",""todos"":[{""id"":""msmzj493z5gie"",""title"":""Abgabe"",""start"":""2026-08-10"",""end"":""2026-08-28"",""done"":false,""progress"":23,""dependsOn"":[],""assignees"":[""p_fp""]}],""milestones"":[{""id"":""msmzi2pbbsv1s"",""name"":""sxcdv"",""date"":""2026-08-15"",""dependsOn"":[],""position"":""""}],""people"":[],""progress"":0}"
|
24-4101;Krankenhaus Köln, Heizungsmodernisierung;- Austausch Kesselhaus geplant;;;;;;;100%;100%;100%;;100%;100%;;90%;;Aktive Projekte;0;"{""start"":"""",""end"":"""",""todos"":[{""id"":""msmzj493z5gie"",""title"":""Abgabe"",""start"":""2026-08-10"",""end"":""2026-08-28"",""done"":false,""progress"":23,""dependsOn"":[],""assignees"":[""p_fp""]}],""milestones"":[{""id"":""msmzi2pbbsv1s"",""name"":""sxcdv"",""date"":""2026-08-15"",""dependsOn"":[],""position"":""""}],""people"":[],""progress"":0}";"{""LPH 1"":{""Planung"":1}}";"[""LPH 1""]"
|
||||||
24-4102;Bürokomplex Dortmund, Lüftung;- Filterkonzept in Abstimmung;;;;;;;100%;100%;100%;;95%;;;;;Aktive Projekte;1;"{""start"":"""",""end"":"""",""todos"":[],""milestones"":[{""id"":""msmzhc7wo8alc"",""name"":""Test 123"",""date"":""2026-08-10"",""dependsOn"":[],""position"":""""}],""people"":[],""progress"":0}"
|
24-4102;Bürokomplex Dortmund, Lüftung;- Filterkonzept in Abstimmung;;;;;;;100%;100%;100%;;95%;;;;;Aktive Projekte;1;"{""start"":"""",""end"":"""",""todos"":[],""milestones"":[{""id"":""msmzhc7wo8alc"",""name"":""Test 123"",""date"":""2026-08-10"",""dependsOn"":[],""position"":""""}],""people"":[],""progress"":0}";;
|
||||||
26-4105;Wohnanlage Essen, Regenwasser;- Planung Drainage;;;;;;;100%;100%;;;;;;;;Aktive Projekte;4;
|
26-4105;Wohnanlage Essen, Regenwasser;- Planung Drainage;;;;;;;100%;100%;;;;;;;;Aktive Projekte;4;;;
|
||||||
;Badmodernisierung Privatkunde;- Angebot erstellt;;;;;;;;;;;100%;;;;;In Anbahnung;0;
|
;Badmodernisierung Privatkunde;- Angebot erstellt;;;;;;;;;;;100%;;;;;In Anbahnung;0;;;
|
||||||
;Wärmepumpen-Studie;- Erstgespräch durchgeführt;;;;;;;100%;;;;;;;;;In Anbahnung;1;
|
;Wärmepumpen-Studie;- Erstgespräch durchgeführt;;;;;;;100%;;;;;;;;;In Anbahnung;1;;;
|
||||||
;HLS Planungscheckliste;- Vorlage aktualisiert;;;;;;;100%;;;;;;;;;Allgemein;0;
|
;HLS Planungscheckliste;- Vorlage aktualisiert;;;;;;;100%;;;;;;;;;Allgemein;0;;;
|
||||||
21-4001;Feuerwehrgeräteh. Rodenkirchen;;;;;;;;;;;;;;;;;Aktive Projekte;5;
|
21-4001;Feuerwehrgeräteh. Rodenkirchen;;;;;;;;;;;;;;;;;Aktive Projekte;5;;;
|
||||||
|
Reference in new issue
Block a user