Parcourir la source

Revert "refactor: set amended docname to original docname"

This reverts commit d459847ae3.
version-14
leela il y a 4 ans
Parent
révision
b719e1481d
8 fichiers modifiés avec 28 ajouts et 164 suppressions
  1. +3
    -5
      frappe/core/doctype/doctype/test_doctype.py
  2. +3
    -6
      frappe/model/document.py
  3. +12
    -71
      frappe/model/naming.py
  4. +0
    -1
      frappe/patches.txt
  5. +0
    -27
      frappe/patches/v13_0/rename_cancelled_docs.py
  6. +10
    -14
      frappe/public/js/frappe/form/form.js
  7. +0
    -6
      frappe/public/js/frappe/router.js
  8. +0
    -34
      frappe/tests/test_naming.py

+ 3
- 5
frappe/core/doctype/doctype/test_doctype.py Voir le fichier

@@ -348,7 +348,6 @@ class TestDocType(unittest.TestCase):
dump_docs = json.dumps(docs.get('docs'))
cancel_all_linked_docs(dump_docs)
data_link_doc.cancel()
data_doc.name = '{}-CAN-0'.format(data_doc.name)
data_doc.load_from_db()
self.assertEqual(data_link_doc.docstatus, 2)
self.assertEqual(data_doc.docstatus, 2)
@@ -372,7 +371,7 @@ class TestDocType(unittest.TestCase):
for data in link_doc.get('permissions'):
data.submit = 1
data.cancel = 1
link_doc.insert(ignore_if_duplicate=True)
link_doc.insert()

#create first parent doctype
test_doc_1 = new_doctype('Test Doctype 1')
@@ -387,7 +386,7 @@ class TestDocType(unittest.TestCase):
for data in test_doc_1.get('permissions'):
data.submit = 1
data.cancel = 1
test_doc_1.insert(ignore_if_duplicate=True)
test_doc_1.insert()

#crete second parent doctype
doc = new_doctype('Test Doctype 2')
@@ -402,7 +401,7 @@ class TestDocType(unittest.TestCase):
for data in link_doc.get('permissions'):
data.submit = 1
data.cancel = 1
doc.insert(ignore_if_duplicate=True)
doc.insert()

# create doctype data
data_link_doc_1 = frappe.new_doc('Test Linked Doctype 1')
@@ -433,7 +432,6 @@ class TestDocType(unittest.TestCase):
# checking that doc for Test Doctype 2 is not canceled
self.assertRaises(frappe.LinkExistsError, data_link_doc_1.cancel)

data_doc_2.name = '{}-CAN-0'.format(data_doc_2.name)
data_doc.load_from_db()
data_doc_2.load_from_db()
self.assertEqual(data_link_doc_1.docstatus, 2)


+ 3
- 6
frappe/model/document.py Voir le fichier

@@ -5,7 +5,7 @@ import time
from frappe import _, msgprint, is_whitelisted
from frappe.utils import flt, cstr, now, get_datetime_str, file_lock, date_diff
from frappe.model.base_document import BaseDocument, get_controller
from frappe.model.naming import set_new_name, gen_new_name_for_cancelled_doc
from frappe.model.naming import set_new_name
from werkzeug.exceptions import NotFound, Forbidden
import hashlib, json
from frappe.model import optional_fields, table_fields
@@ -705,6 +705,7 @@ class Document(BaseDocument):
else:
tmp = frappe.db.sql("""select modified, docstatus from `tab{0}`
where name = %s for update""".format(self.doctype), self.name, as_dict=True)

if not tmp:
frappe.throw(_("Record does not exist"))
else:
@@ -915,12 +916,8 @@ class Document(BaseDocument):

@whitelist.__func__
def _cancel(self):
"""Cancel the document. Sets `docstatus` = 2, then saves.
"""
"""Cancel the document. Sets `docstatus` = 2, then saves."""
self.docstatus = 2
new_name = gen_new_name_for_cancelled_doc(self)
frappe.rename_doc(self.doctype, self.name, new_name, force=True, show_alert=False)
self.name = new_name
self.save()

@whitelist.__func__


+ 12
- 71
frappe/model/naming.py Voir le fichier

@@ -28,7 +28,7 @@ def set_new_name(doc):
doc.name = None

if getattr(doc, "amended_from", None):
doc.name = _get_amended_name(doc)
_set_amended_name(doc)
return

