fix: Merge conflicts

This commit is contained in:
marination
2025-05-13 13:35:19 +02:00
parent f94a14c06a
commit 3deb11e5b2
12 changed files with 19 additions and 328 deletions

View File

@@ -236,11 +236,7 @@
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
<<<<<<< HEAD
"modified": "2024-01-31 13:34:18.101256",
=======
"modified": "2025-03-03 17:32:25.939482",
>>>>>>> e403d3f153 (feat: Unit Price Items in Buying (RFQ, SQ, PO))
"modified_by": "Administrator",
"module": "Buying",
"name": "Buying Settings",
@@ -286,12 +282,7 @@
"role": "Purchase User"
}
],
<<<<<<< HEAD
"sort_field": "modified",
=======
"row_format": "Dynamic",
"sort_field": "creation",
>>>>>>> e403d3f153 (feat: Unit Price Items in Buying (RFQ, SQ, PO))
"sort_order": "DESC",
"states": [],
"track_changes": 1

View File

@@ -1281,20 +1281,19 @@
"print_hide": 1
},
{
<<<<<<< HEAD
"fieldname": "dispatch_address_display",
"fieldtype": "Text Editor",
"label": "Dispatch Address Details",
"print_hide": 1,
"read_only": 1
=======
},
{
"default": "0",
"fieldname": "has_unit_price_items",
"fieldtype": "Check",
"hidden": 1,
"label": "Has Unit Price Items",
"no_copy": 1
>>>>>>> e403d3f153 (feat: Unit Price Items in Buying (RFQ, SQ, PO))
}
],
"grid_page_length": 50,
@@ -1302,11 +1301,7 @@
"idx": 105,
"is_submittable": 1,
"links": [],
<<<<<<< HEAD
"modified": "2025-04-09 16:54:08.836106",
=======
"modified": "2025-03-03 16:48:08.697520",
>>>>>>> e403d3f153 (feat: Unit Price Items in Buying (RFQ, SQ, PO))
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order",

View File

@@ -5,11 +5,7 @@
import json
import frappe
<<<<<<< HEAD
from frappe.tests.utils import FrappeTestCase, change_settings
=======
from frappe.tests import IntegrationTestCase, UnitTestCase, change_settings
>>>>>>> eea758f5b2 (test: Purchase Order with Unit Price Items)
from frappe.utils import add_days, flt, getdate, nowdate
from frappe.utils.data import today
@@ -48,13 +44,6 @@ class TestPurchaseOrder(FrappeTestCase):
po.items[1].qty = 0
self.assertRaises(InvalidQtyError, po.save)
<<<<<<< HEAD
=======
# No error with qty=1
po.items[1].qty = 1
po.save()
self.assertEqual(po.items[1].qty, 1)
def test_purchase_order_zero_qty(self):
po = create_purchase_order(qty=0, do_not_save=True)
@@ -62,7 +51,6 @@ class TestPurchaseOrder(FrappeTestCase):
po.save()
self.assertEqual(po.items[0].qty, 0)
>>>>>>> eea758f5b2 (test: Purchase Order with Unit Price Items)
def test_make_purchase_receipt(self):
po = create_purchase_order(do_not_submit=True)
self.assertRaises(frappe.ValidationError, make_purchase_receipt, po.name)
@@ -812,8 +800,6 @@ class TestPurchaseOrder(FrappeTestCase):
po_doc.reload()
self.assertEqual(po_doc.advance_paid, 5000)
from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_invoice
company_doc.book_advance_payments_in_separate_party_account = False
company_doc.save()
@@ -1218,7 +1204,7 @@ class TestPurchaseOrder(FrappeTestCase):
po.reload()
self.assertEqual(po.per_billed, 100)
@IntegrationTestCase.change_settings("Buying Settings", {"allow_zero_qty_in_purchase_order": 1})
@change_settings("Buying Settings", {"allow_zero_qty_in_purchase_order": 1})
def test_receive_zero_qty_purchase_order(self):
"""
Test the flow of a Unit Price PO and PR creation against it until completion.
@@ -1267,7 +1253,7 @@ class TestPurchaseOrder(FrappeTestCase):
self.assertEqual(po.per_received, 100.0)
self.assertEqual(po.status, "To Bill")
@IntegrationTestCase.change_settings("Buying Settings", {"allow_zero_qty_in_purchase_order": 1})
@change_settings("Buying Settings", {"allow_zero_qty_in_purchase_order": 1})
def test_bill_zero_qty_purchase_order(self):
po = create_purchase_order(qty=0)

View File

@@ -322,11 +322,7 @@
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
<<<<<<< HEAD
"modified": "2023-11-06 12:45:28.898706",
=======
"modified": "2025-03-03 16:48:39.856779",
>>>>>>> e403d3f153 (feat: Unit Price Items in Buying (RFQ, SQ, PO))
"modified_by": "Administrator",
"module": "Buying",
"name": "Request for Quotation",

View File

@@ -5,11 +5,7 @@
from urllib.parse import urlparse
import frappe
<<<<<<< HEAD
from frappe.tests.utils import FrappeTestCase
=======
from frappe.tests import IntegrationTestCase, UnitTestCase, change_settings
>>>>>>> 8f96c0b546 (test: Zero Qty in RFQ and Supplier Quotation)
from frappe.tests.utils import FrappeTestCase, change_settings
from frappe.utils import nowdate
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import (
@@ -24,29 +20,7 @@ from erpnext.stock.doctype.item.test_item import make_item
from erpnext.templates.pages.rfq import check_supplier_has_docname_access
<<<<<<< HEAD
class TestRequestforQuotation(FrappeTestCase):
=======
class UnitTestRequestForQuotation(UnitTestCase):
"""
Unit tests for RequestForQuotation.
Use this class for testing individual functions and methods.
"""
pass
class TestRequestforQuotation(IntegrationTestCase):
def test_rfq_qty(self):
rfq = make_request_for_quotation(qty=0, do_not_save=True)
with self.assertRaises(InvalidQtyError):
rfq.save()
# No error with qty=1
rfq.items[0].qty = 1
rfq.save()
self.assertEqual(rfq.items[0].qty, 1)
def test_rfq_zero_qty(self):
"""
Test if RFQ with zero qty (Unit Price Item) is conditionally allowed.
@@ -57,7 +31,6 @@ class TestRequestforQuotation(IntegrationTestCase):
rfq.save()
self.assertEqual(rfq.items[0].qty, 0)
>>>>>>> 8f96c0b546 (test: Zero Qty in RFQ and Supplier Quotation)
def test_quote_status(self):
rfq = make_request_for_quotation()
@@ -198,7 +171,7 @@ class TestRequestforQuotation(IntegrationTestCase):
supplier_doc.reload()
self.assertTrue(supplier_doc.portal_users[0].user)
@IntegrationTestCase.change_settings("Buying Settings", {"allow_zero_qty_in_request_for_quotation": 1})
@change_settings("Buying Settings", {"allow_zero_qty_in_request_for_quotation": 1})
def test_supplier_quotation_from_zero_qty_rfq(self):
rfq = make_request_for_quotation(qty=0)
sq = make_supplier_quotation_from_rfq(rfq.name, for_supplier=rfq.get("suppliers")[0].supplier)

View File

