Commit Graph

325 Commits

Author SHA1 Message Date
Christian
1b84bee868 Add APScheduler dependency and fix scheduler endpoint 2026-01-02 02:28:33 +01:00
Christian
ebf3b1f31c Fix backup jobs query and add missing config 2026-01-02 02:26:33 +01:00
Christian
3ffee6d428 Add backup storage config settings 2026-01-02 02:23:10 +01:00
Christian
58b598058a Enable backup module functionality 2026-01-02 02:13:17 +01:00
Christian
9fb149c02a Fix Mattermost config field names 2026-01-02 02:06:05 +01:00
Christian
3a3d81cf4c Add Mattermost notification settings 2026-01-02 02:02:44 +01:00
Christian
f77e6dc70b Add backup system configuration settings 2026-01-02 01:54:52 +01:00
Christian
7744e71761 Add paramiko dependency for backup module 2026-01-02 01:48:55 +01:00
Christian
60614ae298 Add backup router registration and fix updateto.sh with sudo 2026-01-02 01:21:00 +01:00
Christian
e10bb20e77 Bump version to 1.3.65 for debug endpoint 2026-01-02 00:01:42 +01:00
Christian
bbb9ce8487 Add debug endpoint for timetracking invoice field diagnostics 2026-01-02 00:01:12 +01:00
Christian
8ac3a9db2f v1.3.64 - Redesigned sync architecture with clear field ownership
BREAKING CHANGES:
- vTiger sync: Never overwrites existing vtiger_id
- Contact sync: REPLACES links instead of appending (idempotent)
- E-conomic sync: Only updates fields it owns (address, city, postal, email_domain, website)
- E-conomic sync: Does NOT overwrite name or cvr_number anymore

ARCHITECTURE:
- Each data source owns specific fields
- Sync operations are now idempotent (can run multiple times)
- Clear documentation of field ownership in sync_router.py
- Contact links deleted and recreated on sync to match vTiger state

FIXED:
- Contact relationships now correct after re-sync
- No more mixed customer data from different sources
- Sorting contacts by company_count DESC (companies first)
2025-12-24 10:34:13 +01:00
Christian
a867a7f128 fix: sync address field from e-conomic (v1.3.63)
- Added address field to UPDATE query in economic sync
- Added address field to INSERT query for new customers
- Fixes issue where address from e-conomic was not synced
- Prevents mixed data (København address with Lundby city/postal)
- Address is now synced along with city, postal_code, country
2025-12-24 09:41:51 +01:00
Christian
0dd24c6420 fix: better error handling for order generation (v1.3.62)
- Added more specific error message when customer not found
- Added debug logging to check customer object type
- Changed error from 'Customer not found' to include customer_id
- Helps diagnose 'string indices must be integers' error
2025-12-24 09:39:31 +01:00
Christian
d228362617 fix: parse customer_rate as float in wizard (v1.3.61)
- Fixed customer_rate being returned as string from DB (NUMERIC type)
- Added parseFloat() when using customer_rate in calculations
- Fixes customer stats showing '-' instead of actual hourly rate
- Applied to loadCustomerContext(), displayCaseEntries(), and approveEntry()
2025-12-24 09:35:46 +01:00
Christian
097f0633f5 fix: settings sync stats loading (v1.3.60)
- Fixed loadSyncStats() to correctly parse API response
- Customers API returns {customers: [...]} not array directly
- Added const data = await response.json() and data.customers
- Fixes sync stats counters showing NaN or incorrect values
2025-12-23 15:50:20 +01:00
Christian
4c2593b99c feat: search e-conomic for customers by name (v1.3.59)
- Added EconomicService.search_customer_by_name() method
- Added GET /api/v1/customers/{id}/search-economic endpoint
- Returns matching e-conomic customers by name (partial match)
- Helps find economic customer number for customers without CVR
- Shows customerNumber, name, CVR, email, city in results
2025-12-23 15:39:35 +01:00
Christian
1b0217ef7b feat: manual link customer to e-conomic (v1.3.58)
- Added POST /api/v1/customers/{id}/link-economic endpoint
- Allows manually setting economic_customer_number for customers without CVR
- Useful for vTiger customers that can't auto-match via CVR or name
- Updates last_synced_at timestamp when linking
2025-12-23 15:36:17 +01:00
Christian
c254e7cb76 feat: dynamic version from VERSION file (v1.3.57)
- Created VERSION file with current version
- Health endpoints now read version from VERSION file instead of hardcoded
- Fixes issue where health check showed wrong version
- main.py /health and /api/v1/system/health now show correct version
2025-12-23 15:32:34 +01:00
Christian
0833f149e1 fix: always sync economic_customer_number from e-conomic (v1.3.56)
- Fixed UPDATE query to include economic_customer_number field
- Previously only set on INSERT, not UPDATE when matching by CVR
- Now e-conomic customer number is always synced as source of truth
- Fixes issue where customers synced from e-conomic were missing customer numbers
2025-12-23 15:22:55 +01:00
Christian
38a47f4d27 fix: wizard customer_rate field name mismatch (v1.3.55)
- Changed wizard.html to use customer_rate instead of customer_hourly_rate
- Fixes issue where wizard displayed default 1200 DKK instead of customer-specific hourly rate
- Backend API returns customer_rate field (from TModuleTimeWithContext model)
- Frontend now correctly reads customer_rate from API response
- Affected lines: 571, 807, 1084 in wizard.html
2025-12-23 15:12:45 +01:00
Christian
64e85da71c Fix: Use absolute URL for bulk rate update to avoid path resolution issues (v1.3.54) 2025-12-23 15:03:49 +01:00
Christian
641698be8b Fix: Bulk customer rate update using request body (v1.3.53)
Fixed API endpoint to accept JSON request body instead of query params:
- Added TModuleBulkRateUpdate Pydantic model
- Changed endpoint to accept request body
- Fixed parameter references to use request.customer_ids and request.hourly_rate
- Added migration for hourly_rate_updated and time_card_toggled event types

