mirror of
https://github.com/frappe/erpnext.git
synced 2026-07-30 07:44:36 +00:00
Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cfbd9af100 | ||
|
|
966c296872 | ||
|
|
0ff871e38e | ||
|
|
9df10dbc40 | ||
|
|
bdaae81171 | ||
|
|
8f977f40f0 | ||
|
|
3bc7c88133 | ||
|
|
84b6f68108 | ||
|
|
e5b38607ce | ||
|
|
b3c9d0d910 | ||
|
|
c417365e03 | ||
|
|
b2a4175d43 | ||
|
|
a801bba83e | ||
|
|
3ccb511e25 | ||
|
|
8c51f2e5a1 | ||
|
|
5dbca09899 | ||
|
|
9ec7bb9be3 | ||
|
|
0281afcead | ||
|
|
348e4616cb | ||
|
|
a165b37fd7 | ||
|
|
cdc86bd76c | ||
|
|
e9df06406f | ||
|
|
c574494ddd |
@@ -4,7 +4,7 @@ import frappe
|
||||
|
||||
from erpnext.hooks import regional_overrides
|
||||
|
||||
__version__ = "13.52.7"
|
||||
__version__ = "13.52.11"
|
||||
|
||||
|
||||
def get_default_company(user=None):
|
||||
|
||||
@@ -616,7 +616,9 @@ class PaymentEntry(AccountsController):
|
||||
if not self.apply_tax_withholding_amount:
|
||||
return
|
||||
|
||||
net_total = self.paid_amount
|
||||
order_amount = self.get_order_net_total()
|
||||
|
||||
net_total = flt(order_amount) + flt(self.unallocated_amount)
|
||||
|
||||
# Adding args as purchase invoice to get TDS amount
|
||||
args = frappe._dict(
|
||||
@@ -661,6 +663,20 @@ class PaymentEntry(AccountsController):
|
||||
for d in to_remove:
|
||||
self.remove(d)
|
||||
|
||||
def get_order_net_total(self):
|
||||
if self.party_type == "Supplier":
|
||||
doctype = "Purchase Order"
|
||||
else:
|
||||
doctype = "Sales Order"
|
||||
|
||||
docnames = [d.reference_name for d in self.references if d.reference_doctype == doctype]
|
||||
|
||||
tax_withholding_net_total = frappe.db.get_value(
|
||||
doctype, {"name": ["in", docnames]}, ["sum(base_net_total)"]
|
||||
)
|
||||
|
||||
return tax_withholding_net_total
|
||||
|
||||
def apply_taxes(self):
|
||||
self.initialize_taxes()
|
||||
self.determine_exclusive_rate()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
import collections
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
@@ -44,6 +44,7 @@ class POSInvoice(SalesInvoice):
|
||||
self.validate_debit_to_acc()
|
||||
self.validate_write_off_account()
|
||||
self.validate_change_amount()
|
||||
self.validate_duplicate_serial_and_batch_no()
|
||||
self.validate_change_account()
|
||||
self.validate_item_cost_centers()
|
||||
self.validate_warehouse()
|
||||
@@ -154,6 +155,27 @@ class POSInvoice(SalesInvoice):
|
||||
title=_("Item Unavailable"),
|
||||
)
|
||||
|
||||
def validate_duplicate_serial_and_batch_no(self):
|
||||
serial_nos = []
|
||||
batch_nos = []
|
||||
|
||||
for row in self.get("items"):
|
||||
if row.serial_no:
|
||||
serial_nos = row.serial_no.split("\n")
|
||||
|
||||
if row.batch_no and not row.serial_no:
|
||||
batch_nos.append(row.batch_no)
|
||||
|
||||
if serial_nos:
|
||||
for key, value in collections.Counter(serial_nos).items():
|
||||
if value > 1:
|
||||
frappe.throw(_("Duplicate Serial No {0} found").format("key"))
|
||||
|
||||
if batch_nos:
|
||||
for key, value in collections.Counter(batch_nos).items():
|
||||
if value > 1:
|
||||
frappe.throw(_("Duplicate Batch No {0} found").format("key"))
|
||||
|
||||
def validate_pos_reserved_batch_qty(self, item):
|
||||
filters = {"item_code": item.item_code, "warehouse": item.warehouse, "batch_no": item.batch_no}
|
||||
|
||||
|
||||
@@ -1580,6 +1580,52 @@ class TestPurchaseInvoice(unittest.TestCase, StockTestMixin):
|
||||
|
||||
self.assertTrue(return_pi.docstatus == 1)
|
||||
|
||||
def test_payment_allocation_for_payment_terms(self):
|
||||
from erpnext.buying.doctype.purchase_order.test_purchase_order import (
|
||||
create_pr_against_po,
|
||||
create_purchase_order,
|
||||
)
|
||||
from erpnext.selling.doctype.sales_order.test_sales_order import (
|
||||
automatically_fetch_payment_terms,
|
||||
)
|
||||
from erpnext.stock.doctype.purchase_receipt.purchase_receipt import (
|
||||
make_purchase_invoice as make_pi_from_pr,
|
||||
)
|
||||
|
||||
automatically_fetch_payment_terms()
|
||||
frappe.db.set_value(
|
||||
"Payment Terms Template",
|
||||
"_Test Payment Term Template",
|
||||
"allocate_payment_based_on_payment_terms",
|
||||
0,
|
||||
)
|
||||
|
||||
po = create_purchase_order(do_not_save=1)
|
||||
po.payment_terms_template = "_Test Payment Term Template"
|
||||
po.save()
|
||||
po.submit()
|
||||
|
||||
pr = create_pr_against_po(po.name, received_qty=4)
|
||||
pi = make_pi_from_pr(pr.name)
|
||||
self.assertEqual(pi.payment_schedule[0].payment_amount, 1000)
|
||||
|
||||
frappe.db.set_value(
|
||||
"Payment Terms Template",
|
||||
"_Test Payment Term Template",
|
||||
"allocate_payment_based_on_payment_terms",
|
||||
1,
|
||||
)
|
||||
pi = make_pi_from_pr(pr.name)
|
||||
self.assertEqual(pi.payment_schedule[0].payment_amount, 2500)
|
||||
|
||||
automatically_fetch_payment_terms(enable=0)
|
||||
frappe.db.set_value(
|
||||
"Payment Terms Template",
|
||||
"_Test Payment Term Template",
|
||||
"allocate_payment_based_on_payment_terms",
|
||||
0,
|
||||
)
|
||||
|
||||
|
||||
def check_gl_entries(doc, voucher_no, expected_gle, posting_date):
|
||||
gl_entries = frappe.db.sql(
|
||||
|
||||
@@ -1580,15 +1580,13 @@ class SalesInvoice(SellingController):
|
||||
frappe.db.set_value("Customer", self.customer, "loyalty_program_tier", lp_details.tier_name)
|
||||
|
||||
def get_returned_amount(self):
|
||||
from frappe.query_builder.functions import Coalesce, Sum
|
||||
from frappe.query_builder.functions import Sum
|
||||
|
||||
doc = frappe.qb.DocType(self.doctype)
|
||||
returned_amount = (
|
||||
frappe.qb.from_(doc)
|
||||
.select(Sum(doc.grand_total))
|
||||
.where(
|
||||
(doc.docstatus == 1) & (doc.is_return == 1) & (Coalesce(doc.return_against, "") == self.name)
|
||||
)
|
||||
.where((doc.docstatus == 1) & (doc.is_return == 1) & (doc.return_against == self.name))
|
||||
).run()
|
||||
|
||||
return abs(returned_amount[0][0]) if returned_amount[0][0] else 0
|
||||
|
||||
@@ -186,6 +186,42 @@ class TestTaxWithholdingCategory(unittest.TestCase):
|
||||
for d in reversed(invoices):
|
||||
d.cancel()
|
||||
|
||||
def test_tds_deduction_for_po_via_payment_entry(self):
|
||||
from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
|
||||
|
||||
frappe.db.set_value(
|
||||
"Supplier", "Test TDS Supplier8", "tax_withholding_category", "Cumulative Threshold TDS"
|
||||
)
|
||||
order = create_purchase_order(supplier="Test TDS Supplier8", rate=40000, do_not_save=True)
|
||||
|
||||
# Add some tax on the order
|
||||
order.append(
|
||||
"taxes",
|
||||
{
|
||||
"category": "Total",
|
||||
"charge_type": "Actual",
|
||||
"account_head": "_Test Account VAT - _TC",
|
||||
"cost_center": "Main - _TC",
|
||||
"tax_amount": 8000,
|
||||
"description": "Test",
|
||||
"add_deduct_tax": "Add",
|
||||
},
|
||||
)
|
||||
|
||||
order.save()
|
||||
|
||||
order.apply_tds = 1
|
||||
order.tax_withholding_category = "Cumulative Threshold TDS"
|
||||
order.submit()
|
||||
|
||||
self.assertEqual(order.taxes[0].tax_amount, 4000)
|
||||
|
||||
payment = get_payment_entry(order.doctype, order.name)
|
||||
payment.apply_tax_withholding_amount = 1
|
||||
payment.tax_withholding_category = "Cumulative Threshold TDS"
|
||||
payment.submit()
|
||||
self.assertEqual(payment.taxes[0].tax_amount, 4000)
|
||||
|
||||
def test_multi_category_single_supplier(self):
|
||||
frappe.db.set_value(
|
||||
"Supplier", "Test TDS Supplier5", "tax_withholding_category", "Test Service Category"
|
||||
@@ -275,6 +311,37 @@ def cancel_invoices():
|
||||
frappe.get_doc("Sales Invoice", d).cancel()
|
||||
|
||||
|
||||
def create_purchase_order(**args):
|
||||
# return purchase order doc object
|
||||
item = frappe.db.get_value("Item", {"item_name": "TDS Item"}, "name")
|
||||
args = frappe._dict(args)
|
||||
po = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Purchase Order",
|
||||
"transaction_date": today(),
|
||||
"schedule_date": today(),
|
||||
"apply_tds": 0 if args.do_not_apply_tds else 1,
|
||||
"supplier": args.supplier,
|
||||
"company": "_Test Company",
|
||||
"taxes_and_charges": "",
|
||||
"currency": "INR",
|
||||
"taxes": [],
|
||||
"items": [
|
||||
{
|
||||
"doctype": "Purchase Order Item",
|
||||
"item_code": item,
|
||||
"qty": args.qty or 1,
|
||||
"rate": args.rate or 10000,
|
||||
"cost_center": "Main - _TC",
|
||||
"expense_account": "Stock Received But Not Billed - _TC",
|
||||
}
|
||||
],
|
||||
}
|
||||
)
|
||||
po.save()
|
||||
return po
|
||||
|
||||
|
||||
def create_purchase_invoice(**args):
|
||||
# return sales invoice doc object
|
||||
item = frappe.db.get_value("Item", {"item_name": "TDS Item"}, "name")
|
||||
@@ -351,6 +418,8 @@ def create_records():
|
||||
"Test TDS Supplier4",
|
||||
"Test TDS Supplier5",
|
||||
"Test TDS Supplier6",
|
||||
"Test TDS Supplier7",
|
||||
"Test TDS Supplier8",
|
||||
]:
|
||||
if frappe.db.exists("Supplier", name):
|
||||
continue
|
||||
|
||||
@@ -148,17 +148,33 @@ class Asset(AccountsController):
|
||||
frappe.throw(_("Item {0} must be a non-stock item").format(self.item_code))
|
||||
|
||||
def validate_cost_center(self):
|
||||
if not self.cost_center:
|
||||
return
|
||||
|
||||
cost_center_company = frappe.db.get_value("Cost Center", self.cost_center, "company")
|
||||
if cost_center_company != self.company:
|
||||
frappe.throw(
|
||||
_("Selected Cost Center {} doesn't belongs to {}").format(
|
||||
frappe.bold(self.cost_center), frappe.bold(self.company)
|
||||
),
|
||||
title=_("Invalid Cost Center"),
|
||||
if self.cost_center:
|
||||
cost_center_company, cost_center_is_group = frappe.db.get_value(
|
||||
"Cost Center", self.cost_center, ["company", "is_group"]
|
||||
)
|
||||
if cost_center_company != self.company:
|
||||
frappe.throw(
|
||||
_("Cost Center {} doesn't belong to Company {}").format(
|
||||
frappe.bold(self.cost_center), frappe.bold(self.company)
|
||||
),
|
||||
title=_("Invalid Cost Center"),
|
||||
)
|
||||
if cost_center_is_group:
|
||||
frappe.throw(
|
||||
_(
|
||||
"Cost Center {} is a group cost center and group cost centers cannot be used in transactions"
|
||||
).format(frappe.bold(self.cost_center)),
|
||||
title=_("Invalid Cost Center"),
|
||||
)
|
||||
|
||||
else:
|
||||
if not frappe.get_cached_value("Company", self.company, "depreciation_cost_center"):
|
||||
frappe.throw(
|
||||
_(
|
||||
"Please set a Cost Center for the Asset or set an Asset Depreciation Cost Center for the Company {}"
|
||||
).format(frappe.bold(self.company)),
|
||||
title=_("Missing Cost Center"),
|
||||
)
|
||||
|
||||
def validate_in_use_date(self):
|
||||
if not self.available_for_use_date:
|
||||
|
||||
@@ -33,6 +33,7 @@ frappe.ui.form.on('Asset Category', {
|
||||
var d = locals[cdt][cdn];
|
||||
return {
|
||||
"filters": {
|
||||
"account_type": "Depreciation",
|
||||
"root_type": ["in", ["Expense", "Income"]],
|
||||
"is_group": 0,
|
||||
"company": d.company_name
|
||||
|
||||
@@ -53,7 +53,7 @@ class AssetCategory(Document):
|
||||
account_type_map = {
|
||||
"fixed_asset_account": {"account_type": ["Fixed Asset"]},
|
||||
"accumulated_depreciation_account": {"account_type": ["Accumulated Depreciation"]},
|
||||
"depreciation_expense_account": {"root_type": ["Expense", "Income"]},
|
||||
"depreciation_expense_account": {"account_type": ["Depreciation"]},
|
||||
"capital_work_in_progress_account": {"account_type": ["Capital Work in Progress"]},
|
||||
}
|
||||
for d in self.accounts:
|
||||
|
||||
@@ -7,13 +7,14 @@ from itertools import chain
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.query_builder.functions import IfNull, Sum
|
||||
from frappe.utils import cstr, flt, formatdate, getdate
|
||||
from frappe.utils import add_months, cstr, flt, formatdate, getdate, nowdate, today
|
||||
|
||||
from erpnext.accounts.report.financial_statements import (
|
||||
get_fiscal_year_data,
|
||||
get_period_list,
|
||||
validate_fiscal_year,
|
||||
)
|
||||
from erpnext.accounts.utils import get_fiscal_year
|
||||
from erpnext.assets.doctype.asset.asset import get_asset_value_after_depreciation
|
||||
|
||||
|
||||
@@ -37,15 +38,26 @@ def get_conditions(filters):
|
||||
|
||||
if filters.get("company"):
|
||||
conditions["company"] = filters.company
|
||||
|
||||
if filters.filter_based_on == "Date Range":
|
||||
if not filters.from_date and not filters.to_date:
|
||||
filters.from_date = add_months(nowdate(), -12)
|
||||
filters.to_date = nowdate()
|
||||
|
||||
conditions[date_field] = ["between", [filters.from_date, filters.to_date]]
|
||||
if filters.filter_based_on == "Fiscal Year":
|
||||
elif filters.filter_based_on == "Fiscal Year":
|
||||
if not filters.from_fiscal_year and not filters.to_fiscal_year:
|
||||
default_fiscal_year = get_fiscal_year(today())[0]
|
||||
filters.from_fiscal_year = default_fiscal_year
|
||||
filters.to_fiscal_year = default_fiscal_year
|
||||
|
||||
fiscal_year = get_fiscal_year_data(filters.from_fiscal_year, filters.to_fiscal_year)
|
||||
validate_fiscal_year(fiscal_year, filters.from_fiscal_year, filters.to_fiscal_year)
|
||||
filters.year_start_date = getdate(fiscal_year.year_start_date)
|
||||
filters.year_end_date = getdate(fiscal_year.year_end_date)
|
||||
|
||||
conditions[date_field] = ["between", [filters.year_start_date, filters.year_end_date]]
|
||||
|
||||
if filters.get("only_existing_assets"):
|
||||
conditions["is_existing_asset"] = filters.get("only_existing_assets")
|
||||
if filters.get("asset_category"):
|
||||
|
||||
@@ -1635,8 +1635,13 @@ class AccountsController(TransactionBase):
|
||||
)
|
||||
self.append("payment_schedule", data)
|
||||
|
||||
allocate_payment_based_on_payment_terms = frappe.db.get_value(
|
||||
"Payment Terms Template", self.payment_terms_template, "allocate_payment_based_on_payment_terms"
|
||||
)
|
||||
|
||||
if not (
|
||||
automatically_fetch_payment_terms
|
||||
and allocate_payment_based_on_payment_terms
|
||||
and self.linked_order_has_payment_terms(po_or_so, fieldname, doctype)
|
||||
):
|
||||
for d in self.get("payment_schedule"):
|
||||
|
||||
@@ -250,6 +250,9 @@ class LoanRepayment(AccountsController):
|
||||
)
|
||||
|
||||
def check_future_accruals(self):
|
||||
if self.is_term_loan:
|
||||
return
|
||||
|
||||
future_accrual_date = frappe.db.get_value(
|
||||
"Loan Interest Accrual",
|
||||
{"posting_date": (">", self.posting_date), "docstatus": 1, "loan": self.against_loan},
|
||||
|
||||
@@ -79,6 +79,7 @@ class BOMUpdateLog(Document):
|
||||
else:
|
||||
frappe.enqueue(
|
||||
method="erpnext.manufacturing.doctype.bom_update_log.bom_update_log.process_boms_cost_level_wise",
|
||||
queue="long",
|
||||
update_doc=self,
|
||||
now=frappe.flags.in_test,
|
||||
)
|
||||
|
||||
@@ -157,12 +157,21 @@ def get_next_higher_level_boms(
|
||||
def get_leaf_boms() -> List[str]:
|
||||
"Get BOMs that have no dependencies."
|
||||
|
||||
return frappe.db.sql_list(
|
||||
"""select name from `tabBOM` bom
|
||||
where docstatus=1 and is_active=1
|
||||
and not exists(select bom_no from `tabBOM Item`
|
||||
where parent=bom.name and ifnull(bom_no, '')!='')"""
|
||||
)
|
||||
bom = frappe.qb.DocType("BOM")
|
||||
bom_item = frappe.qb.DocType("BOM Item")
|
||||
|
||||
boms = (
|
||||
frappe.qb.from_(bom)
|
||||
.left_join(bom_item)
|
||||
.on((bom.name == bom_item.parent) & (bom_item.bom_no != ""))
|
||||
.select(bom.name)
|
||||
.where((bom.docstatus == 1) & (bom.is_active == 1) & (bom_item.bom_no.isnull()))
|
||||
.distinct()
|
||||
).run(as_list=True)
|
||||
|
||||
boms = [bom[0] for bom in boms]
|
||||
|
||||
return boms
|
||||
|
||||
|
||||
def _generate_dependence_map() -> defaultdict:
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"actions": [],
|
||||
"autoname": "format:{####}",
|
||||
"creation": "2019-05-26 15:03:43.996455",
|
||||
"doctype": "DocType",
|
||||
@@ -12,7 +13,6 @@
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fetch_from": "goal.objective",
|
||||
"fieldname": "objective",
|
||||
"fieldtype": "Text",
|
||||
"in_list_view": 1,
|
||||
@@ -38,14 +38,17 @@
|
||||
}
|
||||
],
|
||||
"istable": 1,
|
||||
"modified": "2019-05-26 16:12:54.832058",
|
||||
"links": [],
|
||||
"modified": "2023-07-28 18:10:23.351246",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Quality Management",
|
||||
"name": "Quality Goal Objective",
|
||||
"naming_rule": "Expression",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": [],
|
||||
"track_changes": 1
|
||||
}
|
||||
@@ -96,18 +96,26 @@ class SalesOrder(SellingController):
|
||||
and customer = %s",
|
||||
(self.po_no, self.name, self.customer),
|
||||
)
|
||||
if (
|
||||
so
|
||||
and so[0][0]
|
||||
and not cint(
|
||||
if so and so[0][0]:
|
||||
if cint(
|
||||
frappe.db.get_single_value("Selling Settings", "allow_against_multiple_purchase_orders")
|
||||
)
|
||||
):
|
||||
frappe.msgprint(
|
||||
_("Warning: Sales Order {0} already exists against Customer's Purchase Order {1}").format(
|
||||
so[0][0], self.po_no
|
||||
):
|
||||
frappe.msgprint(
|
||||
_("Warning: Sales Order {0} already exists against Customer's Purchase Order {1}").format(
|
||||
frappe.bold(so[0][0]), frappe.bold(self.po_no)
|
||||
)
|
||||
)
|
||||
else:
|
||||
frappe.throw(
|
||||
_(
|
||||
"Sales Order {0} already exists against Customer's Purchase Order {1}. To allow multiple Sales Orders, Enable {2} in {3}"
|
||||
).format(
|
||||
frappe.bold(so[0][0]),
|
||||
frappe.bold(self.po_no),
|
||||
frappe.bold(_("'Allow Multiple Sales Orders Against a Customer's Purchase Order'")),
|
||||
get_link_to_form("Selling Settings", "Selling Settings"),
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
def validate_for_items(self):
|
||||
for d in self.get("items"):
|
||||
|
||||
@@ -1741,7 +1741,7 @@ def make_sales_order(**args):
|
||||
so.company = args.company or "_Test Company"
|
||||
so.customer = args.customer or "_Test Customer"
|
||||
so.currency = args.currency or "INR"
|
||||
so.po_no = args.po_no or "12345"
|
||||
so.po_no = args.po_no or ""
|
||||
if args.selling_price_list:
|
||||
so.selling_price_list = args.selling_price_list
|
||||
|
||||
|
||||
@@ -697,7 +697,7 @@ class TestDeliveryNote(FrappeTestCase):
|
||||
|
||||
def test_dn_billing_status_case1(self):
|
||||
# SO -> DN -> SI
|
||||
so = make_sales_order()
|
||||
so = make_sales_order(po_no="12345")
|
||||
dn = create_dn_against_so(so.name, delivered_qty=2)
|
||||
|
||||
self.assertEqual(dn.status, "To Bill")
|
||||
@@ -724,7 +724,7 @@ class TestDeliveryNote(FrappeTestCase):
|
||||
make_sales_invoice,
|
||||
)
|
||||
|
||||
so = make_sales_order()
|
||||
so = make_sales_order(po_no="12345")
|
||||
|
||||
si = make_sales_invoice(so.name)
|
||||
si.get("items")[0].qty = 5
|
||||
@@ -768,7 +768,7 @@ class TestDeliveryNote(FrappeTestCase):
|
||||
|
||||
frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1)
|
||||
|
||||
so = make_sales_order()
|
||||
so = make_sales_order(po_no="12345")
|
||||
|
||||
dn1 = make_delivery_note(so.name)
|
||||
dn1.get("items")[0].qty = 2
|
||||
@@ -814,7 +814,7 @@ class TestDeliveryNote(FrappeTestCase):
|
||||
from erpnext.accounts.doctype.sales_invoice.sales_invoice import make_delivery_note
|
||||
from erpnext.selling.doctype.sales_order.sales_order import make_sales_invoice
|
||||
|
||||
so = make_sales_order()
|
||||
so = make_sales_order(po_no="12345")
|
||||
|
||||
si = make_sales_invoice(so.name)
|
||||
si.submit()
|
||||
@@ -1180,6 +1180,10 @@ class TestDeliveryNote(FrappeTestCase):
|
||||
|
||||
self.assertTrue(return_dn.docstatus == 1)
|
||||
|
||||
def tearDown(self):
|
||||
frappe.db.rollback()
|
||||
frappe.db.set_single_value("Selling Settings", "dont_reserve_sales_order_qty_on_sales_return", 0)
|
||||
|
||||
|
||||
def create_delivery_note(**args):
|
||||
dn = frappe.new_doc("Delivery Note")
|
||||
|
||||
@@ -278,6 +278,8 @@ def update_args_in_repost_item_valuation(
|
||||
frappe.publish_realtime(
|
||||
"item_reposting_progress",
|
||||
{"name": doc.name, "items_to_be_repost": json.dumps(args, default=str), "current_index": index},
|
||||
doctype=doc.doctype,
|
||||
docname=doc.name,
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user