diff --git a/crm/fcrm/doctype/crm_invitation/crm_invitation.js b/crm/fcrm/doctype/crm_invitation/crm_invitation.js index f2ff047f..6e0485d8 100644 --- a/crm/fcrm/doctype/crm_invitation/crm_invitation.js +++ b/crm/fcrm/doctype/crm_invitation/crm_invitation.js @@ -1,8 +1,12 @@ // Copyright (c) 2024, Frappe Technologies Pvt. Ltd. and contributors // For license information, please see license.txt -// frappe.ui.form.on("CRM Invitation", { -// refresh(frm) { - -// }, -// }); +frappe.ui.form.on("CRM Invitation", { + refresh(frm) { + if (frm.doc.status != "Accepted") { + frm.add_custom_button(__("Accept Invitation"), () => { + return frm.call("accept_invitation"); + }); + } + }, +}); diff --git a/crm/fcrm/doctype/crm_invitation/crm_invitation.py b/crm/fcrm/doctype/crm_invitation/crm_invitation.py index cc1862f7..f4c9a8f9 100644 --- a/crm/fcrm/doctype/crm_invitation/crm_invitation.py +++ b/crm/fcrm/doctype/crm_invitation/crm_invitation.py @@ -6,4 +6,74 @@ from frappe.model.document import Document class CRMInvitation(Document): - pass \ No newline at end of file + def before_insert(self): + frappe.utils.validate_email_address(self.email, True) + + self.key = frappe.generate_hash(length=12) + self.invited_by = frappe.session.user + self.status = "Pending" + + def after_insert(self): + self.invite_via_email() + + def invite_via_email(self): + invite_link = frappe.utils.get_url(f"/api/method/crm.api.accept_invitation?key={self.key}") + if frappe.local.dev_server: + print(f"Invite link for {self.email}: {invite_link}") + + title = f"Frappe CRM" + template = "crm_invitation" + + frappe.sendmail( + recipients=self.email, + subject=f"You have been invited to join {title}", + template=template, + args={"title": title, "invite_link": invite_link}, + now=True, + ) + self.db_set("email_sent_at", frappe.utils.now()) + + @frappe.whitelist() + def accept_invitation(self): + frappe.only_for("System Manager") + self.accept() + + def accept(self): + if self.status == "Expired": + frappe.throw("Invalid or expired key") + + user = self.create_user_if_not_exists() + user.append_roles(self.role) + user.save(ignore_permissions=True) + + self.status = "Accepted" + self.accepted_at = frappe.utils.now() + self.save(ignore_permissions=True) + + def create_user_if_not_exists(self): + if not frappe.db.exists("User", self.email): + first_name = self.email.split("@")[0].title() + user = frappe.get_doc( + doctype="User", + user_type="System User", + email=self.email, + send_welcome_email=0, + first_name=first_name, + ).insert(ignore_permissions=True) + else: + user = frappe.get_doc("User", self.email) + return user + + +def expire_invitations(): + """expire invitations after 3 days""" + from frappe.utils import add_days, now + + days = 3 + invitations_to_expire = frappe.db.get_all( + "CRM Invitation", filters={"status": "Pending", "creation": ["<", add_days(now(), -days)]} + ) + for invitation in invitations_to_expire: + invitation = frappe.get_doc("CRM Invitation", invitation.name) + invitation.status = "Expired" + invitation.save(ignore_permissions=True) diff --git a/crm/templates/emails/crm_invitation.html b/crm/templates/emails/crm_invitation.html new file mode 100644 index 00000000..3e74b1d1 --- /dev/null +++ b/crm/templates/emails/crm_invitation.html @@ -0,0 +1,4 @@ +