feat: add Consolidated Print action to list view
Wires the new /consolidated_printview backend route into the List View bulk-actions menu so users can print selected records as one continuous layout without page breaks between them. - BulkOperations.consolidated_print() validates docs against the same draft/cancelled print-settings rules as the existing print(), enforces a 100-document limit, and opens a dialog to pick Letter Head and Print Format before launching the consolidated print window - bulk_consolidated_printing() action added to list_view.js and registered immediately after the existing "Print" entry, gated by the same frappe.model.can_print() permission check Made-with: Cursor
This commit is contained in:
parent
101983c7af
commit
59f12a1ac4
2 changed files with 103 additions and 0 deletions
|
|
@ -166,6 +166,100 @@ 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({
|
||||
|
|
|
|||
|
|
@ -2264,6 +2264,14 @@ 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"),
|
||||
|
|
@ -2552,6 +2560,7 @@ 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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue