diff --git a/erpnext/__init__.py b/erpnext/__init__.py index bfe8539d5ee..2f29a025b29 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -5,7 +5,7 @@ import frappe from erpnext.hooks import regional_overrides from frappe.utils import getdate -__version__ = '11.1.53' +__version__ = '11.1.54' def get_default_company(user=None): '''Get default company for user''' diff --git a/erpnext/accounts/doctype/account/account_tree.js b/erpnext/accounts/doctype/account/account_tree.js index 3614881db31..0fd21f81332 100644 --- a/erpnext/accounts/doctype/account/account_tree.js +++ b/erpnext/accounts/doctype/account/account_tree.js @@ -121,7 +121,10 @@ frappe.treeview_settings["Account"] = { }, onrender: function(node) { if(frappe.boot.user.can_read.indexOf("GL Entry") !== -1){ - var dr_or_cr = in_list(["Liability", "Income", "Equity"], node.data.root_type) ? "Cr" : "Dr"; + + // show Dr if positive since balance is calculated as debit - credit else show Cr + let dr_or_cr = node.data.balance_in_account_currency > 0 ? "Dr": "Cr"; + if (node.data && node.data.balance!==undefined) { $('' + (node.data.balance_in_account_currency ? diff --git a/erpnext/accounts/doctype/accounting_period/accounting_period.json b/erpnext/accounts/doctype/accounting_period/accounting_period.json index ed30b83c260..57f8e32dc68 100644 --- a/erpnext/accounts/doctype/accounting_period/accounting_period.json +++ b/erpnext/accounts/doctype/accounting_period/accounting_period.json @@ -167,39 +167,7 @@ "set_only_once": 0, "translatable": 0, "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "status", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Status", - "length": 0, - "no_copy": 0, - "options": "Open\nClosed", - "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, - "translatable": 0, - "unique": 0 - }, + }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -273,7 +241,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-04-13 19:14:47.593753", + "modified": "2019-08-01 19:14:47.593753", "modified_by": "Administrator", "module": "Accounts", "name": "Accounting Period", diff --git a/erpnext/accounts/doctype/accounting_period/accounting_period.py b/erpnext/accounts/doctype/accounting_period/accounting_period.py index 1a366d2f7fb..180460c091c 100644 --- a/erpnext/accounts/doctype/accounting_period/accounting_period.py +++ b/erpnext/accounts/doctype/accounting_period/accounting_period.py @@ -4,8 +4,10 @@ from __future__ import unicode_literals import frappe -from frappe import _ from frappe.model.document import Document +from frappe import _ + +class OverlapError(frappe.ValidationError): pass class AccountingPeriod(Document): def validate(self): @@ -34,12 +36,13 @@ class AccountingPeriod(Document): }, as_dict=True) if len(existing_accounting_period) > 0: - frappe.throw(_("Accounting Period overlaps with {0}".format(existing_accounting_period[0].get("name")))) + frappe.throw(_("Accounting Period overlaps with {0}") + .format(existing_accounting_period[0].get("name")), OverlapError) def get_doctypes_for_closing(self): docs_for_closing = [] - #if not self.closed_documents or len(self.closed_documents) == 0: - doctypes = ["Sales Invoice", "Purchase Invoice", "Journal Entry", "Payroll Entry", "Bank Reconciliation", "Asset", "Purchase Order", "Sales Order", "Leave Application", "Leave Allocation", "Stock Entry"] + doctypes = ["Sales Invoice", "Purchase Invoice", "Journal Entry", "Payroll Entry", "Bank Reconciliation", + "Asset", "Purchase Order", "Sales Order", "Leave Application", "Leave Allocation", "Stock Entry"] closed_doctypes = [{"document_type": doctype, "closed": 1} for doctype in doctypes] for closed_doctype in closed_doctypes: docs_for_closing.append(closed_doctype) @@ -52,4 +55,4 @@ class AccountingPeriod(Document): self.append('closed_documents', { "document_type": doctype_for_closing.document_type, "closed": doctype_for_closing.closed - }) + }) \ No newline at end of file diff --git a/erpnext/accounts/doctype/accounting_period/test_accounting_period.py b/erpnext/accounts/doctype/accounting_period/test_accounting_period.py index 29deefdbedb..022d7a7e804 100644 --- a/erpnext/accounts/doctype/accounting_period/test_accounting_period.py +++ b/erpnext/accounts/doctype/accounting_period/test_accounting_period.py @@ -5,23 +5,42 @@ from __future__ import unicode_literals import frappe import unittest +from frappe.utils import nowdate, add_months +from erpnext.accounts.general_ledger import ClosedAccountingPeriod +from erpnext.accounts.doctype.accounting_period.accounting_period import OverlapError +from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice -# class TestAccountingPeriod(unittest.TestCase): -# def test_overlap(self): -# ap1 = create_accounting_period({"start_date":"2018-04-01", "end_date":"2018-06-30", "company":"Wind Power LLC"}) -# ap1.save() -# ap2 = create_accounting_period({"start_date":"2018-06-30", "end_date":"2018-07-10", "company":"Wind Power LLC"}) -# self.assertRaises(frappe.OverlapError, accounting_period_2.save()) -# -# def tearDown(self): -# pass -# -# -# def create_accounting_period(**args): -# accounting_period = frappe.new_doc("Accounting Period") -# accounting_period.start_date = args.start_date or frappe.utils.datetime.date(2018, 4, 1) -# accounting_period.end_date = args.end_date or frappe.utils.datetime.date(2018, 6, 30) -# accounting_period.company = args.company -# accounting_period.period_name = "_Test_Period_Name_1" -# -# return accounting_period +class TestAccountingPeriod(unittest.TestCase): + def test_overlap(self): + ap1 = create_accounting_period(start_date = "2018-04-01", + end_date = "2018-06-30", company = "Wind Power LLC") + ap1.save() + + ap2 = create_accounting_period(start_date = "2018-06-30", + end_date = "2018-07-10", company = "Wind Power LLC", period_name = "Test Accounting Period 1") + self.assertRaises(OverlapError, ap2.save) + + def test_accounting_period(self): + ap1 = create_accounting_period(period_name = "Test Accounting Period 2") + ap1.save() + + doc = create_sales_invoice(do_not_submit=1, cost_center = "_Test Company - _TC", warehouse = "Stores - _TC") + self.assertRaises(ClosedAccountingPeriod, doc.submit) + + def tearDown(self): + for d in frappe.get_all("Accounting Period"): + frappe.delete_doc("Accounting Period", d.name) + +def create_accounting_period(**args): + args = frappe._dict(args) + + accounting_period = frappe.new_doc("Accounting Period") + accounting_period.start_date = args.start_date or nowdate() + accounting_period.end_date = args.end_date or add_months(nowdate(), 1) + accounting_period.company = args.company or "_Test Company" + accounting_period.period_name =args.period_name or "_Test_Period_Name_1" + accounting_period.append("closed_documents", { + "document_type": 'Sales Invoice', "closed": 1 + }) + + return accounting_period \ No newline at end of file diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py index a40e99a8d93..a2368ba8a12 100644 --- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py +++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py @@ -50,7 +50,7 @@ class BankTransaction(StatusUpdater): if paid_amount and allocated_amount: if flt(allocated_amount[0]["allocated_amount"]) > flt(paid_amount): frappe.throw(_("The total allocated amount ({0}) is greated than the paid amount ({1}).".format(flt(allocated_amount[0]["allocated_amount"]), flt(paid_amount)))) - elif flt(allocated_amount[0]["allocated_amount"]) == flt(paid_amount): + else: if payment_entry.payment_document in ["Payment Entry", "Journal Entry", "Purchase Invoice", "Expense Claim"]: self.clear_simple_entry(payment_entry) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index ecb841ce9dd..bfe82a0c3e5 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -78,6 +78,7 @@ class SalesInvoice(SellingController): self.so_dn_required() self.validate_proj_cust() + self.validate_pos_return() self.validate_with_previous_doc() self.validate_uom_is_integer("stock_uom", "stock_qty") self.validate_uom_is_integer("uom", "qty") @@ -199,6 +200,16 @@ class SalesInvoice(SellingController): if "Healthcare" in active_domains: manage_invoice_submit_cancel(self, "on_submit") + def validate_pos_return(self): + + if self.is_pos and self.is_return: + total_amount_in_payments = 0 + for payment in self.payments: + total_amount_in_payments += payment.amount + + if total_amount_in_payments < self.rounded_total: + frappe.throw(_("Total payments amount can't be greater than {}".format(-self.rounded_total))) + def validate_pos_paid_amount(self): if len(self.payments) == 0 and self.is_pos: frappe.throw(_("At least one mode of payment is required for POS invoice.")) diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py index 36cba427186..f2b9fb4f027 100644 --- a/erpnext/accounts/general_ledger.py +++ b/erpnext/accounts/general_ledger.py @@ -9,11 +9,13 @@ from frappe.model.meta import get_field_precision from erpnext.accounts.doctype.budget.budget import validate_expense_against_budget +class ClosedAccountingPeriod(frappe.ValidationError): pass class StockAccountInvalidTransaction(frappe.ValidationError): pass def make_gl_entries(gl_map, cancel=False, adv_adj=False, merge_entries=True, update_outstanding='Yes', from_repost=False): if gl_map: if not cancel: + validate_accounting_period(gl_map) gl_map = process_gl_map(gl_map, merge_entries) if gl_map and len(gl_map) > 1: save_entries(gl_map, adv_adj, update_outstanding, from_repost) @@ -22,6 +24,27 @@ def make_gl_entries(gl_map, cancel=False, adv_adj=False, merge_entries=True, upd else: delete_gl_entries(gl_map, adv_adj=adv_adj, update_outstanding=update_outstanding) +def validate_accounting_period(gl_map): + accounting_periods = frappe.db.sql(""" SELECT + ap.name as name + FROM + `tabAccounting Period` ap, `tabClosed Document` cd + WHERE + ap.name = cd.parent + AND ap.company = %(company)s + AND cd.closed = 1 + AND cd.document_type = %(voucher_type)s + AND %(date)s between ap.start_date and ap.end_date + """, { + 'date': gl_map[0].posting_date, + 'company': gl_map[0].company, + 'voucher_type': gl_map[0].voucher_type + }, as_dict=1) + + if accounting_periods: + frappe.throw(_("You can't create accounting entries in the closed accounting period {0}") + .format(accounting_periods[0].name), ClosedAccountingPeriod) + def process_gl_map(gl_map, merge_entries=True): if merge_entries: gl_map = merge_similar_entries(gl_map) diff --git a/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.html b/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.html index 889b7f71aa5..2c015192c4b 100644 --- a/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.html +++ b/erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.html @@ -4,7 +4,7 @@ {%- macro render_currency(df, doc) -%}
+ {%- if doc.align_labels_right %} text-right{%- endif -%}">
@@ -23,7 +23,7 @@ {%- for charge in data -%} {%- if (charge.tax_amount or doc.flags.print_taxes_with_zero_amount) and (not charge.included_in_print_rate or doc.flags.show_inclusive_tax_in_print) -%}
-
+
{{ frappe.utils.fmt_money((charge.tax_amount)|int|abs, currency=doc.currency) }} @@ -103,8 +103,8 @@ {% for section in page %}
{% if section.columns.fields %} - {%- if doc._line_breaks and loop.index != 1 -%}
{%- endif -%} - {%- if doc._show_section_headings and section.label and section.has_data -%} + {%- if doc.print_line_breaks and loop.index != 1 -%}
{%- endif -%} + {%- if doc.print_section_headings and section.label and section.has_data -%}

{{ _(section.label) }}

{% endif %} {%- endif -%} diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index 56480144e85..12cf96b1ac0 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -472,7 +472,7 @@ def make_rm_stock_entry(purchase_order, rm_items): 'from_warehouse': rm_item_data["warehouse"], 'stock_uom': rm_item_data["stock_uom"], 'main_item_code': rm_item_data["item_code"], - 'allow_alternative_item': item_wh[rm_item_code].get('allow_alternative_item') + 'allow_alternative_item': item_wh.get(rm_item_code, {}).get('allow_alternative_item') } } stock_entry.add_to_stock_entry_detail(items_dict) diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index 74427436fa4..14fe35e7821 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -717,7 +717,7 @@ def get_items_from_bom(item_code, bom, exploded_item=1): where t2.parent = t1.name and t1.item = %s and t1.docstatus = 1 and t1.is_active = 1 and t1.name = %s - and t2.item_code = t3.name and t3.is_stock_item = 1""".format(doctype), + and t2.item_code = t3.name""".format(doctype), (item_code, bom), as_dict=1) if not bom_items: diff --git a/erpnext/controllers/website_list_for_contact.py b/erpnext/controllers/website_list_for_contact.py index 187eaed107f..0738fd506f2 100644 --- a/erpnext/controllers/website_list_for_contact.py +++ b/erpnext/controllers/website_list_for_contact.py @@ -21,42 +21,45 @@ def get_list_context(context=None): def get_transaction_list(doctype, txt=None, filters=None, limit_start=0, limit_page_length=20, order_by="modified"): user = frappe.session.user - key = None + ignore_permissions = False if not filters: filters = [] if doctype == 'Supplier Quotation': - filters.append((doctype, "docstatus", "<", 2)) + filters.append((doctype, 'docstatus', '<', 2)) else: - filters.append((doctype, "docstatus", "=", 1)) + filters.append((doctype, 'docstatus', '=', 1)) - if (user != "Guest" and is_website_user()) or doctype == 'Request for Quotation': + if (user != 'Guest' and is_website_user()) or doctype == 'Request for Quotation': parties_doctype = 'Request for Quotation Supplier' if doctype == 'Request for Quotation' else doctype # find party for this contact customers, suppliers = get_customers_suppliers(parties_doctype, user) - if not customers and not suppliers: return [] - - key, parties = get_party_details(customers, suppliers) - - if doctype == 'Request for Quotation': - return rfq_transaction_list(parties_doctype, doctype, parties, limit_start, limit_page_length) - - filters.append((doctype, key, "in", parties)) - - if key: - return post_process(doctype, get_list_for_transactions(doctype, txt, - filters=filters, fields="name",limit_start=limit_start, - limit_page_length=limit_page_length,ignore_permissions=True, - order_by="modified desc")) + if customers: + if doctype == 'Quotation': + filters.append(('quotation_to', '=', 'Customer')) + filters.append(('party_name', 'in', customers)) + else: + filters.append(('customer', 'in', customers)) + elif suppliers: + filters.append(('supplier', 'in', suppliers)) else: return [] - return post_process(doctype, get_list_for_transactions(doctype, txt, filters, limit_start, limit_page_length, - fields="name", order_by="modified desc")) + if doctype == 'Request for Quotation': + parties = customers or suppliers + return rfq_transaction_list(parties_doctype, doctype, parties, limit_start, limit_page_length) + + # Since customers and supplier do not have direct access to internal doctypes + ignore_permissions = True + + transactions = get_list_for_transactions(doctype, txt, filters, limit_start, limit_page_length, + fields='name', ignore_permissions=ignore_permissions, order_by='modified desc') + + return post_process(doctype, transactions) def get_list_for_transactions(doctype, txt, filters, limit_start, limit_page_length=20, - ignore_permissions=False,fields=None, order_by=None): + ignore_permissions=False, fields=None, order_by=None): """ Get List of transactions like Invoices, Orders """ from frappe.www.list import get_list meta = frappe.get_meta(doctype) @@ -83,16 +86,6 @@ def get_list_for_transactions(doctype, txt, filters, limit_start, limit_page_len return data -def get_party_details(customers, suppliers): - if customers: - key, parties = "customer", customers - elif suppliers: - key, parties = "supplier", suppliers - else: - key, parties = "customer", [] - - return key, parties - def rfq_transaction_list(parties_doctype, doctype, parties, limit_start, limit_page_length): data = frappe.db.sql("""select distinct parent as name, supplier from `tab{doctype}` where supplier = '{supplier}' and docstatus=1 order by modified desc limit {start}, {len}""". @@ -159,7 +152,7 @@ def has_website_permission(doc, ptype, user, verbose=False): doctype = doc.doctype customers, suppliers = get_customers_suppliers(doctype, user) if customers: - return frappe.db.exists(doctype, filters=get_customer_filter(doc, customers)) + return frappe.db.exists(doctype, get_customer_filter(doc, customers)) elif suppliers: fieldname = 'suppliers' if doctype == 'Request for Quotation' else 'supplier' return frappe.db.exists(doctype, filters={ @@ -175,7 +168,7 @@ def get_customer_filter(doc, customers): filters.name = doc.name filters[get_customer_field_name(doctype)] = ['in', customers] if doctype == 'Quotation': - filters.party_type = 'Customer' + filters.quotation_to = 'Customer' return filters def get_customer_field_name(doctype): diff --git a/erpnext/crm/doctype/opportunity/opportunity.json b/erpnext/crm/doctype/opportunity/opportunity.json index 4361fab857d..d679d16079c 100644 --- a/erpnext/crm/doctype/opportunity/opportunity.json +++ b/erpnext/crm/doctype/opportunity/opportunity.json @@ -1460,7 +1460,7 @@ "has_web_view": 0, "hide_heading": 0, "hide_toolbar": 0, - "icon": "fa fa-info-sign", + "icon": "fa fa-info-circle", "idx": 195, "image_view": 0, "in_create": 0, diff --git a/erpnext/erpnext_integrations/doctype/quickbooks_migrator/quickbooks_migrator.json b/erpnext/erpnext_integrations/doctype/quickbooks_migrator/quickbooks_migrator.json index b156006e285..9226f0a0d02 100644 --- a/erpnext/erpnext_integrations/doctype/quickbooks_migrator/quickbooks_migrator.json +++ b/erpnext/erpnext_integrations/doctype/quickbooks_migrator/quickbooks_migrator.json @@ -20,6 +20,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "status", "fieldtype": "Select", "hidden": 1, @@ -54,6 +55,7 @@ "collapsible": 1, "collapsible_depends_on": "eval:doc.client_id && doc.client_secret && doc.redirect_url", "columns": 0, + "fetch_if_empty": 0, "fieldname": "application_settings", "fieldtype": "Section Break", "hidden": 0, @@ -87,6 +89,7 @@ "collapsible": 0, "columns": 0, "default": "", + "fetch_if_empty": 0, "fieldname": "client_id", "fieldtype": "Data", "hidden": 0, @@ -120,6 +123,7 @@ "collapsible": 0, "columns": 0, "default": "", + "fetch_if_empty": 0, "fieldname": "redirect_url", "fieldtype": "Data", "hidden": 0, @@ -153,6 +157,7 @@ "collapsible": 0, "columns": 0, "default": "https://oauth.platform.intuit.com/oauth2/v1/tokens/bearer", + "fetch_if_empty": 0, "fieldname": "token_endpoint", "fieldtype": "Data", "hidden": 0, @@ -185,6 +190,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "application_column_break", "fieldtype": "Column Break", "hidden": 0, @@ -217,6 +223,7 @@ "collapsible": 0, "columns": 0, "default": "", + "fetch_if_empty": 0, "fieldname": "client_secret", "fieldtype": "Data", "hidden": 0, @@ -250,6 +257,7 @@ "collapsible": 0, "columns": 0, "default": "com.intuit.quickbooks.accounting", + "fetch_if_empty": 0, "fieldname": "scope", "fieldtype": "Data", "hidden": 0, @@ -284,6 +292,7 @@ "collapsible": 0, "columns": 0, "default": "https://quickbooks.api.intuit.com/v3", + "fetch_if_empty": 0, "fieldname": "api_endpoint", "fieldtype": "Data", "hidden": 0, @@ -316,6 +325,7 @@ "bold": 0, "collapsible": 1, "columns": 0, + "fetch_if_empty": 0, "fieldname": "authorization_settings", "fieldtype": "Section Break", "hidden": 0, @@ -349,6 +359,7 @@ "collapsible": 0, "columns": 0, "default": "https://appcenter.intuit.com/connect/oauth2", + "fetch_if_empty": 0, "fieldname": "authorization_endpoint", "fieldtype": "Data", "hidden": 0, @@ -381,6 +392,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "refresh_token", "fieldtype": "Small Text", "hidden": 1, @@ -413,6 +425,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "code", "fieldtype": "Data", "hidden": 1, @@ -445,6 +458,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "authorization_column_break", "fieldtype": "Column Break", "hidden": 0, @@ -476,6 +490,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "authorization_url", "fieldtype": "Data", "hidden": 0, @@ -508,6 +523,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "access_token", "fieldtype": "Small Text", "hidden": 1, @@ -540,6 +556,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "quickbooks_company_id", "fieldtype": "Data", "hidden": 1, @@ -572,6 +589,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "company_settings", "fieldtype": "Section Break", "hidden": 1, @@ -604,6 +622,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "company", "fieldtype": "Link", "hidden": 0, @@ -637,6 +656,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "default_shipping_account", "fieldtype": "Link", "hidden": 1, @@ -670,6 +690,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "default_warehouse", "fieldtype": "Link", "hidden": 1, @@ -703,6 +724,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "company_column_break", "fieldtype": "Column Break", "hidden": 0, @@ -734,6 +756,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "default_cost_center", "fieldtype": "Link", "hidden": 1, @@ -767,6 +790,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "fetch_if_empty": 0, "fieldname": "undeposited_funds_account", "fieldtype": "Link", "hidden": 1, @@ -804,7 +828,7 @@ "issingle": 1, "istable": 0, "max_attachments": 0, - "modified": "2018-10-17 03:12:53.506229", + "modified": "2019-08-07 05:53:00.920316", "modified_by": "Administrator", "module": "ERPNext Integrations", "name": "QuickBooks Migrator", @@ -834,7 +858,7 @@ "quick_entry": 1, "read_only": 0, "read_only_onload": 0, - "show_name_in_global_search": 1, + "show_name_in_global_search": 0, "sort_field": "modified", "sort_order": "DESC", "track_changes": 0, diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.js b/erpnext/hr/doctype/expense_claim/expense_claim.js index cfdb813cb8c..a9ad7c5a068 100644 --- a/erpnext/hr/doctype/expense_claim/expense_claim.js +++ b/erpnext/hr/doctype/expense_claim/expense_claim.js @@ -188,8 +188,7 @@ frappe.ui.form.on("Expense Claim", { frappe.set_route("query-report", "General Ledger"); }, __("View")); } - - if (frm.doc.docstatus===1 && !cint(frm.doc.is_paid) && cint(frm.doc.grand_total) > 0 + if (frm.doc.docstatus===1 && !cint(frm.doc.is_paid) && (cint(frm.doc.total_amount_reimbursed) < cint(frm.doc.total_sanctioned_amount)) && frappe.model.can_create("Payment Entry")) { frm.add_custom_button(__('Payment'), diff --git a/erpnext/public/js/controllers/buying.js b/erpnext/public/js/controllers/buying.js index cb9c23bb628..97a05dea84a 100644 --- a/erpnext/public/js/controllers/buying.js +++ b/erpnext/public/js/controllers/buying.js @@ -391,7 +391,8 @@ erpnext.buying.get_items_from_product_bundle = function(frm) { company: frm.doc.company, is_subcontracted: frm.doc.is_subcontracted, transaction_date: frm.doc.transaction_date || frm.doc.posting_date, - ignore_pricing_rule: frm.doc.ignore_pricing_rule + ignore_pricing_rule: frm.doc.ignore_pricing_rule, + doctype: frm.doc.doctype } }, freeze: true, diff --git a/erpnext/regional/italy/utils.py b/erpnext/regional/italy/utils.py index cb6b736320e..c8b90ec9ca8 100644 --- a/erpnext/regional/italy/utils.py +++ b/erpnext/regional/italy/utils.py @@ -129,6 +129,8 @@ def download_zip(files, output_filename): def get_invoice_summary(items, taxes): summary_data = frappe._dict() + + applied_tax_row_ids = [] for tax in taxes: #Include only VAT charges. if tax.charge_type == "Actual": @@ -153,7 +155,9 @@ def get_invoice_summary(items, taxes): net_amount=reference_row.tax_amount, taxable_amount=reference_row.tax_amount, item_tax_rate={tax.account_head: tax.rate}, - charges=True + charges=True, + type="Actual", + tax_row_name=tax.name ) ) @@ -165,13 +169,21 @@ def get_invoice_summary(items, taxes): item_tax_rate = json.loads(item.item_tax_rate) if item_tax_rate and tax.account_head in item_tax_rate: + if (item.get("tax_row_name") + and item.get("tax_row_name") in applied_tax_row_ids): + continue + key = cstr(item_tax_rate[tax.account_head]) if key not in summary_data: summary_data.setdefault(key, {"tax_amount": 0.0, "taxable_amount": 0.0, "tax_exemption_reason": "", "tax_exemption_law": ""}) + if item.get("type") and item.get("type") == "Actual": + applied_tax_row_ids.append(item.get("tax_row_name")) + summary_data[key]["tax_amount"] += item.tax_amount summary_data[key]["taxable_amount"] += item.net_amount + if key == "0.0": summary_data[key]["tax_exemption_reason"] = tax.tax_exemption_reason summary_data[key]["tax_exemption_law"] = tax.tax_exemption_law diff --git a/erpnext/setup/doctype/item_group/item_group.py b/erpnext/setup/doctype/item_group/item_group.py index 4107f854b38..fff07261053 100644 --- a/erpnext/setup/doctype/item_group/item_group.py +++ b/erpnext/setup/doctype/item_group/item_group.py @@ -3,7 +3,6 @@ from __future__ import unicode_literals import frappe -import urllib import copy from frappe.utils import nowdate, cint, cstr from frappe.utils.nestedset import NestedSet @@ -12,6 +11,7 @@ from frappe.website.render import clear_cache from frappe.website.doctype.website_slideshow.website_slideshow import get_slideshow from erpnext.shopping_cart.product_info import set_product_info_for_website from erpnext.utilities.product import get_qty_in_stock +from six.moves.urllib.parse import quote class ItemGroup(NestedSet, WebsiteGenerator): nsm_parent_field = 'parent_item_group' @@ -166,7 +166,7 @@ def get_item_for_list_in_html(context): # add missing absolute link in files # user may forget it during upload if (context.get("website_image") or "").startswith("files/"): - context["website_image"] = "/" + urllib.quote(context["website_image"]) + context["website_image"] = "/" + quote(context["website_image"]) context["show_availability_status"] = cint(frappe.db.get_single_value('Products Settings', 'show_availability_status')) @@ -216,4 +216,4 @@ def get_item_group_defaults(item, company): row.pop("name") return row - return frappe._dict() \ No newline at end of file + return frappe._dict() diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.js b/erpnext/stock/doctype/delivery_note/delivery_note.js index e8224eb458f..955dd9b9392 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.js +++ b/erpnext/stock/doctype/delivery_note/delivery_note.js @@ -171,7 +171,7 @@ erpnext.stock.DeliveryNoteController = erpnext.selling.SellingController.extend( }); if(!from_sales_invoice) { - this.frm.add_custom_button(__('Invoice'), function() { me.make_sales_invoice() }, + this.frm.add_custom_button(__('Sales Invoice'), function() { me.make_sales_invoice() }, __("Make")); } } diff --git a/erpnext/templates/pages/rfq.py b/erpnext/templates/pages/rfq.py index 62ec60966bb..67679a1a7d3 100644 --- a/erpnext/templates/pages/rfq.py +++ b/erpnext/templates/pages/rfq.py @@ -5,8 +5,7 @@ from __future__ import unicode_literals import frappe from frappe import _ from frappe.utils import formatdate -from erpnext.controllers.website_list_for_contact import (get_customers_suppliers, - get_party_details) +from erpnext.controllers.website_list_for_contact import get_customers_suppliers def get_context(context): context.no_cache = 1 @@ -23,8 +22,8 @@ def get_supplier(): doctype = frappe.form_dict.doctype parties_doctype = 'Request for Quotation Supplier' if doctype == 'Request for Quotation' else doctype customers, suppliers = get_customers_suppliers(parties_doctype, frappe.session.user) - key, parties = get_party_details(customers, suppliers) - return parties[0] if key == 'supplier' else '' + + return suppliers[0] if suppliers else '' def check_supplier_has_docname_access(supplier): status = True diff --git a/erpnext/templates/print_formats/includes/taxes.html b/erpnext/templates/print_formats/includes/taxes.html index 377f9a34bd1..6e984f39016 100644 --- a/erpnext/templates/print_formats/includes/taxes.html +++ b/erpnext/templates/print_formats/includes/taxes.html @@ -1,7 +1,7 @@ {%- macro render_discount_amount(doc) -%} {%- if doc.discount_amount -%}
-
+
- {{ doc.get_formatted("discount_amount", doc) }} @@ -19,7 +19,7 @@ {%- for charge in data -%} {%- if (charge.tax_amount or doc.flags.print_taxes_with_zero_amount) and (not charge.included_in_print_rate or doc.flags.show_inclusive_tax_in_print) -%}
-
+
{{ frappe.format_value(frappe.utils.flt(charge.tax_amount), diff --git a/erpnext/templates/print_formats/includes/total.html b/erpnext/templates/print_formats/includes/total.html index c13bf92760d..81799809ba7 100644 --- a/erpnext/templates/print_formats/includes/total.html +++ b/erpnext/templates/print_formats/includes/total.html @@ -1,12 +1,12 @@
{% if doc.flags.show_inclusive_tax_in_print %} -
+
{{ doc.get_formatted("net_total", doc) }}
{% else %} -
+
{{ doc.get_formatted("total", doc) }}