mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-01 03:09:09 +00:00
Merge pull request #45264 from frappe/version-14-hotfix
chore: release v14
This commit is contained in:
@@ -523,9 +523,11 @@ def get_tds_amount(ldc, parties, inv, tax_details, vouchers):
|
|||||||
else:
|
else:
|
||||||
tax_withholding_net_total = inv.get("tax_withholding_net_total", 0)
|
tax_withholding_net_total = inv.get("tax_withholding_net_total", 0)
|
||||||
|
|
||||||
if (threshold and tax_withholding_net_total >= threshold) or (
|
has_cumulative_threshold_breached = (
|
||||||
cumulative_threshold and (supp_credit_amt + supp_inv_credit_amt) >= cumulative_threshold
|
cumulative_threshold and (supp_credit_amt + supp_inv_credit_amt) >= cumulative_threshold
|
||||||
):
|
)
|
||||||
|
|
||||||
|
if (threshold and tax_withholding_net_total >= threshold) or (has_cumulative_threshold_breached):
|
||||||
# Get net total again as TDS is calculated on net total
|
# Get net total again as TDS is calculated on net total
|
||||||
# Grand is used to just check for threshold breach
|
# Grand is used to just check for threshold breach
|
||||||
net_total = (
|
net_total = (
|
||||||
@@ -533,9 +535,7 @@ def get_tds_amount(ldc, parties, inv, tax_details, vouchers):
|
|||||||
)
|
)
|
||||||
supp_credit_amt += net_total
|
supp_credit_amt += net_total
|
||||||
|
|
||||||
if (cumulative_threshold and supp_credit_amt >= cumulative_threshold) and cint(
|
if has_cumulative_threshold_breached and cint(tax_details.tax_on_excess_amount):
|
||||||
tax_details.tax_on_excess_amount
|
|
||||||
):
|
|
||||||
supp_credit_amt = net_total + tax_withholding_net_total - cumulative_threshold
|
supp_credit_amt = net_total + tax_withholding_net_total - cumulative_threshold
|
||||||
|
|
||||||
if ldc and is_valid_certificate(ldc, inv.get("posting_date") or inv.get("transaction_date"), 0):
|
if ldc and is_valid_certificate(ldc, inv.get("posting_date") or inv.get("transaction_date"), 0):
|
||||||
|
|||||||
@@ -2188,6 +2188,9 @@ class AccountsController(TransactionBase):
|
|||||||
return
|
return
|
||||||
|
|
||||||
for d in self.get("payment_schedule"):
|
for d in self.get("payment_schedule"):
|
||||||
|
if d.due_date and d.discount_date:
|
||||||
|
d.validate_from_to_dates("discount_date", "due_date")
|
||||||
|
|
||||||
if self.doctype == "Sales Order" and getdate(d.due_date) < getdate(self.transaction_date):
|
if self.doctype == "Sales Order" and getdate(d.due_date) < getdate(self.transaction_date):
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
_("Row {0}: Due Date in the Payment Terms table cannot be before Posting Date").format(
|
_("Row {0}: Due Date in the Payment Terms table cannot be before Posting Date").format(
|
||||||
|
|||||||
@@ -201,7 +201,7 @@
|
|||||||
"description": "In the case of 'Use Multi-Level BOM' in a work order, if the user wishes to add sub-assembly costs to Finished Goods items without using a job card as well the scrap items, then this option needs to be enable.",
|
"description": "In the case of 'Use Multi-Level BOM' in a work order, if the user wishes to add sub-assembly costs to Finished Goods items without using a job card as well the scrap items, then this option needs to be enable.",
|
||||||
"fieldname": "set_op_cost_and_scrape_from_sub_assemblies",
|
"fieldname": "set_op_cost_and_scrape_from_sub_assemblies",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Set Operating Cost / Scrape Items From Sub-assemblies"
|
"label": "Set Operating Cost / Scrap Items From Sub-assemblies"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "icon-wrench",
|
"icon": "icon-wrench",
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ class Timesheet(Document):
|
|||||||
if data.task and data.task not in tasks:
|
if data.task and data.task not in tasks:
|
||||||
task = frappe.get_doc("Task", data.task)
|
task = frappe.get_doc("Task", data.task)
|
||||||
task.update_time_and_costing()
|
task.update_time_and_costing()
|
||||||
task.save()
|
task.save(ignore_permissions=True)
|
||||||
tasks.append(data.task)
|
tasks.append(data.task)
|
||||||
|
|
||||||
elif data.project and data.project not in projects:
|
elif data.project and data.project not in projects:
|
||||||
|
|||||||
@@ -322,7 +322,11 @@ def _make_sales_order(source_name, target_doc=None, ignore_permissions=False):
|
|||||||
2. If selections: Is Alternative Item/Has Alternative Item: Map if selected and adequate qty
|
2. If selections: Is Alternative Item/Has Alternative Item: Map if selected and adequate qty
|
||||||
3. If selections: Simple row: Map if adequate qty
|
3. If selections: Simple row: Map if adequate qty
|
||||||
"""
|
"""
|
||||||
has_qty = item.qty > 0
|
balance_qty = item.qty - ordered_items.get(item.item_code, 0.0)
|
||||||
|
if balance_qty <= 0:
|
||||||
|
return False
|
||||||
|
|
||||||
|
has_qty = balance_qty
|
||||||
|
|
||||||
if not selected_rows:
|
if not selected_rows:
|
||||||
return not item.is_alternative
|
return not item.is_alternative
|
||||||
|
|||||||
@@ -30,6 +30,38 @@ class TestQuotation(FrappeTestCase):
|
|||||||
|
|
||||||
self.assertTrue(sales_order.get("payment_schedule"))
|
self.assertTrue(sales_order.get("payment_schedule"))
|
||||||
|
|
||||||
|
def test_do_not_add_ordered_items_in_new_sales_order(self):
|
||||||
|
from erpnext.selling.doctype.quotation.quotation import make_sales_order
|
||||||
|
from erpnext.stock.doctype.item.test_item import make_item
|
||||||
|
|
||||||
|
item = make_item("_Test Item for Quotation for SO", {"is_stock_item": 1})
|
||||||
|
|
||||||
|
quotation = make_quotation(qty=5, do_not_submit=True)
|
||||||
|
quotation.append(
|
||||||
|
"items",
|
||||||
|
{
|
||||||
|
"item_code": item.name,
|
||||||
|
"qty": 5,
|
||||||
|
"rate": 100,
|
||||||
|
"conversion_factor": 1,
|
||||||
|
"uom": item.stock_uom,
|
||||||
|
"warehouse": "_Test Warehouse - _TC",
|
||||||
|
"stock_uom": item.stock_uom,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
quotation.submit()
|
||||||
|
|
||||||
|
sales_order = make_sales_order(quotation.name)
|
||||||
|
sales_order.delivery_date = nowdate()
|
||||||
|
self.assertEqual(len(sales_order.items), 2)
|
||||||
|
sales_order.remove(sales_order.items[1])
|
||||||
|
sales_order.submit()
|
||||||
|
|
||||||
|
sales_order = make_sales_order(quotation.name)
|
||||||
|
self.assertEqual(len(sales_order.items), 1)
|
||||||
|
self.assertEqual(sales_order.items[0].item_code, item.name)
|
||||||
|
self.assertEqual(sales_order.items[0].qty, 5.0)
|
||||||
|
|
||||||
def test_gross_profit(self):
|
def test_gross_profit(self):
|
||||||
from erpnext.stock.doctype.item.test_item import make_item
|
from erpnext.stock.doctype.item.test_item import make_item
|
||||||
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
|
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
|
||||||
|
|||||||
Reference in New Issue
Block a user