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

chore: release v14
This commit is contained in:
Deepesh Garg
2024-04-03 16:01:29 +05:30
committed by GitHub
13 changed files with 90 additions and 104 deletions

View File

@@ -428,7 +428,10 @@ frappe.ui.form.on("Journal Entry Account", {
} }
}, },
cost_center: function (frm, dt, dn) { cost_center: function (frm, dt, dn) {
erpnext.journal_entry.set_account_details(frm, dt, dn); // Don't reset for Gain/Loss type journals, as it will make Debit and Credit values '0'
if (frm.doc.voucher_type != "Exchange Gain Or Loss") {
erpnext.journal_entry.set_account_details(frm, dt, dn);
}
}, },
account: function (frm, dt, dn) { account: function (frm, dt, dn) {

View File

@@ -576,6 +576,7 @@
"fieldtype": "Select", "fieldtype": "Select",
"hidden": 1, "hidden": 1,
"label": "Payment Order Status", "label": "Payment Order Status",
"no_copy": 1,
"options": "Initiated\nPayment Ordered", "options": "Initiated\nPayment Ordered",
"read_only": 1 "read_only": 1
}, },

View File

@@ -1817,9 +1817,9 @@ def validate_inter_company_party(doctype, party, company, inter_company_referenc
companies = [d.company for d in companies] companies = [d.company for d in companies]
if not company in companies: if not company in companies:
frappe.throw( frappe.throw(
_("{0} not allowed to transact with {1}. Please change the Company.").format( _(
partytype, company "{0} not allowed to transact with {1}. Please change the Company or add the Company in the 'Allowed To Transact With'-Section in the Customer record."
) ).format(_(partytype), company)
) )

View File

@@ -673,7 +673,7 @@ class ReceivablePayableReport(object):
else: else:
future_amount_field = "future_amount_in_base_currency" future_amount_field = "future_amount_in_base_currency"
if row.remaining_balance > 0 and future.get(future_amount_field): if row.remaining_balance != 0 and future.get(future_amount_field):
if future.get(future_amount_field) > row.outstanding: if future.get(future_amount_field) > row.outstanding:
row.future_amount = row.outstanding row.future_amount = row.outstanding
future[future_amount_field] = future.get(future_amount_field) - row.outstanding future[future_amount_field] = future.get(future_amount_field) - row.outstanding

View File

@@ -469,11 +469,30 @@ class TestAccountsReceivable(AccountsTestMixin, FrappeTestCase):
) )
def test_future_payments(self): def test_future_payments(self):
sr = self.create_sales_invoice(do_not_submit=True)
sr.is_return = 1
sr.items[0].qty = -1
sr.items[0].rate = 10
sr.calculate_taxes_and_totals()
sr.submit()
si = self.create_sales_invoice() si = self.create_sales_invoice()
pe = get_payment_entry(si.doctype, si.name) pe = get_payment_entry(si.doctype, si.name)
pe.append(
"references",
{
"reference_doctype": sr.doctype,
"reference_name": sr.name,
"due_date": sr.due_date,
"total_amount": sr.grand_total,
"outstanding_amount": sr.outstanding_amount,
"allocated_amount": sr.outstanding_amount,
},
)
pe.posting_date = add_days(today(), 1) pe.posting_date = add_days(today(), 1)
pe.paid_amount = 90.0 pe.paid_amount = 80
pe.references[0].allocated_amount = 90.0 pe.references[0].allocated_amount = 90.0 # pe.paid_amount + sr.grand_total
pe.save().submit() pe.save().submit()
filters = { filters = {
"company": self.company, "company": self.company,
@@ -485,16 +504,21 @@ class TestAccountsReceivable(AccountsTestMixin, FrappeTestCase):
"show_future_payments": True, "show_future_payments": True,
} }
report = execute(filters)[1] report = execute(filters)[1]
self.assertEqual(len(report), 1) self.assertEqual(len(report), 2)
expected_data = [100.0, 100.0, 10.0, 90.0] expected_data = {sr.name: [10.0, -10.0, 0.0, -10], si.name: [100.0, 100.0, 10.0, 90.0]}
row = report[0] rows = report[:2]
self.assertEqual( for row in rows:
expected_data, [row.invoiced, row.outstanding, row.remaining_balance, row.future_amount] self.assertEqual(
) expected_data[row.voucher_no],
[row.invoiced or row.paid, row.outstanding, row.remaining_balance, row.future_amount],
)
pe.cancel() pe.cancel()
sr.load_from_db() # Outstanding amount is updated so a updated timestamp is needed.
sr.cancel()
# full payment in future date # full payment in future date
pe = get_payment_entry(si.doctype, si.name) pe = get_payment_entry(si.doctype, si.name)
pe.posting_date = add_days(today(), 1) pe.posting_date = add_days(today(), 1)