Resolves: 'Not Found' error and audit log constraint violations
2025-12-23 14:39:57 +01:00
Christian
246ad27fe3 Feature: Bulk customer hourly rate updates (v1.3.52)
Added bulk selection and update functionality for customer hourly rates:

Frontend (customers.html):
- Added checkbox column with select-all functionality
- Created bulk price update modal with customer list
- Implemented JavaScript for selection state management
- Shows selected count in UI badge
- Supports indeterminate state for partial selection

Backend (router.py):
- New POST /api/v1/timetracking/customers/bulk-update-rate endpoint
- Accepts {customer_ids: List[int], hourly_rate: float}
- Updates multiple customers in single SQL query
- Creates audit log entries for each updated customer
- Returns updated count

Use case: Select multiple customers and update hourly rate simultaneously
2025-12-23 14:31:10 +01:00
Christian
f8d9e0b252 Feature: Marker vTiger Timelog som faktureret (invoiced)
Når ordre eksporteres til e-conomic opdateres vTiger Timelog med:
- billed_via_thehub_id: Hub ordre ID (f.eks. 5)
- cf_timelog_invoiced: '1' (markér som faktureret)

Dette sikrer at timelogs i vTiger bliver markeret som fakturerede
og kan filtreres/rapporteres korrekt i vTiger.
2025-12-23 14:20:50 +01:00
Christian
0c0e589543 Fix: updateto.sh skal bruge docker-compose.prod.yml
KRITISK FIX: Serveren stoppede fordi updateto.sh brugte forkert compose fil

Problem:
- updateto.sh brugte 'docker-compose.yml' (dev version)
- Dev versionen har 'restart: unless-stopped'
- Production skal bruge 'docker-compose.prod.yml' med 'restart: always'
- Når server rebooter eller opdateres stopper containerne og starter ikke automatisk

