Skip to content

[Core]: Data migration from InvoicePlane v1 (guided importer) #678

Description

@nielsdrost7

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

  • Dry-run counts match the fixture exactly and no rows are written.
  • All entity counts in v2 match the fixture after migration.
  • Invoice total/paid/balance match ip_invoice_amounts per invoice; statuses map correctly.
  • Client contact data (email/phone/address) lands on relation + contact/address models.
  • Re-running the migration is idempotent (no duplicates) or blocked with a clear message.
  • PHPUnit feature tests cover dry-run, full run, financial invariants, idempotency.

Metadata

Metadata

Assignees

No one assigned

    Labels

    high-priorefinedRefined with SMART plan / test suggestions

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions