Merge pull request #42448 from frappe/version-14-hotfix

chore: release v14
This commit is contained in:
ruthra kumar
2024-07-24 12:55:36 +05:30
committed by GitHub
10 changed files with 149 additions and 7 deletions

View File

@@ -200,6 +200,7 @@ class PaymentReconciliation(Document):
conditions.append(doc.docstatus == 1)
conditions.append(doc[frappe.scrub(self.party_type)] == self.party)
conditions.append(doc.is_return == 1)
conditions.append(doc.outstanding_amount != 0)
if self.payment_name:
conditions.append(doc.name.like(f"%{self.payment_name}%"))

View File

@@ -1335,6 +1335,46 @@ class TestPaymentReconciliation(FrappeTestCase):
# Should not raise frappe.exceptions.ValidationError: Payment Entry has been modified after you pulled it. Please pull it again.
pr.reconcile()
def test_cr_note_payment_limit_filter(self):
transaction_date = nowdate()
amount = 100
for _ in range(6):
self.create_sales_invoice(qty=1, rate=amount, posting_date=transaction_date)
cr_note = self.create_sales_invoice(
qty=-1, rate=amount, posting_date=transaction_date, do_not_save=True, do_not_submit=True
)
cr_note.is_return = 1
cr_note = cr_note.save().submit()
pr = self.create_payment_reconciliation()
pr.get_unreconciled_entries()
self.assertEqual(len(pr.invoices), 6)
self.assertEqual(len(pr.payments), 6)
invoices = [x.as_dict() for x in pr.get("invoices")]
payments = [x.as_dict() for x in pr.get("payments")]
pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments}))
pr.reconcile()
pr.get_unreconciled_entries()
self.assertEqual(pr.get("invoices"), [])
self.assertEqual(pr.get("payments"), [])
self.create_sales_invoice(qty=1, rate=amount, posting_date=transaction_date)
cr_note = self.create_sales_invoice(
qty=-1, rate=amount, posting_date=transaction_date, do_not_save=True, do_not_submit=True
)
cr_note.is_return = 1
cr_note = cr_note.save().submit()
# Limit should not affect in fetching the unallocated cr_note
pr.invoice_limit = 5
pr.payment_limit = 5
pr.get_unreconciled_entries()
self.assertEqual(len(pr.invoices), 1)
self.assertEqual(len(pr.payments), 1)
def make_customer(customer_name, currency=None):
if not frappe.db.exists("Customer", customer_name):

View File

