329 lines
8.3 KiB
Markdown
329 lines
8.3 KiB
Markdown
# Migration Guide: Tax Template to Tax Type
|
|
|
|
## Overview
|
|
|
|
This guide explains how to migrate existing Purchase Invoices from the old `item_tax_template` system to the new `tax_type` field.
|
|
|
|
---
|
|
|
|
## Background
|
|
|
|
**Before:** Agricultural purchase invoices used `item_tax_template` field to determine tax rates:
|
|
- "ƏDV 0%" → 0% VAT
|
|
- "ƏDV-dən azadolma" → 0% VAT (exempt)
|
|
- "ƏDV 2% cəlb" → 5% tax
|
|
|
|
**After:** Agricultural purchase invoices now use `tax_type` field:
|
|
- "Tax Free" → 0% VAT
|
|
- "Taxable" → 5% tax
|
|
|
|
---
|
|
|
|
## Who Needs to Migrate?
|
|
|
|
You need to migrate if you have:
|
|
- Purchase Invoices with `agricultural_goods = True`
|
|
- Items with `item_tax_template` set
|
|
- Items with `tax_type` = None (empty)
|
|
|
|
---
|
|
|
|
## Migration Options
|
|
|
|
### Option 1: Manual Migration (Recommended for Few Documents)
|
|
|
|
For each Purchase Invoice:
|
|
|
|
1. Open the document in edit mode
|
|
2. Check if `agricultural_goods` is checked
|
|
3. For each item in the items table:
|
|
- Look at the old `item_tax_template` value
|
|
- Set new `tax_type` based on mapping:
|
|
- If template is "ƏDV 2% cəlb" → select **"Taxable"**
|
|
- If template is anything else → select **"Tax Free"**
|
|
4. Save the document
|
|
5. `agricultural_tax_amount` will calculate automatically
|
|
|
|
### Option 2: Bulk Migration Script (For Many Documents)
|
|
|
|
Run this script in bench console:
|
|
|
|
```python
|
|
import frappe
|
|
|
|
def migrate_tax_templates_to_tax_type():
|
|
"""
|
|
Migrate item_tax_template values to tax_type for agricultural invoices
|
|
|
|
Mapping:
|
|
- "ƏDV 2% cəlb" → "Taxable" (5% tax)
|
|
- All others → "Tax Free" (0% VAT)
|
|
"""
|
|
|
|
# Get all agricultural purchase invoices (exclude cancelled)
|
|
invoices = frappe.get_all(
|
|
"Purchase Invoice",
|
|
filters={
|
|
"agricultural_goods": 1,
|
|
"docstatus": ["<", 2] # Draft or Submitted
|
|
},
|
|
fields=["name", "docstatus"]
|
|
)
|
|
|
|
print(f"\nFound {len(invoices)} agricultural purchase invoices")
|
|
print("="*60)
|
|
|
|
migrated_count = 0
|
|
skipped_count = 0
|
|
|
|
for inv in invoices:
|
|
doc = frappe.get_doc("Purchase Invoice", inv.name)
|
|
modified = False
|
|
|
|
for item in doc.items:
|
|
# Skip if tax_type already set
|
|
if item.tax_type:
|
|
continue
|
|
|
|
# Only migrate if item_tax_template exists
|
|
if not item.item_tax_template:
|
|
continue
|
|
|
|
# Map template to tax_type
|
|
if item.item_tax_template == "ƏDV 2% cəlb":
|
|
item.tax_type = "Taxable"
|
|
# Calculate 5% tax
|
|
item.agricultural_tax_amount = item.amount * 0.05
|
|
else:
|
|
# ƏDV 0%, ƏDV-dən azadolma, etc.
|
|
item.tax_type = "Tax Free"
|
|
item.agricultural_tax_amount = 0
|
|
|
|
modified = True
|
|
|
|
if modified:
|
|
try:
|
|
# For submitted documents, allow update
|
|
if doc.docstatus == 1:
|
|
doc.flags.ignore_validate_update_after_submit = True
|
|
|
|
doc.save()
|
|
migrated_count += 1
|
|
print(f"✓ Migrated: {doc.name} ({len(doc.items)} items)")
|
|
|
|
except Exception as e:
|
|
print(f"✗ Error migrating {doc.name}: {str(e)}")
|
|
else:
|
|
skipped_count += 1
|
|
print(f"⊘ Skipped: {doc.name} (no items to migrate)")
|
|
|
|
print("="*60)
|
|
print(f"\nMigration Complete:")
|
|
print(f" - Migrated: {migrated_count}")
|
|
print(f" - Skipped: {skipped_count}")
|
|
print(f" - Total: {len(invoices)}")
|
|
print()
|
|
|
|
# Run the migration
|
|
migrate_tax_templates_to_tax_type()
|
|
```
|
|
|
|
**How to run:**
|
|
|
|
```bash
|
|
cd /home/frappe/frappe-bench
|
|
bench --site site1 console
|
|
|
|
# Paste the script above, then press Enter
|
|
```
|
|
|
|
---
|
|
|
|
## Migration Mapping Table
|
|
|
|
| Old Item Tax Template | New Tax Type | Tax Amount Calculation |
|
|
|-----------------------|--------------|------------------------|
|
|
| ƏDV 0% | Tax Free | 0% (no tax) |
|
|
| ƏDV-dən azadolma | Tax Free | 0% (no tax) |
|
|
| ƏDV 2% cəlb | Taxable | 5% of amount |
|
|
| (empty) | Tax Free | 0% (default) |
|
|
| Any other | Tax Free | 0% (safe default) |
|
|
|
|
---
|
|
|
|
## Pre-Migration Checklist
|
|
|
|
- [ ] Backup your database: `bench --site site1 backup`
|
|
- [ ] Test the migration script on a single document first
|
|
- [ ] Verify the mapping is correct for your use case
|
|
- [ ] Note: Cancelled documents (docstatus = 2) are NOT migrated
|
|
|
|
---
|
|
|
|
## Post-Migration Verification
|
|
|
|
After migration, verify:
|
|
|
|
1. **Check migrated documents:**
|
|
```python
|
|
import frappe
|
|
|
|
# Get sample migrated document
|
|
doc = frappe.get_doc("Purchase Invoice", "ACC-PINV-2026-XXXXX")
|
|
|
|
for item in doc.items:
|
|
print(f"Item: {item.item_code}")
|
|
print(f" Old: {item.item_tax_template}")
|
|
print(f" New: {item.tax_type}")
|
|
print(f" Tax: {item.agricultural_tax_amount}")
|
|
print()
|
|
```
|
|
|
|
2. **Check counts:**
|
|
```python
|
|
import frappe
|
|
|
|
# Count items with tax_type set
|
|
result = frappe.db.sql("""
|
|
SELECT
|
|
tax_type,
|
|
COUNT(*) as count
|
|
FROM `tabPurchase Invoice Item`
|
|
WHERE parent IN (
|
|
SELECT name
|
|
FROM `tabPurchase Invoice`
|
|
WHERE agricultural_goods = 1
|
|
AND docstatus < 2
|
|
)
|
|
GROUP BY tax_type
|
|
""", as_dict=True)
|
|
|
|
for row in result:
|
|
print(f"{row.tax_type or '(empty)'}: {row.count} items")
|
|
```
|
|
|
|
3. **Test E-Taxes sending:**
|
|
- Open a migrated Purchase Invoice
|
|
- Verify buttons are visible (if agricultural_goods = True)
|
|
- Try sending to E-Taxes
|
|
- Confirm payload is correct
|
|
|
|
---
|
|
|
|
## Rollback Plan
|
|
|
|
If migration causes issues, you can:
|
|
|
|
1. **Restore from backup:**
|
|
```bash
|
|
bench --site site1 restore /path/to/backup.sql.gz
|
|
```
|
|
|
|
2. **Clear tax_type manually:**
|
|
```python
|
|
import frappe
|
|
|
|
frappe.db.sql("""
|
|
UPDATE `tabPurchase Invoice Item`
|
|
SET tax_type = NULL, agricultural_tax_amount = 0
|
|
WHERE parent IN (
|
|
SELECT name
|
|
FROM `tabPurchase Invoice`
|
|
WHERE agricultural_goods = 1
|
|
)
|
|
""")
|
|
|
|
frappe.db.commit()
|
|
```
|
|
|
|
---
|
|
|
|
## FAQ
|
|
|
|
### Q: Will old documents still work without migration?
|
|
**A:** Yes, but:
|
|
- Buttons will be hidden if `agricultural_goods = False`
|
|
- You must manually set `tax_type` before sending to E-Taxes
|
|
- Validation will fail if `tax_type` is empty
|
|
|
|
### Q: Do I need to migrate cancelled documents?
|
|
**A:** No, cancelled documents (docstatus = 2) don't need migration.
|
|
|
|
### Q: What happens to the old `item_tax_template` field?
|
|
**A:** It's still there but no longer used by E-Taxes integration. You can keep it for reference.
|
|
|
|
### Q: Can I delete `item_tax_template` after migration?
|
|
**A:** No! Other parts of ERPNext may use it. Only the E-Taxes integration uses `tax_type`.
|
|
|
|
### Q: What if I have custom tax templates?
|
|
**A:** The migration script treats all templates except "ƏDV 2% cəlb" as "Tax Free". If you have custom templates with different rates, adjust the script accordingly.
|
|
|
|
---
|
|
|
|
## Support
|
|
|
|
If you encounter issues:
|
|
|
|
1. Check `IMPLEMENTATION_SUMMARY.md` for implementation details
|
|
2. Check logs: `bench --site site1 logs`
|
|
3. Review validation errors in the UI
|
|
4. Test with a new Purchase Invoice first
|
|
|
|
---
|
|
|
|
## Migration Timeline
|
|
|
|
**Recommended approach:**
|
|
|
|
1. **Week 1:** Test migration script on staging/development
|
|
2. **Week 2:** Migrate draft documents on production
|
|
3. **Week 3:** Migrate submitted documents on production
|
|
4. **Week 4:** Verify all E-Taxes integrations work correctly
|
|
|
|
**Note:** No deadline - you can migrate documents as needed. New documents will use the new fields automatically.
|
|
|
|
---
|
|
|
|
## Example Migration Session
|
|
|
|
```bash
|
|
# 1. Backup database
|
|
bench --site site1 backup
|
|
|
|
# 2. Run migration
|
|
bench --site site1 console
|
|
|
|
# 3. Paste migration script (see Option 2 above)
|
|
|
|
# 4. Verify results
|
|
# Sample output:
|
|
# Found 15 agricultural purchase invoices
|
|
# ============================================================
|
|
# ✓ Migrated: ACC-PINV-2026-00001 (3 items)
|
|
# ✓ Migrated: ACC-PINV-2026-00002 (5 items)
|
|
# ⊘ Skipped: ACC-PINV-2026-00003 (no items to migrate)
|
|
# ...
|
|
# ============================================================
|
|
# Migration Complete:
|
|
# - Migrated: 12
|
|
# - Skipped: 3
|
|
# - Total: 15
|
|
|
|
# 5. Clear cache
|
|
bench --site site1 clear-cache
|
|
|
|
# 6. Test in UI
|
|
# Open one of the migrated documents and verify tax_type is set
|
|
```
|
|
|
|
---
|
|
|
|
## Conclusion
|
|
|
|
✅ Migration is optional but recommended
|
|
✅ Old and new systems coexist
|
|
✅ No data loss - both fields are preserved
|
|
✅ Easy rollback via database backup
|
|
|
|
**For new documents:** Just use the new `tax_type` field - no migration needed!
|