Merge pull request #15976 from deepeshgarg007/summary
[Fix] Accounts receivable summary print format showing zero values
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index bb94383..92efe8e 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -5,7 +5,7 @@
from erpnext.hooks import regional_overrides
from frappe.utils import getdate
-__version__ = '10.1.70'
+__version__ = '10.1.72'
def get_default_company(user=None):
'''Get default company for user'''
diff --git a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
index f5f832d..995efee 100644
--- a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
+++ b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
@@ -11,11 +11,17 @@
from frappe import MandatoryError
class TestPricingRule(unittest.TestCase):
+ def setUp(self):
+ frappe.db.sql("delete from `tabPricing Rule`")
+
+ def tearDown(self):
+ frappe.db.sql("delete from `tabPricing Rule`")
+
def test_pricing_rule_for_discount(self):
from erpnext.stock.get_item_details import get_item_details
from frappe import MandatoryError
- frappe.db.sql("delete from `tabPricing Rule`")
+
test_record = {
"doctype": "Pricing Rule",
@@ -89,14 +95,10 @@
details = get_item_details(args)
self.assertEqual(details.get("discount_percentage"), 15)
- frappe.db.sql("delete from `tabPricing Rule`")
-
def test_pricing_rule_for_margin(self):
from erpnext.stock.get_item_details import get_item_details
from frappe import MandatoryError
- frappe.db.sql("delete from `tabPricing Rule`")
-
test_record = {
"doctype": "Pricing Rule",
"title": "_Test Pricing Rule",
@@ -111,14 +113,14 @@
"company": "_Test Company"
}
frappe.get_doc(test_record.copy()).insert()
-
+
item_price = frappe.get_doc({
"doctype": "Item Price",
"price_list": "_Test Price List 2",
"item_code": "_Test FG Item 2",
"price_list_rate": 100
})
-
+
item_price.insert(ignore_permissions=True)
args = frappe._dict({
@@ -138,14 +140,10 @@
self.assertEqual(details.get("margin_type"), "Percentage")
self.assertEqual(details.get("margin_rate_or_amount"), 10)
- frappe.db.sql("delete from `tabPricing Rule`")
-
def test_pricing_rule_for_variants(self):
from erpnext.stock.get_item_details import get_item_details
from frappe import MandatoryError
- frappe.db.sql("delete from `tabPricing Rule`")
-
if not frappe.db.exists("Item", "Test Variant PRT"):
frappe.get_doc({
"doctype": "Item",
@@ -213,8 +211,6 @@
self.assertEqual(details.get("discount_percentage"), 17.5)
def test_pricing_rule_for_stock_qty(self):
- frappe.db.sql("delete from `tabPricing Rule`")
-
test_record = {
"doctype": "Pricing Rule",
"title": "_Test Pricing Rule",
@@ -257,25 +253,19 @@
self.assertEqual(so.items[0].rate, 100)
def test_pricing_rule_with_margin_and_discount(self):
- frappe.delete_doc_if_exists('Pricing Rule', '_Test Pricing Rule')
- make_pricing_rule(selling=1, margin_type="Percentage", margin_rate_or_amount=10)
+ make_pricing_rule(selling=1, margin_type="Percentage", margin_rate_or_amount=10, discount_percentage=10)
si = create_sales_invoice(do_not_save=True)
si.items[0].price_list_rate = 1000
si.payment_schedule = []
si.insert(ignore_permissions=True)
item = si.items[0]
- self.assertEqual(item.rate, 1100)
self.assertEqual(item.margin_rate_or_amount, 10)
-
- # With discount
- item.discount_percentage = 10
- si.payment_schedule = []
- si.save()
- item = si.items[0]
- self.assertEqual(item.rate, 990)
+ self.assertEqual(item.rate_with_margin, 1100)
self.assertEqual(item.discount_percentage, 10)
- frappe.db.sql("delete from `tabPricing Rule`")
+ self.assertEqual(item.discount_amount, 110)
+ self.assertEqual(item.rate, 990)
+
def make_pricing_rule(**args):
args = frappe._dict(args)
diff --git a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.js b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.js
index 91a06f4..7b373f0 100644
--- a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.js
+++ b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.js
@@ -43,6 +43,13 @@
"reqd": 1
},
{
+ "fieldname": "presentation_currency",
+ "label": __("Currency"),
+ "fieldtype": "Select",
+ "options": erpnext.get_presentation_currency_list(),
+ "default": frappe.defaults.get_user_default("Currency")
+ },
+ {
"fieldname":"accumulated_in_group_company",
"label": __("Accumulated Values in Group Company"),
"fieldtype": "Check",
diff --git a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py
index 2d13469..b9aebd8 100644
--- a/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py
+++ b/erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py
@@ -5,6 +5,7 @@
import frappe, erpnext
from frappe import _
from frappe.utils import flt, cint
+from erpnext.accounts.report.utils import get_currency, convert_to_presentation_currency
from erpnext.accounts.report.financial_statements import get_fiscal_year_data, sort_accounts
from erpnext.accounts.report.balance_sheet.balance_sheet import (get_provisional_profit_loss,
check_opening_balance, get_chart_data)
@@ -48,7 +49,7 @@
data.extend(liability or [])
data.extend(equity or [])
- company_currency = frappe.db.get_value("Company", filters.company, "default_currency")
+ company_currency = get_company_currency(filters)
provisional_profit_loss, total_credit = get_provisional_profit_loss(asset, liability, equity,
companies, filters.get('company'), company_currency, True)
@@ -59,7 +60,7 @@
"account_name": "'" + _("Unclosed Fiscal Years Profit / Loss (Credit)") + "'",
"account": "'" + _("Unclosed Fiscal Years Profit / Loss (Credit)") + "'",
"warn_if_negative": True,
- "currency": frappe.get_cached_value('Company', filters.company, "default_currency")
+ "currency": company_currency
}
for company in companies:
unclosed[company] = opening_balance
@@ -92,7 +93,7 @@
return data, None, chart
def get_income_expense_data(companies, fiscal_year, filters):
- company_currency = frappe.get_cached_value('Company', filters.company, "default_currency")
+ company_currency = get_company_currency(filters)
income = get_data(companies, "Income", "Credit", fiscal_year, filters, True)
expense = get_data(companies, "Expense", "Debit", fiscal_year, filters, True)
@@ -107,7 +108,7 @@
income, expense, net_profit_loss = get_income_expense_data(companies, fiscal_year, filters)
data = []
- company_currency = frappe.get_cached_value('Company', filters.company, "default_currency")
+ company_currency = get_company_currency(filters)
for cash_flow_account in cash_flow_accounts:
section_data = []
@@ -185,6 +186,7 @@
"fieldname": company,
"label": company,
"fieldtype": "Currency",
+ "options": "currency",
"width": 150
})
@@ -216,7 +218,8 @@
return out
def get_company_currency(filters=None):
- return frappe.get_cached_value('Company', filters.get('company'), "default_currency")
+ return (filters.get('presentation_currency')
+ or frappe.get_cached_value('Company', filters.company, "default_currency"))
def calculate_values(accounts_by_name, gl_entries_by_account, companies, fiscal_year, filters):
for entries in gl_entries_by_account.values():
@@ -328,28 +331,42 @@
filters.get('company'), ["lft", "rgt"])
additional_conditions = get_additional_conditions(from_date, ignore_closing_entries, filters)
-
- gl_entries = frappe.db.sql("""select gl.posting_date, gl.account, gl.debit, gl.credit, gl.is_opening, gl.company,
- gl.fiscal_year, gl.debit_in_account_currency, gl.credit_in_account_currency, gl.account_currency,
- acc.account_name, acc.account_number
- from `tabGL Entry` gl, `tabAccount` acc where acc.name = gl.account and gl.company in
- (select name from `tabCompany` where lft >= %(company_lft)s and rgt <= %(company_rgt)s)
- {additional_conditions} and gl.posting_date <= %(to_date)s and acc.lft >= %(lft)s and acc.rgt <= %(rgt)s
- order by gl.account, gl.posting_date""".format(additional_conditions=additional_conditions),
- {
- "from_date": from_date,
- "to_date": to_date,
- "lft": root_lft,
- "rgt": root_rgt,
+ companies = frappe.db.sql(""" select name, default_currency from `tabCompany`
+ where lft >= %(company_lft)s and rgt <= %(company_rgt)s""", {
"company_lft": company_lft,
"company_rgt": company_rgt,
- },
- as_dict=True)
+ }, as_dict=1)
- for entry in gl_entries:
- key = entry.account_number or entry.account_name
- validate_entries(key, entry, accounts_by_name)
- gl_entries_by_account.setdefault(key, []).append(entry)
+ currency_info = frappe._dict({
+ 'report_date': to_date,
+ 'presentation_currency': filters.get('presentation_currency')
+ })
+
+ for d in companies:
+ gl_entries = frappe.db.sql("""select gl.posting_date, gl.account, gl.debit, gl.credit, gl.is_opening, gl.company,
+ gl.fiscal_year, gl.debit_in_account_currency, gl.credit_in_account_currency, gl.account_currency,
+ acc.account_name, acc.account_number
+ from `tabGL Entry` gl, `tabAccount` acc where acc.name = gl.account and gl.company = %(company)s
+ {additional_conditions} and gl.posting_date <= %(to_date)s and acc.lft >= %(lft)s and acc.rgt <= %(rgt)s
+ order by gl.account, gl.posting_date""".format(additional_conditions=additional_conditions),
+ {
+ "from_date": from_date,
+ "to_date": to_date,
+ "lft": root_lft,
+ "rgt": root_rgt,
+ "company": d.name
+ },
+ as_dict=True)
+
+ if filters and filters.get('presentation_currency') != d.default_currency:
+ currency_info['company'] = d.name
+ currency_info['company_currency'] = d.default_currency
+ convert_to_presentation_currency(gl_entries, currency_info)
+
+ for entry in gl_entries:
+ key = entry.account_number or entry.account_name
+ validate_entries(key, entry, accounts_by_name)
+ gl_entries_by_account.setdefault(key, []).append(entry)
return gl_entries_by_account
diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py
index 6985c80..a441025 100644
--- a/erpnext/controllers/taxes_and_totals.py
+++ b/erpnext/controllers/taxes_and_totals.py
@@ -65,12 +65,13 @@
if item.doctype in ['Quotation Item', 'Sales Order Item', 'Delivery Note Item', 'Sales Invoice Item']:
item.rate_with_margin, item.base_rate_with_margin = self.calculate_margin(item)
-
- item.rate = flt(item.rate_with_margin * (1.0 - (item.discount_percentage / 100.0)), item.precision("rate"))\
- if item.rate_with_margin > 0 else item.rate
+ if flt(item.rate_with_margin) > 0:
+ item.rate = flt(item.rate_with_margin * (1.0 - (item.discount_percentage / 100.0)), item.precision("rate"))
+ item.discount_amount = item.rate_with_margin - item.rate
+ elif flt(item.price_list_rate) > 0:
+ item.discount_amount = item.price_list_rate - item.rate
item.net_rate = item.rate
- item.discount_amount = item.price_list_rate - item.rate
item.amount = flt(item.rate * item.qty, item.precision("amount"))
item.net_amount = item.amount
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 87b7942..6947c02 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -12,7 +12,7 @@
source_link = "https://github.com/frappe/erpnext"
develop_version = '12.x.x-develop'
-staging_version = '11.0.3-beta.20'
+staging_version = '11.0.3-beta.22'
error_report_email = "support@erpnext.com"
diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.py b/erpnext/hr/doctype/employee_advance/employee_advance.py
index 62355b8..1c8b5f9 100644
--- a/erpnext/hr/doctype/employee_advance/employee_advance.py
+++ b/erpnext/hr/doctype/employee_advance/employee_advance.py
@@ -13,7 +13,7 @@
class EmployeeAdvance(Document):
def onload(self):
- self.get("__onload").make_payment_via_journal_entry = frappe.db.get_single_value('Accounts Settings',
+ self.get("__onload").make_payment_via_journal_entry = frappe.db.get_single_value('Accounts Settings',
'make_payment_via_journal_entry')
def validate(self):
@@ -47,7 +47,7 @@
paid_amount = frappe.db.sql("""
select ifnull(sum(debit_in_account_currency), 0) as paid_amount
from `tabGL Entry`
- where against_voucher_type = 'Employee Advance'
+ where against_voucher_type = 'Employee Advance'
and against_voucher = %s
and party_type = 'Employee'
and party = %s
@@ -67,7 +67,7 @@
select sum(ifnull(allocated_amount, 0))
from `tabExpense Claim Advance`
where employee_advance = %s and docstatus=1 and allocated_amount > 0
- """, self.name)[0][0]
+ """, self.name)[0][0] or 0
if claimed_amount:
frappe.db.set_value("Employee Advance", self.name, "claimed_amount", flt(claimed_amount))
diff --git a/erpnext/hr/doctype/salary_structure/salary_structure.js b/erpnext/hr/doctype/salary_structure/salary_structure.js
index 4a111e7..033938d 100755
--- a/erpnext/hr/doctype/salary_structure/salary_structure.js
+++ b/erpnext/hr/doctype/salary_structure/salary_structure.js
@@ -58,6 +58,9 @@
doc.company = frm.doc.company;
frappe.set_route('Form', 'Salary Structure Assignment', doc.name);
});
+ frm.add_custom_button(__("Assign to Employees"),function () {
+ frm.trigger('assign_to_employees')
+ })
}
let fields_read_only = ["is_tax_applicable", "is_flexible_benefit", "variable_based_on_taxable_salary"];
fields_read_only.forEach(function(field) {
@@ -65,6 +68,43 @@
});
},
+ assign_to_employees:function (frm) {
+ var d = new frappe.ui.Dialog({
+ title: __("Assign to Employees"),
+ fields: [
+ {fieldname: "sec_break", fieldtype: "Section Break", label: __("Filter Employees By (Optional)")},
+ {fieldname: "grade", fieldtype: "Link", options: "Employee Grade", label: __("Employee Grade")},
+ {fieldname:'department', fieldtype:'Link', options: 'Department', label: __('Department')},
+ {fieldname:'designation', fieldtype:'Link', options: 'Designation', label: __('Designation')},
+ {fieldname:"employee", fieldtype: "Link", options: "Employee", label: __("Employee")},
+ {fieldname:'base_variable', fieldtype:'Section Break'},
+ {fieldname:'from_date', fieldtype:'Date', label: __('From Date'), "reqd": 1},
+ {fieldname:'base_col_br', fieldtype:'Column Break'},
+ {fieldname:'base', fieldtype:'Currency', label: __('Base')},
+ {fieldname:'variable', fieldtype:'Currency', label: __('Variable')}
+ ],
+ primary_action: function() {
+ var data = d.get_values();
+
+ frappe.call({
+ doc: frm.doc,
+ method: "assign_salary_structure",
+ args: data,
+ callback: function(r) {
+ if(!r.exc) {
+ d.hide();
+ frm.reload_doc();
+ }
+ }
+ });
+ },
+ primary_action_label: __('Assign')
+ });
+
+
+ d.show();
+ },
+
salary_slip_based_on_timesheet: function(frm) {
frm.trigger("toggle_fields")
},
diff --git a/erpnext/hr/doctype/salary_structure/salary_structure.py b/erpnext/hr/doctype/salary_structure/salary_structure.py
index a36d820..7ead140 100644
--- a/erpnext/hr/doctype/salary_structure/salary_structure.py
+++ b/erpnext/hr/doctype/salary_structure/salary_structure.py
@@ -65,6 +65,76 @@
if not have_a_flexi and flt(self.max_benefits) > 0:
frappe.throw(_("Salary Structure should have flexible benefit component(s) to dispense benefit amount"))
+ def get_employees(self, **kwargs):
+ conditions, values = [], []
+ for field, value in kwargs.items():
+ if value:
+ conditions.append("{0}=%s".format(field))
+ values.append(value)
+
+ condition_str = " and " + " and ".join(conditions) if conditions else ""
+
+ employees = frappe.db.sql_list("select name from tabEmployee where status='Active' {condition}"
+ .format(condition=condition_str), tuple(values))
+
+ return employees
+
+ @frappe.whitelist()
+ def assign_salary_structure(self, grade=None, department=None, designation=None,employee=None,
+ from_date=None, base=None,variable=None):
+ employees = self.get_employees(grade= grade,department= department,designation= designation,name=employee)
+
+ if employees:
+ if len(employees) > 20:
+ frappe.enqueue(assign_salary_structure_for_employees, timeout=600,
+ employees=employees, salary_structure=self,from_date=from_date, base=base,variable=variable)
+ else:
+ assign_salary_structure_for_employees(employees, self,from_date=from_date, base=base,variable=variable)
+ else:
+ frappe.msgprint(_("No Employee Found"))
+
+
+
+def assign_salary_structure_for_employees(employees, salary_structure,from_date=None, base=None,variable=None):
+ salary_structures_assignments = []
+ existing_assignments_for = get_existing_assignments(employees, salary_structure.name,from_date)
+ count=0
+ for employee in employees:
+ if employee in existing_assignments_for:
+ continue
+ count +=1
+
+ salary_structures_assignment = create_salary_structures_assignment(employee, salary_structure, from_date, base, variable)
+ salary_structures_assignments.append(salary_structures_assignment)
+ frappe.publish_progress(count*100/len(set(employees) - set(existing_assignments_for)), title = _("Assigning Structures..."))
+
+ if salary_structures_assignments:
+ frappe.msgprint(_("Structures have been assigned successfully"))
+
+
+def create_salary_structures_assignment(employee, salary_structure, from_date, base, variable):
+ assignment = frappe.new_doc("Salary Structure Assignment")
+ assignment.employee = employee
+ assignment.salary_structure = salary_structure.name
+ assignment.from_date = from_date
+ assignment.base = base
+ assignment.variable = variable
+ assignment.save(ignore_permissions = True)
+ assignment.submit()
+ return assignment.name
+
+
+def get_existing_assignments(employees, salary_structure,from_date):
+ salary_structures_assignments = frappe.db.sql_list("""
+ select distinct employee from `tabSalary Structure Assignment`
+ where salary_structure=%s and employee in (%s)
+ and from_date=%s and docstatus=1
+ """ % ('%s', ', '.join(['%s']*len(employees)),'%s'), [salary_structure] + employees+[from_date])
+ if salary_structures_assignments:
+ frappe.msgprint(_("Skipping Salary Structure Assignment for the following employees, as Salary Structure Assignment records already exists against them. {0}")
+ .format("\n".join(salary_structures_assignments)))
+ return salary_structures_assignments
+
@frappe.whitelist()
def make_salary_slip(source_name, target_doc = None, employee = None, as_print = False, print_format = None):
def postprocess(source, target):
diff --git a/erpnext/hr/doctype/salary_structure/test_salary_structure.py b/erpnext/hr/doctype/salary_structure/test_salary_structure.py
index 1a16db7..1a660d9 100644
--- a/erpnext/hr/doctype/salary_structure/test_salary_structure.py
+++ b/erpnext/hr/doctype/salary_structure/test_salary_structure.py
@@ -71,6 +71,19 @@
for row in salary_structure.deductions:
self.assertFalse(("\n" in row.formula) or ("\n" in row.condition))
+ def test_salary_structures_assignment(self):
+ salary_structure = make_salary_structure("Salary Structure Sample", "Monthly")
+ employee = "test_assign_stucture@salary.com"
+ employee_doc_name = make_employee(employee)
+ # clear the already assigned stuctures
+ frappe.db.sql('''delete from `tabSalary Structure Assignment` where employee=%s and salary_structure=%s ''',
+ ("test_assign_stucture@salary.com",salary_structure.name))
+ #test structure_assignment
+ salary_structure.assign_salary_structure(employee=employee_doc_name,from_date='2013-01-01',base=5000,variable=200)
+ salary_structure_assignment = frappe.get_doc("Salary Structure Assignment",{'employee':employee_doc_name, 'from_date':'2013-01-01'})
+ self.assertEqual(salary_structure_assignment.docstatus, 1)
+ self.assertEqual(salary_structure_assignment.base, 5000)
+ self.assertEqual(salary_structure_assignment.variable, 200)
def make_salary_structure(salary_structure, payroll_frequency, employee=None, dont_submit=False, other_details=None, test_tax=False):
if test_tax:
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index 0eab982..d72f00a 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -108,7 +108,8 @@
"item_code": item.item_code,
"item_name": item.item_name,
"bom_no": item.bom_no,
- "stock_qty": item.stock_qty
+ "stock_qty": item.stock_qty,
+ "allow_transfer_for_manufacture": item.allow_transfer_for_manufacture
})
for r in ret:
if not item.get(r):
@@ -127,6 +128,8 @@
self.validate_rm_item(item)
args['bom_no'] = args['bom_no'] or item and cstr(item[0]['default_bom']) or ''
+ args['transfer_for_manufacture'] = (cstr(args.get('allow_transfer_for_manufacture', '')) or
+ item and item[0].allow_transfer_for_manufacture or 0)
args.update(item[0])
rate = self.get_rm_rate(args)
@@ -142,7 +145,7 @@
'qty' : args.get("qty") or args.get("stock_qty") or 1,
'stock_qty' : args.get("qty") or args.get("stock_qty") or 1,
'base_rate' : rate,
- 'allow_transfer_for_manufacture': item and args['allow_transfer_for_manufacture'] or 0
+ 'allow_transfer_for_manufacture': cint(args['transfer_for_manufacture']) or 0
}
return ret_item
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 1f231e6..f771181 100755
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -572,8 +572,10 @@
execute:frappe.delete_doc("Page", "Purchase Analytics")
execute:frappe.delete_doc("Page", "Stock Analytics")
execute:frappe.delete_doc("Page", "Production Analytics")
-erpnext.patches.v11_0.ewaybill_fields_gst_india
+erpnext.patches.v11_0.ewaybill_fields_gst_india #2018-11-13
erpnext.patches.v11_0.drop_column_max_days_allowed
erpnext.patches.v11_0.change_healthcare_desktop_icons
erpnext.patches.v10_0.update_user_image_in_employee
-erpnext.patches.v11_0.update_delivery_trip_status
\ No newline at end of file
+erpnext.patches.v11_0.update_delivery_trip_status
+erpnext.patches.v10_0.repost_gle_for_purchase_receipts_with_rejected_items
+erpnext.patches.v11_0.set_missing_gst_hsn_code
diff --git a/erpnext/patches/v10_0/repost_gle_for_purchase_receipts_with_rejected_items.py b/erpnext/patches/v10_0/repost_gle_for_purchase_receipts_with_rejected_items.py
new file mode 100644
index 0000000..68c06ef
--- /dev/null
+++ b/erpnext/patches/v10_0/repost_gle_for_purchase_receipts_with_rejected_items.py
@@ -0,0 +1,32 @@
+# Copyright (c) 2017, Frappe and Contributors
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import frappe, erpnext
+
+def execute():
+ for company in frappe.get_all("Company"):
+ if not erpnext.is_perpetual_inventory_enabled(company.name):
+ continue
+
+ acc_frozen_upto = frappe.db.get_value("Accounts Settings", None, "acc_frozen_upto") or "1900-01-01"
+ pr_with_rejected_warehouse = frappe.db.sql("""
+ select pr.name
+ from `tabPurchase Receipt` pr, `tabPurchase Receipt Item` pr_item
+ where pr.name = pr_item.parent
+ and pr.posting_date > %s
+ and pr.docstatus=1
+ and pr.company = %s
+ and pr_item.rejected_qty > 0
+ """, (acc_frozen_upto, company.name), as_dict=1)
+
+ for d in pr_with_rejected_warehouse:
+ doc = frappe.get_doc("Purchase Receipt", d.name)
+
+ doc.docstatus = 2
+ doc.make_gl_entries_on_cancel(repost_future_gle=False)
+
+
+ # update gl entries for submit state of PR
+ doc.docstatus = 1
+ doc.make_gl_entries(repost_future_gle=False)
diff --git a/erpnext/patches/v11_0/set_missing_gst_hsn_code.py b/erpnext/patches/v11_0/set_missing_gst_hsn_code.py
new file mode 100644
index 0000000..3c2cea2
--- /dev/null
+++ b/erpnext/patches/v11_0/set_missing_gst_hsn_code.py
@@ -0,0 +1,43 @@
+import frappe
+from erpnext.controllers.taxes_and_totals import get_itemised_tax_breakup_html
+
+def execute():
+ company = frappe.db.sql_list("select name from tabCompany where country = 'India'")
+ if not company:
+ return
+
+ doctypes = ["Quotation", "Sales Order", "Delivery Note", "Sales Invoice",
+ "Supplier Quotation", "Purchase Order", "Purchase Receipt", "Purchase Invoice"]
+
+ for dt in doctypes:
+ date_field = "posting_date"
+ if dt in ["Quotation", "Sales Order", "Supplier Quotation", "Purchase Order"]:
+ date_field = "transaction_date"
+
+ transactions = frappe.db.sql("""
+ select dt.name, dt_item.name as child_name
+ from `tab{dt}` dt, `tab{dt} Item` dt_item
+ where dt.name = dt_item.parent
+ and dt.`{date_field}` > '2018-06-01'
+ and dt.docstatus = 1
+ and ifnull(dt_item.gst_hsn_code, '') = ''
+ and ifnull(dt_item.item_code, '') != ''
+ and dt.company in ({company})
+ """.format(dt=dt, date_field=date_field, company=", ".join(['%s']*len(company))), tuple(company), as_dict=1)
+
+ if not transactions:
+ continue
+
+ transaction_rows_name = [d.child_name for d in transactions]
+
+ frappe.db.sql("""
+ update `tab{dt} Item` dt_item
+ set dt_item.gst_hsn_code = (select gst_hsn_code from tabItem where name=dt_item.item_code)
+ where dt_item.name in ({rows_name})
+ """.format(dt=dt, rows_name=", ".join(['%s']*len(transaction_rows_name))), tuple(transaction_rows_name))
+
+ parent = set([d.name for d in transactions])
+ for t in list(parent):
+ trans_doc = frappe.get_doc(dt, t)
+ hsnwise_tax = get_itemised_tax_breakup_html(trans_doc)
+ frappe.db.set_value(dt, t, "other_charges_calculation", hsnwise_tax, update_modified=False)
\ No newline at end of file
diff --git a/erpnext/patches/v11_0/update_total_qty_field.py b/erpnext/patches/v11_0/update_total_qty_field.py
index 5c7663d..8f08699 100644
--- a/erpnext/patches/v11_0/update_total_qty_field.py
+++ b/erpnext/patches/v11_0/update_total_qty_field.py
@@ -9,12 +9,12 @@
frappe.reload_doc('stock', 'doctype', 'purchase_receipt')
frappe.reload_doc('accounts', 'doctype', 'sales_invoice')
frappe.reload_doc('accounts', 'doctype', 'purchase_invoice')
-
+
doctypes = ["Sales Order", "Sales Invoice", "Delivery Note",\
"Purchase Order", "Purchase Invoice", "Purchase Receipt", "Quotation", "Supplier Quotation"]
for doctype in doctypes:
- total_qty = frappe.db.sql('''
+ total_qty = frappe.db.sql('''
SELECT
parent, SUM(qty) as qty
FROM
@@ -22,14 +22,25 @@
GROUP BY parent
''' % (doctype), as_dict = True)
- when_then = []
- for d in total_qty:
- when_then.append("""
- when dt.name = '{0}' then {1}
- """.format(frappe.db.escape(d.get("parent")), d.get("qty")))
+ # Query to update total_qty might become too big, Update in batches
+ # batch_size is chosen arbitrarily, Don't try too hard to reason about it
+ batch_size = 100000
+ for i in range(0, len(total_qty), batch_size):
+ batch_transactions = total_qty[i:i + batch_size]
- if when_then:
- frappe.db.sql('''
- UPDATE
- `tab%s` dt SET dt.total_qty = CASE %s ELSE 0.0 END
- ''' % (doctype, " ".join(when_then)))
\ No newline at end of file
+ # UPDATE with CASE for some reason cannot use PRIMARY INDEX,
+ # causing all rows to be examined, leading to a very slow update
+
+ # UPDATE with WHERE clause uses PRIMARY INDEX, but will lead to too many queries
+
+ # INSERT with ON DUPLICATE KEY UPDATE uses PRIMARY INDEX
+ # and can perform multiple updates per query
+ # This is probably never used anywhere else as of now, but should be
+ values = []
+ for d in batch_transactions:
+ values.append("('{}', {})".format(d.parent, d.qty))
+ conditions = ",".join(values)
+ frappe.db.sql("""
+ INSERT INTO `tab{}` (name, total_qty) VALUES {}
+ ON DUPLICATE KEY UPDATE name = VALUES(name), total_qty = VALUES(total_qty)
+ """.format(doctype, conditions))
diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js
index 21e02b7..a2d44c3 100644
--- a/erpnext/public/js/controllers/taxes_and_totals.js
+++ b/erpnext/public/js/controllers/taxes_and_totals.js
@@ -13,8 +13,8 @@
+ flt(effective_item_rate) * ( flt(item.margin_rate_or_amount) / 100);
} else {
item.rate_with_margin = flt(effective_item_rate) + flt(item.margin_rate_or_amount);
- item.base_rate_with_margin = flt(item.rate_with_margin) * flt(this.frm.doc.conversion_rate);
}
+ item.base_rate_with_margin = flt(item.rate_with_margin) * flt(this.frm.doc.conversion_rate);
item.rate = flt(item.rate_with_margin , precision("rate", item));
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index f3c29fc..a33b87f 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -33,6 +33,7 @@
item.margin_rate_or_amount = 0;
item.rate_with_margin = 0;
}
+ item.base_rate_with_margin = item.rate_with_margin * flt(this.frm.doc.conversion_rate);
cur_frm.cscript.set_gross_profit(item);
cur_frm.cscript.calculate_taxes_and_totals();
diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py
index c754121..d282f5c 100644
--- a/erpnext/regional/india/setup.py
+++ b/erpnext/regional/india/setup.py
@@ -85,7 +85,7 @@
def make_custom_fields(update=True):
hsn_sac_field = dict(fieldname='gst_hsn_code', label='HSN/SAC',
- fieldtype='Data', options='item_code.gst_hsn_code', insert_after='description',
+ fieldtype='Data', fetch_from='item_code.gst_hsn_code', insert_after='description',
allow_on_submit=1, print_hide=1)
invoice_gst_fields = [
dict(fieldname='gst_section', label='GST Details', fieldtype='Section Break',
diff --git a/erpnext/stock/doctype/item_barcode/item_barcode.json b/erpnext/stock/doctype/item_barcode/item_barcode.json
index c8a3a89..d89ca55 100644
--- a/erpnext/stock/doctype/item_barcode/item_barcode.json
+++ b/erpnext/stock/doctype/item_barcode/item_barcode.json
@@ -1,5 +1,6 @@
{
"allow_copy": 0,
+ "allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
@@ -15,6 +16,7 @@
"fields": [
{
"allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -38,13 +40,15 @@
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
- "reqd": 1,
+ "reqd": 0,
"search_index": 0,
"set_only_once": 0,
+ "translatable": 0,
"unique": 1
},
{
"allow_bulk_edit": 0,
+ "allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -72,6 +76,7 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
+ "translatable": 0,
"unique": 0
}
],
@@ -85,7 +90,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
- "modified": "2017-12-10 20:55:23.814039",
+ "modified": "2018-11-13 06:03:09.814357",
"modified_by": "Administrator",
"module": "Stock",
"name": "Item Barcode",
@@ -99,5 +104,6 @@
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
- "track_seen": 0
+ "track_seen": 0,
+ "track_views": 0
}
\ No newline at end of file
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index e482f58..f006d00 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -185,7 +185,8 @@
if warehouse_account.get(d.warehouse):
stock_value_diff = frappe.db.get_value("Stock Ledger Entry",
{"voucher_type": "Purchase Receipt", "voucher_no": self.name,
- "voucher_detail_no": d.name}, "stock_value_difference")
+ "voucher_detail_no": d.name, "warehouse": d.warehouse}, "stock_value_difference")
+
if not stock_value_diff:
continue
gl_entries.append(self.get_gl_dict({