@@ -3,58 +3,15 @@
import frappe
<<<<<<< HEAD
from frappe.tests.utils import FrappeTestCase
from frappe.tests.utils import FrappeTestCase, change_settings
from frappe.utils import add_days, today
from erpnext.buying.doctype.supplier_quotation.supplier_quotation import make_purchase_order
class TestPurchaseOrder(FrappeTestCase):
def test_make_purchase_order(self):
from erpnext.buying.doctype.supplier_quotation.supplier_quotation import make_purchase_order
sq = frappe.copy_doc(test_records[0]).insert()
=======
from frappe.tests import IntegrationTestCase, UnitTestCase, change_settings
from erpnext.buying.doctype.supplier_quotation.supplier_quotation import make_purchase_order
from erpnext.controllers.accounts_controller import InvalidQtyError
class UnitTestSupplierQuotation(UnitTestCase):
"""
Unit tests for SupplierQuotation.
Use this class for testing individual functions and methods.
"""
pass
class TestPurchaseOrder(IntegrationTestCase):
def test_supplier_quotation_qty(self):
sq = frappe.copy_doc(self.globalTestRecords["Supplier Quotation"][0])
sq.items[0].qty = 0
with self.assertRaises(InvalidQtyError):
sq.save()
# No error with qty=1
sq.items[0].qty = 1
sq.save()
self.assertEqual(sq.items[0].qty, 1)
def test_supplier_quotation_zero_qty(self):
"""
Test if RFQ with zero qty (Unit Price Item) is conditionally allowed.
"""
sq = frappe.copy_doc(self.globalTestRecords["Supplier Quotation"][0])
sq.items[0].qty = 0
with change_settings("Buying Settings", {"allow_zero_qty_in_supplier_quotation": 1}):
sq.save()
self.assertEqual(sq.items[0].qty, 0)
def test_make_purchase_order(self):
sq = frappe.copy_doc(self.globalTestRecords["Supplier Quotation"][0]).insert()
>>>>>>> 8f96c0b546 (test: Zero Qty in RFQ and Supplier Quotation)
self.assertRaises(frappe.ValidationError, make_purchase_order, sq.name)
@@ -73,17 +30,9 @@ class TestPurchaseOrder(IntegrationTestCase):
po.insert()
<<<<<<< HEAD
<<<<<<< HEAD
test_records = frappe.get_test_records("Supplier Quotation")
=======
@change_settings("Buying Settings", {"allow_zero_qty_in_supplier_quotation": 1})
=======
@IntegrationTestCase.change_settings("Buying Settings", {"allow_zero_qty_in_supplier_quotation": 1})
>>>>>>> eea758f5b2 (test: Purchase Order with Unit Price Items)
def test_map_purchase_order_from_zero_qty_supplier_quotation(self):
sq = frappe.copy_doc(self.globalTestRecords["Supplier Quotation"][0])
sq = frappe.copy_doc(test_records[0]).insert()
sq.items[0].qty = 0
sq.submit()
@@ -91,4 +40,6 @@ test_records = frappe.get_test_records("Supplier Quotation")
self.assertEqual(len(po.get("items")), 1)
self.assertEqual(po.get("items")[0].qty, 0)
self.assertEqual(po.get("items")[0].item_code, sq.get("items")[0].item_code)
>>>>>>> 8f96c0b546 (test: Zero Qty in RFQ and Supplier Quotation)
test_records = frappe.get_test_records("Supplier Quotation")

View File

@@ -1259,17 +1259,8 @@ class AccountsController(TransactionBase):
)
def validate_qty_is_not_zero(self):
<<<<<<< HEAD
if self.doctype == "Purchase Receipt":
if self.doctype == "Purchase Receipt" or self.flags.allow_zero_qty:
return
=======
if self.flags.allow_zero_qty:
return
for item in self.items:
if self.doctype == "Purchase Receipt" and item.rejected_qty:
continue
>>>>>>> c1e4e7af28 (feat: Unit Price Contract)
for item in self.items:
if not flt(item.qty):

View File

@@ -1099,15 +1099,7 @@
"idx": 82,
"is_submittable": 1,
"links": [],
<<<<<<< HEAD
<<<<<<< HEAD
"modified": "2024-11-26 12:43:29.293637",
=======
"modified": "2025-02-28 18:52:44.063265",
>>>>>>> c1e4e7af28 (feat: Unit Price Contract)
=======
"modified": "2025-03-03 16:49:20.050303",
>>>>>>> e403d3f153 (feat: Unit Price Items in Buying (RFQ, SQ, PO))
"modified_by": "Administrator",
"module": "Selling",
"name": "Quotation",

View File

