mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-23 23:19:20 +00:00
Merge branch 'version-13-hotfix' into asset_bug_fixes_13
This commit is contained in:
2
.github/workflows/docs-checker.yml
vendored
2
.github/workflows/docs-checker.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
|||||||
- name: 'Setup Environment'
|
- name: 'Setup Environment'
|
||||||
uses: actions/setup-python@v2
|
uses: actions/setup-python@v2
|
||||||
with:
|
with:
|
||||||
python-version: 3.6
|
python-version: '3.10'
|
||||||
|
|
||||||
- name: 'Clone repo'
|
- name: 'Clone repo'
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|||||||
@@ -49,7 +49,6 @@
|
|||||||
<br>
|
<br>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{{ _("Against") }}: {{ row.against }}
|
|
||||||
<br>{{ _("Remarks") }}: {{ row.remarks }}
|
<br>{{ _("Remarks") }}: {{ row.remarks }}
|
||||||
{% if row.bill_no %}
|
{% if row.bill_no %}
|
||||||
<br>{{ _("Supplier Invoice No") }}: {{ row.bill_no }}
|
<br>{{ _("Supplier Invoice No") }}: {{ row.bill_no }}
|
||||||
|
|||||||
@@ -1117,6 +1117,46 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
|
|
||||||
frappe.db.sql("delete from `tabPOS Profile`")
|
frappe.db.sql("delete from `tabPOS Profile`")
|
||||||
|
|
||||||
|
def test_bin_details_of_packed_item(self):
|
||||||
|
from erpnext.selling.doctype.product_bundle.test_product_bundle import make_product_bundle
|
||||||
|
from erpnext.stock.doctype.item.test_item import make_item
|
||||||
|
|
||||||
|
# test Update Items with product bundle
|
||||||
|
if not frappe.db.exists("Item", "_Test Product Bundle Item New"):
|
||||||
|
bundle_item = make_item("_Test Product Bundle Item New", {"is_stock_item": 0})
|
||||||
|
bundle_item.append(
|
||||||
|
"item_defaults", {"company": "_Test Company", "default_warehouse": "_Test Warehouse - _TC"}
|
||||||
|
)
|
||||||
|
bundle_item.save(ignore_permissions=True)
|
||||||
|
|
||||||
|
make_item("_Packed Item New 1", {"is_stock_item": 1})
|
||||||
|
make_product_bundle("_Test Product Bundle Item New", ["_Packed Item New 1"], 2)
|
||||||
|
|
||||||
|
si = create_sales_invoice(
|
||||||
|
item_code="_Test Product Bundle Item New",
|
||||||
|
update_stock=1,
|
||||||
|
warehouse="_Test Warehouse - _TC",
|
||||||
|
transaction_date=add_days(nowdate(), -1),
|
||||||
|
do_not_submit=1,
|
||||||
|
)
|
||||||
|
|
||||||
|
make_stock_entry(item="_Packed Item New 1", target="_Test Warehouse - _TC", qty=120, rate=100)
|
||||||
|
|
||||||
|
bin_details = frappe.db.get_value(
|
||||||
|
"Bin",
|
||||||
|
{"item_code": "_Packed Item New 1", "warehouse": "_Test Warehouse - _TC"},
|
||||||
|
["actual_qty", "projected_qty", "ordered_qty"],
|
||||||
|
as_dict=1,
|
||||||
|
)
|
||||||
|
|
||||||
|
si.transaction_date = nowdate()
|
||||||
|
si.save()
|
||||||
|
|
||||||
|
packed_item = si.packed_items[0]
|
||||||
|
self.assertEqual(flt(bin_details.actual_qty), flt(packed_item.actual_qty))
|
||||||
|
self.assertEqual(flt(bin_details.projected_qty), flt(packed_item.projected_qty))
|
||||||
|
self.assertEqual(flt(bin_details.ordered_qty), flt(packed_item.ordered_qty))
|
||||||
|
|
||||||
def test_pos_si_without_payment(self):
|
def test_pos_si_without_payment(self):
|
||||||
make_pos_profile()
|
make_pos_profile()
|
||||||
|
|
||||||
|
|||||||
@@ -378,15 +378,14 @@ class Deferred_Revenue_and_Expense_Report(object):
|
|||||||
ret += [{}]
|
ret += [{}]
|
||||||
|
|
||||||
# add total row
|
# add total row
|
||||||
if ret is not []:
|
if self.filters.type == "Revenue":
|
||||||
if self.filters.type == "Revenue":
|
total_row = frappe._dict({"name": "Total Deferred Income"})
|
||||||
total_row = frappe._dict({"name": "Total Deferred Income"})
|
elif self.filters.type == "Expense":
|
||||||
elif self.filters.type == "Expense":
|
total_row = frappe._dict({"name": "Total Deferred Expense"})
|
||||||
total_row = frappe._dict({"name": "Total Deferred Expense"})
|
|
||||||
|
|
||||||
for idx, period in enumerate(self.period_list, 0):
|
for idx, period in enumerate(self.period_list, 0):
|
||||||
total_row[period.key] = self.period_total[idx].total
|
total_row[period.key] = self.period_total[idx].total
|
||||||
ret.append(total_row)
|
ret.append(total_row)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|||||||
@@ -25,8 +25,8 @@
|
|||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="width: 12%">{%= __("Date") %}</th>
|
<th style="width: 12%">{%= __("Date") %}</th>
|
||||||
<th style="width: 15%">{%= __("Ref") %}</th>
|
<th style="width: 15%">{%= __("Reference") %}</th>
|
||||||
<th style="width: 25%">{%= __("Party") %}</th>
|
<th style="width: 25%">{%= __("Remarks") %}</th>
|
||||||
<th style="width: 15%">{%= __("Debit") %}</th>
|
<th style="width: 15%">{%= __("Debit") %}</th>
|
||||||
<th style="width: 15%">{%= __("Credit") %}</th>
|
<th style="width: 15%">{%= __("Credit") %}</th>
|
||||||
<th style="width: 18%">{%= __("Balance (Dr - Cr)") %}</th>
|
<th style="width: 18%">{%= __("Balance (Dr - Cr)") %}</th>
|
||||||
@@ -45,7 +45,6 @@
|
|||||||
<br>
|
<br>
|
||||||
{% } %}
|
{% } %}
|
||||||
|
|
||||||
{{ __("Against") }}: {%= data[i].against %}
|
|
||||||
<br>{%= __("Remarks") %}: {%= data[i].remarks %}
|
<br>{%= __("Remarks") %}: {%= data[i].remarks %}
|
||||||
{% if(data[i].bill_no) { %}
|
{% if(data[i].bill_no) { %}
|
||||||
<br>{%= __("Supplier Invoice No") %}: {%= data[i].bill_no %}
|
<br>{%= __("Supplier Invoice No") %}: {%= data[i].bill_no %}
|
||||||
|
|||||||
@@ -1239,6 +1239,11 @@ class TestPurchaseOrder(FrappeTestCase):
|
|||||||
|
|
||||||
automatically_fetch_payment_terms(enable=0)
|
automatically_fetch_payment_terms(enable=0)
|
||||||
|
|
||||||
|
def test_variant_item_po(self):
|
||||||
|
po = create_purchase_order(item_code="_Test Variant Item", qty=1, rate=100, do_not_save=1)
|
||||||
|
|
||||||
|
self.assertRaises(frappe.ValidationError, po.save)
|
||||||
|
|
||||||
|
|
||||||
def make_pr_against_po(po, received_qty=0):
|
def make_pr_against_po(po, received_qty=0):
|
||||||
pr = make_purchase_receipt(po)
|
pr = make_purchase_receipt(po)
|
||||||
@@ -1342,8 +1347,8 @@ def create_purchase_order(**args):
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
po.set_missing_values()
|
|
||||||
if not args.do_not_save:
|
if not args.do_not_save:
|
||||||
|
po.set_missing_values()
|
||||||
po.insert()
|
po.insert()
|
||||||
if not args.do_not_submit:
|
if not args.do_not_submit:
|
||||||
if po.is_subcontracted == "Yes":
|
if po.is_subcontracted == "Yes":
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class SellingController(StockController):
|
|||||||
def onload(self):
|
def onload(self):
|
||||||
super(SellingController, self).onload()
|
super(SellingController, self).onload()
|
||||||
if self.doctype in ("Sales Order", "Delivery Note", "Sales Invoice"):
|
if self.doctype in ("Sales Order", "Delivery Note", "Sales Invoice"):
|
||||||
for item in self.get("items"):
|
for item in self.get("items") + (self.get("packed_items") or []):
|
||||||
item.update(get_bin_details(item.item_code, item.warehouse, include_child_warehouses=True))
|
item.update(get_bin_details(item.item_code, item.warehouse, include_child_warehouses=True))
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ status_map = {
|
|||||||
"eval:(self.per_delivered == 100 or self.skip_delivery_note) and self.per_billed == 100 and self.docstatus == 1",
|
"eval:(self.per_delivered == 100 or self.skip_delivery_note) and self.per_billed == 100 and self.docstatus == 1",
|
||||||
],
|
],
|
||||||
["Cancelled", "eval:self.docstatus==2"],
|
["Cancelled", "eval:self.docstatus==2"],
|
||||||
["Closed", "eval:self.status=='Closed'"],
|
["Closed", "eval:self.status=='Closed' and self.docstatus != 2"],
|
||||||
["On Hold", "eval:self.status=='On Hold'"],
|
["On Hold", "eval:self.status=='On Hold'"],
|
||||||
],
|
],
|
||||||
"Purchase Order": [
|
"Purchase Order": [
|
||||||
@@ -79,7 +79,7 @@ status_map = {
|
|||||||
["Delivered", "eval:self.status=='Delivered'"],
|
["Delivered", "eval:self.status=='Delivered'"],
|
||||||
["Cancelled", "eval:self.docstatus==2"],
|
["Cancelled", "eval:self.docstatus==2"],
|
||||||
["On Hold", "eval:self.status=='On Hold'"],
|
["On Hold", "eval:self.status=='On Hold'"],
|
||||||
["Closed", "eval:self.status=='Closed'"],
|
["Closed", "eval:self.status=='Closed' and self.docstatus != 2"],
|
||||||
],
|
],
|
||||||
"Delivery Note": [
|
"Delivery Note": [
|
||||||
["Draft", None],
|
["Draft", None],
|
||||||
@@ -87,7 +87,7 @@ status_map = {
|
|||||||
["Return Issued", "eval:self.per_returned == 100 and self.docstatus == 1"],
|
["Return Issued", "eval:self.per_returned == 100 and self.docstatus == 1"],
|
||||||
["Completed", "eval:self.per_billed == 100 and self.docstatus == 1"],
|
["Completed", "eval:self.per_billed == 100 and self.docstatus == 1"],
|
||||||
["Cancelled", "eval:self.docstatus==2"],
|
["Cancelled", "eval:self.docstatus==2"],
|
||||||
["Closed", "eval:self.status=='Closed'"],
|
["Closed", "eval:self.status=='Closed' and self.docstatus != 2"],
|
||||||
],
|
],
|
||||||
"Purchase Receipt": [
|
"Purchase Receipt": [
|
||||||
["Draft", None],
|
["Draft", None],
|
||||||
@@ -95,7 +95,7 @@ status_map = {
|
|||||||
["Return Issued", "eval:self.per_returned == 100 and self.docstatus == 1"],
|
["Return Issued", "eval:self.per_returned == 100 and self.docstatus == 1"],
|
||||||
["Completed", "eval:self.per_billed == 100 and self.docstatus == 1"],
|
["Completed", "eval:self.per_billed == 100 and self.docstatus == 1"],
|
||||||
["Cancelled", "eval:self.docstatus==2"],
|
["Cancelled", "eval:self.docstatus==2"],
|
||||||
["Closed", "eval:self.status=='Closed'"],
|
["Closed", "eval:self.status=='Closed' and self.docstatus != 2"],
|
||||||
],
|
],
|
||||||
"Material Request": [
|
"Material Request": [
|
||||||
["Draft", None],
|
["Draft", None],
|
||||||
|
|||||||
@@ -173,7 +173,10 @@ class TestWebsiteItem(unittest.TestCase):
|
|||||||
# Website Item Portal Tests Begin
|
# Website Item Portal Tests Begin
|
||||||
|
|
||||||
def test_website_item_breadcrumbs(self):
|
def test_website_item_breadcrumbs(self):
|
||||||
"Check if breadcrumbs include homepage, product listing navigation page, parent item group(s) and item group."
|
"""
|
||||||
|
Check if breadcrumbs include homepage, product listing navigation page,
|
||||||
|
parent item group(s) and item group
|
||||||
|
"""
|
||||||
from erpnext.setup.doctype.item_group.item_group import get_parent_item_groups
|
from erpnext.setup.doctype.item_group.item_group import get_parent_item_groups
|
||||||
|
|
||||||
item_code = "Test Breadcrumb Item"
|
item_code = "Test Breadcrumb Item"
|
||||||
@@ -196,7 +199,7 @@ class TestWebsiteItem(unittest.TestCase):
|
|||||||
breadcrumbs = get_parent_item_groups(item.item_group)
|
breadcrumbs = get_parent_item_groups(item.item_group)
|
||||||
|
|
||||||
self.assertEqual(breadcrumbs[0]["name"], "Home")
|
self.assertEqual(breadcrumbs[0]["name"], "Home")
|
||||||
self.assertEqual(breadcrumbs[1]["name"], "Shop by Category")
|
self.assertEqual(breadcrumbs[1]["name"], "All Products")
|
||||||
self.assertEqual(breadcrumbs[2]["name"], "_Test Item Group B") # parent item group
|
self.assertEqual(breadcrumbs[2]["name"], "_Test Item Group B") # parent item group
|
||||||
self.assertEqual(breadcrumbs[3]["name"], "_Test Item Group B - 1")
|
self.assertEqual(breadcrumbs[3]["name"], "_Test Item Group B - 1")
|
||||||
|
|
||||||
|
|||||||
@@ -374,4 +374,4 @@ erpnext.patches.v13_0.reset_corrupt_defaults
|
|||||||
erpnext.patches.v13_0.show_hr_payroll_deprecation_warning
|
erpnext.patches.v13_0.show_hr_payroll_deprecation_warning
|
||||||
erpnext.patches.v13_0.create_accounting_dimensions_for_asset_repair
|
erpnext.patches.v13_0.create_accounting_dimensions_for_asset_repair
|
||||||
execute:frappe.db.set_value("Naming Series", "Naming Series", {"select_doc_for_series": "", "set_options": "", "prefix": "", "current_value": 0, "user_must_always_select": 0})
|
execute:frappe.db.set_value("Naming Series", "Naming Series", {"select_doc_for_series": "", "set_options": "", "prefix": "", "current_value": 0, "user_must_always_select": 0})
|
||||||
erpnext.patches.v13_0.update_schedule_type_in_loans
|
erpnext.patches.v13_0.update_schedule_type_in_loans
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ from erpnext.stock.stock_ledger import update_entries_after
|
|||||||
|
|
||||||
def execute():
|
def execute():
|
||||||
doctypes_to_reload = [
|
doctypes_to_reload = [
|
||||||
|
("setup", "company"),
|
||||||
("stock", "repost_item_valuation"),
|
("stock", "repost_item_valuation"),
|
||||||
("stock", "stock_entry_detail"),
|
("stock", "stock_entry_detail"),
|
||||||
("stock", "purchase_receipt_item"),
|
("stock", "purchase_receipt_item"),
|
||||||
|
|||||||
@@ -115,24 +115,16 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
|
|||||||
calculate_item_values: function() {
|
calculate_item_values: function() {
|
||||||
let me = this;
|
let me = this;
|
||||||
if (!this.discount_amount_applied) {
|
if (!this.discount_amount_applied) {
|
||||||
$.each(this.frm.doc["items"] || [], function(i, item) {
|
for (item of this.frm.doc.items || []) {
|
||||||
frappe.model.round_floats_in(item);
|
frappe.model.round_floats_in(item);
|
||||||
item.net_rate = item.rate;
|
item.net_rate = item.rate;
|
||||||
|
item.qty = item.qty === undefined ? (me.frm.doc.is_return ? -1 : 1) : item.qty;
|
||||||
if ((!item.qty) && me.frm.doc.is_return) {
|
item.net_amount = item.amount = flt(item.rate * item.qty, precision("amount", item));
|
||||||
item.amount = flt(item.rate * -1, precision("amount", item));
|
|
||||||
} else if ((!item.qty) && me.frm.doc.is_debit_note) {
|
|
||||||
item.amount = flt(item.rate, precision("amount", item));
|
|
||||||
} else {
|
|
||||||
item.amount = flt(item.rate * item.qty, precision("amount", item));
|
|
||||||
}
|
|
||||||
|
|
||||||
item.net_amount = item.amount;
|
|
||||||
item.item_tax_amount = 0.0;
|
item.item_tax_amount = 0.0;
|
||||||
item.total_weight = flt(item.weight_per_unit * item.stock_qty);
|
item.total_weight = flt(item.weight_per_unit * item.stock_qty);
|
||||||
|
|
||||||
me.set_in_company_currency(item, ["price_list_rate", "rate", "amount", "net_rate", "net_amount"]);
|
me.set_in_company_currency(item, ["price_list_rate", "rate", "amount", "net_rate", "net_amount"]);
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -546,6 +546,42 @@ class TestSalesOrder(FrappeTestCase):
|
|||||||
workflow.is_active = 0
|
workflow.is_active = 0
|
||||||
workflow.save()
|
workflow.save()
|
||||||
|
|
||||||
|
def test_bin_details_of_packed_item(self):
|
||||||
|
# test Update Items with product bundle
|
||||||
|
if not frappe.db.exists("Item", "_Test Product Bundle Item New"):
|
||||||
|
bundle_item = make_item("_Test Product Bundle Item New", {"is_stock_item": 0})
|
||||||
|
bundle_item.append(
|
||||||
|
"item_defaults", {"company": "_Test Company", "default_warehouse": "_Test Warehouse - _TC"}
|
||||||
|
)
|
||||||
|
bundle_item.save(ignore_permissions=True)
|
||||||
|
|
||||||
|
make_item("_Packed Item New 1", {"is_stock_item": 1})
|
||||||
|
make_product_bundle("_Test Product Bundle Item New", ["_Packed Item New 1"], 2)
|
||||||
|
|
||||||
|
so = make_sales_order(
|
||||||
|
item_code="_Test Product Bundle Item New",
|
||||||
|
warehouse="_Test Warehouse - _TC",
|
||||||
|
transaction_date=add_days(nowdate(), -1),
|
||||||
|
do_not_submit=1,
|
||||||
|
)
|
||||||
|
|
||||||
|
make_stock_entry(item="_Packed Item New 1", target="_Test Warehouse - _TC", qty=120, rate=100)
|
||||||
|
|
||||||
|
bin_details = frappe.db.get_value(
|
||||||
|
"Bin",
|
||||||
|
{"item_code": "_Packed Item New 1", "warehouse": "_Test Warehouse - _TC"},
|
||||||
|
["actual_qty", "projected_qty", "ordered_qty"],
|
||||||
|
as_dict=1,
|
||||||
|
)
|
||||||
|
|
||||||
|
so.transaction_date = nowdate()
|
||||||
|
so.save()
|
||||||
|
|
||||||
|
packed_item = so.packed_items[0]
|
||||||
|
self.assertEqual(flt(bin_details.actual_qty), flt(packed_item.actual_qty))
|
||||||
|
self.assertEqual(flt(bin_details.projected_qty), flt(packed_item.projected_qty))
|
||||||
|
self.assertEqual(flt(bin_details.ordered_qty), flt(packed_item.ordered_qty))
|
||||||
|
|
||||||
def test_update_child_product_bundle(self):
|
def test_update_child_product_bundle(self):
|
||||||
# test Update Items with product bundle
|
# test Update Items with product bundle
|
||||||
if not frappe.db.exists("Item", "_Product Bundle Item"):
|
if not frappe.db.exists("Item", "_Product Bundle Item"):
|
||||||
|
|||||||
@@ -149,12 +149,12 @@ def get_item_for_list_in_html(context):
|
|||||||
|
|
||||||
|
|
||||||
def get_parent_item_groups(item_group_name, from_item=False):
|
def get_parent_item_groups(item_group_name, from_item=False):
|
||||||
base_nav_page = {"name": _("Shop by Category"), "route": "/shop-by-category"}
|
base_nav_page = {"name": _("All Products"), "route": "/all-products"}
|
||||||
|
|
||||||
if from_item and frappe.request.environ.get("HTTP_REFERER"):
|
if from_item and frappe.request.environ.get("HTTP_REFERER"):
|
||||||
# base page after 'Home' will vary on Item page
|
# base page after 'Home' will vary on Item page
|
||||||
last_page = frappe.request.environ["HTTP_REFERER"].split("/")[-1].split("?")[0]
|
last_page = frappe.request.environ["HTTP_REFERER"].split("/")[-1].split("?")[0]
|
||||||
if last_page and last_page in ("shop-by-category", "all-products"):
|
if last_page and last_page == "shop-by-category":
|
||||||
base_nav_page_title = " ".join(last_page.split("-")).title()
|
base_nav_page_title = " ".join(last_page.split("-")).title()
|
||||||
base_nav_page = {"name": _(base_nav_page_title), "route": "/" + last_page}
|
base_nav_page = {"name": _(base_nav_page_title), "route": "/" + last_page}
|
||||||
|
|
||||||
|
|||||||
@@ -490,6 +490,46 @@ class TestDeliveryNote(FrappeTestCase):
|
|||||||
|
|
||||||
self.assertEqual(gle_warehouse_amount, 1400)
|
self.assertEqual(gle_warehouse_amount, 1400)
|
||||||
|
|
||||||
|
def test_bin_details_of_packed_item(self):
|
||||||
|
from erpnext.selling.doctype.product_bundle.test_product_bundle import make_product_bundle
|
||||||
|
from erpnext.stock.doctype.item.test_item import make_item
|
||||||
|
|
||||||
|
# test Update Items with product bundle
|
||||||
|
if not frappe.db.exists("Item", "_Test Product Bundle Item New"):
|
||||||
|
bundle_item = make_item("_Test Product Bundle Item New", {"is_stock_item": 0})
|
||||||
|
bundle_item.append(
|
||||||
|
"item_defaults", {"company": "_Test Company", "default_warehouse": "_Test Warehouse - _TC"}
|
||||||
|
)
|
||||||
|
bundle_item.save(ignore_permissions=True)
|
||||||
|
|
||||||
|
make_item("_Packed Item New 1", {"is_stock_item": 1})
|
||||||
|
make_product_bundle("_Test Product Bundle Item New", ["_Packed Item New 1"], 2)
|
||||||
|
|
||||||
|
si = create_delivery_note(
|
||||||
|
item_code="_Test Product Bundle Item New",
|
||||||
|
update_stock=1,
|
||||||
|
warehouse="_Test Warehouse - _TC",
|
||||||
|
transaction_date=add_days(nowdate(), -1),
|
||||||
|
do_not_submit=1,
|
||||||
|
)
|
||||||
|
|
||||||
|
make_stock_entry(item="_Packed Item New 1", target="_Test Warehouse - _TC", qty=120, rate=100)
|
||||||
|
|
||||||
|
bin_details = frappe.db.get_value(
|
||||||
|
"Bin",
|
||||||
|
{"item_code": "_Packed Item New 1", "warehouse": "_Test Warehouse - _TC"},
|
||||||
|
["actual_qty", "projected_qty", "ordered_qty"],
|
||||||
|
as_dict=1,
|
||||||
|
)
|
||||||
|
|
||||||
|
si.transaction_date = nowdate()
|
||||||
|
si.save()
|
||||||
|
|
||||||
|
packed_item = si.packed_items[0]
|
||||||
|
self.assertEqual(flt(bin_details.actual_qty), flt(packed_item.actual_qty))
|
||||||
|
self.assertEqual(flt(bin_details.projected_qty), flt(packed_item.projected_qty))
|
||||||
|
self.assertEqual(flt(bin_details.ordered_qty), flt(packed_item.ordered_qty))
|
||||||
|
|
||||||
def test_return_for_serialized_items(self):
|
def test_return_for_serialized_items(self):
|
||||||
se = make_serialized_item()
|
se = make_serialized_item()
|
||||||
serial_no = get_serial_nos(se.get("items")[0].serial_no)[0]
|
serial_no = get_serial_nos(se.get("items")[0].serial_no)[0]
|
||||||
@@ -650,6 +690,11 @@ class TestDeliveryNote(FrappeTestCase):
|
|||||||
update_delivery_note_status(dn.name, "Closed")
|
update_delivery_note_status(dn.name, "Closed")
|
||||||
self.assertEqual(frappe.db.get_value("Delivery Note", dn.name, "Status"), "Closed")
|
self.assertEqual(frappe.db.get_value("Delivery Note", dn.name, "Status"), "Closed")
|
||||||
|
|
||||||
|
# Check cancelling closed delivery note
|
||||||
|
dn.load_from_db()
|
||||||
|
dn.cancel()
|
||||||
|
self.assertEqual(dn.status, "Cancelled")
|
||||||
|
|
||||||
def test_dn_billing_status_case1(self):
|
def test_dn_billing_status_case1(self):
|
||||||
# SO -> DN -> SI
|
# SO -> DN -> SI
|
||||||
so = make_sales_order()
|
so = make_sales_order()
|
||||||
|
|||||||
@@ -74,11 +74,10 @@ class ItemAttribute(Document):
|
|||||||
def validate_duplication(self):
|
def validate_duplication(self):
|
||||||
values, abbrs = [], []
|
values, abbrs = [], []
|
||||||
for d in self.item_attribute_values:
|
for d in self.item_attribute_values:
|
||||||
d.abbr = d.abbr.upper()
|
if d.attribute_value.lower() in map(str.lower, values):
|
||||||
if d.attribute_value in values:
|
frappe.throw(_("Attribute value: {0} must appear only once").format(d.attribute_value.title()))
|
||||||
frappe.throw(_("{0} must appear only once").format(d.attribute_value))
|
|
||||||
values.append(d.attribute_value)
|
values.append(d.attribute_value)
|
||||||
|
|
||||||
if d.abbr in abbrs:
|
if d.abbr.lower() in map(str.lower, abbrs):
|
||||||
frappe.throw(_("{0} must appear only once").format(d.abbr))
|
frappe.throw(_("Abbreviation: {0} must appear only once").format(d.abbr.title()))
|
||||||
abbrs.append(d.abbr)
|
abbrs.append(d.abbr)
|
||||||
|
|||||||
@@ -226,8 +226,10 @@ def validate_item_details(args, item):
|
|||||||
|
|
||||||
validate_end_of_life(item.name, item.end_of_life, item.disabled)
|
validate_end_of_life(item.name, item.end_of_life, item.disabled)
|
||||||
|
|
||||||
if args.transaction_type == "selling" and cint(item.has_variants):
|
if cint(item.has_variants):
|
||||||
throw(_("Item {0} is a template, please select one of its variants").format(item.name))
|
msg = f"Item {item.name} is a template, please select one of its variants"
|
||||||
|
|
||||||
|
throw(_(msg), title=_("Template Item Selected"))
|
||||||
|
|
||||||
elif args.transaction_type == "buying" and args.doctype != "Material Request":
|
elif args.transaction_type == "buying" and args.doctype != "Material Request":
|
||||||
if args.get("is_subcontracted") == "Yes" and item.is_sub_contracted_item != 1:
|
if args.get("is_subcontracted") == "Yes" and item.is_sub_contracted_item != 1:
|
||||||
|
|||||||
Reference in New Issue
Block a user