Fixed merge conflict

This commit is contained in:
Nabin Hait 2017-05-24 18:39:16 +05:30
commit c795386230
21 changed files with 103 additions and 444 deletions

View File

@ -2,7 +2,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import frappe import frappe
__version__ = '8.0.37' __version__ = '8.0.38'
def get_default_company(user=None): def get_default_company(user=None):

View File

@ -415,10 +415,10 @@ class SalesInvoice(SellingController):
throw(_("Customer {0} does not belong to project {1}").format(self.customer,self.project)) throw(_("Customer {0} does not belong to project {1}").format(self.customer,self.project))
def validate_pos(self): def validate_pos(self):
if flt(self.paid_amount) + flt(self.write_off_amount) \ if self.is_return:
- flt(self.grand_total) > 1/(10**(self.precision("grand_total") + 1)) and self.is_return: if flt(self.paid_amount) + flt(self.write_off_amount) - flt(self.grand_total) < \
frappe.throw(_("""Paid amount + Write Off Amount can not be greater than Grand Total""")) 1/(10**(self.precision("grand_total") + 1)):
frappe.throw(_("Paid amount + Write Off Amount can not be greater than Grand Total"))
def validate_item_code(self): def validate_item_code(self):
for d in self.get('items'): for d in self.get('items'):

View File

@ -7,10 +7,13 @@ import frappe
import datetime import datetime
from frappe import _, msgprint, scrub from frappe import _, msgprint, scrub
from frappe.defaults import get_user_permissions from frappe.defaults import get_user_permissions
from frappe.utils import add_days, getdate, formatdate, get_first_day, date_diff, add_years, get_timestamp from frappe.utils import add_days, getdate, formatdate, get_first_day, date_diff, \
add_years, get_timestamp, nowdate
from frappe.geo.doctype.address.address import get_address_display, get_default_address from frappe.geo.doctype.address.address import get_address_display, get_default_address
from frappe.email.doctype.contact.contact import get_contact_details, get_default_contact from frappe.email.doctype.contact.contact import get_contact_details, get_default_contact
from erpnext.exceptions import PartyFrozen, InvalidCurrency, PartyDisabled, InvalidAccountCurrency from erpnext.exceptions import PartyFrozen, InvalidCurrency, PartyDisabled, InvalidAccountCurrency
from erpnext.accounts.utils import get_fiscal_year
from erpnext import get_default_currency
class DuplicatePartyAccountError(frappe.ValidationError): pass class DuplicatePartyAccountError(frappe.ValidationError): pass
@ -359,4 +362,37 @@ def get_timeline_data(doctype, name):
timestamp = get_timestamp(date) timestamp = get_timestamp(date)
out.update({ timestamp: count }) out.update({ timestamp: count })
return out return out
def get_dashboard_info(party_type, party):
current_fiscal_year = get_fiscal_year(nowdate(), as_dict=True)
party_account_currency = get_party_account_currency(party_type, party, frappe.db.get_default("company"))
company_default_currency = get_default_currency()
if party_account_currency==company_default_currency:
total_field = "base_grand_total"
else:
total_field = "grand_total"
doctype = "Sales Invoice" if party_type=="Customer" else "Purchase Invoice"
billing_this_year = frappe.db.sql("""
select sum({0})
from `tab{1}`
where {2}=%s and docstatus=1 and posting_date between %s and %s
""".format(total_field, doctype, party_type.lower()),
(party, current_fiscal_year.year_start_date, current_fiscal_year.year_end_date))
total_unpaid = frappe.db.sql("""
select sum(debit_in_account_currency) - sum(credit_in_account_currency)
from `tabGL Entry`
where party_type = %s and party=%s""", (party_type, party))
info = {}
info["billing_this_year"] = billing_this_year[0][0] if billing_this_year else 0
info["currency"] = party_account_currency
info["total_unpaid"] = total_unpaid[0][0] if total_unpaid else 0
if party_type == "Supplier":
info["total_unpaid"] = -1 * info["total_unpaid"]
return info

