Skip to content

Commit

Permalink
Merge pull request #235 from frappe/develop
Browse files Browse the repository at this point in the history
chore: Merge develop to main
  • Loading branch information
shariquerik authored Jul 1, 2024
2 parents aac89ac + 64b8766 commit 4bdc1b2
Show file tree
Hide file tree
Showing 23 changed files with 1,933 additions and 226 deletions.
264 changes: 211 additions & 53 deletions crm/api/doc.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from frappe.model.document import get_controller
from frappe.model import no_value_fields
from pypika import Criterion
from frappe.utils import make_filter_tuple

from crm.api.views import get_views
from crm.fcrm.doctype.crm_form_script.crm_form_script import get_form_script
Expand Down Expand Up @@ -200,19 +201,27 @@ def get_quick_filters(doctype: str):
return quick_filters

@frappe.whitelist()
def get_list_data(
def get_data(
doctype: str,
filters: dict,
order_by: str,
page_length=20,
page_length_count=20,
columns=None,
rows=None,
column_field=None,
title_field=None,
columns=[],
rows=[],
kanban_columns=[],
kanban_fields=[],
view=None,
default_filters=None,
):
custom_view = False
filters = frappe._dict(filters)
rows = frappe.parse_json(rows or "[]")
columns = frappe.parse_json(columns or "[]")
kanban_fields = frappe.parse_json(kanban_fields or "[]")
kanban_columns = frappe.parse_json(kanban_columns or "[]")

custom_view_name = view.get('custom_view_name') if view else None
view_type = view.get('view_type') if view else None
Expand All @@ -235,61 +244,133 @@ def get_list_data(
filters.update(default_filters)

is_default = True
if columns or rows:
custom_view = True
is_default = False
columns = frappe.parse_json(columns)
rows = frappe.parse_json(rows)

if not columns:
columns = [
{"label": "Name", "type": "Data", "key": "name", "width": "16rem"},
{"label": "Last Modified", "type": "Datetime", "key": "modified", "width": "8rem"},
]

if not rows:
rows = ["name"]

default_view_filters = {
"dt": doctype,
"type": view_type or 'list',
"is_default": 1,
"user": frappe.session.user,
}

data = []
_list = get_controller(doctype)

if not custom_view and frappe.db.exists("CRM View Settings", default_view_filters):
list_view_settings = frappe.get_doc("CRM View Settings", default_view_filters)
columns = frappe.parse_json(list_view_settings.columns)
rows = frappe.parse_json(list_view_settings.rows)
is_default = False
elif not custom_view or is_default and hasattr(_list, "default_list_data"):
columns = _list.default_list_data().get("columns")

if hasattr(_list, "default_list_data"):
rows = _list.default_list_data().get("rows")

# check if rows has all keys from columns if not add them
for column in columns:
if column.get("key") not in rows:
rows.append(column.get("key"))
column["label"] = _(column.get("label"))
if view_type != "kanban":
if columns or rows:
custom_view = True
is_default = False
columns = frappe.parse_json(columns)
rows = frappe.parse_json(rows)

if not columns:
columns = [
{"label": "Name", "type": "Data", "key": "name", "width": "16rem"},
{"label": "Last Modified", "type": "Datetime", "key": "modified", "width": "8rem"},
]

if not rows:
rows = ["name"]

default_view_filters = {
"dt": doctype,
"type": view_type or 'list',
"is_default": 1,
"user": frappe.session.user,
}

if column.get("key") == "_liked_by" and column.get("width") == "10rem":
column["width"] = "50px"
if not custom_view and frappe.db.exists("CRM View Settings", default_view_filters):
list_view_settings = frappe.get_doc("CRM View Settings", default_view_filters)
columns = frappe.parse_json(list_view_settings.columns)
rows = frappe.parse_json(list_view_settings.rows)
is_default = False
elif not custom_view or is_default and hasattr(_list, "default_list_data"):
columns = _list.default_list_data().get("columns")

# check if rows has all keys from columns if not add them
for column in columns:
if column.get("key") not in rows:
rows.append(column.get("key"))
column["label"] = _(column.get("label"))

if column.get("key") == "_liked_by" and column.get("width") == "10rem":
column["width"] = "50px"

# check if rows has group_by_field if not add it
if group_by_field and group_by_field not in rows:
rows.append(group_by_field)

data = frappe.get_list(
doctype,
fields=rows,
filters=filters,
order_by=order_by,
page_length=page_length,
) or []

if view_type == "kanban":
if not kanban_columns and column_field:
field_meta = frappe.get_meta(doctype).get_field(column_field)
if field_meta.fieldtype == "Link":
kanban_columns = frappe.get_all(
field_meta.options,
fields=["name"],
order_by="modified asc",
)
elif field_meta.fieldtype == "Select":
kanban_columns = [{"name": option} for option in field_meta.options.split("\n")]

if not title_field:
title_field = "name"
if hasattr(_list, "default_kanban_settings"):
title_field = _list.default_kanban_settings().get("title_field")

if title_field not in rows:
rows.append(title_field)

if not kanban_fields:
kanban_fields = ["name"]
if hasattr(_list, "default_kanban_settings"):
kanban_fields = json.loads(_list.default_kanban_settings().get("kanban_fields"))

for field in kanban_fields:
if field not in rows:
rows.append(field)

for kc in kanban_columns:
column_filters = { column_field: kc.get('name') }
if column_field in filters and filters.get(column_field) != kc.name:
column_data = []
else:
column_filters.update(filters.copy())
page_length = 20

# check if rows has group_by_field if not add it
if group_by_field and group_by_field not in rows:
rows.append(group_by_field)
if kc.get("page_length"):
page_length = kc.get("page_length")

data = frappe.get_list(
doctype,
fields=rows,
filters=filters,
order_by=order_by,
page_length=page_length,
) or []
order = kc.get("order")
if order:
column_data = get_records_based_on_order(doctype, rows, column_filters, page_length, order)
else:
column_data = frappe.get_list(
doctype,
fields=rows,
filters=convert_filter_to_tuple(doctype, column_filters),
order_by=order_by,
page_length=page_length,
)

new_filters = filters.copy()
new_filters.update({ column_field: kc.get('name') })

all_count = len(frappe.get_list(doctype, filters=convert_filter_to_tuple(doctype, new_filters)))

kc["all_count"] = all_count
kc["count"] = len(column_data)

for d in column_data:
getCounts(d, doctype)

if order:
column_data = sorted(
column_data, key=lambda x: order.index(x.get("name"))
if x.get("name") in order else len(order)
)

data.append({"column": kc, "fields": kanban_fields, "data": column_data})

fields = frappe.get_meta(doctype).fields
fields = [field for field in fields if field.fieldtype not in no_value_fields]
Expand Down Expand Up @@ -365,6 +446,10 @@ def get_options(type, options):
"columns": columns,
"rows": rows,
"fields": fields,
"column_field": column_field,
"title_field": title_field,
"kanban_columns": kanban_columns,
"kanban_fields": kanban_fields,
"group_by_field": group_by_field,
"page_length": page_length,
"page_length_count": page_length_count,
Expand All @@ -374,8 +459,46 @@ def get_options(type, options):
"row_count": len(data),
"form_script": get_form_script(doctype),
"list_script": get_form_script(doctype, "List"),
"view_type": view_type,
}

def convert_filter_to_tuple(doctype, filters):
if isinstance(filters, dict):
filters_items = filters.items()
filters = []
for key, value in filters_items:
filters.append(make_filter_tuple(doctype, key, value))
return filters


def get_records_based_on_order(doctype, rows, filters, page_length, order):
records = []
filters = convert_filter_to_tuple(doctype, filters)
in_filters = filters.copy()
in_filters.append([doctype, "name", "in", order[:page_length]])
records = frappe.get_list(
doctype,
fields=rows,
filters=in_filters,
order_by="creation desc",
page_length=page_length,
)

if len(records) < page_length:
not_in_filters = filters.copy()
not_in_filters.append([doctype, "name", "not in", order])
remaining_records = frappe.get_list(
doctype,
fields=rows,
filters=not_in_filters,
order_by="creation desc",
page_length=page_length - len(records),
)
for record in remaining_records:
records.append(record)

return records

@frappe.whitelist()
def get_fields_meta(doctype, restricted_fieldtypes=None, as_array=False):
not_allowed_fieldtypes = [
Expand All @@ -391,12 +514,38 @@ def get_fields_meta(doctype, restricted_fieldtypes=None, as_array=False):
fields = frappe.get_meta(doctype).fields
fields = [field for field in fields if field.fieldtype not in not_allowed_fieldtypes]

standard_fields = [
{"fieldname": "name", "fieldtype": "Link", "label": "ID", "options": doctype},
{
"fieldname": "owner",
"fieldtype": "Link",
"label": "Created By",
"options": "User"
},
{
"fieldname": "modified_by",
"fieldtype": "Link",
"label": "Last Updated By",
"options": "User",
},
{"fieldname": "_user_tags", "fieldtype": "Data", "label": "Tags"},
{"fieldname": "_liked_by", "fieldtype": "Data", "label": "Like"},
{"fieldname": "_comments", "fieldtype": "Text", "label": "Comments"},
{"fieldname": "_assign", "fieldtype": "Text", "label": "Assigned To"},
{"fieldname": "creation", "fieldtype": "Datetime", "label": "Created On"},
{"fieldname": "modified", "fieldtype": "Datetime", "label": "Last Updated On"},
]

for field in standard_fields:
if not restricted_fieldtypes or field.get('fieldtype') not in restricted_fieldtypes:
fields.append(field)

if as_array:
return fields

fields_meta = {}
for field in fields:
fields_meta[field.fieldname] = field
fields_meta[field.get('fieldname')] = field

return fields_meta

Expand Down Expand Up @@ -531,4 +680,13 @@ def get_fields(doctype: str, allow_all_fieldtypes: bool = False):
"mandatory": field.reqd,
})

