Skip to content

Commit d90c8a9

Browse files
authored
Merge pull request #46714 from frappe/version-14-hotfix
chore: release v14
2 parents 7e8d2dc + 15bb1fd commit d90c8a9

8 files changed

Lines changed: 152 additions & 24 deletions

File tree

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
name: "Auto-label PRs based on title"
2+
3+
on:
4+
pull_request_target:
5+
types: [opened, reopened]
6+
7+
jobs:
8+
add-label-if-prefix-matches:
9+
permissions:
10+
contents: read
11+
pull-requests: write
12+
runs-on: ubuntu-latest
13+
steps:
14+
- name: Check PR title and add label if it matches prefixes
15+
uses: actions/github-script@v7
16+
continue-on-error: true
17+
with:
18+
script: |
19+
const title = context.payload.pull_request.title.toLowerCase();
20+
const prefixes = ['chore', 'ci', 'style', 'test', 'refactor'];
21+
22+
// Check if the PR title starts with any of the prefixes
23+
if (prefixes.some(prefix => title.startsWith(prefix))) {
24+
await github.rest.issues.addLabels({
25+
owner: context.repo.owner,
26+
repo: context.repo.repo,
27+
issue_number: context.payload.pull_request.number,
28+
labels: ['skip-release-notes']
29+
});
30+
}

erpnext/accounts/doctype/gl_entry/gl_entry.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@
8888
"label": "Cost Center",
8989
"oldfieldname": "cost_center",
9090
"oldfieldtype": "Link",
91-
"options": "Cost Center"
91+
"options": "Cost Center",
92+
"search_index": 1
9293
},
9394
{
9495
"fieldname": "debit",
@@ -258,7 +259,7 @@
258259
"idx": 1,
259260
"in_create": 1,
260261
"links": [],
261-
"modified": "2024-03-19 18:30:49.613401",
262+
"modified": "2025-03-21 15:29:11.221890",
262263
"modified_by": "Administrator",
263264
"module": "Accounts",
264265
"name": "GL Entry",
@@ -292,4 +293,4 @@
292293
"sort_field": "modified",
293294
"sort_order": "DESC",
294295
"states": []
295-
}
296+
}

erpnext/accounts/doctype/journal_entry/journal_entry.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -433,8 +433,22 @@ def check_credit_limit(self):
433433
if customers:
434434
from erpnext.selling.doctype.customer.customer import check_credit_limit
435435

436+
customer_details = frappe._dict(
437+
frappe.db.get_all(
438+
"Customer Credit Limit",
439+
filters={
440+
"parent": ["in", customers],
441+
"parenttype": ["=", "Customer"],
442+
"company": ["=", self.company],
443+
},
444+
fields=["parent", "bypass_credit_limit_check"],
445+
as_list=True,
446+
)
447+
)
448+
436449
for customer in customers:
437-
check_credit_limit(customer, self.company)
450+
ignore_outstanding_sales_order = bool(customer_details.get(customer))
451+
check_credit_limit(customer, self.company, ignore_outstanding_sales_order)
438452

439453
def validate_cheque_info(self):
440454
if self.voucher_type in ["Bank Entry"]:

erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
from frappe.model.document import Document
77
from frappe.utils.data import comma_and
88

9+
from erpnext.stock import get_warehouse_account_map
10+
911

1012
class RepostAccountingLedger(Document):
1113
def __init__(self, *args, **kwargs):
@@ -77,6 +79,9 @@ def generate_preview_data(self):
7779
doc = frappe.get_doc(x.voucher_type, x.voucher_no)
7880
if doc.doctype in ["Payment Entry", "Journal Entry"]:
7981
gle_map = doc.build_gl_map()
82+
elif doc.doctype == "Purchase Receipt":
83+
warehouse_account_map = get_warehouse_account_map(doc.company)
84+
gle_map = doc.get_gl_entries(warehouse_account_map)
8085
else:
8186
gle_map = doc.get_gl_entries()
8287

@@ -155,6 +160,14 @@ def start_repost(account_repost_doc=str) -> None:
155160
doc.force_set_against_expense_account()
156161
doc.make_gl_entries()
157162

163+
elif doc.doctype == "Purchase Receipt":
164+
if not repost_doc.delete_cancelled_entries:
165+
doc.docstatus = 2
166+
doc.make_gl_entries_on_cancel()
167+
168+
doc.docstatus = 1
169+
doc.make_gl_entries(from_repost=True)
170+
158171
elif doc.doctype in ["Payment Entry", "Journal Entry", "Expense Claim"]:
159172
if not repost_doc.delete_cancelled_entries:
160173
doc.make_gl_entries(1)

erpnext/accounts/doctype/repost_accounting_ledger/test_repost_accounting_ledger.py

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
1313
from erpnext.accounts.test.accounts_mixin import AccountsTestMixin
1414
from erpnext.accounts.utils import get_fiscal_year
15+
from erpnext.stock.doctype.item.test_item import make_item
16+
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import get_gl_entries, make_purchase_receipt
1517

1618

1719
class TestRepostAccountingLedger(AccountsTestMixin, FrappeTestCase):
@@ -202,9 +204,81 @@ def test_05_without_deletion_flag(self):
202204
self.assertIsNotNone(frappe.db.exists("GL Entry", {"voucher_no": si.name, "is_cancelled": 1}))
203205
self.assertIsNotNone(frappe.db.exists("GL Entry", {"voucher_no": pe.name, "is_cancelled": 1}))
204206

