There is no tracked path for an existing InvoicePlane v1 user to move to v2 with their data — the single most important adoption route. #85/#141 cover generic CSV imports; #136 is a feature-parity checklist, not a tool. Nothing maps the v1 schema to v2.
Source-of-truth schema: v1 tables ip_clients, ip_invoices, ip_invoice_items, ip_invoice_amounts, ip_payments, ip_payment_methods, ip_quotes, ip_quote_items, ip_products, ip_tax_rates, ip_users, ip_projects, ip_tasks (see v1 application/modules/*/models/).
Specific
A guided Import from InvoicePlane v1 flow (admin panel) that accepts either a direct connection to a v1 MySQL database or a v1 SQL dump, and migrates into one target company: clients → relations (+contacts/addresses), invoices + items + amounts → invoices/invoice_items, payments + methods → payments, quotes + items → quotes/quote_items, products/families/units → products/categories/units, tax rates → tax_rates, projects/tasks → projects/tasks. Invoice numbers, dates, statuses, and balances are preserved; v1 statuses map to v2 enums.
Measurable
- A dry-run mode reports per-entity counts that will be migrated, plus unmappable rows.
- After migration, per-entity counts in v2 equal v1 source counts minus reported skips.
- Spot financial invariant: for every migrated invoice, v2 total/paid/balance equal v1
ip_invoice_amounts values.
- The run is recorded as an import batch and can be rolled back (import-history issue).
Achievable
A V1MigrationService per entity (Modules/Core/Services/Migration/) reading the v1 connection via a secondary DB connection; mapping tables for statuses and payment methods; wrapped in a queued job with progress notifications. Reuses BelongsToCompany auto-scoping by setting the target tenant.
Relevant
Every current v1 installation is a prospective v2 user; without this, "upgrade" means starting from zero. High-prio candidate alongside #85.
Time-Bound
Two sprints (one for clients/invoices/payments, one for quotes/products/projects + dry-run polish), after the CSV importer conventions exist.
Arrange
- A seeded v1 database (fixture SQL) with 3 clients, 5 invoices (mixed statuses incl. paid + overdue), 8 items, 4 payments, 2 quotes, 6 products, 2 tax rates, 1 project with 2 tasks.
- An empty v2 target company.
Act
- Run dry-run, then the real migration against the fixture.
Assert
There is no tracked path for an existing InvoicePlane v1 user to move to v2 with their data — the single most important adoption route. #85/#141 cover generic CSV imports; #136 is a feature-parity checklist, not a tool. Nothing maps the v1 schema to v2.
Source-of-truth schema: v1 tables
ip_clients,ip_invoices,ip_invoice_items,ip_invoice_amounts,ip_payments,ip_payment_methods,ip_quotes,ip_quote_items,ip_products,ip_tax_rates,ip_users,ip_projects,ip_tasks(see v1application/modules/*/models/).Specific
A guided Import from InvoicePlane v1 flow (admin panel) that accepts either a direct connection to a v1 MySQL database or a v1 SQL dump, and migrates into one target company: clients →
relations(+contacts/addresses), invoices + items + amounts →invoices/invoice_items, payments + methods →payments, quotes + items →quotes/quote_items, products/families/units →products/categories/units, tax rates →tax_rates, projects/tasks →projects/tasks. Invoice numbers, dates, statuses, and balances are preserved; v1 statuses map to v2 enums.Measurable
ip_invoice_amountsvalues.Achievable
A
V1MigrationServiceper entity (Modules/Core/Services/Migration/) reading the v1 connection via a secondary DB connection; mapping tables for statuses and payment methods; wrapped in a queued job with progress notifications. Reuses BelongsToCompany auto-scoping by setting the target tenant.Relevant
Every current v1 installation is a prospective v2 user; without this, "upgrade" means starting from zero. High-prio candidate alongside #85.
Time-Bound
Two sprints (one for clients/invoices/payments, one for quotes/products/projects + dry-run polish), after the CSV importer conventions exist.
Arrange
Act
Assert
total/paid/balancematchip_invoice_amountsper invoice; statuses map correctly.