refactor!: remove social media post module
diff --git a/erpnext/crm/doctype/linkedin_settings/__init__.py b/erpnext/crm/doctype/linkedin_settings/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/crm/doctype/linkedin_settings/__init__.py
+++ /dev/null
diff --git a/erpnext/crm/doctype/linkedin_settings/linkedin_settings.js b/erpnext/crm/doctype/linkedin_settings/linkedin_settings.js
deleted file mode 100644
index 7d6b395..0000000
--- a/erpnext/crm/doctype/linkedin_settings/linkedin_settings.js
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-
-frappe.ui.form.on('LinkedIn Settings', {
- onload: function(frm) {
- if (frm.doc.session_status == 'Expired' && frm.doc.consumer_key && frm.doc.consumer_secret) {
- frappe.confirm(
- __('Session not valid. Do you want to login?'),
- function(){
- frm.trigger("login");
- },
- function(){
- window.close();
- }
- );
- }
- frm.dashboard.set_headline(__("For more information, {0}.", [`<a target='_blank' href='https://docs.erpnext.com/docs/user/manual/en/CRM/linkedin-settings'>${__('click here')}</a>`]));
- },
- refresh: function(frm) {
- if (frm.doc.session_status=="Expired"){
- let msg = __("Session not active. Save document to login.");
- frm.dashboard.set_headline_alert(
- `<div class="row">
- <div class="col-xs-12">
- <span class="indicator whitespace-nowrap red"><span class="hidden-xs">${msg}</span></span>
- </div>
- </div>`
- );
- }
-
- if (frm.doc.session_status=="Active"){
- let d = new Date(frm.doc.modified);
- d.setDate(d.getDate()+60);
- let dn = new Date();
- let days = d.getTime() - dn.getTime();
- days = Math.floor(days/(1000 * 3600 * 24));
- let msg,color;
-
- if (days>0){
- msg = __("Your session will be expire in {0} days.", [days]);
- color = "green";
- }
- else {
- msg = __("Session is expired. Save doc to login.");
- color = "red";
- }
-
- frm.dashboard.set_headline_alert(
- `<div class="row">
- <div class="col-xs-12">
- <span class="indicator whitespace-nowrap ${color}"><span class="hidden-xs">${msg}</span></span>
- </div>
- </div>`
- );
- }
- },
- login: function(frm) {
- if (frm.doc.consumer_key && frm.doc.consumer_secret){
- frappe.dom.freeze();
- frappe.call({
- doc: frm.doc,
- method: "get_authorization_url",
- callback : function(r) {
- window.location.href = r.message;
- }
- }).fail(function() {
- frappe.dom.unfreeze();
- });
- }
- },
- after_save: function(frm) {
- frm.trigger("login");
- }
-});
diff --git a/erpnext/crm/doctype/linkedin_settings/linkedin_settings.json b/erpnext/crm/doctype/linkedin_settings/linkedin_settings.json
deleted file mode 100644
index f882e36..0000000
--- a/erpnext/crm/doctype/linkedin_settings/linkedin_settings.json
+++ /dev/null
@@ -1,112 +0,0 @@
-{
- "actions": [],
- "creation": "2020-01-30 13:36:39.492931",
- "doctype": "DocType",
- "documentation": "https://docs.erpnext.com/docs/user/manual/en/CRM/linkedin-settings",
- "editable_grid": 1,
- "engine": "InnoDB",
- "field_order": [
- "account_name",
- "column_break_2",
- "company_id",
- "oauth_details",
- "consumer_key",
- "column_break_5",
- "consumer_secret",
- "user_details_section",
- "access_token",
- "person_urn",
- "session_status"
- ],
- "fields": [
- {
- "fieldname": "account_name",
- "fieldtype": "Data",
- "label": "Account Name",
- "read_only": 1
- },
- {
- "fieldname": "oauth_details",
- "fieldtype": "Section Break",
- "label": "OAuth Credentials"
- },
- {
- "fieldname": "consumer_key",
- "fieldtype": "Data",
- "in_list_view": 1,
- "label": "Consumer Key",
- "reqd": 1
- },
- {
- "fieldname": "consumer_secret",
- "fieldtype": "Password",
- "in_list_view": 1,
- "label": "Consumer Secret",
- "reqd": 1
- },
- {
- "fieldname": "access_token",
- "fieldtype": "Data",
- "hidden": 1,
- "label": "Access Token",
- "read_only": 1
- },
- {
- "fieldname": "person_urn",
- "fieldtype": "Data",
- "hidden": 1,
- "label": "Person URN",
- "read_only": 1
- },
- {
- "fieldname": "column_break_5",
- "fieldtype": "Column Break"
- },
- {
- "fieldname": "user_details_section",
- "fieldtype": "Section Break",
- "label": "User Details"
- },
- {
- "fieldname": "session_status",
- "fieldtype": "Select",
- "hidden": 1,
- "label": "Session Status",
- "options": "Expired\nActive",
- "read_only": 1
- },
- {
- "fieldname": "column_break_2",
- "fieldtype": "Column Break"
- },
- {
- "fieldname": "company_id",
- "fieldtype": "Data",
- "label": "Company ID",
- "reqd": 1
- }
- ],
- "issingle": 1,
- "links": [],
- "modified": "2021-02-18 15:19:21.920725",
- "modified_by": "Administrator",
- "module": "CRM",
- "name": "LinkedIn Settings",
- "owner": "Administrator",
- "permissions": [
- {
- "create": 1,
- "delete": 1,
- "email": 1,
- "print": 1,
- "read": 1,
- "role": "System Manager",
- "share": 1,
- "write": 1
- }
- ],
- "quick_entry": 1,
- "sort_field": "modified",
- "sort_order": "DESC",
- "track_changes": 1
-}
\ No newline at end of file
diff --git a/erpnext/crm/doctype/linkedin_settings/linkedin_settings.py b/erpnext/crm/doctype/linkedin_settings/linkedin_settings.py
deleted file mode 100644
index 64b3a01..0000000
--- a/erpnext/crm/doctype/linkedin_settings/linkedin_settings.py
+++ /dev/null
@@ -1,208 +0,0 @@
-# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-from urllib.parse import urlencode
-
-import frappe
-import requests
-from frappe import _
-from frappe.model.document import Document
-from frappe.utils import get_url_to_form
-from frappe.utils.file_manager import get_file_path
-
-
-class LinkedInSettings(Document):
- @frappe.whitelist()
- def get_authorization_url(self):
- params = urlencode(
- {
- "response_type": "code",
- "client_id": self.consumer_key,
- "redirect_uri": "{0}/api/method/erpnext.crm.doctype.linkedin_settings.linkedin_settings.callback?".format(
- frappe.utils.get_url()
- ),
- "scope": "r_emailaddress w_organization_social r_basicprofile r_liteprofile r_organization_social rw_organization_admin w_member_social",
- }
- )
-
- url = "https://www.linkedin.com/oauth/v2/authorization?{}".format(params)
-
- return url
-
- def get_access_token(self, code):
- url = "https://www.linkedin.com/oauth/v2/accessToken"
- body = {
- "grant_type": "authorization_code",
- "code": code,
- "client_id": self.consumer_key,
- "client_secret": self.get_password(fieldname="consumer_secret"),
- "redirect_uri": "{0}/api/method/erpnext.crm.doctype.linkedin_settings.linkedin_settings.callback?".format(
- frappe.utils.get_url()
- ),
- }
- headers = {"Content-Type": "application/x-www-form-urlencoded"}
-
- response = self.http_post(url=url, data=body, headers=headers)
- response = frappe.parse_json(response.content.decode())
- self.db_set("access_token", response["access_token"])
-
- def get_member_profile(self):
- response = requests.get(url="https://api.linkedin.com/v2/me", headers=self.get_headers())
- response = frappe.parse_json(response.content.decode())
-
- frappe.db.set_value(
- self.doctype,
- self.name,
- {
- "person_urn": response["id"],
- "account_name": response["vanityName"],
- "session_status": "Active",
- },
- )
- frappe.local.response["type"] = "redirect"
- frappe.local.response["location"] = get_url_to_form("LinkedIn Settings", "LinkedIn Settings")
-
- def post(self, text, title, media=None):
- if not media:
- return self.post_text(text, title)
- else:
- media_id = self.upload_image(media)
-
- if media_id:
- return self.post_text(text, title, media_id=media_id)
- else:
- self.log_error("LinkedIn: Failed to upload media")
-
- def upload_image(self, media):
- media = get_file_path(media)
- register_url = "https://api.linkedin.com/v2/assets?action=registerUpload"
- body = {
- "registerUploadRequest": {
- "recipes": ["urn:li:digitalmediaRecipe:feedshare-image"],
- "owner": "urn:li:organization:{0}".format(self.company_id),
- "serviceRelationships": [
- {"relationshipType": "OWNER", "identifier": "urn:li:userGeneratedContent"}
- ],
- }
- }
- headers = self.get_headers()
- response = self.http_post(url=register_url, body=body, headers=headers)
-
- if response.status_code == 200:
- response = response.json()
- asset = response["value"]["asset"]
- upload_url = response["value"]["uploadMechanism"][
- "com.linkedin.digitalmedia.uploading.MediaUploadHttpRequest"
- ]["uploadUrl"]
- headers["Content-Type"] = "image/jpeg"
- response = self.http_post(upload_url, headers=headers, data=open(media, "rb"))
- if response.status_code < 200 and response.status_code > 299:
- frappe.throw(
- _("Error While Uploading Image"),
- title="{0} {1}".format(response.status_code, response.reason),
- )
- return None
- return asset
-
- return None
-
- def post_text(self, text, title, media_id=None):
- url = "https://api.linkedin.com/v2/shares"
- headers = self.get_headers()
- headers["X-Restli-Protocol-Version"] = "2.0.0"
- headers["Content-Type"] = "application/json; charset=UTF-8"
-
- body = {
- "distribution": {"linkedInDistributionTarget": {}},
- "owner": "urn:li:organization:{0}".format(self.company_id),
- "subject": title,
- "text": {"text": text},
- }
-
- reference_url = self.get_reference_url(text)
- if reference_url:
- body["content"] = {"contentEntities": [{"entityLocation": reference_url}]}
-
- if media_id:
- body["content"] = {"contentEntities": [{"entity": media_id}], "shareMediaCategory": "IMAGE"}
-
- response = self.http_post(url=url, headers=headers, body=body)
- return response
-
- def http_post(self, url, headers=None, body=None, data=None):
- try:
- response = requests.post(url=url, json=body, data=data, headers=headers)
- if response.status_code not in [201, 200]:
- raise
-
- except Exception as e:
- self.api_error(response)
-
- return response
-
- def get_headers(self):
- return {"Authorization": "Bearer {}".format(self.access_token)}
-
- def get_reference_url(self, text):
- import re
-
- regex_url = r"http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+"
- urls = re.findall(regex_url, text)
- if urls:
- return urls[0]
-
- def delete_post(self, post_id):
- try:
- response = requests.delete(
- url="https://api.linkedin.com/v2/shares/urn:li:share:{0}".format(post_id),
- headers=self.get_headers(),
- )
- if response.status_code != 200:
- raise
- except Exception:
- self.api_error(response)
-
- def get_post(self, post_id):
- url = "https://api.linkedin.com/v2/organizationalEntityShareStatistics?q=organizationalEntity&organizationalEntity=urn:li:organization:{0}&shares[0]=urn:li:share:{1}".format(
- self.company_id, post_id
- )
-
- try:
- response = requests.get(url=url, headers=self.get_headers())
- if response.status_code != 200:
- raise
-
- except Exception:
- self.api_error(response)
-
- response = frappe.parse_json(response.content.decode())
- if len(response.elements):
- return response.elements[0]
-
- return None
-
- def api_error(self, response):
- content = frappe.parse_json(response.content.decode())
-
- if response.status_code == 401:
- self.db_set("session_status", "Expired")
- frappe.db.commit()
- frappe.throw(content["message"], title=_("LinkedIn Error - Unauthorized"))
- elif response.status_code == 403:
- frappe.msgprint(_("You didn't have permission to access this API"))
- frappe.throw(content["message"], title=_("LinkedIn Error - Access Denied"))
- else:
- frappe.throw(response.reason, title=response.status_code)
-
-
-@frappe.whitelist(allow_guest=True)
-def callback(code=None, error=None, error_description=None):
- if not error:
- linkedin_settings = frappe.get_doc("LinkedIn Settings")
- linkedin_settings.get_access_token(code)
- linkedin_settings.get_member_profile()
- frappe.db.commit()
- else:
- frappe.local.response["type"] = "redirect"
- frappe.local.response["location"] = get_url_to_form("LinkedIn Settings", "LinkedIn Settings")
diff --git a/erpnext/crm/doctype/linkedin_settings/test_linkedin_settings.py b/erpnext/crm/doctype/linkedin_settings/test_linkedin_settings.py
deleted file mode 100644
index 09732e4..0000000
--- a/erpnext/crm/doctype/linkedin_settings/test_linkedin_settings.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-# import frappe
-import unittest
-
-
-class TestLinkedInSettings(unittest.TestCase):
- pass
diff --git a/erpnext/crm/doctype/social_media_post/__init__.py b/erpnext/crm/doctype/social_media_post/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/erpnext/crm/doctype/social_media_post/__init__.py
+++ /dev/null
diff --git a/erpnext/crm/doctype/social_media_post/social_media_post.js b/erpnext/crm/doctype/social_media_post/social_media_post.js
deleted file mode 100644
index 71d044c..0000000
--- a/erpnext/crm/doctype/social_media_post/social_media_post.js
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
-// For license information, please see license.txt
-frappe.ui.form.on('Social Media Post', {
- validate: function(frm) {
- if (frm.doc.linkedin === 0) {
- frappe.throw(__("Select atleast one Social Media Platform to Share on."));
- }
- if (frm.doc.scheduled_time) {
- let scheduled_time = new Date(frm.doc.scheduled_time);
- let date_time = new Date();
- if (scheduled_time.getTime() < date_time.getTime()) {
- frappe.throw(__("Scheduled Time must be a future time."));
- }
- }
- frm.trigger('validate_tweet_length');
- },
-
- text: function(frm) {
- if (frm.doc.text) {
- frm.set_df_property('text', 'description', `${frm.doc.text.length}/280`);
- frm.refresh_field('text');
- frm.trigger('validate_tweet_length');
- }
- },
-
- validate_tweet_length: function(frm) {
- if (frm.doc.text && frm.doc.text.length > 280) {
- frappe.throw(__("Tweet length Must be less than 280."));
- }
- },
-
- onload: function(frm) {
- frm.trigger('make_dashboard');
- },
-
- make_dashboard: function(frm) {
- if (frm.doc.post_status == "Posted") {
- frappe.call({
- doc: frm.doc,
- method: 'get_post',
- freeze: true,
- callback: (r) => {
- if (!r.message) {
- return;
- }
-
- let datasets = [], colors = [];
- if (r.message && r.message.linkedin) {
- colors.push('#0077b5');
- datasets.push({
- name: 'LinkedIn',
- values: [r.message.linkedin.totalShareStatistics.likeCount, r.message.linkedin.totalShareStatistics.shareCount]
- });
- }
-
- if (datasets.length) {
- frm.dashboard.render_graph({
- data: {
- labels: ['Likes', 'Retweets/Shares'],
- datasets: datasets
- },
-
- title: __("Post Metrics"),
- type: 'bar',
- height: 300,
- colors: colors
- });
- }
- }
- });
- }
- },
-
- refresh: function(frm) {
- frm.trigger('text');
-
- if (frm.doc.docstatus === 1) {
- if (!['Posted', 'Deleted'].includes(frm.doc.post_status)) {
- frm.trigger('add_post_btn');
- }
- if (frm.doc.post_status !='Deleted') {
- frm.add_custom_button(__('Delete Post'), function() {
- frappe.confirm(__('Are you sure want to delete the Post from Social Media platforms?'),
- function() {
- frappe.call({
- doc: frm.doc,
- method: 'delete_post',
- freeze: true,
- callback: () => {
- frm.reload_doc();
- }
- });
- }
- );
- });
- }
-
- if (frm.doc.post_status !='Deleted') {
- let html='';
- if (frm.doc.linkedin) {
- let color = frm.doc.linkedin_post_id ? "green" : "red";
- let status = frm.doc.linkedin_post_id ? "Posted" : "Not Posted";
- html += `<div class="col-xs-6">
- <span class="indicator whitespace-nowrap ${color}"><span>LinkedIn : ${status} </span></span>
- </div>` ;
- }
- html = `<div class="row">${html}</div>`;
- frm.dashboard.set_headline_alert(html);
- }
- }
- },
-
- add_post_btn: function(frm) {
- frm.add_custom_button(__('Post Now'), function() {
- frappe.call({
- doc: frm.doc,
- method: 'post',
- freeze: true,
- callback: function() {
- frm.reload_doc();
- }
- });
- });
- }
-});
diff --git a/erpnext/crm/doctype/social_media_post/social_media_post.json b/erpnext/crm/doctype/social_media_post/social_media_post.json
deleted file mode 100644
index 1e3e01c..0000000
--- a/erpnext/crm/doctype/social_media_post/social_media_post.json
+++ /dev/null
@@ -1,169 +0,0 @@
-{
- "actions": [],
- "autoname": "format: CRM-SMP-{YYYY}-{MM}-{DD}-{###}",
- "creation": "2020-01-30 11:53:13.872864",
- "doctype": "DocType",
- "documentation": "https://docs.erpnext.com/docs/user/manual/en/CRM/social-media-post",
- "editable_grid": 1,
- "engine": "InnoDB",
- "field_order": [
- "title",
- "campaign_name",
- "scheduled_time",
- "post_status",
- "column_break_6",
- "linkedin",
- "linkedin_post_id",
- "linkedin_section",
- "linkedin_post",
- "column_break_15",
- "attachments_section",
- "image",
- "amended_from"
- ],
- "fields": [
- {
- "fieldname": "image",
- "fieldtype": "Attach Image",
- "label": "Image"
- },
- {
- "default": "1",
- "fieldname": "linkedin",
- "fieldtype": "Check",
- "label": "LinkedIn"
- },
- {
- "fieldname": "amended_from",
- "fieldtype": "Link",
- "label": "Amended From",
- "no_copy": 1,
- "options": "Social Media Post",
- "print_hide": 1,
- "read_only": 1
- },
- {
- "allow_on_submit": 1,
- "fieldname": "post_status",
- "fieldtype": "Select",
- "label": "Post Status",
- "no_copy": 1,
- "options": "\nScheduled\nPosted\nCancelled\nDeleted\nError",
- "read_only": 1
- },
- {
- "allow_on_submit": 1,
- "fieldname": "linkedin_post_id",
- "fieldtype": "Data",
- "hidden": 1,
- "label": "LinkedIn Post Id",
- "no_copy": 1,
- "read_only": 1
- },
- {
- "fieldname": "campaign_name",
- "fieldtype": "Link",
- "in_list_view": 1,
- "label": "Campaign",
- "options": "Campaign"
- },
- {
- "fieldname": "column_break_6",
- "fieldtype": "Column Break",
- "label": "Share On"
- },
- {
- "collapsible": 1,
- "depends_on": "eval:doc.linkedin==1",
- "fieldname": "linkedin_section",
- "fieldtype": "Section Break",
- "label": "LinkedIn"
- },
- {
- "collapsible": 1,
- "fieldname": "attachments_section",
- "fieldtype": "Section Break",
- "label": "Attachments"
- },
- {
- "fieldname": "linkedin_post",
- "fieldtype": "Text",
- "label": "Post",
- "mandatory_depends_on": "eval:doc.linkedin ==1"
- },
- {
- "fieldname": "column_break_15",
- "fieldtype": "Column Break"
- },
- {
- "allow_on_submit": 1,
- "fieldname": "scheduled_time",
- "fieldtype": "Datetime",
- "label": "Scheduled Time",
- "read_only_depends_on": "eval:doc.post_status == \"Posted\""
- },
- {
- "fieldname": "title",
- "fieldtype": "Data",
- "label": "Title",
- "reqd": 1
- }
- ],
- "is_submittable": 1,
- "links": [],
- "modified": "2023-09-14 11:24:29.105683",
- "modified_by": "Administrator",
- "module": "CRM",
- "name": "Social Media Post",
- "naming_rule": "Expression",
- "owner": "Administrator",
- "permissions": [
- {
- "cancel": 1,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "System Manager",
- "share": 1,
- "submit": 1,
- "write": 1
- },
- {
- "cancel": 1,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Sales User",
- "share": 1,
- "submit": 1,
- "write": 1
- },
- {
- "cancel": 1,
- "create": 1,
- "delete": 1,
- "email": 1,
- "export": 1,
- "print": 1,
- "read": 1,
- "report": 1,
- "role": "Sales Manager",
- "share": 1,
- "submit": 1,
- "write": 1
- }
- ],
- "sort_field": "modified",
- "sort_order": "DESC",
- "states": [],
- "title_field": "title",
- "track_changes": 1
-}
\ No newline at end of file
diff --git a/erpnext/crm/doctype/social_media_post/social_media_post.py b/erpnext/crm/doctype/social_media_post/social_media_post.py
deleted file mode 100644
index 9615a83..0000000
--- a/erpnext/crm/doctype/social_media_post/social_media_post.py
+++ /dev/null
@@ -1,77 +0,0 @@
-# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
-# For license information, please see license.txt
-
-
-import datetime
-
-import frappe
-from frappe import _
-from frappe.model.document import Document
-
-
-class SocialMediaPost(Document):
- def validate(self):
- if not self.linkedin:
- frappe.throw(_("Select atleast one Social Media Platform to Share on."))
-
- if self.scheduled_time:
- current_time = frappe.utils.now_datetime()
- scheduled_time = frappe.utils.get_datetime(self.scheduled_time)
- if scheduled_time < current_time:
- frappe.throw(_("Scheduled Time must be a future time."))
-
- if self.text and len(self.text) > 280:
- frappe.throw(_("Tweet length must be less than 280."))
-
- def submit(self):
- if self.scheduled_time:
- self.post_status = "Scheduled"
- super(SocialMediaPost, self).submit()
-
- def on_cancel(self):
- self.db_set("post_status", "Cancelled")
-
- @frappe.whitelist()
- def delete_post(self):
- if self.linkedin and self.linkedin_post_id:
- linkedin = frappe.get_doc("LinkedIn Settings")
- linkedin.delete_post(self.linkedin_post_id)
-
- self.db_set("post_status", "Deleted")
-
- @frappe.whitelist()
- def get_post(self):
- response = {}
- if self.linkedin and self.linkedin_post_id:
- linkedin = frappe.get_doc("LinkedIn Settings")
- response["linkedin"] = linkedin.get_post(self.linkedin_post_id)
- return response
-
- @frappe.whitelist()
- def post(self):
- try:
- if self.linkedin and not self.linkedin_post_id:
- linkedin = frappe.get_doc("LinkedIn Settings")
- linkedin_post = linkedin.post(self.linkedin_post, self.title, self.image)
- self.db_set("linkedin_post_id", linkedin_post.headers["X-RestLi-Id"])
- self.db_set("post_status", "Posted")
-
- except Exception:
- self.db_set("post_status", "Error")
- self.log_error("Social posting failed")
-
-
-def process_scheduled_social_media_posts():
- posts = frappe.get_all(
- "Social Media Post",
- filters={"post_status": "Scheduled", "docstatus": 1},
- fields=["name", "scheduled_time"],
- )
- start = frappe.utils.now_datetime()
- end = start + datetime.timedelta(minutes=10)
- for post in posts:
- if post.scheduled_time:
- post_time = frappe.utils.get_datetime(post.scheduled_time)
- if post_time > start and post_time <= end:
- sm_post = frappe.get_doc("Social Media Post", post.name)
- sm_post.post()
diff --git a/erpnext/crm/doctype/social_media_post/social_media_post_list.js b/erpnext/crm/doctype/social_media_post/social_media_post_list.js
deleted file mode 100644
index a8c8272..0000000
--- a/erpnext/crm/doctype/social_media_post/social_media_post_list.js
+++ /dev/null
@@ -1,11 +0,0 @@
-frappe.listview_settings['Social Media Post'] = {
- add_fields: ["status", "post_status"],
- get_indicator: function(doc) {
- return [__(doc.post_status), {
- "Scheduled": "orange",
- "Posted": "green",
- "Error": "red",
- "Deleted": "red"
- }[doc.post_status]];
- }
-}
diff --git a/erpnext/crm/doctype/social_media_post/test_social_media_post.py b/erpnext/crm/doctype/social_media_post/test_social_media_post.py
deleted file mode 100644
index 7574476..0000000
--- a/erpnext/crm/doctype/social_media_post/test_social_media_post.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
-# See license.txt
-
-# import frappe
-import unittest
-
-
-class TestSocialMediaPost(unittest.TestCase):
- pass
diff --git a/erpnext/crm/workspace/crm/crm.json b/erpnext/crm/workspace/crm/crm.json
index b107df7..4b5b9af 100644
--- a/erpnext/crm/workspace/crm/crm.json
+++ b/erpnext/crm/workspace/crm/crm.json
@@ -125,131 +125,6 @@
{
"hidden": 0,
"is_query_report": 0,
- "label": "Campaign",
- "link_count": 0,
- "onboard": 0,
- "type": "Card Break"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "Campaign",
- "link_count": 0,
- "link_to": "Campaign",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "Email Campaign",
- "link_count": 0,
- "link_to": "Email Campaign",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "Social Media Post",
- "link_count": 0,
- "link_to": "Social Media Post",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "SMS Center",
- "link_count": 0,
- "link_to": "SMS Center",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "SMS Log",
- "link_count": 0,
- "link_to": "SMS Log",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "Email Group",
- "link_count": 0,
- "link_to": "Email Group",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Settings",
- "link_count": 0,
- "onboard": 0,
- "type": "Card Break"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "CRM Settings",
- "link_count": 0,
- "link_to": "CRM Settings",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "SMS Settings",
- "link_count": 0,
- "link_to": "SMS Settings",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "Twitter Settings",
- "link_count": 0,
- "link_to": "Twitter Settings",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "dependencies": "",
- "hidden": 0,
- "is_query_report": 0,
- "label": "LinkedIn Settings",
- "link_count": 0,
- "link_to": "LinkedIn Settings",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
"label": "Maintenance",
"link_count": 0,
"onboard": 0,
@@ -450,9 +325,101 @@
"link_type": "DocType",
"onboard": 0,
"type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Settings",
+ "link_count": 2,
+ "onboard": 0,
+ "type": "Card Break"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "CRM Settings",
+ "link_count": 0,
+ "link_to": "CRM Settings",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "dependencies": "",
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "SMS Settings",
+ "link_count": 0,
+ "link_to": "SMS Settings",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Campaign",
+ "link_count": 5,
+ "onboard": 0,
+ "type": "Card Break"
+ },
+ {
+ "dependencies": "",
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Campaign",
+ "link_count": 0,
+ "link_to": "Campaign",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "dependencies": "",
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Email Campaign",
+ "link_count": 0,
+ "link_to": "Email Campaign",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "dependencies": "",
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "SMS Center",
+ "link_count": 0,
+ "link_to": "SMS Center",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "dependencies": "",
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "SMS Log",
+ "link_count": 0,
+ "link_to": "SMS Log",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "dependencies": "",
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Email Group",
+ "link_count": 0,
+ "link_to": "Email Group",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
}
],
- "modified": "2023-05-26 16:49:04.298122",
+ "modified": "2023-09-14 12:11:03.968048",
"modified_by": "Administrator",
"module": "CRM",
"name": "CRM",
@@ -463,7 +430,7 @@
"quick_lists": [],
"restrict_to_domain": "",
"roles": [],
- "sequence_id": 10.0,
+ "sequence_id": 17.0,
"shortcuts": [
{
"color": "Blue",
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 41db6b3..c7398cc 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -423,9 +423,6 @@
"erpnext.stock.reorder_item.reorder_item",
],
},
- "all": [
- "erpnext.crm.doctype.social_media_post.social_media_post.process_scheduled_social_media_posts",
- ],
"hourly": [
"erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.automatic_synchronization",
"erpnext.projects.doctype.project.project.project_status_update_reminder",
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 22c3715..7a07f56 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -340,6 +340,8 @@
erpnext.patches.v14_0.single_to_multi_dunning
execute:frappe.db.set_single_value('Selling Settings', 'allow_negative_rates_for_items', 0)
execute:frappe.delete_doc('DocType', 'Twitter Settings', ignore_missing=True)
+execute:frappe.delete_doc('DocType', 'LinkedIn Settings', ignore_missing=True)
+execute:frappe.delete_doc('DocType', 'Social Media Post', ignore_missing=True)
erpnext.patches.v15_0.correct_asset_value_if_je_with_workflow
erpnext.patches.v15_0.delete_woocommerce_settings_doctype
# below migration patch should always run last