elif getattr(doc.meta, "issingle", False):
@@ -221,15 +221,6 @@ def revert_series_if_last(key, name, doc=None):
* prefix = #### and hashes = 2021 (hash doesn't exist)
* will search hash in key then accordingly get prefix = ""
"""
if hasattr(doc, 'amended_from'):
# do not revert if doc is amended, since cancelled docs still exist
if doc.docstatus != 2 and doc.amended_from:
return

# for first cancelled doc
if doc.docstatus == 2 and not doc.amended_from:
name, _ = NameParser.parse_docname(doc.name, sep='-CAN-')

if ".#" in key:
prefix, hashes = key.rsplit(".", 1)
if "#" not in hashes:
@@ -312,9 +303,16 @@ def append_number_if_name_exists(doctype, value, fieldname="name", separator="-"
return value


def _get_amended_name(doc):
name, _ = NameParser(doc).parse_amended_from()
return name
def _set_amended_name(doc):
am_id = 1
am_prefix = doc.amended_from
if frappe.db.get_value(doc.doctype, doc.amended_from, "amended_from"):
am_id = cint(doc.amended_from.split("-")[-1]) + 1
am_prefix = "-".join(doc.amended_from.split("-")[:-1]) # except the last hyphen

doc.name = am_prefix + "-" + str(am_id)
return doc.name


def _field_autoname(autoname, doc, skip_slicing=None):
"""
@@ -325,6 +323,7 @@ def _field_autoname(autoname, doc, skip_slicing=None):
name = (cstr(doc.get(fieldname)) or "").strip()
return name


def _prompt_autoname(autoname, doc):
"""
Generate a name using Prompt option. This simply means the user will have to set the name manually.
@@ -355,61 +354,3 @@ def _format_autoname(autoname, doc):
name = re.sub(r"(\{[\w | #]+\})", get_param_value_for_match, autoname_value)

return name

class NameParser:
"""Parse document name and return all the parts of it.