return _fields
return _fields


def getCounts(d, doctype):
d["_email_count"] = frappe.db.count("Communication", filters={"reference_doctype": doctype, "reference_name": d.get("name"), "communication_type": "Communication"}) or 0
d["_email_count"] = d["_email_count"] + frappe.db.count("Communication", filters={"reference_doctype": doctype, "reference_name": d.get("name"), "communication_type": "Automated Message"})
d["_comment_count"] = frappe.db.count("Comment", filters={"reference_doctype": doctype, "reference_name": d.get("name"), "comment_type": "Comment"})
d["_task_count"] = frappe.db.count("CRM Task", filters={"reference_doctype": doctype, "reference_docname": d.get("name")})
d["_note_count"] = frappe.db.count("FCRM Note", filters={"reference_doctype": doctype, "reference_docname": d.get("name")})
return d
8 changes: 8 additions & 0 deletions crm/fcrm/doctype/crm_deal/crm_deal.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,14 @@ def default_list_data():
]
return {'columns': columns, 'rows': rows}

@staticmethod
def default_kanban_settings():
return {
"column_field": "status",
"title_field": "organization",
"kanban_fields": '["annual_revenue", "email", "mobile_no", "_assign", "modified"]'
}

@frappe.whitelist()
def add_contact(deal, contact):
if not frappe.has_permission("CRM Deal", "write", deal):
Expand Down
9 changes: 9 additions & 0 deletions crm/fcrm/doctype/crm_lead/crm_lead.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,15 @@ def default_list_data():
]
return {'columns': columns, 'rows': rows}

@staticmethod
def default_kanban_settings():
return {
"column_field": "status",
"title_field": "lead_name",
"kanban_fields": '["organization", "email", "mobile_no", "_assign", "modified"]'
}


@frappe.whitelist()
def convert_to_deal(lead, doc=None):
if not (doc and doc.flags.get("ignore_permissions")) and not frappe.has_permission("CRM Lead", "write", lead):
Expand Down
8 changes: 8 additions & 0 deletions crm/fcrm/doctype/crm_task/crm_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,11 @@ def default_list_data():
"modified",
]
return {'columns': columns, 'rows': rows}

@staticmethod
def default_kanban_settings():
return {
"column_field": "status",
"title_field": "title",
"kanban_fields": '["description", "priority", "creation"]'
}
Loading

0 comments on commit 4bdc1b2

Please sign in to comment.