Løsning:
- updateto.sh bruger nu '-f docker-compose.prod.yml' eksplicit
- Sikrer korrekt restart politik (always) anvendes
- Containerne vil nu starte automatisk efter reboot
2025-12-23 13:58:29 +01:00
Christian
acc78b03a3 UI: Vis Hub ordre ID i ordre detaljer efter eksport
- Tilføjet Hub ordre ID til success/info beskeder
- Viser at vTiger Timelog er opdateret med Hub ordre ID
- Gør det tydeligt at koblinger mellem Hub og vTiger er oprettet
2025-12-23 02:03:23 +01:00
Christian
807e7f6395 Feature: Opdater vTiger Timelog med Hub ordre ID efter eksport
- Tilføjet update_timelog_billed() metode til vtiger_sync.py
- Opdaterer billed_via_thehub_id felt i vTiger Timelog records
- Kaldes automatisk efter succesfuld e-conomic eksport
- Respekterer READ_ONLY og DRY_RUN safety flags
- Fejler ikke eksporten hvis vTiger update fejler (bare logger warning)
2025-12-23 01:44:14 +01:00
Christian
a2857f5e12 Fix: Tilføj case_number og Hub ordre nr til e-conomic
- Varetekst: Tilføj case_number tilbage (CC5784)
- Format: 'CC5784 / Arbejde konstant / 09.12.2025 - Marley'
- Tilføj Hub ordre nummer (TT-20251222-005) til otherReference felt
- otherReference vises som 'Øvrig ref' i e-conomic
2025-12-23 01:33:19 +01:00
Christian
0f97dda8cd Fix: Fjern timer/pris/total fra e-conomic varetekst
- Før: 'CC5784. 8.0 timer 1,200,- 9,600 / Arbejde konstant / 09.12.2025 - Marley'
- Nu: 'Arbejde konstant / 09.12.2025 - Marley'
- e-conomic viser timer og priser i egne kolonner, så det er overflødigt i teksten
2025-12-23 01:27:09 +01:00
Christian
3b8bae3186 Fix: Tilføj 'posted' status til tmodule_orders check constraint
- Database constraint tillod kun: draft, exported, sent, cancelled
- Code satte status til 'posted' efter e-conomic export
- Tilføjet 'posted' til check_status constraint
- Fixes: new row violates check constraint error
2025-12-23 01:22:47 +01:00
Christian
5c96639a79 Fix: Gør e-conomic product number konfigurerbar
BUG FIX:
- Hardcoded 'TIME001' eksisterer ikke i e-conomic
- Tilføjet TIMETRACKING_ECONOMIC_PRODUCT setting (default: '1000')
- Produkt nummer kan nu ændres via .env
- Fejl: Product 'TIME001' not found

LØSNING:
Tilføj til .env: TIMETRACKING_ECONOMIC_PRODUCT=XXXX
hvor XXXX er dit produkt nummer for konsulentimer i e-conomic
2025-12-23 01:11:58 +01:00
Christian
05d2ac9356 Fix: Gør e-conomic layout konfigurerbar (layout 21 er historisk)
BUG FIX:
- Hardcoded layout 21 fejler med 'Layout 21 is historic'
- Tilføjet TIMETRACKING_ECONOMIC_LAYOUT setting (default: 19)
- Layout 19 er standard dansk faktura layout
- Kan nu ændres via .env uden kode-ændringer

ERROR: e-conomic API error - layout: Layout '21' is historic
LØSNING: Brug layout 19 eller andet aktivt layout nummer
2025-12-23 01:04:44 +01:00
Christian
a98a5784b7 Fix: Return single order object ved cancel_order (ikke list)
BUG FIX:
- execute_query returnerer list, men TModuleOrder(**updated) forventede dict
- TypeError: argument after ** must be a mapping, not list
- Changed til updated[0] for at få første row
- Dette er den SIDSTE execute_query/execute_query_single bug i order_service.py

ERROR: TModuleOrder() argument after ** must be a mapping, not list
  → return TModuleOrder(**updated)
  → updated er list, skal være dict
2025-12-23 00:46:38 +01:00
Christian
776f7a52ad Fix: Tilføj manglende kolonner til tmodule_order_lines
CRITICAL BUG FIX:
- case_contact, time_date, is_travel manglede i tmodule_order_lines tabel
- Forårsagede SQL fejl ved order creation INSERT
- Opdateret migration 031 til at tilføje alle manglende kolonner
- Applied direkte på production DB

