Skip to content

feat: contract stats cards (#556) + cost attribution per org (#538)#721

Open
whiteghost0001 wants to merge 3 commits into
SoroScan:mainfrom
whiteghost0001:feat/contract-stats-cards-and-cost-attribution
Open

feat: contract stats cards (#556) + cost attribution per org (#538)#721
whiteghost0001 wants to merge 3 commits into
SoroScan:mainfrom
whiteghost0001:feat/contract-stats-cards-and-cost-attribution

Conversation

@whiteghost0001
Copy link
Copy Markdown
Contributor

Issue #556 — Contract Stats Cards (frontend)

Closes #556

What was done

Added a ContractStatsCards component to the Event Explorer Dashboard that displays four at-a-glance statistics for the currently selected contract:

• Total Events — total event count for the active filter/page set
• Events / Hour — count of events emitted in the last 60 minutes
• Latest Event — wall-clock time of the most recent event
• Event Types — number of distinct event types in the current result set

How it was done

  • Created soroscan-frontend/app/dashboard/components/ContractStatsCards.tsx A pure client component that receives the already-loaded events, totalCount, and loading props from EventExplorerDashboard. Stats are derived with useMemo — no extra network requests.
  • Created ContractStatsCards.module.css with a 4-column responsive grid (collapses to 2-col on ≤700 px, 1-col on ≤400 px) styled to match the existing terminal/cyber aesthetic (JetBrains Mono, cyan/green accents, dark glass-morphism cards with a coloured left border per stat).
  • Imported and rendered ContractStatsCards inside EventExplorerDashboard.tsx between the AdvancedSearch bar and the events table section.

Issue #538 — Cost Attribution per Organization (backend) Closes #538

What was done

Implemented a full billing cost-attribution pipeline for multi-tenant orgs:

  1. OrganizationUsage model (django-backend/soroscan/ingest/models.py) Stores a monthly usage snapshot per Team with three billing dimensions:

    • request_count (API/ingestion requests → compute cost)
    • storage_bytes (serialised event payload bytes → storage cost)
    • egress_bytes (bytes served via API → egress cost)
      Unique constraint on (team, period_start) so each org has one record
      per billing month.
  2. Migration 0016_organizationusage.py Creates the ingest_organizationusage table and adds a composite index on (team_id, period_start) for fast per-org period lookups.

  3. Billing service (django-backend/soroscan/ingest/services/billing.py) - compute_costs(usage) — converts raw usage counters to itemised USD costs using configurable per-unit rates (BILLING_PRICE_PER_REQUEST, BILLING_PRICE_PER_GB_STORAGE, BILLING_PRICE_PER_GB_EGRESS in Django settings; sensible defaults baked in). - snapshot_usage_for_team(team, period_start, period_end) — queries ContractEvent for the team's contracts in the given date range, counts events (request_count), sums serialised payload sizes (storage_bytes), and upserts an OrganizationUsage record.

  4. REST API view + URL GET /api/billing/orgs/<team_slug>/costs/?period=YYYY-MM - Authenticated endpoint; caller must be a team member or staff. - Defaults to the current calendar month if period is omitted. - Calls snapshot_usage_for_team then compute_costs and returns: { team, period_start, period_end, usage: {...}, costs: {...} } - Registered in ingest/urls.py as 'org-cost-attribution'.

…oroScan#538)

## Issue SoroScan#556 — Contract Stats Cards (frontend)
Closes SoroScan#556

### What was done
Added a ContractStatsCards component to the Event Explorer Dashboard that
displays four at-a-glance statistics for the currently selected contract:

  • Total Events     — total event count for the active filter/page set
  • Events / Hour   — count of events emitted in the last 60 minutes
  • Latest Event    — wall-clock time of the most recent event
  • Event Types     — number of distinct event types in the current result set

### How it was done
- Created soroscan-frontend/app/dashboard/components/ContractStatsCards.tsx
  A pure client component that receives the already-loaded `events`,
  `totalCount`, and `loading` props from EventExplorerDashboard. Stats are
  derived with useMemo — no extra network requests.
- Created ContractStatsCards.module.css with a 4-column responsive grid
  (collapses to 2-col on ≤700 px, 1-col on ≤400 px) styled to match the
  existing terminal/cyber aesthetic (JetBrains Mono, cyan/green accents,
  dark glass-morphism cards with a coloured left border per stat).
- Imported and rendered ContractStatsCards inside EventExplorerDashboard.tsx
  between the AdvancedSearch bar and the events table section.

---

## Issue SoroScan#538 — Cost Attribution per Organization (backend)
Closes SoroScan#538

### What was done
Implemented a full billing cost-attribution pipeline for multi-tenant orgs:

  1. OrganizationUsage model (django-backend/soroscan/ingest/models.py)
     Stores a monthly usage snapshot per Team with three billing dimensions:
       - request_count   (API/ingestion requests → compute cost)
       - storage_bytes   (serialised event payload bytes → storage cost)
       - egress_bytes    (bytes served via API → egress cost)
     Unique constraint on (team, period_start) so each org has one record
     per billing month.

  2. Migration 0016_organizationusage.py
     Creates the ingest_organizationusage table and adds a composite index
     on (team_id, period_start) for fast per-org period lookups.

  3. Billing service (django-backend/soroscan/ingest/services/billing.py)
       - compute_costs(usage) — converts raw usage counters to itemised USD
         costs using configurable per-unit rates (BILLING_PRICE_PER_REQUEST,
         BILLING_PRICE_PER_GB_STORAGE, BILLING_PRICE_PER_GB_EGRESS in
         Django settings; sensible defaults baked in).
       - snapshot_usage_for_team(team, period_start, period_end) — queries
         ContractEvent for the team's contracts in the given date range,
         counts events (request_count), sums serialised payload sizes
         (storage_bytes), and upserts an OrganizationUsage record.

  4. REST API view + URL
       GET /api/billing/orgs/<team_slug>/costs/?period=YYYY-MM
       - Authenticated endpoint; caller must be a team member or staff.
       - Defaults to the current calendar month if period is omitted.
       - Calls snapshot_usage_for_team then compute_costs and returns:
           { team, period_start, period_end, usage: {...}, costs: {...} }
       - Registered in ingest/urls.py as 'org-cost-attribution'.
@drips-wave
Copy link
Copy Markdown

drips-wave Bot commented Jun 1, 2026

@whiteghost0001 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

@whiteghost0001
Copy link
Copy Markdown
Contributor Author

conflict resolve

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Contract Stats Cards Cost Attribution per Organization

1 participant