207+
def test_06_repost_purchase_receipt(self):
208+
from erpnext.accounts.doctype.account.test_account import create_account
209+
210+
provisional_account = create_account(
211+
account_name="Provision Account",
212+
parent_account="Current Liabilities - _TC",
213+
company=self.company,
214+
)
215+
216+
another_provisional_account = create_account(
217+
account_name="Another Provision Account",
218+
parent_account="Current Liabilities - _TC",
219+
company=self.company,
220+
)
221+
222+
company = frappe.get_doc("Company", self.company)
223+
company.enable_provisional_accounting_for_non_stock_items = 1
224+
company.default_provisional_account = provisional_account
225+
company.save()
226+
227+
test_cc = company.cost_center
228+
default_expense_account = company.default_expense_account
229+
230+
item = make_item(properties={"is_stock_item": 0})
231+
232+
pr = make_purchase_receipt(company=self.company, item_code=item.name, rate=1000.0, qty=1.0)
233+
pr_gl_entries = get_gl_entries(pr.doctype, pr.name, skip_cancelled=True)
234+
expected_pr_gles = [
235+
{"account": provisional_account, "debit": 0.0, "credit": 1000.0, "cost_center": test_cc},
236+
{"account": default_expense_account, "debit": 1000.0, "credit": 0.0, "cost_center": test_cc},
237+
]
238+
self.assertEqual(expected_pr_gles, pr_gl_entries)
239+
240+
# change the provisional account
241+
frappe.db.set_value(
242+
"Purchase Receipt Item",
243+
pr.items[0].name,
244+
"provisional_expense_account",
245+
another_provisional_account,
246+
)
247+
248+
repost_doc = frappe.new_doc("Repost Accounting Ledger")
249+
repost_doc.company = self.company
250+
repost_doc.delete_cancelled_entries = True
251+
repost_doc.append("vouchers", {"voucher_type": pr.doctype, "voucher_no": pr.name})
252+
repost_doc.save().submit()
253+
254+
pr_gles_after_repost = get_gl_entries(pr.doctype, pr.name, skip_cancelled=True)
255+
expected_pr_gles_after_repost = [
256+
{"account": default_expense_account, "debit": 1000.0, "credit": 0.0, "cost_center": test_cc},
257+
{"account": another_provisional_account, "debit": 0.0, "credit": 1000.0, "cost_center": test_cc},
258+
]
259+
self.assertEqual(len(pr_gles_after_repost), len(expected_pr_gles_after_repost))
260+
self.assertEqual(expected_pr_gles_after_repost, pr_gles_after_repost)
261+
262+
# teardown
263+
repost_doc.cancel()
264+
repost_doc.delete()
265+
266+
pr.reload()
267+
pr.cancel()
268+
269+
company.enable_provisional_accounting_for_non_stock_items = 0
270+
company.default_provisional_account = None
271+
company.save()
272+
205273

206274
def update_repost_settings():
207-
allowed_types = ["Sales Invoice", "Purchase Invoice", "Payment Entry", "Journal Entry"]
275+
allowed_types = [
276+
"Sales Invoice",
277+
"Purchase Invoice",
278+
"Payment Entry",
279+
"Journal Entry",
280+
"Purchase Receipt",
281+
]
208282
repost_settings = frappe.get_doc("Repost Accounting Ledger Settings")
209283
for x in allowed_types:
210284
repost_settings.append("allowed_types", {"document_type": x, "allowed": True})

erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1773,17 +1773,6 @@ def test_multi_currency_gle(self):
17731773

17741774
self.assertTrue(gle)
17751775

1776-
def test_invoice_exchange_rate(self):
1777-
si = create_sales_invoice(
1778-
customer="_Test Customer USD",
1779-
debit_to="_Test Receivable USD - _TC",
1780-
currency="USD",
1781-
conversion_rate=1,
1782-
do_not_save=1,
1783-
)
1784-
1785-
self.assertRaises(frappe.ValidationError, si.save)
1786-
17871776
def test_invalid_currency(self):
17881777
# Customer currency = USD
17891778

erpnext/controllers/accounts_controller.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2459,12 +2459,17 @@ def check_conversion_rate(self):
24592459
default_currency = erpnext.get_company_currency(self.company)
24602460
if not default_currency:
24612461
throw(_("Please enter default currency in Company Master"))
2462-
if (
2463-
(self.currency == default_currency and flt(self.conversion_rate) != 1.00)
2464-
or not self.conversion_rate
2465-
or (self.currency != default_currency and flt(self.conversion_rate) == 1.00)
2466-
):
2467-
throw(_("Conversion rate cannot be 0 or 1"))
2462+
2463+
if not self.conversion_rate:
2464+
throw(_("Conversion rate cannot be 0"))
2465+
2466+
if self.currency == default_currency and flt(self.conversion_rate) != 1.00:
2467+
throw(_("Conversion rate must be 1.00 if document currency is same as company currency"))
2468+
2469+
if self.currency != default_currency and flt(self.conversion_rate) == 1.00:
2470+
frappe.msgprint(
2471+
_("Conversion rate is 1.00, but document currency is different from company currency")
2472+
)
24682473

24692474
def check_finance_books(self, item, asset):
24702475
if (

erpnext/public/js/utils.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -750,7 +750,7 @@ erpnext.utils.update_child_items = function (opts) {
750750
});
751751
}
752752

753-
new frappe.ui.Dialog({
753+
let dialog = new frappe.ui.Dialog({
754754
title: __("Update Items"),
755755
size: "extra-large",
756756
fields: [
@@ -787,7 +787,9 @@ erpnext.utils.update_child_items = function (opts) {
787787
refresh_field("items");
788788
},
789789
primary_action_label: __("Update"),
790-
}).show();
790+
});
791+
792+
dialog.show();
791793
};
792794

793795
erpnext.utils.map_current_doc = function (opts) {

0 commit comments

Comments
 (0)