Merge branch 'develop'
This commit is contained in:
commit
fa0adafa82
@ -1,2 +1,2 @@
|
||||
from __future__ import unicode_literals
|
||||
__version__ = '6.6.4'
|
||||
__version__ = '6.6.5'
|
||||
|
@ -147,6 +147,8 @@ class Account(Document):
|
||||
self.validate_warehouse(old_warehouse)
|
||||
if self.warehouse:
|
||||
self.validate_warehouse(self.warehouse)
|
||||
elif self.warehouse:
|
||||
self.warehouse = None
|
||||
|
||||
def validate_warehouse(self, warehouse):
|
||||
if frappe.db.get_value("Stock Ledger Entry", {"warehouse": warehouse}):
|
||||
|
@ -498,14 +498,17 @@ def get_default_bank_cash_account(company, voucher_type, mode_of_payment=None):
|
||||
if voucher_type=="Bank Entry":
|
||||
account = frappe.db.get_value("Company", company, "default_bank_account")
|
||||
if not account:
|
||||
account = frappe.db.get_value("Account", {"company": company, "account_type": "Bank", "is_group": 0})
|
||||
account = frappe.db.get_value("Account",
|
||||
{"company": company, "account_type": "Bank", "is_group": 0})
|
||||
elif voucher_type=="Cash Entry":
|
||||
account = frappe.db.get_value("Company", company, "default_cash_account")
|
||||
if not account:
|
||||
account = frappe.db.get_value("Account", {"company": company, "account_type": "Cash", "is_group": 0})
|
||||
account = frappe.db.get_value("Account",
|
||||
{"company": company, "account_type": "Cash", "is_group": 0})
|
||||
|
||||
if account:
|
||||
account_details = frappe.db.get_value("Account", account, ["account_currency", "account_type"], as_dict=1)
|
||||
account_details = frappe.db.get_value("Account", account,
|
||||
["account_currency", "account_type"], as_dict=1)
|
||||
return {
|
||||
"account": account,
|
||||
"balance": get_balance_on(account),
|
||||
@ -814,11 +817,19 @@ def get_account_balance_and_party_type(account, date, company, debit=None, credi
|
||||
return grid_values
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_exchange_rate(account, account_currency, company,
|
||||
def get_exchange_rate(account, account_currency=None, company=None,
|
||||
reference_type=None, reference_name=None, debit=None, credit=None, exchange_rate=None):
|
||||
from erpnext.setup.utils import get_exchange_rate
|
||||
account_details = frappe.db.get_value("Account", account,
|
||||
["account_type", "root_type", "account_currency", "company"], as_dict=1)
|
||||
|
||||
if not company:
|
||||
company = account_details.company
|
||||
|
||||
if not account_currency:
|
||||
account_currency = account_details.account_currency
|
||||
|
||||
company_currency = get_company_currency(company)
|
||||
account_details = frappe.db.get_value("Account", account, ["account_type", "root_type"], as_dict=1)
|
||||
|
||||
if account_currency != company_currency:
|
||||
if reference_type in ("Sales Invoice", "Purchase Invoice") and reference_name:
|
||||
|
@ -160,6 +160,9 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
||||
me.set_dynamic_labels();
|
||||
me.calculate_taxes_and_totals();
|
||||
if(callback_fn) callback_fn();
|
||||
frappe.after_ajax(function() {
|
||||
cur_frm.doc.__missing_values_set = false;
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -109,7 +109,8 @@ def get_party_details(party, party_type, args=None):
|
||||
def get_tax_template(posting_date, args):
|
||||
"""Get matching tax rule"""
|
||||
args = frappe._dict(args)
|
||||
conditions = []
|
||||
conditions = ["""(from_date is null or from_date = '' or from_date <= '{0}')
|
||||
and (to_date is null or to_date = '' or to_date >= '{0}')""".format(posting_date)]
|
||||
|
||||
for key, value in args.iteritems():
|
||||
if key in "use_for_shopping_cart":
|
||||
@ -117,16 +118,16 @@ def get_tax_template(posting_date, args):
|
||||
else:
|
||||
conditions.append("ifnull({0}, '') in ('', '{1}')".format(key, frappe.db.escape(cstr(value))))
|
||||
|
||||
matching = frappe.db.sql("""select * from `tabTax Rule`
|
||||
tax_rule = frappe.db.sql("""select * from `tabTax Rule`
|
||||
where {0}""".format(" and ".join(conditions)), as_dict = True)
|
||||
|
||||
if not matching:
|
||||
if not tax_rule:
|
||||
return None
|
||||
|
||||
for rule in matching:
|
||||
for rule in tax_rule:
|
||||
rule.no_of_keys_matched = 0
|
||||
for key in args:
|
||||
if rule.get(key): rule.no_of_keys_matched += 1
|
||||
|
||||
rule = sorted(matching, lambda b, a: cmp(a.no_of_keys_matched, b.no_of_keys_matched) or cmp(a.priority, b.priority))[0]
|
||||
rule = sorted(tax_rule, lambda b, a: cmp(a.no_of_keys_matched, b.no_of_keys_matched) or cmp(a.priority, b.priority))[0]
|
||||
return rule.sales_tax_template or rule.purchase_tax_template
|
||||
|
@ -209,13 +209,12 @@ erpnext.AccountsChart = Class.extend({
|
||||
{fieldtype:'Check', fieldname:'is_group', label:__('Is Group'),
|
||||
description: __('Further accounts can be made under Groups, but entries can be made against non-Groups')},
|
||||
{fieldtype:'Select', fieldname:'account_type', label:__('Account Type'),
|
||||
options: ['', 'Bank', 'Cash', 'Warehouse', 'Receivable', 'Payable',
|
||||
'Equity', 'Cost of Goods Sold', 'Fixed Asset', 'Expense Account',
|
||||
'Income Account', 'Tax', 'Chargeable', 'Temporary'].join('\n'),
|
||||
options: ['', 'Bank', 'Cash', 'Warehouse', 'Tax', 'Chargeable'].join('\n'),
|
||||
description: __("Optional. This setting will be used to filter in various transactions.") },
|
||||
{fieldtype:'Float', fieldname:'tax_rate', label:__('Tax Rate')},
|
||||
{fieldtype:'Link', fieldname:'warehouse', label:__('Warehouse'), options:"Warehouse"},
|
||||
{fieldtype:'Link', fieldname:'account_currency', label:__('Currency'), options:"Currency"}
|
||||
{fieldtype:'Link', fieldname:'account_currency', label:__('Currency'), options:"Currency",
|
||||
description: __("Optional. Sets company's default currency, if not specified.")}
|
||||
]
|
||||
})
|
||||
|
||||
|
@ -29,7 +29,7 @@ blogs.
|
||||
"""
|
||||
app_icon = "icon-th"
|
||||
app_color = "#e74c3c"
|
||||
app_version = "6.6.4"
|
||||
app_version = "6.6.5"
|
||||
github_link = "https://github.com/frappe/erpnext"
|
||||
|
||||
error_report_email = "support@erpnext.com"
|
||||
|
@ -18,24 +18,25 @@ erpnext.hr.ExpenseClaimController = frappe.ui.form.Controller.extend({
|
||||
jv.voucher_type = 'Bank Entry';
|
||||
jv.company = cur_frm.doc.company;
|
||||
jv.remark = 'Payment against Expense Claim: ' + cur_frm.doc.name;
|
||||
jv.fiscal_year = cur_frm.doc.fiscal_year;
|
||||
var expense = cur_frm.doc.expenses || [];
|
||||
for(var i = 0; i < expense.length; i++){
|
||||
var d1 = frappe.model.add_child(jv, 'Journal Entry Account', 'accounts');
|
||||
d1.debit = expense[i].sanctioned_amount;
|
||||
d1.account = expense[i].default_account;
|
||||
d1.debit_in_account_currency = expense[i].sanctioned_amount;
|
||||
d1.reference_type = cur_frm.doc.doctype;
|
||||
d1.reference_name = cur_frm.doc.name;
|
||||
}
|
||||
|
||||
// credit to bank
|
||||
var d1 = frappe.model.add_child(jv, 'Journal Entry Account', 'accounts');
|
||||
d1.credit = cur_frm.doc.total_sanctioned_amount;
|
||||
d1.credit_in_account_currency = cur_frm.doc.total_sanctioned_amount;
|
||||
d1.reference_type = cur_frm.doc.doctype;
|
||||
d1.reference_name = cur_frm.doc.name;
|
||||
if(r.message) {
|
||||
d1.account = r.message.account;
|
||||
d1.balance = r.message.balance;
|
||||
d1.account_currency = r.message.account_currency;
|
||||
d1.account_type = r.message.account_type;
|
||||
}
|
||||
|
||||
loaddoc('Journal Entry', jv.name);
|
||||
|
@ -22,11 +22,16 @@ erpnext.utils.get_party_details = function(frm, method, args, callback) {
|
||||
}
|
||||
|
||||
if (args) {
|
||||
args.posting_date = frm.doc.transaction_date;
|
||||
args.posting_date = frm.doc.posting_date || frm.doc.transaction_date;
|
||||
}
|
||||
}
|
||||
if(!args) return;
|
||||
|
||||
if(frappe.meta.get_docfield(frm.doc.doctype, "taxes")) {
|
||||
if(!erpnext.utils.validate_mandatory(frm, "Posting/Transaction Date",
|
||||
args.posting_date, args.party_type=="Customer" ? "customer": "supplier")) return;
|
||||
}
|
||||
|
||||
args.currency = frm.doc.currency;
|
||||
args.company = frm.doc.company;
|
||||
args.doctype = frm.doc.doctype;
|
||||
@ -64,6 +69,15 @@ erpnext.utils.get_address_display = function(frm, address_field, display_field)
|
||||
if(r.message){
|
||||
frm.set_value(display_field, r.message)
|
||||
}
|
||||
|
||||
if(frappe.meta.get_docfield(frm.doc.doctype, "taxes")) {
|
||||
if(!erpnext.utils.validate_mandatory(frm, "Customer/Supplier",
|
||||
frm.doc.customer || frm.doc.supplier, address_field)) return;
|
||||
|
||||
if(!erpnext.utils.validate_mandatory(frm, "Posting/Transaction Date",
|
||||
frm.doc.posting_date || frm.doc.transaction_date, address_field)) return;
|
||||
} else return;
|
||||
|
||||
frappe.call({
|
||||
method: "erpnext.accounts.party.set_taxes",
|
||||
args: {
|
||||
@ -99,3 +113,13 @@ erpnext.utils.get_contact_details = function(frm) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
erpnext.utils.validate_mandatory = function(frm, label, value, trigger_on) {
|
||||
if(!value) {
|
||||
frm.doc[trigger_on] = "";
|
||||
refresh_field(trigger_on);
|
||||
frappe.msgprint(__("Please enter {0} first", [label]));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
@ -22,7 +22,9 @@ def delete_company_transactions(company_name):
|
||||
|
||||
for doctype in frappe.db.sql_list("""select parent from
|
||||
tabDocField where fieldtype='Link' and options='Company'"""):
|
||||
if doctype not in ("Account", "Cost Center", "Warehouse", "Budget Detail", "Party Account", "Employee"):
|
||||
if doctype not in ("Account", "Cost Center", "Warehouse", "Budget Detail",
|
||||
"Party Account", "Employee", "Sales Taxes and Charges Template",
|
||||
"Purchase Taxes and Charges Template", "POS Profile"):
|
||||
delete_for_doctype(doctype, company_name)
|
||||
|
||||
# Clear notification counts
|
||||
|
@ -139,7 +139,7 @@ class EmailDigest(Document):
|
||||
|
||||
for i, e in enumerate(events):
|
||||
e.starts_on_label = format_time(e.starts_on)
|
||||
e.ends_on_label = format_time(e.ends_on)
|
||||
e.ends_on_label = format_time(e.ends_on) if e.ends_on else None
|
||||
e.date = formatdate(e.starts)
|
||||
e.link = get_url_to_form("Event", e.name)
|
||||
|
||||
@ -346,7 +346,7 @@ class EmailDigest(Document):
|
||||
self.get_next_sending()
|
||||
|
||||
def fmt_money(self, value):
|
||||
return fmt_money(value, currency = self.currency)
|
||||
return fmt_money(abs(value), currency = self.currency)
|
||||
|
||||
def send():
|
||||
now_date = now_datetime().date()
|
||||
|
@ -52,6 +52,8 @@
|
||||
<span style="{{ label_css }}">
|
||||
{% if e.all_day %}
|
||||
{{ _("All Day") }}
|
||||
{% elif (not e.ends_on_label or e.starts_on_label == e.ends_on_label)%}
|
||||
{{ e.starts_on_label }}
|
||||
{% else %}
|
||||
{{ e.starts_on_label }} - {{ e.ends_on_label }}
|
||||
{% endif %}
|
||||
|
@ -735,7 +735,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Warehouse",
|
||||
"label": "From Warehouse",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "warehouse",
|
||||
"oldfieldtype": "Link",
|
||||
@ -755,13 +755,15 @@
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"depends_on": "",
|
||||
"description": "",
|
||||
"fieldname": "target_warehouse",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Target Warehouse",
|
||||
"label": "To Warehouse (Optional)",
|
||||
"no_copy": 0,
|
||||
"options": "Warehouse",
|
||||
"permlevel": 0,
|
||||
@ -831,7 +833,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Available Qty at Warehouse",
|
||||
"label": "Available Qty at From Warehouse",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "actual_qty",
|
||||
"oldfieldtype": "Currency",
|
||||
@ -857,7 +859,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Available Batch Qty at Warehouse",
|
||||
"label": "Available Batch Qty at From Warehouse",
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
@ -1160,7 +1162,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2015-10-19 03:04:50.887288",
|
||||
"modified": "2015-10-26 02:19:18.053222",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Delivery Note Item",
|
||||
|
@ -5,6 +5,7 @@ from __future__ import unicode_literals
|
||||
import frappe
|
||||
import json
|
||||
import urllib
|
||||
import itertools
|
||||
from frappe import msgprint, _
|
||||
from frappe.utils import cstr, flt, cint, getdate, now_datetime, formatdate
|
||||
from frappe.website.website_generator import WebsiteGenerator
|
||||
@ -130,6 +131,8 @@ class Item(WebsiteGenerator):
|
||||
|
||||
self.set_attribute_context(context)
|
||||
|
||||
self.set_disabled_attributes(context)
|
||||
|
||||
context.parents = self.get_parents(context)
|
||||
|
||||
return context
|
||||
@ -189,6 +192,11 @@ class Item(WebsiteGenerator):
|
||||
for attr in self.attributes:
|
||||
values = context.attribute_values.setdefault(attr.attribute, [])
|
||||
|
||||
if cint(frappe.db.get_value("Item Attribute", attr.attribute, "numeric_values")):
|
||||
for val in sorted(attribute_values_available.get(attr.attribute, []), key=flt):
|
||||
values.append(val)
|
||||
|
||||
else:
|
||||
# get list of values defined (for sequence)
|
||||
for attr_value in frappe.db.get_all("Item Attribute Value",
|
||||
fields=["attribute_value"], filters={"parent": attr.attribute}, order_by="idx asc"):
|
||||
@ -198,6 +206,49 @@ class Item(WebsiteGenerator):
|
||||
|
||||
context.variant_info = json.dumps(context.variants)
|
||||
|
||||
def set_disabled_attributes(self, context):
|
||||
"""Disable selection options of attribute combinations that do not result in a variant"""
|
||||
if not self.attributes:
|
||||
return
|
||||
|
||||
context.disabled_attributes = {}
|
||||
attributes = [attr.attribute for attr in self.attributes]
|
||||
|
||||
def find_variant(combination):
|
||||
for variant in context.variants:
|
||||
if len(variant.attributes) < len(attributes):
|
||||
continue
|
||||
|
||||
if "combination" not in variant:
|
||||
ref_combination = []
|
||||
|
||||
for attr in variant.attributes:
|
||||
idx = attributes.index(attr.attribute)
|
||||
ref_combination.insert(idx, attr.attribute_value)
|
||||
|
||||
variant["combination"] = ref_combination
|
||||
|
||||
if not (set(combination) - set(variant["combination"])):
|
||||
# check if the combination is a subset of a variant combination
|
||||
# eg. [Blue, 0.5] is a possible combination if exists [Blue, Large, 0.5]
|
||||
return True
|
||||
|
||||
for i, attr in enumerate(self.attributes):
|
||||
if i==0:
|
||||
continue
|
||||
|
||||
combination_source = []
|
||||
|
||||
# loop through previous attributes
|
||||
for prev_attr in self.attributes[:i]:
|
||||
combination_source.append([context.selected_attributes[prev_attr.attribute]])
|
||||
|
||||
combination_source.append(context.attribute_values[attr.attribute])
|
||||
|
||||
for combination in itertools.product(*combination_source):
|
||||
if not find_variant(combination):
|
||||
context.disabled_attributes.setdefault(attr.attribute, []).append(combination[-1])
|
||||
|
||||
def check_warehouse_is_set_for_stock_item(self):
|
||||
if self.is_stock_item==1 and not self.default_warehouse and frappe.get_all("Warehouse"):
|
||||
frappe.msgprint(_("Default Warehouse is mandatory for stock Item."),
|
||||
|
@ -155,7 +155,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Warehouse",
|
||||
"label": "From Warehouse",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "warehouse",
|
||||
"oldfieldtype": "Link",
|
||||
@ -179,7 +179,7 @@
|
||||
"ignore_user_permissions": 0,
|
||||
"in_filter": 0,
|
||||
"in_list_view": 0,
|
||||
"label": "Target Warehouse",
|
||||
"label": "To Warehouse (Optional)",
|
||||
"no_copy": 0,
|
||||
"options": "Warehouse",
|
||||
"permlevel": 0,
|
||||
@ -511,7 +511,7 @@
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"modified": "2015-10-12 07:38:58.896987",
|
||||
"modified": "2015-10-26 02:25:47.718911",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Packed Item",
|
||||
|
@ -4,6 +4,7 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import flt, today
|
||||
|
||||
def execute(filters=None):
|
||||
filters = frappe._dict(filters or {})
|
||||
@ -18,12 +19,19 @@ def get_columns():
|
||||
_("Shortage Qty") + ":Float:100"]
|
||||
|
||||
def get_data(filters):
|
||||
item_map = {}
|
||||
bin_list = get_bin_list(filters)
|
||||
item_map = get_item_map(filters.get("item_code"))
|
||||
warehouse_company = {}
|
||||
data = []
|
||||
|
||||
for bin in get_bin_list(filters):
|
||||
item = item_map.setdefault(bin.item_code, frappe.get_doc("Item", bin.item_code))
|
||||
for bin in bin_list:
|
||||
item = item_map.get(bin.item_code)
|
||||
|
||||
if not item:
|
||||
# likely an item that has reached its end of life
|
||||
continue
|
||||
|
||||
# item = item_map.setdefault(bin.item_code, get_item(bin.item_code))
|
||||
company = warehouse_company.setdefault(bin.warehouse, frappe.db.get_value("Warehouse", bin.warehouse, "company"))
|
||||
|
||||
if filters.brand and filters.brand != item.brand:
|
||||
@ -45,7 +53,7 @@ def get_data(filters):
|
||||
|
||||
data.append([item.name, item.item_name, item.description, item.item_group, item.brand, bin.warehouse,
|
||||
item.stock_uom, bin.actual_qty, bin.planned_qty, bin.indented_qty, bin.ordered_qty, bin.reserved_qty,
|
||||
bin.projected_qty, re_order_level, re_order_qty, re_order_level - bin.projected_qty])
|
||||
bin.projected_qty, re_order_level, re_order_qty, re_order_level - flt(bin.projected_qty)])
|
||||
|
||||
return data
|
||||
|
||||
@ -61,3 +69,35 @@ def get_bin_list(filters):
|
||||
filters=bin_filters, order_by="item_code, warehouse")
|
||||
|
||||
return bin_list
|
||||
|
||||
def get_item_map(item_code):
|
||||
"""Optimization: get only the item doc and re_order_levels table"""
|
||||
|
||||
condition = ""
|
||||
if item_code:
|
||||
condition = 'and item_code = "{0}"'.format(frappe.db.escape(item_code))
|
||||
|
||||
items = frappe.db.sql("""select * from `tabItem` item
|
||||
where is_stock_item = 1
|
||||
{condition}
|
||||
and (end_of_life > %(today)s or end_of_life is null or end_of_life='0000-00-00')
|
||||
and exists (select name from `tabBin` bin where bin.item_code=item.name)"""\
|
||||
.format(condition=condition), {"today": today()}, as_dict=True)
|
||||
|
||||
condition = ""
|
||||
if item_code:
|
||||
condition = 'where parent="{0}"'.format(frappe.db.escape(item_code))
|
||||
|
||||
reorder_levels = frappe._dict()
|
||||
for ir in frappe.db.sql("""select * from `tabItem Reorder` {condition}""".format(condition=condition), as_dict=1):
|
||||
if ir.parent not in reorder_levels:
|
||||
reorder_levels[ir.parent] = []
|
||||
|
||||
reorder_levels[ir.parent].append(ir)
|
||||
|
||||
item_map = frappe._dict()
|
||||
for item in items:
|
||||
item["reorder_levels"] = reorder_levels.get(item.name) or []
|
||||
item_map[item.name] = item
|
||||
|
||||
return item_map
|
||||
|
@ -29,7 +29,8 @@
|
||||
<div class="item-attribute-selectors">
|
||||
{% if has_variants %}
|
||||
{% for d in attributes %}
|
||||
<div class="item-view-attribute"
|
||||
{% if attribute_values[d.attribute] -%}
|
||||
<div class="item-view-attribute {% if (attribute_values[d.attribute] | len)==1 -%} hidden {%- endif %}"
|
||||
style="margin-bottom: 10px;">
|
||||
<h6 class="text-muted">{{ _(d.attribute) }}</h6>
|
||||
<select class="form-control"
|
||||
@ -37,12 +38,17 @@
|
||||
data-attribute="{{ d.attribute }}">
|
||||
{% for value in attribute_values[d.attribute] %}
|
||||
<option value="{{ value }}"
|
||||
{% if selected_attributes and selected_attributes[d.attribute]==value -%} selected {%- endif %}>
|
||||
{% if selected_attributes and selected_attributes[d.attribute]==value -%}
|
||||
selected
|
||||
{%- elif disabled_attributes and value in disabled_attributes.get(d.attribute, []) -%}
|
||||
disabled
|
||||
{%- endif %}>
|
||||
{{ _(value) }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
{%- endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
@ -64,8 +64,23 @@ frappe.ready(function() {
|
||||
});
|
||||
});
|
||||
|
||||
$("[itemscope] .item-view-attribute select").on("change", function() {
|
||||
$("[itemscope] .item-view-attribute .form-control").on("change", function() {
|
||||
try {
|
||||
var item_code = encodeURIComponent(get_item_code());
|
||||
} catch(e) {
|
||||
// unable to find variant
|
||||
// then chose the closest available one
|
||||
|
||||
var attribute = $(this).attr("data-attribute");
|
||||
var attribute_value = $(this).val()
|
||||
var item_code = update_attribute_selectors(attribute, attribute_value);
|
||||
|
||||
if (!item_code) {
|
||||
msgprint(__("Please select some other value for {0}", [attribute]))
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
if (window.location.search.indexOf(item_code)!==-1) {
|
||||
return;
|
||||
}
|
||||
@ -83,10 +98,8 @@ var toggle_update_cart = function(qty) {
|
||||
|
||||
function get_item_code() {
|
||||
if(window.variant_info) {
|
||||
attributes = {};
|
||||
$('[itemscope]').find(".item-view-attribute select").each(function() {
|
||||
attributes[$(this).attr('data-attribute')] = $(this).val();
|
||||
});
|
||||
var attributes = get_selected_attributes();
|
||||
|
||||
for(var i in variant_info) {
|
||||
var variant = variant_info[i];
|
||||
var match = true;
|
||||
@ -106,3 +119,51 @@ function get_item_code() {
|
||||
return item_code;
|
||||
}
|
||||
}
|
||||
|
||||
function update_attribute_selectors(selected_attribute, selected_attribute_value) {
|
||||
// find the closest match keeping the selected attribute in focus and get the item code
|
||||
|
||||
var attributes = get_selected_attributes();
|
||||
|
||||
var previous_match_score = 0;
|
||||
var matched;
|
||||
for(var i in variant_info) {
|
||||
var variant = variant_info[i];
|
||||
var match_score = 0;
|
||||
var has_selected_attribute = false;
|
||||
|
||||
for(var j in variant.attributes) {
|
||||
if(attributes[variant.attributes[j].attribute]===variant.attributes[j].attribute_value) {
|
||||
match_score = match_score + 1;
|
||||
|
||||
if (variant.attributes[j].attribute==selected_attribute && variant.attributes[j].attribute_value==selected_attribute_value) {
|
||||
has_selected_attribute = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (has_selected_attribute && (match_score > previous_match_score)) {
|
||||
previous_match_score = match_score;
|
||||
matched = variant;
|
||||
}
|
||||
}
|
||||
|
||||
if (matched) {
|
||||
for (var j in matched.attributes) {
|
||||
var attr = matched.attributes[j];
|
||||
$('[itemscope]')
|
||||
.find(repl('.item-view-attribute .form-control[data-attribute="%(attribute)s"]', attr))
|
||||
.val(attr.attribute_value);
|
||||
}
|
||||
|
||||
return matched.name;
|
||||
}
|
||||
}
|
||||
|
||||
function get_selected_attributes() {
|
||||
var attributes = {};
|
||||
$('[itemscope]').find(".item-view-attribute .form-control").each(function() {
|
||||
attributes[$(this).attr('data-attribute')] = $(this).val();
|
||||
});
|
||||
return attributes;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user