Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 
 

161 рядки
4.2 KiB

  1. import json
  2. import frappe
  3. from frappe.core.doctype.file import remove_file_by_url
  4. from frappe.rate_limiter import rate_limit
  5. from frappe.utils import flt
  6. from frappe.website.doctype.web_form.web_form import WebForm
  7. from payments.utils import get_payment_gateway_controller
  8. class PaymentWebForm(WebForm):
  9. def validate(self):
  10. super().validate()
  11. if getattr(self, "accept_payment", False):
  12. self.validate_payment_amount()
  13. def validate_payment_amount(self):
  14. if self.amount_based_on_field and not self.amount_field:
  15. frappe.throw(frappe._("Please select a Amount Field."))
  16. elif not self.amount_based_on_field and not flt(self.amount) > 0:
  17. frappe.throw(frappe._("Amount must be greater than 0."))
  18. def get_payment_gateway_url(self, doc):
  19. if getattr(self, "accept_payment", False):
  20. controller = get_payment_gateway_controller(self.payment_gateway)
  21. title = f"Payment for {doc.doctype} {doc.name}"
  22. amount = self.amount
  23. if self.amount_based_on_field:
  24. amount = doc.get(self.amount_field)
  25. from decimal import Decimal
  26. if amount is None or Decimal(amount) <= 0:
  27. return frappe.utils.get_url(self.success_url or self.route)
  28. payment_details = {
  29. "amount": amount,
  30. "title": title,
  31. "description": title,
  32. "reference_doctype": doc.doctype,
  33. "reference_docname": doc.name,
  34. "payer_email": frappe.session.user,
  35. "payer_name": frappe.utils.get_fullname(frappe.session.user),
  36. "order_id": doc.name,
  37. "currency": self.currency,
  38. "redirect_to": frappe.utils.get_url(self.success_url or self.route),
  39. }
  40. # Redirect the user to this url
  41. return controller.get_payment_url(**payment_details)
  42. @frappe.whitelist(allow_guest=True)
  43. @rate_limit(key="web_form", limit=5, seconds=60, methods=["POST"])
  44. def accept(web_form, data, docname=None, for_payment=False):
  45. """Save the web form"""
  46. data = frappe._dict(json.loads(data))
  47. for_payment = frappe.parse_json(for_payment)
  48. docname = docname or data.name
  49. files = []
  50. files_to_delete = []
  51. web_form = frappe.get_doc("Web Form", web_form)
  52. if docname and not web_form.allow_edit:
  53. frappe.throw(frappe._("You are not allowed to update this Web Form Document"))
  54. frappe.flags.in_web_form = True
  55. meta = frappe.get_meta(data.doctype)
  56. if docname:
  57. # update
  58. doc = frappe.get_doc(data.doctype, docname)
  59. else:
  60. # insert
  61. doc = frappe.new_doc(data.doctype)
  62. # set values
  63. for field in web_form.web_form_fields:
  64. fieldname = field.fieldname
  65. df = meta.get_field(fieldname)
  66. value = data.get(fieldname, None)
  67. if df and df.fieldtype in ("Attach", "Attach Image"):
  68. if value and "data:" and "base64" in value:
  69. files.append((fieldname, value))
  70. if not doc.name:
  71. doc.set(fieldname, "")
  72. continue
  73. elif not value and doc.get(fieldname):
  74. files_to_delete.append(doc.get(fieldname))
  75. doc.set(fieldname, value)
  76. if for_payment:
  77. web_form.validate_mandatory(doc)
  78. doc.run_method("validate_payment")
  79. if doc.name:
  80. if web_form.has_web_form_permission(doc.doctype, doc.name, "write"):
  81. doc.save(ignore_permissions=True)
  82. else:
  83. # only if permissions are present
  84. doc.save()
  85. else:
  86. # insert
  87. if web_form.login_required and frappe.session.user == "Guest":
  88. frappe.throw(frappe._("You must login to submit this form"))
  89. ignore_mandatory = True if files else False
  90. doc.insert(ignore_permissions=True, ignore_mandatory=ignore_mandatory)
  91. # add files
  92. if files:
  93. for f in files:
  94. fieldname, filedata = f
  95. # remove earlier attached file (if exists)
  96. if doc.get(fieldname):
  97. remove_file_by_url(doc.get(fieldname), doctype=doc.doctype, name=doc.name)
  98. # save new file
  99. filename, dataurl = filedata.split(",", 1)
  100. _file = frappe.get_doc(
  101. {
  102. "doctype": "File",
  103. "file_name": filename,
  104. "attached_to_doctype": doc.doctype,
  105. "attached_to_name": doc.name,
  106. "content": dataurl,
  107. "decode": True,
  108. }
  109. )
  110. _file.save()
  111. # update values
  112. doc.set(fieldname, _file.file_url)
  113. doc.save(ignore_permissions=True)
  114. if files_to_delete:
  115. for f in files_to_delete:
  116. if f:
  117. remove_file_by_url(f, doctype=doc.doctype, name=doc.name)
  118. frappe.flags.web_form_doc = doc
  119. if for_payment:
  120. # this is needed for Payments app
  121. return web_form.get_payment_gateway_url(doc)
  122. else:
  123. return doc