Merge branch 'develop' into supplier-quotn-comparison
This commit is contained in:
commit
dd10c54baa
@ -165,9 +165,14 @@ def tax_account_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
AND company = %(company)s
|
||||
AND account_currency = %(currency)s
|
||||
AND `{searchfield}` LIKE %(txt)s
|
||||
{mcond}
|
||||
ORDER BY idx DESC, name
|
||||
LIMIT %(offset)s, %(limit)s
|
||||
""".format(account_type_condition=account_type_condition, searchfield=searchfield),
|
||||
""".format(
|
||||
account_type_condition=account_type_condition,
|
||||
searchfield=searchfield,
|
||||
mcond=get_match_cond(doctype)
|
||||
),
|
||||
dict(
|
||||
account_types=filters.get("account_type"),
|
||||
company=filters.get("company"),
|
||||
@ -359,9 +364,21 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
|
||||
if filters.get("is_return"):
|
||||
having_clause = ""
|
||||
|
||||
meta = frappe.get_meta("Batch", cached=True)
|
||||
searchfields = meta.get_search_fields()
|
||||
|
||||
search_columns = ''
|
||||
if searchfields:
|
||||
search_columns = ", " + ", ".join(searchfields)
|
||||
|
||||
if args.get('warehouse'):
|
||||
searchfields = ['batch.' + field for field in searchfields]
|
||||
if searchfields:
|
||||
search_columns = ", " + ", ".join(searchfields)
|
||||
|
||||
batch_nos = frappe.db.sql("""select sle.batch_no, round(sum(sle.actual_qty),2), sle.stock_uom,
|
||||
concat('MFG-',batch.manufacturing_date), concat('EXP-',batch.expiry_date)
|
||||
{search_columns}
|
||||
from `tabStock Ledger Entry` sle
|
||||
INNER JOIN `tabBatch` batch on sle.batch_no = batch.name
|
||||
where
|
||||
@ -377,6 +394,7 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
|
||||
group by batch_no {having_clause}
|
||||
order by batch.expiry_date, sle.batch_no desc
|
||||
limit %(start)s, %(page_len)s""".format(
|
||||
search_columns = search_columns,
|
||||
cond=cond,
|
||||
match_conditions=get_match_cond(doctype),
|
||||
having_clause = having_clause
|
||||
@ -384,7 +402,9 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
|
||||
|
||||
return batch_nos
|
||||
else:
|
||||
return frappe.db.sql("""select name, concat('MFG-', manufacturing_date), concat('EXP-',expiry_date) from `tabBatch` batch
|
||||
return frappe.db.sql("""select name, concat('MFG-', manufacturing_date), concat('EXP-',expiry_date)
|
||||
{search_columns}
|
||||
from `tabBatch` batch
|
||||
where batch.disabled = 0
|
||||
and item = %(item_code)s
|
||||
and (name like %(txt)s
|
||||
@ -394,7 +414,7 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
|
||||
{0}
|
||||
{match_conditions}
|
||||
order by expiry_date, name desc
|
||||
limit %(start)s, %(page_len)s""".format(cond, match_conditions=get_match_cond(doctype)), args)
|
||||
limit %(start)s, %(page_len)s""".format(cond, search_columns = search_columns, match_conditions=get_match_cond(doctype)), args)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
|
@ -282,6 +282,11 @@ auto_cancel_exempted_doctypes= [
|
||||
]
|
||||
|
||||
scheduler_events = {
|
||||
"cron": {
|
||||
"0/30 * * * *": [
|
||||
"erpnext.utilities.doctype.video.video.update_youtube_data",
|
||||
]
|
||||
},
|
||||
"all": [
|
||||
"erpnext.projects.doctype.project.project.project_status_update_reminder",
|
||||
"erpnext.healthcare.doctype.patient_appointment.patient_appointment.send_appointment_reminder",
|
||||
|
@ -690,6 +690,7 @@ erpnext.patches.v12_0.set_valid_till_date_in_supplier_quotation
|
||||
erpnext.patches.v13_0.update_old_loans
|
||||
erpnext.patches.v12_0.set_serial_no_status #2020-05-21
|
||||
erpnext.patches.v12_0.update_price_list_currency_in_bom
|
||||
execute:frappe.reload_doctype('Dashboard')
|
||||
execute:frappe.delete_doc_if_exists('Dashboard', 'Accounts')
|
||||
erpnext.patches.v13_0.update_actual_start_and_end_date_in_wo
|
||||
erpnext.patches.v13_0.set_company_field_in_healthcare_doctypes #2020-05-25
|
||||
@ -726,3 +727,4 @@ erpnext.patches.v13_0.drop_razorpay_payload_column
|
||||
erpnext.patches.v13_0.update_start_end_date_for_old_shift_assignment
|
||||
erpnext.patches.v13_0.setting_custom_roles_for_some_regional_reports
|
||||
erpnext.patches.v13_0.change_default_pos_print_format
|
||||
erpnext.patches.v13_0.set_youtube_video_id
|
||||
|
10
erpnext/patches/v13_0/set_youtube_video_id.py
Normal file
10
erpnext/patches/v13_0/set_youtube_video_id.py
Normal file
@ -0,0 +1,10 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from erpnext.utilities.doctype.video.video import get_id_from_url
|
||||
|
||||
def execute():
|
||||
frappe.reload_doc("utilities", "doctype","video")
|
||||
|
||||
for video in frappe.get_all("Video", fields=["name", "url", "youtube_video_id"]):
|
||||
if video.url and not video.youtube_video_id:
|
||||
frappe.db.set_value("Video", video.name, "youtube_video_id", get_id_from_url(video.url))
|
@ -9,13 +9,15 @@ frappe.query_reports["Batch-Wise Balance History"] = {
|
||||
"fieldtype": "Date",
|
||||
"width": "80",
|
||||
"default": frappe.sys_defaults.year_start_date,
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname":"to_date",
|
||||
"label": __("To Date"),
|
||||
"fieldtype": "Date",
|
||||
"width": "80",
|
||||
"default": frappe.datetime.get_today()
|
||||
"default": frappe.datetime.get_today(),
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "item",
|
||||
|
@ -11,6 +11,9 @@ from frappe.utils import cint, flt, getdate
|
||||
def execute(filters=None):
|
||||
if not filters: filters = {}
|
||||
|
||||
if filters.from_date > filters.to_date:
|
||||
frappe.throw(_("From Date must be before To Date"))
|
||||
|
||||
float_precision = cint(frappe.db.get_default("float_precision")) or 3
|
||||
|
||||
columns = get_columns(filters)
|
||||
|
29
erpnext/utilities/desk_page/utilities/utilities.json
Normal file
29
erpnext/utilities/desk_page/utilities/utilities.json
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"cards": [
|
||||
{
|
||||
"hidden": 0,
|
||||
"label": "Video",
|
||||
"links": "[\n {\n \"description\": \"Video\",\n \"label\": \"Video\",\n \"name\": \"Video\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Video settings\",\n \"label\": \"Video Settings\",\n \"name\": \"Video Settings\",\n \"type\": \"doctype\"\n }\n]"
|
||||
}
|
||||
],
|
||||
"category": "Modules",
|
||||
"charts": [],
|
||||
"creation": "2020-09-10 12:21:22.335307",
|
||||
"developer_mode_only": 0,
|
||||
"disable_user_customization": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Desk Page",
|
||||
"extends_another_page": 0,
|
||||
"hide_custom": 0,
|
||||
"idx": 0,
|
||||
"is_standard": 1,
|
||||
"label": "Utilities",
|
||||
"modified": "2020-09-10 12:33:30.089853",
|
||||
"modified_by": "user@erpnext.com",
|
||||
"module": "Utilities",
|
||||
"name": "Utilities",
|
||||
"owner": "user@erpnext.com",
|
||||
"pin_to_bottom": 1,
|
||||
"pin_to_top": 0,
|
||||
"shortcuts": []
|
||||
}
|
@ -2,7 +2,16 @@
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Video', {
|
||||
// refresh: function(frm) {
|
||||
refresh: function (frm) {
|
||||
frm.events.toggle_youtube_statistics_section(frm);
|
||||
frm.add_custom_button("Watch Video", () => frappe.help.show_video(frm.doc.url, frm.doc.title));
|
||||
},
|
||||
|
||||
// }
|
||||
toggle_youtube_statistics_section: (frm) => {
|
||||
if (frm.doc.provider === "YouTube") {
|
||||
frappe.db.get_single_value("Video Settings", "enable_youtube_tracking").then( val => {
|
||||
frm.toggle_display("youtube_tracking_section", val);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -11,11 +11,19 @@
|
||||
"title",
|
||||
"provider",
|
||||
"url",
|
||||
"youtube_video_id",
|
||||
"column_break_4",
|
||||
"publish_date",
|
||||
"duration",
|
||||
"youtube_tracking_section",
|
||||
"like_count",
|
||||
"view_count",
|
||||
"col_break",
|
||||
"dislike_count",
|
||||
"comment_count",
|
||||
"section_break_7",
|
||||
"description"
|
||||
"description",
|
||||
"image"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
@ -37,7 +45,6 @@
|
||||
{
|
||||
"fieldname": "url",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "URL",
|
||||
"reqd": 1
|
||||
},
|
||||
@ -48,11 +55,12 @@
|
||||
{
|
||||
"fieldname": "publish_date",
|
||||
"fieldtype": "Date",
|
||||
"in_list_view": 1,
|
||||
"label": "Publish Date"
|
||||
},
|
||||
{
|
||||
"fieldname": "duration",
|
||||
"fieldtype": "Data",
|
||||
"fieldtype": "Duration",
|
||||
"label": "Duration"
|
||||
},
|
||||
{
|
||||
@ -62,13 +70,67 @@
|
||||
{
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Text Editor",
|
||||
"in_list_view": 1,
|
||||
"label": "Description",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "like_count",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Likes",
|
||||
"no_copy": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "view_count",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Views",
|
||||
"no_copy": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "col_break",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "dislike_count",
|
||||
"fieldtype": "Float",
|
||||
"label": "Dislikes",
|
||||
"no_copy": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "comment_count",
|
||||
"fieldtype": "Float",
|
||||
"label": "Comments",
|
||||
"no_copy": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "image",
|
||||
"fieldtype": "Attach Image",
|
||||
"hidden": 1,
|
||||
"label": "Image",
|
||||
"no_copy": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.provider==\"YouTube\"",
|
||||
"fieldname": "youtube_tracking_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Youtube Statistics"
|
||||
},
|
||||
{
|
||||
"fieldname": "youtube_video_id",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"label": "Youtube ID",
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"image_field": "image",
|
||||
"links": [],
|
||||
"modified": "2020-07-21 19:29:46.603734",
|
||||
"modified": "2020-09-07 17:02:20.185794",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Utilities",
|
||||
"name": "Video",
|
||||
|
@ -3,8 +3,144 @@
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
# import frappe
|
||||
import frappe
|
||||
import re
|
||||
import pytz
|
||||
from frappe.model.document import Document
|
||||
from frappe import _
|
||||
from datetime import datetime
|
||||
from six import string_types
|
||||
from pyyoutube import Api
|
||||
|
||||
class Video(Document):
|
||||
pass
|
||||
def validate(self):
|
||||
if self.provider == "YouTube" and is_tracking_enabled():
|
||||
self.set_video_id()
|
||||
self.set_youtube_statistics()
|
||||
|
||||
def set_video_id(self):
|
||||
if self.url and not self.get("youtube_video_id"):
|
||||
self.youtube_video_id = get_id_from_url(self.url)
|
||||
|
||||
def set_youtube_statistics(self):
|
||||
api_key = frappe.db.get_single_value("Video Settings", "api_key")
|
||||
api = Api(api_key=api_key)
|
||||
|
||||
try:
|
||||
video = api.get_video_by_id(video_id=self.youtube_video_id)
|
||||
video_stats = video.items[0].to_dict().get('statistics')
|
||||
|
||||
self.like_count = video_stats.get('likeCount')
|
||||
self.view_count = video_stats.get('viewCount')
|
||||
self.dislike_count = video_stats.get('dislikeCount')
|
||||
self.comment_count = video_stats.get('commentCount')
|
||||
|
||||
except Exception:
|
||||
title = "Failed to Update YouTube Statistics for Video: {0}".format(self.name)
|
||||
frappe.log_error(title + "\n\n" + frappe.get_traceback(), title=title)
|
||||
|
||||
def is_tracking_enabled():
|
||||
return frappe.db.get_single_value("Video Settings", "enable_youtube_tracking")
|
||||
|
||||
|
||||
def get_frequency(value):
|
||||
# Return numeric value from frequency field, return 1 as fallback default value: 1 hour
|
||||
if value != "Daily":
|
||||
return frappe.utils.cint(value[:2].strip())
|
||||
elif value:
|
||||
return 24
|
||||
return 1
|
||||
|
||||
|
||||
def update_youtube_data():
|
||||
# Called every 30 minutes via hooks
|
||||
enable_youtube_tracking, frequency = frappe.db.get_value("Video Settings", "Video Settings", ["enable_youtube_tracking", "frequency"])
|
||||
|
||||
if not enable_youtube_tracking:
|
||||
return
|
||||
|
||||
frequency = get_frequency(frequency)
|
||||
time = datetime.now()
|
||||
timezone = pytz.timezone(frappe.utils.get_time_zone())
|
||||
site_time = time.astimezone(timezone)
|
||||
|
||||
if frequency == 30:
|
||||
batch_update_youtube_data()
|
||||
elif site_time.hour % frequency == 0 and site_time.minute < 15:
|
||||
# make sure it runs within the first 15 mins of the hour
|
||||
batch_update_youtube_data()
|
||||
|
||||
|
||||
def get_formatted_ids(video_list):
|
||||
# format ids to comma separated string for bulk request
|
||||
ids = []
|
||||
for video in video_list:
|
||||
ids.append(video.youtube_video_id)
|
||||
|
||||
return ','.join(ids)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_id_from_url(url):
|
||||
"""
|
||||
Returns video id from url
|
||||
:param youtube url: String URL
|
||||
"""
|
||||
if not isinstance(url, string_types):
|
||||
frappe.throw(_("URL can only be a string"), title=_("Invalid URL"))
|
||||
|
||||
pattern = re.compile(r'[a-z\:\//\.]+(youtube|youtu)\.(com|be)/(watch\?v=|embed/|.+\?v=)?([^"&?\s]{11})?')
|
||||
id = pattern.match(url)
|
||||
return id.groups()[-1]
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def batch_update_youtube_data():
|
||||
def get_youtube_statistics(video_ids):
|
||||
api_key = frappe.db.get_single_value("Video Settings", "api_key")
|
||||
api = Api(api_key=api_key)
|
||||
try:
|
||||
video = api.get_video_by_id(video_id=video_ids)
|
||||
video_stats = video.items
|
||||
return video_stats
|
||||
except Exception:
|
||||
title = "Failed to Update YouTube Statistics"
|
||||
frappe.log_error(title + "\n\n" + frappe.get_traceback(), title=title)
|
||||
|
||||
def prepare_and_set_data(video_list):
|
||||
video_ids = get_formatted_ids(video_list)
|
||||
stats = get_youtube_statistics(video_ids)
|
||||
set_youtube_data(stats)
|
||||
|
||||
def set_youtube_data(entries):
|
||||
for entry in entries:
|
||||
video_stats = entry.to_dict().get('statistics')
|
||||
video_id = entry.to_dict().get('id')
|
||||
stats = {
|
||||
'like_count' : video_stats.get('likeCount'),
|
||||
'view_count' : video_stats.get('viewCount'),
|
||||
'dislike_count' : video_stats.get('dislikeCount'),
|
||||
'comment_count' : video_stats.get('commentCount'),
|
||||
'video_id': video_id
|
||||
}
|
||||
|
||||
frappe.db.sql("""
|
||||
UPDATE `tabVideo`
|
||||
SET
|
||||
like_count = %(like_count)s,
|
||||
view_count = %(view_count)s,
|
||||
dislike_count = %(dislike_count)s,
|
||||
comment_count = %(comment_count)s
|
||||
WHERE youtube_video_id = %(video_id)s""", stats)
|
||||
|
||||
video_list = frappe.get_all("Video", fields=["youtube_video_id"])
|
||||
if len(video_list) > 50:
|
||||
# Update in batches of 50
|
||||
start, end = 0, 50
|
||||
while start < len(video_list):
|
||||
batch = video_list[start:end]
|
||||
prepare_and_set_data(batch)
|
||||
start += 50
|
||||
end += 50
|
||||
else:
|
||||
prepare_and_set_data(video_list)
|
||||
|
7
erpnext/utilities/doctype/video/video_list.js
Normal file
7
erpnext/utilities/doctype/video/video_list.js
Normal file
@ -0,0 +1,7 @@
|
||||
frappe.listview_settings["Video"] = {
|
||||
onload: (listview) => {
|
||||
listview.page.add_menu_item(__("Video Settings"), function() {
|
||||
frappe.set_route("Form","Video Settings", "Video Settings");
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
# import frappe
|
||||
import unittest
|
||||
|
||||
class TestVideoSettings(unittest.TestCase):
|
||||
pass
|
@ -0,0 +1,8 @@
|
||||
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Video Settings', {
|
||||
// refresh: function(frm) {
|
||||
|
||||
// }
|
||||
});
|
60
erpnext/utilities/doctype/video_settings/video_settings.json
Normal file
60
erpnext/utilities/doctype/video_settings/video_settings.json
Normal file
@ -0,0 +1,60 @@
|
||||
{
|
||||
"actions": [],
|
||||
"creation": "2020-08-02 03:50:21.339609",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"enable_youtube_tracking",
|
||||
"api_key",
|
||||
"frequency"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "enable_youtube_tracking",
|
||||
"fieldtype": "Check",
|
||||
"label": "Enable YouTube Tracking"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.enable_youtube_tracking",
|
||||
"fieldname": "api_key",
|
||||
"fieldtype": "Data",
|
||||
"label": "API Key",
|
||||
"mandatory_depends_on": "eval:doc.enable_youtube_tracking"
|
||||
},
|
||||
{
|
||||
"default": "1 hr",
|
||||
"depends_on": "eval:doc.enable_youtube_tracking",
|
||||
"fieldname": "frequency",
|
||||
"fieldtype": "Select",
|
||||
"label": "Frequency",
|
||||
"mandatory_depends_on": "eval:doc.enable_youtube_tracking",
|
||||
"options": "30 mins\n1 hr\n6 hrs\nDaily"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2020-09-07 16:09:00.360668",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Utilities",
|
||||
"name": "Video 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
|
||||
}
|
22
erpnext/utilities/doctype/video_settings/video_settings.py
Normal file
22
erpnext/utilities/doctype/video_settings/video_settings.py
Normal file
@ -0,0 +1,22 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from apiclient.discovery import build
|
||||
|
||||
class VideoSettings(Document):
|
||||
def validate(self):
|
||||
self.validate_youtube_api_key()
|
||||
|
||||
def validate_youtube_api_key(self):
|
||||
if self.enable_youtube_tracking and self.api_key:
|
||||
try:
|
||||
build("youtube", "v3", developerKey=self.api_key)
|
||||
except Exception:
|
||||
title = _("Failed to Authenticate the API key.")
|
||||
frappe.log_error(title + "\n\n" + frappe.get_traceback(), title=title)
|
||||
frappe.throw(title + " Please check the error logs.", title=_("Invalid Credentials"))
|
0
erpnext/utilities/report/__init__.py
Normal file
0
erpnext/utilities/report/__init__.py
Normal file
@ -0,0 +1,20 @@
|
||||
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
/* eslint-disable */
|
||||
|
||||
frappe.query_reports["YouTube Interactions"] = {
|
||||
"filters": [
|
||||
{
|
||||
fieldname: "from_date",
|
||||
label: __("From Date"),
|
||||
fieldtype: "Date",
|
||||
default: frappe.datetime.add_months(frappe.datetime.now_date(), -12),
|
||||
},
|
||||
{
|
||||
fieldname:"to_date",
|
||||
label: __("To Date"),
|
||||
fieldtype: "Date",
|
||||
default: frappe.datetime.now_date(),
|
||||
}
|
||||
]
|
||||
};
|
@ -0,0 +1,27 @@
|
||||
{
|
||||
"add_total_row": 0,
|
||||
"creation": "2020-08-02 05:05:00.457093",
|
||||
"disable_prepared_report": 0,
|
||||
"disabled": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"idx": 0,
|
||||
"is_standard": "Yes",
|
||||
"modified": "2020-08-02 05:05:00.457093",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Utilities",
|
||||
"name": "YouTube Interactions",
|
||||
"owner": "Administrator",
|
||||
"prepared_report": 0,
|
||||
"ref_doctype": "Video",
|
||||
"report_name": "YouTube Interactions",
|
||||
"report_type": "Script Report",
|
||||
"roles": [
|
||||
{
|
||||
"role": "All"
|
||||
},
|
||||
{
|
||||
"role": "System Manager"
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import flt
|
||||
|
||||
def execute(filters=None):
|
||||
if not frappe.db.get_single_value("Video Settings", "enable_youtube_tracking") or not filters:
|
||||
return [], []
|
||||
|
||||
columns = get_columns()
|
||||
data = get_data(filters)
|
||||
chart_data, summary = get_chart_summary_data(data)
|
||||
return columns, data, None, chart_data, summary
|
||||
|
||||
def get_columns():
|
||||
return [
|
||||
{
|
||||
"label": _("Published Date"),
|
||||
"fieldname": "publish_date",
|
||||
"fieldtype": "Date",
|
||||
"width": 100
|
||||
},
|
||||
{
|
||||
"label": _("Title"),
|
||||
"fieldname": "title",
|
||||
"fieldtype": "Data",
|
||||
"width": 200
|
||||
},
|
||||
{
|
||||
"label": _("Duration"),
|
||||
"fieldname": "duration",
|
||||
"fieldtype": "Duration",
|
||||
"width": 100
|
||||
},
|
||||
{
|
||||
"label": _("Views"),
|
||||
"fieldname": "view_count",
|
||||
"fieldtype": "Float",
|
||||
"width": 200
|
||||
},
|
||||
{
|
||||
"label": _("Likes"),
|
||||
"fieldname": "like_count",
|
||||
"fieldtype": "Float",
|
||||
"width": 200
|
||||
},
|
||||
{
|
||||
"label": _("Dislikes"),
|
||||
"fieldname": "dislike_count",
|
||||
"fieldtype": "Float",
|
||||
"width": 100
|
||||
},
|
||||
{
|
||||
"label": _("Comments"),
|
||||
"fieldname": "comment_count",
|
||||
"fieldtype": "Float",
|
||||
"width": 100
|
||||
}
|
||||
]
|
||||
|
||||
def get_data(filters):
|
||||
return frappe.db.sql("""
|
||||
SELECT
|
||||
publish_date, title, provider, duration,
|
||||
view_count, like_count, dislike_count, comment_count
|
||||
FROM `tabVideo`
|
||||
WHERE view_count is not null
|
||||
and publish_date between %(from_date)s and %(to_date)s
|
||||
ORDER BY view_count desc""", filters, as_dict=1)
|
||||
|
||||
def get_chart_summary_data(data):
|
||||
labels, likes, views = [], [], []
|
||||
total_views = 0
|
||||
|
||||
for row in data:
|
||||
labels.append(row.get('title'))
|
||||
likes.append(row.get('like_count'))
|
||||
views.append(row.get('view_count'))
|
||||
total_views += flt(row.get('view_count'))
|
||||
|
||||
|
||||
chart_data = {
|
||||
"data" : {
|
||||
"labels" : labels,
|
||||
"datasets" : [
|
||||
{
|
||||
"name" : "Likes",
|
||||
"values" : likes
|
||||
},
|
||||
{
|
||||
"name" : "Views",
|
||||
"values" : views
|
||||
}
|
||||
]
|
||||
},
|
||||
"type": "bar",
|
||||
"barOptions": {
|
||||
"stacked": 1
|
||||
},
|
||||
}
|
||||
|
||||
summary = [
|
||||
{
|
||||
"value": total_views,
|
||||
"indicator": "Blue",
|
||||
"label": "Total Views",
|
||||
"datatype": "Float",
|
||||
}
|
||||
]
|
||||
return chart_data, summary
|
@ -7,6 +7,7 @@ plaid-python==6.0.0
|
||||
pycountry==19.8.18
|
||||
PyGithub==1.44.1
|
||||
python-stdnum==1.12
|
||||
python-youtube==0.6.0
|
||||
taxjar==1.9.0
|
||||
tweepy==3.8.0
|
||||
Unidecode==1.1.1
|
||||
|
Loading…
x
Reference in New Issue
Block a user