Skip to content
Back to skills

215 Name Skill B2a091d8

ASecurity

Build a complete project management system with Telegram bot, task distribution, and photo reports using n8n. Based on DDC Project Management repository.

  • 9 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added May 31, 2026
businesspythongobashnodeexpressgitapiperformancedocumentation

Works with

  • cli
  • api

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned May 31, 2026

npx -y skills add tools-only/X-Skills --skill 215-name-skill_b2a091d8 --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 215 Name Skill B2a091d8?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 215 Name Skill B2a091d8
[![Security: A β€” Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-215-name-skill-b2a091d8/badge)](https://www.skillsdirectory.com/skills/tools-only-215-name-skill-b2a091d8)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: "n8n-project-management"
description: "Build a complete project management system with Telegram bot, task distribution, and photo reports using n8n. Based on DDC Project Management repository."
homepage: "https://datadrivenconstruction.io"
metadata: {"openclaw": {"emoji": "πŸ”§", "os": ["darwin", "linux", "win32"], "homepage": "https://datadrivenconstruction.io", "requires": {"bins": ["python3"]}}}
---
# n8n Project Management System for Construction

Build a universal task management and reporting system for construction projects using n8n automation, Telegram bot, and Google Sheets.

## Business Case

**Problem**: Construction managers spend 2-3 hours daily on:
- Distributing tasks to foremen and workers
- Collecting progress updates via calls/messages
- Compiling photo documentation
- Tracking task completion status

**Solution**: Automated system that:
- Sends task reminders via Telegram at scheduled times
- Collects status reports (text + photos + GPS)
- Auto-saves all data to Google Sheets
- Provides real-time visibility to managers

**ROI**: 70% reduction in administrative time for task management

## Source Repository

```
https://github.com/datadrivenconstruction/Project-management-n8n-with-task-management-and-photo-reports
```

## System Architecture

```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    PROJECT MANAGEMENT SYSTEM                          β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                       β”‚
β”‚   MANAGER                          WORKER                            β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                   β”‚
β”‚   β”‚ Google      β”‚                  β”‚ Telegram    β”‚                   β”‚
β”‚   β”‚ Sheets      β”‚                  β”‚ Bot         β”‚                   β”‚
β”‚   β”‚             β”‚                  β”‚             β”‚                   β”‚
β”‚   β”‚ β€’ Tasks     β”‚    n8n           β”‚ β€’ /start    β”‚                   β”‚
β”‚   β”‚ β€’ Schedule  │◄──Workflow──────►│ β€’ Tasks     β”‚                   β”‚
β”‚   β”‚ β€’ Reports   β”‚                  β”‚ β€’ Photos    β”‚                   β”‚
β”‚   β”‚ β€’ Photos    β”‚                  β”‚ β€’ GPS       β”‚                   β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                   β”‚
β”‚         β”‚                                β”‚                           β”‚
β”‚         β–Ό                                β–Ό                           β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                   β”‚
β”‚   β”‚ Dashboard   β”‚                  β”‚ Google      β”‚                   β”‚
β”‚   β”‚ View        β”‚                  β”‚ Drive       β”‚                   β”‚
β”‚   β”‚             β”‚                  β”‚ (Photos)    β”‚                   β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                   β”‚
β”‚                                                                       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

## Implementation Guide

### Step 1: Create Telegram Bot

```python
# 1. Open @BotFather in Telegram
# 2. Send /newbot
# 3. Name: "YourProject Tasks Bot"
# 4. Username: "YourProjectTasks_bot"
# 5. Save the token: 123456789:ABCdefGHIjklMNOpqrsTUVwxyz

# Test bot connection
import requests

BOT_TOKEN = "YOUR_BOT_TOKEN"
response = requests.get(f"https://api.telegram.org/bot{BOT_TOKEN}/getMe")
print(response.json())
# Expected: {"ok": true, "result": {"id": ..., "first_name": "YourProject Tasks Bot"}}
```

### Step 2: Setup Google Sheets

Create spreadsheet with these sheets:

**Sheet 1: Tasks**
| Column | Type | Description |
|--------|------|-------------|
| Task_ID | Text | Unique identifier (TASK-001) |
| Project | Text | Project name |
| Object | Text | Building/area |
| Section | Text | Floor/zone |
| Task | Text | Task description |
| Executor | Text | Assigned worker name |
| Executor_ID | Number | Telegram user ID |
| Date | Date | Due date (DD.MM.YYYY) |
| Send_Time | Time | Reminder time |
| Priority | Text | πŸ”΄High / 🟑Medium / 🟒Low |
| Status | Text | Pending/Sent/Completed/Partial |
| Response | Text | Worker's response |
| Response_Time | DateTime | When responded |
| Photo_Link | URL | Google Drive link |
| GPS_Lat | Number | Latitude |
| GPS_Lon | Number | Longitude |

**Sheet 2: Workers**
| Column | Type | Description |
|--------|------|-------------|
| Name | Text | Worker full name |
| Role | Text | Foreman/Worker/Contractor |
| Telegram_ID | Number | User ID from /start |
| Phone | Text | Phone number |
| Registered | DateTime | Registration date |

**Sheet 3: Photo Reports**
| Column | Type | Description |
|--------|------|-------------|
| Report_ID | Text | Unique ID |
| Report_Type | Text | Daily/Safety/Quality |
| Executor | Text | Who should submit |
| Date | Date | Report date |
| Time | Time | Deadline |
| Status | Text | Pending/Submitted |
| Photo_Link | URL | Drive folder link |
| Comment | Text | Worker comment |

### Step 3: Import n8n Workflow

```json
// Core workflow structure (simplified)
{
  "nodes": [
    {
      "name": "Telegram Trigger",
      "type": "n8n-nodes-base.telegramTrigger",
      "parameters": {
        "updates": ["message", "callback_query"]
      }
    },
    {
      "name": "Route Messages",
      "type": "n8n-nodes-base.switch",
      "parameters": {
        "rules": [
          {"value": "/start"},
          {"value": "/status"},
          {"value": "/help"},
          {"value": "text_reply"},
          {"value": "photo"},
          {"value": "location"}
        ]
      }
    },
    {
      "name": "Check Tasks Schedule",
      "type": "n8n-nodes-base.cron",
      "parameters": {
        "cronExpression": "* * * * *"
      }
    },
    {
      "name": "Get Pending Tasks",
      "type": "n8n-nodes-base.googleSheets",
      "parameters": {
        "operation": "readRows",
        "sheetName": "Tasks",
        "filters": {
          "Status": "Pending",
          "Send_Time": "now"
        }
      }
    },
    {
      "name": "Send Task Reminder",
      "type": "n8n-nodes-base.telegram",
      "parameters": {
        "operation": "sendMessage",
        "chatId": "={{$json.Executor_ID}}",
        "text": "πŸ“‹ *Π—Π°Π΄Π°Ρ‡Π°: {{$json.Task}}*\nπŸ“ ΠžΠ±ΡŠΠ΅ΠΊΡ‚: {{$json.Object}}\n⏰ Π‘Ρ€ΠΎΠΊ: {{$json.Date}}\n{{$json.Priority}}"
      }
    }
  ]
}
```

### Step 4: Configure Webhook

```bash
# Set Telegram webhook to n8n
curl -X POST "https://api.telegram.org/bot${BOT_TOKEN}/setWebhook" \
  -d "url=https://your-n8n-instance.com/webhook/telegram-project-manager"

# Verify webhook is set
curl "https://api.telegram.org/bot${BOT_TOKEN}/getWebhookInfo"
```

## Worker Commands

### Registration: /start

```
User: /start

Bot: πŸ‘‹ Π”ΠΎΠ±Ρ€ΠΎ ΠΏΠΎΠΆΠ°Π»ΠΎΠ²Π°Ρ‚ΡŒ Π² систСму управлСния Π·Π°Π΄Π°Ρ‡Π°ΠΌΠΈ!

ΠŸΠΎΠΆΠ°Π»ΡƒΠΉΡΡ‚Π°, ΡƒΠΊΠ°ΠΆΠΈΡ‚Π΅ вашС имя:

User: Иван ΠŸΠ΅Ρ‚Ρ€ΠΎΠ²

Bot: Π’Ρ‹Π±Π΅Ρ€ΠΈΡ‚Π΅ Π²Π°ΡˆΡƒ Ρ€ΠΎΠ»ΡŒ:
[ΠŸΡ€ΠΎΡ€Π°Π±] [Π Π°Π±ΠΎΡ‡ΠΈΠΉ] [Бубподрядчик]

User: [ΠŸΡ€ΠΎΡ€Π°Π±]

Bot: βœ… РСгистрация Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½Π°!
Имя: Иван ΠŸΠ΅Ρ‚Ρ€ΠΎΠ²
Роль: ΠŸΡ€ΠΎΡ€Π°Π±
ID: 123456789

Π’Ρ‹ Π±ΡƒΠ΄Π΅Ρ‚Π΅ ΠΏΠΎΠ»ΡƒΡ‡Π°Ρ‚ΡŒ Π·Π°Π΄Π°Ρ‡ΠΈ автоматичСски.
Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ /help для справки.
```

### Receiving Task

```
Bot: πŸ“‹ *ЗАДАЧА #TASK-047*
━━━━━━━━━━━━━━━━━━━━━
πŸ“ ΠžΠ±ΡŠΠ΅ΠΊΡ‚: Π–Πš Π‘ΠΎΠ»Π½Π΅Ρ‡Π½Ρ‹ΠΉ, ΠšΠΎΡ€ΠΏΡƒΡ 2
πŸ— БСкция: 5 этаТ, ΠΊΠ². 51-55
πŸ“ Π—Π°Π΄Π°Ρ‡Π°: ΠœΠΎΠ½Ρ‚Π°ΠΆ элСктропроводки
⏰ Π‘Ρ€ΠΎΠΊ: 24.01.2026
πŸ”΄ ΠŸΡ€ΠΈΠΎΡ€ΠΈΡ‚Π΅Ρ‚: Высокий
━━━━━━━━━━━━━━━━━━━━━

ΠžΡ‚Π²Π΅Ρ‚ΡŒΡ‚Π΅ Π½Π° это сообщСниС для ΠΎΡ‚Ρ‡Π΅Ρ‚Π°:
β€’ ВСкст: статус + ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΉ
β€’ Π€ΠΎΡ‚ΠΎ: ΠΏΡ€ΠΈΠΊΡ€Π΅ΠΏΠΈΡ‚Π΅ Ρ„ΠΎΡ‚ΠΎ Ρ€Π°Π±ΠΎΡ‚
β€’ GPS: ΠΎΡ‚ΠΏΡ€Π°Π²ΡŒΡ‚Π΅ Π³Π΅ΠΎΠ»ΠΎΠΊΠ°Ρ†ΠΈΡŽ
```

### Task Response

```
User: (reply to task message)
Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ
ΠŸΡ€ΠΎΠ²ΠΎΠ΄ΠΊΠ° смонтирована ΠΏΠΎ всСм ΠΊΠ²Π°Ρ€Ρ‚ΠΈΡ€Π°ΠΌ, ΠΆΠ΄Π΅ΠΌ ΠΏΡ€ΠΈΠ΅ΠΌΠΊΡƒ

Bot: βœ… ΠžΡ‚Ρ‡Π΅Ρ‚ принят!
━━━━━━━━━━━━━━━━━━━━━
πŸ“‹ Π—Π°Π΄Π°Ρ‡Π°: #TASK-047
πŸ“Š Бтатус: Π’Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ
πŸ’¬ ΠšΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΉ: ΠŸΡ€ΠΎΠ²ΠΎΠ΄ΠΊΠ° смонтирована...
⏰ ВрСмя: 24.01.2026 14:35
━━━━━━━━━━━━━━━━━━━━━
```

### Photo Report

```
User: (sends photo as reply to task)
[Photo of completed electrical work]
Caption: ΠœΠΎΠ½Ρ‚Π°ΠΆ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½, Π³ΠΎΡ‚ΠΎΠ²ΠΎ ΠΊ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ΅

Bot: πŸ“· Π€ΠΎΡ‚ΠΎ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΎ ΠΈ сохранСно!
━━━━━━━━━━━━━━━━━━━━━
πŸ“‹ Π—Π°Π΄Π°Ρ‡Π°: #TASK-047
πŸ”— Π€ΠΎΡ‚ΠΎ: [Бсылка Π½Π° Google Drive]
πŸ’¬ ΠšΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΉ: ΠœΠΎΠ½Ρ‚Π°ΠΆ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½...
⏰ ВрСмя: 24.01.2026 14:38
━━━━━━━━━━━━━━━━━━━━━
```

### GPS Location

```
User: (sends location)
πŸ“ [Location: 55.7558, 37.6173]

Bot: πŸ“ ГСолокация ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π°!
━━━━━━━━━━━━━━━━━━━━━
πŸ“‹ Π—Π°Π΄Π°Ρ‡Π°: #TASK-047
πŸ—Ί ΠšΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚Ρ‹: 55.7558, 37.6173
πŸ”— ΠšΠ°Ρ€Ρ‚Π°: [Google Maps Link]
⏰ ВрСмя: 24.01.2026 14:40
━━━━━━━━━━━━━━━━━━━━━
```

## Manager Dashboard

### Google Sheets View

```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ TASK DASHBOARD                                          πŸ”„ Auto-refresh β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                         β”‚
β”‚  TODAY'S SUMMARY                                                       β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                    β”‚
β”‚  β”‚ Total: 24 β”‚ βœ… Done:15β”‚ ⏳ Pending:7β”‚ ⚠️ Late:2β”‚                    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                    β”‚
β”‚                                                                         β”‚
β”‚  TASK LIST                                             Filter: [Today β–Ό]β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚
β”‚  β”‚ Task ID  β”‚ Task       β”‚ Worker   β”‚ Status β”‚ Photo  β”‚ Response     β”‚β”‚
β”‚  β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”‚
β”‚  β”‚ TASK-047 β”‚ Π­Π»Π΅ΠΊΡ‚Ρ€ΠΈΠΊΠ°  β”‚ ΠŸΠ΅Ρ‚Ρ€ΠΎΠ²   β”‚ βœ…     β”‚ πŸ“· 3   β”‚ Π’Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ    β”‚β”‚
β”‚  β”‚ TASK-048 β”‚ Π‘Π°Π½Ρ‚Π΅Ρ…Π½ΠΈΠΊΠ° β”‚ Иванов   β”‚ ⏳     β”‚ -      β”‚ -            β”‚β”‚
β”‚  β”‚ TASK-049 β”‚ Π¨Ρ‚ΡƒΠΊΠ°Ρ‚ΡƒΡ€ΠΊΠ° β”‚ Π‘ΠΈΠ΄ΠΎΡ€ΠΎΠ²  β”‚ ⚠️     β”‚ πŸ“· 1   β”‚ Частично     β”‚β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜β”‚
β”‚                                                                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

## Python Integration

```python
import gspread
from oauth2client.service_account import ServiceAccountCredentials
import pandas as pd
from datetime import datetime, timedelta

class ProjectTaskManager:
    """Integration with n8n Project Management System"""

    def __init__(self, credentials_path: str, spreadsheet_id: str):
        scope = [
            'https://spreadsheets.google.com/feeds',
            'https://www.googleapis.com/auth/drive'
        ]
        creds = ServiceAccountCredentials.from_json_keyfile_name(
            credentials_path, scope
        )
        self.client = gspread.authorize(creds)
        self.spreadsheet = self.client.open_by_key(spreadsheet_id)

    def create_task(self, task: dict) -> str:
        """Create new task in system"""
        tasks_sheet = self.spreadsheet.worksheet('Tasks')

        # Generate task ID
        all_tasks = tasks_sheet.get_all_records()
        task_num = len(all_tasks) + 1
        task_id = f"TASK-{task_num:04d}"

        # Prepare row
        row = [
            task_id,
            task.get('project', ''),
            task.get('object', ''),
            task.get('section', ''),
            task.get('description', ''),
            task.get('executor_name', ''),
            task.get('executor_id', ''),
            task.get('date', datetime.now().strftime('%d.%m.%Y')),
            task.get('send_time', '09:00'),
            task.get('priority', '🟑Medium'),
            'Pending',  # Status
            '',  # Response
            '',  # Response_Time
            '',  # Photo_Link
            '',  # GPS_Lat
            ''   # GPS_Lon
        ]

        tasks_sheet.append_row(row)
        return task_id

    def create_bulk_tasks(self, tasks: list) -> list:
        """Create multiple tasks at once"""
        task_ids = []
        for task in tasks:
            task_id = self.create_task(task)
            task_ids.append(task_id)
        return task_ids

    def get_today_summary(self) -> dict:
        """Get summary of today's tasks"""
        tasks_sheet = self.spreadsheet.worksheet('Tasks')
        all_tasks = tasks_sheet.get_all_records()

        today = datetime.now().strftime('%d.%m.%Y')
        today_tasks = [t for t in all_tasks if t['Date'] == today]

        return {
            'total': len(today_tasks),
            'completed': len([t for t in today_tasks if t['Status'] == 'Completed']),
            'pending': len([t for t in today_tasks if t['Status'] == 'Pending']),
            'partial': len([t for t in today_tasks if t['Status'] == 'Partial']),
            'with_photos': len([t for t in today_tasks if t['Photo_Link']])
        }

    def get_worker_performance(self, worker_name: str, days: int = 30) -> dict:
        """Analyze worker performance over period"""
        tasks_sheet = self.spreadsheet.worksheet('Tasks')
        all_tasks = tasks_sheet.get_all_records()

        cutoff_date = datetime.now() - timedelta(days=days)

        worker_tasks = [
            t for t in all_tasks
            if t['Executor'] == worker_name
            and datetime.strptime(t['Date'], '%d.%m.%Y') >= cutoff_date
        ]

        if not worker_tasks:
            return {'error': 'No tasks found'}

        completed = len([t for t in worker_tasks if t['Status'] == 'Completed'])
        total = len(worker_tasks)

        return {
            'worker': worker_name,
            'period_days': days,
            'total_tasks': total,
            'completed': completed,
            'completion_rate': round(completed / total * 100, 1),
            'with_photos': len([t for t in worker_tasks if t['Photo_Link']]),
            'with_gps': len([t for t in worker_tasks if t['GPS_Lat']])
        }


# Usage Example
if __name__ == "__main__":
    manager = ProjectTaskManager(
        'credentials.json',
        'your-spreadsheet-id'
    )

    # Create tasks for the week
    weekly_tasks = [
        {
            'project': 'Π–Πš Π‘ΠΎΠ»Π½Π΅Ρ‡Π½Ρ‹ΠΉ',
            'object': 'ΠšΠΎΡ€ΠΏΡƒΡ 2',
            'section': '5 этаТ',
            'description': 'ΠœΠΎΠ½Ρ‚Π°ΠΆ элСктропроводки ΠΊΠ². 51-55',
            'executor_name': 'ΠŸΠ΅Ρ‚Ρ€ΠΎΠ² И.И.',
            'executor_id': '123456789',
            'date': '24.01.2026',
            'send_time': '08:00',
            'priority': 'πŸ”΄High'
        },
        {
            'project': 'Π–Πš Π‘ΠΎΠ»Π½Π΅Ρ‡Π½Ρ‹ΠΉ',
            'object': 'ΠšΠΎΡ€ΠΏΡƒΡ 2',
            'section': '5 этаТ',
            'description': 'ΠœΠΎΠ½Ρ‚Π°ΠΆ сантСхники ΠΊΠ². 51-55',
            'executor_name': 'Иванов А.П.',
            'executor_id': '987654321',
            'date': '25.01.2026',
            'send_time': '08:00',
            'priority': '🟑Medium'
        }
    ]

    task_ids = manager.create_bulk_tasks(weekly_tasks)
    print(f"Created tasks: {task_ids}")

    # Get summary
    summary = manager.get_today_summary()
    print(f"Today's summary: {summary}")
```

## n8n Workflow Templates

### Template 1: Morning Task Distribution

```yaml
name: Morning Task Distribution
trigger:
  type: cron
  expression: "0 8 * * 1-6"  # 8:00 AM, Mon-Sat

steps:
  - get_today_tasks:
      node: Google Sheets
      operation: readRows
      sheet: Tasks
      filter: Date = TODAY(), Status = Pending

  - group_by_worker:
      node: Code
      code: |
        const grouped = {};
        items.forEach(item => {
          const worker = item.json.Executor_ID;
          if (!grouped[worker]) grouped[worker] = [];
          grouped[worker].push(item.json);
        });
        return Object.entries(grouped).map(([id, tasks]) => ({
          worker_id: id,
          tasks: tasks
        }));

  - send_task_list:
      node: Telegram
      operation: sendMessage
      chatId: "={{$json.worker_id}}"
      text: |
        πŸŒ… *Π”ΠΎΠ±Ρ€ΠΎΠ΅ ΡƒΡ‚Ρ€ΠΎ! Π’Π°ΡˆΠΈ Π·Π°Π΄Π°Ρ‡ΠΈ Π½Π° сСгодня:*

        {{#each tasks}}
        ━━━━━━━━━━━━━━━━━━━━━
        {{priority}} *{{Task}}*
        πŸ“ {{Object}} / {{Section}}
        ⏰ Π‘Ρ€ΠΎΠΊ: {{Date}}
        {{/each}}

        ΠžΡ‚Π²Π΅Ρ‚ΡŒΡ‚Π΅ Π½Π° ΠΊΠ°ΠΆΠ΄ΡƒΡŽ Π·Π°Π΄Π°Ρ‡Ρƒ ΠΏΠΎ ΠΌΠ΅Ρ€Π΅ выполнСния.
```

### Template 2: Photo Report Collection

```yaml
name: Scheduled Photo Reports
trigger:
  type: cron
  expression: "0 12,17 * * 1-6"  # 12:00 and 17:00

steps:
  - get_photo_reports:
      node: Google Sheets
      operation: readRows
      sheet: Photo Reports
      filter: Date = TODAY(), Status = Pending

  - send_photo_request:
      node: Telegram
      operation: sendMessage
      chatId: "={{$json.Executor_ID}}"
      text: |
        πŸ“· *ВрСбуСтся Ρ„ΠΎΡ‚ΠΎ-ΠΎΡ‚Ρ‡Π΅Ρ‚*
        ━━━━━━━━━━━━━━━━━━━━━
        πŸ“‹ Π’ΠΈΠΏ: {{$json.Report_Type}}
        πŸ“ ΠžΠ±ΡŠΠ΅ΠΊΡ‚: {{$json.Object}}
        ⏰ Π‘Ρ€ΠΎΠΊ: {{$json.Time}}

        ΠŸΠΎΠΆΠ°Π»ΡƒΠΉΡΡ‚Π°, ΠΎΡ‚ΠΏΡ€Π°Π²ΡŒΡ‚Π΅ Ρ„ΠΎΡ‚ΠΎ с ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠ΅ΠΌ.
      replyMarkup:
        inline_keyboard:
          - [{text: "πŸ“· ΠžΡ‚ΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ Ρ„ΠΎΡ‚ΠΎ", callback_data: "photo_{{$json.Report_ID}}"}]
```

### Template 3: End of Day Summary

```yaml
name: End of Day Report
trigger:
  type: cron
  expression: "0 18 * * 1-6"  # 18:00

steps:
  - get_day_stats:
      node: Google Sheets
      operation: readRows
      sheet: Tasks
      filter: Date = TODAY()

  - calculate_stats:
      node: Code
      code: |
        const stats = {
          total: items.length,
          completed: items.filter(i => i.json.Status === 'Completed').length,
          partial: items.filter(i => i.json.Status === 'Partial').length,
          pending: items.filter(i => i.json.Status === 'Pending').length,
          photos: items.filter(i => i.json.Photo_Link).length
        };
        stats.completion_rate = Math.round(stats.completed / stats.total * 100);
        return [{ json: stats }];

  - send_to_manager:
      node: Telegram
      operation: sendMessage
      chatId: "MANAGER_CHAT_ID"
      text: |
        πŸ“Š *Π˜Ρ‚ΠΎΠ³ΠΈ дня: {{$now.format('DD.MM.YYYY')}}*
        ━━━━━━━━━━━━━━━━━━━━━

        πŸ“‹ ВсСго Π·Π°Π΄Π°Ρ‡: {{$json.total}}
        βœ… Π’Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ: {{$json.completed}}
        ⏳ Частично: {{$json.partial}}
        ❌ НС Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΎ: {{$json.pending}}

        πŸ“· Π€ΠΎΡ‚ΠΎ-ΠΎΡ‚Ρ‡Π΅Ρ‚ΠΎΠ²: {{$json.photos}}
        πŸ“ˆ Π’Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅: {{$json.completion_rate}}%

        [ΠžΡ‚ΠΊΡ€Ρ‹Ρ‚ΡŒ Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ]({{SPREADSHEET_URL}})
```

## Best Practices

### Task Design
1. Keep tasks atomic (1 task = 1 action)
2. Include clear location (Object + Section)
3. Set realistic deadlines
4. Use priority wisely (not everything is πŸ”΄High)

### Photo Reports
1. Request photos at milestones, not continuously
2. Use Google Drive folders per project/date
3. Include location verification (GPS)
4. Set clear expectations (what should be in photo)

### Worker Engagement
1. Acknowledge all responses quickly
2. Provide daily feedback
3. Recognize high performers
4. Keep bot messages concise

## Resources

- **Repository**: https://github.com/datadrivenconstruction/Project-management-n8n-with-task-management-and-photo-reports
- **Demo Bot**: @ProjectManagementTasks_Bot
- **Demo Sheet**: [Google Sheets Demo](https://docs.google.com/spreadsheets/d/1fWi_0W_jqKa61h2oB3zZLdTDBK8_cQ123RtF70X1rwc)
- **n8n Documentation**: https://docs.n8n.io

---

*"Automation is not about replacing people, it's about freeing them to do what only people can do."*

Files in this skill

  • README.md1.1 KB
  • skill.md22 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.