View File

@ -6,11 +6,9 @@ import frappe
import frappe.defaults import frappe.defaults
from frappe import msgprint, _ from frappe import msgprint, _
from frappe.model.naming import make_autoname from frappe.model.naming import make_autoname
from frappe.geo.address_and_contact import (load_address_and_contact, from frappe.geo.address_and_contact import load_address_and_contact, delete_contact_and_address
delete_contact_and_address)
from erpnext.utilities.transaction_base import TransactionBase from erpnext.utilities.transaction_base import TransactionBase
from erpnext.accounts.party import validate_party_accounts, get_timeline_data # keep this from erpnext.accounts.party import validate_party_accounts, get_dashboard_info, get_timeline_data # keep this
class Supplier(TransactionBase): class Supplier(TransactionBase):
def get_feed(self): def get_feed(self):
@ -22,22 +20,7 @@ class Supplier(TransactionBase):
self.load_dashboard_info() self.load_dashboard_info()
def load_dashboard_info(self): def load_dashboard_info(self):
billing_this_year = frappe.db.sql(""" info = get_dashboard_info(self.doctype, self.name)
select sum(credit_in_account_currency) - sum(debit_in_account_currency)
from `tabGL Entry`
where voucher_type='Purchase Invoice' and party_type = 'Supplier'
and party=%s and fiscal_year = %s""",
(self.name, frappe.db.get_default("fiscal_year")))
total_unpaid = frappe.db.sql("""select sum(outstanding_amount)
from `tabPurchase Invoice`
where supplier=%s and docstatus = 1""", self.name)
info = {}
info["billing_this_year"] = billing_this_year[0][0] if billing_this_year else 0
info["total_unpaid"] = total_unpaid[0][0] if total_unpaid else 0
self.set_onload('dashboard_info', info) self.set_onload('dashboard_info', info)
def autoname(self): def autoname(self):

View File

@ -396,4 +396,5 @@ erpnext.patches.v8_0.merge_student_batch_and_student_group
erpnext.patches.v8_0.rename_total_margin_to_rate_with_margin # 11-05-2017 erpnext.patches.v8_0.rename_total_margin_to_rate_with_margin # 11-05-2017
erpnext.patches.v8_0.fix_status_for_invoices_with_negative_outstanding erpnext.patches.v8_0.fix_status_for_invoices_with_negative_outstanding
erpnext.patches.v8_0.make_payments_table_blank_for_non_pos_invoice erpnext.patches.v8_0.make_payments_table_blank_for_non_pos_invoice
erpnext.patches.v8_0.set_sales_invoice_serial_number_from_delivery_note erpnext.patches.v8_0.set_sales_invoice_serial_number_from_delivery_note
erpnext.patches.v8_0.delete_schools_depricated_doctypes

View File

