moved directory structure

This commit is contained in:
Rushabh Mehta
2012-09-24 19:13:42 +05:30
parent e47a6779e9
commit 2fa2f7178d
1637 changed files with 47 additions and 11450 deletions

View File

@@ -0,0 +1,108 @@
# DocType Mapper, Customer Issue-Maintenance Visit
[
# These values are common in all dictionaries
{
'creation': '2010-08-08 17:09:34',
'docstatus': 0,
'modified': '2011-09-15 15:04:41',
'modified_by': 'Administrator',
'owner': 'ashwini@webnotestech.com'
},
# These values are common for all Table Mapper Detail
{
'doctype': 'Table Mapper Detail',
'from_table': 'Customer Issue',
'name': '__common__',
'parent': 'Customer Issue-Maintenance Visit',
'parentfield': 'table_mapper_details',
'parenttype': 'DocType Mapper',
'reference_key': 'prevdoc_docname',
'validation_logic': 'docstatus=1'
},
# These values are common for all Field Mapper Detail
{
'doctype': 'Field Mapper Detail',
'map': 'Yes',
'name': '__common__',
'parent': 'Customer Issue-Maintenance Visit',
'parentfield': 'field_mapper_details',
'parenttype': 'DocType Mapper'
},
# These values are common for all DocType Mapper
{
'doctype': 'DocType Mapper',
'from_doctype': 'Customer Issue',
'module': 'Support',
'name': '__common__',
'ref_doc_submitted': 1,
'to_doctype': 'Maintenance Visit'
},
# DocType Mapper, Customer Issue-Maintenance Visit
{
'doctype': 'DocType Mapper',
'name': 'Customer Issue-Maintenance Visit'
},
# Field Mapper Detail
{
'checking_operator': '=',
'doctype': 'Field Mapper Detail',
'from_field': 'customer',
'match_id': 0,
'to_field': 'customer'
},
# Field Mapper Detail
{
'doctype': 'Field Mapper Detail',
'from_field': 'name',
'match_id': 0,
'to_field': 'customer_issue_no'
},
# Field Mapper Detail
{
'checking_operator': '=',
'doctype': 'Field Mapper Detail',
'from_field': 'complaint',
'match_id': 1,
'to_field': 'description'
},
# Field Mapper Detail
{
'doctype': 'Field Mapper Detail',
'from_field': 'doctype',
'match_id': 1,
'to_field': 'prevdoc_doctype'
},
# Field Mapper Detail
{
'doctype': 'Field Mapper Detail',
'from_field': 'name',
'match_id': 1,
'to_field': 'prevdoc_docname'
},
# Table Mapper Detail
{
'doctype': 'Table Mapper Detail',
'match_id': 1,
'reference_doctype_key': 'prevdoc_doctype',
'to_field': 'maintenance_visit_details',
'to_table': 'Maintenance Visit Purpose'
},
# Table Mapper Detail
{
'doctype': 'Table Mapper Detail',
'match_id': 0,
'to_table': 'Maintenance Visit'
}
]

View File

@@ -0,0 +1,99 @@
# DocType Mapper, Maintenance Schedule-Maintenance Visit
[
# These values are common in all dictionaries
{
'creation': '2012-06-27 13:18:25',
'docstatus': 0,
'modified': '2012-06-27 13:18:25',
'modified_by': u'Administrator',
'owner': u'Administrator'
},
# These values are common for all Table Mapper Detail
{
'doctype': u'Table Mapper Detail',
'name': '__common__',
'parent': u'Maintenance Schedule-Maintenance Visit',
'parentfield': u'table_mapper_details',
'parenttype': u'DocType Mapper',
'validation_logic': u'docstatus=1'
},
# These values are common for all Field Mapper Detail
{
'doctype': u'Field Mapper Detail',
'map': u'Yes',
'name': '__common__',
'parent': u'Maintenance Schedule-Maintenance Visit',
'parentfield': u'field_mapper_details',
'parenttype': u'DocType Mapper'
},
# These values are common for all DocType Mapper
{
'doctype': u'DocType Mapper',
'from_doctype': u'Maintenance Schedule',
'module': u'Support',
'name': '__common__',
'ref_doc_submitted': 1,
'to_doctype': u'Maintenance Visit'
},
# DocType Mapper, Maintenance Schedule-Maintenance Visit
{
'doctype': u'DocType Mapper',
'name': u'Maintenance Schedule-Maintenance Visit'
},
# Field Mapper Detail
{
'checking_operator': u'=',
'doctype': u'Field Mapper Detail',
'from_field': u'customer',
'match_id': 0,
'to_field': u'customer'
},
# Field Mapper Detail
{
'doctype': u'Field Mapper Detail',
'from_field': u'name',
'match_id': 0,
'to_field': u'maintenance_schedule'
},
# Field Mapper Detail
{
'doctype': u'Field Mapper Detail',
'from_field': u'parent',
'match_id': 1,
'to_field': u'prevdoc_docname'
},
# Field Mapper Detail
{
'doctype': u'Field Mapper Detail',
'from_field': u'parenttype',
'match_id': 1,
'to_field': u'prevdoc_doctype'
},
# Table Mapper Detail
{
'doctype': u'Table Mapper Detail',
'from_field': u'item_maintenance_detail',
'from_table': u'Maintenance Schedule Item',
'match_id': 1,
'to_field': u'maintenance_visit_details',
'to_table': u'Maintenance Visit Purpose'
},
# Table Mapper Detail
{
'doctype': u'Table Mapper Detail',
'from_table': u'Maintenance Schedule',
'match_id': 0,
'to_table': u'Maintenance Visit'
}
]

View File

@@ -0,0 +1,101 @@
# DocType Mapper, Sales Order-Maintenance Schedule
[
# These values are common in all dictionaries
{
'creation': '2010-08-08 17:09:35',
'docstatus': 0,
'modified': '2011-09-15 15:04:44',
'modified_by': 'Administrator',
'owner': 'Administrator'
},
# These values are common for all Table Mapper Detail
{
'doctype': 'Table Mapper Detail',
'name': '__common__',
'parent': 'Sales Order-Maintenance Schedule',
'parentfield': 'table_mapper_details',
'parenttype': 'DocType Mapper'
},
# These values are common for all Field Mapper Detail
{
'doctype': 'Field Mapper Detail',
'map': 'Yes',
'name': '__common__',
'parent': 'Sales Order-Maintenance Schedule',
'parentfield': 'field_mapper_details',
'parenttype': 'DocType Mapper'
},
# These values are common for all DocType Mapper
{
'doctype': 'DocType Mapper',
'from_doctype': 'Sales Order',
'module': 'Support',
'name': '__common__',
'ref_doc_submitted': 1,
'to_doctype': 'Maintenance Schedule'
},
# DocType Mapper, Sales Order-Maintenance Schedule
{
'doctype': 'DocType Mapper',
'name': 'Sales Order-Maintenance Schedule'
},
# Field Mapper Detail
{
'checking_operator': '=',
'doctype': 'Field Mapper Detail',
'from_field': 'customer',
'match_id': 0,
'to_field': 'customer'
},
# Field Mapper Detail
{
'doctype': 'Field Mapper Detail',
'from_field': 'name',
'match_id': 0,
'to_field': 'sales_order_no'
},
# Field Mapper Detail
{
'checking_operator': '=',
'doctype': 'Field Mapper Detail',
'from_field': 'item_code',
'match_id': 1,
'to_field': 'item_code'
},
# Field Mapper Detail
{
'doctype': 'Field Mapper Detail',
'from_field': 'parent',
'match_id': 1,
'to_field': 'prevdoc_docname'
},
# Table Mapper Detail
{
'doctype': 'Table Mapper Detail',
'from_field': 'sales_order_details',
'from_table': 'Sales Order Item',
'match_id': 1,
'to_field': 'item_maintenance_detail',
'to_table': 'Maintenance Schedule Item',
'validation_logic': 'docstatus =1'
},
# Table Mapper Detail
{
'doctype': 'Table Mapper Detail',
'from_table': 'Sales Order',
'match_id': 0,
'to_table': 'Maintenance Schedule',
'validation_logic': 'docstatus=1'
}
]

View File

@@ -0,0 +1,99 @@
# DocType Mapper, Sales Order-Maintenance Visit
[
# These values are common in all dictionaries
{
'creation': '2010-08-08 17:09:36',
'docstatus': 0,
'modified': '2011-09-15 15:04:45',
'modified_by': 'Administrator',
'owner': 'ashwini@webnotestech.com'
},
# These values are common for all Table Mapper Detail
{
'doctype': 'Table Mapper Detail',
'name': '__common__',
'parent': 'Sales Order-Maintenance Visit',
'parentfield': 'table_mapper_details',
'parenttype': 'DocType Mapper',
'validation_logic': 'docstatus=1'
},
# These values are common for all Field Mapper Detail
{
'doctype': 'Field Mapper Detail',
'map': 'Yes',
'name': '__common__',
'parent': 'Sales Order-Maintenance Visit',
'parentfield': 'field_mapper_details',
'parenttype': 'DocType Mapper'
},
# These values are common for all DocType Mapper
{
'doctype': 'DocType Mapper',
'from_doctype': 'Sales Order',
'module': 'Support',
'name': '__common__',
'ref_doc_submitted': 1,
'to_doctype': 'Maintenance Visit'
},
# DocType Mapper, Sales Order-Maintenance Visit
{
'doctype': 'DocType Mapper',
'name': 'Sales Order-Maintenance Visit'
},
# Field Mapper Detail
{
'checking_operator': '=',
'doctype': 'Field Mapper Detail',
'from_field': 'customer',
'match_id': 0,
'to_field': 'customer'
},
# Field Mapper Detail
{
'doctype': 'Field Mapper Detail',
'from_field': 'name',
'match_id': 0,
'to_field': 'sales_order_no'
},
# Field Mapper Detail
{
'doctype': 'Field Mapper Detail',
'from_field': 'parent',
'match_id': 1,
'to_field': 'prevdoc_docname'
},
# Field Mapper Detail
{
'doctype': 'Field Mapper Detail',
'from_field': 'parenttype',
'match_id': 1,
'to_field': 'prevdoc_doctype'
},
# Table Mapper Detail
{
'doctype': 'Table Mapper Detail',
'from_field': 'sales_order_details',
'from_table': 'Sales Order Item',
'match_id': 1,
'to_field': 'maintenance_visit_details',
'to_table': 'Maintenance Visit Purpose'
},
# Table Mapper Detail
{
'doctype': 'Table Mapper Detail',
'from_table': 'Sales Order',
'match_id': 0,
'to_table': 'Maintenance Visit'
}
]

7
support/__init__.py Normal file
View File

