Skip to content

Commit

Permalink
Merge pull request #37788 from frappe/version-14-hotfix
Browse files Browse the repository at this point in the history
chore: release v14
  • Loading branch information
rohitwaghchaure authored Oct 31, 2023
2 parents 7c2bd24 + b7b62a8 commit c117ab8
Show file tree
Hide file tree
Showing 32 changed files with 440 additions and 916 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
get_entries,
)
from erpnext.accounts.utils import get_balance_on
from erpnext.setup.utils import get_exchange_rate


class BankReconciliationTool(Document):
Expand Down Expand Up @@ -129,7 +130,7 @@ def create_journal_entry_bts(
bank_transaction = frappe.db.get_values(
"Bank Transaction",
bank_transaction_name,
fieldname=["name", "deposit", "withdrawal", "bank_account"],
fieldname=["name", "deposit", "withdrawal", "bank_account", "currency"],
as_dict=True,
)[0]
company_account = frappe.get_value("Bank Account", bank_transaction.bank_account, "account")
Expand All @@ -143,29 +144,94 @@ def create_journal_entry_bts(
)

company = frappe.get_value("Account", company_account, "company")
company_default_currency = frappe.get_cached_value("Company", company, "default_currency")
company_account_currency = frappe.get_cached_value("Account", company_account, "account_currency")
second_account_currency = frappe.get_cached_value("Account", second_account, "account_currency")

# determine if multi-currency Journal or not
is_multi_currency = (
True
if company_default_currency != company_account_currency
or company_default_currency != second_account_currency
or company_default_currency != bank_transaction.currency
else False
)

accounts = []
# Multi Currency?
accounts.append(
{
"account": second_account,
"credit_in_account_currency": bank_transaction.deposit,
"debit_in_account_currency": bank_transaction.withdrawal,
"party_type": party_type,
"party": party,
"cost_center": get_default_cost_center(company),
}
)
second_account_dict = {
"account": second_account,
"account_currency": second_account_currency,
"credit_in_account_currency": bank_transaction.deposit,
"debit_in_account_currency": bank_transaction.withdrawal,
"party_type": party_type,
"party": party,
"cost_center": get_default_cost_center(company),
}

accounts.append(
{
"account": company_account,
"bank_account": bank_transaction.bank_account,
"credit_in_account_currency": bank_transaction.withdrawal,
"debit_in_account_currency": bank_transaction.deposit,
"cost_center": get_default_cost_center(company),
}
)
company_account_dict = {
"account": company_account,
"account_currency": company_account_currency,
"bank_account": bank_transaction.bank_account,
"credit_in_account_currency": bank_transaction.withdrawal,
"debit_in_account_currency": bank_transaction.deposit,
"cost_center": get_default_cost_center(company),
}

# convert transaction amount to company currency
if is_multi_currency:
exc_rate = get_exchange_rate(bank_transaction.currency, company_default_currency, posting_date)
withdrawal_in_company_currency = flt(exc_rate * abs(bank_transaction.withdrawal))
deposit_in_company_currency = flt(exc_rate * abs(bank_transaction.deposit))
else:
withdrawal_in_company_currency = bank_transaction.withdrawal
deposit_in_company_currency = bank_transaction.deposit

# if second account is of foreign currency, convert and set debit and credit fields.
if second_account_currency != company_default_currency:
exc_rate = get_exchange_rate(second_account_currency, company_default_currency, posting_date)
second_account_dict.update(
{
"exchange_rate": exc_rate,
"credit": deposit_in_company_currency,
"debit": withdrawal_in_company_currency,
"credit_in_account_currency": flt(deposit_in_company_currency / exc_rate) or 0,
"debit_in_account_currency": flt(withdrawal_in_company_currency / exc_rate) or 0,
}
)
else:
second_account_dict.update(
{
"exchange_rate": 1,
"credit": deposit_in_company_currency,
"debit": withdrawal_in_company_currency,
"credit_in_account_currency": deposit_in_company_currency,
"debit_in_account_currency": withdrawal_in_company_currency,
}
)

# if company account is of foreign currency, convert and set debit and credit fields.
if company_account_currency != company_default_currency:
exc_rate = get_exchange_rate(company_account_currency, company_default_currency, posting_date)
company_account_dict.update(
{
"exchange_rate": exc_rate,
"credit": withdrawal_in_company_currency,
"debit": deposit_in_company_currency,
}
)
else:
company_account_dict.update(
{
"exchange_rate": 1,
"credit": withdrawal_in_company_currency,
"debit": deposit_in_company_currency,
"credit_in_account_currency": withdrawal_in_company_currency,
"debit_in_account_currency": deposit_in_company_currency,
}
)

accounts.append(second_account_dict)
accounts.append(company_account_dict)

journal_entry_dict = {
"voucher_type": entry_type,
Expand All @@ -175,6 +241,9 @@ def create_journal_entry_bts(
"cheque_no": reference_number,
"mode_of_payment": mode_of_payment,
}
if is_multi_currency:
journal_entry_dict.update({"multi_currency": True})

journal_entry = frappe.new_doc("Journal Entry")
journal_entry.update(journal_entry_dict)
journal_entry.set("accounts", accounts)
Expand Down
20 changes: 14 additions & 6 deletions erpnext/accounts/party.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from typing import Optional

import frappe
from frappe import _, msgprint, scrub
from frappe import _, msgprint, qb, scrub
from frappe.contacts.doctype.address.address import get_company_address, get_default_address
from frappe.core.doctype.user_permission.user_permission import get_permitted_documents
from frappe.model.utils import get_fetch_values
Expand Down Expand Up @@ -459,11 +459,19 @@ def generator():

def get_party_gle_currency(party_type, party, company):
def generator():
existing_gle_currency = frappe.db.sql(
"""select account_currency from `tabGL Entry`
where docstatus=1 and company=%(company)s and party_type=%(party_type)s and party=%(party)s
limit 1""",
{"company": company, "party_type": party_type, "party": party},
gl = qb.DocType("GL Entry")
existing_gle_currency = (
qb.from_(gl)
.select(gl.account_currency)
.where(
(gl.docstatus == 1)
& (gl.company == company)
& (gl.party_type == party_type)
& (gl.party == party)
& (gl.is_cancelled == 0)
)
.limit(1)
.run()
)

return existing_gle_currency[0][0] if existing_gle_currency else None
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,6 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
"label": __("Accounting Dimension"),
"fieldtype": "Link",
"options": "Accounting Dimension",
"get_query": () =>{
return {
filters: {
"disabled": 0
}
}
}
},
{
"fieldname": "fiscal_year",
Expand Down
1 change: 0 additions & 1 deletion erpnext/assets/doctype/asset/asset.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ frappe.ui.form.on('Asset', {
frm.set_query("item_code", function() {
return {
"filters": {
"disabled": 0,
"is_fixed_asset": 1,
"is_stock_item": 0
}
Expand Down
18 changes: 9 additions & 9 deletions erpnext/buying/doctype/buying_settings/buying_settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"transaction_settings_section",
"po_required",
"pr_required",
"over_order_allowance",
"blanket_order_allowance",
"column_break_12",
"maintain_same_rate",
"set_landed_cost_based_on_purchase_invoice_rate",
Expand Down Expand Up @@ -159,27 +159,27 @@
"fieldtype": "Check",
"label": "Set Landed Cost Based on Purchase Invoice Rate"
},
{
"default": "0",
"description": "Percentage you are allowed to order more against the Blanket Order Quantity. For example: If you have a Blanket Order of Quantity 100 units. and your Allowance is 10% then you are allowed to order 110 units.",
"fieldname": "over_order_allowance",
"fieldtype": "Float",
"label": "Over Order Allowance (%)"
},
{
"default": "0",
"description": "While making Purchase Invoice from Purchase Order, use Exchange Rate on Invoice's transaction date rather than inheriting it from Purchase Order. Only applies for Purchase Invoice.",
"fieldname": "use_transaction_date_exchange_rate",
"fieldtype": "Check",
"label": "Use Transaction Date Exchange Rate"
},
{
"default": "0",
"description": "Percentage you are allowed to order beyond the Blanket Order quantity.",
"fieldname": "blanket_order_allowance",
"fieldtype": "Float",
"label": "Blanket Order Allowance (%)"
}
],
"icon": "fa fa-cog",
"idx": 1,
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
"modified": "2023-10-16 16:22:03.201078",
"modified": "2023-10-25 14:03:32.520418",
"modified_by": "Administrator",
"module": "Buying",
"name": "Buying Settings",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,6 @@ frappe.query_reports["Supplier Quotation Comparison"] = {
}
}
}
else {
return {
filters: { "disabled": 0 }
}
}
}
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def validate_against_blanket_order(order_doc):
allowance = flt(
frappe.db.get_single_value(
"Selling Settings" if order_doc.doctype == "Sales Order" else "Buying Settings",
"over_order_allowance",
"blanket_order_allowance",
)
)
for bo_name, item_data in order_data.items():
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def test_purchase_order_creation(self):
po1.currency = get_company_currency(po1.company)
self.assertEqual(po1.items[0].qty, (bo.items[0].qty - bo.items[0].ordered_qty))

def test_over_order_allowance(self):
def test_blanket_order_allowance(self):
# Sales Order
bo = make_blanket_order(blanket_order_type="Selling", quantity=100)

Expand All @@ -74,7 +74,7 @@ def test_over_order_allowance(self):
so.items[0].qty = 110
self.assertRaises(frappe.ValidationError, so.submit)

frappe.db.set_single_value("Selling Settings", "over_order_allowance", 10)
frappe.db.set_single_value("Selling Settings", "blanket_order_allowance", 10)
so.submit()

# Purchase Order
Expand All @@ -87,7 +87,7 @@ def test_over_order_allowance(self):
po.items[0].qty = 110
self.assertRaises(frappe.ValidationError, po.submit)

frappe.db.set_single_value("Buying Settings", "over_order_allowance", 10)
frappe.db.set_single_value("Buying Settings", "blanket_order_allowance", 10)
po.submit()


Expand Down
4 changes: 2 additions & 2 deletions erpnext/manufacturing/doctype/job_card/job_card_calendar.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ frappe.views.calendar["Job Card"] = {
},
gantt: {
field_map: {
"start": "started_time",
"end": "started_time",
"start": "expected_start_date",
"end": "expected_end_date",
"id": "name",
"title": "subject",
"color": "color",
Expand Down
2 changes: 1 addition & 1 deletion erpnext/manufacturing/doctype/job_card/job_card_list.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
frappe.listview_settings['Job Card'] = {
has_indicator_for_draft: true,

add_fields: ["expected_start_date", "expected_end_date"],
get_indicator: function(doc) {
const status_colors = {
"Work In Progress": "orange",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1734,7 +1734,10 @@ def get_raw_materials_of_sub_assembly_items(
if not item.conversion_factor and item.purchase_uom:
item.conversion_factor = get_uom_conversion_factor(item.item_code, item.purchase_uom)

item_details.setdefault(item.get("item_code"), item)
if details := item_details.get(item.get("item_code")):
details.qty += item.get("qty")
else:
item_details.setdefault(item.get("item_code"), item)

return item_details

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1321,6 +1321,33 @@ def test_transfer_and_purchase_mrp_for_purchase_uom(self):
self.assertTrue(row.warehouse == mrp_warhouse)
self.assertEqual(row.quantity, 12)

def test_mr_qty_for_same_rm_with_different_sub_assemblies(self):
from erpnext.manufacturing.doctype.bom.test_bom import create_nested_bom

bom_tree = {
"Fininshed Goods2 For SUB Test": {
"SubAssembly2 For SUB Test": {"ChildPart2 For SUB Test": {}},
"SubAssembly3 For SUB Test": {"ChildPart2 For SUB Test": {}},
}
}

parent_bom = create_nested_bom(bom_tree, prefix="")
plan = create_production_plan(
item_code=parent_bom.item,
planned_qty=1,
ignore_existing_ordered_qty=1,
do_not_submit=1,
skip_available_sub_assembly_item=1,
warehouse="_Test Warehouse - _TC",
)

plan.get_sub_assembly_items()
plan.make_material_request()

for row in plan.mr_items:
if row.item_code == "ChildPart2 For SUB Test":
self.assertEqual(row.quantity, 2)


def create_production_plan(**args):
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ frappe.query_reports["BOM Operations Time"] = {
"options": "Item",
"get_query": () =>{
return {
filters: { "disabled": 0, "is_stock_item": 1 }
filters: { "is_stock_item": 1 }
}
}
},
Expand Down
2 changes: 2 additions & 0 deletions erpnext/patches.txt
Original file line number Diff line number Diff line change
Expand Up @@ -342,5 +342,7 @@ execute:frappe.db.set_single_value('Selling Settings', 'allow_negative_rates_for
erpnext.patches.v14_0.correct_asset_value_if_je_with_workflow
erpnext.patches.v14_0.migrate_deferred_accounts_to_item_defaults
erpnext.patches.v14_0.create_accounting_dimensions_in_sales_order_item
erpnext.patches.v14_0.rename_over_order_allowance_field
erpnext.patches.v14_0.migrate_delivery_stop_lock_field
# below migration patch should always run last
erpnext.patches.v14_0.migrate_gl_to_payment_ledger
7 changes: 7 additions & 0 deletions erpnext/patches/v14_0/migrate_delivery_stop_lock_field.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import frappe
from frappe.model.utils.rename_field import rename_field


def execute():
if frappe.db.has_column("Delivery Stop", "lock"):
rename_field("Delivery Stop", "lock", "locked")
15 changes: 15 additions & 0 deletions erpnext/patches/v14_0/rename_over_order_allowance_field.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from frappe.model.utils.rename_field import rename_field


def execute():
rename_field(
"Buying Settings",
"over_order_allowance",
"blanket_order_allowance",
)

rename_field(
"Selling Settings",
"over_order_allowance",
"blanket_order_allowance",
)
Loading

0 comments on commit c117ab8

Please sign in to comment.