@ -3,26 +3,32 @@ from frappe.model.utils.rename_field import rename_field
def execute(): def execute():
#Rename Grading Structure to Grading Scale #Rename Grading Structure to Grading Scale
frappe.rename_doc("DocType", "Grading Structure", "Grading Scale", force=True) if not frappe.db.exists("DocType", "Grading Scale"):
frappe.rename_doc("DocType", "Grade Interval", "Grading Scale Interval", force=True) frappe.rename_doc("DocType", "Grading Structure", "Grading Scale", force=True)
if not frappe.db.exists("DocType", "Grading Scale Interval"):
frappe.rename_doc("DocType", "Grade Interval", "Grading Scale Interval", force=True)
frappe.reload_doc("schools", "doctype", "grading_scale_interval") frappe.reload_doc("schools", "doctype", "grading_scale_interval")
rename_field("Grading Scale Interval", "to_score", "threshold") if "to_score" in frappe.db.get_table_columns("Grading Scale Interval"):
rename_field("Grading Scale Interval", "to_score", "threshold")
frappe.rename_doc("DocType", "Assessment", "Assessment Plan", force=True) if not frappe.db.exists("DocType", "Assessment Plan"):
frappe.rename_doc("DocType", "Assessment", "Assessment Plan", force=True)
#Rename Assessment Results #Rename Assessment Results
frappe.reload_doc("schools", "doctype", "assessment_plan") frappe.reload_doc("schools", "doctype", "assessment_plan")
rename_field("Assessment Plan", "grading_structure", "grading_scale") if "grading_structure" in frappe.db.get_table_columns("Assessment Plan"):
rename_field("Assessment Plan", "grading_structure", "grading_scale")
frappe.reload_doc("schools", "doctype", "assessment_result") frappe.reload_doc("schools", "doctype", "assessment_result")
frappe.reload_doc("schools", "doctype", "assessment_result_detail") frappe.reload_doc("schools", "doctype", "assessment_result_detail")
frappe.reload_doc("schools", "doctype", "assessment_criteria") frappe.reload_doc("schools", "doctype", "assessment_criteria")
for assessment in frappe.get_all("Assessment Plan", fields=["name", "grading_scale"], filters = [["docstatus", "!=", 2 ]]): for assessment in frappe.get_all("Assessment Plan",
print assessment fields=["name", "grading_scale"], filters = [["docstatus", "!=", 2 ]]):
for stud_result in frappe.db.sql("select * from `tabAssessment Result` where parent= %s", assessment.name, as_dict=True): for stud_result in frappe.db.sql("select * from `tabAssessment Result` where parent= %s",
assessment.name, as_dict=True):
if stud_result.result: if stud_result.result:
assessment_result = frappe.new_doc("Assessment Result") assessment_result = frappe.new_doc("Assessment Result")
assessment_result.student = stud_result.student assessment_result.student = stud_result.student

View File

@ -0,0 +1,14 @@
# Copyright (c) 2017, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
def execute():
""" delete doctypes """
if frappe.db.exists("DocType", "Grading Structure"):
frappe.delete_doc("DocType", "Grading Structure", force=1)
if frappe.db.exists("DocType", "Grade Interval"):
frappe.delete_doc("DocType", "Grade Interval", force=1)

View File

@ -68,12 +68,12 @@
</div> </div>
<div class="col-xs-6 numeric_keypad hidden-xs" style="display:none"> <div class="col-xs-6 numeric_keypad hidden-xs" style="display:none">
{% var chartData = [__("Qty"), __("Disc"), __("Price")] %} {% for(var i=0; i {% var chartData = ["Qty", "Disc", "Price"] %} {% for(var i=0; i
<3; i++) { %} <div class="row text-right"> <3; i++) { %} <div class="row text-right">
{% for(var j=i*3; j {% for(var j=i*3; j
<(i+1)*3; j++) { %} <button type="button" class="btn btn-default numeric-keypad" val="{{j+1}}">{{j+1}}</button> <(i+1)*3; j++) { %} <button type="button" class="btn btn-default numeric-keypad" val="{{j+1}}">{{j+1}}</button>
{% } %} {% } %}
<button type="button" id="pos-item-{{ chartData[i].toLowerCase() }}" class="btn text-center btn-default numeric-keypad pos-operation">{{ chartData[i] }}</button> <button type="button" id="pos-item-{{ chartData[i].toLowerCase() }}" class="btn text-center btn-default numeric-keypad pos-operation">{{ __(chartData[i]) }}</button>
</div> </div>
{% } %} {% } %}
<div class="row text-right"> <div class="row text-right">
@ -120,8 +120,8 @@
<div class="cell search-item"></div> <div class="cell search-item"></div>
</div> </div>
<div class="app-listing item-list image-view-container"> <div class="app-listing item-list image-view-container">
</div> </div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,122 +0,0 @@
{
"allow_copy": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2016-08-26 03:11:09.591049",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "grade_code",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Grade Code",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "min_score",
"fieldtype": "Percent",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Min Score",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "1",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "grade_description",
"fieldtype": "Small Text",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Grade Description",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2016-12-14 12:54:56.902465",
"modified_by": "Administrator",
"module": "Schools",
"name": "Grade Interval",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_seen": 0
}