@@ -2,39 +2,13 @@
# License: GNU General Public License v3. See license.txt
import frappe
<<<<<<< HEAD
from frappe.tests.utils import FrappeTestCase
=======
from frappe.tests import IntegrationTestCase, UnitTestCase, change_settings
>>>>>>> 0447c7be0a (fix: Treat rows as Unit Price rows only until the qty is 0)
from frappe.tests.utils import FrappeTestCase, change_settings
from frappe.utils import add_days, add_months, flt, getdate, nowdate
test_dependencies = ["Product Bundle"]
<<<<<<< HEAD
class TestQuotation(FrappeTestCase):
=======
class UnitTestQuotation(UnitTestCase):
"""
Unit tests for Quotation.
Use this class for testing individual functions and methods.
"""
pass
class TestQuotation(IntegrationTestCase):
def test_quotation_qty(self):
qo = make_quotation(qty=0, do_not_save=True)
with self.assertRaises(InvalidQtyError):
qo.save()
# No error with qty=1
qo.items[0].qty = 1
qo.save()
self.assertEqual(qo.items[0].qty, 1)
def test_quotation_zero_qty(self):
"""
Test if Quote with zero qty (Unit Price Item) is conditionally allowed.
@@ -44,7 +18,6 @@ class TestQuotation(IntegrationTestCase):
qo.save()
self.assertEqual(qo.items[0].qty, 0)
>>>>>>> 0447c7be0a (fix: Treat rows as Unit Price rows only until the qty is 0)
def test_make_quotation_without_terms(self):
quotation = make_quotation(do_not_save=1)
self.assertFalse(quotation.get("payment_schedule"))
@@ -797,7 +770,7 @@ class TestQuotation(IntegrationTestCase):
self.assertEqual(quotation.rounding_adjustment, 0)
self.assertEqual(quotation.rounded_total, 0)
@IntegrationTestCase.change_settings("Selling Settings", {"allow_zero_qty_in_quotation": 1})
@change_settings("Selling Settings", {"allow_zero_qty_in_quotation": 1})
def test_so_from_zero_qty_quotation(self):
from erpnext.selling.doctype.quotation.quotation import make_sales_order
from erpnext.stock.doctype.item.test_item import make_item

View File

@@ -153,11 +153,7 @@ class SalesOrder(SellingController):
shipping_address_name: DF.Link | None
shipping_rule: DF.Link | None
skip_delivery_note: DF.Check
<<<<<<< HEAD
<<<<<<< HEAD
source: DF.Link | None
=======
>>>>>>> 71f65bab5e (fix: Linters)
status: DF.Literal[
"",
"Draft",
@@ -170,12 +166,6 @@ class SalesOrder(SellingController):
"Cancelled",
"Closed",
]
<<<<<<< HEAD
=======
status: DF.Literal["", "Draft", "On Hold", "To Pay", "To Deliver and Bill", "To Bill", "To Deliver", "Completed", "Cancelled", "Closed"]
>>>>>>> c1e4e7af28 (feat: Unit Price Contract)
=======
>>>>>>> 71f65bab5e (fix: Linters)
tax_category: DF.Link | None
tax_id: DF.Data | None
taxes: DF.Table[SalesTaxesandCharges]

View File

@@ -6,11 +6,7 @@ import json
import frappe
import frappe.permissions
from frappe.core.doctype.user_permission.test_user_permission import create_user
<<<<<<< HEAD
from frappe.tests.utils import FrappeTestCase, change_settings
=======
from frappe.tests import IntegrationTestCase, change_settings
>>>>>>> 55981c8358 (test: Sales Order + fix: Mapping of Items from Quotation & SO)
from frappe.utils import add_days, flt, getdate, nowdate, today
from erpnext.accounts.test.accounts_mixin import AccountsTestMixin
@@ -90,31 +86,6 @@ class TestSalesOrder(AccountsTestMixin, FrappeTestCase):
)
update_child_qty_rate("Sales Order", trans_item, so.name)
<<<<<<< HEAD
=======
def test_sales_order_qty(self):
so = make_sales_order(qty=1, do_not_save=True)
# NonNegativeError with qty=-1
so.append(
"items",
{
"item_code": "_Test Item",
"qty": -1,
"rate": 10,
},
)
self.assertRaises(frappe.NonNegativeError, so.save)
# InvalidQtyError with qty=0
so.items[1].qty = 0
self.assertRaises(InvalidQtyError, so.save)
# No error with qty=1
so.items[1].qty = 1
so.save()
self.assertEqual(so.items[0].qty, 1)
def test_sales_order_zero_qty(self):
po = make_sales_order(qty=0, do_not_save=True)
@@ -122,7 +93,6 @@ class TestSalesOrder(AccountsTestMixin, FrappeTestCase):
po.save()
self.assertEqual(po.items[0].qty, 0)
>>>>>>> 55981c8358 (test: Sales Order + fix: Mapping of Items from Quotation & SO)
def test_make_material_request(self):
so = make_sales_order(do_not_submit=True)
@@ -1983,79 +1953,6 @@ class TestSalesOrder(AccountsTestMixin, FrappeTestCase):
self.assertEqual(so.items[0].rate, scenario.get("expected_rate"))
self.assertEqual(so.packed_items[0].rate, scenario.get("expected_rate"))
<<<<<<< HEAD
=======
@patch(
# this also shadows one (1) call to _get_payment_gateway_controller
"erpnext.accounts.doctype.payment_request.payment_request.PaymentRequest.get_payment_url",
return_value=None,
)
def test_sales_order_advance_payment_status(self, mocked_get_payment_url):
from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry
from erpnext.accounts.doctype.payment_request.payment_request import make_payment_request
# Flow progressing to SI with payment entries "moved" from SO to SI
so = make_sales_order(qty=1, rate=100, do_not_submit=True)
# no-op; for optical consistency with how a webshop SO would look like
so.order_type = "Shopping Cart"
so.submit()
self.assertEqual(frappe.db.get_value(so.doctype, so.name, "advance_payment_status"), "Not Requested")
pr = make_payment_request(
dt=so.doctype,
dn=so.name,
order_type="Shopping Cart",
submit_doc=True,
return_doc=True,
mute_email=True,
)
self.assertEqual(frappe.db.get_value(so.doctype, so.name, "advance_payment_status"), "Requested")
pe = pr.set_as_paid()
pr.reload() # status updated
pe.reload() # references moved to Sales Invoice
self.assertEqual(pr.status, "Paid")
self.assertEqual(pe.references[0].reference_doctype, "Sales Invoice")
self.assertEqual(frappe.db.get_value(so.doctype, so.name, "advance_payment_status"), "Fully Paid")
pe.cancel()
pr.reload()
self.assertEqual(pr.status, "Paid") # TODO: this might be a bug
so.reload() # reload
# regardless, since the references have already "handed-over" to SI,
# the SO keeps its historical state at the time of hand over
self.assertEqual(frappe.db.get_value(so.doctype, so.name, "advance_payment_status"), "Fully Paid")
pr.cancel()
self.assertEqual(
frappe.db.get_value(so.doctype, so.name, "advance_payment_status"), "Not Requested"
) # TODO: this might be a bug; handover has happened
# Flow NOT progressing to SI with payment entries NOT "moved"
so = make_sales_order(qty=1, rate=100)
self.assertEqual(frappe.db.get_value(so.doctype, so.name, "advance_payment_status"), "Not Requested")
pr = make_payment_request(
dt=so.doctype, dn=so.name, submit_doc=True, return_doc=True, mute_email=True
)
self.assertEqual(frappe.db.get_value(so.doctype, so.name, "advance_payment_status"), "Requested")
pe = get_payment_entry(so.doctype, so.name).save().submit()
self.assertEqual(frappe.db.get_value(so.doctype, so.name, "advance_payment_status"), "Fully Paid")
pe.reload()
pe.cancel()
self.assertEqual(
frappe.db.get_value(so.doctype, so.name, "advance_payment_status"), "Requested"
) # here: reset
pr.reload()
pr.cancel()
self.assertEqual(
frappe.db.get_value(so.doctype, so.name, "advance_payment_status"), "Not Requested"
) # here: reset
>>>>>>> 0447c7be0a (fix: Treat rows as Unit Price rows only until the qty is 0)
def test_pick_list_without_rejected_materials(self):
serial_and_batch_item = make_item(
"_Test Serial and Batch Item for Rejected Materials",
@@ -2302,7 +2199,7 @@ class TestSalesOrder(AccountsTestMixin, FrappeTestCase):
po.submit()
self.assertEqual(po.taxes[0].tax_amount, 2)
@IntegrationTestCase.change_settings("Selling Settings", {"allow_zero_qty_in_sales_order": 1})
@change_settings("Selling Settings", {"allow_zero_qty_in_sales_order": 1})
def test_deliver_zero_qty_purchase_order(self):
"""
Test the flow of a Unit Price SO and DN creation against it until completion.
@@ -2350,7 +2247,7 @@ class TestSalesOrder(AccountsTestMixin, FrappeTestCase):
self.assertEqual(so.per_delivered, 100.0)
self.assertEqual(so.status, "To Bill")
@IntegrationTestCase.change_settings("Selling Settings", {"allow_zero_qty_in_sales_order": 1})
@change_settings("Selling Settings", {"allow_zero_qty_in_sales_order": 1})
def test_bill_zero_qty_sales_order(self):
so = make_sales_order(qty=0)

