Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 
 
 

166 строки
4.7 KiB

  1. # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
  2. # MIT License. See license.txt
  3. from __future__ import unicode_literals
  4. import frappe, os, copy, json
  5. from frappe import _
  6. from frappe.modules import get_doc_path
  7. from jinja2 import TemplateNotFound
  8. from frappe.utils.formatters import format_value
  9. from frappe.utils import cint
  10. no_cache = 1
  11. no_sitemap = 1
  12. base_template_path = "templates/pages/print.html"
  13. standard_format = "templates/print_formats/standard.html"
  14. def get_context(context):
  15. if not frappe.form_dict.format:
  16. frappe.form_dict.format = standard_format
  17. if not frappe.form_dict.doctype or not frappe.form_dict.name:
  18. return {
  19. "body": """<h1>Error</h1>
  20. <p>Parameters doctype, name and format required</p>
  21. <pre>%s</pre>""" % repr(frappe.form_dict)
  22. }
  23. doc = frappe.get_doc(frappe.form_dict.doctype, frappe.form_dict.name)
  24. for ptype in ("read", "print"):
  25. if not frappe.has_permission(doc.doctype, ptype, doc):
  26. return {
  27. "body": """<h1>Error</h1>
  28. <p>No {ptype} permission</p>""".format(ptype=ptype)
  29. }
  30. meta = frappe.get_meta(doc.doctype)
  31. return {
  32. "body": get_html(doc, print_format = frappe.form_dict.format,
  33. meta=meta, trigger_print = frappe.form_dict.trigger_print),
  34. "css": get_print_style(frappe.form_dict.style),
  35. "comment": frappe.session.user,
  36. "title": doc.get(meta.title_field) if meta.title_field else doc.name
  37. }
  38. @frappe.whitelist()
  39. def get_html(doc, name=None, print_format=None, meta=None,
  40. no_letterhead=False, trigger_print=False):
  41. from jinja2 import Environment
  42. if isinstance(doc, basestring) and isinstance(name, basestring):
  43. doc = frappe.get_doc(doc, name)
  44. if isinstance(doc, basestring):
  45. doc = frappe.get_doc(json.loads(doc))
  46. if not meta:
  47. meta = frappe.get_meta(doc.doctype)
  48. if print_format in ("Standard", standard_format):
  49. template = frappe.get_template("templates/print_formats/standard.html")
  50. else:
  51. template = Environment().from_string(get_print_format(doc.doctype,
  52. print_format))
  53. args = {
  54. "doc": doc,
  55. "meta": frappe.get_meta(doc.doctype),
  56. "layout": make_layout(doc, meta),
  57. "frappe": frappe,
  58. "utils": frappe.utils,
  59. "is_visible": is_visible,
  60. "format": format_value,
  61. "no_letterhead": no_letterhead,
  62. "trigger_print": cint(trigger_print),
  63. "letter_head": frappe.db.get_value("Letter Head",
  64. doc.letter_head, "content") if doc.get("letter_head") else ""
  65. }
  66. html = template.render(args, filters={"len": len})
  67. return html
  68. def get_print_format(doctype, format_name):
  69. if format_name==standard_format:
  70. return format_name
  71. opts = frappe.db.get_value("Print Format", format_name, "disabled", as_dict=True)
  72. if not opts:
  73. frappe.throw(_("Print Format {0} does not exist").format(format_name), frappe.DoesNotExistError)
  74. elif opts.disabled:
  75. frappe.throw(_("Print Format {0} is disabled").format(format_name), frappe.DoesNotExistError)
  76. # server, find template
  77. path = os.path.join(get_doc_path(frappe.db.get_value("DocType", doctype, "module"),
  78. "Print Format", format_name), frappe.scrub(format_name) + ".html")
  79. if os.path.exists(path):
  80. with open(path, "r") as pffile:
  81. return pffile.read()
  82. else:
  83. html = frappe.db.get_value("Print Format", format_name, "html")
  84. if html:
  85. return html
  86. else:
  87. frappe.throw(_("No template found at path: {0}").format(path),
  88. frappe.TemplateNotFoundError)
  89. def make_layout(doc, meta):
  90. layout, page = [], []
  91. layout.append(page)
  92. for df in meta.fields:
  93. if df.fieldtype=="Section Break" or page==[]:
  94. page.append([])
  95. if df.fieldtype=="Column Break" or (page[-1]==[] and df.fieldtype!="Section Break"):
  96. page[-1].append([])
  97. if is_visible(df) and doc.get(df.fieldname) is not None:
  98. page[-1][-1].append(df)
  99. # if table, add the row info in the field
  100. # if a page break is found, create a new docfield
  101. if df.fieldtype=="Table":
  102. df.rows = []
  103. df.start = 0
  104. df.end = None
  105. for i, row in enumerate(doc.get(df.fieldname)):
  106. if row.get("page_break"):
  107. # close the earlier row
  108. df.end = i
  109. # new page, with empty section and column
  110. page = [[[]]]
  111. layout.append(page)
  112. # continue the table in a new page
  113. df = copy.copy(df)
  114. df.start = i
  115. df.end = None
  116. page[-1][-1].append(df)
  117. # filter empty sections
  118. layout = [filter(lambda s: any(filter(lambda c: any(c), s)), page) for page in layout]
  119. return layout
  120. def is_visible(df):
  121. no_display = ("Section Break", "Column Break", "Button")
  122. return (df.fieldtype not in no_display) and df.label and not df.print_hide
  123. def get_print_style(style=None):
  124. if not style:
  125. style = frappe.db.get_default("print_style") or "Standard"
  126. css = frappe.get_template("templates/styles/standard.css").render()
  127. try:
  128. css += frappe.get_template("templates/styles/" + style.lower() + ".css").render()
  129. except TemplateNotFound:
  130. pass
  131. return css