feat: new REST API for copy_doc (#31160)

* feat: new REST API for copy_doc

* test: copy endpoint
This commit is contained in:
Raffael Meyer 2025-02-07 13:16:53 +01:00 committed by GitHub
parent 165968714d
commit aade0df7bf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 31 additions and 0 deletions

View file

@ -95,6 +95,17 @@ def create_doc(doctype: str):
return frappe.new_doc(doctype, **data).insert()
def copy_doc(doctype: str, name: str, ignore_no_copy: bool = True):
"""Return a clean copy of the given document that can be modified and posted as a new document."""
doc = frappe.get_doc(doctype, name)
doc.check_permission("read")
doc.apply_fieldlevel_read_permissions()
copy = frappe.copy_doc(doc, ignore_no_copy=ignore_no_copy)
return copy.as_dict(no_private_properties=True, no_nulls=True)
def update_doc(doctype: str, name: str):
data = frappe.form_dict
@ -186,6 +197,7 @@ url_rules = [
Rule("/document/<doctype>", methods=["GET"], endpoint=document_list),
Rule("/document/<doctype>", methods=["POST"], endpoint=create_doc),
Rule("/document/<doctype>/<path:name>/", methods=["GET"], endpoint=read_doc),
Rule("/document/<doctype>/<path:name>/copy", methods=["GET"], endpoint=copy_doc),
Rule("/document/<doctype>/<path:name>/", methods=["PATCH", "PUT"], endpoint=update_doc),
Rule("/document/<doctype>/<path:name>/", methods=["DELETE"], endpoint=delete_doc),
Rule(

View file

@ -84,6 +84,25 @@ class TestResourceAPIV2(FrappeAPITestCase):
self.assertIsInstance(docname, str)
self.GENERATED_DOCUMENTS.append(docname)
def test_copy_document(self):
doc = frappe.get_doc(self.DOCTYPE, self.GENERATED_DOCUMENTS[0])
response = self.get(self.resource(self.DOCTYPE, doc.name, "copy"))
self.assertEqual(response.status_code, 200)
data = response.json["data"]
self.assertEqual(data["doctype"], self.DOCTYPE)
self.assertEqual(data["description"], doc.description)
self.assertEqual(data["status"], doc.status)
self.assertEqual(data["priority"], doc.priority)
self.assertNotIn("name", data)
self.assertNotIn("creation", data)
self.assertNotIn("modified", data)
self.assertNotIn("modified_by", data)
self.assertNotIn("owner", data)
self.assertNotIn("docstatus", data)
def test_delete_document(self):
doc_to_delete = choice(self.GENERATED_DOCUMENTS)
response = self.delete(self.resource(self.DOCTYPE, doc_to_delete))