Revert "Consolidated bulk print from list view" (#37724)
This commit is contained in:
parent
c5349c4ec0
commit
1f42ed8d5a
4 changed files with 0 additions and 306 deletions
|
|
@ -166,104 +166,6 @@ export default class BulkOperations {
|
|||
dialog.show();
|
||||
}
|
||||
|
||||
consolidated_print(docs) {
|
||||
const print_settings = frappe.model.get_doc(":Print Settings", "Print Settings");
|
||||
const allow_print_for_draft = cint(print_settings.allow_print_for_draft);
|
||||
const is_submittable = frappe.model.is_submittable(this.doctype);
|
||||
const allow_print_for_cancelled = cint(print_settings.allow_print_for_cancelled);
|
||||
const letterheads = this.get_letterhead_options();
|
||||
const MAX_CONSOLIDATED_LIMIT = 100;
|
||||
|
||||
const valid_docs = docs
|
||||
.filter((doc) => {
|
||||
return (
|
||||
!is_submittable ||
|
||||
doc.docstatus === 1 ||
|
||||
(allow_print_for_cancelled && doc.docstatus == 2) ||
|
||||
(allow_print_for_draft && doc.docstatus == 0) ||
|
||||
frappe.user.has_role("Administrator")
|
||||
);
|
||||
})
|
||||
.map((doc) => doc.name);
|
||||
|
||||
const invalid_docs = docs.filter((doc) => !valid_docs.includes(doc.name));
|
||||
|
||||
if (invalid_docs.length > 0) {
|
||||
frappe.msgprint(__("You selected Draft or Cancelled documents"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (valid_docs.length === 0) {
|
||||
frappe.msgprint(__("Select atleast 1 record for printing"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (valid_docs.length > MAX_CONSOLIDATED_LIMIT) {
|
||||
frappe.msgprint(
|
||||
__("You can only consolidate up to {0} documents at a time", [
|
||||
MAX_CONSOLIDATED_LIMIT,
|
||||
])
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const dialog = new frappe.ui.Dialog({
|
||||
title: __("Consolidated Print"),
|
||||
fields: [
|
||||
{
|
||||
fieldtype: "HTML",
|
||||
options: `<p class="text-muted small">${__(
|
||||
"All selected documents will be rendered in a single continuous layout without page breaks between them."
|
||||
)}</p>`,
|
||||
},
|
||||
{
|
||||
fieldtype: "Select",
|
||||
label: __("Letter Head"),
|
||||
fieldname: "letter_sel",
|
||||
options: letterheads,
|
||||
default: letterheads[0],
|
||||
},
|
||||
{
|
||||
fieldtype: "Select",
|
||||
label: __("Print Format"),
|
||||
fieldname: "print_sel",
|
||||
options: frappe.meta.get_print_formats(this.doctype),
|
||||
default: frappe.get_meta(this.doctype).default_print_format,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
dialog.set_primary_action(__("Print"), (args) => {
|
||||
if (!args) return;
|
||||
const default_print_format = frappe.get_meta(this.doctype).default_print_format;
|
||||
const with_letterhead = args.letter_sel == __("No Letterhead") ? 0 : 1;
|
||||
const print_format = args.print_sel ? args.print_sel : default_print_format;
|
||||
const names_json = JSON.stringify(valid_docs);
|
||||
const letterhead = args.letter_sel;
|
||||
|
||||
const w = window.open(
|
||||
"/consolidated_printview?" +
|
||||
"doctype=" +
|
||||
encodeURIComponent(this.doctype) +
|
||||
"&names=" +
|
||||
encodeURIComponent(names_json) +
|
||||
"&format=" +
|
||||
encodeURIComponent(print_format) +
|
||||
"&no_letterhead=" +
|
||||
(with_letterhead ? "0" : "1") +
|
||||
"&letterhead=" +
|
||||
encodeURIComponent(letterhead) +
|
||||
"&trigger_print=1"
|
||||
);
|
||||
|
||||
if (!w) {
|
||||
frappe.msgprint(__("Please enable pop-ups"));
|
||||
}
|
||||
dialog.hide();
|
||||
});
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
get_letterhead_options() {
|
||||
const letterhead_options = [__("No Letterhead")];
|
||||
frappe.call({
|
||||
|
|
|
|||
|
|
@ -2279,14 +2279,6 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList {
|
|||
};
|
||||
};
|
||||
|
||||
const bulk_consolidated_printing = () => {
|
||||
return {
|
||||
label: __("Consolidated Print", null, "Button in list view actions menu"),
|
||||
action: () => bulk_operations.consolidated_print(this.get_checked_items()),
|
||||
standard: true,
|
||||
};
|
||||
};
|
||||
|
||||
const bulk_delete = () => {
|
||||
return {
|
||||
label: __("Delete", null, "Button in list view actions menu"),
|
||||
|
|
@ -2577,7 +2569,6 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList {
|
|||
// bulk printing
|
||||
if (frappe.model.can_print(doctype)) {
|
||||
actions_menu_items.push(bulk_printing());
|
||||
actions_menu_items.push(bulk_consolidated_printing());
|
||||
}
|
||||
|
||||
// bulk submit
|
||||
|
|
|
|||
|
|
@ -1,81 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="{{ lang }}" dir="{{ layout_direction }}">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{ title }}</title>
|
||||
<meta name="generator" content="frappe">
|
||||
{{ include_style('print.bundle.css') }}
|
||||
{% if print_style %}
|
||||
<style>
|
||||
{{ print_style }}
|
||||
</style>
|
||||
{% endif %}
|
||||
<style>
|
||||
/* ── Consolidated Print overrides ───────────────────────────────────────
|
||||
Remove forced page breaks that the standard per-document template inserts
|
||||
between its internal "pages". Documents flow continuously. */
|
||||
.consolidated-doc .page-break {
|
||||
page-break-after: auto !important;
|
||||
break-after: auto !important;
|
||||
}
|
||||
|
||||
/* Visual separator shown on screen between documents (hidden when printing) */
|
||||
.consolidated-doc-separator {
|
||||
border: none;
|
||||
border-top: 2px dashed #ccc;
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
.consolidated-doc:not(:last-child) {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
@media print {
|
||||
/* Thin rule visible in the printed output so documents are distinguishable */
|
||||
.consolidated-doc:not(:last-child)::after {
|
||||
content: "";
|
||||
display: block;
|
||||
border-top: 1px solid #888;
|
||||
margin: 12px 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="action-banner print-hide">
|
||||
<a class="p-2" onclick="window.print();">
|
||||
{{ _("Print") }}
|
||||
</a>
|
||||
</div>
|
||||
<div class="print-format-gutter">
|
||||
<div class="print-format">
|
||||
{{ body }}
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// Mirror the footer-positioning logic from printview.html for each doc
|
||||
document.querySelectorAll('.consolidated-doc').forEach(function(docEl) {
|
||||
const pageDiv = docEl.querySelector('.page-break');
|
||||
if (pageDiv) {
|
||||
pageDiv.style.display = 'flex';
|
||||
pageDiv.style.flexDirection = 'column';
|
||||
}
|
||||
const footerHtml = docEl.getElementById
|
||||
? docEl.getElementById('footer-html')
|
||||
: docEl.querySelector('#footer-html');
|
||||
if (footerHtml) {
|
||||
footerHtml.classList.add('hidden-pdf');
|
||||
footerHtml.classList.remove('visible-pdf');
|
||||
footerHtml.style.order = 1;
|
||||
footerHtml.style.marginTop = '20px';
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
{%- if doc_count -%}
|
||||
<!-- consolidated: {{ doc_count }} documents -->
|
||||
{%- endif -%}
|
||||
</html>
|
||||
|
|
@ -1,118 +0,0 @@
|
|||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# License: MIT. See LICENSE
|
||||
|
||||
import json
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.core.doctype.access_log.access_log import make_access_log
|
||||
from frappe.utils import cint
|
||||
from frappe.utils.jinja_globals import is_rtl
|
||||
from frappe.www.printview import (
|
||||
get_print_format_doc,
|
||||
get_print_style,
|
||||
get_rendered_template,
|
||||
set_link_titles,
|
||||
trigger_print_script,
|
||||
)
|
||||
|
||||
no_cache = 1
|
||||
|
||||
MAX_CONSOLIDATED_PRINT_DOCS = 100
|
||||
|
||||
|
||||
def get_context(context):
|
||||
"""Build context for consolidated (multi-document, no page-break) print."""
|
||||
doctype = frappe.form_dict.get("doctype")
|
||||
names_json = frappe.form_dict.get("names")
|
||||
|
||||
if not doctype or not names_json:
|
||||
return {
|
||||
"body": "<h1>Error</h1><p>Parameters <code>doctype</code> and <code>names</code> are required.</p>",
|
||||
"print_style": "",
|
||||
"title": "Error",
|
||||
"lang": "en",
|
||||
"layout_direction": "ltr",
|
||||
"doc_count": 0,
|
||||
}
|
||||
|
||||
try:
|
||||
names = json.loads(names_json)
|
||||
except (json.JSONDecodeError, TypeError):
|
||||
frappe.throw(_("Invalid names parameter: must be a JSON array of document names"))
|
||||
|
||||
if not isinstance(names, list) or len(names) == 0:
|
||||
frappe.throw(_("At least one document name is required"))
|
||||
|
||||
if len(names) > MAX_CONSOLIDATED_PRINT_DOCS:
|
||||
frappe.throw(
|
||||
_("Cannot consolidate more than {0} documents at a time").format(MAX_CONSOLIDATED_PRINT_DOCS)
|
||||
)
|
||||
|
||||
format_name = frappe.form_dict.get("format") or None
|
||||
no_letterhead = frappe.form_dict.get("no_letterhead", 0)
|
||||
letterhead = frappe.form_dict.get("letterhead") or None
|
||||
trigger_print = cint(frappe.form_dict.get("trigger_print", 0))
|
||||
|
||||
meta = frappe.get_meta(doctype)
|
||||
print_format = get_print_format_doc(format_name, meta=meta)
|
||||
|
||||
all_html_parts = []
|
||||
|
||||
for name in names:
|
||||
try:
|
||||
doc = frappe.get_lazy_doc(doctype, name)
|
||||
set_link_titles(doc)
|
||||
html = _get_doc_print_html(doc, print_format, meta, no_letterhead, letterhead)
|
||||
all_html_parts.append(html)
|
||||
except frappe.PermissionError:
|
||||
frappe.log_error(
|
||||
title="Consolidated Print Permission Error",
|
||||
message=f"No permission to print {doctype} {name}",
|
||||
)
|
||||
except Exception:
|
||||
frappe.log_error(
|
||||
title="Consolidated Print Render Error",
|
||||
message=f"Error rendering {doctype} {name}",
|
||||
)
|
||||
|
||||
separator = '<div class="consolidated-doc-separator print-hide"></div>'
|
||||
body = separator.join(f'<div class="consolidated-doc">{html}</div>' for html in all_html_parts)
|
||||
|
||||
if trigger_print:
|
||||
body += trigger_print_script
|
||||
|
||||
make_access_log(
|
||||
doctype=doctype,
|
||||
document=", ".join(names[:10]),
|
||||
file_type="PDF",
|
||||
method="Print",
|
||||
page=f"Consolidated Print Format: {getattr(print_format, 'name', 'Standard')} ({len(names)} docs)",
|
||||
)
|
||||
|
||||
return {
|
||||
"body": body,
|
||||
"print_style": get_print_style(frappe.form_dict.get("style"), print_format),
|
||||
"title": f"Consolidated Print — {doctype}",
|
||||
"lang": frappe.local.lang,
|
||||
"layout_direction": "rtl" if is_rtl() else "ltr",
|
||||
"doctype": doctype,
|
||||
"doc_count": len(all_html_parts),
|
||||
}
|
||||
|
||||
|
||||
def _get_doc_print_html(doc, print_format, meta, no_letterhead, letterhead):
|
||||
"""Return rendered HTML for a single document, handling both standard and beta print formats."""
|
||||
if print_format and print_format.get("print_format_builder_beta"):
|
||||
from frappe.utils.weasyprint import get_html
|
||||
|
||||
return get_html(doctype=doc.doctype, name=doc.name, print_format=print_format.name)
|
||||
|
||||
return get_rendered_template(
|
||||
doc=doc,
|
||||
print_format=print_format,
|
||||
meta=meta,
|
||||
no_letterhead=no_letterhead,
|
||||
letterhead=letterhead,
|
||||
trigger_print=False,
|
||||
)
|
||||
Loading…
Add table
Reference in a new issue