View File

@ -1,11 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
class GradeInterval(Document):
def validate(self):
pass

View File

@ -1,8 +0,0 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Grading Structure', {
refresh: function(frm) {
}
});

View File

@ -1,202 +0,0 @@
{
"allow_copy": 0,
"allow_import": 0,
"allow_rename": 1,
"autoname": "field:grading_system_name",
"beta": 0,
"creation": "2016-08-26 03:06:53.922972",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "grading_system_name",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Grading System Name",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_2",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "description",
"fieldtype": "Text",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Description",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "grading_intervals_section",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Grading Intervals",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "grade_intervals",
"fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Grade Intervals",
"length": 0,
"no_copy": 0,
"options": "Grade Interval",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2016-12-14 12:35:39.690256",
"modified_by": "Administrator",
"module": "Schools",
"name": "Grading Structure",
"name_case": "",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"is_custom": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Academics User",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
}
],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"sort_field": "modified",
"sort_order": "DESC",
"title_field": "grading_system_name",
"track_seen": 0
}

View File

@ -1,25 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
from frappe import _
from frappe.utils import cstr
class GradingStructure(Document):
def validate(self):
grade_intervals = self.get("grade_intervals")
check_overlap(grade_intervals, self)
#Check if any of the grade intervals for this grading structure overlap
def check_overlap(grade_intervals, parent_doc):
for interval1 in grade_intervals:
for interval2 in grade_intervals:
if interval1.name == interval2.name:
pass
else:
if (interval1.from_score <= interval2.from_score and interval1.to_score >= interval2.from_score) or (interval1.from_score <= interval2.to_score and interval1.to_score >= interval2.to_score):
frappe.throw(_("""The intervals for Grade Code {0} overlaps with the grade intervals for other grades.
Please check intervals {0} and {1} and try again""".format(interval1.grade_code, interval2.grade_code)))

View File

@ -1,12 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
from __future__ import unicode_literals
import frappe
import unittest
# test_records = frappe.get_test_records('Grading Structure')
class TestGradingStructure(unittest.TestCase):
pass

View File

@ -10,8 +10,7 @@ from frappe.utils import flt, cint, cstr
from frappe.desk.reportview import build_match_conditions from frappe.desk.reportview import build_match_conditions
from erpnext.utilities.transaction_base import TransactionBase from erpnext.utilities.transaction_base import TransactionBase
from frappe.geo.address_and_contact import load_address_and_contact, delete_contact_and_address from frappe.geo.address_and_contact import load_address_and_contact, delete_contact_and_address
from erpnext.accounts.party import validate_party_accounts, get_timeline_data # keep this from erpnext.accounts.party import validate_party_accounts, get_dashboard_info, get_timeline_data # keep this
from erpnext import get_default_currency
class Customer(TransactionBase): class Customer(TransactionBase):
def get_feed(self): def get_feed(self):
@ -23,25 +22,9 @@ class Customer(TransactionBase):
self.load_dashboard_info() self.load_dashboard_info()
def load_dashboard_info(self): def load_dashboard_info(self):
billing_this_year = frappe.db.sql(""" info = get_dashboard_info(self.doctype, self.name)
select sum(debit_in_account_currency) - sum(credit_in_account_currency), account_currency
from `tabGL Entry`
where voucher_type='Sales Invoice' and party_type = 'Customer'
and party=%s and fiscal_year = %s""",
(self.name, frappe.db.get_default("fiscal_year")))
total_unpaid = frappe.db.sql("""select sum(outstanding_amount)
from `tabSales Invoice`
where customer=%s and docstatus = 1""", self.name)
info = {}
info["billing_this_year"] = billing_this_year[0][0] if billing_this_year else 0
info["currency"] = billing_this_year[0][1] if billing_this_year else get_default_currency()
info["total_unpaid"] = total_unpaid[0][0] if total_unpaid else 0
self.set_onload('dashboard_info', info) self.set_onload('dashboard_info', info)
def autoname(self): def autoname(self):
cust_master_name = frappe.defaults.get_global_default('cust_master_name') cust_master_name = frappe.defaults.get_global_default('cust_master_name')
if cust_master_name == 'Customer Name': if cust_master_name == 'Customer Name':

