From 7cb38663bcfdae6079e744651b1dc1e7a8f8af64 Mon Sep 17 00:00:00 2001 From: Christian Date: Fri, 2 Jan 2026 12:45:25 +0100 Subject: [PATCH] fix: Timetracking wizard approval endpoint (v1.3.76) - Fix parameter handling in approve_time_entry endpoint - Change from query params to body Dict[str, Any] - Send all required fields to wizard.approve_time_entry() - Calculate rounded_to if auto-rounding enabled - Add approval_note, billable, is_travel fields - Add Dict, Any imports --- RELEASE_NOTES_v1.3.76.md | 73 ++++++++++++++++++++++++++++++ VERSION | 2 +- app/timetracking/backend/router.py | 33 ++++++++++---- 3 files changed, 97 insertions(+), 11 deletions(-) create mode 100644 RELEASE_NOTES_v1.3.76.md diff --git a/RELEASE_NOTES_v1.3.76.md b/RELEASE_NOTES_v1.3.76.md new file mode 100644 index 0000000..5eec712 --- /dev/null +++ b/RELEASE_NOTES_v1.3.76.md @@ -0,0 +1,73 @@ +# Release Notes - v1.3.76 + +**Release Date:** 2. januar 2026 + +## 🐛 Bug Fixes + +### Timetracking Wizard Approval +- **Fixed approval endpoint** - Wizard approval nu virker korrekt +- **Fixed parameter handling** - Router modtager nu body params korrekt som Dict +- **Fixed missing fields** - Sender nu alle nødvendige felter til wizard.approve_time_entry(): + - `rounded_to` beregnes hvis auto-rounding er enabled + - `approval_note` sendes med fra frontend + - `billable` sættes til true som default + - `is_travel` sendes med fra checkbox + +### Technical Details +- Ændret `/api/v1/timetracking/wizard/approve/{time_id}` endpoint +- Modtager nu `request: Dict[str, Any]` i stedet for individuelle query params +- Tilføjet `Dict, Any` imports i router +- Beregner `rounded_to` baseret på TIMETRACKING_AUTO_ROUND setting + +## 📝 Files Changed + +- `app/timetracking/backend/router.py` - Fixed approve_time_entry endpoint + +## 🚀 Deployment Instructions + +### Production Server Update + +1. **SSH til serveren:** + ```bash + ssh bmcadmin@172.16.31.183 + ``` + +2. **Naviger til projekt directory:** + ```bash + cd /opt/bmc_hub + ``` + +3. **Pull ny version:** + ```bash + git fetch --tags + git checkout v1.3.76 + ``` + +4. **Genstart containers:** + ```bash + docker-compose restart api + ``` + +5. **Verificer:** + ```bash + curl http://localhost:8001/health + # Test approval: + # Gå til http://172.16.31.183:8000/timetracking/wizard + # Godkend en tidsregistrering + ``` + +## ⚠️ Breaking Changes + +None - this is a bug fix + +## 📊 Impact + +- Timetracking wizard approval virker nu igen +- Ingen database ændringer nødvendige +- Ingen configuration ændringer nødvendige + +--- + +**Git Tag:** v1.3.76 +**Previous Version:** v1.3.75 +**Commit:** TBD diff --git a/VERSION b/VERSION index a45b0c2..3039f47 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.3.75 \ No newline at end of file +1.3.76 \ No newline at end of file diff --git a/app/timetracking/backend/router.py b/app/timetracking/backend/router.py index a3e2c60..27f2d08 100644 --- a/app/timetracking/backend/router.py +++ b/app/timetracking/backend/router.py @@ -7,7 +7,7 @@ Isoleret routing uden påvirkning af existing Hub endpoints. """ import logging -from typing import Optional, List +from typing import Optional, List, Dict, Any from fastapi import APIRouter, HTTPException, Depends from fastapi.responses import JSONResponse @@ -218,9 +218,7 @@ async def get_next_pending_entry( @router.post("/wizard/approve/{time_id}", response_model=TModuleTimeWithContext, tags=["Wizard"]) async def approve_time_entry( time_id: int, - billable_hours: Optional[float] = None, - hourly_rate: Optional[float] = None, - rounding_method: Optional[str] = None, + request: Dict[str, Any], user_id: Optional[int] = None ): """ @@ -229,10 +227,12 @@ async def approve_time_entry( Path params: - time_id: ID på tidsregistreringen - Body (optional): - - billable_hours: Timer efter godkendelse (hvis ikke angivet, bruges original_hours med auto-rounding) - - hourly_rate: Timepris i DKK (override customer rate) - - rounding_method: "up", "down", "nearest" (override default) + Body: + - billable_hours: Timer efter godkendelse (optional) + - hourly_rate: Timepris i DKK (optional) + - is_travel: True hvis kørsel (optional) + - approval_note: Godkendelsesnote (optional) + - rounding_method: "up", "down", "nearest" (optional) """ try: from app.core.config import settings @@ -253,6 +253,9 @@ async def approve_time_entry( raise HTTPException(status_code=404, detail="Time entry not found") # Beregn approved_hours + billable_hours = request.get('billable_hours') + rounding_method = request.get('rounding_method') + if billable_hours is None: approved_hours = Decimal(str(entry['original_hours'])) @@ -267,20 +270,30 @@ async def approve_time_entry( approved_hours = (approved_hours / increment).quantize(Decimal('1'), rounding='ROUND_DOWN') * increment else: approved_hours = (approved_hours / increment).quantize(Decimal('1'), rounding='ROUND_HALF_UP') * increment + + rounded_to = increment + else: + rounded_to = None else: approved_hours = Decimal(str(billable_hours)) + rounded_to = None # Opdater med hourly_rate hvis angivet + hourly_rate = request.get('hourly_rate') if hourly_rate is not None: execute_update( "UPDATE tmodule_times SET hourly_rate = %s WHERE id = %s", (Decimal(str(hourly_rate)), time_id) ) - # Godkend + # Godkend med alle felter approval = TModuleTimeApproval( time_id=time_id, - approved_hours=float(approved_hours) + approved_hours=float(approved_hours), + rounded_to=float(rounded_to) if rounded_to else None, + approval_note=request.get('approval_note'), + billable=True, # Default til fakturerbar + is_travel=request.get('is_travel', False) ) return wizard.approve_time_entry(approval, user_id=user_id)