brotherton-erpnext/erpnext/patches/v5_7/item_template_attributes.py
2015-09-10 18:10:15 +05:30

125 lines
4.0 KiB
Python

# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
import MySQLdb
def execute():
"""
Structure History:
1. Item and Item Variant
2. Item, Variant Attribute, Manage Variants and Manage Variant Items
3. Item, Item Variant Attribute, Item Attribute and Item Attribute Type (latest)
"""
rename_and_reload_doctypes()
variant_templates = frappe.get_all("Item", filters={"has_variants": 1}, limit_page_length=1)
if not variant_templates:
# database does not have items that have variants
# so no point in running the patch
return
variant_attributes = frappe.get_all("Item Variant Attribute", fields=["*"], limit_page_length=1)
if variant_attributes:
# manage variant patch is already applied
migrate_manage_variants()
else:
# old structure based on "Item Variant" table
try:
migrate_item_variants()
except MySQLdb.ProgrammingError:
print "`tabItem Variant` not found"
def rename_and_reload_doctypes():
if "tabVariant Attribute" in frappe.db.get_tables():
frappe.rename_doc("DocType", "Variant Attribute", "Item Variant Attribute")
frappe.reload_doctype("Item")
frappe.reload_doc("Stock", "DocType", "Item Variant Attribute")
frappe.reload_doc("Stock", "DocType", "Item Attribute Value")
frappe.reload_doc("Stock", "DocType", "Item Attribute")
def migrate_manage_variants():
item_attribute = {}
for d in frappe.db.sql("""select DISTINCT va.attribute, i.variant_of
from `tabItem Variant Attribute` va, `tabItem` i
where va.parent = i.name and ifnull(i.variant_of, '')!=''""", as_dict=1):
item_attribute.setdefault(d.variant_of, []).append({"attribute": d.attribute})
for item, attributes in item_attribute.items():
template = frappe.get_doc("Item", item)
template.set('attributes', attributes)
template.save()
# patch old style
def migrate_item_variants():
for item in frappe.get_all("Item", filters={"has_variants": 1}):
all_variants = frappe.get_all("Item", filters={"variant_of": item.name}, fields=["name", "description"])
item_attributes = frappe.db.sql("""select distinct item_attribute, item_attribute_value
from `tabItem Variant` where parent=%s""", item.name)
if not item_attributes and not all_variants:
item = frappe.get_doc("Item", item.name)
item.has_variants = 0
item.save()
continue
attribute_value_options = {}
for attribute, value in item_attributes:
attribute_value_options.setdefault(attribute, []).append(value)
possible_combinations = get_possible_combinations(attribute_value_options)
for variant in all_variants:
for combination in possible_combinations:
match = True
for attribute, value in combination.items():
if "{0}: {1}".format(attribute, value) not in variant.description:
match = False
break
if match:
# found the right variant
save_attributes_in_variant(variant, combination)
break
save_attributes_in_template(item, attribute_value_options)
frappe.delete_doc("DocType", "Item Variant")
def save_attributes_in_template(item, attribute_value_options):
# store attribute in Item Variant Attribute table for template
template = frappe.get_doc("Item", item)
template.set("attributes", [{"attribute": attribute} for attribute in attribute_value_options.keys()])
template.save()
def get_possible_combinations(attribute_value_options):
possible_combinations = []
for attribute, values in attribute_value_options.items():
if not possible_combinations:
for v in values:
possible_combinations.append({attribute: v})
else:
for v in values:
for combination in possible_combinations:
combination[attribute] = v
return possible_combinations
def save_attributes_in_variant(variant, combination):
# add data into attributes table
variant_item = frappe.get_doc("Item", variant.name)
variant_item.set("attributes", [])
for attribute, value in combination.items():
variant_item.append("attributes", {
"attribute": attribute,
"attribute_value": value
})
variant_item.save()