Skip to content

feat: security tab with derived holding and full execution history - #4257

Merged
gilgardosh merged 3 commits into
mainfrom
feat/security-business-tab
Aug 20, 2026
Merged

feat: security tab with derived holding and full execution history#4257
gilgardosh merged 3 commits into
mainfrom
feat/security-business-tab

Conversation

@gilgardosh

Copy link
Copy Markdown
Collaborator

Step 6 of the per-security businesses plan. Stacked on #4256.

A security business had no view of its own — trades were visible one charge at a time, and the only
way to see what is held was to add the executions up by hand. The business page now grows a
Security tab, shown for any business with a businesses_securities row:

  • Position summary — units held, weighted average cost per unit bought, totals bought and sold,
    with the ISIN, symbol, exchange, currency, type and ETF/foreign badges.
  • Full execution history across every Poalim key the security is known by, oldest first, each row
    linking to the charge behind its cash movement ( when nothing matched).

The position is derived, and says so

Holdings are not scraped, so the card states the date the ingested history starts from and that
anything held before it is not counted. Corporate actions that change the unit count without an
execution row are invisible for the same reason. Cash-only actions (dividends, interest) leave the
count alone; buys, distributions and transfers in add; sales, redemptions and transfers out subtract.

Server

Query.securityBusinessHistory(businessId)SecurityBusinessHistory (SecurityPosition +
SecurityHistoryExecution, an execution with its transaction and charge). The pairing is the one the
charge view already shows, read from the other end: the security business's own transactions matched
against its executions by matchExecutionsToTransactions (#4253). The tab runs its own query — like
Charges/Transactions/Ledger — so a business page never pays for execution history it doesn't show.

Shared table

The charge panel's "Portfolio activity" table and the new one are now one component
(components/securities/security-executions-table.tsx) over one fragment, so the two always read
alike. The charge panel changes in no other way.

Verification

  • yarn generate, yarn lint, yarn prettier clean; server and client both typecheck.
  • yarn test — 3439 passed, incl. 8 new position cases (buys minus sells, weighted average cost,
    cash-only actions leaving the count alone, transfers in/out, redemption as both an exit and
    proceeds, history span independent of row order).
  • yarn test:integration — 3882 passed.

🤖 Generated with Claude Code

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds a dedicated Security tab on a security business page, backed by a new GraphQL query that returns a derived position summary plus the full execution history, and reuses a shared executions table UI between the charge panel and the new tab.

Changes:

  • Server: add Query.securityBusinessHistory(businessId) returning security metadata, derived SecurityPosition, and execution rows paired to transactions/charges.
  • Server: add calculateSecurityPosition() (with tests) to derive quantity/average cost/totals and the history span.
  • Client: introduce a shared SecurityExecutionsTable component and add the new Business “Security” tab UI using the new query.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
packages/server/src/modules/foreign-securities/types.ts Adds proto types for security business history + derived position.
packages/server/src/modules/foreign-securities/typeDefs/security-businesses.graphql.ts Extends schema with securityBusinessHistory and related types.
packages/server/src/modules/foreign-securities/resolvers/security-businesses.resolver.ts Implements query + field resolvers for history executions and position formatting.
packages/server/src/modules/foreign-securities/providers/foreign-securities.provider.ts Adds DB query + matching logic to fetch full security history and pair executions to transactions.
packages/server/src/modules/foreign-securities/providers/tests/foreign-securities.integration.test.ts Updates provider test construction for the new dependency.
packages/server/src/modules/foreign-securities/helpers/security-position.helper.ts Introduces the position derivation logic from executions.
packages/server/src/modules/foreign-securities/helpers/tests/security-position.helper.test.ts Adds unit tests for position derivation cases.
packages/client/src/components/securities/security-executions-table.tsx New shared executions table + GraphQL fragment for consistent rendering.
packages/client/src/components/charges/extended-info/foreign-securities-info.tsx Reuses the shared executions table component in the charge panel.
packages/client/src/components/business/security-section.tsx New Security tab content: position summary + full execution history with charge links.
packages/client/src/components/business/index.tsx Adds a “Security” tab trigger/content when securityInfo is present.
codegen.ts Maps new GraphQL types to server proto types for resolvers/codegen.
.changeset/security-business-tab.md Changeset documenting the new security business page/tab feature.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +74 to +75
totalBought: position => formatFinancialAmount(position.totalBought, position.currency),
totalSold: position => formatFinancialAmount(position.totalSold, position.currency),

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Good catch — fixed in the latest push. All three amounts now go through a positionAmount(value, currency) helper that returns null when either is missing, so averageCost keeps its existing guard and the two totals gain the same one.

The client needed no change: the card already renders position.totalBought?.formatted ?? "—", so it was faithfully displaying a wrong value rather than missing a null case. Pinned the contract the resolver leans on in the position helper test (no executions ⇒ currency: null).

@gilgardosh
gilgardosh force-pushed the feat/security-businesses-backfill branch from 9742d03 to 4442f0b Compare August 20, 2026 09:47
@gilgardosh
gilgardosh force-pushed the feat/security-business-tab branch from 5a78f8c to 5e176c4 Compare August 20, 2026 09:52
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack August 20, 2026 09:52 — with GitHub Actions Inactive
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack August 20, 2026 09:52 — with GitHub Actions Inactive
@gilgardosh
gilgardosh force-pushed the feat/security-businesses-backfill branch 2 times, most recently from fed3740 to cb23ed0 Compare August 20, 2026 13:40
@gilgardosh
gilgardosh force-pushed the feat/security-business-tab branch from 5e176c4 to 0b787ee Compare August 20, 2026 13:45
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack August 20, 2026 13:45 — with GitHub Actions Inactive
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack August 20, 2026 13:45 — with GitHub Actions Inactive
@gilgardosh
gilgardosh force-pushed the feat/security-business-tab branch from 0b787ee to 566a682 Compare August 20, 2026 13:47
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack August 20, 2026 13:48 — with GitHub Actions Inactive
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack August 20, 2026 13:48 — with GitHub Actions Inactive
@gilgardosh
gilgardosh changed the base branch from feat/security-businesses-backfill to feat/security-businesses-plan August 20, 2026 13:48
gilgardosh and others added 2 commits August 20, 2026 16:56
Adds Query.securityBusinessHistory and a Security tab on the business page,
shown for any business with a businesses_securities row. Shows the position
derived from ingested executions - with the as-of caveat, since holdings are
not scraped - and every execution across the security's Poalim keys, each
linking to the charge behind its cash movement.

The charge panel's portfolio table and the new one are now one shared
component over one fragment.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Addresses review feedback. A security with no ingested executions has no
currency, and formatFinancialAmount falls back to the local one - so the card
showed a confident ILS 0 for totals nothing is known about. The resolver now
returns null for all three amounts when the currency is null; the client
already renders null as an em dash.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@gilgardosh
gilgardosh force-pushed the feat/security-business-tab branch from 566a682 to e137d21 Compare August 20, 2026 13:56
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack August 20, 2026 13:56 — with GitHub Actions Inactive
@gilgardosh
gilgardosh changed the base branch from feat/security-businesses-plan to main August 20, 2026 13:56
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack August 20, 2026 13:56 — with GitHub Actions Inactive
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack August 20, 2026 14:53 — with GitHub Actions Inactive
@gilgardosh
gilgardosh merged commit e813ec1 into main Aug 20, 2026
9 of 10 checks passed
@gilgardosh
gilgardosh deleted the feat/security-business-tab branch August 20, 2026 14:54
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack August 20, 2026 14:54 — with GitHub Actions Inactive
@github-actions

Copy link
Copy Markdown
Contributor

🚀 Snapshot Release (alpha)

The latest changes of this PR are available as alpha on npm (based on the declared changesets):

Package Version Info
@accounter/client 0.1.0-alpha-20260820145547-9aa709e6e4b6848f940ba48f372d24aecfccc955 npm ↗︎ unpkg ↗︎
@accounter/green-invoice-graphql 0.8.7-alpha-20260820145547-9aa709e6e4b6848f940ba48f372d24aecfccc955 npm ↗︎ unpkg ↗︎
@accounter/hashavshevet-mesh 0.2.13-alpha-20260820145547-9aa709e6e4b6848f940ba48f372d24aecfccc955 npm ↗︎ unpkg ↗︎
@accounter/israeli-vat-scraper 0.1.13-alpha-20260820145547-9aa709e6e4b6848f940ba48f372d24aecfccc955 npm ↗︎ unpkg ↗︎
@accounter/modern-poalim-scraper 0.11.0-alpha-20260820145547-9aa709e6e4b6848f940ba48f372d24aecfccc955 npm ↗︎ unpkg ↗︎
@accounter/payper-mesh 0.2.13-alpha-20260820145547-9aa709e6e4b6848f940ba48f372d24aecfccc955 npm ↗︎ unpkg ↗︎
@accounter/scraper-app 0.0.3-alpha-20260820145547-9aa709e6e4b6848f940ba48f372d24aecfccc955 npm ↗︎ unpkg ↗︎
@accounter/server 0.2.0-alpha-20260820145547-9aa709e6e4b6848f940ba48f372d24aecfccc955 npm ↗︎ unpkg ↗︎
@accounter/shaam-uniform-format-generator 0.2.7-alpha-20260820145547-9aa709e6e4b6848f940ba48f372d24aecfccc955 npm ↗︎ unpkg ↗︎
@accounter/shaam6111-generator 0.1.9-alpha-20260820145547-9aa709e6e4b6848f940ba48f372d24aecfccc955 npm ↗︎ unpkg ↗︎

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.

2 participants