View File

@ -91,8 +91,7 @@ def get_exchange_rate(from_currency, to_currency, transaction_date=None):
response.raise_for_status() response.raise_for_status()
value = response.json()["rates"][to_currency] value = response.json()["rates"][to_currency]
cache.setex(key, value, 6 * 60 * 60) cache.setex(key, value, 6 * 60 * 60)
return flt(value) return flt(value)
except: except:
frappe.msgprint(_("Unable to find exchange rate for {0} to {1} for key date {2}").format(from_currency, to_currency, transaction_date)) frappe.msgprint(_("Unable to find exchange rate for {0} to {1} for key date {2}. Please create a Currency Exchange record manually").format(from_currency, to_currency, transaction_date))
return 0.0 return 0.0

View File

@ -44,8 +44,6 @@ frappe.ui.form.on("Item", {
}, __("View")); }, __("View"));
} }
// make sensitive fields(has_serial_no, is_stock_item, valuation_method)
// read only if any stock ledger entry exists
if(!frm.doc.is_fixed_asset) { if(!frm.doc.is_fixed_asset) {
erpnext.item.make_dashboard(frm); erpnext.item.make_dashboard(frm);
} }
@ -77,6 +75,8 @@ frappe.ui.form.on("Item", {
erpnext.item.edit_prices_button(frm); erpnext.item.edit_prices_button(frm);
// make sensitive fields(has_serial_no, is_stock_item, valuation_method, has_batch_no)
// read only if any stock ledger entry exists
if (!frm.doc.__islocal && frm.doc.is_stock_item) { if (!frm.doc.__islocal && frm.doc.is_stock_item) {
frm.toggle_enable(['has_serial_no', 'is_stock_item', 'valuation_method', 'has_batch_no'], frm.toggle_enable(['has_serial_no', 'is_stock_item', 'valuation_method', 'has_batch_no'],
(frm.doc.__onload && frm.doc.__onload.sle_exists=="exists") ? false : true); (frm.doc.__onload && frm.doc.__onload.sle_exists=="exists") ? false : true);

View File

@ -74,7 +74,8 @@ class PurchaseReceipt(BuyingController):
"Purchase Order Item": { "Purchase Order Item": {
"ref_dn_field": "purchase_order_item", "ref_dn_field": "purchase_order_item",
"compare_fields": [["project", "="], ["uom", "="], ["item_code", "="]], "compare_fields": [["project", "="], ["uom", "="], ["item_code", "="]],
"is_child_table": True "is_child_table": True,
"allow_duplicate_prev_row_id": True
} }
}) })

View File

@ -26,3 +26,19 @@ class StockSettings(Document):
# show/hide barcode field # show/hide barcode field
frappe.make_property_setter({'fieldname': 'barcode', 'property': 'hidden', frappe.make_property_setter({'fieldname': 'barcode', 'property': 'hidden',
'value': 0 if self.show_barcode_field else 1}) 'value': 0 if self.show_barcode_field else 1})
self.cant_change_valuation_method()
def cant_change_valuation_method(self):
db_valuation_method = frappe.db.get_single_value("Stock Settings", "valuation_method")
if db_valuation_method and db_valuation_method != self.valuation_method:
# check if there are any stock ledger entries against items
# which does not have it's own valuation method
sle = frappe.db.sql("""select name from `tabStock Ledger Entry` sle
where exists(select name from tabItem
where name=sle.item_code and (valuation_method is null or valuation_method=''))
""")
if sle:
frappe.throw(_("Can't change valuation method, as there are transactions against some items which does not have it's own valuation method"))