ERROR: column 'case_contact' does not exist
  → INSERT INTO tmodule_order_lines ... case_contact, time_date, is_travel
2025-12-23 00:33:28 +01:00
Christian
0fdf4549d6 Fix: Tilføj RETURNING id til order INSERT statements
CRITICAL BUG FIX:
- execute_insert() kalder cursor.fetchone() men INSERT havde ingen RETURNING clause
- Forårsagede '500: no results to fetch' ved order oprettelse
- Tilføjet RETURNING id til:
  * tmodule_orders INSERT (linje 222)
  * tmodule_order_lines INSERT (linje 240)
- Opdateret database.py docstring til at gøre RETURNING requirement klart

ERROR: ProgrammingError - no results to fetch
  → INSERT INTO tmodule_orders ... VALUES (...)
  → Manglede RETURNING id
2025-12-23 00:29:25 +01:00
Christian
718de1a6bd Fix: Remove hourly_rate query from customers table (kolonne eksisterer ikke)
BUG FIX:
- _get_hourly_rate() tried to query hourly_rate from customers table
- customers table har ikke hourly_rate kolonne
- Forårsagede '500: no results to fetch' fejl ved order oprettelse
- Changed execute_query_single → execute_query for tmodule_customers check
- Removed hub customer rate check (ikke relevant)
- Falls back til default rate fra settings

ERROR: SELECT hourly_rate FROM customers WHERE id = 512
       → column 'hourly_rate' does not exist
2025-12-23 00:23:01 +01:00
Christian
152670b4b2 Fix: Tilføj manglende is_travel og hourly_rate kolonner til tmodule_times
CRITICAL BUG FIX:
- Approval endpoint fejlede fordi is_travel kolonne ikke eksisterede i DB
- Koden referenced is_travel men migration var aldrig kørt
- Tilføjet is_travel (BOOLEAN DEFAULT false)
- Tilføjet hourly_rate (DECIMAL(10,2)) til times tabel
- Testet: Approval virker nu korrekt (entry 1225 godkendt)

RODSAG:
- User kunne ikke godkende timer fordi SQL fejlede med 'column does not exist'
- Dette forklarer hvorfor 0 entries nogensinde er blevet approved i systemet
2025-12-23 00:16:32 +01:00
Christian
0205516422 Cleanup: Fjernet duplikat order check i cancel_order 2025-12-22 22:20:20 +01:00
Christian
dd23312731 Fix: Flere steder i order_service brugte execute_query_single forkert 2025-12-22 17:13:10 +01:00
Christian
0d9af55dfc Fix: Timetracking ordre generering brugte execute_query_single i stedet for execute_query 2025-12-22 16:57:52 +01:00
Christian
3628cbd9fe Fix: Kontakt detail viser nu relaterede firmaer i Firmaer fanen 2025-12-22 16:40:49 +01:00
Christian
d2c7a8a624 Fix: SQL ambiguous column error i contacts søgning - prefikseret med c. 2025-12-22 16:04:49 +01:00
Christian
9fe17e7f85 Fix: Tilføjet company_count og company_names til contacts API med JOIN 2025-12-22 15:48:21 +01:00
Christian
ba0a2fd160 Fix: Ændret debug endpoint path for at undgå conflict 2025-12-22 15:43:47 +01:00
Christian
bd2de09076 Add: Debug endpoint for contact-company links 2025-12-22 15:35:26 +01:00
Christian
5bb6e73a26 Fix: Contacts query skulle returnere alle rækker ikke kun én 2025-12-22 15:29:28 +01:00
Christian
e4b940009f Feature: Auto-create customers from vTiger accounts when linking contacts 2025-12-22 15:20:29 +01:00
Christian
e541758c44 Add: Sync diagnostics endpoint for troubleshooting contact linking 2025-12-22 15:14:31 +01:00
Christian
6d949d7060 Refactor: Komplet omskrivning af kontakt sync med simpel logik 2025-12-22 15:05:40 +01:00