Accounts Receivable Updates
Overview
This merge request brings several significant improvements to our invoice management application:
-
Dynamic Totals & Discounts:
- Invoice totals are now computed dynamically based on each line item’s price and quantity, with any applicable discounts factored in. This replaces the old static total.
-
Advanced Invoice Status:
- I've replaced the simple boolean "complete" flag with a multi-state system where invoices can be "Open", "Paid", or "Closed".
- The UI now features a dropdown in the invoice detail view for updating the status, and the sidebar shows the count of invoices in the "Open" state for each client.
-
Code Cleanup & Test Separation:
I've reorganized the project structure for better maintainability:- Components are now placed in
src/components/. - Store logic is contained within
src/store/, with its unit tests insrc/store/tests/. - Utility functions reside in
src/utils/, with corresponding tests insrc/utils/tests/. - Component tests are separated into
src/tests/. - End-to-end tests remain in the top-level
e2e/directory. - A global test setup file (
src/setupTests.ts) is used for configuration (e.g., importing jest-dom).
- Components are now placed in
-
Improved Test Coverage:
Both unit tests and end-to-end tests have been expanded:- Unit Tests: Verify the correct calculation of totals, discount computations, status updates in the store, and component behavior.
- E2E Tests: Validate critical user flows such as navigation, invoice status updates via the dropdown, and the invoice editing process.
Key Changes
-
Utils Update:
ThecalculateInvoiceTotalfunction now computes the invoice total dynamically by summing subtotals for both projects and services, with discounts applied where relevant. For example:function calculateInvoiceTotal(invoice: Invoice): number { const computeSubtotal = (items: LineItem[]): number => items.reduce((sum, item) => sum + item.price_cents * item.quantity, 0); return computeSubtotal(invoice.projects) + computeSubtotal(invoice.services); } -
Store Enhancements:
TheInvoiceinterface now includes astateproperty with possible values "Open", "Paid", or "Closed". New actions (UPDATE_STATUSandEDIT_INVOICE) have been added to the reducer to support status updates and invoice editing. -
Routing Updates:
A new route/invoices/:id/edithas been added to allow users to edit invoices. This route renders the InvoiceAdd component in edit mode. -
Testing Improvements:
- Unit Tests: Validate store logic, utility functions, and component behaviors (including form pre-population and status updates).
- End-to-End Tests: Ensure that user flows—such as navigating to the invoice edit page, updating status via the dropdown, and confirming updated data—work as expected.
How to Verify
- Run unit tests:
npm test - Run end-to-end tests:
npm run test:e2e - Manual Verification:
- Start the development server with
npm run dev. - Navigate to an invoice detail view and verify that the total is calculated dynamically and that the status dropdown works as intended.
- Check the invoice edit functionality at
/invoices/:id/editto confirm the form is pre-populated and updates are saved. - Verify that the sidebar correctly groups invoices and shows the open invoice count per client.
- Start the development server with
This merge request not only enhances the core functionality of the invoice management application but also improves overall code organization and testing coverage, laying a strong foundation for future features.
Next Steps
- Edit invoices
- create InvoiceAdd component. The component would support an optional
initialInvoiceprop and anisEditingflag. When in edit mode, the form is pre-populated with existing invoice data and, on submission, dispatches anEDIT_INVOICEaction.
- create InvoiceAdd component. The component would support an optional
- Increase unit test coverage
- Increase e2e coverage