Skip to content

Feat/ledger#444

Open
Paulijuz wants to merge 76 commits intomainfrom
feat/ledger
Open

Feat/ledger#444
Paulijuz wants to merge 76 commits intomainfrom
feat/ledger

Conversation

@Paulijuz
Copy link
Member

@Paulijuz Paulijuz commented Sep 23, 2025

After more than of year of waiting the ledger (money) system is finally here!* 💵 💸 💰

This includes:
✅ A flexible double entry ledger system for tracking transaction (deposits, payouts, purchases, etc.)
✅ Simple logic to calculate balances (goodbye ginormous sql query)
✅ Uniform ledger account interface between groups and users (no more source and drain accounts)
✅ Payments with Stripe (integrated with webhooks like before)
✅ Card detail saving with Stripe (makes use of new-ish CustomerSessions API for simpler integration)**

⚠️ *This PR is marked as draft until #443 is merged as it builts on top of it. I also have to tie up a few loose ends regarding permissions, although I think it might be best to do that in another PR.

⚠️ **I have not tested this fully yet so a few changes might still come.

@Paulijuz Paulijuz marked this pull request as ready for review January 19, 2026 19:35
@Paulijuz
Copy link
Member Author

As this PR is large enough as it is i will add integration to the event system in the branch feat/event-payments.

@Paulijuz
Copy link
Member Author

Paulijuz commented Feb 9, 2026

More merge conflicts... 😩

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR implements a comprehensive ledger (money/accounting) system for the application, introducing double-entry bookkeeping, Stripe payment integration, and ledger accounts for users and groups. The implementation builds on top of PR #443 which simplified service method interfaces.

Changes:

  • Added complete ledger schema with accounts, transactions, entries, and payment models supporting both Stripe and manual payments
  • Implemented double-entry accounting logic with automatic fee calculations and balance tracking
  • Integrated Stripe for payment processing, including webhook handling and saved payment method management
  • Created UI components for account management, deposits, payouts, and transaction history
  • Added test infrastructure with utilities for testing ledger operations

Reviewed changes

Copilot reviewed 101 out of 103 changed files in this pull request and generated 22 comments.

Show a summary per file
File Description
src/prisma/schema/ledger.prisma Core ledger database schema defining accounts, transactions, entries, and payments
src/prisma/schema/user.prisma Added ledger account and Stripe customer relations to users
src/prisma/schema/group.prisma Added ledger account relation to groups
src/services/ledger/accounts/operations.ts Ledger account CRUD operations and balance calculations
src/services/ledger/transactions/operations.ts Transaction creation, state management, and advancement logic
src/services/ledger/transactions/calculateFees.ts Fee calculation formulas for debit and credit entries
src/services/ledger/transactions/determineTransactionState.ts State machine for transaction lifecycle management
src/services/ledger/payments/operations.ts Payment creation and initiation for Stripe and manual payments
src/services/ledger/payments/stripeWebhookCallback.ts Webhook handler for Stripe payment events
src/services/ledger/movements/operations.ts High-level deposit and payout orchestration
src/services/stripeCustomers/operations.ts Stripe customer management and saved payment methods
src/lib/currency/convert.ts Currency conversion utilities replacing old money module
src/app/api/stripe-events/route.ts API route for receiving Stripe webhooks
src/app/_components/Ledger/* UI components for ledger account and transaction management
src/app/_components/Stripe/* Stripe integration components for payments
tests/services/ledger/* Test files for ledger functionality
tests/utils.ts Test utility for handling promise settlement
package.json Added Stripe SDK dependencies

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 101 out of 103 changed files in this pull request and generated 10 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +10 to +18
type Props = {
ref?: React.Ref<StripePaymentRef>,
}

export default function StripePayment({ ref }: Props) {
const stripe = useStripe()
const elements = useElements()

useImperativeHandle(ref, () => ({

stripe:
image: stripe/stripe-cli:v1.37.3
command: listen --forward-to http://nginx:80/api/stripe-events --skip-verify
STRIPE_SECRET_KEY: ${STRIPE_SECRET_KEY}
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY: ${NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY}
STRIPE_WEBHOOK_SECRET: ${STRIPE_WEBHOOK_SECRET}
MAIL_DOMAIN: ${MAIL_DOMAIN}
Comment on lines +131 to +136
stripe.paymentIntents.cancel(
paymentIntent.id,
{},
{ idempotencyKey: `project-next-payment-id-${paymentIntent.id}` },
)
}
Comment on lines +25 to +27
operation: async ({ prisma, data }): Promise<LedgerAccount> => {
const type = data.type ?? data.userId !== undefined ? 'USER' : 'GROUP'

Comment on lines +19 to +27
// Avoid loading the Stripe components until they are needed
const StripePayment = lazy(() => import('@/components/Stripe/StripePayment'))
const StripeProvider = lazy(() => import('@/components/Stripe/StripeProvider'))

const defaultPaymentProvider: PaymentProvider = 'STRIPE'
const paymentProviderNames: Record<PaymentProvider, string> = {
STRIPE: 'Stripe',
MANUAL: 'Manuell Betaling',
}
switch (type) {
case 'card':
return <>
<span>{card?.brand.toUpperCase()}</span>
<FontAwesomeIcon icon={faXmark}/>
</button>
</li>
)) : <p><em>Du har ingen lagrede betalingskort.</em></p>}
Comment on lines +17 to +18
const event = stripe.webhooks.constructEvent(body, stripeSignature, process.env.STRIPE_WEBHOOK_SECRET)

Comment on lines +28 to +30
describe.skip('payments', () => {
beforeAll(async () => {
await prisma.ledgerAccount.createMany({
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