@@ -428,11 +428,12 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends e
frappe.msgprint(__("Please specify Company to proceed"));
} else {
var me = this;
const for_validate = me.frm.doc.is_return ? true : false;
return this.frm.call({
doc: me.frm.doc,
method: "set_missing_values",
args: {
for_validate: true,
for_validate: for_validate,
},
callback: function (r) {
if (!r.exc) {

View File

@@ -288,13 +288,13 @@ class ReceivablePayableReport:
must_consider = False
if self.filters.get("for_revaluation_journals"):
if (abs(row.outstanding) > 0.0 / 10**self.currency_precision) or (
abs(row.outstanding_in_account_currency) > 0.0 / 10**self.currency_precision
if (abs(row.outstanding) >= 0.0 / 10**self.currency_precision) or (
abs(row.outstanding_in_account_currency) >= 0.0 / 10**self.currency_precision
):
must_consider = True
else:
if (abs(row.outstanding) > 1.0 / 10**self.currency_precision) and (
(abs(row.outstanding_in_account_currency) > 1.0 / 10**self.currency_precision)
if (abs(row.outstanding) >= 1.0 / 10**self.currency_precision) and (
(abs(row.outstanding_in_account_currency) >= 1.0 / 10**self.currency_precision)
or (row.voucher_no in self.err_journals)
):
must_consider = True

View File

@@ -955,3 +955,32 @@ class TestAccountsReceivable(AccountsTestMixin, FrappeTestCase):
self.assertEqual(
expected_data, [row.invoiced, row.outstanding, row.remaining_balance, row.future_amount]
)
def test_accounts_receivable_output_for_minor_outstanding(self):
"""
AR/AP should report miniscule outstanding of 0.01. Or else there will be slight difference with General Ledger/Trial Balance
"""
filters = {
"company": self.company,
"report_date": today(),
"range1": 30,
"range2": 60,
"range3": 90,
"range4": 120,
}
# check invoice grand total and invoiced column's value for 3 payment terms
si = self.create_sales_invoice(no_payment_schedule=True)
pe = get_payment_entry("Sales Invoice", si.name, bank_account=self.cash, party_amount=99.99)
pe.paid_from = self.debit_to
pe.save().submit()
report = execute(filters)
expected_data_after_payment = [100, 100, 99.99, 0.01]
self.assertEqual(len(report[1]), 1)
row = report[1][0]
self.assertEqual(
expected_data_after_payment,
[row.invoice_grand_total, row.invoiced, row.paid, row.outstanding],
)

View File

@@ -0,0 +1,63 @@
import frappe
from frappe.tests.utils import FrappeTestCase
from frappe.utils import getdate, today
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
from erpnext.accounts.report.item_wise_purchase_register.item_wise_purchase_register import execute
from erpnext.accounts.test.accounts_mixin import AccountsTestMixin
class TestItemWisePurchaseRegister(AccountsTestMixin, FrappeTestCase):
def setUp(self):
self.create_company()
self.create_supplier()
self.create_item()
def tearDown(self):
frappe.db.rollback()
def create_purchase_invoice(self, do_not_submit=False):
pi = make_purchase_invoice(
item=self.item,
company=self.company,
supplier=self.supplier,
is_return=False,
update_stock=False,
do_not_save=1,
rate=100,
price_list_rate=100,
qty=1,
)
pi = pi.save()
if not do_not_submit:
pi = pi.submit()
return pi
def test_basic_report_output(self):
pi = self.create_purchase_invoice()
filters = frappe._dict({"from_date": today(), "to_date": today(), "company": self.company})
report = execute(filters)
self.assertEqual(len(report[1]), 1)
expected_result = {
"item_code": pi.items[0].item_code,
"invoice": pi.name,
"posting_date": getdate(),
"supplier": pi.supplier,
"credit_to": pi.credit_to,
"company": self.company,
"expense_account": pi.items[0].expense_account,
"stock_qty": 1.0,
"stock_uom": pi.items[0].stock_uom,
"rate": 100.0,
"amount": 100.0,
"total_tax": 0,
"total": 100.0,
"currency": "INR",
}
report_output = {k: v for k, v in report[1][0].items() if k in expected_result}
self.assertDictEqual(report_output, expected_result)

View File

@@ -170,7 +170,7 @@
"fieldname": "supplier_type",
"fieldtype": "Select",
"label": "Supplier Type",
"options": "Company\nIndividual\nProprietorship\nPartnership",
"options": "Company\nIndividual\nPartnership",
"reqd": 1
},
{

View File

@@ -271,6 +271,7 @@ erpnext.patches.v13_0.create_accounting_dimensions_for_asset_repair
erpnext.patches.v14_0.update_reference_due_date_in_journal_entry
erpnext.patches.v14_0.france_depreciation_warning
erpnext.patches.v14_0.clear_reconciliation_values_from_singles
erpnext.patches.v14_0.update_proprietorship_to_individual
[post_model_sync]
execute:frappe.delete_doc_if_exists('Workspace', 'ERPNext Integrations Settings')

View File

@@ -0,0 +1,7 @@
import frappe
def execute():
for doctype in ["Customer", "Supplier"]:
field = doctype.lower() + "_type"
frappe.db.set_value(doctype, {field: "Proprietorship"}, field, "Individual")

View File

@@ -131,7 +131,7 @@
"label": "Customer Type",
"oldfieldname": "customer_type",
"oldfieldtype": "Select",
"options": "Company\nIndividual\nProprietorship\nPartnership",
"options": "Company\nIndividual\nPartnership",
"reqd": 1
},
{