diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 0a735a1da1..8c47111e01 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__ = '12.0.5' +__version__ = '12.0.7' def get_default_company(user=None): '''Get default company for user''' diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index da6b167880..401d1806f2 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -624,7 +624,7 @@ def get_outstanding_reference_documents(args): data = negative_outstanding_invoices + outstanding_invoices + orders_to_be_billed if not data: - frappe.msgprint(_("No outstanding invoices found for the {0} {1}.") + frappe.msgprint(_("No outstanding invoices found for the {0} {1} which qualify the filters you have specified") .format(args.get("party_type").lower(), args.get("party"))) return data diff --git a/erpnext/accounts/doctype/payment_order/payment_order.js b/erpnext/accounts/doctype/payment_order/payment_order.js index f2f00cebcb..ce9cfe527c 100644 --- a/erpnext/accounts/doctype/payment_order/payment_order.js +++ b/erpnext/accounts/doctype/payment_order/payment_order.js @@ -66,6 +66,7 @@ frappe.ui.form.on('Payment Order', { get_query_filters: { bank: frm.doc.bank, docstatus: 1, + payment_type: ("!=", "Receive"), bank_account: frm.doc.company_bank_account, paid_from: frm.doc.account, payment_order_status: ["=", "Initiated"], diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 874230052a..4f80b78c88 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/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index 86fd1088f5..ec3fb1fc9c 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -119,19 +119,11 @@ def get_gl_entries(filters): select_fields = """, debit, credit, debit_in_account_currency, credit_in_account_currency """ - group_by_statement = '' order_by_statement = "order by posting_date, account" if filters.get("group_by") == _("Group by Voucher"): order_by_statement = "order by posting_date, voucher_type, voucher_no" - if filters.get("group_by") == _("Group by Voucher (Consolidated)"): - group_by_statement = "group by voucher_type, voucher_no, account, cost_center" - - select_fields = """, sum(debit) as debit, sum(credit) as credit, - sum(debit_in_account_currency) as debit_in_account_currency, - sum(credit_in_account_currency) as credit_in_account_currency""" - if filters.get("include_default_book_entries"): filters['company_fb'] = frappe.db.get_value("Company", filters.get("company"), 'default_finance_book') @@ -144,11 +136,10 @@ def get_gl_entries(filters): against_voucher_type, against_voucher, account_currency, remarks, against, is_opening {select_fields} from `tabGL Entry` - where company=%(company)s {conditions} {group_by_statement} + where company=%(company)s {conditions} {order_by_statement} """.format( select_fields=select_fields, conditions=get_conditions(filters), - group_by_statement=group_by_statement, order_by_statement=order_by_statement ), filters, as_dict=1) @@ -185,7 +176,8 @@ def get_conditions(filters): if not (filters.get("account") or filters.get("party") or filters.get("group_by") in ["Group by Account", "Group by Party"]): conditions.append("posting_date >=%(from_date)s") - conditions.append("posting_date <=%(to_date)s") + + conditions.append("(posting_date <=%(to_date)s or is_opening = 'Yes')") if filters.get("project"): conditions.append("project in %(project)s") @@ -286,6 +278,7 @@ def initialize_gle_map(gl_entries, filters): def get_accountwise_gle(filters, gl_entries, gle_map): totals = get_totals_dict() entries = [] + consolidated_gle = OrderedDict() group_by = group_by_field(filters.get('group_by')) def update_value_in_dict(data, key, gle): @@ -310,12 +303,20 @@ def get_accountwise_gle(filters, gl_entries, gle_map): update_value_in_dict(totals, 'total', gle) if filters.get("group_by") != _('Group by Voucher (Consolidated)'): gle_map[gle.get(group_by)].entries.append(gle) - else: - entries.append(gle) + elif filters.get("group_by") == _('Group by Voucher (Consolidated)'): + key = (gle.get("voucher_type"), gle.get("voucher_no"), + gle.get("account"), gle.get("cost_center")) + if key not in consolidated_gle: + consolidated_gle.setdefault(key, gle) + else: + update_value_in_dict(consolidated_gle, key, gle) update_value_in_dict(gle_map[gle.get(group_by)].totals, 'closing', gle) update_value_in_dict(totals, 'closing', gle) + for key, value in consolidated_gle.items(): + entries.append(value) + return totals, entries def get_result_as_list(data, filters): diff --git a/erpnext/controllers/website_list_for_contact.py b/erpnext/controllers/website_list_for_contact.py index 187eaed107..0738fd506f 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/patches.txt b/erpnext/patches.txt index 33d4f55ae0..b6ea542554 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -596,6 +596,7 @@ erpnext.patches.v12_0.rename_pricing_rule_child_doctypes erpnext.patches.v12_0.move_target_distribution_from_parent_to_child erpnext.patches.v12_0.stock_entry_enhancements erpnext.patches.v10_0.item_barcode_childtable_migrate # 16-02-2019 #25-06-2019 +erpnext.patches.v12_0.make_item_manufacturer erpnext.patches.v12_0.move_item_tax_to_item_tax_template erpnext.patches.v11_1.set_variant_based_on erpnext.patches.v11_1.woocommerce_set_creation_user @@ -606,7 +607,6 @@ erpnext.patches.v11_1.delete_scheduling_tool erpnext.patches.v12_0.rename_tolerance_fields erpnext.patches.v12_0.make_custom_fields_for_bank_remittance #14-06-2019 execute:frappe.delete_doc_if_exists("Page", "support-analytics") -erpnext.patches.v12_0.make_item_manufacturer erpnext.patches.v12_0.remove_patient_medical_record_page erpnext.patches.v11_1.move_customer_lead_to_dynamic_column erpnext.patches.v11_1.set_default_action_for_quality_inspection diff --git a/erpnext/patches/v12_0/update_pricing_rule_fields.py b/erpnext/patches/v12_0/update_pricing_rule_fields.py index 8f8349e9b5..985613a973 100644 --- a/erpnext/patches/v12_0/update_pricing_rule_fields.py +++ b/erpnext/patches/v12_0/update_pricing_rule_fields.py @@ -5,67 +5,67 @@ from __future__ import unicode_literals import frappe parentfield = { - 'item_code': 'items', - 'item_group': 'item_groups', - 'brand': 'brands' + 'item_code': 'items', + 'item_group': 'item_groups', + 'brand': 'brands' } def execute(): - if not frappe.get_all('Pricing Rule', limit=1): - return + if not frappe.get_all('Pricing Rule', limit=1): + return - frappe.reload_doc('accounts', 'doctype', 'pricing_rule_detail') - doctypes = {'Supplier Quotation': 'buying', 'Purchase Order': 'buying', 'Purchase Invoice': 'accounts', - 'Purchase Receipt': 'stock', 'Quotation': 'selling', 'Sales Order': 'selling', - 'Sales Invoice': 'accounts', 'Delivery Note': 'stock'} + frappe.reload_doc('accounts', 'doctype', 'pricing_rule_detail') + doctypes = {'Supplier Quotation': 'buying', 'Purchase Order': 'buying', 'Purchase Invoice': 'accounts', + 'Purchase Receipt': 'stock', 'Quotation': 'selling', 'Sales Order': 'selling', + 'Sales Invoice': 'accounts', 'Delivery Note': 'stock'} - for doctype, module in doctypes.items(): - frappe.reload_doc(module, 'doctype', frappe.scrub(doctype)) + for doctype, module in doctypes.items(): + frappe.reload_doc(module, 'doctype', frappe.scrub(doctype)) - child_doc = frappe.scrub(doctype) + '_item' - frappe.reload_doc(module, 'doctype', child_doc) + child_doc = frappe.scrub(doctype) + '_item' + frappe.reload_doc(module, 'doctype', child_doc, force=True) - child_doctype = doctype + ' Item' + child_doctype = doctype + ' Item' - frappe.db.sql(""" UPDATE `tab{child_doctype}` SET pricing_rules = pricing_rule - WHERE docstatus < 2 and pricing_rule is not null and pricing_rule != '' - """.format(child_doctype= child_doctype)) + frappe.db.sql(""" UPDATE `tab{child_doctype}` SET pricing_rules = pricing_rule + WHERE docstatus < 2 and pricing_rule is not null and pricing_rule != '' + """.format(child_doctype= child_doctype)) - data = frappe.db.sql(""" SELECT pricing_rule, name, parent, - parenttype, creation, modified, docstatus, modified_by, owner, name - FROM `tab{child_doc}` where docstatus < 2 and pricing_rule is not null - and pricing_rule != ''""".format(child_doc=child_doctype), as_dict=1) + data = frappe.db.sql(""" SELECT pricing_rule, name, parent, + parenttype, creation, modified, docstatus, modified_by, owner, name + FROM `tab{child_doc}` where docstatus < 2 and pricing_rule is not null + and pricing_rule != ''""".format(child_doc=child_doctype), as_dict=1) - values = [] - for d in data: - values.append((d.pricing_rule, d.name, d.parent, 'pricing_rules', d.parenttype, - d.creation, d.modified, d.docstatus, d.modified_by, d.owner, frappe.generate_hash("", 10))) + values = [] + for d in data: + values.append((d.pricing_rule, d.name, d.parent, 'pricing_rules', d.parenttype, + d.creation, d.modified, d.docstatus, d.modified_by, d.owner, frappe.generate_hash("", 10))) - if values: - frappe.db.sql(""" INSERT INTO - `tabPricing Rule Detail` (`pricing_rule`, `child_docname`, `parent`, `parentfield`, `parenttype`, - `creation`, `modified`, `docstatus`, `modified_by`, `owner`, `name`) - VALUES {values} """.format(values=', '.join(['%s'] * len(values))), tuple(values)) + if values: + frappe.db.sql(""" INSERT INTO + `tabPricing Rule Detail` (`pricing_rule`, `child_docname`, `parent`, `parentfield`, `parenttype`, + `creation`, `modified`, `docstatus`, `modified_by`, `owner`, `name`) + VALUES {values} """.format(values=', '.join(['%s'] * len(values))), tuple(values)) - frappe.reload_doc('accounts', 'doctype', 'pricing_rule') + frappe.reload_doc('accounts', 'doctype', 'pricing_rule') - for doctype, apply_on in {'Pricing Rule Item Code': 'Item Code', - 'Pricing Rule Item Group': 'Item Group', 'Pricing Rule Brand': 'Brand'}.items(): - frappe.reload_doc('accounts', 'doctype', frappe.scrub(doctype)) + for doctype, apply_on in {'Pricing Rule Item Code': 'Item Code', + 'Pricing Rule Item Group': 'Item Group', 'Pricing Rule Brand': 'Brand'}.items(): + frappe.reload_doc('accounts', 'doctype', frappe.scrub(doctype)) - field = frappe.scrub(apply_on) - data = frappe.get_all('Pricing Rule', fields=[field, "name", "creation", "modified", - "owner", "modified_by"], filters= {'apply_on': apply_on}) + field = frappe.scrub(apply_on) + data = frappe.get_all('Pricing Rule', fields=[field, "name", "creation", "modified", + "owner", "modified_by"], filters= {'apply_on': apply_on}) - values = [] - for d in data: - values.append((d.get(field), d.name, parentfield.get(field), 'Pricing Rule', - d.creation, d.modified, d.owner, d.modified_by, frappe.generate_hash("", 10))) + values = [] + for d in data: + values.append((d.get(field), d.name, parentfield.get(field), 'Pricing Rule', + d.creation, d.modified, d.owner, d.modified_by, frappe.generate_hash("", 10))) - if values: - frappe.db.sql(""" INSERT INTO - `tab{doctype}` ({field}, parent, parentfield, parenttype, creation, modified, - owner, modified_by, name) - VALUES {values} """.format(doctype=doctype, - field=field, values=', '.join(['%s'] * len(values))), tuple(values)) \ No newline at end of file + if values: + frappe.db.sql(""" INSERT INTO + `tab{doctype}` ({field}, parent, parentfield, parenttype, creation, modified, + owner, modified_by, name) + VALUES {values} """.format(doctype=doctype, + field=field, values=', '.join(['%s'] * len(values))), tuple(values)) diff --git a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.js b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.js index 0d6cef0792..a1cea8f609 100644 --- a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.js +++ b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.js @@ -2,7 +2,7 @@ // For license information, please see license.txt frappe.ui.form.on('GSTR 3B Report', { - refresh : function(frm){ + refresh : function(frm) { if(!frm.is_new()) { frm.set_intro(__("Please save the report again to rebuild or update")); frm.add_custom_button(__('Download JSON'), function() { @@ -39,9 +39,13 @@ frappe.ui.form.on('GSTR 3B Report', { }); }); } + + let current_year = new Date().getFullYear(); + let options = [current_year, current_year-1, current_year-2]; + frm.set_df_property('year', 'options', options); }, - setup: function(frm){ + setup: function(frm) { frm.set_query('company_address', function(doc) { if(!doc.company) { frappe.throw(__('Please set Company')); diff --git a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.json b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.json index 7b0462fd4b..548d40b974 100644 --- a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.json +++ b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.json @@ -1,259 +1,73 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "autoname": "format:GSTR3B-{month}-{year}-{company_address}", - "beta": 0, - "creation": "2019-02-04 11:35:55.964639", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", + "autoname": "format:GSTR3B-{month}-{year}-{company_address}", + "creation": "2019-02-04 11:35:55.964639", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "company", + "company_address", + "year", + "month", + "json_output", + "missing_field_invoices" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "company", - "fieldtype": "Link", - "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": "Company", - "length": 0, - "no_copy": 0, - "options": "Company", - "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 - }, + "fieldname": "company", + "fieldtype": "Link", + "label": "Company", + "options": "Company" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "company_address", - "fieldtype": "Link", - "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": "Company Address", - "length": 0, - "no_copy": 0, - "options": "Address", - "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 - }, + "fieldname": "company_address", + "fieldtype": "Link", + "label": "Company Address", + "options": "Address" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "year", - "fieldtype": "Data", - "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": "Year", - "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, - "translatable": 0, - "unique": 0 - }, + "fieldname": "year", + "fieldtype": "Select", + "label": "Year" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "month", - "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": "Month", - "length": 0, - "no_copy": 0, - "options": "January\nFebruary\nMarch\nApril\nMay\nJune\nJuly\nAugust\nSeptember\nOctober\nNovember\nDecember", - "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 - }, + "fieldname": "month", + "fieldtype": "Select", + "label": "Month", + "options": "January\nFebruary\nMarch\nApril\nMay\nJune\nJuly\nAugust\nSeptember\nOctober\nNovember\nDecember" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "json_output", - "fieldtype": "Code", - "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": "JSON Output", - "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, - "translatable": 0, - "unique": 0 - }, + "fieldname": "json_output", + "fieldtype": "Code", + "label": "JSON Output" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "missing_field_invoices", - "fieldtype": "Small Text", - "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": "Invoices with no Place Of Supply", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "fieldname": "missing_field_invoices", + "fieldtype": "Small Text", + "label": "Invoices with no Place Of Supply", + "read_only": 1 } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2019-03-04 10:04:44.767655", - "modified_by": "Administrator", - "module": "Regional", - "name": "GSTR 3B Report", - "name_case": "", - "owner": "Administrator", + ], + "modified": "2019-08-10 22:30:26.727038", + "modified_by": "Administrator", + "module": "Regional", + "name": "GSTR 3B Report", + "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, "write": 1 } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1, - "track_seen": 0, - "track_views": 0 + ], + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py index aad267e90a..79dace7925 100644 --- a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py +++ b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py @@ -329,28 +329,29 @@ class GSTR3BReport(Document): d.gst_category, [] ) - if state_number != d.place_of_supply.split("-")[0]: - inter_state_supply_details[d.gst_category].append({ - "pos": d.place_of_supply, - "txval": flt(d.total, 2), - "iamt": flt(inter_state_supply_tax_mapping.get(d.place_of_supply), 2) - }) - else: - osup_det = self.report_dict["sup_details"]["osup_det"] - osup_det["txval"] = flt(osup_det["txval"] + d.total, 2) - osup_det["camt"] = flt(osup_det["camt"] + inter_state_supply_tax_mapping.get(d.place_of_supply)/2, 2) - osup_det["samt"] = flt(osup_det["samt"] + inter_state_supply_tax_mapping.get(d.place_of_supply)/2, 2) + if d.place_of_supply: + if state_number != d.place_of_supply.split("-")[0]: + inter_state_supply_details[d.gst_category].append({ + "pos": d.place_of_supply.split("-")[0], + "txval": flt(d.total, 2), + "iamt": flt(inter_state_supply_tax_mapping.get(d.place_of_supply), 2) + }) + else: + osup_det = self.report_dict["sup_details"]["osup_det"] + osup_det["txval"] = flt(osup_det["txval"] + d.total, 2) + osup_det["camt"] = flt(osup_det["camt"] + inter_state_supply_tax_mapping.get(d.place_of_supply)/2, 2) + osup_det["samt"] = flt(osup_det["samt"] + inter_state_supply_tax_mapping.get(d.place_of_supply)/2, 2) return inter_state_supply_details def get_inward_nil_exempt(self, state): - inward_nil_exempt = frappe.db.sql(""" select a.gst_state, sum(i.base_amount) as base_amount, - i.is_nil_exempt, i.is_non_gst from `tabPurchase Invoice` p , `tabPurchase Invoice Item` i, `tabAddress` a - where p.docstatus = 1 and p.name = i.parent and p.supplier_address = a.name + inward_nil_exempt = frappe.db.sql(""" select p.place_of_supply, sum(i.base_amount) as base_amount, + i.is_nil_exempt, i.is_non_gst from `tabPurchase Invoice` p , `tabPurchase Invoice Item` i + where p.docstatus = 1 and p.name = i.parent and i.is_nil_exempt = 1 or i.is_non_gst = 1 and month(p.posting_date) = %s and year(p.posting_date) = %s and p.company = %s and p.company_gstin = %s - group by a.gst_state """, (self.month_no, self.year, self.company, self.gst_details.get("gstin")), as_dict=1) + group by p.place_of_supply """, (self.month_no, self.year, self.company, self.gst_details.get("gstin")), as_dict=1) inward_nil_exempt_details = { "gst": { @@ -364,14 +365,15 @@ class GSTR3BReport(Document): } for d in inward_nil_exempt: - if d.is_nil_exempt == 1 and state == d.gst_state: - inward_nil_exempt_details["gst"]["intra"] += d.base_amount - elif d.is_nil_exempt == 1 and state != d.gst_state: - inward_nil_exempt_details["gst"]["inter"] += d.base_amount - elif d.is_non_gst == 1 and state == d.gst_state: - inward_nil_exempt_details["non_gst"]["inter"] += d.base_amount - elif d.is_non_gst == 1 and state != d.gst_state: - inward_nil_exempt_details["non_gst"]["intra"] += d.base_amount + if d.place_of_supply: + if d.is_nil_exempt == 1 and state == d.place_of_supply.split("-")[1]: + inward_nil_exempt_details["gst"]["intra"] += d.base_amount + elif d.is_nil_exempt == 1 and state != d.place_of_supply.split("-")[1]: + inward_nil_exempt_details["gst"]["inter"] += d.base_amount + elif d.is_non_gst == 1 and state == d.place_of_supply.split("-")[1]: + inward_nil_exempt_details["non_gst"]["intra"] += d.base_amount + elif d.is_non_gst == 1 and state != d.place_of_supply.split("-")[1]: + inward_nil_exempt_details["non_gst"]["inter"] += d.base_amount return inward_nil_exempt_details diff --git a/erpnext/regional/doctype/gstr_3b_report/test_gstr_3b_report.py b/erpnext/regional/doctype/gstr_3b_report/test_gstr_3b_report.py index de150f466e..fef73d9a0a 100644 --- a/erpnext/regional/doctype/gstr_3b_report/test_gstr_3b_report.py +++ b/erpnext/regional/doctype/gstr_3b_report/test_gstr_3b_report.py @@ -176,6 +176,9 @@ def create_purchase_invoices(): do_not_save=1 ) + pi1.shipping_address = "_Test Supplier GST-1-Billing" + pi1.save() + pi1.submit() def make_suppliers(): @@ -218,6 +221,7 @@ def make_suppliers(): "link_name": "_Test Registered Supplier" }) + address.is_shipping_address = 1 address.save() if not frappe.db.exists('Address', '_Test Supplier GST-2-Billing'): diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py index da29d20503..584391e1e0 100644 --- a/erpnext/setup/doctype/company/company.py +++ b/erpnext/setup/doctype/company/company.py @@ -252,7 +252,7 @@ class Company(NestedSet): def set_mode_of_payment_account(self): cash = frappe.db.get_value('Mode of Payment', {'type': 'Cash'}, 'name') if cash and self.default_cash_account \ - and not frappe.db.get_value('Mode of Payment Account', {'company': self.name, 'parent': 'Cash'}): + and not frappe.db.get_value('Mode of Payment Account', {'company': self.name, 'parent': cash}): mode_of_payment = frappe.get_doc('Mode of Payment', cash) mode_of_payment.append('accounts', { 'company': self.name, diff --git a/erpnext/setup/doctype/item_group/item_group.py b/erpnext/setup/doctype/item_group/item_group.py index cab21162c7..33ab992568 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' @@ -165,7 +165,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')) @@ -218,4 +218,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 569a03a8f1..a88bb2ad1e 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.js +++ b/erpnext/stock/doctype/delivery_note/delivery_note.js @@ -197,7 +197,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() }, __('Create')); } } diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json index a142bb9035..383fb61f51 100644 --- a/erpnext/stock/doctype/item/item.json +++ b/erpnext/stock/doctype/item/item.json @@ -468,7 +468,6 @@ }, { "default": "0", - "depends_on": "has_batch_no", "fieldname": "retain_sample", "fieldtype": "Check", "label": "Retain Sample" diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js index 7da648aad9..8266055d69 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js @@ -190,7 +190,7 @@ erpnext.stock.PurchaseReceiptController = erpnext.buying.BuyingController.extend frappe.set_route("Form", doc.doctype, doc.name); } else { - frappe.msgprint(__("Retention Stock Entry already created or Sample Quantity not provided")); + frappe.msgprint(__("Purchase Receipt doesn't have any Item for which Retain Sample is enabled.")); } } }); diff --git a/erpnext/templates/generators/item/item_details.html b/erpnext/templates/generators/item/item_details.html index 8e560333ae..4cbecb0215 100644 --- a/erpnext/templates/generators/item/item_details.html +++ b/erpnext/templates/generators/item/item_details.html @@ -9,9 +9,9 @@