View File

@@ -59,10 +59,11 @@ def get_pos_entries(filters, group_by_field):
order_by += ", p.{}".format(group_by_field) order_by += ", p.{}".format(group_by_field)
select_mop_field = ", p.base_paid_amount - p.change_amount as paid_amount " select_mop_field = ", p.base_paid_amount - p.change_amount as paid_amount "
# nosemgrep
return frappe.db.sql( return frappe.db.sql(
""" """
SELECT SELECT
p.posting_date, p.name as pos_invoice, p.pos_profile, p.posting_date, p.name as pos_invoice, p.pos_profile, p.company,
p.owner, p.customer, p.is_return, p.base_grand_total as grand_total {select_mop_field} p.owner, p.customer, p.is_return, p.base_grand_total as grand_total {select_mop_field}
FROM FROM
`tabPOS Invoice` p {from_sales_invoice_payment} `tabPOS Invoice` p {from_sales_invoice_payment}
@@ -207,14 +208,14 @@ def get_columns(filters):
"label": _("Grand Total"), "label": _("Grand Total"),
"fieldname": "grand_total", "fieldname": "grand_total",
"fieldtype": "Currency", "fieldtype": "Currency",
"options": "company:currency", "options": "Company:company:default_currency",
"width": 120, "width": 120,
}, },
{ {
"label": _("Paid Amount"), "label": _("Paid Amount"),
"fieldname": "paid_amount", "fieldname": "paid_amount",
"fieldtype": "Currency", "fieldtype": "Currency",
"options": "company:currency", "options": "Company:company:default_currency",
"width": 120, "width": 120,
}, },
{ {
@@ -224,6 +225,13 @@ def get_columns(filters):
"width": 150, "width": 150,
}, },
{"label": _("Is Return"), "fieldname": "is_return", "fieldtype": "Data", "width": 80}, {"label": _("Is Return"), "fieldname": "is_return", "fieldtype": "Data", "width": 80},
{
"label": _("Company"),
"fieldname": "company",
"fieldtype": "Link",
"options": "Company",
"width": 120,
},
] ]
return columns return columns

View File

@@ -149,6 +149,7 @@ def get_data(filters):
"asset_category": asset.asset_category, "asset_category": asset.asset_category,
"purchase_date": asset.purchase_date, "purchase_date": asset.purchase_date,
"asset_value": asset_value, "asset_value": asset_value,
"company": asset.company,
} }
data.append(row) data.append(row)
@@ -379,30 +380,37 @@ def get_columns(filters):
"label": _("Gross Purchase Amount"), "label": _("Gross Purchase Amount"),
"fieldname": "gross_purchase_amount", "fieldname": "gross_purchase_amount",
"fieldtype": "Currency", "fieldtype": "Currency",
"options": "company:currency", "options": "Company:company:default_currency",
"width": 250, "width": 250,
}, },
{ {
"label": _("Opening Accumulated Depreciation"), "label": _("Opening Accumulated Depreciation"),
"fieldname": "opening_accumulated_depreciation", "fieldname": "opening_accumulated_depreciation",
"fieldtype": "Currency", "fieldtype": "Currency",
"options": "company:currency", "options": "Company:company:default_currency",
"width": 250, "width": 250,
}, },
{ {
"label": _("Depreciated Amount"), "label": _("Depreciated Amount"),
"fieldname": "depreciated_amount", "fieldname": "depreciated_amount",
"fieldtype": "Currency", "fieldtype": "Currency",
"options": "company:currency", "options": "Company:company:default_currency",
"width": 250, "width": 250,
}, },
{ {
"label": _("Asset Value"), "label": _("Asset Value"),
"fieldname": "asset_value", "fieldname": "asset_value",
"fieldtype": "Currency", "fieldtype": "Currency",
"options": "company:currency", "options": "Company:company:default_currency",
"width": 250, "width": 250,
}, },
{
"label": _("Company"),
"fieldname": "company",
"fieldtype": "Link",
"options": "Company",
"width": 120,
},
] ]
return [ return [
@@ -433,28 +441,28 @@ def get_columns(filters):
"label": _("Gross Purchase Amount"), "label": _("Gross Purchase Amount"),
"fieldname": "gross_purchase_amount", "fieldname": "gross_purchase_amount",
"fieldtype": "Currency", "fieldtype": "Currency",
"options": "company:currency", "options": "Company:company:default_currency",
"width": 100, "width": 100,
}, },
{ {
"label": _("Asset Value"), "label": _("Asset Value"),
"fieldname": "asset_value", "fieldname": "asset_value",
"fieldtype": "Currency", "fieldtype": "Currency",
"options": "company:currency", "options": "Company:company:default_currency",
"width": 100, "width": 100,
}, },
{ {
"label": _("Opening Accumulated Depreciation"), "label": _("Opening Accumulated Depreciation"),
"fieldname": "opening_accumulated_depreciation", "fieldname": "opening_accumulated_depreciation",
"fieldtype": "Currency", "fieldtype": "Currency",
"options": "company:currency", "options": "Company:company:default_currency",
"width": 90, "width": 90,
}, },
{ {
"label": _("Depreciated Amount"), "label": _("Depreciated Amount"),
"fieldname": "depreciated_amount", "fieldname": "depreciated_amount",
"fieldtype": "Currency", "fieldtype": "Currency",
"options": "company:currency", "options": "Company:company:default_currency",
"width": 100, "width": 100,
}, },
{ {
@@ -479,4 +487,11 @@ def get_columns(filters):
"options": "Location", "options": "Location",
"width": 100, "width": 100,
}, },
{
"label": _("Company"),
"fieldname": "company",
"fieldtype": "Link",
"options": "Company",
"width": 120,
},
] ]

View File

@@ -461,7 +461,7 @@
}, },
{ {
"fieldname": "other_charges_calculation", "fieldname": "other_charges_calculation",
"fieldtype": "Markdown Editor", "fieldtype": "Text Editor",
"label": "Taxes and Charges Calculation", "label": "Taxes and Charges Calculation",
"no_copy": 1, "no_copy": 1,
"oldfieldtype": "HTML", "oldfieldtype": "HTML",
@@ -927,7 +927,7 @@
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"is_submittable": 1, "is_submittable": 1,
"links": [], "links": [],
"modified": "2024-03-20 16:03:59.069145", "modified": "2024-03-28 10:20:30.231915",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Buying", "module": "Buying",
"name": "Supplier Quotation", "name": "Supplier Quotation",
@@ -995,4 +995,4 @@
"states": [], "states": [],
"timeline_field": "supplier", "timeline_field": "supplier",
"title_field": "title" "title_field": "title"
} }

View File

@@ -669,7 +669,7 @@ class StockController(AccountsController):
self.validate_multi_currency() self.validate_multi_currency()
self.validate_packed_items() self.validate_packed_items()
if self.get("is_internal_supplier"): if self.get("is_internal_supplier") and self.docstatus == 1:
self.validate_internal_transfer_qty() self.validate_internal_transfer_qty()
else: else:
self.validate_internal_transfer_warehouse() self.validate_internal_transfer_warehouse()

View File

@@ -965,6 +965,9 @@ def make_inter_company_transaction(doctype, source_name, target_doc=None):
for tax in get_taxes_and_charges(master_doctype, target.get("taxes_and_charges")): for tax in get_taxes_and_charges(master_doctype, target.get("taxes_and_charges")):
target.append("taxes", tax) target.append("taxes", tax)
if not target.get("items"):
frappe.throw(_("All items have already been received"))
def update_details(source_doc, target_doc, source_parent): def update_details(source_doc, target_doc, source_parent):
target_doc.inter_company_invoice_reference = source_doc.name target_doc.inter_company_invoice_reference = source_doc.name
if target_doc.doctype == "Purchase Receipt": if target_doc.doctype == "Purchase Receipt":
@@ -1020,6 +1023,10 @@ def make_inter_company_transaction(doctype, source_name, target_doc=None):
shipping_address_name=target_doc.shipping_address_name, shipping_address_name=target_doc.shipping_address_name,
) )
def update_item(source, target, source_parent):
if source_parent.doctype == "Delivery Note" and source.received_qty:
target.qty = flt(source.qty) + flt(source.returned_qty) - flt(source.received_qty)
doclist = get_mapped_doc( doclist = get_mapped_doc(
doctype, doctype,
source_name, source_name,
@@ -1043,6 +1050,8 @@ def make_inter_company_transaction(doctype, source_name, target_doc=None):
"Material_request_item": "material_request_item", "Material_request_item": "material_request_item",
}, },
"field_no_map": ["warehouse"], "field_no_map": ["warehouse"],
"condition": lambda item: item.received_qty < item.qty + item.returned_qty,
"postprocess": update_item,
}, },
}, },
target_doc, target_doc,

View File

@@ -9,17 +9,7 @@ import frappe
from frappe import _ from frappe import _
from frappe.model.mapper import get_mapped_doc from frappe.model.mapper import get_mapped_doc
from frappe.query_builder.functions import Sum from frappe.query_builder.functions import Sum
from frappe.utils import ( from frappe.utils import cint, comma_or, cstr, flt, format_time, formatdate, getdate, nowdate
cint,
comma_or,
cstr,
flt,
format_time,
formatdate,
getdate,
month_diff,
nowdate,
)
import erpnext import erpnext
from erpnext.accounts.general_ledger import process_gl_map from erpnext.accounts.general_ledger import process_gl_map
@@ -168,41 +158,6 @@ class StockEntry(StockController):
self.reset_default_field_value("from_warehouse", "items", "s_warehouse") self.reset_default_field_value("from_warehouse", "items", "s_warehouse")
self.reset_default_field_value("to_warehouse", "items", "t_warehouse") self.reset_default_field_value("to_warehouse", "items", "t_warehouse")
def submit(self):
if self.is_enqueue_action():
frappe.msgprint(
_(
"The task has been enqueued as a background job. In case there is any issue on processing in background, the system will add a comment about the error on this Stock Entry and revert to the Draft stage"
)
)
self.queue_action("submit", timeout=2000)
else:
self._submit()
def cancel(self):
if self.is_enqueue_action():
frappe.msgprint(
_(
"The task has been enqueued as a background job. In case there is any issue on processing in background, the system will add a comment about the error on this Stock Entry and revert to the Submitted stage"
)
)
self.queue_action("cancel", timeout=2000)
else:
self._cancel()
def is_enqueue_action(self, force=False) -> bool:
if force:
return True
if frappe.flags.in_test:
return False
# If line items are more than 100 or record is older than 6 months
if len(self.items) > 50 or month_diff(nowdate(), self.posting_date) > 6:
return True
return False
def on_submit(self): def on_submit(self):
self.update_stock_ledger() self.update_stock_ledger()

View File

@@ -1702,36 +1702,6 @@ class TestStockEntry(FrappeTestCase):
self.assertRaises(frappe.ValidationError, sr_doc.submit) self.assertRaises(frappe.ValidationError, sr_doc.submit)
def test_enqueue_action(self):
frappe.flags.in_test = False
item_code = "Test Enqueue Item - 001"
create_item(item_code=item_code, is_stock_item=1, valuation_rate=10)
doc = make_stock_entry(
item_code=item_code,
posting_date=add_to_date(today(), months=-7),
posting_time="00:00:00",
purpose="Material Receipt",
qty=10,
to_warehouse="_Test Warehouse - _TC",
do_not_submit=True,
)
self.assertTrue(doc.is_enqueue_action())
doc = make_stock_entry(
item_code=item_code,
posting_date=today(),
posting_time="00:00:00",
purpose="Material Receipt",
qty=10,
to_warehouse="_Test Warehouse - _TC",
do_not_submit=True,
)
self.assertFalse(doc.is_enqueue_action())
frappe.flags.in_test = True
def test_auto_reorder_level(self): def test_auto_reorder_level(self):
from erpnext.stock.reorder_item import reorder_item from erpnext.stock.reorder_item import reorder_item

View File

@@ -49,6 +49,7 @@ frappe.ui.form.on("Warehouse", {
frm.add_custom_button(__("Stock Balance"), function () { frm.add_custom_button(__("Stock Balance"), function () {
frappe.set_route("query-report", "Stock Balance", { frappe.set_route("query-report", "Stock Balance", {
warehouse: frm.doc.name, warehouse: frm.doc.name,
company: frm.doc.company,
}); });
}); });