Merge branch 'master' of github.com:webnotes/erpnext
This commit is contained in:
commit
dd71a02ec7
@ -70,5 +70,5 @@ cur_frm.fields_dict["expense_account"].get_query = function(doc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cur_frm.fields_dict.user.get_query = function(doc,cdt,cdn) {
|
cur_frm.fields_dict.user.get_query = function(doc,cdt,cdn) {
|
||||||
return{ query:"controllers.queries.profile_query"}
|
return{ query:"core.doctype.profile.profile.profile_query"}
|
||||||
}
|
}
|
||||||
|
@ -80,7 +80,6 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
|
|||||||
source_doctype: "Delivery Note",
|
source_doctype: "Delivery Note",
|
||||||
get_query: function() {
|
get_query: function() {
|
||||||
var filters = {
|
var filters = {
|
||||||
docstatus: 1,
|
|
||||||
company: cur_frm.doc.company
|
company: cur_frm.doc.company
|
||||||
};
|
};
|
||||||
if(cur_frm.doc.customer) filters["customer"] = cur_frm.doc.customer;
|
if(cur_frm.doc.customer) filters["customer"] = cur_frm.doc.customer;
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import webnotes
|
import webnotes
|
||||||
|
from webnotes.widgets.reportview import get_match_cond
|
||||||
|
|
||||||
def get_filters_cond(doctype, filters, conditions):
|
def get_filters_cond(doctype, filters, conditions):
|
||||||
if filters:
|
if filters:
|
||||||
@ -22,34 +23,6 @@ def get_filters_cond(doctype, filters, conditions):
|
|||||||
cond = ''
|
cond = ''
|
||||||
return cond
|
return cond
|
||||||
|
|
||||||
def get_match_cond(doctype, searchfield = 'name'):
|
|
||||||
from webnotes.widgets.reportview import build_match_conditions
|
|
||||||
cond = build_match_conditions(doctype)
|
|
||||||
|
|
||||||
if cond:
|
|
||||||
cond = ' and ' + cond
|
|
||||||
else:
|
|
||||||
cond = ''
|
|
||||||
return cond
|
|
||||||
|
|
||||||
# searches for enabled profiles
|
|
||||||
def profile_query(doctype, txt, searchfield, start, page_len, filters):
|
|
||||||
return webnotes.conn.sql("""select name, concat_ws(' ', first_name, middle_name, last_name)
|
|
||||||
from `tabProfile`
|
|
||||||
where ifnull(enabled, 0)=1
|
|
||||||
and docstatus < 2
|
|
||||||
and name not in ('Administrator', 'Guest')
|
|
||||||
and (%(key)s like "%(txt)s"
|
|
||||||
or concat_ws(' ', first_name, middle_name, last_name) like "%(txt)s")
|
|
||||||
%(mcond)s
|
|
||||||
order by
|
|
||||||
case when name like "%(txt)s" then 0 else 1 end,
|
|
||||||
case when concat_ws(' ', first_name, middle_name, last_name) like "%(txt)s"
|
|
||||||
then 0 else 1 end,
|
|
||||||
name asc
|
|
||||||
limit %(start)s, %(page_len)s""" % {'key': searchfield, 'txt': "%%%s%%" % txt,
|
|
||||||
'mcond':get_match_cond(doctype, searchfield), 'start': start, 'page_len': page_len})
|
|
||||||
|
|
||||||
# searches for active employees
|
# searches for active employees
|
||||||
def employee_query(doctype, txt, searchfield, start, page_len, filters):
|
def employee_query(doctype, txt, searchfield, start, page_len, filters):
|
||||||
return webnotes.conn.sql("""select name, employee_name from `tabEmployee`
|
return webnotes.conn.sql("""select name, employee_name from `tabEmployee`
|
||||||
@ -196,10 +169,12 @@ def get_price_list_currency(doctype, txt, searchfield, start, page_len, filters)
|
|||||||
def get_delivery_notes_to_be_billed(doctype, txt, searchfield, start, page_len, filters):
|
def get_delivery_notes_to_be_billed(doctype, txt, searchfield, start, page_len, filters):
|
||||||
return webnotes.conn.sql("""select `tabDelivery Note`.name, `tabDelivery Note`.customer_name
|
return webnotes.conn.sql("""select `tabDelivery Note`.name, `tabDelivery Note`.customer_name
|
||||||
from `tabDelivery Note`
|
from `tabDelivery Note`
|
||||||
where `tabDelivery Note`.`%(key)s` like %(txt)s %(fcond)s and
|
where `tabDelivery Note`.`%(key)s` like %(txt)s and
|
||||||
|
`tabDelivery Note`.docstatus = 1 %(fcond)s and
|
||||||
(ifnull((select sum(qty) from `tabDelivery Note Item` where
|
(ifnull((select sum(qty) from `tabDelivery Note Item` where
|
||||||
`tabDelivery Note Item`.parent=`tabDelivery Note`.name), 0) >
|
`tabDelivery Note Item`.parent=`tabDelivery Note`.name), 0) >
|
||||||
ifnull((select sum(qty) from `tabSales Invoice Item` where
|
ifnull((select sum(qty) from `tabSales Invoice Item` where
|
||||||
|
`tabSales Invoice Item`.docstatus = 1 and
|
||||||
`tabSales Invoice Item`.delivery_note=`tabDelivery Note`.name), 0))
|
`tabSales Invoice Item`.delivery_note=`tabDelivery Note`.name), 0))
|
||||||
%(mcond)s order by `tabDelivery Note`.`%(key)s` asc
|
%(mcond)s order by `tabDelivery Note`.`%(key)s` asc
|
||||||
limit %(start)s, %(page_len)s""" % {
|
limit %(start)s, %(page_len)s""" % {
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
---
|
||||||
|
{
|
||||||
|
"_label": "Calculate Incentive for Sales Team"
|
||||||
|
}
|
||||||
|
---
|
||||||
|
Can be used in any Sales Transaction with **Sales Team** Table:
|
||||||
|
|
||||||
|
|
||||||
|
cur_frm.cscript.custom_validate = function(doc) {
|
||||||
|
// calculate incentives for each person on the deal
|
||||||
|
total_incentive = 0
|
||||||
|
$.each(wn.model.get("Sales Team", {parent:doc.name}), function(i, d) {
|
||||||
|
|
||||||
|
// calculate incentive
|
||||||
|
var incentive_percent = 2;
|
||||||
|
if(doc.grand_total > 400) incentive_percent = 4;
|
||||||
|
|
||||||
|
// actual incentive
|
||||||
|
d.incentives = flt(doc.grand_total) * incentive_percent / 100;
|
||||||
|
total_incentive += flt(d.incentives)
|
||||||
|
});
|
||||||
|
|
||||||
|
doc.total_incentive = total_incentive;
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
{
|
||||||
|
"_label": "Custom Script: Fetch Values from Master"
|
||||||
|
}
|
||||||
|
---
|
||||||
|
To pull a value of a link on selection, use the `add_fetch` method.
|
||||||
|
|
||||||
|
add_fetch(link_fieldname, source_fieldname, target_fieldname)
|
||||||
|
|
||||||
|
### Example
|
||||||
|
|
||||||
|
You create Custom Field **VAT ID** (`vat_id`) in **Customer** and **Sales Invoice** and want to make sure this value gets updated every time you select a Customer in a Sales Invoice.
|
||||||
|
|
||||||
|
Then in the Sales Invoice Custom Script, add this line:
|
||||||
|
|
||||||
|
cur_frm.add_fetch('customer','vat_id','vat_id')
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
See: [How to create a custom script](!docs.dev.custom_script.html)
|
@ -0,0 +1,35 @@
|
|||||||
|
---
|
||||||
|
{
|
||||||
|
"_label": "Generate Item Code based on Custom Logic"
|
||||||
|
}
|
||||||
|
---
|
||||||
|
Add this in the Custom Script of **Item**, so that the new Item Code is generated just before the a new Item is saved.
|
||||||
|
|
||||||
|
cur_frm.cscript.custom_validate = function(doc) {
|
||||||
|
// clear item_code (name is from item_code)
|
||||||
|
doc.item_code = "";
|
||||||
|
|
||||||
|
// first 2 characters based on item_group
|
||||||
|
switch(doc.item_group) {
|
||||||
|
case "Test A":
|
||||||
|
doc.item_code = "TA";
|
||||||
|
break;
|
||||||
|
case "Test B":
|
||||||
|
doc.item_code = "TB";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
doc.item_code = "XX";
|
||||||
|
}
|
||||||
|
|
||||||
|
// add next 2 characters based on brand
|
||||||
|
switch(doc.brand) {
|
||||||
|
case "Brand A":
|
||||||
|
doc.item_code += "BA";
|
||||||
|
break;
|
||||||
|
case "Brand B":
|
||||||
|
doc.item_code += "BB";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
doc.item_code += "BX";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
---
|
||||||
|
{
|
||||||
|
"_label": "Make an Item read-only after Saving"
|
||||||
|
}
|
||||||
|
---
|
||||||
|
Use the method `cur_frm.set_df_property` to update the field's display.
|
||||||
|
|
||||||
|
In this script we also use the `__islocal` property of the doc to check if the document has been saved atleast once or is never saved. If `__islocal` is `1`, then the document has never been saved.
|
||||||
|
|
||||||
|
cur_frm.cscript.custom_refresh = function(doc) {
|
||||||
|
// use the __islocal value of doc, to check if the doc is saved or not
|
||||||
|
cur_frm.set_df_property("myfield", "read_only", doc.__islocal ? 0 : 1);
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
---
|
||||||
|
{
|
||||||
|
"_label": "Date Validation: Do not allow past dates in a date field"
|
||||||
|
}
|
||||||
|
---
|
||||||
|
|
||||||
|
cur_frm.cscript.custom_validate = function(doc) {
|
||||||
|
if (doc.from_date < get_today()) {
|
||||||
|
msgprint("You can not select past date in From Date");
|
||||||
|
validated = false;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
---
|
||||||
|
{
|
||||||
|
"_label": "Restrict Purpose of Stock Entry"
|
||||||
|
}
|
||||||
|
---
|
||||||
|
|
||||||
|
cur_frm.cscript.custom_validate = function(doc) {
|
||||||
|
if(user=="user1@example.com" && doc.purpose!="Material Receipt") {
|
||||||
|
msgprint("You are only allowed Material Receipt");
|
||||||
|
validated = false;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
{
|
||||||
|
"_label": "Restrict User Based on Child Record (Warehouse)"
|
||||||
|
}
|
||||||
|
---
|
||||||
|
|
||||||
|
// restrict certain warehouse to Material Manager
|
||||||
|
cur_frm.cscript.custom_validate = function(doc) {
|
||||||
|
if(user_roles.indexOf("Material Manager")==-1) {
|
||||||
|
|
||||||
|
var restricted_in_source = wn.model.get("Stock Entry Detail",
|
||||||
|
{parent:cur_frm.doc.name, s_warehouse:"Restricted"});
|
||||||
|
|
||||||
|
var restricted_in_target = wn.model.get("Stock Entry Detail",
|
||||||
|
{parent:cur_frm.doc.name, t_warehouse:"Restricted"})
|
||||||
|
|
||||||
|
if(restricted_in_source.length || restricted_in_target.length) {
|
||||||
|
msgprint("Only Material Manager can make entry in Restricted Warehouse");
|
||||||
|
validated = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
{
|
||||||
|
"_label": "Restrict Cancel Rights based on Certain Order Value"
|
||||||
|
}
|
||||||
|
---
|
||||||
|
Add a handler to `custom_before_cancel` event:
|
||||||
|
|
||||||
|
cur_frm.cscript.custom_before_cancel = function(doc) {
|
||||||
|
if (user_roles.indexOf("Accounts User")!=-1 && user_roles.indexOf("Accounts Manager")==-1
|
||||||
|
&& user_roles.indexOf("System Manager")==-1) {
|
||||||
|
if (flt(doc.grand_total) > 10000) {
|
||||||
|
msgprint("You can not cancel this transaction, because grand total \
|
||||||
|
is greater than 10000");
|
||||||
|
validated = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +0,0 @@
|
|||||||
---
|
|
||||||
{
|
|
||||||
"_label": "Client Scripts: Custoimzing ERPNext"
|
|
||||||
|
|
||||||
}
|
|
||||||
---
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
31
docs/dev/docs.dev.custom_script.md
Normal file
31
docs/dev/docs.dev.custom_script.md
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
---
|
||||||
|
{
|
||||||
|
"_label": "Custom Script Examples",
|
||||||
|
"_toc": [
|
||||||
|
"docs.dev.custom_script.fetch",
|
||||||
|
"docs.dev.custom_script.validate",
|
||||||
|
"docs.dev.custom_script.validate1",
|
||||||
|
"docs.dev.custom_script.validate2",
|
||||||
|
"docs.dev.custom_script.validate3",
|
||||||
|
"docs.dev.custom_script.read_only",
|
||||||
|
"docs.dev.custom_script.calculate",
|
||||||
|
"docs.dev.custom_script.item_code"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
---
|
||||||
|
### How to Create a Custom Script
|
||||||
|
|
||||||
|
Create a Custom Script (you must have System Manager role for this):
|
||||||
|
|
||||||
|
1. Got to: Setup > Custom Script > New Custom Script
|
||||||
|
1. Select the DocType in which you want to add the Custom Script
|
||||||
|
|
||||||
|
---
|
||||||
|
### Notes
|
||||||
|
|
||||||
|
1. Server Custom Scripts are only available for the Administrator.
|
||||||
|
1. Client Custom Scripts are in Javascript and Server Custom Scripts are in Python.
|
||||||
|
1. For testing, make sure to go to Tools > Clear Cache and refresh after updating a Custom Script.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
|||||||
"docs.dev.quickstart",
|
"docs.dev.quickstart",
|
||||||
"docs.dev.framework",
|
"docs.dev.framework",
|
||||||
"docs.dev.modules",
|
"docs.dev.modules",
|
||||||
"docs.dev.client_script",
|
"docs.dev.custom_script",
|
||||||
"docs.dev.api",
|
"docs.dev.api",
|
||||||
"docs.dev.translate",
|
"docs.dev.translate",
|
||||||
"docs.dev.docs"
|
"docs.dev.docs"
|
||||||
|
@ -6,7 +6,7 @@ erpnext.hr.EmployeeController = wn.ui.form.Controller.extend({
|
|||||||
setup: function() {
|
setup: function() {
|
||||||
this.setup_leave_approver_select();
|
this.setup_leave_approver_select();
|
||||||
this.frm.fields_dict.user_id.get_query = function(doc,cdt,cdn) {
|
this.frm.fields_dict.user_id.get_query = function(doc,cdt,cdn) {
|
||||||
return { query:"controllers.queries.profile_query"} }
|
return { query:"core.doctype.profile.profile.profile_query"} }
|
||||||
this.frm.fields_dict.reports_to.get_query = function(doc,cdt,cdn) {
|
this.frm.fields_dict.reports_to.get_query = function(doc,cdt,cdn) {
|
||||||
return{ query:"controllers.queries.employee_query"} }
|
return{ query:"controllers.queries.employee_query"} }
|
||||||
},
|
},
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
wn.provide("erpnext.queries");
|
wn.provide("erpnext.queries");
|
||||||
$.extend(erpnext.queries, {
|
$.extend(erpnext.queries, {
|
||||||
profile: function() {
|
profile: function() {
|
||||||
return { query: "controllers.queries.profile_query" };
|
return { query: "core.doctype.profile.profile.profile_query" };
|
||||||
},
|
},
|
||||||
|
|
||||||
lead: function() {
|
lead: function() {
|
||||||
|
@ -40,8 +40,7 @@ class DocType(TransactionBase):
|
|||||||
|
|
||||||
def validate_values(self):
|
def validate_values(self):
|
||||||
if webnotes.defaults.get_global_default('cust_master_name') == 'Naming Series' and not self.doc.naming_series:
|
if webnotes.defaults.get_global_default('cust_master_name') == 'Naming Series' and not self.doc.naming_series:
|
||||||
msgprint("Series is Mandatory.")
|
webnotes.throw("Series is Mandatory.", webnotes.MandatoryError)
|
||||||
raise Exception
|
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.validate_values()
|
self.validate_values()
|
||||||
|
@ -14,12 +14,12 @@ erpnext.LeadController = wn.ui.form.Controller.extend({
|
|||||||
onload: function() {
|
onload: function() {
|
||||||
if(cur_frm.fields_dict.lead_owner.df.options.match(/^Profile/)) {
|
if(cur_frm.fields_dict.lead_owner.df.options.match(/^Profile/)) {
|
||||||
cur_frm.fields_dict.lead_owner.get_query = function(doc,cdt,cdn) {
|
cur_frm.fields_dict.lead_owner.get_query = function(doc,cdt,cdn) {
|
||||||
return { query:"controllers.queries.profile_query" } }
|
return { query:"core.doctype.profile.profile.profile_query" } }
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cur_frm.fields_dict.contact_by.df.options.match(/^Profile/)) {
|
if(cur_frm.fields_dict.contact_by.df.options.match(/^Profile/)) {
|
||||||
cur_frm.fields_dict.contact_by.get_query = function(doc,cdt,cdn) {
|
cur_frm.fields_dict.contact_by.get_query = function(doc,cdt,cdn) {
|
||||||
return { query:"controllers.queries.profile_query" } }
|
return { query:"core.doctype.profile.profile.profile_query" } }
|
||||||
}
|
}
|
||||||
|
|
||||||
if(in_list(user_roles,'System Manager')) {
|
if(in_list(user_roles,'System Manager')) {
|
||||||
|
@ -7,7 +7,7 @@ import webnotes
|
|||||||
from webnotes.utils import cstr, getdate
|
from webnotes.utils import cstr, getdate
|
||||||
from webnotes.model.bean import getlist
|
from webnotes.model.bean import getlist
|
||||||
from webnotes.model.code import get_obj
|
from webnotes.model.code import get_obj
|
||||||
from webnotes import msgprint
|
from webnotes import _, msgprint
|
||||||
|
|
||||||
sql = webnotes.conn.sql
|
sql = webnotes.conn.sql
|
||||||
|
|
||||||
@ -278,3 +278,7 @@ def _make_customer(source_name, ignore_permissions=False):
|
|||||||
return customer
|
return customer
|
||||||
else:
|
else:
|
||||||
raise e
|
raise e
|
||||||
|
except webnotes.MandatoryError:
|
||||||
|
from webnotes.utils import get_url_to_form
|
||||||
|
webnotes.throw(_("Before proceeding, please create Customer from Lead") + \
|
||||||
|
(" - %s" % get_url_to_form("Lead", lead_name)))
|
||||||
|
@ -161,7 +161,7 @@ def _get_item_discount(item_group, customer):
|
|||||||
FROM `tabItem Group` AS node, `tabItem Group` AS parent
|
FROM `tabItem Group` AS node, `tabItem Group` AS parent
|
||||||
WHERE parent.lft <= node.lft and parent.rgt >= node.rgt and node.name = %s
|
WHERE parent.lft <= node.lft and parent.rgt >= node.rgt and node.name = %s
|
||||||
GROUP BY parent.name
|
GROUP BY parent.name
|
||||||
ORDER BY parent.lft desc""", item_group)]
|
ORDER BY parent.lft desc""", (item_group,))]
|
||||||
|
|
||||||
discount = 0
|
discount = 0
|
||||||
for d in parent_item_groups:
|
for d in parent_item_groups:
|
||||||
|
@ -69,10 +69,10 @@ cur_frm.cscript.transaction = function(doc,cdt,cdn){
|
|||||||
|
|
||||||
|
|
||||||
cur_frm.fields_dict.system_user.get_query = function(doc,cdt,cdn) {
|
cur_frm.fields_dict.system_user.get_query = function(doc,cdt,cdn) {
|
||||||
return{ query:"controllers.queries.profile_query" } }
|
return{ query:"core.doctype.profile.profile.profile_query" } }
|
||||||
|
|
||||||
cur_frm.fields_dict.approving_user.get_query = function(doc,cdt,cdn) {
|
cur_frm.fields_dict.approving_user.get_query = function(doc,cdt,cdn) {
|
||||||
return{ query:"controllers.queries.profile_query" } }
|
return{ query:"core.doctype.profile.profile.profile_query" } }
|
||||||
|
|
||||||
cur_frm.fields_dict['approving_role'].get_query = cur_frm.fields_dict['system_role'].get_query;
|
cur_frm.fields_dict['approving_role'].get_query = cur_frm.fields_dict['system_role'].get_query;
|
||||||
|
|
||||||
|
@ -16,7 +16,9 @@ def boot_session(bootinfo):
|
|||||||
|
|
||||||
if webnotes.session['user']!='Guest':
|
if webnotes.session['user']!='Guest':
|
||||||
bootinfo['letter_heads'] = get_letter_heads()
|
bootinfo['letter_heads'] = get_letter_heads()
|
||||||
|
|
||||||
|
load_country_and_currency(bootinfo)
|
||||||
|
|
||||||
import webnotes.model.doctype
|
import webnotes.model.doctype
|
||||||
bootinfo['notification_settings'] = webnotes.doc("Notification Control",
|
bootinfo['notification_settings'] = webnotes.doc("Notification Control",
|
||||||
"Notification Control").get_values()
|
"Notification Control").get_values()
|
||||||
@ -36,7 +38,15 @@ def boot_session(bootinfo):
|
|||||||
|
|
||||||
bootinfo['docs'] += webnotes.conn.sql("""select name, default_currency, cost_center
|
bootinfo['docs'] += webnotes.conn.sql("""select name, default_currency, cost_center
|
||||||
from `tabCompany`""", as_dict=1, update={"doctype":":Company"})
|
from `tabCompany`""", as_dict=1, update={"doctype":":Company"})
|
||||||
|
|
||||||
|
def load_country_and_currency(bootinfo):
|
||||||
|
if bootinfo.control_panel.country and \
|
||||||
|
webnotes.conn.exists("Country", bootinfo.control_panel.country):
|
||||||
|
bootinfo["docs"] += [webnotes.doc("Country", bootinfo.control_panel.country)]
|
||||||
|
|
||||||
|
bootinfo["docs"] += webnotes.conn.sql("""select * from tabCurrency
|
||||||
|
where ifnull(enabled,0)=1""", as_dict=1, update={"doctype":":Currency"})
|
||||||
|
|
||||||
def get_letter_heads():
|
def get_letter_heads():
|
||||||
"""load letter heads with startup"""
|
"""load letter heads with startup"""
|
||||||
import webnotes
|
import webnotes
|
||||||
|
@ -64,6 +64,12 @@ def check_if_expired():
|
|||||||
webnotes.response['message'] = 'Account Expired'
|
webnotes.response['message'] = 'Account Expired'
|
||||||
raise webnotes.AuthenticationError
|
raise webnotes.AuthenticationError
|
||||||
|
|
||||||
|
def on_build():
|
||||||
|
from website.helpers.make_web_include_files import make
|
||||||
|
make()
|
||||||
|
|
||||||
|
from home.page.latest_updates import latest_updates
|
||||||
|
latest_updates.make()
|
||||||
|
|
||||||
def comment_added(doc):
|
def comment_added(doc):
|
||||||
"""add comment to feed"""
|
"""add comment to feed"""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user