View File

@@ -32,16 +32,9 @@
"allow_sales_order_creation_for_expired_quotation",
"dont_reserve_sales_order_qty_on_sales_return",
"hide_tax_id",
<<<<<<< HEAD
"enable_discount_accounting"
=======
"enable_discount_accounting",
"enable_cutoff_date_on_bulk_delivery_note_creation",
"allow_zero_qty_in_quotation",
"allow_zero_qty_in_sales_order",
"experimental_section",
"use_server_side_reactivity"
>>>>>>> c1e4e7af28 (feat: Unit Price Contract)
"allow_zero_qty_in_sales_order"
],
"fields": [
{
@@ -209,25 +202,6 @@
"fieldname": "blanket_order_allowance",
"fieldtype": "Float",
"label": "Blanket Order Allowance (%)"
<<<<<<< HEAD
=======
},
{
"default": "0",
"fieldname": "enable_cutoff_date_on_bulk_delivery_note_creation",
"fieldtype": "Check",
"label": "Enable Cut-Off Date on Bulk Delivery Note Creation"
},
{
"fieldname": "experimental_section",
"fieldtype": "Section Break",
"label": "Experimental"
},
{
"default": "1",
"fieldname": "use_server_side_reactivity",
"fieldtype": "Check",
"label": "Use Server Side Reactivity"
},
{
"default": "0",
@@ -239,12 +213,7 @@
"default": "0",
"fieldname": "allow_zero_qty_in_quotation",
"fieldtype": "Check",
<<<<<<< HEAD
"label": "Allow 0 Qty in Quotation (Unit Price Contract)"
>>>>>>> c1e4e7af28 (feat: Unit Price Contract)
=======
"label": "Allow 0 Qty in Quotation (Unit Price Items)"
>>>>>>> e403d3f153 (feat: Unit Price Items in Buying (RFQ, SQ, PO))
}
],
"grid_page_length": 50,
@@ -253,15 +222,7 @@
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
<<<<<<< HEAD
<<<<<<< HEAD
"modified": "2023-10-25 14:03:03.966701",
=======
"modified": "2025-02-28 18:19:46.436595",
>>>>>>> c1e4e7af28 (feat: Unit Price Contract)
=======
"modified": "2025-03-03 16:39:16.360823",
>>>>>>> e403d3f153 (feat: Unit Price Items in Buying (RFQ, SQ, PO))
"modified_by": "Administrator",
"module": "Selling",
"name": "Selling Settings",
@@ -286,12 +247,7 @@
"write": 1
}
],
<<<<<<< HEAD
"sort_field": "modified",
=======
"row_format": "Dynamic",
"sort_field": "creation",
>>>>>>> c1e4e7af28 (feat: Unit Price Contract)
"sort_order": "DESC",
"states": [],
"track_changes": 1