Legacy Order Import Strategy
Overview
This document outlines the strategy for importing historical orders from the legacy system into the new Rails application.
Current System Mapping
Legacy Order Fields → New Order Fields
| Legacy Field |
New Field |
Notes |
| order_id |
order_number |
Keep original ID for reference |
| status |
status |
Map statuses (see below) |
| customer_id |
company_id/contact_id |
Lookup migrated customer |
| firstname/lastname |
contact |
Create/lookup contact |
| vendor_id |
vendor_id |
Match by legacy vendor mapping |
| product/product_id |
product_id |
Match by name or create mapping |
| dropofftime |
delivery_date |
Convert timestamp to date |
| pickuptime |
pickup_date |
Calculate rental_days |
| address/city/state/zip |
delivery_address, etc |
Direct mapping |
| notes |
notes |
Customer-visible notes |
| vendor_dropoff_notes |
internal_notes |
Vendor instructions |
| price |
base_price |
Rental price |
| cost |
vendor_base_cost |
Vendor cost |
| total_amount |
total_amount |
Total after tax |
| paymentmethod |
payment_method |
Map payment methods |
| ponum |
payment_terms note |
PO number reference |
| billing* fields |
billing_* fields |
Billing address info |
Status Mapping
| Legacy Status |
New Status |
Invoice? |
| pending |
pending |
No |
| confirmed |
confirmed |
No |
| delivered |
active |
No |
| active |
active |
No |
| completed |
completed |
Yes |
| cancelled |
cancelled |
No |
Payment Method Mapping
| Legacy |
New |
Notes |
| cc, credit_card |
credit_card |
|
| po, purchase_order |
purchase_order |
|
| cash |
purchase_order |
Convert to PO with notes |
| check |
purchase_order |
Convert to PO with notes |
Import Process
Phase 1: Pre-Import Validation
- Verify all vendors exist in new system
- Create vendor mapping table (legacy_id → new_id)
- Create product mapping table
- Verify customers have been imported
- Generate import report showing:
- Total orders to import
- Orders by status
- Unmapped vendors/products
- Date range coverage
Phase 2: Test Import (Dry Run)
- Import 10-20 sample orders
- Validate data integrity
- Check calculations (totals, dates)
- Verify vendor/customer relationships
- Review unmapped fields
Phase 3: Batch Import
- Import orders in batches of 100
- Skip orders with errors (log for review)
- Track progress with counters
- Generate detailed log file
Phase 4: Post-Import Tasks
- Generate uninvoiced orders report
- Review orders needing attention
- Create invoices for completed orders
- Reconcile totals with legacy system
Import Options
Option 1: Import All Historical Data
- Pros: Complete historical record
- Cons: May include irrelevant old data
- Recommendation: Filter by date (e.g., last 2 years)
Option 2: Import Only Uninvoiced Orders
- Pros: Focused on actionable data
- Cons: Loses historical context
- Recommendation: Best for immediate billing needs
Option 3: Import Active + Uninvoiced
- Pros: Current rental status + billing needs
- Cons: Missing completed history
- Recommendation: Good middle ground
Data Mapping Tables
We'll create these reference tables to maintain mappings:
# In new system - track legacy mappings
Order.add_columns:
- legacy_order_id (integer)
- imported_at (datetime)
- import_notes (text)
# Vendor mapping (in import task)
@vendor_mapping = {
legacy_vendor_id => new_vendor_id,
# Populated during import
}
# Product mapping (by name matching)
@product_mapping = {
"20 Yard Dumpster" => Product.find_by(name: "20 Yard Dumpster")&.id,
# Etc.
}
Handling Edge Cases
Missing Vendors
- Create "Legacy Vendor - [Name]" placeholder
- Flag for manual review
- Associate orders with placeholder
Missing Products
- Create generic product "Legacy Product - [Name]"
- Use pricing from legacy order
- Flag for mapping review
Invalid Addresses
- Import as-is with validation errors
- Flag for manual cleanup
- Still allows order to be invoiced
Payment Data
- DO NOT import credit card numbers
- Import only last 4 digits if needed for reference
- PO numbers safe to import
Invoice Generation Strategy
After import, for uninvoiced orders:
-
Group by Customer + Time Period
- Monthly grouping for recurring items
- Individual invoices for one-time orders
-
Review Before Invoicing
- Validate pricing
- Confirm customer details
- Check for duplicates
-
Generate Drafts First
- All invoices as "draft" status
- Manual review and send
- Prevents accidental billing
Running the Import
# Test connection
bin/rails legacy:test
# View statistics
bin/rails legacy:stats
# Import customers first (if not done)
bin/rails legacy:import_customers
# Preview order import
bin/rails legacy:preview_order_import[2024-01-01,2025-12-31]
# Import orders (dry run)
bin/rails legacy:import_orders[2024-01-01,2025-12-31,true]
# Actual import
bin/rails legacy:import_orders[2024-01-01,2025-12-31,false]
# Generate uninvoiced report
bin/rails legacy:uninvoiced_orders_report
Success Metrics
- [ ] All vendors mapped
- [ ] All products mapped
- [ ] 95%+ orders imported successfully
- [ ] All customer relationships preserved
- [ ] Uninvoiced orders identified
- [ ] Draft invoices created for review
- [ ] No data loss vs legacy system
Rollback Plan
If import fails or has issues:
- All imported orders have
legacy_order_id field
- Can delete with:
Order.where.not(legacy_order_id: nil).delete_all
- Re-run import with fixes
- Incremental import possible (skip existing)