@@ -0,0 +1,7 @@
from __future__ import unicode_literals
install_docs = [
{'doctype':'Role', 'role_name':'Support Team', 'name':'Support Team'},
{'doctype':'Role', 'role_name':'Support Manager', 'name':'Support Manager'},
{'doctype':'Role', 'role_name':'Maintenance User', 'name':'Maintenance User'},
{'doctype':'Role', 'role_name':'Maintenance Manager', 'name':'Maintenance Manager'}
]

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1,121 @@
cur_frm.cscript.refresh = function(doc, dt, dn) {
if(!doc.__islocal) {
var field_list = ['lead', 'customer', 'supplier', 'contact', 'opportunity',
'quotation', 'support_ticket'];
var hide_list = [];
$.each(field_list, function(i, v) {
if(!doc[v]) hide_list.push(v);
});
if(hide_list.length < field_list.length) hide_field(hide_list);
}
}
cur_frm.cscript.make_communication_body = function() {
var communication_wrapper = cur_frm.fields_dict.communication_html.wrapper;
communication_wrapper.innerHTML = '';
cur_frm.communication_html = $a(communication_wrapper, 'div');
$(cur_frm.communication_html).css({
'min-height': '275px',
});
}
cur_frm.cscript.render_communication_list = function(doc, dt, dn) {
var ListView = wn.views.ListView.extend({
init: function(doclistview) {
this._super(doclistview);
this.fields = this.fields.concat([
"`tabCommunication`.communication_date",
"`tabCommunication`.category",
"`tabCommunication`.subject",
"`tabCommunication`.content"
]);
this.order_by = "`tabCommunication`.communication_date desc";
},
prepare_data: function(data) {
this._super(data);
this.prepare_when(data, data.creation);
// escape double quote
data.content = cstr(data.subject).replace(/"/gi, '\"')
+ " | " + cstr(data.content).replace(/"/gi, '\"');
if(data.content && data.content.length > 50) {
data.content = '<span title="'+data.content+'">' +
data.content.substr(0,50) + '...</span>';
}
},
columns: [
{width: '3%', content: 'docstatus'},
{width: '15%', content: 'name'},
{width: '15%', content: 'category'},
{width: '55%', content: 'content'},
{width: '12%', content:'when',
css: {'text-align': 'right', 'color':'#777'}}
],
});
cur_frm.cscript.render_list(doc, 'Communication', cur_frm.communication_html,
ListView, function(doctype) {
var new_doc = LocalDB.create(doctype);
new_doc = locals[doctype][new_doc];
new_doc[doc.doctype.toLowerCase().replace(" ", "_")] = doc.name;
loaddoc(new_doc.doctype, new_doc.name);
});
}
// Render List
cur_frm.cscript.render_list = function(doc, doctype, wrapper, ListView, make_new_doc) {
wn.model.with_doctype(doctype, function(r) {
if((r && r['403']) || wn.boot.profile.all_read.indexOf(doctype)===-1) {
return;
}
var RecordListView = wn.views.RecordListView.extend({
default_docstatus: ['0', '1', '2'],
default_filters: [
[doctype, doc.doctype.toLowerCase().replace(" ", "_"), '=', doc.name],
],
});
if (make_new_doc) {
RecordListView = RecordListView.extend({
make_new_doc: make_new_doc,
});
}
var record_list_view = new RecordListView(doctype, wrapper, ListView);
if (!cur_frm[doctype.toLowerCase().replace(" ", "_") + "_list"]) {
cur_frm[doctype.toLowerCase().replace(" ", "_") + "_list"] = record_list_view;
}
});
}
cur_frm.cscript.contact = function(doc, dt, dn) {
if (doc.contact) {
wn.call({
method: 'support.doctype.communication.communication.get_customer_supplier',
args: {
contact: doc.contact
},
callback: function(r, rt) {
if (!r.exc && r.message) {
doc = locals[doc.doctype][doc.name];
doc[r.message['fieldname']] = r.message['value'];
refresh_field(r.message['fieldname']);
}
},
});
}
}
cur_frm.cscript.hide_dialog = function() {
if(cur_frm.communication_list)
cur_frm.communication_list.run();
}

View File

@@ -0,0 +1,47 @@
# ERPNext - web based ERP (http://erpnext.com)
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals
import webnotes
from webnotes.model.doc import make_autoname
@webnotes.whitelist()
def get_customer_supplier(args=None):
"""
Get Customer/Supplier, given a contact, if a unique match exists
"""
import webnotes
if not args: args = webnotes.form_dict
if not args.get('contact'):
raise Exception, "Please specify a contact to fetch Customer/Supplier"
result = webnotes.conn.sql("""\
select customer, supplier
from `tabContact`
where name = %s""", args.get('contact'), as_dict=1)
if result and len(result)==1 and (result[0]['customer'] or result[0]['supplier']):
return {
'fieldname': result[0]['customer'] and 'customer' or 'supplier',
'value': result[0]['customer'] or result[0]['supplier']
}
return {}
class DocType():
def __init__(self, doc, doclist=[]):
self.doc = doc
self.doclist = doclist
def autoname(self):
self.doc.name = make_autoname(self.doc.naming_series+'.#####')

View File

@@ -0,0 +1,406 @@
# DocType, Communication
[
# These values are common in all dictionaries
{
'creation': '2012-06-26 11:58:13',
'docstatus': 0,
'modified': '2012-08-31 16:44:13',
'modified_by': u'Administrator',
'owner': u'Administrator'
},
# These values are common for all DocType
{
'allow_attach': 1,
'description': u'Keep a track of all communications',
'doctype': 'DocType',
'document_type': u'Master',
'in_dialog': 1,
'module': u'Support',
'name': '__common__',
'version': 1
},
# These values are common for all DocField
{
'doctype': u'DocField',
'name': '__common__',
'parent': u'Communication',
'parentfield': u'fields',
'parenttype': u'DocType'
},
# These values are common for all DocPerm
{
'amend': 0,
'doctype': u'DocPerm',
'name': '__common__',
'parent': u'Communication',
'parentfield': u'permissions',
'parenttype': u'DocType',
'read': 1,
'submit': 0,
'write': 1
},
# DocType, Communication
{
'doctype': 'DocType',
'name': u'Communication'
},
# DocPerm
{
'cancel': 0,
'create': 1,
'doctype': u'DocPerm',
'permlevel': 0,
'role': u'Support Team'
},
# DocPerm
{
'cancel': 0,
'create': 1,
'doctype': u'DocPerm',
'permlevel': 0,
'role': u'Sales Manager'
},
# DocPerm
{
'cancel': 0,
'create': 1,
'doctype': u'DocPerm',
'permlevel': 0,
'role': u'Sales User'
},
# DocPerm
{
'cancel': 0,
'create': 0,
'doctype': u'DocPerm',
'permlevel': 1,
'role': u'Sales Manager'
},
# DocPerm
{
'cancel': 1,
'create': 0,
'doctype': u'DocPerm',
'permlevel': 1,
'role': u'Support Manager'
},
# DocPerm
{
'cancel': 1,
'create': 1,
'doctype': u'DocPerm',
'permlevel': 0,
'role': u'Support Manager'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'basic_info',
'fieldtype': u'Section Break',
'label': u'Basic Info',
'permlevel': 0
},
# DocField
{
'colour': u'White:FFF',
'default': u'COMM-',
'doctype': u'DocField',
'fieldname': u'naming_series',
'fieldtype': u'Select',
'hidden': 1,
'label': u'Naming Series',
'options': u'COMM-',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'category',
'fieldtype': u'Select',
'label': u'Category',
'options': u'\nSales\nComplaint\nHelp\nSuggestion\nMiscellaneous\nSent Mail',
'permlevel': 0,
'reqd': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'action',
'fieldtype': u'Select',
'label': u'Action',
'options': u'\nCreated Opportunity\nSent Quotation\nCreated Support Ticket\nCreated Customer Issue\nNo Action\nSent Mail',
'permlevel': 0,
'reqd': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'next_communication_date',
'fieldtype': u'Date',
'label': u'Next Communcation On',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'column_break2',
'fieldtype': u'Column Break',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'subject',
'fieldtype': u'Small Text',
'label': u'Subject',
'permlevel': 0,
'reqd': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'section_break1',
'fieldtype': u'Section Break',
'options': u'simple',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'content',
'fieldtype': u'Text',
'label': u'Content',
'permlevel': 0,
'reqd': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'additional_info',
'fieldtype': u'Section Break',
'label': u'Additional Info',
'permlevel': 0
},
# DocField
{
'colour': u'White:FFF',
'doctype': u'DocField',
'fieldname': u'column_break3',
'fieldtype': u'Column Break',
'label': u'Communication With / Related To',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'lead',
'fieldtype': u'Link',
'hidden': 0,
'label': u'Lead',
'options': u'Lead',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'contact',
'fieldtype': u'Link',
'label': u'Contact',
'options': u'Contact',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'customer',
'fieldtype': u'Link',
'label': u'Customer',
'options': u'Customer',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'supplier',
'fieldtype': u'Link',
'label': u'Supplier',
'options': u'Supplier',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'opportunity',
'fieldtype': u'Link',
'label': u'Opportunity',
'options': u'Opportunity',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'quotation',
'fieldtype': u'Link',
'label': u'Quotation',
'options': u'Quotation',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'support_ticket',
'fieldtype': u'Link',
'label': u'Support Ticket',
'options': u'Support Ticket',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'column_break1',
'fieldtype': u'Column Break',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'communication_medium',
'fieldtype': u'Select',
'label': u'Communication Medium',
'options': u'\nChat\nPhone\nEmail\nSMS\nVisit\nOther',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'phone_no',
'fieldtype': u'Data',
'label': u'Phone No.',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'email_address',
'fieldtype': u'Data',
'label': u'Email Address',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'section_break2',
'fieldtype': u'Section Break',
'options': u'simple',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'column_break4',
'fieldtype': u'Column Break',
'label': u'Communication Carried Out By',
'permlevel': 0
},
# DocField
{
'colour': u'White:FFF',
'default': u'__user',
'doctype': u'DocField',
'fieldname': u'user',
'fieldtype': u'Link',
'label': u'User',
'options': u'Profile',
'permlevel': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'sales_person',
'fieldtype': u'Link',
'label': u'Sales Person',
'options': u'Sales Person',
'permlevel': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'column_break5',
'fieldtype': u'Column Break',
'label': u'Communication Carried Out On',
'permlevel': 0
},
# DocField
{
'colour': u'White:FFF',
'default': u'Today',
'doctype': u'DocField',
'fieldname': u'communication_date',
'fieldtype': u'Date',
'label': u'Date',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'file_list',
'fieldtype': u'Text',
'hidden': 1,
'label': u'File List',
'no_copy': 1,
'permlevel': 0,
'print_hide': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'_user_tags',
'fieldtype': u'Data',
'hidden': 1,
'label': u'User Tags',
'no_copy': 1,
'permlevel': 0,
'print_hide': 1
}
]

View File

@@ -0,0 +1,43 @@
wn.doclistviews['Communication'] = wn.views.ListView.extend({
init: function(doclistview) {
this._super(doclistview);
this.fields = this.fields.concat([
"`tabCommunication`.creation",
"`tabCommunication`.category",
"`tabCommunication`.subject",
"`tabCommunication`.content"
]);
this.order_by = "`tabCommunication`.creation desc";
this.stats = this.stats.concat(['category']);
},
prepare_data: function(data) {
this._super(data);
this.prepare_when(data, data.creation);
// escape double quote
data.content = cstr(data.subject)
+ " | " + cstr(data.content);
data.content = data.content.replace(/"/gi, '\"')
.replace(/</gi, '&lt;').replace(/>/gi, '&gt;');
if(data.content && data.content.length > 50) {
data.content = '<span title="'+data.content+'">' +
data.content.substr(0,50) + '...</span>';
}
},
columns: [
{width: '3%', content: 'check'},
{width: '5%', content: 'avatar'},
{width: '15%', content: 'name'},
{width: '15%', content: 'category'},
{width: '55%', content: 'content+tags'},
{width: '12%', content:'when',
css: {'text-align': 'right', 'color':'#777'}}
],
make_new_doc: function(new_doctype) {
new_doc(new_doctype, 1);
}
});

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1,146 @@
// ERPNext - web based ERP (http://erpnext.com)
// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
cur_frm.cscript.onload = function(doc,cdt,cdn){
if(!doc.status) set_multiple(dt,dn,{status:'Open'});
if(doc.__islocal){
hide_field(['customer_address','contact_person']);
}
}
cur_frm.cscript.refresh = function(doc,ct,cdn){
if(doc.docstatus == 1 && (doc.status == 'Open' || doc.status == 'Work In Progress'))
cur_frm.add_custom_button('Make Maintenance Visit', cur_frm.cscript['Make Maintenance Visit']);
}
//customer
cur_frm.cscript.customer = function(doc,dt,dn) {
var callback = function(r,rt) {
var doc = locals[cur_frm.doctype][cur_frm.docname];
cur_frm.refresh();
}
if(doc.customer) $c_obj(make_doclist(doc.doctype, doc.name), 'get_default_customer_address', '', callback);
if(doc.customer) unhide_field(['customer_address','contact_person']);
}
cur_frm.cscript.customer_address = cur_frm.cscript.contact_person = function(doc,dt,dn) {
if(doc.customer)
get_server_fields('get_customer_address',
JSON.stringify({customer: doc.customer, address: doc.customer_address, contact: doc.contact_person}),'', doc, dt, dn, 1);
}
cur_frm.fields_dict.customer_address.on_new = function(dn) {
locals['Address'][dn].customer = locals[cur_frm.doctype][cur_frm.docname].customer;
locals['Address'][dn].customer_name = locals[cur_frm.doctype][cur_frm.docname].customer_name;
}
cur_frm.fields_dict.contact_person.on_new = function(dn) {
locals['Contact'][dn].customer = locals[cur_frm.doctype][cur_frm.docname].customer;
locals['Contact'][dn].customer_name = locals[cur_frm.doctype][cur_frm.docname].customer_name;
}
cur_frm.fields_dict['customer_address'].get_query = function(doc, cdt, cdn) {
return 'SELECT name,address_line1,city FROM tabAddress WHERE customer = "'+ doc.customer +
'" AND docstatus != 2 AND name LIKE "%s" ORDER BY name ASC LIMIT 50';
}
cur_frm.fields_dict['contact_person'].get_query = function(doc, cdt, cdn) {
return 'SELECT name,CONCAT(first_name," ",ifnull(last_name,"")) As FullName,department,designation \
FROM tabContact WHERE customer = "' + doc.customer +
'" AND docstatus != 2 AND name LIKE "%s" ORDER BY name ASC LIMIT 50';
}
cur_frm.cscript['Make Maintenance Visit'] = function() {
var doc = cur_frm.doc;
if (doc.docstatus == 1) {
$c_obj(make_doclist(doc.doctype, doc.name),'check_maintenance_visit','',
function(r,rt){
if(r.message == 'No'){
n = createLocal("Maintenance Visit");
$c('dt_map', args={
'docs':compress_doclist([locals["Maintenance Visit"][n]]),
'from_doctype':'Customer Issue',
'to_doctype':'Maintenance Visit',
'from_docname':doc.name,
'from_to_list':"[['Customer Issue', 'Maintenance Visit'], ['Customer Issue', 'Maintenance Visit Purpose']]"
}, function(r,rt) {
loaddoc("Maintenance Visit", n);
});
} else{
msgprint("You have already completed maintenance against this Customer Issue");
}
}
);
}
}
// ----------
// serial no
// ----------
cur_frm.fields_dict['serial_no'].get_query = function(doc, cdt, cdn) {
var cond = '';
if(doc.item_code) cond = ' AND `tabSerial No`.item_code = "'+ doc.item_code +'"';
if(doc.customer) cond += ' AND `tabSerial No`.customer = "' + doc.customer + '"';
return 'SELECT `tabSerial No`.name, `tabSerial No`.description \
FROM `tabSerial No` \
WHERE `tabSerial No`.docstatus != 2 AND `tabSerial No`.status = "Delivered" \
AND `tabSerial No`.name LIKE "%s" ' + cond + ' ORDER BY `tabSerial No`.name ASC LIMIT 50';
}
cur_frm.add_fetch('serial_no', 'item_code', 'item_code');
cur_frm.add_fetch('serial_no', 'item_name', 'item_name');
cur_frm.add_fetch('serial_no', 'description', 'description');
cur_frm.add_fetch('serial_no', 'maintenance_status', 'warranty_amc_status');
cur_frm.add_fetch('serial_no', 'warranty_expiry_date', 'warranty_expiry_date');
cur_frm.add_fetch('serial_no', 'amc_expiry_date', 'amc_expiry_date');
if (cstr(doc.customer) == '') {
cur_frm.add_fetch('serial_no', 'customer', 'customer');
cur_frm.add_fetch('serial_no', 'customer_name', 'customer_name');
cur_frm.add_fetch('serial_no', 'delivery_address', 'customer_address');
}
// ----------
// item code
// ----------
cur_frm.fields_dict['item_code'].get_query = function(doc, cdt, cdn) {
if(doc.serial_no) {
return 'SELECT `tabSerial No`.item_code, `tabSerial No`.description \
FROM `tabSerial No` \
WHERE `tabSerial No`.docstatus != 2 AND `tabSerial No`.name = "' + doc.serial_no +
'" AND `tabSerial No`.item_code LIKE "%s" ORDER BY `tabSerial No`.item_code ASC LIMIT 50';
}
else{
return 'SELECT `tabItem`.name, `tabItem`.item_name, `tabItem`.description \
FROM `tabItem` \
WHERE `tabItem`.docstatus != 2 AND `tabItem`.%(key)s LIKE "%s" ORDER BY `tabItem`.name ASC LIMIT 50';
}
}
cur_frm.add_fetch('item_code', 'item_name', 'item_name');
cur_frm.add_fetch('item_code', 'description', 'description');
//get query select Territory
//=======================================================================================================================
cur_frm.fields_dict['territory'].get_query = function(doc,cdt,cdn) {
return 'SELECT `tabTerritory`.`name`,`tabTerritory`.`parent_territory` \
FROM `tabTerritory` \
WHERE `tabTerritory`.`is_group` = "No" AND `tabTerritory`.`docstatus`!= 2 \
AND `tabTerritory`.%(key)s LIKE "%s" ORDER BY `tabTerritory`.`name` ASC LIMIT 50';
}

View File

@@ -0,0 +1,78 @@
# ERPNext - web based ERP (http://erpnext.com)
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Please edit this list and import only required elements
from __future__ import unicode_literals
import webnotes
from webnotes.utils import add_days, add_months, add_years, cint, cstr, date_diff, default_fields, flt, fmt_money, formatdate, generate_hash, getTraceback, get_defaults, get_first_day, get_last_day, getdate, has_common, month_name, now, nowdate, replace_newlines, sendmail, set_default, str_esc_quote, user_format, validate_email_add
from webnotes.model import db_exists
from webnotes.model.doc import Document, addchild, getchildren, make_autoname
from webnotes.model.doclist import getlist, copy_doclist
from webnotes.model.code import get_obj, get_server_obj, run_server_obj, updatedb, check_syntax
from webnotes import session, form, is_testing, msgprint, errprint
set = webnotes.conn.set
sql = webnotes.conn.sql
get_value = webnotes.conn.get_value
in_transaction = webnotes.conn.in_transaction
convert_to_lists = webnotes.conn.convert_to_lists
# -----------------------------------------------------------------------------------------
from utilities.transaction_base import TransactionBase
class DocType(TransactionBase):
def __init__(self, doc, doclist=[]):
self.doc = doc
self.doclist = doclist
def autoname(self):
self.doc.name = make_autoname(self.doc.naming_series + '.######')
#check if maintenance schedule already generated
#============================================
def check_maintenance_visit(self):
nm = sql("select t1.name from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2 where t2.parent=t1.name and t2.prevdoc_docname=%s and t1.docstatus=1 and t1.completion_status='Fully Completed'", self.doc.name)
nm = nm and nm[0][0] or ''
if not nm:
return 'No'
def on_submit(self):
if session['user'] != 'Guest':
if not self.doc.allocated_to:
msgprint("Please select service person name whom you want to assign this issue")
raise Exception
def validate(self):
if session['user'] != 'Guest' and not self.doc.customer:
msgprint("Please select Customer from whom issue is raised")
raise Exception
def on_cancel(self):
lst = sql("select t1.name from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2 where t2.parent = t1.name and t2.prevdoc_docname = '%s' and t1.docstatus!=2"%(self.doc.name))
if lst:
lst1 = ','.join([x[0] for x in lst])
msgprint("Maintenance Visit No. "+lst1+" already created against this customer issue. So can not be Cancelled")
raise Exception
else:
set(self.doc, 'status', 'Cancelled')
def on_update(self):
pass

View File

@@ -0,0 +1,664 @@
# DocType, Customer Issue
[
# These values are common in all dictionaries
{
'creation': '2012-04-13 11:56:39',
'docstatus': 0,
'modified': '2012-05-18 17:04:36',
'modified_by': u'Administrator',
'owner': u'harshada@webnotestech.com'
},
# These values are common for all DocType
{
'_last_update': u'1325570647',
'colour': u'White:FFF',
'default_print_format': u'Standard',
'doctype': 'DocType',
'is_submittable': 1,
'module': u'Support',
'name': '__common__',
'search_fields': u'status,customer,customer_name,allocated_to,allocated_on, territory',
'section_style': u'Tabbed',
'server_code_error': u' ',
'show_in_menu': 0,
'subject': u'%(complaint)s By %(complaint_raised_by)s on %(issue_date)s',
'tag_fields': u'status',
'version': 1
},
# These values are common for all DocField
{
'doctype': u'DocField',
'name': '__common__',
'parent': u'Customer Issue',
'parentfield': u'fields',
'parenttype': u'DocType'
},
# These values are common for all DocPerm
{
'doctype': u'DocPerm',
'name': '__common__',
'parent': u'Customer Issue',
'parentfield': u'permissions',
'parenttype': u'DocType',
'read': 1
},
# DocType, Customer Issue
{
'doctype': 'DocType',
'name': u'Customer Issue'
},
# DocPerm
{
'create': 1,
'doctype': u'DocPerm',
'permlevel': 0,
'role': u'Guest',
'write': 1
},
# DocPerm
{
'amend': 1,
'cancel': 1,
'create': 1,
'doctype': u'DocPerm',
'permlevel': 0,
'role': u'System Manager',
'submit': 1,
'write': 1
},
# DocPerm
{
'doctype': u'DocPerm',
'permlevel': 1,
'role': u'System Manager'
},
# DocPerm
{
'amend': 1,
'cancel': 1,
'create': 1,
'doctype': u'DocPerm',
'permlevel': 0,
'role': u'Maintenance Manager',
'submit': 1,
'write': 1
},
# DocPerm
{
'doctype': u'DocPerm',
'permlevel': 1,
'role': u'Maintenance Manager'
},
# DocPerm
{
'amend': 1,
'cancel': 1,
'create': 1,
'doctype': u'DocPerm',
'permlevel': 0,
'role': u'Maintenance User',
'submit': 1,
'write': 1
},
# DocPerm
{
'doctype': u'DocPerm',
'permlevel': 1,
'role': u'Maintenance User'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'basic_info',
'fieldtype': u'Section Break',
'label': u'Basic Info',
'oldfieldtype': u'Section Break',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'naming_series',
'fieldtype': u'Select',
'in_filter': 0,
'label': u'Series',
'no_copy': 1,
'oldfieldname': u'naming_series',
'oldfieldtype': u'Select',
'options': u'\nCI/2010-2011/',
'permlevel': 0,
'reqd': 1,
'search_index': 0
},
# DocField
{
'default': u'Today',
'doctype': u'DocField',
'fieldname': u'complaint_date',
'fieldtype': u'Date',
'in_filter': 1,
'label': u'Issue Date',
'oldfieldname': u'complaint_date',
'oldfieldtype': u'Date',
'permlevel': 0,
'reqd': 1,
'search_index': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'column_break0',
'fieldtype': u'Column Break',
'oldfieldtype': u'Column Break',
'permlevel': 0,
'width': u'50%'
},
# DocField
{
'colour': u'White:FFF',
'doctype': u'DocField',
'fieldname': u'customer',
'fieldtype': u'Link',
'in_filter': 1,
'label': u'Customer',
'oldfieldname': u'customer',
'oldfieldtype': u'Link',
'options': u'Customer',
'permlevel': 0,
'print_hide': 1,
'reqd': 1,
'search_index': 1,
'trigger': u'Client'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'customer_address',
'fieldtype': u'Link',
'label': u'Customer Address',
'options': u'Address',
'permlevel': 0,
'print_hide': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'contact_person',
'fieldtype': u'Link',
'label': u'Contact Person',
'options': u'Contact',
'permlevel': 0,
'print_hide': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'issue_details',
'fieldtype': u'Section Break',
'label': u'Issue Details',
'oldfieldtype': u'Section Break',
'options': u'Simple',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'serial_no',
'fieldtype': u'Link',
'label': u'Serial No',
'options': u'Serial No',
'permlevel': 0,
'trigger': u'Client'
},
# DocField
{
'colour': u'White:FFF',
'doctype': u'DocField',
'fieldname': u'item_code',
'fieldtype': u'Link',
'in_filter': 1,
'label': u'Item Code',
'oldfieldname': u'item_code',
'oldfieldtype': u'Link',
'options': u'Item',
'permlevel': 0,
'reqd': 0,
'search_index': 1,
'trigger': u'Client'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'complaint',
'fieldtype': u'Small Text',
'label': u'Issue',
'no_copy': 1,
'oldfieldname': u'complaint',
'oldfieldtype': u'Small Text',
'permlevel': 0,
'reqd': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'column_break1',
'fieldtype': u'Column Break',
'oldfieldtype': u'Column Break',
'permlevel': 0,
'width': u'50%'
},
# DocField
{
'colour': u'White:FFF',
'depends_on': u'eval:doc.item_code',
'doctype': u'DocField',
'fieldname': u'item_name',
'fieldtype': u'Data',
'label': u'Item Name',
'oldfieldname': u'item_name',
'oldfieldtype': u'Data',
'permlevel': 1
},
# DocField
{
'colour': u'White:FFF',
'depends_on': u'eval:doc.item_code',
'doctype': u'DocField',
'fieldname': u'description',
'fieldtype': u'Small Text',
'label': u'Description',
'oldfieldname': u'description',
'oldfieldtype': u'Small Text',
'permlevel': 1,
'width': u'300px'
},
# DocField
{
'colour': u'White:FFF',
'doctype': u'DocField',
'fieldname': u'warranty_amc_status',
'fieldtype': u'Select',
'hidden': 0,
'in_filter': 1,
'label': u'Warranty / AMC Status',
'options': u'\nUnder Warranty\nOut of Warranty\nUnder AMC\nOut of AMC',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'warranty_expiry_date',
'fieldtype': u'Date',
'label': u'Warranty Expiry Date',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'amc_expiry_date',
'fieldtype': u'Date',
'label': u'AMC Expiry Date',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'resolution_section',
'fieldtype': u'Section Break',
'label': u'Resolution',
'oldfieldtype': u'Section Break',
'options': u'Simple',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'allocated_on',
'fieldtype': u'Date',
'in_filter': 1,
'label': u'Allocated On',
'oldfieldname': u'allocated_on',
'oldfieldtype': u'Date',
'permlevel': 0,
'search_index': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'allocated_to',
'fieldtype': u'Link',
'in_filter': 1,
'label': u'Allocated To',
'oldfieldname': u'allocated_to',
'oldfieldtype': u'Link',
'options': u'Profile',
'permlevel': 0,
'search_index': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'column_break2',
'fieldtype': u'Column Break',
'oldfieldtype': u'Column Break',
'permlevel': 0,
'width': u'50%'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'resolution_date',
'fieldtype': u'Date',
'in_filter': 1,
'label': u'Resolution Date',
'no_copy': 1,
'oldfieldname': u'resolution_date',
'oldfieldtype': u'Date',
'permlevel': 0,
'search_index': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'resolved_by',
'fieldtype': u'Link',
'in_filter': 1,
'label': u'Resolved By',
'no_copy': 1,
'oldfieldname': u'resolved_by',
'oldfieldtype': u'Link',
'options': u'Sales Person',
'permlevel': 0,
'search_index': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'resolution_details',
'fieldtype': u'Text',
'label': u'Resolution Details',
'no_copy': 1,
'oldfieldname': u'resolution_details',
'oldfieldtype': u'Text',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'contact_info',
'fieldtype': u'Section Break',
'label': u'Contact Info',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'col_break3',
'fieldtype': u'Column Break',
'permlevel': 0,
'width': u'50%'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'customer_name',
'fieldtype': u'Data',
'label': u'Customer Name',
'permlevel': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'customer_group',
'fieldtype': u'Link',
'label': u'Customer Group',
'options': u'Customer Group',
'permlevel': 0,
'print_hide': 1,
'reqd': 0
},
# DocField
{
'colour': u'White:FFF',
'doctype': u'DocField',
'fieldname': u'territory',
'fieldtype': u'Link',
'in_filter': 1,
'label': u'Territory',
'oldfieldname': u'territory',
'oldfieldtype': u'Link',
'options': u'Territory',
'permlevel': 0,
'print_hide': 1,
'reqd': 0,
'search_index': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'address_display',
'fieldtype': u'Small Text',
'label': u'Address',
'permlevel': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'col_break4',
'fieldtype': u'Column Break',
'permlevel': 0,
'width': u'50%'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'contact_display',
'fieldtype': u'Small Text',
'label': u'Contact',
'permlevel': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'contact_mobile',
'fieldtype': u'Data',
'label': u'Mobile No',
'permlevel': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'contact_email',
'fieldtype': u'Data',
'label': u'Contact Email',
'permlevel': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'service_address',
'fieldtype': u'Small Text',
'label': u'Service Address',
'oldfieldname': u'service_address',
'oldfieldtype': u'Small Text',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'more_info',
'fieldtype': u'Section Break',
'label': u'More Info',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'col_break5',
'fieldtype': u'Column Break',
'permlevel': 0,
'width': u'50%'
},
# DocField
{
'colour': u'White:FFF',
'doctype': u'DocField',
'fieldname': u'company',
'fieldtype': u'Link',
'in_filter': 1,
'label': u'Company',
'oldfieldname': u'company',
'oldfieldtype': u'Link',
'options': u'Company',
'permlevel': 0,
'print_hide': 1,
'reqd': 1,
'search_index': 1,
'trigger': u'Client'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'fiscal_year',
'fieldtype': u'Select',
'in_filter': 1,
'label': u'Fiscal Year',
'oldfieldname': u'fiscal_year',
'oldfieldtype': u'Select',
'options': u'link:Fiscal Year',
'permlevel': 0,
'print_hide': 1,
'reqd': 1,
'search_index': 1
},
# DocField
{
'colour': u'White:FFF',
'default': u'Open',
'doctype': u'DocField',
'fieldname': u'status',
'fieldtype': u'Select',
'in_filter': 1,
'label': u'Status',
'no_copy': 1,
'oldfieldname': u'status',
'oldfieldtype': u'Select',
'options': u'\nOpen\nClosed\nWork In Progress\nCancelled',
'permlevel': 0,
'reqd': 1,
'search_index': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'col_break6',
'fieldtype': u'Column Break',
'permlevel': 0,
'width': u'50%'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'complaint_raised_by',
'fieldtype': u'Data',
'label': u'Raised By',
'oldfieldname': u'complaint_raised_by',
'oldfieldtype': u'Data',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'from_company',
'fieldtype': u'Data',
'label': u'From Company',
'oldfieldname': u'from_company',
'oldfieldtype': u'Data',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'amended_from',
'fieldtype': u'Data',
'hidden': 1,
'label': u'Amended From',
'no_copy': 1,
'oldfieldname': u'amended_from',
'oldfieldtype': u'Data',
'permlevel': 0,
'print_hide': 1,
'width': u'150px'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'amendment_date',
'fieldtype': u'Date',
'hidden': 1,
'label': u'Amendment Date',
'no_copy': 1,
'oldfieldname': u'amendment_date',
'oldfieldtype': u'Date',
'permlevel': 0,
'print_hide': 1,
'width': u'100px'
}
]

View File

@@ -0,0 +1,60 @@
// render
wn.doclistviews['Customer Issue'] = wn.views.ListView.extend({
me: this,
init: function(d) {
this._super(d)
this.fields = this.fields.concat([
"`tabCustomer Issue`.customer",
"`tabCustomer Issue`.serial_no",
"`tabCustomer Issue`.item_name",
"`tabCustomer Issue`.complaint",
"`tabCustomer Issue`.status",
]);
this.stats = this.stats.concat(['status', 'company']);
//this.show_hide_check_column();
},
prepare_data: function(data) {
this._super(data);
if(data.status=='Open') {
data.label_type = 'important';
} else if(data.status=='Closed') {
data.label_type = 'success';
} else if(data.status=='Cancelled') {
data.label_type = 'info';
} else if(data.status=='Work In Progress') {
data.label_type = 'info';
data.status = 'WIP';
}
data.status_html = repl(
'<span class="label label-%(label_type)s">%(status)s</span>', data);
var a = $(data.status_html).click(function() {
me.set_filter('status', $(this).text());
});
var concat_list = [data.customer];
data.serial_no && concat_list.push(data.serial_no);
data.complaint && concat_list.push(data.complaint);
data.complaint = concat_list.join(" | ");
// description
if(data.complaint && data.complaint.length > 50) {
data.complaint = '<span title="'+data.complaint+'">' +
data.complaint.substr(0,50) + '...</span>';
}
},
columns: [
{width: '3%', content: 'check'},
{width: '5%', content: 'avatar'},
{width: '3%', content: 'docstatus'},
{width: '20%', content: 'name'},
{width: '10%', content: 'status_html'},
{width: '47%', content: 'complaint+tags', css: {color:'#777'}},
{width: '12%', content: 'modified',
css: {'text-align': 'right', 'color':'#777'}}
]
});

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1,133 @@
// ERPNext - web based ERP (http://erpnext.com)
// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
cur_frm.cscript.onload = function(doc, dt, dn) {
if(!doc.status) set_multiple(dt,dn,{status:'Draft'});
if(doc.__islocal){
set_multiple(dt,dn,{transaction_date:get_today()});
hide_field(['customer_address','contact_person','customer_name','address_display','contact_display','contact_mobile','contact_email','territory','customer_group']);
}
}
//customer
cur_frm.cscript.customer = function(doc,dt,dn) {
var callback = function(r,rt) {
var doc = locals[cur_frm.doctype][cur_frm.docname];
cur_frm.refresh();
}
if(doc.customer) $c_obj(make_doclist(doc.doctype, doc.name), 'get_default_customer_address', '', callback);
if(doc.customer) unhide_field(['customer_address','contact_person','customer_name','address_display','contact_display','contact_mobile','contact_email','territory','customer_group']);
}
cur_frm.cscript.customer_address = cur_frm.cscript.contact_person = function(doc,dt,dn) {
if(doc.customer) get_server_fields('get_customer_address', JSON.stringify({customer: doc.customer, address: doc.customer_address, contact: doc.contact_person}),'', doc, dt, dn, 1);
}
cur_frm.fields_dict.customer_address.on_new = function(dn) {
locals['Address'][dn].customer = locals[cur_frm.doctype][cur_frm.docname].customer;
locals['Address'][dn].customer_name = locals[cur_frm.doctype][cur_frm.docname].customer_name;
}
cur_frm.fields_dict.contact_person.on_new = function(dn) {
locals['Contact'][dn].customer = locals[cur_frm.doctype][cur_frm.docname].customer;
locals['Contact'][dn].customer_name = locals[cur_frm.doctype][cur_frm.docname].customer_name;
}
cur_frm.fields_dict['customer_address'].get_query = function(doc, cdt, cdn) {
return 'SELECT name,address_line1,city FROM tabAddress WHERE customer = "'+ doc.customer +'" AND docstatus != 2 AND name LIKE "%s" ORDER BY name ASC LIMIT 50';
}
cur_frm.fields_dict['contact_person'].get_query = function(doc, cdt, cdn) {
return 'SELECT name,CONCAT(first_name," ",ifnull(last_name,"")) As FullName,department,designation FROM tabContact WHERE customer = "'+ doc.customer +'" AND docstatus != 2 AND name LIKE "%s" ORDER BY name ASC LIMIT 50';
}
//
cur_frm.fields_dict['item_maintenance_detail'].grid.get_field('item_code').get_query = function(doc, cdt, cdn) {
return 'SELECT tabItem.name,tabItem.item_name,tabItem.description FROM tabItem WHERE tabItem.is_service_item="Yes" AND tabItem.docstatus != 2 AND tabItem.%(key)s LIKE "%s" LIMIT 50';
}
// Get Items based on SO Selected
cur_frm.cscript.get_items = function(doc, dt, dn) {
var callback = function(r,rt) {
unhide_field(['customer_address','contact_person','customer_name','address_display','contact_display','contact_mobile','contact_email','territory','customer_group']);
cur_frm.refresh();
}
get_server_fields('pull_sales_order_detail','','',doc, dt, dn,1,callback);
}
cur_frm.cscript.item_code = function(doc, cdt, cdn) {
var fname = cur_frm.cscript.fname;
var d = locals[cdt][cdn];
if (d.item_code) {
get_server_fields('get_item_details',d.item_code, 'item_maintenance_detail',doc,cdt,cdn,1);
}
}
/*
cur_frm.fields_dict['contact_person'].get_query = function(doc, cdt, cdn) {
return 'SELECT `tabContact`.contact_name FROM `tabContact` WHERE `tabContact`.is_customer = 1 AND `tabContact`.customer = "'+ doc.customer+'" AND `tabContact`.contact_name LIKE "%s" ORDER BY `tabContact`.contact_name ASC LIMIT 50';
}
cur_frm.cscript.customer = function(doc, cdt, cdn) {
get_server_fields('get_customer_details','','',doc, cdt, cdn, 1);
}
*/
cur_frm.fields_dict['sales_order_no'].get_query = function(doc) {
doc = locals[this.doctype][this.docname];
var cond = '';
if(doc.customer) {
cond = '`tabSales Order`.customer = "'+doc.customer+'" AND';
}
return repl('SELECT DISTINCT `tabSales Order`.name FROM `tabSales Order`, `tabSales Order Item`, `tabItem` WHERE `tabSales Order`.company = "%(company)s" AND `tabSales Order`.docstatus = 1 AND `tabSales Order Item`.parent = `tabSales Order`.name AND `tabSales Order Item`.item_code = `tabItem`.name AND `tabItem`.is_service_item = "Yes" AND %(cond)s `tabSales Order`.name LIKE "%s" ORDER BY `tabSales Order`.name DESC LIMIT 50', {company:doc.company, cond:cond});
}
cur_frm.cscript.periodicity = function(doc, cdt, cdn){
var d = locals[cdt][cdn];
if(d.start_date && d.end_date){
arg = {}
arg.start_date = d.start_date;
arg.end_date = d.end_date;
arg.periodicity = d.periodicity;
get_server_fields('get_no_of_visits',docstring(arg),'item_maintenance_detail',doc, cdt, cdn, 1);
}
else{
msgprint("Please enter Start Date and End Date");
}
}
cur_frm.cscript.generate_schedule = function(doc, cdt, cdn) {
if (!doc.__islocal) {
$c('runserverobj', args={'method':'generate_schedule', 'docs':compress_doclist(make_doclist(cdt,cdn))},
function(r,rt){
refresh_field('maintenance_schedule_detail');
}
);
} else {
alert("Please save the document before generating maintenance schedule");
}
}
//get query select Territory
//=======================================================================================================================
cur_frm.fields_dict['territory'].get_query = function(doc,cdt,cdn) {
return 'SELECT `tabTerritory`.`name`,`tabTerritory`.`parent_territory` FROM `tabTerritory` WHERE `tabTerritory`.`is_group` = "No" AND `tabTerritory`.`docstatus`!= 2 AND `tabTerritory`.%(key)s LIKE "%s" ORDER BY `tabTerritory`.`name` ASC LIMIT 50';
}

View File

@@ -0,0 +1,348 @@
# ERPNext - web based ERP (http://erpnext.com)
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Please edit this list and import only required elements
from __future__ import unicode_literals
import webnotes
from webnotes.utils import add_days, add_months, add_years, cint, cstr, date_diff, default_fields, flt, fmt_money, formatdate, generate_hash, getTraceback, get_defaults, get_first_day, get_last_day, getdate, has_common, month_name, now, nowdate, replace_newlines, sendmail, set_default, str_esc_quote, user_format, validate_email_add
from webnotes.model import db_exists
from webnotes.model.doc import Document, addchild, getchildren, make_autoname
from webnotes.model.doclist import getlist, copy_doclist
from webnotes.model.code import get_obj, get_server_obj, run_server_obj, updatedb, check_syntax
from webnotes import session, form, is_testing, msgprint, errprint
set = webnotes.conn.set
sql = webnotes.conn.sql
get_value = webnotes.conn.get_value
in_transaction = webnotes.conn.in_transaction
convert_to_lists = webnotes.conn.convert_to_lists
# -----------------------------------------------------------------------------------------
from utilities.transaction_base import TransactionBase
class DocType(TransactionBase):
def __init__(self, doc, doclist=[]):
self.doc = doc
self.doclist = doclist
# pull sales order details
#--------------------------
def pull_sales_order_detail(self):
self.doclist = self.doc.clear_table(self.doclist, 'item_maintenance_detail')
self.doclist = self.doc.clear_table(self.doclist, 'maintenance_schedule_detail')
self.doclist = get_obj('DocType Mapper', 'Sales Order-Maintenance Schedule').dt_map('Sales Order', 'Maintenance Schedule', self.doc.sales_order_no, self.doc, self.doclist, "[['Sales Order', 'Maintenance Schedule'],['Sales Order Item', 'Maintenance Schedule Item']]")
#pull item details
#-------------------
def get_item_details(self, item_code):
item = sql("select item_name, description from `tabItem` where name = '%s'" %(item_code), as_dict=1)
ret = {
'item_name': item and item[0]['item_name'] or '',
'description' : item and item[0]['description'] or ''
}
return ret
# generate maintenance schedule
#-------------------------------------
def generate_schedule(self):
import datetime
self.doclist = self.doc.clear_table(self.doclist, 'maintenance_schedule_detail')
count = 0
sql("delete from `tabMaintenance Schedule Detail` where parent='%s'" %(self.doc.name))
for d in getlist(self.doclist, 'item_maintenance_detail'):
self.validate_maintenance_detail()
s_list =[]
s_list = self.create_schedule_list(d.start_date, d.end_date, d.no_of_visits)
for i in range(d.no_of_visits):
child = addchild(self.doc,'maintenance_schedule_detail','Maintenance Schedule Detail',1,self.doclist)
child.item_code = d.item_code
child.item_name = d.item_name
child.scheduled_date = s_list[i].strftime('%Y-%m-%d')
if d.serial_no:
child.serial_no = d.serial_no
child.idx = count
count = count+1
child.incharge_name = d.incharge_name
child.save(1)
self.on_update()
def on_submit(self):
if not getlist(self.doclist, 'maintenance_schedule_detail'):
msgprint("Please click on 'Generate Schedule' to get schedule")
raise Exception
self.check_serial_no_added()
self.validate_serial_no_warranty()
self.validate_schedule()
email_map ={}
for d in getlist(self.doclist, 'item_maintenance_detail'):
if d.serial_no:
self.update_amc_date(d.serial_no, d.end_date)
if d.incharge_name not in email_map:
e = sql("select email_id, name from `tabSales Person` where name='%s' " %(d.incharge_name),as_dict=1)[0]
email_map[d.incharge_name] = (e['email_id'])
scheduled_date =sql("select scheduled_date from `tabMaintenance Schedule Detail` \
where incharge_name='%s' and item_code='%s' and parent='%s' " %(d.incharge_name, \
d.item_code, self.doc.name), as_dict=1)
for key in scheduled_date:
if email_map[d.incharge_name]:
self.add_calender_event(key["scheduled_date"],email_map[d.incharge_name],d.item_code)
set(self.doc, 'status', 'Submitted')
def add_calender_event(self,scheduled_date,incharge_email,item_code):
""" Add calendar event for Maintenece Schedule in calendar of Allocated person"""
event = Document('Event')
event.owner = incharge_email
event.description = "Reference:%s, Item Code:%s and Customer: %s" %(self.doc.name, item_code, self.doc.customer)
event.event_date = scheduled_date
event.event_hour = '10:00'
event.event_type = 'Private'
event.ref_type = 'Maintenance Schedule'
event.ref_name = self.doc.name
event.save(1)
#get schedule dates
#----------------------
def create_schedule_list(self, start_date, end_date, no_of_visit):
schedule_list = []
start_date1 = start_date
date_diff = (getdate(end_date) - getdate(start_date)).days
add_by = date_diff/no_of_visit
#schedule_list.append(start_date1)
while(getdate(start_date1) < getdate(end_date)):
start_date1 = add_days(start_date1, add_by)
if len(schedule_list) < no_of_visit:
schedule_list.append(getdate(start_date1))
return schedule_list
#validate date range and periodicity selected
#-------------------------------------------------
def validate_period(self, arg):
arg1 = eval(arg)
if getdate(arg1['start_date']) >= getdate(arg1['end_date']):
msgprint("Start date should be less than end date ")
raise Exception
period = (getdate(arg1['end_date'])-getdate(arg1['start_date'])).days+1
if (arg1['periodicity']=='Yearly' or arg1['periodicity']=='Half Yearly' or arg1['periodicity']=='Quarterly') and period<365:
msgprint(cstr(arg1['periodicity'])+ " periodicity can be set for period of atleast 1 year or more only")
raise Exception
elif arg1['periodicity']=='Monthly' and period<30:
msgprint("Monthly periodicity can be set for period of atleast 1 month or more")
raise Exception
elif arg1['periodicity']=='Weekly' and period<7:
msgprint("Weekly periodicity can be set for period of atleast 1 week or more")
raise Exception
#get count on the basis of periodicity selected
#----------------------------------------------------
def get_no_of_visits(self, arg):
arg1 = eval(arg)
start_date = arg1['start_date']
self.validate_period(arg)
period = (getdate(arg1['end_date'])-getdate(arg1['start_date'])).days+1
count =0
if arg1['periodicity'] == 'Weekly':
count = period/7
elif arg1['periodicity'] == 'Monthly':
count = period/30
elif arg1['periodicity'] == 'Quarterly':
count = period/91
elif arg1['periodicity'] == 'Half Yearly':
count = period/182
elif arg1['periodicity'] == 'Yearly':
count = period/365
ret = {'no_of_visits':count}
return ret
def validate_maintenance_detail(self):
if not getlist(self.doclist, 'item_maintenance_detail'):
msgprint("Please enter Maintaince Details first")
raise Exception
for d in getlist(self.doclist, 'item_maintenance_detail'):
if not d.item_code:
msgprint("Please select item code")
raise Exception
elif not d.start_date or not d.end_date:
msgprint("Please select Start Date and End Date for item "+d.item_code)
raise Exception
elif not d.no_of_visits:
msgprint("Please mention no of visits required")
raise Exception
elif not d.incharge_name:
msgprint("Please select Incharge Person's name")
raise Exception
if getdate(d.start_date) >= getdate(d.end_date):
msgprint("Start date should be less than end date for item "+d.item_code)
raise Exception
#check if maintenance schedule already created against same sales order
#-----------------------------------------------------------------------------------
def validate_sales_order(self):
for d in getlist(self.doclist, 'item_maintenance_detail'):
if d.prevdoc_docname:
chk = sql("select t1.name from `tabMaintenance Schedule` t1, `tabMaintenance Schedule Item` t2 where t2.parent=t1.name and t2.prevdoc_docname=%s and t1.docstatus=1", d.prevdoc_docname)
if chk:
msgprint("Maintenance Schedule against "+d.prevdoc_docname+" already exist")
raise Exception
# Validate values with reference document
#----------------------------------------
def validate_reference_value(self):
get_obj('DocType Mapper', 'Sales Order-Maintenance Schedule', with_children = 1).validate_reference_value(self, self.doc.name)
def validate_serial_no(self):
for d in getlist(self.doclist, 'item_maintenance_detail'):
cur_s_no=[]
if d.serial_no:
cur_serial_no = d.serial_no.replace(' ', '')
cur_s_no = cur_serial_no.split(',')
for x in cur_s_no:
chk = sql("select name, status from `tabSerial No` where docstatus!=2 and name=%s", (x))
chk1 = chk and chk[0][0] or ''
status = chk and chk[0][1] or ''
if not chk1:
msgprint("Serial no "+x+" does not exist in system.")
raise Exception
else:
if status=='In Store' or status=='Note in Use' or status=='Scrapped':
msgprint("Serial no "+x+" is '"+status+"'")
raise Exception
def validate(self):
self.validate_maintenance_detail()
self.validate_sales_order()
if self.doc.sales_order_no:
self.validate_reference_value()
self.validate_serial_no()
self.validate_start_date()
# validate that maintenance start date can not be before serial no delivery date
#-------------------------------------------------------------------------------------------
def validate_start_date(self):
for d in getlist(self.doclist, 'item_maintenance_detail'):
if d.serial_no:
cur_serial_no = d.serial_no.replace(' ', '')
cur_s_no = cur_serial_no.split(',')
for x in cur_s_no:
dt = sql("select delivery_date from `tabSerial No` where name = %s", x)
dt = dt and dt[0][0] or ''
if dt:
if dt > getdate(d.start_date):
msgprint("Maintenance start date can not be before delivery date "+dt.strftime('%Y-%m-%d')+" for serial no "+x)
raise Exception
#update amc expiry date in serial no
#------------------------------------------
def update_amc_date(self,serial_no,amc_end_date):
#get current list of serial no
cur_serial_no = serial_no.replace(' ', '')
cur_s_no = cur_serial_no.split(',')
for x in cur_s_no:
sql("update `tabSerial No` set amc_expiry_date = '%s', maintenance_status = 'Under AMC' where name = '%s'"% (amc_end_date,x))
def on_update(self):
set(self.doc, 'status', 'Draft')
#validate that new maintenance start date does not clash with existing mntc end date
#-------------------------------------------------------------------------------------------------
def validate_serial_no_warranty(self):
for d in getlist(self.doclist, 'item_maintenance_detail'):
if d.serial_no:
dt = sql("select warranty_expiry_date, amc_expiry_date from `tabSerial No` where name = %s", d.serial_no, as_dict=1)
if dt[0]['warranty_expiry_date']:
if dt[0]['warranty_expiry_date'] >= getdate(d.start_date):
msgprint("Serial no "+d.serial_no+" for item "+d.item_code+" is already under warranty till "+(dt[0]['warranty_expiry_date']).strftime('%Y-%m-%d')+". You can schedule AMC start date after "+(dt[0]['warranty_expiry_date']).strftime('%Y-%m-%d'))
raise Exception
if dt[0]['amc_expiry_date']:
if dt[0]['amc_expiry_date'] >= getdate(d.start_date):
msgprint("Serial no "+d.serial_no+" for item "+d.item_code+" is already under AMC till "+(dt[0]['amc_expiry_date']).strftime('%Y-%m-%d')+". You can schedule new AMC start date after "+(dt[0]['amc_expiry_date']).strftime('%Y-%m-%d'))
raise Exception
#validate if schedule generated for all items
#-------------------------------------------------
def validate_schedule(self):
item_lst1 =[]
item_lst2 =[]
for d in getlist(self.doclist, 'item_maintenance_detail'):
if d.item_code not in item_lst1:
item_lst1.append(d.item_code)
for m in getlist(self.doclist, 'maintenance_schedule_detail'):
if m.item_code not in item_lst2:
item_lst2.append(m.item_code)
if len(item_lst1) != len(item_lst2):
msgprint("Maintenance Schedule is not generated for all the items. Please click on 'Generate Schedule'")
raise Exception
else:
for x in item_lst1:
if x not in item_lst2:
msgprint("Maintenance Schedule is not generated for item "+x+". Please click on 'Generate Schedule'")
raise Exception
#check if serial no present in item maintenance table
#-----------------------------------------------------------
def check_serial_no_added(self):
serial_present =[]
for d in getlist(self.doclist, 'item_maintenance_detail'):
if d.serial_no:
serial_present.append(d.item_code)
for m in getlist(self.doclist, 'maintenance_schedule_detail'):
if serial_present:
if m.item_code in serial_present and not m.serial_no:
msgprint("Please click on 'Generate Schedule' to fetch serial no added for item "+m.item_code)
raise Exception
def on_cancel(self):
for d in getlist(self.doclist, 'item_maintenance_detail'):
if d.serial_no:
self.update_amc_date(d.serial_no, '')
set(self.doc, 'status', 'Cancelled')
sql("delete from `tabEvent` where ref_type='Maintenance Schedule' and ref_name='%s' " %(self.doc.name))
def on_trash(self):
sql("delete from `tabEvent` where ref_type='Maintenance Schedule' and ref_name='%s' " %(self.doc.name))

View File

@@ -0,0 +1,399 @@
# DocType, Maintenance Schedule
[
# These values are common in all dictionaries
{
'creation': '2012-03-27 14:36:41',
'docstatus': 0,
'modified': '2012-03-27 14:45:49',
'modified_by': u'Administrator',
'owner': u'Administrator'
},
# These values are common for all DocType
{
'_last_update': u'1322549701',
'autoname': u'MS.#####',
'colour': u'White:FFF',
'default_print_format': u'Standard',
'doctype': 'DocType',
'is_submittable': 1,
'module': u'Support',
'name': '__common__',
'search_fields': u'status,customer,customer_name, sales_order_no',
'section_style': u'Simple',
'server_code_error': u' ',
'show_in_menu': 0,
'version': 156
},
# These values are common for all DocField
{
'doctype': u'DocField',
'name': '__common__',
'parent': u'Maintenance Schedule',
'parentfield': u'fields',
'parenttype': u'DocType'
},
# These values are common for all DocPerm
{
'doctype': u'DocPerm',
'name': '__common__',
'parent': u'Maintenance Schedule',
'parentfield': u'permissions',
'parenttype': u'DocType',
'read': 1
},
# DocType, Maintenance Schedule
{
'doctype': 'DocType',
'name': u'Maintenance Schedule'
},
# DocPerm
{
'amend': 1,
'cancel': 1,
'create': 1,
'doctype': u'DocPerm',
'permlevel': 0,
'role': u'System Manager',
'submit': 1,
'write': 1
},
# DocPerm
{
'doctype': u'DocPerm',
'permlevel': 1,
'role': u'System Manager'
},
# DocPerm
{
'amend': 1,
'cancel': 1,
'create': 1,
'doctype': u'DocPerm',
'permlevel': 0,
'role': u'Maintenance Manager',
'submit': 1,
'write': 1
},
# DocPerm
{
'doctype': u'DocPerm',
'permlevel': 1,
'role': u'Maintenance Manager'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'customer_details',
'fieldtype': u'Section Break',
'label': u'Customer Details',
'oldfieldtype': u'Section Break',
'options': u'Simple',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'column_break0',
'fieldtype': u'Column Break',
'oldfieldtype': u'Column Break',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'customer',
'fieldtype': u'Link',
'in_filter': 1,
'label': u'Customer',
'oldfieldname': u'customer',
'oldfieldtype': u'Link',
'options': u'Customer',
'permlevel': 0,
'print_hide': 1,
'reqd': 1,
'search_index': 1,
'trigger': u'Client'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'customer_address',
'fieldtype': u'Link',
'label': u'Customer Address',
'options': u'Address',
'permlevel': 0,
'print_hide': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'contact_person',
'fieldtype': u'Link',
'label': u'Contact Person',
'options': u'Contact',
'permlevel': 0,
'print_hide': 1
},
# DocField
{
'colour': u'White:FFF',
'doctype': u'DocField',
'fieldname': u'customer_name',
'fieldtype': u'Data',
'in_filter': 1,
'label': u'Name',
'oldfieldname': u'customer_name',
'oldfieldtype': u'Data',
'permlevel': 1,
'reqd': 0,
'search_index': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'address_display',
'fieldtype': u'Small Text',
'label': u'Address',
'permlevel': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'contact_display',
'fieldtype': u'Small Text',
'label': u'Contact',
'permlevel': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'contact_mobile',
'fieldtype': u'Text',
'label': u'Mobile No',
'permlevel': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'contact_email',
'fieldtype': u'Text',
'label': u'Contact Email',
'permlevel': 1,
'print_hide': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'column_break1',
'fieldtype': u'Column Break',
'oldfieldtype': u'Column Break',
'permlevel': 0
},
# DocField
{
'colour': u'White:FFF',
'doctype': u'DocField',
'fieldname': u'transaction_date',
'fieldtype': u'Date',
'in_filter': 1,
'label': u'Transaction Date',
'oldfieldname': u'transaction_date',
'oldfieldtype': u'Date',
'permlevel': 0,
'reqd': 1,
'search_index': 0
},
# DocField
{
'colour': u'White:FFF',
'default': u'Draft',
'doctype': u'DocField',
'fieldname': u'status',
'fieldtype': u'Select',
'in_filter': 1,
'label': u'Status',
'no_copy': 1,
'oldfieldname': u'status',
'oldfieldtype': u'Select',
'options': u'\nDraft\nSubmitted\nCancelled',
'permlevel': 1,
'reqd': 1,
'search_index': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'amended_from',
'fieldtype': u'Data',
'label': u'Amended From',
'no_copy': 1,
'oldfieldname': u'amended_from',
'oldfieldtype': u'Data',
'permlevel': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'amendment_date',
'fieldtype': u'Date',
'hidden': 1,
'label': u'Amendment Date',
'no_copy': 1,
'oldfieldname': u'amendment_date',
'oldfieldtype': u'Date',
'permlevel': 1,
'print_hide': 1,
'report_hide': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'company',
'fieldtype': u'Link',
'in_filter': 1,
'label': u'Company',
'oldfieldname': u'company',
'oldfieldtype': u'Link',
'options': u'Company',
'permlevel': 0,
'reqd': 1,
'search_index': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'territory',
'fieldtype': u'Link',
'in_filter': 1,
'label': u'Territory',
'oldfieldname': u'territory',
'oldfieldtype': u'Link',
'options': u'Territory',
'permlevel': 0,
'reqd': 1,
'search_index': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'customer_group',
'fieldtype': u'Link',
'label': u'Customer Group',
'options': u'Customer Group',
'permlevel': 0,
'reqd': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'items',
'fieldtype': u'Section Break',
'label': u'Items',
'oldfieldtype': u'Section Break',
'options': u'Simple',
'permlevel': 0
},
# DocField
{
'colour': u'White:FFF',
'doctype': u'DocField',
'fieldname': u'sales_order_no',
'fieldtype': u'Link',
'in_filter': 1,
'label': u'Sales Order No',
'oldfieldname': u'sales_order_no',
'oldfieldtype': u'Link',
'options': u'Sales Order',
'permlevel': 0,
'search_index': 1,
'trigger': u'Client'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'get_items',
'fieldtype': u'Button',
'label': u'Get Items',
'oldfieldtype': u'Button',
'options': u'pull_sales_order_detail',
'permlevel': 0,
'report_hide': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'item_maintenance_detail',
'fieldtype': u'Table',
'label': u'Maintenance Schedule Item',
'oldfieldname': u'item_maintenance_detail',
'oldfieldtype': u'Table',
'options': u'Maintenance Schedule Item',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'schedule',
'fieldtype': u'Section Break',
'label': u'Schedule',
'oldfieldtype': u'Section Break',
'options': u'Simple',
'permlevel': 0
},
# DocField
{
'colour': u'White:FFF',
'doctype': u'DocField',
'fieldname': u'generate_schedule',
'fieldtype': u'Button',
'label': u'Generate Schedule',
'oldfieldtype': u'Button',
'permlevel': 0,
'trigger': u'Client'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'maintenance_schedule_detail',
'fieldtype': u'Table',
'label': u'Maintenance Schedule Detail',
'oldfieldname': u'maintenance_schedule_detail',
'oldfieldtype': u'Table',
'options': u'Maintenance Schedule Detail',
'permlevel': 1
}
]

View File

@@ -0,0 +1,24 @@
// render
wn.doclistviews['Maintenance Schedule'] = wn.views.ListView.extend({
me: this,
init: function(d) {
this._super(d)
this.fields = this.fields.concat([
"`tabMaintenance Schedule`.customer",
]);
this.stats = this.stats.concat(['company']);
//this.show_hide_check_column();
},
columns: [
{width: '3%', content: 'check'},
{width: '5%', content: 'avatar'},
{width: '3%', content: 'docstatus'},
{width: '20%', content: 'name'},
{width: '55%', content: 'customer+tags'},
{width: '14%', content: 'modified',
css: {'text-align': 'right', 'color':'#777'}}
]
});

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1,129 @@
# DocType, Maintenance Schedule Detail
[
# These values are common in all dictionaries
{
'creation': '2012-03-27 14:36:42',
'docstatus': 0,
'modified': '2012-03-27 14:36:42',
'modified_by': u'Administrator',
'owner': u'Administrator'
},
# These values are common for all DocType
{
'autoname': u'MSD.#####',
'colour': u'White:FFF',
'default_print_format': u'Standard',
'doctype': 'DocType',
'istable': 1,
'module': u'Support',
'name': '__common__',
'section_style': u'Simple',
'server_code_error': u' ',
'show_in_menu': 0,
'version': 13
},
# These values are common for all DocField
{
'doctype': u'DocField',
'name': '__common__',
'parent': u'Maintenance Schedule Detail',
'parentfield': u'fields',
'parenttype': u'DocType'
},
# DocType, Maintenance Schedule Detail
{
'doctype': 'DocType',
'name': u'Maintenance Schedule Detail'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'item_code',
'fieldtype': u'Link',
'in_filter': 1,
'label': u'Item Code',
'oldfieldname': u'item_code',
'oldfieldtype': u'Link',
'options': u'Item',
'permlevel': 1,
'reqd': 0,
'search_index': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'item_name',
'fieldtype': u'Data',
'in_filter': 0,
'label': u'Item Name',
'oldfieldname': u'item_name',
'oldfieldtype': u'Data',
'permlevel': 1,
'search_index': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'scheduled_date',
'fieldtype': u'Date',
'in_filter': 1,
'label': u'Scheduled Date',
'oldfieldname': u'scheduled_date',
'oldfieldtype': u'Date',
'permlevel': 0,
'reqd': 1,
'search_index': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'actual_date',
'fieldtype': u'Date',
'hidden': 1,
'label': u'Actual Date',
'no_copy': 1,
'oldfieldname': u'actual_date',
'oldfieldtype': u'Date',
'permlevel': 1,
'print_hide': 1,
'report_hide': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'incharge_name',
'fieldtype': u'Link',
'in_filter': 1,
'label': u'Incharge Name',
'oldfieldname': u'incharge_name',
'oldfieldtype': u'Link',
'options': u'Sales Person',
'permlevel': 0,
'reqd': 1,
'search_index': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'serial_no',
'fieldtype': u'Small Text',
'in_filter': 1,
'label': u'Serial No',
'no_copy': 0,
'oldfieldname': u'serial_no',
'oldfieldtype': u'Small Text',
'permlevel': 1,
'search_index': 0,
'width': u'160px'
}
]

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1,176 @@
# DocType, Maintenance Schedule Item
[
# These values are common in all dictionaries
{
'creation': '2012-03-27 14:36:41',
'docstatus': 0,
'modified': '2012-03-27 14:36:41',
'modified_by': u'Administrator',
'owner': u'Administrator'
},
# These values are common for all DocType
{
'autoname': u'IMD.#####',
'colour': u'White:FFF',
'default_print_format': u'Standard',
'doctype': 'DocType',
'istable': 1,
'module': u'Support',
'name': '__common__',
'section_style': u'Simple',
'server_code_error': u' ',
'show_in_menu': 0,
'version': 9
},
# These values are common for all DocField
{
'doctype': u'DocField',
'name': '__common__',
'parent': u'Maintenance Schedule Item',
'parentfield': u'fields',
'parenttype': u'DocType'
},
# DocType, Maintenance Schedule Item
{
'doctype': 'DocType',
'name': u'Maintenance Schedule Item'
},
# DocField
{
'colour': u'White:FFF',
'doctype': u'DocField',
'fieldname': u'item_code',
'fieldtype': u'Link',
'in_filter': 1,
'label': u'Item Code',
'oldfieldname': u'item_code',
'oldfieldtype': u'Link',
'options': u'Item',
'permlevel': 0,
'reqd': 1,
'search_index': 1,
'trigger': u'Client'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'item_name',
'fieldtype': u'Data',
'label': u'Item Name',
'oldfieldname': u'item_name',
'oldfieldtype': u'Data',
'permlevel': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'description',
'fieldtype': u'Data',
'label': u'Description',
'oldfieldname': u'description',
'oldfieldtype': u'Data',
'permlevel': 1,
'width': u'300px'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'start_date',
'fieldtype': u'Date',
'in_filter': 1,
'label': u'Start Date',
'oldfieldname': u'start_date',
'oldfieldtype': u'Date',
'permlevel': 0,
'reqd': 1,
'search_index': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'end_date',
'fieldtype': u'Date',
'in_filter': 1,
'label': u'End Date',
'oldfieldname': u'end_date',
'oldfieldtype': u'Date',
'permlevel': 0,
'reqd': 1,
'search_index': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'periodicity',
'fieldtype': u'Select',
'label': u'Periodicity',
'oldfieldname': u'periodicity',
'oldfieldtype': u'Select',
'options': u'\nWeekly\nMonthly\nQuarterly\nHalf Yearly\nYearly\nRandom',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'no_of_visits',
'fieldtype': u'Int',
'label': u'No of Visits',
'oldfieldname': u'no_of_visits',
'oldfieldtype': u'Int',
'permlevel': 0,
'reqd': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'incharge_name',
'fieldtype': u'Link',
'in_filter': 1,
'label': u'Incharge Name',
'oldfieldname': u'incharge_name',
'oldfieldtype': u'Link',
'options': u'Sales Person',
'permlevel': 0,
'reqd': 1,
'search_index': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'serial_no',
'fieldtype': u'Small Text',
'label': u'Serial No',
'oldfieldname': u'serial_no',
'oldfieldtype': u'Small Text',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'prevdoc_docname',
'fieldtype': u'Data',
'in_filter': 1,
'label': u'Against Docname',
'no_copy': 1,
'oldfieldname': u'prevdoc_docname',
'oldfieldtype': u'Data',
'permlevel': 1,
'print_hide': 1,
'search_index': 1,
'width': u'150px'
}
]

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1,116 @@
// ERPNext - web based ERP (http://erpnext.com)
// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
cur_frm.cscript.onload = function(doc, dt, dn) {
if(!doc.status) set_multiple(dt,dn,{status:'Draft'});
if(doc.__islocal) set_multiple(dt,dn,{mntc_date:get_today()});
hide_contact_info(doc);
}
var hide_contact_info = function(doc) {
if(doc.customer) $(cur_frm.fields_dict.contact_info_section.row.wrapper).toggle(true);
else $(cur_frm.fields_dict.contact_info_section.row.wrapper).toggle(false);
}
cur_frm.cscript.refresh = function(doc) {
hide_contact_info(doc);
}
//customer
cur_frm.cscript.customer = function(doc,dt,dn) {
var callback = function(r,rt) {
var doc = locals[cur_frm.doctype][cur_frm.docname];
cur_frm.refresh();
}
if(doc.customer) $c_obj(make_doclist(doc.doctype, doc.name), 'get_default_customer_address', '', callback);
hide_contact_info(doc);
}
cur_frm.cscript.customer_address = cur_frm.cscript.contact_person = function(doc,dt,dn) {
if(doc.customer) get_server_fields('get_customer_address', JSON.stringify({customer: doc.customer, address: doc.customer_address, contact: doc.contact_person}),'', doc, dt, dn, 1);
}
cur_frm.fields_dict.customer_address.on_new = function(dn) {
locals['Address'][dn].customer = locals[cur_frm.doctype][cur_frm.docname].customer;
locals['Address'][dn].customer_name = locals[cur_frm.doctype][cur_frm.docname].customer_name;
}
cur_frm.fields_dict.contact_person.on_new = function(dn) {
locals['Contact'][dn].customer = locals[cur_frm.doctype][cur_frm.docname].customer;
locals['Contact'][dn].customer_name = locals[cur_frm.doctype][cur_frm.docname].customer_name;
}
cur_frm.fields_dict['customer_address'].get_query = function(doc, cdt, cdn) {
return 'SELECT name,address_line1,city FROM tabAddress WHERE customer = "'+ doc.customer +'" AND docstatus != 2 AND name LIKE "%s" ORDER BY name ASC LIMIT 50';
}
cur_frm.fields_dict['contact_person'].get_query = function(doc, cdt, cdn) {
return 'SELECT name,CONCAT(first_name," ",ifnull(last_name,"")) As FullName,department,designation FROM tabContact WHERE customer = "'+ doc.customer +'" AND docstatus != 2 AND name LIKE "%s" ORDER BY name ASC LIMIT 50';
}
cur_frm.cscript.get_items = function(doc, dt, dn) {
var callback = function(r,rt) {
hide_contact_info(doc);
cur_frm.refresh();
}
get_server_fields('fetch_items','','',doc, dt, dn,1,callback);
}
cur_frm.fields_dict['maintenance_visit_details'].grid.get_field('item_code').get_query = function(doc, cdt, cdn) {
return 'SELECT tabItem.name,tabItem.item_name,tabItem.description FROM tabItem WHERE tabItem.is_service_item="Yes" AND tabItem.docstatus != 2 AND tabItem.%(key)s LIKE "%s" LIMIT 50';
}
cur_frm.cscript.item_code = function(doc, cdt, cdn) {
var fname = cur_frm.cscript.fname;
var d = locals[cdt][cdn];
if (d.item_code) {
get_server_fields('get_item_details',d.item_code, 'maintenance_visit_details',doc,cdt,cdn,1);
}
}
cur_frm.fields_dict['sales_order_no'].get_query = function(doc) {
doc = locals[this.doctype][this.docname];
var cond = '';
if(doc.customer) {
cond = '`tabSales Order`.customer = "'+doc.customer+'" AND';
}
return repl('SELECT DISTINCT `tabSales Order`.name FROM `tabSales Order`, `tabSales Order Item`, `tabItem` WHERE `tabSales Order`.company = "%(company)s" AND `tabSales Order`.docstatus = 1 AND `tabSales Order Item`.parent = `tabSales Order`.name AND `tabSales Order Item`.item_code = `tabItem`.name AND `tabItem`.is_service_item = "Yes" AND %(cond)s `tabSales Order`.name LIKE "%s" ORDER BY `tabSales Order`.name DESC LIMIT 50', {company:doc.company, cond:cond});
}
cur_frm.fields_dict['customer_issue_no'].get_query = function(doc) {
doc = locals[this.doctype][this.docname];
var cond = '';
if(doc.customer) {
cond = '`tabCustomer Issue`.customer = "'+doc.customer+'" AND';
}
return repl('SELECT `tabCustomer Issue`.name FROM `tabCustomer Issue` WHERE `tabCustomer Issue`.company = "%(company)s" AND %(cond)s `tabCustomer Issue`.docstatus = 1 AND (`tabCustomer Issue`.status = "Open" OR `tabCustomer Issue`.status = "Work In Progress") AND `tabCustomer Issue`.name LIKE "%s" ORDER BY `tabCustomer Issue`.name DESC LIMIT 50', {company:doc.company, cond:cond});
}
cur_frm.fields_dict['maintenance_schedule'].get_query = function(doc) {
doc = locals[this.doctype][this.docname];
var cond = '';
if(doc.customer) {
cond = '`tabMaintenance Schedule`.customer = "'+doc.customer+'" AND';
}
return repl('SELECT `tabMaintenance Schedule`.name FROM `tabMaintenance Schedule` WHERE `tabMaintenance Schedule`.company = "%(company)s" AND %(cond)s `tabMaintenance Schedule`.docstatus = 1 AND `tabMaintenance Schedule`.name LIKE "%s" ORDER BY `tabMaintenance Schedule`.name DESC LIMIT 50', {company:doc.company, cond:cond});
}
//get query select Territory
cur_frm.fields_dict['territory'].get_query = function(doc,cdt,cdn) {
return 'SELECT `tabTerritory`.`name`,`tabTerritory`.`parent_territory` FROM `tabTerritory` WHERE `tabTerritory`.`is_group` = "No" AND `tabTerritory`.`docstatus`!= 2 AND `tabTerritory`.%(key)s LIKE "%s" ORDER BY `tabTerritory`.`name` ASC LIMIT 50';
}

View File

@@ -0,0 +1,165 @@
# ERPNext - web based ERP (http://erpnext.com)
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Please edit this list and import only required elements
from __future__ import unicode_literals
import webnotes
from webnotes.utils import add_days, add_months, add_years, cint, cstr, date_diff, default_fields, flt, fmt_money, formatdate, generate_hash, getTraceback, get_defaults, get_first_day, get_last_day, getdate, has_common, month_name, now, nowdate, replace_newlines, sendmail, set_default, str_esc_quote, user_format, validate_email_add
from webnotes.model import db_exists
from webnotes.model.doc import Document, addchild, getchildren, make_autoname
from webnotes.model.doclist import getlist, copy_doclist
from webnotes.model.code import get_obj, get_server_obj, run_server_obj, updatedb, check_syntax
from webnotes import session, form, is_testing, msgprint, errprint
set = webnotes.conn.set
sql = webnotes.conn.sql
get_value = webnotes.conn.get_value
in_transaction = webnotes.conn.in_transaction
convert_to_lists = webnotes.conn.convert_to_lists
# -----------------------------------------------------------------------------------------
from utilities.transaction_base import TransactionBase
class DocType(TransactionBase):
def __init__(self, doc, doclist=[]):
self.doc = doc
self.doclist = doclist
#get item details
#------------------
def get_item_details(self, item_code):
item = sql("select item_name,description from `tabItem` where name = '%s'" %(item_code), as_dict=1)
ret = {
'item_name' : item and item[0]['item_name'] or '',
'description' : item and item[0]['description'] or ''
}
return ret
# fetch details of resp Sales order or customer issue
#-----------------------------------------------------------
def fetch_items(self):
if self.doc.sales_order_no and self.doc.customer_issue_no :
msgprint("You can not fetch details of both, Sales Order and Customer Issue, in same Maintenance Visit")
raise Exception
self.doclist = self.doc.clear_table(self.doclist, 'maintenance_visit_details')
if self.doc.sales_order_no:
self.doclist = get_obj('DocType Mapper', 'Sales Order-Maintenance Visit').dt_map('Sales Order', \
'Maintenance Visit', self.doc.sales_order_no, self.doc, self.doclist, "[['Sales Order', 'Maintenance Visit'],\
['Sales Order Item', 'Maintenance Visit Purpose']]")
elif self.doc.customer_issue_no:
self.doclist = get_obj('DocType Mapper', 'Customer Issue-Maintenance Visit').dt_map('Customer Issue', \
'Maintenance Visit', self.doc.customer_issue_no, self.doc, self.doclist, "[['Customer Issue', 'Maintenance Visit'],\
['Customer Issue', 'Maintenance Visit Purpose']]")
elif self.doc.maintenance_schedule:
self.doclist = get_obj('DocType Mapper', 'Maintenance Schedule-Maintenance Visit').dt_map('Maintenance Schedule',\
'Maintenance Visit', self.doc.maintenance_schedule, self.doc, self.doclist, "[['Maintenance Schedule', \
'Maintenance Visit'], ['Maintenance Schedule Item', 'Maintenance Visit Purpose']]")
#validate reference value using doctype mapper
#-----------------------------------------------------
def validate_reference_value(self, check_for):
if check_for == 'Sales Order':
get_obj('DocType Mapper', 'Sales Order-Maintenance Visit', with_children = 1).validate_reference_value(self, self.doc.name)
elif check_for == 'Customer Issue':
get_obj('DocType Mapper', 'Customer Issue-Maintenance Visit', with_children = 1).validate_reference_value(self, self.doc.name)
#check if serial no exist in system
#--------------------------------------
def validate_serial_no(self):
for d in getlist(self.doclist, 'maintenance_visit_details'):
if d.serial_no and not sql("select name from `tabSerial No` where name = '%s' and docstatus != 2" % d.serial_no):
msgprint("Serial No: "+ d.serial_no + " not exists in the system")
raise Exception
def validate(self):
if not getlist(self.doclist, 'maintenance_visit_details'):
msgprint("Please enter maintenance details")
raise Exception
check_for = ''
for d in getlist(self.doclist, 'maintenance_visit_details'):
if d.prevdoc_doctype == 'Sales Order':
check_for = 'Sales Order'
elif d.prevdoc_doctype == 'Customer Issue':
check_for = 'Customer Issue'
if check_for:
self.validate_reference_value(check_for)
self.validate_serial_no()
def update_customer_issue(self, flag):
for d in getlist(self.doclist, 'maintenance_visit_details'):
if d.prevdoc_docname and d.prevdoc_doctype == 'Customer Issue' :
if flag==1:
mntc_date = self.doc.mntc_date
service_person = d.service_person
work_done = d.work_done
if self.doc.completion_status == 'Fully Completed':
status = 'Closed'
elif self.doc.completion_status == 'Partially Completed':
status = 'Work In Progress'
else:
nm = sql("select t1.name, t1.mntc_date, t2.service_person, t2.work_done from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2 where t2.parent = t1.name and t1.completion_status = 'Partially Completed' and t2.prevdoc_docname = %s and t1.name!=%s and t1.docstatus = 1 order by t1.name desc limit 1", (d.prevdoc_docname, self.doc.name))
if nm:
status = 'Work In Progress'
mntc_date = nm and nm[0][1] or ''
service_person = nm and nm[0][2] or ''
work_done = nm and nm[0][3] or ''
else:
status = 'Open'
mntc_date = ''
service_person = ''
work_done = ''
sql("update `tabCustomer Issue` set resolution_date=%s, resolved_by=%s, resolution_details=%s, status=%s where name =%s",(mntc_date,service_person,work_done,status,d.prevdoc_docname))
def check_if_last_visit(self):
"""check if last maintenance visit against same sales order/ customer issue"""
check_for_docname = check_for_doctype = None
for d in getlist(self.doclist, 'maintenance_visit_details'):
if d.prevdoc_docname:
check_for_docname = d.prevdoc_docname
check_for_doctype = d.prevdoc_doctype
if check_for_docname:
check = sql("select t1.name from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2 where t2.parent = t1.name and t1.name!=%s and t2.prevdoc_docname=%s and t1.docstatus = 1 and (t1.mntc_date > %s or (t1.mntc_date = %s and t1.mntc_time > %s))", (self.doc.name, check_for_docname, self.doc.mntc_date, self.doc.mntc_date, self.doc.mntc_time))
if check:
check_lst = [x[0] for x in check]
check_lst =','.join(check_lst)
msgprint("To cancel this, you need to cancel Maintenance Visit(s) "+cstr(check_lst)+" created after this maintenance visit against same "+check_for_doctype)
raise Exception
else:
self.update_customer_issue(0)
def on_submit(self):
self.update_customer_issue(1)
set(self.doc, 'status', 'Submitted')
def on_cancel(self):
self.check_if_last_visit()
set(self.doc, 'status', 'Cancelled')
def on_update(self):
pass

View File

@@ -0,0 +1,531 @@
# DocType, Maintenance Visit
[
# These values are common in all dictionaries
{
'creation': '2012-06-11 12:10:15',
'docstatus': 0,
'modified': '2012-06-27 12:50:00',
'modified_by': u'Administrator',
'owner': u'ashwini@webnotestech.com'
},
# These values are common for all DocType
{
'_last_update': u'1322549701',
'autoname': u'MV.#####',
'colour': u'White:FFF',
'default_print_format': u'Standard',
'doctype': 'DocType',
'is_submittable': 1,
'module': u'Support',
'name': '__common__',
'search_fields': u'status,maintenance_type,customer,customer_name, address,mntc_date,company,fiscal_year',
'section_style': u'Simple',
'server_code_error': u' ',
'show_in_menu': 0,
'subject': u'To %(customer_name)s on %(mntc_date)s',
'tag_fields': u'completion_status,maintenance_type',
'version': 1
},
# These values are common for all DocField
{
'doctype': u'DocField',
'name': '__common__',
'parent': u'Maintenance Visit',
'parentfield': u'fields',
'parenttype': u'DocType'
},
# These values are common for all DocPerm
{
'doctype': u'DocPerm',
'name': '__common__',
'parent': u'Maintenance Visit',
'parentfield': u'permissions',
'parenttype': u'DocType',
'read': 1
},
# DocType, Maintenance Visit
{
'doctype': 'DocType',
'name': u'Maintenance Visit'
},
# DocPerm
{
'amend': 1,
'cancel': 1,
'create': 1,
'doctype': u'DocPerm',
'permlevel': 0,
'role': u'System Manager',
'submit': 1,
'write': 1
},
# DocPerm
{
'doctype': u'DocPerm',
'permlevel': 1,
'role': u'System Manager'
},
# DocPerm
{
'amend': 1,
'cancel': 1,
'create': 1,
'doctype': u'DocPerm',
'permlevel': 0,
'role': u'Maintenance Manager',
'submit': 1,
'write': 1
},
# DocPerm
{
'doctype': u'DocPerm',
'permlevel': 1,
'role': u'Maintenance Manager'
},
# DocPerm
{
'amend': 1,
'cancel': 1,
'create': 1,
'doctype': u'DocPerm',
'permlevel': 0,
'role': u'Maintenance User',
'submit': 1,
'write': 1
},
# DocPerm
{
'doctype': u'DocPerm',
'permlevel': 1,
'role': u'Maintenance User'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'customer_details',
'fieldtype': u'Section Break',
'label': u'Customer Details',
'oldfieldtype': u'Section Break',
'options': u'Simple',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'column_break0',
'fieldtype': u'Column Break',
'oldfieldtype': u'Column Break',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'customer',
'fieldtype': u'Link',
'in_filter': 1,
'label': u'Customer',
'oldfieldname': u'customer',
'oldfieldtype': u'Link',
'options': u'Customer',
'permlevel': 0,
'print_hide': 1,
'reqd': 1,
'search_index': 0,
'trigger': u'Client'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'customer_name',
'fieldtype': u'Data',
'hidden': 1,
'label': u'Customer Name',
'permlevel': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'address_display',
'fieldtype': u'Small Text',
'hidden': 1,
'label': u'Address',
'permlevel': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'contact_display',
'fieldtype': u'Small Text',
'hidden': 1,
'label': u'Contact',
'permlevel': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'contact_mobile',
'fieldtype': u'Data',
'hidden': 1,
'label': u'Mobile No',
'permlevel': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'contact_email',
'fieldtype': u'Data',
'hidden': 1,
'label': u'Contact Email',
'permlevel': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'column_break1',
'fieldtype': u'Column Break',
'oldfieldtype': u'Column Break',
'permlevel': 0,
'width': u'50%'
},
# DocField
{
'default': u'Today',
'doctype': u'DocField',
'fieldname': u'mntc_date',
'fieldtype': u'Date',
'label': u'Maintenance Date',
'no_copy': 1,
'oldfieldname': u'mntc_date',
'oldfieldtype': u'Date',
'permlevel': 0,
'reqd': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'mntc_time',
'fieldtype': u'Time',
'label': u'Maintenance Time',
'no_copy': 1,
'oldfieldname': u'mntc_time',
'oldfieldtype': u'Time',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'maintenance_details',
'fieldtype': u'Section Break',
'label': u'Maintenance Details',
'oldfieldtype': u'Section Break',
'options': u'Simple',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'completion_status',
'fieldtype': u'Select',
'label': u'Completion Status',
'oldfieldname': u'completion_status',
'oldfieldtype': u'Select',
'options': u'\nPartially Completed\nFully Completed',
'permlevel': 0,
'reqd': 1
},
# DocField
{
'colour': u'White:FFF',
'default': u'Unscheduled',
'doctype': u'DocField',
'fieldname': u'maintenance_type',
'fieldtype': u'Select',
'in_filter': 1,
'label': u'Maintenance Type',
'oldfieldname': u'maintenance_type',
'oldfieldtype': u'Select',
'options': u'\nScheduled\nUnscheduled\nBreakdown',
'permlevel': 0,
'reqd': 1,
'search_index': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'column_break2',
'fieldtype': u'Column Break',
'oldfieldtype': u'Column Break',
'permlevel': 0,
'width': u'50%'
},
# DocField
{
'colour': u'White:FFF',
'doctype': u'DocField',
'fieldname': u'sales_order_no',
'fieldtype': u'Link',
'in_filter': 1,
'label': u'Sales Order No',
'oldfieldname': u'sales_order_no',
'oldfieldtype': u'Link',
'options': u'Sales Order',
'permlevel': 0,
'search_index': 1,
'trigger': u'Client'
},
# DocField
{
'colour': u'White:FFF',
'doctype': u'DocField',
'fieldname': u'customer_issue_no',
'fieldtype': u'Link',
'in_filter': 1,
'label': u'Customer Issue No',
'oldfieldname': u'customer_issue_no',
'oldfieldtype': u'Link',
'options': u'Customer Issue',
'permlevel': 0,
'search_index': 1,
'trigger': u'Client'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'maintenance_schedule',
'fieldtype': u'Link',
'in_filter': 1,
'label': u'Maintenance Schedule',
'options': u'Maintenance Schedule',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'get_items',
'fieldtype': u'Button',
'label': u'Get Items',
'oldfieldtype': u'Button',
'options': u'fetch_items',
'permlevel': 0,
'print_hide': 1,
'report_hide': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'section_break0',
'fieldtype': u'Section Break',
'oldfieldtype': u'Section Break',
'options': u'Simple',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'maintenance_visit_details',
'fieldtype': u'Table',
'label': u'Maintenance Visit Purpose',
'oldfieldname': u'maintenance_visit_details',
'oldfieldtype': u'Table',
'options': u'Maintenance Visit Purpose',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'more_info',
'fieldtype': u'Section Break',
'label': u'More Info',
'oldfieldtype': u'Section Break',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'customer_feedback',
'fieldtype': u'Small Text',
'label': u'Customer Feedback',
'oldfieldname': u'customer_feedback',
'oldfieldtype': u'Small Text',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'col_break3',
'fieldtype': u'Column Break',
'permlevel': 0
},
# DocField
{
'colour': u'White:FFF',
'default': u'Draft',
'doctype': u'DocField',
'fieldname': u'status',
'fieldtype': u'Data',
'label': u'Status',
'no_copy': 1,
'oldfieldname': u'status',
'oldfieldtype': u'Data',
'options': u'\nDraft\nCancelled\nSubmitted',
'permlevel': 1,
'reqd': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'amended_from',
'fieldtype': u'Data',
'label': u'Amended From',
'no_copy': 1,
'oldfieldname': u'amended_from',
'oldfieldtype': u'Data',
'permlevel': 1,
'print_hide': 1,
'width': u'150px'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'amendment_date',
'fieldtype': u'Date',
'label': u'Amendment Date',
'no_copy': 1,
'oldfieldname': u'amendment_date',
'oldfieldtype': u'Date',
'permlevel': 0,
'print_hide': 1,
'width': u'100px'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'company',
'fieldtype': u'Select',
'in_filter': 1,
'label': u'Company',
'oldfieldname': u'company',
'oldfieldtype': u'Select',
'options': u'link:Company',
'permlevel': 0,
'print_hide': 1,
'reqd': 1,
'search_index': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'fiscal_year',
'fieldtype': u'Select',
'in_filter': 1,
'label': u'Fiscal Year',
'oldfieldname': u'fiscal_year',
'oldfieldtype': u'Select',
'options': u'link:Fiscal Year',
'permlevel': 0,
'print_hide': 1,
'reqd': 1,
'search_index': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'contact_info_section',
'fieldtype': u'Section Break',
'label': u'Contact Info',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'customer_address',
'fieldtype': u'Link',
'label': u'Customer Address',
'options': u'Address',
'permlevel': 0,
'print_hide': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'contact_person',
'fieldtype': u'Link',
'label': u'Contact Person',
'options': u'Contact',
'permlevel': 0,
'print_hide': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'col_break4',
'fieldtype': u'Column Break',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'territory',
'fieldtype': u'Link',
'label': u'Territory',
'options': u'Territory',
'permlevel': 0,
'print_hide': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'customer_group',
'fieldtype': u'Link',
'label': u'Customer Group',
'options': u'Customer Group',
'permlevel': 0,
'print_hide': 1
}
]

View File

@@ -0,0 +1,41 @@
// render
wn.doclistviews['Maintenance Visit'] = wn.views.ListView.extend({
me: this,
init: function(d) {
this._super(d)
this.fields = this.fields.concat([
"`tabMaintenance Visit`.customer_name",
"`tabMaintenance Visit`.mntc_date",
"`tabMaintenance Visit`.mntc_time",
"`tabMaintenance Visit`.maintenance_type",
"`tabMaintenance Visit`.completion_status",
]);
this.stats = this.stats.concat(['completion_status', 'company']);
//this.show_hide_check_column();
},
prepare_data: function(data) {
this._super(data);
data.mntc_date = wn.datetime.str_to_user(data.mntc_date);
data.mntc_time = wn.datetime.time_to_ampm(data.mntc_time);
data.date_time = "on " + data.mntc_date + " at " +
data.mntc_time[0] + ":" + data.mntc_time[1] + " " + data.mntc_time[2];
data.customer_name = data.customer_name + " " + data.date_time;
data.completion_status = data.completion_status +
(data.maintenance_type ? " [" + data.maintenance_type + "]": "");
},
columns: [
{width: '3%', content: 'check'},
{width: '5%', content: 'avatar'},
{width: '3%', content: 'docstatus'},
{width: '15%', content: 'name'},
{width: '40%', content: 'customer_name+tags'},
{width: '20%', content: 'completion_status'},
{width: '14%', content: 'modified',
css: {'text-align': 'right', 'color':'#777'}}
]
});

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1,163 @@
# DocType, Maintenance Visit Purpose
[
# These values are common in all dictionaries
{
'creation': '2012-03-27 14:36:43',
'docstatus': 0,
'modified': '2012-03-27 14:36:43',
'modified_by': u'Administrator',
'owner': u'ashwini@webnotestech.com'
},
# These values are common for all DocType
{
'autoname': u'MVD.#####',
'colour': u'White:FFF',
'doctype': 'DocType',
'istable': 1,
'module': u'Support',
'name': '__common__',
'section_style': u'Simple',
'server_code_error': u' ',
'version': 13
},
# These values are common for all DocField
{
'doctype': u'DocField',
'name': '__common__',
'parent': u'Maintenance Visit Purpose',
'parentfield': u'fields',
'parenttype': u'DocType'
},
# DocType, Maintenance Visit Purpose
{
'doctype': 'DocType',
'name': u'Maintenance Visit Purpose'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'description',
'fieldtype': u'Small Text',
'label': u'Description',
'oldfieldname': u'description',
'oldfieldtype': u'Small Text',
'permlevel': 0,
'reqd': 1,
'width': u'300px'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'service_person',
'fieldtype': u'Link',
'label': u'Service Person',
'oldfieldname': u'service_person',
'oldfieldtype': u'Link',
'options': u'Sales Person',
'permlevel': 0,
'reqd': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'work_done',
'fieldtype': u'Small Text',
'label': u'Work Done',
'oldfieldname': u'work_done',
'oldfieldtype': u'Small Text',
'permlevel': 0,
'reqd': 1
},
# DocField
{
'colour': u'White:FFF',
'doctype': u'DocField',
'fieldname': u'item_code',
'fieldtype': u'Link',
'label': u'Item Code',
'oldfieldname': u'item_code',
'oldfieldtype': u'Link',
'options': u'Item',
'permlevel': 0,
'trigger': u'Client'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'item_name',
'fieldtype': u'Data',
'label': u'Item Name',
'oldfieldname': u'item_name',
'oldfieldtype': u'Data',
'permlevel': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'serial_no',
'fieldtype': u'Small Text',
'label': u'Serial No',
'oldfieldname': u'serial_no',
'oldfieldtype': u'Small Text',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'prevdoc_docname',
'fieldtype': u'Data',
'hidden': 0,
'label': u'Against Document No',
'no_copy': 1,
'oldfieldname': u'prevdoc_docname',
'oldfieldtype': u'Data',
'permlevel': 1,
'print_hide': 1,
'report_hide': 1,
'width': u'160px'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'prevdoc_detail_docname',
'fieldtype': u'Data',
'hidden': 1,
'label': u'Against Document Detail No',
'no_copy': 1,
'oldfieldname': u'prevdoc_detail_docname',
'oldfieldtype': u'Data',
'permlevel': 1,
'print_hide': 1,
'report_hide': 1,
'width': u'160px'
},
# DocField
{
'colour': u'White:FFF',
'doctype': u'DocField',
'fieldname': u'prevdoc_doctype',
'fieldtype': u'Data',
'hidden': 0,
'label': u'Document Type',
'no_copy': 1,
'oldfieldname': u'prevdoc_doctype',
'oldfieldtype': u'Data',
'permlevel': 1,
'print_hide': 1,
'report_hide': 1,
'width': u'150px'
}
]

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1,26 @@
// ERPNext - web based ERP (http://erpnext.com)
// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
cur_frm.cscript.refresh = function(doc) {
erpnext.hide_naming_series();
if(!doc.__islocal && !cint(doc.email_sent) && !doc.__unsaved) {
cur_frm.add_custom_button('Send', function() {
$c_obj(make_doclist(doc.doctype, doc.name), 'send_emails', '', function(r) {
cur_frm.refresh();
});
})
}
}

View File

@@ -0,0 +1,113 @@
# ERPNext - web based ERP (http://erpnext.com)
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals
import webnotes
import webnotes.utils
class DocType():
def __init__(self, d, dl):
self.doc, self.doclist = d, dl
self.dt_map = {
"Contact": {
"email_field": "email_id",
"first_name_field": "first_name",
},
"Lead": {
"email_field": "email_id",
"first_name_field": "lead_name"
}
}
self.query_map = {
"contacts": """select distinct email_id from `tabContact`
where ifnull(email_id, '') != '' """,
"customer_contacts": """select distinct email_id from `tabContact`
where ifnull(customer, '') != '' and ifnull(email_id, '') != '' """,
"leads": """select distinct email_id from `tabLead`
where ifnull(email_id, '') != '' """,
"active_leads": """select distinct email_id from `tabLead`
where status = "Open" and ifnull(email_id, '') != '' """,
"blog_subscribers": """select distinct email_id from `tabLead`
where ifnull(blog_subscriber,0) = 1 and ifnull(email_id, '') != '' """
}
def autoname(self):
from webnotes.model.doc import make_autoname
self.doc.name = make_autoname(self.doc.naming_series+ '.#####')
def send_emails(self):
"""send emails to leads and customers"""
# TODO: create unsubscribed check in customer
if self.doc.email_sent:
webnotes.msgprint("""Newsletter has already been sent""", raise_exception=1)
self.all_recipients = []
self.send_count = {}
if self.doc.contacts:
self.send("contacts", "Contact")
elif self.doc.customer_contacts:
self.send("customer_contacts", "Contact")
if self.doc.leads:
self.send("leads", "Lead")
else:
if self.doc.active_leads:
self.send("active_leads", "Lead")
if self.doc.blog_subscribers:
self.send("blog_subscribers", "Lead")
webnotes.conn.set(self.doc, "email_sent", 1)
webnotes.msgprint("""Scheduled to send to %s""" % \
", ".join(["%d %s(s)" % (self.send_count[s], s) for s in self.send_count]))
def test_send(self, doctype="Lead"):
args = self.dt_map[doctype]
sender = webnotes.utils.get_email_id(self.doc.owner)
recipients = self.doc.test_email_id.split(",")
from webnotes.utils.email_lib.bulk import send
send(recipients = recipients, sender = sender,
subject = self.doc.subject, message = self.get_message(),
doctype = doctype, email_field = args["email_field"],
first_name_field = args["first_name_field"], last_name_field = "")
webnotes.msgprint("""Scheduled to send to %s""" % self.doc.test_email_id)
def get_recipients(self, key):
recipients = webnotes.conn.sql(self.query_map[key])
recipients = [r[0] for r in recipients if r not in self.all_recipients]
self.all_recipients += recipients
return recipients
def get_message(self):
if not hasattr(self, "message"):
import markdown2
self.message = markdown2.markdown(self.doc.message)
return self.message
def send(self, query_key, doctype):
webnotes.conn.auto_commit_on_many_writes = True
recipients = self.get_recipients(query_key)
sender = webnotes.utils.get_email_id(self.doc.owner)
args = self.dt_map[doctype]
self.send_count[doctype] = self.send_count.setdefault(doctype, 0) + len(recipients)
from webnotes.utils.email_lib.bulk import send
send(recipients = recipients, sender = sender,
subject = self.doc.subject, message = self.get_message(),
doctype = doctype, email_field = args["email_field"],
first_name_field = args["first_name_field"], last_name_field = "")

View File

@@ -0,0 +1,233 @@
# DocType, Newsletter
[
# These values are common in all dictionaries
{
u'creation': '2012-08-23 18:49:12',
u'docstatus': 0,
u'modified': '2012-08-24 14:45:00',
u'modified_by': u'Administrator',
u'owner': u'Administrator'
},
# These values are common for all DocType
{
'description': u'Create and Send Newsletters',
u'doctype': u'DocType',
'document_type': u'Other',
'module': u'Support',
u'name': u'__common__',
'version': 1
},
# These values are common for all DocField
{
u'doctype': u'DocField',
u'name': u'__common__',
'parent': u'Newsletter',
'parentfield': u'fields',
'parenttype': u'DocType'
},
# These values are common for all DocPerm
{
u'doctype': u'DocPerm',
u'name': u'__common__',
'parent': u'Newsletter',
'parentfield': u'permissions',
'parenttype': u'DocType',
'read': 1
},
# DocType, Newsletter
{
u'doctype': u'DocType',
u'name': u'Newsletter'
},
# DocField
{
u'doctype': u'DocField',
'fieldname': u'basic_info',
'fieldtype': u'Section Break',
'label': u'Basic Info',
'permlevel': 0
},
# DocField
{
'colour': u'White:FFF',
'default': u'NL-',
u'doctype': u'DocField',
'fieldname': u'naming_series',
'fieldtype': u'Select',
'label': u'Naming Series',
'options': u'NL-',
'permlevel': 0,
'reqd': 1
},
# DocField
{
'colour': u'White:FFF',
'description': u'A Lead with this email id should exist',
u'doctype': u'DocField',
'fieldname': u'test_email_id',
'fieldtype': u'Data',
'label': u'Test Email Id',
'permlevel': 0
},
# DocField
{
u'doctype': u'DocField',
'fieldname': u'test_send',
'fieldtype': u'Button',
'label': u'Test',
'options': u'test_send',
'permlevel': 0
},
# DocField
{
u'doctype': u'DocField',
'fieldname': u'column_break1',
'fieldtype': u'Column Break',
'label': u'Send To',
'permlevel': 0
},
# DocField
{
'colour': u'White:FFF',
u'doctype': u'DocField',
'fieldname': u'contacts',
'fieldtype': u'Check',
'label': u'All Contacts',
'permlevel': 0
},
# DocField
{
'colour': u'White:FFF',
u'doctype': u'DocField',
'fieldname': u'customer_contacts',
'fieldtype': u'Check',
'label': u'All Customer Contacts',
'permlevel': 0
},
# DocField
{
'colour': u'White:FFF',
u'doctype': u'DocField',
'fieldname': u'leads',
'fieldtype': u'Check',
'label': u'All Leads',
'permlevel': 0
},
# DocField
{
u'doctype': u'DocField',
'fieldname': u'active_leads',
'fieldtype': u'Check',
'label': u'All Active Leads',
'permlevel': 0
},
# DocField
{
u'doctype': u'DocField',
'fieldname': u'blog_subscribers',
'fieldtype': u'Check',
'label': u'All Blog Subscribers',
'permlevel': 0
},
# DocField
{
u'doctype': u'DocField',
'fieldname': u'newsletter_content',
'fieldtype': u'Section Break',
'label': u'Newsletter Content',
'permlevel': 0
},
# DocField
{
'colour': u'White:FFF',
u'doctype': u'DocField',
'fieldname': u'subject',
'fieldtype': u'Small Text',
'label': u'Subject',
'permlevel': 0,
'reqd': 1
},
# DocField
{
'colour': u'White:FFF',
u'doctype': u'DocField',
'fieldname': u'message',
'fieldtype': u'Code',
'label': u'Message',
'options': u'Markdown',
'permlevel': 0,
'reqd': 0
},
# DocField
{
u'doctype': u'DocField',
'fieldname': u'newsletter_status',
'fieldtype': u'Section Break',
'label': u'Newsletter Status',
'permlevel': 0
},
# DocField
{
'colour': u'White:FFF',
u'doctype': u'DocField',
'fieldname': u'email_sent',
'fieldtype': u'Check',
'label': u'Email Sent?',
'no_copy': 1,
'permlevel': 1
},
# DocPerm
{
'cancel': 1,
'create': 1,
u'doctype': u'DocPerm',
'permlevel': 0,
'role': u'Sales Manager',
'write': 1
},
# DocPerm
{
'cancel': 1,
'create': 1,
u'doctype': u'DocPerm',
'permlevel': 0,
'role': u'Support Manager',
'write': 1
},
# DocPerm
{
u'doctype': u'DocPerm',
'permlevel': 1,
'role': u'Sales Manager'
},
# DocPerm
{
u'doctype': u'DocPerm',
'permlevel': 1,
'role': u'Support Manager'
}
]

View File

@@ -0,0 +1,34 @@
// ERPNext - web based ERP (http://erpnext.com)
// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
wn.doclistviews['Newsletter'] = wn.views.ListView.extend({
init: function(doclistview) {
this._super(doclistview);
this.fields = this.fields.concat([
"`tabNewsletter`.subject",
"`tabNewsletter`.email_sent",
]);
},
columns: [
{width: '3%', content: 'check'},
{width: '5%', content: 'avatar'},
{width: '15%', content: 'name'},
{width: '55%', content: 'subject+tags'},
{width: '22%', content:'modified',
css: {'text-align': 'right', 'color':'#777'}}
],
});

View File

@@ -0,0 +1,190 @@
# ERPNext - web based ERP (http://erpnext.com)
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals
import webnotes
from webnotes.utils import cstr, cint
from webnotes.utils.email_lib.receive import POP3Mailbox
class SupportMailbox(POP3Mailbox):
def __init__(self):
"""
settings_doc must contain
use_ssl, host, username, password
"""
from webnotes.model.doc import Document
# extract email settings
self.email_settings = Document('Email Settings','Email Settings')
if not self.email_settings.fields.get('sync_support_mails'): return
s = Document('Support Email Settings')
s.use_ssl = self.email_settings.support_use_ssl
s.host = self.email_settings.support_host
s.username = self.email_settings.support_username
s.password = self.email_settings.support_password
POP3Mailbox.__init__(self, s)
def check_mails(self):
"""
returns true if there are active sessions
"""
self.auto_close_tickets()
return webnotes.conn.sql("select user from tabSessions where time_to_sec(timediff(now(), lastupdate)) < 1800")
def process_message(self, mail):
"""
Updates message from support email as either new or reply
"""
from home import update_feed
content, content_type = '[Blank Email]', 'text/plain'
if mail.text_content:
content, content_type = mail.text_content, 'text/plain'
else:
content, content_type = mail.html_content, 'text/html'
thread_list = mail.get_thread_id()
email_id = mail.mail['From']
if "<" in mail.mail['From']:
import re
re_result = re.findall('(?<=\<)(\S+)(?=\>)', mail.mail['From'])
if re_result and re_result[0]: email_id = re_result[0]
from webnotes.utils import decode_email_header
full_email_id = decode_email_header(mail.mail['From'])
for thread_id in thread_list:
exists = webnotes.conn.sql("""\
SELECT name
FROM `tabSupport Ticket`
WHERE name=%s AND raised_by REGEXP %s
""" , (thread_id, '(' + email_id + ')'))
if exists and exists[0] and exists[0][0]:
from webnotes.model.code import get_obj
st = get_obj('Support Ticket', thread_id)
st.make_response_record(content, full_email_id, content_type)
# to update modified date
#webnotes.conn.set(st.doc, 'status', 'Open')
st.doc.status = 'Open'
st.doc.save()
update_feed(st.doc, 'on_update')
webnotes.conn.commit()
# extract attachments
self.save_attachments(st.doc, mail.attachments)
webnotes.conn.begin()
return
from webnotes.model.doctype import get_property
opts = get_property('Support Ticket', 'options', 'naming_series')
# new ticket
from webnotes.model.doc import Document
d = Document('Support Ticket')
d.description = content
d.subject = decode_email_header(mail.mail['Subject'])
d.raised_by = full_email_id
d.content_type = content_type
d.status = 'Open'
d.naming_series = opts and opts.split("\n")[0] or 'SUP'
try:
d.save(1)
except:
d.description = 'Unable to extract message'
d.save(1)
else:
# update feed
update_feed(d, 'on_update')
# send auto reply
if cint(self.email_settings.send_autoreply):
self.send_auto_reply(d)
webnotes.conn.commit()
# extract attachments
self.save_attachments(d, mail.attachments)
webnotes.conn.begin()
def save_attachments(self, doc, attachment_list=[]):
"""
Saves attachments from email
attachment_list is a list of dict containing:
'filename', 'content', 'content-type'
"""
from webnotes.utils.file_manager import save_file, add_file_list
for attachment in attachment_list:
webnotes.conn.begin()
fid = save_file(attachment['filename'], attachment['content'], 'Support')
status = add_file_list('Support Ticket', doc.name, attachment['filename'], fid)
if not status:
doc.description = doc.description \
+ "\nCould not attach: " + cstr(attachment['filename'])
doc.save()
webnotes.conn.commit()
def send_auto_reply(self, d):
"""
Send auto reply to emails
"""
from webnotes.utils import cstr
signature = self.email_settings.fields.get('support_signature') or ''
response = self.email_settings.fields.get('support_autoreply') or ("""
A new Ticket has been raised for your query. If you have any additional information, please
reply back to this mail.
We will get back to you as soon as possible
[This is an automatic response]
""" + cstr(signature))
from webnotes.utils.email_lib import sendmail
sendmail(\
recipients = [cstr(d.raised_by)], \
sender = cstr(self.email_settings.fields.get('support_email')), \
subject = '['+cstr(d.name)+'] ' + cstr(d.subject), \
msg = cstr(response))
def auto_close_tickets(self):
"""
Auto Closes Waiting for Customer Support Ticket after 15 days
"""
webnotes.conn.sql("update `tabSupport Ticket` set status = 'Closed' where status = 'Waiting for Customer' and date_sub(curdate(),interval 15 Day) > modified")
def get_support_mails():
"""
Gets new emails from support inbox and updates / creates Support Ticket records
"""
import webnotes
from webnotes.utils import cint
if cint(webnotes.conn.get_value('Email Settings', None, 'sync_support_mails')):
SupportMailbox().get_messages()

View File

@@ -0,0 +1,8 @@
.support-ticket-wrapper {
margin-top: 10px;
}
.support-ticket-title {
padding: 5px;
border-bottom: 1px solid black;
}

View File

@@ -0,0 +1,198 @@
// ERPNext - web based ERP (http://erpnext.com)
// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// threading structure
// -------- orginal message --------
// xoxoxoxo
// -------- reply 1 --------
// -------- reply 2 --------
// xoxoxoxo
// -------- new reply --------
var cs = cur_frm.cscript;
$.extend(cur_frm.cscript, {
onload: function(doc, dt, dn) {
//
// help area
//
if(in_list(user_roles,'System Manager')) {
cur_frm.page_layout.footer.help_area.innerHTML = '';
new wn.widgets.Footer({
parent:cur_frm.page_layout.footer.help_area,
columns:2,
items: [
{
column: 0,
label:'Email Settings',
description:'Integrate your incoming support emails to support ticket',
onclick: function() { loaddoc('Email Settings','Email Settings'); }
},
]
})
}
if(!doc.customer) hide_field(['customer_name','address_display','contact_display','contact_mobile','contact_email']);
},
refresh: function(doc) {
erpnext.hide_naming_series();
cur_frm.cscript.make_listing(doc);
if(!doc.__islocal) {
if(in_list(user_roles,'System Manager')) {
if(doc.status!='Closed') cur_frm.add_custom_button('Close Ticket', cur_frm.cscript['Close Ticket']);
if(doc.status=='Closed') cur_frm.add_custom_button('Re-Open Ticket', cur_frm.cscript['Re-Open Ticket']);
}else if(doc.allocated_to) {
set_field_permlevel('status',2);
if(user==doc.allocated_to && doc.status!='Closed') cur_frm.add_custom_button('Close Ticket', cur_frm.cscript['Close Ticket']);
}
// can't change the main message & subject once set
set_field_permlevel('subject',2);
set_field_permlevel('description',2);
set_field_permlevel('raised_by',2);
}
refresh_field('status');
},
//
// make thread listing
//
make_listing: function(doc) {
cur_frm.fields_dict['thread_html'].wrapper.innerHTML = '';
// render first message
new EmailMessage($a(cur_frm.fields_dict['thread_html'].wrapper, 'div'), {
from_email: doc.raised_by,
creation: doc.creation,
mail: doc.description,
content_type: doc.content_type
}, null, -1)
// render thread
cur_frm.cscript.thread_list = new wn.ui.Listing({
parent: $a(cur_frm.fields_dict['thread_html'].wrapper, 'div'),
no_result_message: 'No responses yet',
get_query: function() {
return 'select mail, from_email, creation, content_type '+
'from `tabSupport Ticket Response` where parent="'+doc.name+'" order by creation asc'
},
as_dict: 1,
render_row: function(parent, data, list, idx) {
new EmailMessage(parent, data, list, idx);
}
});
cur_frm.cscript.thread_list.run();
},
send: function(doc, dt, dn) {
$c_obj(make_doclist(doc.doctype, doc.name), 'send_response', '', function(r,rt) {
locals[dt][dn].new_response = '';
if(!(r.exc || r.server_messages)) {
cur_frm.refresh();
}
});
},
customer: function(doc, dt, dn) {
var callback = function(r,rt) {
var doc = locals[cur_frm.doctype][cur_frm.docname];
if(!r.exc) {
cur_frm.refresh();
}
}
if(doc.customer) $c_obj(make_doclist(doc.doctype, doc.name), 'get_default_customer_address', '', callback);
if(doc.customer) unhide_field(['customer_name','address_display','contact_display','contact_mobile','contact_email']);
},
'Close Ticket': function() {
var doc = cur_frm.doc
var answer = confirm("Close Ticket "+doc.name+"?\n\nAllocated To: "+doc.allocated_to+"\n\nSubject: "+doc.subject+"");
if(answer) {
if(doc.name)
$c_obj(make_doclist(doc.doctype, doc.name),'close_ticket','',function(r,rt) {
if(!r.exc) {
cur_frm.refresh();
}
});
}
},
'Re-Open Ticket': function() {
var doc = cur_frm.doc
var answer = confirm("Re-Open Ticket "+doc.name+"?\n\nAllocated To: "+doc.allocated_to+"\n\nSubject: "+doc.subject+"");
if(answer) {
if(doc.name)
$c_obj(make_doclist(doc.doctype, doc.name),'reopen_ticket','',function(r,rt) {
if(!r.exc) {
cur_frm.refresh();
}
});
}
}
})
EmailMessage = function(parent, args, list, idx) {
var me = this;
$.extend(this, args);
this.make = function() {
this.creation = wn.datetime.str_to_user(this.creation);
if(this.from_email)
this.from_email = this.from_email.replace('<', '&lt;').replace('>', '&gt;');
// main wrapper
w = $a(parent, 'div', 'support-ticket-wrapper well');
//$(w).addClass('support-ticket-wrapper');
// sender and timestamp
$a($a(w, 'div', 'support-ticket-title'),
'span', 'link_type', {}, repl('By %(from_email)s on %(creation)s:', this),
function() {
// toggle message display on timestamp
if(me.message.style.display.toLowerCase()=='none') {
$ds(me.message);
} else {
$dh(me.message);
}
}
);
// email text
this.message = $a(w, 'div', '',
// style
{lineHeight:'1.7em', display:'none', padding: '7px', width: '575px',
wordWrap: 'break-word', textWrap: 'normal', overflowX: 'auto'},
// newlines for text email
(this.content_type=='text/plain' ? this.mail
.replace(/\n[ ]*\n[\n\t ]*/g, '\n\n') // excess whitespace
.replace(/\n/g, '<br>') : this.mail)
);
// show only first and last message
if(idx==-1 || list && list.data.length-1==idx) {
$ds(this.message)
}
}
this.make();
}

View File

@@ -0,0 +1,103 @@
# ERPNext - web based ERP (http://erpnext.com)
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals
import webnotes
from webnotes.model.doc import make_autoname
from utilities.transaction_base import TransactionBase
from home import update_feed
class DocType(TransactionBase):
def __init__(self, doc, doclist=[]):
self.doc = doc
self.doclist = doclist
def autoname(self):
self.doc.name = make_autoname(self.doc.naming_series+'.#####')
def send_response(self):
"""
Adds a new response to the ticket and sends an email to the sender
"""
if not self.doc.new_response:
webnotes.msgprint("Please write something as a response", raise_exception=1)
subject = '[' + self.doc.name + '] ' + (self.doc.subject or 'No Subject Specified')
response = self.doc.new_response + '\n\n[Please do not change the subject while responding.]'
# add last response to new response
response += self.last_response()
signature = webnotes.conn.get_value('Email Settings',None,'support_signature')
if signature:
response += '\n\n' + signature
from webnotes.utils.email_lib import sendmail
sendmail(\
recipients = [self.doc.raised_by], \
sender=webnotes.conn.get_value('Email Settings',None,'support_email'), \
subject=subject, \
msg=response)
self.doc.new_response = None
webnotes.conn.set(self.doc,'status','Waiting for Customer')
self.make_response_record(response)
def last_response(self):
"""return last response"""
tmp = webnotes.conn.sql("""select mail from `tabSupport Ticket Response`
where parent = %s order by creation desc limit 1
""", self.doc.name)
if not tmp:
tmp = webnotes.conn.sql("""
SELECT description from `tabSupport Ticket`
where name = %s
""", self.doc.name)
response_title = "=== In response to ==="
if tmp and tmp[0][0]:
return "\n\n" + response_title + "\n\n" + tmp[0][0].split(response_title)[0]
else:
return ""
def make_response_record(self, response, from_email = None, content_type='text/plain'):
"""
Creates a new Support Ticket Response record
"""
# add to Support Ticket Response
from webnotes.model.doc import Document
d = Document('Support Ticket Response')
d.from_email = from_email or webnotes.user.name
d.parent = self.doc.name
d.parenttype = "Support Ticket"
d.parentfield = "responses"
d.mail = response
d.content_type = content_type
d.save(1)
def close_ticket(self):
webnotes.conn.set(self.doc,'status','Closed')
update_feed(self.doc)
def reopen_ticket(self):
webnotes.conn.set(self.doc,'status','Open')
update_feed(self.doc)

View File

@@ -0,0 +1,411 @@
# DocType, Support Ticket
[
# These values are common in all dictionaries
{
'creation': '2012-04-02 16:02:42',
'docstatus': 0,
'modified': '2012-05-02 11:33:24',
'modified_by': u'Administrator',
'owner': u'Administrator'
},
# These values are common for all DocType
{
'_last_update': u'1311584009',
'allow_attach': 1,
'allow_trash': 1,
'colour': u'White:FFF',
'default_print_format': u'Standard',
'doctype': 'DocType',
'module': u'Support',
'name': '__common__',
'search_fields': u'status,customer,allocated_to,subject,raised_by',
'section_style': u'Tray',
'server_code_error': u' ',
'show_in_menu': 0,
'subject': u'%(subject)s',
'tag_fields': u'status,allocated_to',
'version': 1
},
# These values are common for all DocField
{
'doctype': u'DocField',
'name': '__common__',
'parent': u'Support Ticket',
'parentfield': u'fields',
'parenttype': u'DocType'
},
# These values are common for all DocPerm
{
'amend': 0,
'cancel': 0,
'doctype': u'DocPerm',
'name': '__common__',
'parent': u'Support Ticket',
'parentfield': u'permissions',
'parenttype': u'DocType',
'read': 1,
'submit': 0
},
# DocType, Support Ticket
{
'doctype': 'DocType',
'name': u'Support Ticket'
},
# DocPerm
{
'create': 1,
'doctype': u'DocPerm',
'permlevel': 0,
'role': u'Guest',
'write': 1
},
# DocPerm
{
'create': 1,
'doctype': u'DocPerm',
'permlevel': 0,
'role': u'Customer',
'write': 1
},
# DocPerm
{
'create': 1,
'doctype': u'DocPerm',
'permlevel': 0,
'role': u'Support Team',
'write': 1
},
# DocPerm
{
'create': 0,
'doctype': u'DocPerm',
'permlevel': 1,
'role': u'Support Team',
'write': 1
},
# DocPerm
{
'create': 0,
'doctype': u'DocPerm',
'permlevel': 2,
'role': u'Support Team',
'write': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'naming_series',
'fieldtype': u'Select',
'hidden': 0,
'label': u'Naming Series',
'no_copy': 1,
'options': u'SUP',
'permlevel': 0,
'print_hide': 1,
'reqd': 0,
'search_index': 0
},
# DocField
{
'colour': u'White:FFF',
'default': u'Open',
'doctype': u'DocField',
'fieldname': u'status',
'fieldtype': u'Select',
'in_filter': 0,
'label': u'Status',
'no_copy': 1,
'oldfieldname': u'status',
'oldfieldtype': u'Select',
'options': u'\nOpen\nTo Reply\nWaiting for Customer\nHold\nClosed',
'permlevel': 1,
'reqd': 0,
'search_index': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'subject',
'fieldtype': u'Text',
'in_filter': 1,
'label': u'Subject',
'permlevel': 0,
'reqd': 1
},
# DocField
{
'depends_on': u'eval:doc.__islocal',
'doctype': u'DocField',
'fieldname': u'raised_by',
'fieldtype': u'Data',
'in_filter': 1,
'label': u'Raised By (Email)',
'oldfieldname': u'raised_by',
'oldfieldtype': u'Data',
'permlevel': 0,
'reqd': 1
},
# DocField
{
'depends_on': u'eval:doc.__islocal',
'doctype': u'DocField',
'fieldname': u'description',
'fieldtype': u'Text',
'label': u'Description',
'oldfieldname': u'problem_description',
'oldfieldtype': u'Text',
'permlevel': 0,
'reqd': 0
},
# DocField
{
'depends_on': u'eval:!doc.__islocal',
'doctype': u'DocField',
'fieldname': u'thread_html',
'fieldtype': u'HTML',
'label': u'Thread HTML',
'permlevel': 1
},
# DocField
{
'depends_on': u'eval:!doc.__islocal',
'doctype': u'DocField',
'fieldname': u'new_response',
'fieldtype': u'Text',
'label': u'New Response',
'permlevel': 0
},
# DocField
{
'depends_on': u'eval:!doc.__islocal',
'doctype': u'DocField',
'fieldname': u'send',
'fieldtype': u'Button',
'label': u'Send',
'permlevel': 0
},
# DocField
{
'colour': u'White:FFF',
'doctype': u'DocField',
'fieldname': u'additional_info',
'fieldtype': u'Section Break',
'label': u'Additional Info',
'permlevel': 1
},
# DocField
{
'depends_on': u'eval:!doc.__islocal',
'doctype': u'DocField',
'fieldname': u'column_break0',
'fieldtype': u'Column Break',
'oldfieldtype': u'Column Break',
'permlevel': 1,
'width': u'50%'
},
# DocField
{
'colour': u'White:FFF',
'doctype': u'DocField',
'fieldname': u'customer',
'fieldtype': u'Link',
'in_filter': 1,
'label': u'Customer',
'oldfieldname': u'customer',
'oldfieldtype': u'Link',
'options': u'Customer',
'permlevel': 1,
'print_hide': 1,
'reqd': 0,
'search_index': 1,
'trigger': u'Client'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'customer_name',
'fieldtype': u'Data',
'in_filter': 1,
'label': u'Customer Name',
'oldfieldname': u'customer_name',
'oldfieldtype': u'Data',
'permlevel': 2,
'reqd': 0,
'search_index': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'address_display',
'fieldtype': u'Small Text',
'label': u'Address',
'permlevel': 2
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'contact_display',
'fieldtype': u'Data',
'label': u'Contact Name',
'permlevel': 2
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'contact_mobile',
'fieldtype': u'Data',
'label': u'Mobile No',
'permlevel': 2
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'contact_email',
'fieldtype': u'Data',
'label': u'Contact Email',
'oldfieldname': u'contact_no',
'oldfieldtype': u'Data',
'permlevel': 2
},
# DocField
{
'default': u'Today',
'doctype': u'DocField',
'fieldname': u'opening_date',
'fieldtype': u'Date',
'label': u'Opening Date',
'no_copy': 1,
'oldfieldname': u'opening_date',
'oldfieldtype': u'Date',
'permlevel': 1
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'opening_time',
'fieldtype': u'Time',
'label': u'Opening Time',
'no_copy': 1,
'oldfieldname': u'opening_time',
'oldfieldtype': u'Time',
'permlevel': 1
},
# DocField
{
'depends_on': u'eval:!doc.__islocal',
'doctype': u'DocField',
'fieldname': u'column_break1',
'fieldtype': u'Column Break',
'oldfieldtype': u'Column Break',
'permlevel': 1
},
# DocField
{
'colour': u'White:FFF',
'depends_on': u'eval:!doc.__islocal',
'doctype': u'DocField',
'fieldname': u'allocated_to',
'fieldtype': u'Link',
'in_filter': 1,
'label': u'Allocated To',
'oldfieldname': u'allocated_to',
'oldfieldtype': u'Link',
'options': u'Profile',
'permlevel': 1,
'search_index': 1
},
# DocField
{
'depends_on': u'eval:!doc.__islocal',
'doctype': u'DocField',
'fieldname': u'resolution_details',
'fieldtype': u'Text',
'label': u'Resolution Details',
'no_copy': 1,
'oldfieldname': u'resolution_details',
'oldfieldtype': u'Text',
'permlevel': 1
},
# DocField
{
'colour': u'White:FFF',
'depends_on': u'eval:!doc.__islocal',
'doctype': u'DocField',
'fieldname': u'resolution_date',
'fieldtype': u'Date',
'in_filter': 0,
'label': u'Resolution Date',
'no_copy': 1,
'oldfieldname': u'resolution_date',
'oldfieldtype': u'Date',
'permlevel': 1,
'search_index': 0
},
# DocField
{
'depends_on': u'eval:!doc.__islocal',
'doctype': u'DocField',
'fieldname': u'resolution_time',
'fieldtype': u'Time',
'label': u'Resolution Time',
'oldfieldname': u'resolution_time',
'oldfieldtype': u'Time',
'permlevel': 1
},
# DocField
{
'colour': u'White:FFF',
'doctype': u'DocField',
'fieldname': u'content_type',
'fieldtype': u'Data',
'hidden': 1,
'label': u'Content Type',
'permlevel': 0
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'file_list',
'fieldtype': u'Text',
'hidden': 1,
'label': u'File List',
'no_copy': 1,
'permlevel': 0,
'print_hide': 1
}
]

View File

@@ -0,0 +1,54 @@
// render
wn.doclistviews['Support Ticket'] = wn.views.ListView.extend({
me: this,
init: function(d) {
this._super(d)
this.fields = this.fields.concat([
"`tabSupport Ticket`.status",
"`tabSupport Ticket`.subject",
"`tabSupport Ticket`.description"
]);
this.stats = this.stats.concat(['status']);
this.show_hide_check_column();
},
prepare_data: function(data) {
this._super(data);
if(data.status=='Open' || data.status=='To Reply') {
data.label_type = 'important'
}
else if(data.status=='Closed') {
data.label_type = 'success'
}
else if(data.status=='Hold') {
data.label_type = 'info'
}
else if(data.status=='Waiting for Customer') {
data.label_type = 'info'
data.status = 'Waiting'
}
data.status_html = repl('<span class="label label-%(label_type)s">%(status)s</span>', data);
// escape double quotes
data.description = cstr(data.subject)
+ " | " + cstr(data.description);
data.description = data.description.replace(/"/gi, '\"')
.replace(/</gi, '&lt;').replace(/>/gi, '&gt;');
// description
if(data.description && data.description.length > 50) {
data.description = '<span title="'+data.description+'">' + data.description.substr(0,50) + '...</span>';
}
},
columns: [
{width: '3%', content: 'check'},
{width: '20%', content:'name'},
{width: '10%', content:'status_html'},
{width: '50%', content:'description+tags', css: {color:'#222'}},
{width: '14%', content:'modified', css: {'text-align': 'right', 'color':'#777'}}
]
});

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1,64 @@
# DocType, Support Ticket Response
[
# These values are common in all dictionaries
{
'creation': '2012-03-27 14:36:44',
'docstatus': 0,
'modified': '2012-03-27 14:36:44',
'modified_by': u'Administrator',
'owner': u'Administrator'
},
# These values are common for all DocType
{
'colour': u'White:FFF',
'doctype': 'DocType',
'istable': 1,
'module': u'Support',
'name': '__common__',
'section_style': u'Simple',
'show_in_menu': 0,
'version': 4
},
# These values are common for all DocField
{
'doctype': u'DocField',
'name': '__common__',
'parent': u'Support Ticket Response',
'parentfield': u'fields',
'parenttype': u'DocType',
'permlevel': 0
},
# DocType, Support Ticket Response
{
'doctype': 'DocType',
'name': u'Support Ticket Response'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'mail',
'fieldtype': u'Text',
'label': u'Mail'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'from_email',
'fieldtype': u'Data',
'label': u'From Email'
},
# DocField
{
'doctype': u'DocField',
'fieldname': u'content_type',
'fieldtype': u'Data',
'label': u'Content Type'
}
]

1
support/page/__init__.py Normal file
View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1,48 @@
<div class="layout-wrapper layout-wrapper-background">
<div class="appframe-area"></div>
<div class="layout-main-section">
<div style="width: 48%; float: left;">
<h4><a href="#!List/Support Ticket">Support Ticket</a></h4>
<p class="help">Support queries from customers via email or website</p>
<br>
<h4><a href="#!List/Customer Issue">Customer Issue</a></h4>
<p class="help">Customer Issue against a Serial No (warranty)</p>
<br>
<h4><a href="#!List/Maintenance Schedule">Maintenance Schedule</a></h4>
<p class="help">Plan for scheduled maintenance contracts</p>
<br>
<h4><a href="#!List/Maintenance Visit">Maintenance Visit</a></h4>
<p class="help">Visit report for maintenance visit</p>
<br>
<h4><a href="#!List/Newsletter">Newsletter</a></h4>
<p class="help">Send Newsletters to your contacts</p>
<br>
<h4><a href="#!List/Communication">Communication</a></h4>
<p class="help">Communication Log</p>
</div>
<div style="width: 48%; float: right;">
<h4><a href="#!List/Serial No">Serial No</a></h4>
<p class="help">Single unit of an Item</p>
</div>
<div style="clear: both"></div>
<hr>
<h3>Reports</h3>
<div class="reports-list"></div>
</div>
<div class="layout-side-section">
<div class="psidebar">
<div class="section">
<div class="section-head">Tools</div>
<div class="section-body">
<div class="section-item">
<a class="section-link"
title = "Pull support issue from support email account"
href="#!Form/Email Settings/Email Settings">Email Settings</a>
</div>
</div>
</div>
</div>
</div>
<div style="clear: both;"></div>
</div>

View File

@@ -0,0 +1,20 @@
// ERPNext - web based ERP (http://erpnext.com)
// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pscript['onload_support-home'] = function(wrapper) {
wrapper.appframe = new wn.ui.AppFrame($(wrapper).find('.appframe-area'), 'Support');
erpnext.module_page.setup_page('Support', wrapper);
}

View File

@@ -0,0 +1,28 @@
# Page, support-home
[
# These values are common in all dictionaries
{
'creation': '2012-02-21 13:23:35',
'docstatus': 0,
'modified': '2012-02-21 13:23:35',
'modified_by': u'Administrator',
'owner': u'Administrator'
},
# These values are common for all Page
{
'doctype': 'Page',
'module': u'Support',
'name': '__common__',
'page_name': u'support-home',
'standard': u'Yes',
'title': u'Support Home'
},
# Page, support-home
{
'doctype': 'Page',
'name': u'support-home'
}
]

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1,25 @@
// ERPNext - web based ERP (http://erpnext.com)
// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
report.customize_filters = function() {
this.hide_all_filters();
this.mytabs.items['Select Columns'].hide();
this.mytabs.items['More Filters'].hide()
this.filter_fields_dict['Serial No'+FILTER_SEP +'Territory'].df.filter_hide = 0;
this.filter_fields_dict['Serial No'+FILTER_SEP +'Item Group'].df.filter_hide = 0;
this.filter_fields_dict['Serial No'+FILTER_SEP +'Territory'].df.in_first_page = 1;
this.filter_fields_dict['Serial No'+FILTER_SEP +'Item Group'].df.in_first_page = 1;
}

View File

@@ -0,0 +1,87 @@
# ERPNext - web based ERP (http://erpnext.com)
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# ADD NEW COLUMNS
from __future__ import unicode_literals
row_list = [['Item Group','Data','150px',''],
['Out of AMC','Int','150px',''],
['Under AMC','Int','150px',''],
['Out of Warranty','Int','150px',''],
['Under Warranty','Int','150px',''],
['Total','Int','150px','']
]
for r in row_list:
colnames.append(r[0])
coltypes.append(r[1])
colwidths.append(r[2])
coloptions.append(r[3])
col_idx[r[0]] = len(colnames)-1
#ADD VALUES TO THE COLUMN
out=[]
oa,ua,ow,uw,sum=0,0,0,0,0
nowdate = nowdate()
for r in res:
cc = r[col_idx['Territory']]
item_groups = sql("select distinct item_group from `tabSerial No` where territory = '%s' and item_group like '%%%s'" %(cc,filter_values.get('item_group')))
for col in range(len(colnames)-1): # this would make all first row blank. just for look
r.append('')
out.append(r)
# Add Totals for each Territory
# -----------------------------
det = sql("select COUNT(CASE WHEN amc_expiry_date > '%s' THEN name ELSE NULL END), COUNT(CASE WHEN amc_expiry_date <= '%s' THEN name ELSE NULL END), COUNT(CASE WHEN warranty_expiry_date > '%s' THEN name ELSE NULL END), COUNT(CASE WHEN warranty_expiry_date <= '%s' THEN name ELSE NULL END) from `tabSerial No` where territory = '%s' and item_group like '%%%s'" %(nowdate,nowdate,nowdate,nowdate,cc,filter_values.get('item_group')))
r[col_idx['Item Group']] = ''
r[col_idx['Out of AMC']] = cstr(det[0][0])
r[col_idx['Under AMC']] = cstr(det[0][1])
r[col_idx['Out of Warranty']] = cstr(det[0][2])
r[col_idx['Under Warranty']] = cstr(det[0][3])
tot = cint(det[0][0]) + cint(det[0][1]) + cint(det[0][2]) + cint(det[0][3])
r[col_idx['Total']] = cstr(tot)
oa += cint(det[0][0])
ua += cint(det[0][1])
ow += cint(det[0][2])
uw += cint(det[0][3])
sum += tot
# Add Brand Details belonging to Territory
# ----------------------------------------
for br in item_groups:
br_det = sql("select COUNT(CASE WHEN amc_expiry_date > '%s' THEN name ELSE NULL END), COUNT(CASE WHEN amc_expiry_date <= '%s' THEN name ELSE NULL END), COUNT(CASE WHEN warranty_expiry_date > '%s' THEN name ELSE NULL END), COUNT(CASE WHEN warranty_expiry_date <= '%s' THEN name ELSE NULL END) from `tabSerial No` where territory = '%s' and item_group = '%s'"%(nowdate,nowdate,nowdate,nowdate,cc,br[0]))
t_row = ['' for i in range(len(colnames))]
t_row[col_idx['Item Group']] = br[0]
t_row[col_idx['Out of AMC']] = cint(br_det[0][0])
t_row[col_idx['Under AMC']] = cint(br_det[0][1])
t_row[col_idx['Out of Warranty']] = cint(br_det[0][2])
t_row[col_idx['Under Warranty']] = cint(br_det[0][3])
tot = cint(br_det[0][0]) + cint(br_det[0][1]) + cint(br_det[0][2])+ cint(br_det[0][3])
t_row[col_idx['Total']] = tot
out.append(t_row)
#ADD NEW ROW
# ----------
newrow=['','TOTAL',oa,ua,ow,uw,sum]
out.append(newrow)
res=out

View File

@@ -0,0 +1,35 @@
# Search Criteria, amc_summary
[
# These values are common in all dictionaries
{
'creation': '2012-04-03 12:49:50',
'docstatus': 0,
'modified': '2012-04-03 12:49:50',
'modified_by': u'Administrator',
'owner': u'Administrator'
},
# These values are common for all Search Criteria
{
'add_cond': u"`tabSerial No`.`territory` is not null\n`tabSerial No`.`territory` != ''\n`tabSerial No`.`status` not in ('In Store', 'Scrapped')",
'columns': u'Serial No\x01Territory',
'criteria_name': u'AMC Summary',
'doc_type': u'Serial No',
'doctype': 'Search Criteria',
'filters': u"{'Serial No\x01Saved':1,'Serial No\x01Status':''}",
'group_by': u'`tabSerial No`.`cost_center`',
'module': u'Support',
'name': '__common__',
'page_len': 50,
'sort_by': u'`tabSerial No`.`cost_center`',
'sort_order': u'ASC',
'standard': u'Yes'
},
# Search Criteria, amc_summary
{
'doctype': 'Search Criteria',
'name': u'amc_summary'
}
]

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1,23 @@
// ERPNext - web based ERP (http://erpnext.com)
// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
report.customize_filters = function() {
this.filter_fields_dict['Customer Issue'+FILTER_SEP +'Status'].df.in_first_page = 1;
this.filter_fields_dict['Customer Issue'+FILTER_SEP +'Allocated To'].df.in_first_page = 1;
this.filter_fields_dict['Customer Issue'+FILTER_SEP +'Company'].df['report_default'] = sys_defaults.company;
}
this.mytabs.items['Select Columns'].hide()

View File

@@ -0,0 +1,33 @@
# Search Criteria, customer_issues
[
# These values are common in all dictionaries
{
'creation': '2012-04-03 12:49:51',
'docstatus': 0,
'modified': '2012-04-03 12:49:51',
'modified_by': u'Administrator',
'owner': u'Administrator'
},
# These values are common for all Search Criteria
{
'columns': u'Customer Issue\x01ID,Customer Issue\x01Status,Customer Issue\x01Complaint Date,Customer Issue\x01Complaint,Customer Issue\x01Item Code,Customer Issue\x01Item Name,Customer Issue\x01Allocated To,Customer Issue\x01Allocated On,Customer Issue\x01Resolved By,Customer Issue\x01Resolution Date,Customer Issue\x01Customer Name,Customer Issue\x01Fiscal Year',
'criteria_name': u'Customer Issues',
'doc_type': u'Customer Issue',
'doctype': 'Search Criteria',
'filters': u"{'Customer Issue\x01Saved':1,'Customer Issue\x01Submitted':1,'Customer Issue\x01Status':'','Customer Issue\x01Fiscal Year':''}",
'module': u'Support',
'name': '__common__',
'page_len': 50,
'sort_by': u'`tabCustomer Issue`.`name`',
'sort_order': u'DESC',
'standard': u'Yes'
},
# Search Criteria, customer_issues
{
'doctype': 'Search Criteria',
'name': u'customer_issues'
}
]

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1,20 @@
// ERPNext - web based ERP (http://erpnext.com)
// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
report.customize_filters = function() {
this.filter_fields_dict['Sales Order'+FILTER_SEP +'Company'].df['report_default'] = sys_defaults.company;
this.filter_fields_dict['Sales Order'+FILTER_SEP +'Fiscal Year'].df['report_default'] = sys_defaults.fiscal_year;
}

View File

@@ -0,0 +1,36 @@
# Search Criteria, maintenance_orderwise_pending_amount_to_bill
[
# These values are common in all dictionaries
{
'creation': '2012-04-03 12:49:51',
'docstatus': 0,
'modified': '2012-04-03 12:49:51',
'modified_by': u'Administrator',
'owner': u'ashwini@webnotestech.com'
},
# These values are common for all Search Criteria
{
'add_col': u"SUM((`tabSales Order Item`.`qty` - `tabSales Order Item`.`billed_qty`) * `tabSales Order Item`.`basic_rate`) AS 'Pending Amount'",
'add_cond': u"`tabSales Order`.status != 'Stopped'\n`tabSales Order`.order_type='Maintenance'",
'columns': u'Sales Order\x01ID,Sales Order\x01Customer,Sales Order\x01Customer Name,Sales Order\x01Customer Address,Sales Order\x01Status,Sales Order\x01% Billed,Sales Order\x01Sales Order Date',
'criteria_name': u'Maintenance Orderwise Pending Amount To Bill',
'doc_type': u'Sales Order Item',
'doctype': 'Search Criteria',
'filters': u"{'Sales Order\x01Saved':1,'Sales Order\x01Submitted':1,'Sales Order\x01Status':'','Sales Order\x01Fiscal Year':''}",
'module': u'Support',
'name': '__common__',
'page_len': 50,
'parent_doc_type': u'Sales Order',
'sort_by': u'`tabSales Order`.`name`',
'sort_order': u'DESC',
'standard': u'Yes'
},
# Search Criteria, maintenance_orderwise_pending_amount_to_bill
{
'doctype': 'Search Criteria',
'name': u'maintenance_orderwise_pending_amount_to_bill'
}
]

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1,29 @@
// ERPNext - web based ERP (http://erpnext.com)
// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
report.customize_filters = function() {
this.filter_fields_dict['Maintenance Schedule Detail'+FILTER_SEP +'From Scheduled Date'].df.in_first_page = 1;
this.filter_fields_dict['Maintenance Schedule Detail'+FILTER_SEP +'To Scheduled Date'].df.in_first_page = 1;
this.filter_fields_dict['Maintenance Schedule Detail'+FILTER_SEP +'Incharge Name'].df.in_first_page = 1;
this.filter_fields_dict['Maintenance Schedule'+FILTER_SEP +'Customer'].df.in_first_page = 1;
this.filter_fields_dict['Maintenance Schedule'+FILTER_SEP +'Customer Name'].df.in_first_page = 1;
this.filter_fields_dict['Maintenance Schedule'+FILTER_SEP +'Sales Order No'].df.in_first_page = 1;
//this.filter_fields_dict['Maintenance Schedule'+FILTER_SEP +'Status'].df.in_first_page = 0;
this.filter_fields_dict['Maintenance Schedule'+FILTER_SEP +'Company'].df['report_default'] = sys_defaults.company;
}
this.mytabs.items['Select Columns'].hide()

View File

@@ -0,0 +1,34 @@
# Search Criteria, maintenance_schedule_details
[
# These values are common in all dictionaries
{
'creation': '2012-04-03 12:49:51',
'docstatus': 0,
'modified': '2012-04-03 12:49:51',
'modified_by': u'Administrator',
'owner': u'nabin@webnotestech.com'
},
# These values are common for all Search Criteria
{
'columns': u'Maintenance Schedule Detail\x01Item Code,Maintenance Schedule Detail\x01Item Name,Maintenance Schedule Detail\x01Serial No,Maintenance Schedule Detail\x01Incharge Name,Maintenance Schedule Detail\x01Scheduled Date,Maintenance Schedule\x01Customer Name,Maintenance Schedule\x01Address,Maintenance Schedule\x01Sales Order No',
'criteria_name': u'Maintenance Schedule Details',
'doc_type': u'Maintenance Schedule Detail',
'doctype': 'Search Criteria',
'filters': u"{'Maintenance Schedule\x01Submitted':1,'Maintenance Schedule\x01Status':''}",
'module': u'Support',
'name': '__common__',
'page_len': 50,
'parent_doc_type': u'Maintenance Schedule',
'sort_by': u'`tabMaintenance Schedule Detail`.`item_code`',
'sort_order': u'DESC',
'standard': u'Yes'
},
# Search Criteria, maintenance_schedule_details
{
'doctype': 'Search Criteria',
'name': u'maintenance_schedule_details'
}
]

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1,25 @@
// ERPNext - web based ERP (http://erpnext.com)
// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//this.mytabs.items['Select Columns'].hide();
report.customize_filters = function() {
this.filter_fields_dict['Serial No'+FILTER_SEP +'Status'].df.in_first_page = 0;
this.filter_fields_dict['Serial No'+FILTER_SEP +'Customer'].df.in_first_page = 1;
this.filter_fields_dict['Serial No'+FILTER_SEP +'Customer Name'].df.in_first_page = 1;
this.filter_fields_dict['Serial No'+FILTER_SEP +'Maintenance Status'].df.in_first_page = 1;
}

View File

@@ -0,0 +1,33 @@
# Search Criteria, warranty-amc_expiry_details
[
# These values are common in all dictionaries
{
'creation': '2012-04-03 12:49:53',
'docstatus': 0,
'modified': '2012-04-03 12:49:53',
'modified_by': u'Administrator',
'owner': u'Administrator'
},
# These values are common for all Search Criteria
{
'columns': u'Serial No\x01ID,Serial No\x01Item Code,Serial No\x01Description,Serial No\x01Status,Serial No\x01Item Group,Serial No\x01Purchase Receipt No,Serial No\x01Delivery Note No,Serial No\x01Customer,Serial No\x01Customer Name,Serial No\x01AMC Expiry Date,Serial No\x01Warranty Expiry Date',
'criteria_name': u'Warranty/AMC Expiry Details',
'doc_type': u'Serial No',
'doctype': 'Search Criteria',
'filters': u"{'Serial No\x01Saved':1,'Serial No\x01Status':'','Serial No\x01Maintenance Status':''}",
'module': u'Support',
'name': '__common__',
'page_len': 50,
'sort_by': u'`tabSerial No`.`name`',
'sort_order': u'DESC',
'standard': u'Yes'
},
# Search Criteria, warranty-amc_expiry_details
{
'doctype': 'Search Criteria',
'name': u'warranty-amc_expiry_details'
}
]

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1,26 @@
// ERPNext - web based ERP (http://erpnext.com)
// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
report.customize_filters = function() {
this.hide_all_filters();
this.mytabs.items['Select Columns'].hide();
this.mytabs.items['More Filters'].hide();
this.add_filter({fieldname:'based_on', label:'Based On', fieldtype:'Select', options:'Territory'+NEWLINE+'Item Group',ignore:1,parent:'Serial No',in_first_page:1, report_default:'Item Group'});
}
report.aftertableprint = function(t) {
$yt(t,'*',1,{whiteSpace:'pre'});
}

View File

@@ -0,0 +1,54 @@
# ERPNext - web based ERP (http://erpnext.com)
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals
opt = filter_values.get('based_on')
opt_dict = {'Territory':'territory', 'Item Group':'item_group'}
# ADD NEW COLUMNS
row_list = [[opt,'Data','150px',''],
['Out of AMC','Int','150px',''],
['Under AMC','Int','150px',''],
['Out of Warranty','Int','150px',''],
['Under Warranty','Int','150px',''],
['Total','Int','150px','']]
for r in row_list:
colnames.append(r[0])
coltypes.append(r[1])
colwidths.append(r[2])
coloptions.append(r[3])
col_idx[r[0]] = len(colnames)-1
#ADD VALUES TO THE COLUMN
out=[]
oa,ua,ow,uw,sum=0,0,0,0,0
nowdate = nowdate()
for r in res:
lft_rgt = sql("select lft, rgt from `tab%s` where name = '%s'" % (opt,r[col_idx[opt]].strip()))
det = sql("select COUNT(CASE WHEN t1.amc_expiry_date < '%s' THEN t1.name ELSE NULL END), COUNT(CASE WHEN t1.amc_expiry_date >= '%s' THEN t1.name ELSE NULL END), COUNT(CASE WHEN t1.warranty_expiry_date < '%s' THEN t1.name ELSE NULL END), COUNT(CASE WHEN t1.warranty_expiry_date >= '%s' THEN t1.name ELSE NULL END) from `tabSerial No` t1, `tab%s` t2 where t1.%s = t2.name and t2.lft>= '%s' and t2. rgt <= '%s' and t1.status = 'Delivered' and ifnull(item_group,'')!='' and ifnull(territory,'')!=''" %(nowdate,nowdate,nowdate,nowdate,opt, opt_dict[opt], lft_rgt[0][0], lft_rgt[0][1]))
r.append(cint(det[0][0]))
r.append(cint(det[0][1]))
r.append(cint(det[0][2]))
r.append(cint(det[0][3]))
tot = cint(det[0][0]) + cint(det[0][1]) + cint(det[0][2]) + cint(det[0][3])
r.append(tot)
out.append(r)

View File

@@ -0,0 +1 @@
SELECT CONCAT(REPEAT(' ', COUNT(parent.name) - 1), node.name) AS name FROM `tab%(based_on)s` AS node,`tab%(based_on)s` AS parent WHERE node.lft BETWEEN parent.lft AND parent.rgt AND node.docstatus !=2 GROUP BY node.name ORDER BY node.lft

View File

@@ -0,0 +1,32 @@
# Search Criteria, warranty-amc_summary
[
# These values are common in all dictionaries
{
'creation': '2012-04-03 12:49:53',
'docstatus': 0,
'modified': '2012-04-03 12:49:53',
'modified_by': u'Administrator',
'owner': u'Administrator'
},
# These values are common for all Search Criteria
{
'criteria_name': u'Warranty/AMC Summary',
'doc_type': u'Serial No',
'doctype': 'Search Criteria',
'filters': u"{'Serial No\x01Saved':1,'Serial No\x01Status':''}",
'module': u'Support',
'name': '__common__',
'page_len': 50,
'sort_by': u'name',
'sort_order': u'DESC',
'standard': u'Yes'
},
# Search Criteria, warranty-amc_summary
{
'doctype': 'Search Criteria',
'name': u'warranty-amc_summary'
}
]