Refactoring Plan — Code Audit Sprints¶
Avots: 2026-05-12 pamatīga kodu audita rezultāts (sk. Lielais audits sadaļā zemāk)
Branch: refactor/code-audit-sprints (gan geo-backend, gan geo-mobile)
Total estimate: ~143h, 8 sprinti + Sprint 0 quick wins, ~3 mēneši
Šis dokuments ir vienīgais "kur mēs esam" patiesības avots refaktora ceļā. Atjaunina katrs sprints — ar atzīmētiem checkbox uzdevumiem, datumu un piezīmēm par to, kas atklājās.
Identiska kopija dzīvo geo-mobile/docs/REFACTORING_PLAN.md (sync kā ar CLAUDE.md).
Galvenais konteksts (saīsināts audit)¶
Failu izmēra TOP problēmas¶
Mobile:
- screens/map_screen.dart — 9 423 LOC (god-screen, kritisks)
- screens/monitored_properties_screen.dart — 3 440 LOC
- screens/settings_screen.dart — 1 621 LOC (aug strauji)
- services/cadastre_service.dart — 1 097 LOC (mixed responsibilities)
- 4 skice_*_service.dart faili dublē formatētāju paterns
Backend:
- services/vzd_local_service.py — 3 043 LOC (34 endpoint'i vienā Flask app)
Galvenie smell signāli¶
| Signāls | Skaits | Risks |
|---|---|---|
Color(0x...) ārpus theme |
249 vietās 32 failos | Nav design tokens |
fontSize: hardcoded |
806 izsaukumi | Nav typography tokens |
catch (_) { ... } (klusi norij) |
147 vietās 47 failos | Slēptas problēmas |
| Mobile widget tests | 1 fails (4%) | Nav UI safety net |
| Mobile screen tests | 0 (0%) | Brings deploys uz baidem |
Backend tests allow_failure: true |
True | Green CI bez signāla |
Top arhitektūras parādi¶
map_screen.dartgod-screen — jauns feature = +300-500 LOCvzd_local_service.pymonolīts — 34 @app.route vienā failā- 4
skice_*_servicefailu duplicēšanās - Gmail SMTP laika bumba (Google var noņemt App Password access)
AUTH_BYPASS=1defaults to ON — silent prod risks
Sprintu kopskats¶
| Sprint | Tēma | Effort | Risks | Atkarība |
|---|---|---|---|---|
| 0 | 3 Quick wins (1 day total) | 11h | Low | — |
| A | Theme tokenization | 12h | Low | — |
| B | map_screen.dart demolish #1 | 25h | Med | A |
| C | map_screen.dart demolish #2 + monitored | 25h | Med | B |
| D | Backend Blueprint refaktors | 18h | Med | — (paralēli B/C) |
| E | Test coverage uzplūdes | 20h | Low | D |
| F | Skice + Capture konsolidācija | 18h | Low | E |
| G | External hardening (Mailgun, VMD cache, Billing) | 15h | Med | — |
| H | CI cleanup + lint regulas | 10h | Low | — |
Atkarību diagramma¶
0 (quick wins) ──► A (theme) ──► B (map split) ──► C (map split 2)
│
▼
D (backend BP) ─── paralēli ─── E (testi) ──► F (skice)
│
G (external) ─── paralēli ─── H (CI cleanup) ◄┘
Sprint 0 — Quick Wins ✅ PABEIGTS (2026-05-12)¶
Statuss: Done. Commits: 0977c54 (backend), fc76222 (mobile).
- 0.1
vmd_api.pyretry + 5-min response cache - urllib3 Retry 3× ar exp. backoff (1s, 2s, 4s) uz 408/429/500/502/503/504
- In-memory cache ar TTL 5min, thread-safe lock, _MISS sentinel
- Negative 404 cache (lai neslogo VMD)
- clear_cache() helper testiem
- 3 jauni testi par cache uzvedību
- 0.2 Backend CI: noņemts
allow_failure: true - Integration testi izlaisti ar
-m "not integration" - 108 backend testi tagad reāli bloķē deploy (105 + 3 jauni)
- 0.3 Lint regulas +
dart fix --apply - prefer_const_constructors + prefer_const_literals_to_create_immutables + avoid_redundant_argument_values
- 327 fixes 63 failos automātiski
- 1 regressija labota manuāli (polygon_clip_100_cases_test typed closures)
- 435 mobile testi pass
Sprint A — Theme Tokenization (1-2 nedēļas, ~12h)¶
Mērķis: likvidēt 249× Color(0x...), 806× fontSize:, 200+ hardcoded EdgeInsets.
ATKLĀJUMS sākot: lib/theme/app_spacing.dart un lib/theme/app_typography.dart JAU EKSISTĒ ar pilnu skalu — tikai netiek lietoti. Plāns: migrācija, ne izveide.
- A.1
lib/theme/app_spacing.dart— JAU EKSISTĒ (xs/sm/md/lg/xl/xxl + helper EdgeInsets/SizedBox) - A.2
lib/theme/app_typography.dart— JAU EKSISTĒ (display/headline/title/body/label skala) - A.3
widgets/forest_charts.dart— migrēts 2026-05-12 →theme/forest_palette.dart. 11 sugu krāsas + 4 vecuma klases ekstrahētas uz domēna paletes (neAppColors, jo tās ir mežzinātnes-specifiskas, ne UI tokens). Vienota maiņa karteslejām + PDF eksportam tagad iespējama 1 vietā. - A.x1
widgets/warning_banner.dart— migrēts 2026-05-12. 5 hardcoded →AppColors.statusGood,geofenceOutside,geofenceWarningFlash,statusWarn. - A.x2
widgets/search_panel.dart— migrēts 2026-05-12. 9 hardcoded →AppColors.statusGood,searchResultCadastre,searchResultPlace,searchHighlight. - A.x3
widgets/drawing_toolbar.dart+widgets/map_overlays.dart— migrēti 2026-05-12. 5 hardcoded → jaunstoolbarBgDark+ jaunssnapTargetBlue+ esošieaudioAccent,trackRecordingAccent. - A.4
widgets/status_bar.dart— migrēts 2026-05-12 (4 krāsas → AppColors tokens: statusGood, statusWarn, cautionAmber, criticalRed) - A.5
widgets/weather_banner.dart— migrēts 2026-05-12 (6 krāsas → AppColors weatherSafe/Caution/Danger + Bg varianti; 9 fontSize → AppTypography bodySm/labelMd/labelSm; EdgeInsets → AppSpacing) - [~] A.6
screens/map_screen.dart— daļēja EdgeInsets migrācija 2026-05-12: 14/97 (14%) ievietoti AppSpacing tokens (allSm/allMd/allLg/horizontalLg). Atlikušie 85 ir non-grid vērtības (20, 50, 60, 6, 10, fromLTRB mix) un risk-prone tikt pārveidotas bez vizuālas regresijas — gaida Sprint B ekstraktus, kur mazākajos widget'os tos var izvērtēt individuāli. 132 fontSize neaiztikti — tie ir nestedTextStyle(...)ar krāsām/svariem, prasa strukturālu maiņu, ko labāk veikt pēc Sprint B widget ekstraktiem. - [~] A.7
screens/monitored_properties_screen.dart— daļēji migrēts 2026-05-12: - 5 hardcoded
Color(0x...)→ AppColors tokens (4×deadlineUrgentjauns + 1×snapTargetBlueesošs); 0 atlikušas. - 6 EdgeInsets literāli (5×
all(12)+ 1×all(16)) →AppSpacing.allMd/allLg. - Atlikušie 60+ EdgeInsets ir non-grid (only/fromLTRB ar mixed 4/6/8/10) un 76 inline fontSize neaiztikti — gaida Sprint C ekstraktus (properties_tab.dart, notifications_tab.dart), kur šaurākajos widget'os tos var izvērtēt individuāli.
- A.8 Lint regulas jau spēkā (Sprint 0.3) — pievienot
avoid_const_constructorsun (vēlāk) custom lint, kas aizliedzColor(0x...)ārpustheme/
Atkarība: Sprint 0 ✅
Sprint B — map_screen.dart demolish #1 (2 nedēļas, ~25h)¶
Mērķis: -2500 LOC no map_screen.dart. Galvenokārt ekstraktējams ar zemu state coupling.
- B.0 Dead code sweep 2026-05-12 — 7 unused private metodes + 6 unused lauki + 2 orphan local var + 1 kaskāde-orphan kartēšana noņemts. 262 LOC dzēstas (
map_screen.dart9404 → 9142). flutter analyze: 18 → 3 issues (3 atlikušie ir info-level pre-existingBuildContext across async gaps). 521 unit tests pass; 2 integration tests fail external API atkarību dēļ (LAD), nesaistīts. - Methods:
_buildActiveMapSummary(84 LOC),_showMarkerColorPicker(44 LOC),_drawingHintText(21),_drawingHintIcon(13),_currentMeasurement(11),_overlayCategoryIcon(14),_translateForestField(4) — visiunused_element. - Fields:
_lastAutosaveAt,_lastTappedFeature,_lastTappedCaNumurs,_baseMapExpanded,_overlaysExpanded,_isDragging— visi write-only, nav reader. - Cascade:
_forestFieldNamesstatic const map (~50 LOC) palikas dead pēc_translateForestFielddzēšanas; arī dzēsts. - B.1
widgets/basemaps_overlays_sheet.dart— KORIĢĒT: nav atsevišķa_BasemapsAndOverlaysSheetklases. Faktiskā struktūra: izklīdis funkcijās_buildOverlaySections+ nestēts ExpansionTile UI. Atklāj plāns nepareizs — jārestrukturizē. - [~] B.2 PIVOT 2026-05-12:
_buildTopChipRowizrādījās tikai 15 LOC (plāns kļūdījās ar ~300 LOC estimate — tas ir vienkāršsRow(ScaleBar, search-chip)). Tā vietā ekstrahēts_showMoreMenuSheet+_moreMenuTile+_MoreMenuItemuzwidgets/more_menu_sheet.dart: - Eksportē
MoreMenuItemdata class +showMoreMenuSheet(context, items: ...)funkciju _showMoreMenuSheetmap_screen-ā tikai sastāda items sarakstu un izsauc ekstrakto funkciju- -94 LOC map_screen.dart (9142 → 9048)
- flutter analyze: 3 → 3 (nemainās, joprojām tikai pre-existing async-gap infos)
- B.2-orig
_buildTopChipRowekstraktēšana atcelta — par mazu, lai izmaksātos atsevišķs widget fails. - B.2b 2026-05-12:
_showSharePicker(109 LOC) →widgets/share_picker_sheet.dart(showSharePickerSheet(context, ...)top-level funkcija). Eksports izmanto PackageService + KmlService._showSharePickermap_screen-ā tagad 7-rindu wrapper. map_screen: 9048 → 8948 LOC (-100). - B.2c 2026-05-12:
_showVisibilityPanel+_visibilityTile(kopā ~250 LOC) →widgets/visibility_panel_sheet.dart. Vissarežģītākais ekstrakts šajā sesijā: 4 state lauki + 2 setState mutācijas + 2 dažādas zoom darbības. Atrisinājums: - Sheet uztur lokālas hidden Set kopijas (StatefulBuilder lokālā state)
onChangedcallback paziņo parent setState ar jaunajām Set instancēmonZoomToMainCaunonZoomToBounds(LatLngBounds)abstrahē_mapController.fitCamerano widget'a- map_screen: 8948 → 8716 LOC (-232). Wrapper tagad 18 rindas.
- B.2e 2026-05-12: Apgrūtinājumu UI saraksts (4 metodes, ~117 LOC) →
widgets/encumbrance_list.dart(staticEncumbranceList.header/tile/severityOf/colorOf). Tīrs UI ekstrakts —EncumbranceInfoir nocadastre_service.dart, krāsu klasifikācija pēc Latvian/English atslēgvārdiem (mikroliegumi/biotopi/aizsargjoslas/utml). map_screen: 8598 → 8483 LOC (-115). - B.2d 2026-05-12: Divi mazi sheet ekstrakti vienā commit:
_showHeritageDetails(60 LOC) →widgets/heritage_detail_sheet.dart(showHeritageDetailSheet(context, m)). Tīrs ekstrakts — tikaiHeritageMonumentun launchUrl async._showGpsMenu(70 LOC) →widgets/gps_menu_sheet.dart(showGpsMenuSheet(context, isActive, currentSettings, onToggleGps, onUpdateSettings)). Geofence iestatījumu navigācija saglabāta.- map_screen: 8716 → 8598 LOC (-118).
- B.3 ATCELTS —
_buildActiveMapSummaryjau bija dead, dzēsts B.0. - B.4
services/ozols_layer_controller.dart— Timer + reload + polygon clip (~400 LOC) - B.5
services/audio_recording_controller.dart— koplietots ar Sprint 11 atrastiem ekstraktiem (~300 LOC) - B.6 Funkcionāls regresijas tests — visu plūsmas manuāli pārbaudīt
- B.7
map_screen.dartLOC pēc Sprint B: cieri uz ~6 900 LOC (no 9 142 pēc B.0)
Risks: Med — daudzu state lauku saites jāmaina. Pieprasa rūpīgu testēšanu pēc katra extract.
Sprint B sesija 2026-05-12 — kopsavilkums¶
Rezultāts: map_screen.dart 9404 → 8483 LOC (-921, -9.8%), 37% no Sprint B mērķa (mērķis ~6900).
Veikti 7 commit'i:
1. B.0 — dead code sweep (262 LOC)
2. B.2 — MoreMenuSheet (94 LOC)
3. B.2b — SharePickerSheet (100 LOC)
4. B.2c — VisibilityPanelSheet (232 LOC) ← vissarežģītākais
5. B.2d — HeritageDetailSheet + GpsMenuSheet (118 LOC)
6. B.2e — EncumbranceList (115 LOC)
Arhitektūras vērtība: 6 jauni widget faili ar konsekventu pattern — top-level show*Sheet(context, ...) funkcijas + callback-only saskarne. flutter analyze nav pievienojusi jaunas warnings (3 pre-existing async-gap infos paliek).
Sprint B atlikušais (nākamai sesijai)¶
Augstākās prioritātes (ranked pēc LOC ietekmes):
1. _showLayerPicker (~470 LOC, 5157) — biggest single extract, complex state
2. _buildOverlaySections (~180 LOC) — saistīts ar layer picker
3. _showDrawingColorPicker + _showFeatureColorPicker (~250 LOC kopā) — konsolidēt vienā ColorPickerDialog widget
4. _showCaSettingsSheet (~360 LOC), _showCaEditDialog, _showDrawingEditDialog — medium dialogi
5. B.4 Ozols controller — joprojām prasa arhitektūras lēmumu (ChangeNotifier vai pass-through)
6. B.5 audio controller — jau ekstrahēts iepriekš uz widgets/audio_record_dialog.dart
Ieteikumi nākamajai sesijai¶
- Sākt ar B.2f (Color picker konsolidācija) — divi līdzīgi metodes vienā commit'ā, ~250 LOC, medium risk
- Pēc tam
_showLayerPickerkā atsevišķs commit (lielākais atlikušais ekstrakts, ~470 LOC) - Pirms B.4 (Ozols) — pieņemt arhitektūras lēmumu: ChangeNotifier-based controller vai pass-through callback pattern (kā B.2c VisibilityPanel)
Sprint C — map_screen.dart demolish #2 + monitored_properties split (2 nedēļas, ~25h)¶
- C.1
services/drawing_controller.dart— zīmēšanas state + undo/redo (~600 LOC) - C.2
widgets/geofence_map_binding.dart— geofence rendering (~200 LOC) - C.3
services/deeplink_resolver.dart— post-frame deeplinks (~150 LOC) - C.4
services/map_state_auto_saver.dart— Timer + prefs flush (~200 LOC) - C.5
widgets/encumbrance_mini_sheet.dart— encumbrance sheet (~80 LOC) - C.6
monitored_properties_screen.dartsadalīt: properties_tab.dart— sarakstsnotifications_tab.dart— push notificationsproperty_search_panel.dart— search UI komponente- C.7
map_screen.dartcieri: < 3 500 LOC - C.8
monitored_properties_screen.dartcieri: < 1 500 LOC
Sprint D — Backend Blueprint refaktors (1-2 nedēļas, ~18h)¶
Mērķis: vzd_local_service.py 3 043 LOC → 6 Blueprint moduļi, katrs < 500 LOC.
- D.1 Struktūras izveide:
services/vzd_local_service/ __init__.py # create_app(), reģistrē blueprintus blueprints/ property_bp.py # /api/property/* geocode_bp.py # /api/geocode/*, /api/reverse-geocode forest_bp.py # /api/forest/* subscription_bp.py # /api/subscription/*, /api/checkout/*, /webhook event_bp.py # /api/event/*, /api/services-config metrics_bp.py # /metrics, /health helpers/ db_pool.py # init_pool, query_one, query_all payload.py # _build_property_payload + sub-funkcijas - D.2 Property Blueprint extract (8 endpointu)
- D.3 Geocode Blueprint extract (4 endpointu)
- D.4 Forest Blueprint extract (3 endpointu)
- D.5 Subscription Blueprint extract (Stripe + Customer)
- D.6 Event Blueprint extract
- D.7 Metrics Blueprint extract
- D.8 Helper'i: db_pool + payload
- D.9 Esošie testi paliek funkcionāli; pievienot Blueprint-level tests
- D.10 Deploy verifikācija (gunicorn
vzd_local_service:appjoprojām strādā vai gunicorn entrypoint vajag atjaunot)
Risks: Med — entrypoint maiņa Docker konteinerim.
Sprint E — Test Coverage Uzplūdes (1-2 nedēļas, ~20h)¶
5 kritiskās plūsmas, kurām DRŪKĀKI testus:
- E.1 Stripe webhook tests (backend) — kritisks, klusu silent fail = klients samaksā bez subscription
- E.2 Property aggregator integration test (backend, in-memory PG fixture vai SQLite)
- E.3 Skice → KML/PDF eksports roundtrip (mobile)
- E.4 Marker capture (foto/audio → save → pārlādes) (mobile)
- E.5 Deeplink → MapScreen integration (mobile)
- E.6 CI: pievienot
test/widgetsun atsevišķitest/screensdirektorijas (tagad ne CI iekšā) - E.7 Mērķis: 8-10 jauni widget testi
- E.8 Mērķis: 3 jauni screen smoke tests (Map / Settings / Skice)
Sprint F — Skice + Capture Konsolidācija (1-2 nedēļas, ~18h)¶
- F.1
services/skice_*_service(4 faili) → vienotsservices/skice/: skice_service.dartar exporter strategyexporters/kml_exporter.dartexporters/pdf_exporter.dartexporters/shp_exporter.dartexporters/geojson_exporter.dart- F.2
media_capture+media_serviceapvienot →media_service.dartar capture submodule - F.3 Vienots
CapturePickerUI (foto + audio + piezīme + skice no viena FAB) - F.4
cadastre_service.dartsadalīt 3 daļās: cadastre_api_client.dart— HTTP klientscadastre_geometry.dart— ģeometrijas parsingcadastre_cache.dart— caching layer- F.5 Mobile services count: 66 → ~52
Sprint G — External Services Hardening (1 nedēļa, ~15h)¶
- G.1 Gmail SMTP → Mailgun (vai SES) migrācija
email_service.pyswap SMTP backend- Update
.env.example - DEPLOYMENT.md doc update
- G.2 VMD epak retry + 5-min cache (jau Sprint 0 daļēji)
- G.3
BillingServicefasāde priekš Stripe (mazina lock-in blast radius) - G.4 DB index audit —
pg_stat_user_indexesGrafana panel - G.5 Drop legacy
deployment/refresh_cron.sh
Sprint H — CI + Cleanup (1 nedēļa, ~10h)¶
- H.1
.gitlab-ci.yml(699 LOC) — izvilkt biežos blokus uzdeploy/lib/*.sh - H.2
catch (_)audit pa servisiem — pievienot Sentry hooks - H.3 Pārvaldīt
AUTH_BYPASS=1default (sk. CLAUDE.md) — uz prod tas jāuzliek0 - H.4 Atjaunot CI cron entries dokumentāciju
- H.5 Final code style review + lint pass
Progress Tracking¶
Pārliecinies, ka aizpildi šos pēc katra sprinta:
| Sprint | Statuss | Pabeigts | Reālais effort | Piezīmes |
|---|---|---|---|---|
| 0 | ✅ pabeigts | 2026-05-12 | ~2h | VMD cache + CI blokus + lint regulas (327 auto-fixes) |
| A | 9/9 daļēji: A.3+A.4+A.5+A.x1+A.x2+A.x3 done; A.6+A.7 daļēji | 2026-05-12 | ~4h | 8 widget'i migrēti (50+ hardcoded krāsas); A.6/A.7 daļēji — non-grid spacings un fontSize gaida Sprint B/C dekompozīciju |
| B | 🔄 37% (6/16 commit'i): B.0+B.2+B.2b+B.2c+B.2d+B.2e done | 2026-05-12 (sesija 1) | ~5h | map_screen 9404 → 8483 LOC (-921, -9.8%). 6 jauni widget faili. Mērķis ~6900 LOC; atlikušais — _showLayerPicker ~470, _showCaSettingsSheet ~360, _buildOverlaySections ~180, color picker konsolidācija, B.4 Ozols |
| C | not started | — | — | Atkarīgs no B |
| D | not started | — | — | Paralēli ar B/C |
| E | not started | — | — | Atkarīgs no D |
| F | not started | — | — | Atkarīgs no E |
| G | not started | — | — | — |
| H | not started | — | — | — |
Konvencijas¶
- Branch: Viss darbs
refactor/code-audit-sprintsbranchā. Katra sprinta beigās — squash merge uzmain(geo-backend) vai feature branch (geo-mobile). - Commit prefix:
refactor(sprint-X.Y): ... - Pēc katra extract: flutter analyze + pytest + manuāls smoke test telefonā.
- Sprint progresa update: šo
REFACTORING_PLAN.mdfailu atjauno pa ceļam.
Atsauces¶
- Iepriekšējais ātrais audit (post-Sprint 11): commit
6d18255un05f5582 - Audit dokuments: šo failu pamatā ir 2026-05-12 pamatīga kodu audita pilna atskaite (sk. session chat history)
- Sprintu sekošana: GitLab milestones (sagatavojami nākamajā darba sesijā)