Skip to content

Feature/issue 1072 1073 1074 1075 - #1181

Merged
Xoulomon merged 5 commits into
Xoulomon:mainfrom
Pilot39:feature/issue-1072-1073-1074-1075
Sep 1, 2026
Merged

Feature/issue 1072 1073 1074 1075#1181
Xoulomon merged 5 commits into
Xoulomon:mainfrom
Pilot39:feature/issue-1072-1073-1074-1075

Conversation

@Pilot39

@Pilot39 Pilot39 commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Description

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation
  • CI / Other

Testing

  • Unit tests pass (cargo test / npm test)
  • Integration tests pass
  • Manual testing done

Review Checklist

  • Code follows project style (clippy / ESLint clean)
  • No debug logs or console statements left in
  • Tests added or updated for changed behaviour
  • Docs updated if needed
  • Security implications considered

Related Issues

Closes #1075
Closes #1074
Closes #1073
Closes #1072

Pilot39 added 4 commits August 28, 2026 14:44
… submodules (Xoulomon#1075)

The monolithic contracts.rs was a merge-conflict hotspot.  Route handlers
are now split into focused resource modules under backend/src/api/contracts/.

New files
---------
backend/src/api/mod.rs
  Top-level API module; mounts all sub-APIs under /api.

backend/src/api/contracts/mod.rs
  Re-exports waste and incentive submodules; mounts both under /api/contracts.

backend/src/api/contracts/waste.rs  (~250 lines)
  Handlers: register_waste, get_waste, list_participant_wastes,
            transfer_waste, update_waste_status.
  Route scope: /api/contracts/waste/**
  Integration tests for success, missing fields, invalid status values,
  and self-transfer rejection.

backend/src/api/contracts/incentive.rs  (~220 lines)
  Handlers: distribute_rewards, get_balance, claim_reward, list_programmes.
  Route scope: /api/contracts/incentive/**
  Integration tests for success, zero amounts, missing wallet, and
  programme listing.

backend/src/api/errors.rs
  Shared ApiError type used by all handlers (see also Xoulomon#1073 commit).

Modified files
--------------
backend/src/main.rs
  Add 'mod api;' and wire configure_api_routes into the App builder.
  Replace println! startup log with log::info! (Xoulomon#1074 logging convention).
…Xoulomon#1074)

Define and apply a consistent structured-logging convention to every
service in backend/src/services.

Logging convention (see docs/LOGGING_CONVENTION.md)
---------------------------------------------------
Every log call emits at minimum three key-value fields:
  service  — module name (e.g. 'notifications')
  op       — method name (e.g. 'register_device')
  outcome  — 'ok' | 'error' | 'warn'

These fields make every log line queryable in Grafana/Loki via:
  {app='scavenger-backend'} | json | service='notifications', outcome='error'

Changes per service
-------------------
notifications.rs
  - Added log::info! on successful register_device, get_preferences,
    set_preferences, schedule_notification.
  - Added log::warn! for all validation/guard rejections.
  - Added log::error! for FCM HTTP failures with status code.
  - Removed implicit println!/debug output.

reporting.rs
  - Added log::info! on generate_report, get_report, schedule_report,
    get_templates, cache_report success paths.
  - Added log::warn! for all InvalidReport / NotFound early returns.
  - Includes recipient_count and bytes context where useful.

storage.rs
  - Added log::info! on upload_file (with bytes), delete_file,
    get_signed_url, get_file_metadata success paths.
  - Added log::warn! for every empty-id / zero-expiration guard.

email.rs
  - Added log::info! on successful send_transactional, send_digest,
    add_to_unsubscribe_list, is_unsubscribed.
  - Added log::warn! for validation failures.
  - Added log::error! for SendGrid HTTP failures with status code.
  - Added email_domain() helper to log domain only (PII reduction).
  - Removed println!/eprintln! left over from development.

main.rs (updated in Xoulomon#1075 commit)
  - println! startup message replaced with log::info!.

New file
--------
docs/LOGGING_CONVENTION.md
  - Documents required fields (service, op, outcome).
  - Documents optional fields (request_id, user_id, error, bytes).
  - Documents log-level guidance and PII rules.
  - Includes Grafana/Loki LogQL query examples.
  - Lists banned patterns (println!, unstructured log::info!).
Xoulomon#1073)

All API modules now return Result<_, ApiError> so the client always
receives the same JSON error envelope regardless of which module raised
the error.

New files
---------
backend/src/errors.rs
  Re-exports ApiError, ErrorBody, ErrorDetail from api::errors (the type
  definition lives there; this module is the canonical import path:
  'use crate::errors::ApiError').

  Adds From<ServiceError> for ApiError for all four service error enums:
    ReportError::InvalidReport  → ApiError::Validation (400)
    ReportError::NotFound       → ApiError::NotFound   (404)
    ReportError::ServiceError   → ApiError::Internal   (500)
    StorageError::InvalidFile   → ApiError::Validation (400)
    StorageError::NotFound      → ApiError::NotFound   (404)
    StorageError::ServiceError  → ApiError::Internal   (500)
    NotificationError::Invalid  → ApiError::Validation (400)
    NotificationError::NotFound → ApiError::NotFound   (404)
    NotificationError::Service  → ApiError::Internal   (500)
    EmailError::InvalidEmail    → ApiError::Validation (400)
    EmailError::TemplateError   → ApiError::Internal   (500)
    EmailError::ServiceError    → ApiError::Internal   (500)

  Integration tests assert the exact wire-format shape consistency:
    - every variant produces { error: { code, message, request_id } }
    - no extra top-level keys are present
    - HTTP status codes match for all six variants
    - all service-error conversions produce the correct ApiError code

docs/ERROR_HANDLING.md
  Documents the canonical error type, wire format, HTTP status mapping,
  service error mapping table, and usage patterns.
  Lists explicitly banned patterns (ad-hoc JSON construction, bare
  actix_web::Error, panic!/unwrap() in handlers).

Modified files
--------------
backend/src/main.rs
  Add 'mod errors;' declaration so the module is compiled and its
  From impls are available crate-wide.

Context
-------
The ApiError type and its ResponseError implementation were introduced
in Xoulomon#1075 (backend/src/api/errors.rs).  This commit adds the canonical
top-level re-export path, wires all service-error conversions, and
provides the integration tests required by issue Xoulomon#1073.
…eExport and useImport (Xoulomon#1072)

Audit of frontend/src/hooks/useExportImport.ts call sites confirmed that
only CSV and JSON formats are actively used. All dead branches have been
removed and the hook has been split into two focused modules.

Dead code removed
-----------------
The original combined hook contained format-handling branches with no
call sites in the codebase:
  - XML export/import handler
  - XLS / XLSX export/import handler
  - 'legacy-csv' branch with a different column order (superseded by
    the current CSV path in useAnalyticsExport)
  - Unreachable 'dry-run preview' branch never wired to any UI component

New files
---------
frontend/src/hooks/useExport.ts
  Provides exportToCSV(rows, options?) and exportToJSON(data, options?).
  Both functions are stable useCallback references.
  Supported formats: CSV (text/csv) and JSON (application/json).
  Optional filename override; falls back to 'export-<timestamp>.<ext>'.

frontend/src/hooks/useImport.ts
  Provides importFromCSV(file) and importFromJSON(file).
  Exposes an ImportState<T> { data, error, isLoading } alongside the
  async functions so callers can drive UI feedback from a single hook.
  Supported formats: CSV (parsed into CsvRecord[] header-keyed objects)
  and JSON (parsed into typed T via JSON.parse).

frontend/src/hooks/useExportImport.ts  (updated)
  Now a thin re-export barrel for backward compatibility.
  Documents which dead branches were removed.
  New code should import directly from useExport or useImport.

Test files (new)
----------------
frontend/src/hooks/__tests__/useExport.test.ts  (15 tests)
  - CSV: triggers download, correct MIME type, custom filename,
    timestamped fallback filename, empty-rows guard (no download),
    stable callback reference across re-renders.
  - JSON: triggers download, correct MIME type, custom filename,
    timestamped fallback, array data, stable reference.
  - Dead-branch assertions: exportToXML, exportToXLS, exportToXLSX,
    exportToLegacyCSV are all undefined on the returned object.

frontend/src/hooks/__tests__/useImport.test.ts  (15 tests)
  - CSV: parses header-keyed records, state.data set, error on empty
    file, isLoading lifecycle, FileReader failure, header-only CSV,
    blank-line skipping.
  - JSON: parses object/array, state.data set, error on invalid JSON.
  - Dead-branch assertions: importFromXML, importFromXLS, importFromXLSX,
    dryRunPreview, previewImport are all undefined on the returned object.
@Pilot39
Pilot39 requested a review from Xoulomon as a code owner August 28, 2026 14:20
@drips-wave

drips-wave Bot commented Aug 28, 2026

Copy link
Copy Markdown

@Pilot39 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@Pilot39 Pilot39 closed this Aug 28, 2026
@Pilot39 Pilot39 reopened this Sep 1, 2026
@Pilot39 Pilot39 closed this Sep 1, 2026
@Pilot39 Pilot39 reopened this Sep 1, 2026
@Xoulomon
Xoulomon merged commit 0bfd468 into Xoulomon:main Sep 1, 2026
6 of 119 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants