Merge pull request #33358 from resilient-tech/fix-appointment-booking
fix: remove unnecessary permissions from Appointment and Appointment Booking Settings
diff --git a/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py b/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py
index 325a356..220b747 100644
--- a/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py
+++ b/erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.py
@@ -485,6 +485,10 @@
"default_payable_account": frappe.db.get_value(
"Account", {"company": company.name, "account_type": "Payable", "is_group": 0}
),
+ "default_provisional_account": frappe.db.get_value(
+ "Account",
+ {"company": company.name, "account_type": "Service Received But Not Billed", "is_group": 0},
+ ),
}
)
diff --git a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
index 30ed91b..b834d14 100644
--- a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
+++ b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
@@ -121,12 +121,24 @@
else:
tax_row = get_tax_row_for_tcs(inv, tax_details, tax_amount, tax_deducted)
+ cost_center = get_cost_center(inv)
+ tax_row.update({"cost_center": cost_center})
+
if inv.doctype == "Purchase Invoice":
return tax_row, tax_deducted_on_advances, voucher_wise_amount
else:
return tax_row
+def get_cost_center(inv):
+ cost_center = frappe.get_cached_value("Company", inv.company, "cost_center")
+
+ if len(inv.get("taxes", [])) > 0:
+ cost_center = inv.get("taxes")[0].cost_center
+
+ return cost_center
+
+
def get_tax_withholding_details(tax_withholding_category, posting_date, company):
tax_withholding = frappe.get_doc("Tax Withholding Category", tax_withholding_category)
diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
index a195c57..9d96843 100755
--- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
+++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py
@@ -99,6 +99,9 @@
# Get return entries
self.get_return_entries()
+ # Get Exchange Rate Revaluations
+ self.get_exchange_rate_revaluations()
+
self.data = []
for ple in self.ple_entries:
@@ -251,7 +254,8 @@
row.invoice_grand_total = row.invoiced
if (abs(row.outstanding) > 1.0 / 10**self.currency_precision) and (
- abs(row.outstanding_in_account_currency) > 1.0 / 10**self.currency_precision
+ (abs(row.outstanding_in_account_currency) > 1.0 / 10**self.currency_precision)
+ or (row.voucher_no in self.err_journals)
):
# non-zero oustanding, we must consider this row
@@ -1028,3 +1032,17 @@
"data": {"labels": self.ageing_column_labels, "datasets": rows},
"type": "percentage",
}
+
+ def get_exchange_rate_revaluations(self):
+ je = qb.DocType("Journal Entry")
+ results = (
+ qb.from_(je)
+ .select(je.name)
+ .where(
+ (je.company == self.filters.company)
+ & (je.posting_date.lte(self.filters.report_date))
+ & (je.voucher_type == "Exchange Rate Revaluation")
+ )
+ .run()
+ )
+ self.err_journals = [x[0] for x in results] if results else []
diff --git a/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py
index bac8bee..97a9c15 100644
--- a/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py
+++ b/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py
@@ -1,9 +1,10 @@
import unittest
import frappe
-from frappe.tests.utils import FrappeTestCase
-from frappe.utils import add_days, getdate, today
+from frappe.tests.utils import FrappeTestCase, change_settings
+from frappe.utils import add_days, flt, getdate, today
+from erpnext import get_default_cost_center
from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
from erpnext.accounts.report.accounts_receivable.accounts_receivable import execute
@@ -17,10 +18,37 @@
frappe.db.sql("delete from `tabPayment Entry` where company='_Test Company 2'")
frappe.db.sql("delete from `tabGL Entry` where company='_Test Company 2'")
frappe.db.sql("delete from `tabPayment Ledger Entry` where company='_Test Company 2'")
+ frappe.db.sql("delete from `tabJournal Entry` where company='_Test Company 2'")
+ frappe.db.sql("delete from `tabExchange Rate Revaluation` where company='_Test Company 2'")
+
+ self.create_usd_account()
def tearDown(self):
frappe.db.rollback()
+ def create_usd_account(self):
+ name = "Debtors USD"
+ exists = frappe.db.get_list(
+ "Account", filters={"company": "_Test Company 2", "account_name": "Debtors USD"}
+ )
+ if exists:
+ self.debtors_usd = exists[0].name
+ else:
+ debtors = frappe.get_doc(
+ "Account",
+ frappe.db.get_list(
+ "Account", filters={"company": "_Test Company 2", "account_name": "Debtors"}
+ )[0].name,
+ )
+
+ debtors_usd = frappe.new_doc("Account")
+ debtors_usd.company = debtors.company
+ debtors_usd.account_name = "Debtors USD"
+ debtors_usd.account_currency = "USD"
+ debtors_usd.parent_account = debtors.parent_account
+ debtors_usd.account_type = debtors.account_type
+ self.debtors_usd = debtors_usd.save().name
+
def test_accounts_receivable(self):
filters = {
"company": "_Test Company 2",
@@ -33,7 +61,7 @@
}
# check invoice grand total and invoiced column's value for 3 payment terms
- name = make_sales_invoice()
+ name = make_sales_invoice().name
report = execute(filters)
expected_data = [[100, 30], [100, 50], [100, 20]]
@@ -118,8 +146,74 @@
],
)
+ @change_settings(
+ "Accounts Settings", {"allow_multi_currency_invoices_against_single_party_account": 1}
+ )
+ def test_exchange_revaluation_for_party(self):
+ """
+ Exchange Revaluation for party on Receivable/Payable shoule be included
+ """
-def make_sales_invoice():
+ company = "_Test Company 2"
+ customer = "_Test Customer 2"
+
+ # Using Exchange Gain/Loss account for unrealized as well.
+ company_doc = frappe.get_doc("Company", company)
+ company_doc.unrealized_exchange_gain_loss_account = company_doc.exchange_gain_loss_account
+ company_doc.save()
+
+ si = make_sales_invoice(no_payment_schedule=True, do_not_submit=True)
+ si.currency = "USD"
+ si.conversion_rate = 0.90
+ si.debit_to = self.debtors_usd
+ si = si.save().submit()
+
+ # Exchange Revaluation
+ err = frappe.new_doc("Exchange Rate Revaluation")
+ err.company = company
+ err.posting_date = today()
+ accounts = err.get_accounts_data()
+ err.extend("accounts", accounts)
+ err.accounts[0].new_exchange_rate = 0.95
+ row = err.accounts[0]
+ row.new_balance_in_base_currency = flt(
+ row.new_exchange_rate * flt(row.balance_in_account_currency)
+ )
+ row.gain_loss = row.new_balance_in_base_currency - flt(row.balance_in_base_currency)
+ err.set_total_gain_loss()
+ err = err.save().submit()
+
+ # Submit JV for ERR
+ jv = frappe.get_doc(err.make_jv_entry())
+ jv = jv.save()
+ for x in jv.accounts:
+ x.cost_center = get_default_cost_center(jv.company)
+ jv.submit()
+
+ filters = {
+ "company": company,
+ "report_date": today(),
+ "range1": 30,
+ "range2": 60,
+ "range3": 90,
+ "range4": 120,
+ }
+ report = execute(filters)
+
+ expected_data_for_err = [0, -5, 0, 5]
+ row = [x for x in report[1] if x.voucher_type == jv.doctype and x.voucher_no == jv.name][0]
+ self.assertEqual(
+ expected_data_for_err,
+ [
+ row.invoiced,
+ row.paid,
+ row.credit_note,
+ row.outstanding,
+ ],
+ )
+
+
+def make_sales_invoice(no_payment_schedule=False, do_not_submit=False):
frappe.set_user("Administrator")
si = create_sales_invoice(
@@ -134,22 +228,26 @@
do_not_save=1,
)
- si.append(
- "payment_schedule",
- dict(due_date=getdate(add_days(today(), 30)), invoice_portion=30.00, payment_amount=30),
- )
- si.append(
- "payment_schedule",
- dict(due_date=getdate(add_days(today(), 60)), invoice_portion=50.00, payment_amount=50),
- )
- si.append(
- "payment_schedule",
- dict(due_date=getdate(add_days(today(), 90)), invoice_portion=20.00, payment_amount=20),
- )
+ if not no_payment_schedule:
+ si.append(
+ "payment_schedule",
+ dict(due_date=getdate(add_days(today(), 30)), invoice_portion=30.00, payment_amount=30),
+ )
+ si.append(
+ "payment_schedule",
+ dict(due_date=getdate(add_days(today(), 60)), invoice_portion=50.00, payment_amount=50),
+ )
+ si.append(
+ "payment_schedule",
+ dict(due_date=getdate(add_days(today(), 90)), invoice_portion=20.00, payment_amount=20),
+ )
- si.submit()
+ si = si.save()
- return si.name
+ if not do_not_submit:
+ si = si.submit()
+
+ return si
def make_payment(docname):
diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
index 98c7dc9..a9f5afb 100644
--- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
+++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
@@ -57,44 +57,96 @@
});
}, __("Tools"));
- frm.add_custom_button(__('Download PDF'), () => {
- var suppliers = [];
- const fields = [{
- fieldtype: 'Link',
- label: __('Select a Supplier'),
- fieldname: 'supplier',
- options: 'Supplier',
- reqd: 1,
- get_query: () => {
- return {
- filters: [
- ["Supplier", "name", "in", frm.doc.suppliers.map((row) => {return row.supplier;})]
- ]
- }
- }
- }];
-
- frappe.prompt(fields, data => {
- var child = locals[cdt][cdn]
-
- var w = window.open(
- frappe.urllib.get_full_url("/api/method/erpnext.buying.doctype.request_for_quotation.request_for_quotation.get_pdf?"
- +"doctype="+encodeURIComponent(frm.doc.doctype)
- +"&name="+encodeURIComponent(frm.doc.name)
- +"&supplier="+encodeURIComponent(data.supplier)
- +"&no_letterhead=0"));
- if(!w) {
- frappe.msgprint(__("Please enable pop-ups")); return;
- }
+ frm.add_custom_button(
+ __("Download PDF"),
+ () => {
+ frappe.prompt(
+ [
+ {
+ fieldtype: "Link",
+ label: "Select a Supplier",
+ fieldname: "supplier",
+ options: "Supplier",
+ reqd: 1,
+ default: frm.doc.suppliers?.length == 1 ? frm.doc.suppliers[0].supplier : "",
+ get_query: () => {
+ return {
+ filters: [
+ [
+ "Supplier",
+ "name",
+ "in",
+ frm.doc.suppliers.map((row) => {
+ return row.supplier;
+ }),
+ ],
+ ],
+ };
+ },
+ },
+ {
+ fieldtype: "Section Break",
+ label: "Print Settings",
+ fieldname: "print_settings",
+ collapsible: 1,
+ },
+ {
+ fieldtype: "Link",
+ label: "Print Format",
+ fieldname: "print_format",
+ options: "Print Format",
+ placeholder: "Standard",
+ get_query: () => {
+ return {
+ filters: {
+ doc_type: "Request for Quotation",
+ },
+ };
+ },
+ },
+ {
+ fieldtype: "Link",
+ label: "Language",
+ fieldname: "language",
+ options: "Language",
+ default: frappe.boot.lang,
+ },
+ {
+ fieldtype: "Link",
+ label: "Letter Head",
+ fieldname: "letter_head",
+ options: "Letter Head",
+ default: frm.doc.letter_head,
+ },
+ ],
+ (data) => {
+ var w = window.open(
+ frappe.urllib.get_full_url(
+ "/api/method/erpnext.buying.doctype.request_for_quotation.request_for_quotation.get_pdf?" +
+ new URLSearchParams({
+ doctype: frm.doc.doctype,
+ name: frm.doc.name,
+ supplier: data.supplier,
+ print_format: data.print_format || "Standard",
+ language: data.language || frappe.boot.lang,
+ letter_head: data.letter_head || frm.doc.letter_head || "",
+ }).toString()
+ )
+ );
+ if (!w) {
+ frappe.msgprint(__("Please enable pop-ups"));
+ return;
+ }
+ },
+ "Download PDF for Supplier",
+ "Download"
+ );
},
- 'Download PDF for Supplier',
- 'Download');
- },
- __("Tools"));
+ __("Tools")
+ );
- frm.page.set_inner_btn_group_as_primary(__('Create'));
+ frm.page.set_inner_btn_group_as_primary(__("Create"));
}
-
},
make_supplier_quotation: function(frm) {
diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py
index bdbc9ce..dbc3644 100644
--- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py
+++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py
@@ -389,10 +389,17 @@
@frappe.whitelist()
-def get_pdf(doctype, name, supplier):
- doc = get_rfq_doc(doctype, name, supplier)
- if doc:
- download_pdf(doctype, name, doc=doc)
+def get_pdf(doctype, name, supplier, print_format=None, language=None, letter_head=None):
+ # permissions get checked in `download_pdf`
+ if doc := get_rfq_doc(doctype, name, supplier):
+ download_pdf(
+ doctype,
+ name,
+ print_format,
+ doc=doc,
+ language=language,
+ letter_head=letter_head or None,
+ )
def get_rfq_doc(doctype, name, supplier):
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index fd19d25..7d72c76 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -420,6 +420,7 @@
"erpnext.loan_management.doctype.process_loan_security_shortfall.process_loan_security_shortfall.create_process_loan_security_shortfall",
"erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual.process_loan_interest_accrual_for_term_loans",
"erpnext.crm.utils.open_leads_opportunities_based_on_todays_event",
+ "erpnext.stock.doctype.stock_entry.stock_entry.audit_incorrect_valuation_entries",
],
"monthly_long": [
"erpnext.accounts.deferred_revenue.process_deferred_accounting",
diff --git a/erpnext/selling/report/sales_order_analysis/sales_order_analysis.js b/erpnext/selling/report/sales_order_analysis/sales_order_analysis.js
index 91748bc..f3f931e 100644
--- a/erpnext/selling/report/sales_order_analysis/sales_order_analysis.js
+++ b/erpnext/selling/report/sales_order_analysis/sales_order_analysis.js
@@ -45,6 +45,12 @@
}
},
{
+ "fieldname": "warehouse",
+ "label": __("Warehouse"),
+ "fieldtype": "Link",
+ "options": "Warehouse"
+ },
+ {
"fieldname": "status",
"label": __("Status"),
"fieldtype": "MultiSelectList",
diff --git a/erpnext/selling/report/sales_order_analysis/sales_order_analysis.py b/erpnext/selling/report/sales_order_analysis/sales_order_analysis.py
index 720aa41..63d339a 100644
--- a/erpnext/selling/report/sales_order_analysis/sales_order_analysis.py
+++ b/erpnext/selling/report/sales_order_analysis/sales_order_analysis.py
@@ -53,6 +53,9 @@
if filters.get("status"):
conditions += " and so.status in %(status)s"
+ if filters.get("warehouse"):
+ conditions += " and soi.warehouse = %(warehouse)s"
+
return conditions
diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py
index d6f2378..07ee289 100644
--- a/erpnext/setup/doctype/company/company.py
+++ b/erpnext/setup/doctype/company/company.py
@@ -70,9 +70,6 @@
self.abbr = self.abbr.strip()
- # if self.get('__islocal') and len(self.abbr) > 5:
- # frappe.throw(_("Abbreviation cannot have more than 5 characters"))
-
if not self.abbr.strip():
frappe.throw(_("Abbreviation is mandatory"))
diff --git a/erpnext/stock/doctype/pick_list/pick_list.py b/erpnext/stock/doctype/pick_list/pick_list.py
index 5de7fed..aff5e05 100644
--- a/erpnext/stock/doctype/pick_list/pick_list.py
+++ b/erpnext/stock/doctype/pick_list/pick_list.py
@@ -192,13 +192,13 @@
if item_map.get(key):
item_map[key].qty += item.qty
- item_map[key].stock_qty += item.stock_qty
+ item_map[key].stock_qty += flt(item.stock_qty, item.precision("stock_qty"))
else:
item_map[key] = item
# maintain count of each item (useful to limit get query)
self.item_count_map.setdefault(item_code, 0)
- self.item_count_map[item_code] += item.stock_qty
+ self.item_count_map[item_code] += flt(item.stock_qty, item.precision("stock_qty"))
return item_map.values()
diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py
index a2748d0..541d4d1 100644
--- a/erpnext/stock/doctype/serial_no/serial_no.py
+++ b/erpnext/stock/doctype/serial_no/serial_no.py
@@ -766,13 +766,13 @@
@frappe.whitelist()
def auto_fetch_serial_number(
- qty: float,
+ qty: int,
item_code: str,
warehouse: str,
posting_date: Optional[str] = None,
batch_nos: Optional[Union[str, List[str]]] = None,
for_doctype: Optional[str] = None,
- exclude_sr_nos: Optional[List[str]] = None,
+ exclude_sr_nos=None,
) -> List[str]:
filters = frappe._dict({"item_code": item_code, "warehouse": warehouse})
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index d401f81..a047a9b 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -4,12 +4,24 @@
import json
from collections import defaultdict
+from typing import Dict
import frappe
from frappe import _
from frappe.model.mapper import get_mapped_doc
from frappe.query_builder.functions import Sum
-from frappe.utils import cint, comma_or, cstr, flt, format_time, formatdate, getdate, nowdate
+from frappe.utils import (
+ add_days,
+ cint,
+ comma_or,
+ cstr,
+ flt,
+ format_time,
+ formatdate,
+ getdate,
+ nowdate,
+ today,
+)
import erpnext
from erpnext.accounts.general_ledger import process_gl_map
@@ -2700,3 +2712,62 @@
)
.orderby(stock_entry.creation, stock_entry_detail.item_code, stock_entry_detail.idx)
).run(as_dict=1)
+
+
+def audit_incorrect_valuation_entries():
+ # Audit of stock transfer entries having incorrect valuation
+ from erpnext.controllers.stock_controller import create_repost_item_valuation_entry
+
+ stock_entries = get_incorrect_stock_entries()
+
+ for stock_entry, values in stock_entries.items():
+ reposting_data = frappe._dict(
+ {
+ "posting_date": values.posting_date,
+ "posting_time": values.posting_time,
+ "voucher_type": "Stock Entry",
+ "voucher_no": stock_entry,
+ "company": values.company,
+ }
+ )
+
+ create_repost_item_valuation_entry(reposting_data)
+
+
+def get_incorrect_stock_entries() -> Dict:
+ stock_entry = frappe.qb.DocType("Stock Entry")
+ stock_ledger_entry = frappe.qb.DocType("Stock Ledger Entry")
+ transfer_purposes = [
+ "Material Transfer",
+ "Material Transfer for Manufacture",
+ "Send to Subcontractor",
+ ]
+
+ query = (
+ frappe.qb.from_(stock_entry)
+ .inner_join(stock_ledger_entry)
+ .on(stock_entry.name == stock_ledger_entry.voucher_no)
+ .select(
+ stock_entry.name,
+ stock_entry.company,
+ stock_entry.posting_date,
+ stock_entry.posting_time,
+ Sum(stock_ledger_entry.stock_value_difference).as_("stock_value"),
+ )
+ .where(
+ (stock_entry.docstatus == 1)
+ & (stock_entry.purpose.isin(transfer_purposes))
+ & (stock_ledger_entry.modified > add_days(today(), -2))
+ )
+ .groupby(stock_ledger_entry.voucher_detail_no)
+ .having(Sum(stock_ledger_entry.stock_value_difference) != 0)
+ )
+
+ data = query.run(as_dict=True)
+ stock_entries = {}
+
+ for row in data:
+ if abs(row.stock_value) > 0.1 and row.name not in stock_entries:
+ stock_entries.setdefault(row.name, row)
+
+ return stock_entries
diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py
index b574b71..680d209 100644
--- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py
@@ -5,7 +5,7 @@
import frappe
from frappe.permissions import add_user_permission, remove_user_permission
from frappe.tests.utils import FrappeTestCase, change_settings
-from frappe.utils import add_days, flt, nowdate, nowtime, today
+from frappe.utils import add_days, flt, now, nowdate, nowtime, today
from erpnext.accounts.doctype.account.test_account import get_inventory_account
from erpnext.stock.doctype.item.test_item import (
@@ -17,6 +17,8 @@
from erpnext.stock.doctype.serial_no.serial_no import * # noqa
from erpnext.stock.doctype.stock_entry.stock_entry import (
FinishedGoodError,
+ audit_incorrect_valuation_entries,
+ get_incorrect_stock_entries,
move_sample_to_retention_warehouse,
)
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
@@ -1614,6 +1616,44 @@
self.assertRaises(BatchExpiredError, se.save)
+ def test_audit_incorrect_stock_entries(self):
+ item_code = "Test Incorrect Valuation Rate Item - 001"
+ create_item(item_code=item_code, is_stock_item=1)
+
+ make_stock_entry(
+ item_code=item_code,
+ purpose="Material Receipt",
+ posting_date=add_days(nowdate(), -10),
+ qty=2,
+ rate=500,
+ to_warehouse="_Test Warehouse - _TC",
+ )
+
+ transfer_entry = make_stock_entry(
+ item_code=item_code,
+ purpose="Material Transfer",
+ qty=2,
+ rate=500,
+ from_warehouse="_Test Warehouse - _TC",
+ to_warehouse="_Test Warehouse 1 - _TC",
+ )
+
+ sle_name = frappe.db.get_value(
+ "Stock Ledger Entry", {"voucher_no": transfer_entry.name, "actual_qty": (">", 0)}, "name"
+ )
+
+ frappe.db.set_value(
+ "Stock Ledger Entry", sle_name, {"modified": add_days(now(), -1), "stock_value_difference": 10}
+ )
+
+ stock_entries = get_incorrect_stock_entries()
+ self.assertTrue(transfer_entry.name in stock_entries)
+
+ audit_incorrect_valuation_entries()
+
+ stock_entries = get_incorrect_stock_entries()
+ self.assertFalse(transfer_entry.name in stock_entries)
+
def make_serialized_item(**args):
args = frappe._dict(args)
diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
index 3a0b38a..398b3c9 100644
--- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
+++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
@@ -715,8 +715,8 @@
def get_stock_balance_for(
item_code: str,
warehouse: str,
- posting_date: str,
- posting_time: str,
+ posting_date,
+ posting_time,
batch_no: Optional[str] = None,
with_valuation_rate: bool = True,
):