diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml new file mode 100644 index 00000000000..bd622275d6d --- /dev/null +++ b/.github/workflows/backport.yml @@ -0,0 +1,26 @@ +name: Backport +on: + pull_request_target: + types: + - closed + - labeled + +jobs: + main: + runs-on: ubuntu-latest + timeout-minutes: 60 + steps: + - name: Checkout Actions + uses: actions/checkout@v2 + with: + repository: "frappe/backport" + path: ./actions + ref: develop + - name: Install Actions + run: npm install --production --prefix ./actions + - name: Run backport + uses: ./actions/backport + with: + token: ${{secrets.BACKPORT_BOT_TOKEN}} + labelsToAdd: "backport" + title: "{{originalTitle}}" diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js index bd6acb8dcb5..b0835e15372 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.js +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js @@ -593,12 +593,22 @@ frappe.ui.form.on('Payment Entry', { {fieldtype:"Column Break"}, {fieldtype:"Float", label: __("Less Than Amount"), fieldname:"outstanding_amt_less_than"}, {fieldtype:"Section Break"}, + {fieldtype:"Link", label:__("Cost Center"), fieldname:"cost_center", options:"Cost Center", + "get_query": function() { + return { + "filters": {"company": frm.doc.company} + } + } + }, + {fieldtype:"Column Break"}, + {fieldtype:"Section Break"}, {fieldtype:"Check", label: __("Allocate Payment Amount"), fieldname:"allocate_payment_amount", default:1}, ]; frappe.prompt(fields, function(filters){ frappe.flags.allocate_payment_amount = true; frm.events.validate_filters_data(frm, filters); + frm.doc.cost_center = filters.cost_center; frm.events.get_outstanding_documents(frm, filters); }, __("Filters"), __("Get Outstanding Documents")); }, diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py index ca197476c98..6a56ddaff0d 100644 --- a/erpnext/accounts/general_ledger.py +++ b/erpnext/accounts/general_ledger.py @@ -293,7 +293,8 @@ def delete_gl_entries(gl_entries=None, voucher_type=None, voucher_no=None, select account, posting_date, party_type, party, cost_center, fiscal_year,voucher_type, voucher_no, against_voucher_type, against_voucher, cost_center, company from `tabGL Entry` - where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no), as_dict=True) + where voucher_type=%s and voucher_no=%s + for update""", (voucher_type, voucher_no), as_dict=True) if gl_entries: validate_accounting_period(gl_entries) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index f1e16ce59c4..762b4dcdb71 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -1312,7 +1312,7 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil qty_unchanged = prev_qty == new_qty uom_unchanged = prev_uom == new_uom conversion_factor_unchanged = prev_con_fac == new_con_fac - date_unchanged = prev_date == new_date if prev_date and new_date else False # in case of delivery note etc + date_unchanged = prev_date == getdate(new_date) if prev_date and new_date else False # in case of delivery note etc if rate_unchanged and qty_unchanged and conversion_factor_unchanged and uom_unchanged and date_unchanged: continue diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py index 1615e901350..2b14aa9f865 100644 --- a/erpnext/controllers/status_updater.py +++ b/erpnext/controllers/status_updater.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals import frappe -from frappe.utils import flt, comma_or, nowdate, getdate +from frappe.utils import flt, comma_or, nowdate, getdate, now from frappe import _ from frappe.model.document import Document @@ -307,10 +307,14 @@ class StatusUpdater(Document): target.notify_update() def _update_modified(self, args, update_modified): - args['update_modified'] = '' - if update_modified: - args['update_modified'] = ', modified = now(), modified_by = {0}'\ - .format(frappe.db.escape(frappe.session.user)) + if not update_modified: + args['update_modified'] = '' + return + + args['update_modified'] = ', modified = {0}, modified_by = {1}'.format( + frappe.db.escape(now()), + frappe.db.escape(frappe.session.user) + ) def update_billing_status_for_zero_amount_refdoc(self, ref_dt): ref_fieldname = frappe.scrub(ref_dt) diff --git a/erpnext/manufacturing/doctype/work_order/work_order.json b/erpnext/manufacturing/doctype/work_order/work_order.json index 6152fbb8402..35462b71b68 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.json +++ b/erpnext/manufacturing/doctype/work_order/work_order.json @@ -107,6 +107,8 @@ }, { "depends_on": "eval:doc.production_item", + "fetch_from": "production_item.item_name", + "fetch_if_empty": 1, "fieldname": "item_name", "fieldtype": "Data", "label": "Item Name", @@ -470,7 +472,7 @@ "image_field": "image", "is_submittable": 1, "links": [], - "modified": "2019-12-04 11:20:04.695123", + "modified": "2021-08-16 11:20:04.695123", "modified_by": "Administrator", "module": "Manufacturing", "name": "Work Order", diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 5afcd3150c0..acda0c1955c 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -686,3 +686,4 @@ erpnext.patches.v12_0.purchase_receipt_status erpnext.patches.v12_0.add_company_link_to_einvoice_settings erpnext.patches.v12_0.add_document_type_field_for_italy_einvoicing erpnext.patches.v12_0.create_taxable_value_field_in_purchase_invoice +erpnext.patches.v12_0.show_einvoice_irn_cancelled_field \ No newline at end of file diff --git a/erpnext/patches/v12_0/show_einvoice_irn_cancelled_field.py b/erpnext/patches/v12_0/show_einvoice_irn_cancelled_field.py new file mode 100644 index 00000000000..2319c17b34c --- /dev/null +++ b/erpnext/patches/v12_0/show_einvoice_irn_cancelled_field.py @@ -0,0 +1,12 @@ +from __future__ import unicode_literals +import frappe + +def execute(): + company = frappe.get_all('Company', filters = {'country': 'India'}) + if not company: + return + + irn_cancelled_field = frappe.db.exists('Custom Field', {'dt': 'Sales Invoice', 'fieldname': 'irn_cancelled'}) + if irn_cancelled_field: + frappe.db.set_value('Custom Field', irn_cancelled_field, 'depends_on', 'eval: doc.irn') + frappe.db.set_value('Custom Field', irn_cancelled_field, 'read_only', 0) diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py index 81dcf36bd3c..c71d6bc7eaf 100644 --- a/erpnext/regional/india/setup.py +++ b/erpnext/regional/india/setup.py @@ -414,7 +414,7 @@ def make_custom_fields(update=True): dict(fieldname='ack_date', label='Ack. Date', fieldtype='Data', read_only=1, hidden=1, insert_after='ack_no', no_copy=1, print_hide=1), dict(fieldname='irn_cancelled', label='IRN Cancelled', fieldtype='Check', no_copy=1, print_hide=1, - depends_on='eval:(doc.irn_cancelled === 1)', read_only=1, allow_on_submit=1, insert_after='customer'), + depends_on='eval: doc.irn', allow_on_submit=1, insert_after='customer'), dict(fieldname='eway_bill_cancelled', label='E-Way Bill Cancelled', fieldtype='Check', no_copy=1, print_hide=1, depends_on='eval:(doc.eway_bill_cancelled === 1)', read_only=1, allow_on_submit=1, insert_after='customer'), diff --git a/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/item_group_wise_sales_target_variance.py b/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/item_group_wise_sales_target_variance.py index d7ebafc2173..8778a3ca308 100644 --- a/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/item_group_wise_sales_target_variance.py +++ b/erpnext/selling/report/sales_partner_target_variance_based_on_item_group/item_group_wise_sales_target_variance.py @@ -44,6 +44,18 @@ def get_data(filters, period_list, partner_doctype): if d.item_group not in item_groups: item_groups.append(d.item_group) + if item_groups: + child_items = [] + for item_group in item_groups: + if frappe.db.get_value("Item Group", {"name":item_group}, "is_group"): + for child_item_group in frappe.get_all("Item Group", {"parent_item_group":item_group}): + if child_item_group['name'] not in child_items: + child_items.append(child_item_group['name']) + + for item in child_items: + if item not in item_groups: + item_groups.append(item) + date_field = ("transaction_date" if filters.get('doctype') == "Sales Order" else "posting_date") diff --git a/erpnext/shopping_cart/cart.py b/erpnext/shopping_cart/cart.py index 0fded2ec6f7..891aeb0d609 100644 --- a/erpnext/shopping_cart/cart.py +++ b/erpnext/shopping_cart/cart.py @@ -206,11 +206,11 @@ def update_cart_address(address_type, address_name): if address_type.lower() == "billing": quotation.customer_address = address_name quotation.address_display = address_display - quotation.shipping_address_name == quotation.shipping_address_name or address_name + quotation.shipping_address_name = quotation.shipping_address_name or address_name elif address_type.lower() == "shipping": quotation.shipping_address_name = address_name quotation.shipping_address = address_display - quotation.customer_address == quotation.customer_address or address_name + quotation.customer_address = quotation.customer_address or address_name apply_cart_settings(quotation=quotation) @@ -279,7 +279,7 @@ def update_party(fullname, company_name=None, mobile_no=None, phone=None): party = get_party() party.customer_name = company_name or fullname - party.customer_type == "Company" if company_name else "Individual" + party.customer_type = "Company" if company_name else "Individual" contact_name = frappe.db.get_value("Contact", {"email_id": frappe.session.user}) contact = frappe.get_doc("Contact", contact_name) diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index ae796758c75..a8742eef81e 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -72,9 +72,7 @@ def get_item_details(args, doc=None, for_validate=False, overwrite_warehouse=Tru update_party_blanket_order(args, out) - if not doc or cint(doc.get('is_return')) == 0: - # get price list rate only if the invoice is not a credit or debit note - get_price_list_rate(args, item, out) + get_price_list_rate(args, item, out) if args.customer and cint(args.is_pos): out.update(get_pos_profile_item_details(args.company, args, update_data=True)) diff --git a/erpnext/stock/report/stock_balance/stock_balance.py b/erpnext/stock/report/stock_balance/stock_balance.py index 8ea98cba6f6..c1f48d78130 100644 --- a/erpnext/stock/report/stock_balance/stock_balance.py +++ b/erpnext/stock/report/stock_balance/stock_balance.py @@ -15,8 +15,6 @@ from six import iteritems def execute(filters=None): if not filters: filters = {} - validate_filters(filters) - from_date = filters.get('from_date') to_date = filters.get('to_date') @@ -293,12 +291,6 @@ def get_item_reorder_details(items): return dict((d.parent + d.warehouse, d) for d in item_reorder_details) -def validate_filters(filters): - if not (filters.get("item_code") or filters.get("warehouse")): - sle_count = flt(frappe.db.sql("""select count(name) from `tabStock Ledger Entry`""")[0][0]) - if sle_count > 500000: - frappe.throw(_("Please set filter based on Item or Warehouse due to a large amount of entries.")) - def get_variants_attributes(): '''Return all item variant attributes.''' return [i.name for i in frappe.get_all('Item Attribute')] diff --git a/requirements.txt b/requirements.txt index c49b3f5c707..9f8379c3a9a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,9 +1,9 @@ braintree==3.57.1 -frappe +# frappe # https://github.com/frappe/frappe is installed during bench-init gocardless-pro==1.11.0 googlemaps==3.1.1 pandas==0.24.2 -plaid-python>=7.0.0 +plaid-python~=7.2.1 PyGithub==1.44.1 python-stdnum==1.12 Unidecode==1.1.1