NOTE: It handles cancellend and amended doc parsing for now. It can be expanded.
"""
def __init__(self, doc):
self.doc = doc

def parse_name(self):
if not hasattr(self.doc, "amended_from"):
return (self.doc.name, None, None)

#If document is cancelled document
if hasattr(self.doc, "amended_from") and self.doc.docstatus == 2:
return self.parse_docname(self.doc.name, sep='-CAN-')
return self.parse_docname(self.doc.name)

def parse_amended_from(self):
if not getattr(self.doc, 'amended_from', None):
return (None, None)
return self.parse_docname(self.doc.amended_from, '-CAN-')

@classmethod
def parse_docname(cls, name, sep='-'):
split_list = name.rsplit(sep, 1)

if len(split_list) == 1:
return (name, None)
return (split_list[0], split_list[1])

def get_cancelled_doc_latest_counter(tname, docname):
"""Get the latest counter used for cancelled docs of given docname.
"""
name_prefix = f'{docname}-CAN-'

rows = frappe.db.sql("""
select
name
from `tab{tname}`
where
name like %(name_prefix)s and docstatus=2
""".format(tname=tname), {'name_prefix': name_prefix+'%'}, as_dict=1)

if not rows:
return -1
return max([int(row.name.replace(name_prefix, '') or -1) for row in rows])

def gen_new_name_for_cancelled_doc(doc):
"""Generate a new name for cancelled document.
"""
if getattr(doc, "amended_from", None):
name, _ = NameParser(doc).parse_amended_from()
else:
name = doc.name

counter = get_cancelled_doc_latest_counter(doc.doctype, name)
return f'{name}-CAN-{counter+1}'

+ 0
- 1
frappe/patches.txt Voir le fichier

@@ -180,4 +180,3 @@ frappe.patches.v12_0.rename_uploaded_files_with_proper_name
frappe.patches.v13_0.queryreport_columns
frappe.patches.v13_0.jinja_hook
frappe.patches.v13_0.update_notification_channel_if_empty
frappe.patches.v13_0.rename_cancelled_docs

+ 0
- 27
frappe/patches/v13_0/rename_cancelled_docs.py Voir le fichier

@@ -1,27 +0,0 @@
import frappe
from frappe.model.naming import NameParser
from frappe.model.rename_doc import rename_doc

def execute():
"""Rename already cancelled documents by adding `CAN-X` postfix instead of `-X`.
"""
for doctype in frappe.db.get_all('DocType'):
doctype = frappe.get_doc('DocType', doctype.name)
if doctype.is_submittable and frappe.db.table_exists(doctype.name):
cancelled_docs = frappe.db.get_all(doctype.name, ['amended_from', 'name'], {'docstatus':2})

for doc in cancelled_docs:
if '-CAN-' in doc.name:
continue

current_name = doc.name

if getattr(doc, "amended_from", None):
orig_name, counter = NameParser.parse_docname(doc.name)
else:
orig_name, counter = doc.name, 0
new_name = f'{orig_name}-CAN-{counter or 0}'

print(f"Renaming {doctype.name} record from {current_name} to {new_name}")
rename_doc(doctype.name, current_name, new_name, ignore_permissions=True, show_alert=False)
frappe.db.commit()

+ 10
- 14
frappe/public/js/frappe/form/form.js Voir le fichier

@@ -770,36 +770,32 @@ frappe.ui.form.Form = class FrappeForm {
}

_cancel(btn, callback, on_error, skip_confirm) {
const me = this;
const cancel_doc = () => {
frappe.validated = true;
this.script_manager.trigger("before_cancel").then(() => {
me.script_manager.trigger("before_cancel").then(() => {
if (!frappe.validated) {
return this.handle_save_fail(btn, on_error);
return me.handle_save_fail(btn, on_error);
}

const original_name = this.docname;
const after_cancel = (r) => {
var after_cancel = function(r) {
if (r.exc) {
this.handle_save_fail(btn, on_error);
me.handle_save_fail(btn, on_error);
} else {
frappe.utils.play_sound("cancel");
me.refresh();
callback && callback();
this.script_manager.trigger("after_cancel");
frappe.run_serially([
() => this.rename_notify(this.doctype, original_name, r.docs[0].name),
() => frappe.router.clear_re_route(this.doctype, original_name),
() => this.refresh(),
]);
me.script_manager.trigger("after_cancel");
}
};
frappe.ui.form.save(this, "cancel", after_cancel, btn);
frappe.ui.form.save(me, "cancel", after_cancel, btn);
});
}

if (skip_confirm) {
cancel_doc();
} else {
frappe.confirm(__("Permanently Cancel {0}?", [this.docname]), cancel_doc, this.handle_save_fail(btn, on_error));
frappe.confirm(__("Permanently Cancel {0}?", [this.docname]), cancel_doc, me.handle_save_fail(btn, on_error));
}
};

@@ -821,7 +817,7 @@ frappe.ui.form.Form = class FrappeForm {
'docname': this.doc.name
}).then(is_amended => {
if (is_amended) {
frappe.throw(__('This document is already amended, you cannot amend it again'));
frappe.throw(__('This document is already amended, you cannot ammend it again'));
}
this.validate_form_action("Amend");
var me = this;


+ 0
- 6
frappe/public/js/frappe/router.js Voir le fichier

@@ -234,12 +234,6 @@ frappe.router = {
}
},

clear_re_route(doctype, docname) {
delete frappe.re_route[
`${encodeURIComponent(frappe.router.slug(doctype))}/${encodeURIComponent(docname)}`
];
},

set_title(sub_path) {
if (frappe.route_titles[sub_path]) {
frappe.utils.set_title(frappe.route_titles[sub_path]);


+ 0
- 34
frappe/tests/test_naming.py Voir le fichier

@@ -116,37 +116,3 @@ class TestNaming(unittest.TestCase):

self.assertEqual(current_index.get('current'), 2)
frappe.db.sql("""delete from `tabSeries` where name = %s""", series)

def test_naming_for_cancelled_and_amended_doc(self):
submittable_doctype = frappe.get_doc({
"doctype": "DocType",
"module": "Core",
"custom": 1,
"is_submittable": 1,
"permissions": [{
"role": "System Manager",
"read": 1
}],
"name": 'Submittable Doctype'
}).insert(ignore_if_duplicate=True)

doc = frappe.new_doc('Submittable Doctype')
doc.save()
original_name = doc.name

doc.submit()
doc.cancel()
cancelled_name = doc.name
self.assertEqual(cancelled_name, "{}-CAN-0".format(original_name))

amended_doc = frappe.copy_doc(doc)
amended_doc.docstatus = 0
amended_doc.amended_from = doc.name
amended_doc.save()
self.assertEqual(amended_doc.name, original_name)

amended_doc.submit()
amended_doc.cancel()
self.assertEqual(amended_doc.name, "{}-CAN-1".format(original_name))

submittable_doctype.delete()

Chargement…
Annuler
Enregistrer