Skip to content

Conversation

@kewitz
Copy link
Contributor

@kewitz kewitz commented Jan 6, 2026

@kewitz kewitz force-pushed the refact/enhance-associated-collectives branch from 2bf3916 to 59194c5 Compare January 6, 2026 18:27
Comment on lines 137 to 150
const result = results[0];
return {
expenseTotal: { value: result?.expenseTotal || 0, currency: result?.hostCurrency || 'USD' },
expenseCount: result?.expenseCount || 0,
contributionTotal: { value: result?.contributionTotal || 0, currency: result?.hostCurrency || 'USD' },
contributionCount: result?.contributionCount || 0,
orderCount: result?.orderCount || 0,
};
},

This comment was marked as outdated.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could use a new type like CommunityAssociatedAccountTransactionSummary with just the fields we want here, to avoid confusion with CommunityTransactionSummary as the implementation is different not having year and expenseTotalAcc etc.

Comment on lines +103 to +135
SELECT
t."FromCollectiveId",
t."HostCollectiveId",
t."CollectiveId",
h.currency AS "hostCurrency",
COALESCE(SUM(t."amountInHostCurrency") FILTER (WHERE t.kind = 'EXPENSE'::"enum_Transactions_kind"),
0::bigint) AS "expenseTotal",
COALESCE(COUNT(t.id) FILTER (WHERE t.kind = 'EXPENSE'), 0::bigint) AS "expenseCount",
COALESCE(SUM(t."amountInHostCurrency") FILTER (WHERE t.kind = 'CONTRIBUTION'::"enum_Transactions_kind"),
0::bigint) AS "contributionTotal",
COALESCE(COUNT(t.id) FILTER (WHERE t.kind = 'CONTRIBUTION'),
0::bigint) AS "contributionCount",
COALESCE(COUNT(DISTINCT t."OrderId") FILTER (WHERE t.kind = 'CONTRIBUTION'::"enum_Transactions_kind"),
0::bigint) AS "orderCount"
FROM
"Transactions" t
JOIN "Collectives" h ON t."HostCollectiveId" = h.id
WHERE t."deletedAt" IS NULL
AND t."RefundTransactionId" IS NULL
AND t."isRefund" = FALSE
AND (t.kind = ANY (ARRAY ['CONTRIBUTION'::"enum_Transactions_kind", 'EXPENSE'::"enum_Transactions_kind"]))
AND t."hostCurrency" = h.currency
AND t."FromCollectiveId" = :FromCollectiveId
AND t."CollectiveId" = :CollectiveId
AND t."HostCollectiveId" = :HostCollectiveId
GROUP BY
t."FromCollectiveId", t."HostCollectiveId", t."CollectiveId", h.currency
`,
{
raw: true,
type: sequelize.QueryTypes.SELECT,
replacements: { FromCollectiveId, HostCollectiveId, CollectiveId },
},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this is a blocker or it is desired, but we have some hosts that have switched currency in their past (see query below), so this would filter the transactions before the switch.

There's a sumTransactionsInCurrency that could help to sum up the different currencies if we want to implement that, although with the drawback that the fx rate would keep changing..

WITH host_tx AS (
  SELECT
    t."HostCollectiveId",
    t."hostCurrency",
    MIN(t."createdAt") AS first_seen_at,
    MAX(t."createdAt") AS last_seen_at,
    COUNT(*)           AS tx_count
  FROM "Transactions" t
  WHERE t."deletedAt" IS NULL
    AND t."RefundTransactionId" IS NULL
    AND t."isRefund" = FALSE
    AND t."hostCurrency" IS NOT NULL
  GROUP BY t."HostCollectiveId", t."hostCurrency"
),
host_switch AS (
  SELECT
    "HostCollectiveId",
    COUNT(*) AS distinct_host_currencies,
    MIN(first_seen_at) AS first_tx_at,
    MAX(last_seen_at)  AS last_tx_at
  FROM host_tx
  GROUP BY "HostCollectiveId"
  HAVING COUNT(*) >= 2
)
SELECT
  hs."HostCollectiveId",
  h.slug        AS host_slug,
  h.name        AS host_name,
  h.currency    AS current_host_currency,
  hs.distinct_host_currencies,
  hs.first_tx_at,
  hs.last_tx_at,
  JSONB_AGG(
    JSONB_BUILD_OBJECT(
      'hostCurrency', ht."hostCurrency",
      'firstSeenAt',  ht.first_seen_at,
      'lastSeenAt',   ht.last_seen_at,
      'txCount',      ht.tx_count
    )
    ORDER BY ht.first_seen_at
  ) AS currencies_timeline
FROM host_switch hs
JOIN "Collectives" h ON h.id = hs."HostCollectiveId"
JOIN host_tx ht      ON ht."HostCollectiveId" = hs."HostCollectiveId"
GROUP BY hs."HostCollectiveId", h.slug, h.name, h.currency, hs.distinct_host_currencies, hs.first_tx_at, hs.last_tx_at
ORDER BY hs.last_tx_at DESC;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm OK with keeping this way, because we usually have a transaction to represent the conversion from one currency to another.

This will need to change whenever we implement multi-currency hosts, but even in that condition I think I would rather display the separate amounts in each currency.

@kewitz kewitz force-pushed the refact/enhance-associated-collectives branch from 59194c5 to 9da37c6 Compare January 7, 2026 14:38
@kewitz kewitz merged commit ce8cecc into main Jan 7, 2026
20 checks passed
@kewitz kewitz deleted the refact/enhance-associated-collectives branch January 7, 2026 15:00
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.

3 participants