mirror of
https://github.com/inventree/InvenTree.git
synced 2025-04-29 20:16:44 +00:00
Add custom migration for the part_supplierpricebreak model
- Copies across existing pricing data - Yikes
This commit is contained in:
parent
e4f2eecb3b
commit
83582ae87f
@ -13,6 +13,7 @@ from django.db import models
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
import djmoney.settings
|
import djmoney.settings
|
||||||
|
from djmoney.models.fields import MoneyField
|
||||||
|
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
from django.core.validators import MinValueValidator, MaxValueValidator
|
from django.core.validators import MinValueValidator, MaxValueValidator
|
||||||
@ -536,6 +537,15 @@ class PriceBreak(models.Model):
|
|||||||
|
|
||||||
currency = models.ForeignKey(Currency, blank=True, null=True, on_delete=models.SET_NULL)
|
currency = models.ForeignKey(Currency, blank=True, null=True, on_delete=models.SET_NULL)
|
||||||
|
|
||||||
|
price = MoneyField(
|
||||||
|
max_digits=19,
|
||||||
|
decimal_places=4,
|
||||||
|
default_currency='USD',
|
||||||
|
null=True,
|
||||||
|
verbose_name=_('Price'),
|
||||||
|
help_text=_('Unit price at specified quantity'),
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def symbol(self):
|
def symbol(self):
|
||||||
return self.currency.symbol if self.currency else ''
|
return self.currency.symbol if self.currency else ''
|
||||||
|
24
InvenTree/company/migrations/0025_auto_20201110_1001.py
Normal file
24
InvenTree/company/migrations/0025_auto_20201110_1001.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Generated by Django 3.0.7 on 2020-11-10 10:01
|
||||||
|
|
||||||
|
from django.db import migrations, connection
|
||||||
|
import djmoney.models.fields
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('company', '0024_unique_name_email_constraint'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='supplierpricebreak',
|
||||||
|
name='price',
|
||||||
|
field=djmoney.models.fields.MoneyField(decimal_places=4, default_currency='USD', help_text='Unit price at specified quantity', max_digits=19, null=True, verbose_name='Price'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='supplierpricebreak',
|
||||||
|
name='price_currency',
|
||||||
|
field=djmoney.models.fields.CurrencyField(choices=[('AUD', 'Australian Dollar'), ('CAD', 'Canadian Dollar'), ('EUR', 'Euro'), ('NZD', 'New Zealand Dollar'), ('GBP', 'Pound Sterling'), ('USD', 'US Dollar'), ('JPY', 'Yen')], default='USD', editable=False, max_length=3),
|
||||||
|
),
|
||||||
|
]
|
141
InvenTree/company/migrations/0026_auto_20201110_1011.py
Normal file
141
InvenTree/company/migrations/0026_auto_20201110_1011.py
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
# Generated by Django 3.0.7 on 2020-11-10 10:11
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from moneyed import CURRENCIES
|
||||||
|
from django.db import migrations, connection
|
||||||
|
from company.models import SupplierPriceBreak
|
||||||
|
|
||||||
|
|
||||||
|
def migrate_currencies(apps, schema_editor):
|
||||||
|
"""
|
||||||
|
Migrate from the 'old' method of handling currencies,
|
||||||
|
to the new method which uses the django-money library.
|
||||||
|
|
||||||
|
Previously, we created a custom Currency model,
|
||||||
|
which was very simplistic.
|
||||||
|
|
||||||
|
Here we will attempt to map each existing "currency" reference
|
||||||
|
for the SupplierPriceBreak model, to a new django-money compatible currency.
|
||||||
|
"""
|
||||||
|
|
||||||
|
print("Updating currency references for SupplierPriceBreak model...")
|
||||||
|
|
||||||
|
# A list of available currency codes
|
||||||
|
currency_codes = CURRENCIES.keys()
|
||||||
|
|
||||||
|
cursor = connection.cursor()
|
||||||
|
|
||||||
|
# The 'suffix' field denotes the currency code
|
||||||
|
response = cursor.execute('SELECT id, suffix, description from common_currency;').fetchall()
|
||||||
|
|
||||||
|
remap = {}
|
||||||
|
|
||||||
|
for index, row in enumerate(response):
|
||||||
|
pk, suffix, description = row
|
||||||
|
|
||||||
|
suffix = suffix.strip().upper()
|
||||||
|
|
||||||
|
if suffix not in currency_codes:
|
||||||
|
print("Missing suffix:", suffix)
|
||||||
|
|
||||||
|
while suffix not in currency_codes:
|
||||||
|
# Ask the user to input a valid currency
|
||||||
|
print(f"Could not find a valid currency matching '{suffix}'.")
|
||||||
|
print("Please enter a valid currency code")
|
||||||
|
suffix = str(input("> ")).strip()
|
||||||
|
|
||||||
|
if pk not in remap.keys():
|
||||||
|
remap[pk] = suffix
|
||||||
|
|
||||||
|
# Now iterate through each SupplierPriceBreak and update the rows
|
||||||
|
response = cursor.execute('SELECT id, cost, currency_id, price, price_currency from part_supplierpricebreak;').fetchall()
|
||||||
|
|
||||||
|
count = 0
|
||||||
|
|
||||||
|
for index, row in enumerate(response):
|
||||||
|
pk, cost, currency_id, price, price_currency = row
|
||||||
|
|
||||||
|
# Copy the 'cost' field across to the 'price' field
|
||||||
|
response = cursor.execute(f'UPDATE part_supplierpricebreak set price={cost} where id={pk};')
|
||||||
|
|
||||||
|
# Extract the updated currency code
|
||||||
|
currency_code = remap.get(currency_id, 'USD')
|
||||||
|
|
||||||
|
# Update the currency code
|
||||||
|
response = cursor.execute(f'UPDATE part_supplierpricebreak set price_currency= "{currency_code}" where id={pk};')
|
||||||
|
|
||||||
|
count += 1
|
||||||
|
|
||||||
|
print(f"Updated {count} SupplierPriceBreak rows")
|
||||||
|
|
||||||
|
def reverse_currencies(apps, schema_editor):
|
||||||
|
"""
|
||||||
|
Reverse the "update" process.
|
||||||
|
|
||||||
|
Here we may be in the situation that the legacy "Currency" table is empty,
|
||||||
|
and so we have to re-populate it based on the new price_currency codes.
|
||||||
|
"""
|
||||||
|
|
||||||
|
print("Reversing currency migration...")
|
||||||
|
|
||||||
|
cursor = connection.cursor()
|
||||||
|
|
||||||
|
# Extract a list of currency codes which are in use
|
||||||
|
response = cursor.execute(f'SELECT id, price, price_currency from part_supplierpricebreak;').fetchall()
|
||||||
|
|
||||||
|
codes_in_use = set()
|
||||||
|
|
||||||
|
for index, row in enumerate(response):
|
||||||
|
pk, price, code = row
|
||||||
|
|
||||||
|
codes_in_use.add(code)
|
||||||
|
|
||||||
|
# Copy the 'price' field back into the 'cost' field
|
||||||
|
response = cursor.execute(f'UPDATE part_supplierpricebreak set cost={price} where id={pk};')
|
||||||
|
|
||||||
|
# Keep a dict of which currency objects map to which code
|
||||||
|
code_map = {}
|
||||||
|
|
||||||
|
# For each currency code in use, check if we have a matching Currency object
|
||||||
|
for code in codes_in_use:
|
||||||
|
response = cursor.execute(f'SELECT id, suffix from common_currency where suffix="{code}";')
|
||||||
|
row = response.fetchone()
|
||||||
|
|
||||||
|
if row is not None:
|
||||||
|
# A match exists!
|
||||||
|
pk, suffix = row
|
||||||
|
code_map[suffix] = pk
|
||||||
|
else:
|
||||||
|
# No currency object exists!
|
||||||
|
description = CURRENCIES[code]
|
||||||
|
|
||||||
|
# Create a new object in the database
|
||||||
|
print(f"Creating new Currency object for {code}")
|
||||||
|
|
||||||
|
# Construct a query to create a new Currency object
|
||||||
|
query = f'INSERT into common_currency (symbol, suffix, description, value, base) VALUES ("$", "{code}", "{description}", 1.0, False);'
|
||||||
|
|
||||||
|
response = cursor.execute(query)
|
||||||
|
|
||||||
|
code_map[code] = cursor.lastrowid
|
||||||
|
|
||||||
|
# Ok, now we know how each suffix maps to a Currency object
|
||||||
|
for suffix in code_map.keys():
|
||||||
|
pk = code_map[suffix]
|
||||||
|
|
||||||
|
# Update the table to point to the Currency objects
|
||||||
|
print(f"Currency {suffix} -> pk {pk}")
|
||||||
|
|
||||||
|
response = cursor.execute(f'UPDATE part_supplierpricebreak set currency_id={pk} where price_currency="{suffix}";')
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('company', '0025_auto_20201110_1001'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RunPython(migrate_currencies, reverse_code=reverse_currencies),
|
||||||
|
]
|
Loading…
x
Reference in New Issue
Block a user