From dd9d4bbdea5f7d073eb615f85e2eb583cbbde9b9 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 2 Aug 2012 10:56:40 +0530 Subject: [PATCH 01/12] repost stock patch due to wrong packing list --- .../repost_stock_due_to_wrong_packing_list.py | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/erpnext/patches/july_2012/repost_stock_due_to_wrong_packing_list.py b/erpnext/patches/july_2012/repost_stock_due_to_wrong_packing_list.py index 9e9da7f5ec..ad6a23a171 100644 --- a/erpnext/patches/july_2012/repost_stock_due_to_wrong_packing_list.py +++ b/erpnext/patches/july_2012/repost_stock_due_to_wrong_packing_list.py @@ -1,9 +1,10 @@ def repost_reserved_qty(): import webnotes + from webnotes.utils import flt bins = webnotes.conn.sql("select item_code, warehouse, name, reserved_qty from `tabBin`") for d in bins: reserved_qty = webnotes.conn.sql(""" - select sum((dnpi.qty/so_item.qty)*(so_item.qty - ifnull(so_item.delivered_qty, 0))), so.transaction_date + select sum((dnpi.qty/so_item.qty)*(so_item.qty - ifnull(so_item.delivered_qty, 0))) from `tabDelivery Note Packing Item` dnpi, `tabSales Order Item` so_item, `tabSales Order` so @@ -18,13 +19,11 @@ def repost_reserved_qty(): and dnpi.warehouse = %s """, (d[0], d[1])) if flt(d[3]) != flt(reserved_qty[0][0]): - print d, reserved_qty - #webnotes.conn.sql(""" - # update `tabBin` set reserved_qty = %s where name = %s - #""", (reserved_qty and reserved_qty[0][0] or 0, d[2])) + print d[3], reserved_qty[0][0] + webnotes.conn.sql(""" + update `tabBin` set reserved_qty = %s where name = %s + """, (reserved_qty and reserved_qty[0][0] or 0, d[2])) -repost_reserved_qty() - def cleanup_wrong_sle(): sle = webnotes.conn.sql(""" select item_code, warehouse, voucher_no, name @@ -44,10 +43,10 @@ def cleanup_wrong_sle(): """) if sle: print sle - # for d in sle: - # webnotes.conn.sql("update `tabStock Ledger Entry` set is_cancelled = 'Yes' where name = %s", d[3]) - # create_comment(d[3]) - # repost_bin(d[0], d[1]) + for d in sle: + webnotes.conn.sql("update `tabStock Ledger Entry` set is_cancelled = 'Yes' where name = %s", d[3]) + create_comment(d[3]) + repost_bin(d[0], d[1]) def create_comment(dn): from webnotes.model.doc import Document From a4fe7180f4a58d2771b9bf7bee6af7fcbe2cf09c Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Thu, 2 Aug 2012 13:07:23 +0530 Subject: [PATCH 02/12] html generation moved from web.py to web_cache.py so it can be called from other places as a response from server.py --- erpnext/website/utils.py | 34 ++++++++++++++++++++++++++++++++++ erpnext/website/web_cache.py | 2 ++ public/web.py | 33 +-------------------------------- 3 files changed, 37 insertions(+), 32 deletions(-) diff --git a/erpnext/website/utils.py b/erpnext/website/utils.py index 22fcce741f..470dbd7192 100644 --- a/erpnext/website/utils.py +++ b/erpnext/website/utils.py @@ -41,3 +41,37 @@ def page_name(title): name = title.lower() name = re.sub('[~!@#$%^&*()<>,."\']', '', name) return '-'.join(name.split()[:4]) + +def render(page_name): + """render html page""" + import webnotes + try: + if page_name: + html = get_html(page_name) + else: + html = get_html('index') + except Exception, e: + html = get_html('404') + + print "Content-Type: text/html" + print + print html.encode('utf-8') + +def get_html(page_name): + """get page html""" + page_name = scrub_page_name(page_name) + comments = get_comments(page_name) + + import website.web_cache + html = website.web_cache.get_html(page_name, comments) + return html + +def get_comments(page_name): + import webnotes + + if page_name == '404': + comments = """error: %s""" % webnotes.getTraceback() + else: + comments = """page: %s""" % page_name + + return comments diff --git a/erpnext/website/web_cache.py b/erpnext/website/web_cache.py index 893f7f2d2a..e08499baf1 100644 --- a/erpnext/website/web_cache.py +++ b/erpnext/website/web_cache.py @@ -91,6 +91,7 @@ def get_predefined_pages(): return page_list def prepare_args(page_name): + import webnotes if page_name == 'index': page_name = get_home_page() @@ -98,6 +99,7 @@ def prepare_args(page_name): args = { 'template': 'pages/%s.html' % page_name, 'name': page_name, + 'webnotes': webnotes } else: args = get_doc_fields(page_name) diff --git a/public/web.py b/public/web.py index 34d38feca0..dcacfcd106 100755 --- a/public/web.py +++ b/public/web.py @@ -40,39 +40,8 @@ def init(): def respond(): import webnotes - try: - if 'page' in webnotes.form_dict: - html = get_html(webnotes.form_dict['page']) - else: - # show home page - html = get_html('index') - except Exception, e: - html = get_html('404') - - print "Content-Type: text/html" - print - print html.encode('utf-8') - -def get_html(page_name): import website.utils - page_name = website.utils.scrub_page_name(page_name) - - comments = get_comments(page_name) - - import website.web_cache - html = website.web_cache.get_html(page_name, comments) - - return html - -def get_comments(page_name): - import webnotes - - if page_name == '404': - comments = """error: %s""" % webnotes.getTraceback() - else: - comments = """page: %s""" % page_name - - return comments + return website.utils.render(webnotes.form_dict.get('page')) if __name__=="__main__": init() From f0018b5e051b765a643f46491c17d924c799e417 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Thu, 2 Aug 2012 18:03:12 +0530 Subject: [PATCH 03/12] added unsubscribed fields in Lead and Contact and cleaned up sendmail function --- .../home/doctype/home_control/home_control.py | 16 --- .../project_control/project_control.py | 3 +- erpnext/projects/doctype/task/task.py | 5 +- erpnext/selling/doctype/lead/lead.js | 10 -- erpnext/selling/doctype/lead/lead.py | 56 -------- erpnext/selling/doctype/lead/lead.txt | 30 ++-- erpnext/selling/doctype/lead/lead_list.js | 3 +- .../doctype/opportunity/opportunity.py | 113 +-------------- .../doctype/email_digest/email_digest.py | 1 - .../doctype/email_settings/email_settings.py | 42 ++---- erpnext/startup/schedule_handlers.py | 39 ++--- erpnext/stock/doctype/item/item.py | 21 --- erpnext/utilities/doctype/contact/contact.txt | 134 ++---------------- .../doctype/blog_subscriber/__init__.py | 0 .../blog_subscriber/blog_subscriber.txt | 29 ---- erpnext/website/page/unsubscribe/__init__.py | 0 .../website/page/unsubscribe/unsubscribe.html | 13 -- .../website/page/unsubscribe/unsubscribe.js | 37 ----- .../website/page/unsubscribe/unsubscribe.py | 26 ---- .../website/page/unsubscribe/unsubscribe.txt | 43 ------ .../website/templates/pages/unsubscribed.html | 11 ++ 21 files changed, 70 insertions(+), 562 deletions(-) delete mode 100644 erpnext/website/doctype/blog_subscriber/__init__.py delete mode 100644 erpnext/website/doctype/blog_subscriber/blog_subscriber.txt delete mode 100644 erpnext/website/page/unsubscribe/__init__.py delete mode 100644 erpnext/website/page/unsubscribe/unsubscribe.html delete mode 100644 erpnext/website/page/unsubscribe/unsubscribe.js delete mode 100644 erpnext/website/page/unsubscribe/unsubscribe.py delete mode 100644 erpnext/website/page/unsubscribe/unsubscribe.txt create mode 100644 erpnext/website/templates/pages/unsubscribed.html diff --git a/erpnext/home/doctype/home_control/home_control.py b/erpnext/home/doctype/home_control/home_control.py index fba711e642..b1ddda4011 100644 --- a/erpnext/home/doctype/home_control/home_control.py +++ b/erpnext/home/doctype/home_control/home_control.py @@ -118,22 +118,6 @@ class DocType: out[dt][s[0]] = cint(cnt) return out - def send_feedback(self, args): - args = json.loads(args) - - fb_sender = sql("select concat_ws(' ',first_name, last_name), email from tabProfile where name=%s", session['user']) - fb_subject = 'Feedback : ' + args['subject'] - - - fb_msg = ''' -
-
%s wrote,
-
%s
-
- ''' % (fb_sender[0][0], args['feedback']) - - sendmail('info@webnotestech.com', fb_sender[0][1], msg = fb_msg, subject=args['subject'],parts=[], cc=[], attach=[]) - def get_dt_help(self,dt): return sql("select description from tabDocType where name=%s",dt)[0][0] or '' diff --git a/erpnext/projects/doctype/project_control/project_control.py b/erpnext/projects/doctype/project_control/project_control.py index 0dcd1a94f2..9928ffd35a 100644 --- a/erpnext/projects/doctype/project_control/project_control.py +++ b/erpnext/projects/doctype/project_control/project_control.py @@ -155,7 +155,6 @@ def sent_reminder_task():

If you have already completed this task, please update the system

Good Luck!

(This notification is autogenerated)

""" % i - sendmail(i['allocated_to'], sender='automail@webnotestech.com', msg=msg2,send_now=1, \ - subject='A task has been assigned') + sendmail(i['allocated_to'], msg=msg2, subject='A task has been assigned') sql("update `tabTask` set sent_reminder='1' where name='%(name)s' and allocated_to= '%(allocated_to)s'" % i) diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py index 552a4c86be..bfd98db127 100644 --- a/erpnext/projects/doctype/task/task.py +++ b/erpnext/projects/doctype/task/task.py @@ -115,10 +115,7 @@ class DocType:

Expected End Date: %(exp_end_date)s

Details: %(description)s

(This notification is autogenerated)

""" % i - sendmail(self.doc.allocated_to, sender='automail@webnotestech.com', msg=msg2,send_now=1,\ - subject= task_label + self.doc.subject) - - + sendmail(self.doc.allocated_to, msg=msg2,subject= task_label + self.doc.subject) #validate before closing task def validate_for_closed(self): diff --git a/erpnext/selling/doctype/lead/lead.js b/erpnext/selling/doctype/lead/lead.js index 57f2bee185..504b0bdc7a 100644 --- a/erpnext/selling/doctype/lead/lead.js +++ b/erpnext/selling/doctype/lead/lead.js @@ -110,16 +110,6 @@ cur_frm.cscript['Create Customer'] = function(){ ); } -// send email -// =============================================================== -cur_frm.cscript.send_email = function(doc,cdt,cdn){ - if(doc.__islocal != 1){ - $c_obj(make_doclist(doc.doctype, doc.name),'send_mail','',function(r,rt){}); - }else{ - msgprint("Please save lead first before sending email") - } -} - // Create New Opportunity // =============================================================== cur_frm.cscript['Create Opportunity'] = function(){ diff --git a/erpnext/selling/doctype/lead/lead.py b/erpnext/selling/doctype/lead/lead.py index 166e4fa706..cdb278ec58 100644 --- a/erpnext/selling/doctype/lead/lead.py +++ b/erpnext/selling/doctype/lead/lead.py @@ -82,15 +82,9 @@ class DocType: def on_update(self): - # Add to calendar - # ======================================================================== if self.doc.contact_by: self.add_calendar_event() - if session['user'] == 'Guest': - if self.doc.email_id: - self.send_email_notification() - if not self.doc.naming_series: if session['user'] == 'Guest': import webnotes.model.doctype @@ -102,37 +96,6 @@ class DocType: else: msgprint("Please specify naming series") raise Exception - - def send_email_notification(self): - if not validate_email_add(self.doc.email_id.strip(' ')): - msgprint('error:%s is not a valid email id' % self.doc.email_id.strip(' ')) - raise Exception - else: - subject = 'Thank you for interest in erpnext' - - sendmail([self.doc.email_id.strip(' ')], sender = sender_email[0][0], subject = subject , parts = [['text/html', self.get_notification_msg()]]) - msgprint("Mail Sent") - - def get_notification_msg(self): - t = """ - - - Dear %s,

- - Thank you for contacting us.

- - You have left following message for us,
- %s -

- - You will receive reply on this shortly.

- - Cheers! - - - """ % (self.doc.lead_name, self.doc.remark) - - return t # Add to Calendar # =========================================================================== @@ -157,25 +120,6 @@ class DocType: ev.ref_name = self.doc.name ev.save(1) - -#-----------------Email-------------------------------------------- - def send_emails(self, email=[], subject='', message=''): - if email: - sendmail(email, sender = webnotes.user.name, subject = subject , parts = [['text/html', message]]) - msgprint("Mail Sent") - self.add_in_follow_up(message,'Email') - -#-------------------------Checking Sent Mails Details---------------------------------------------- - def send_mail(self): - if not self.doc.subject or not self.doc.message: - msgprint("Please enter subject & message in their respective fields.") - elif not self.doc.email_id: - msgprint("Recipient not specified. Please add email id of lead in 'Email id' field provided in 'Contact Info' section.") - raise Exception - else : - self.send_emails([self.doc.email_id.strip(' ')], subject = self.doc.subject ,message = self.doc.message) - -#---------------------- Add details in follow up table---------------- def add_in_follow_up(self,message,type): import datetime child = addchild( self.doc, 'follow_up', 'Communication Log', 1, self.doclist) diff --git a/erpnext/selling/doctype/lead/lead.txt b/erpnext/selling/doctype/lead/lead.txt index b6aa8397d7..a467f3af18 100644 --- a/erpnext/selling/doctype/lead/lead.txt +++ b/erpnext/selling/doctype/lead/lead.txt @@ -3,9 +3,9 @@ # These values are common in all dictionaries { - 'creation': '2012-05-15 12:14:52', + 'creation': '2012-06-05 20:03:20', 'docstatus': 0, - 'modified': '2012-05-30 12:43:03', + 'modified': '2012-08-02 18:01:53', 'modified_by': u'Administrator', 'owner': u'Administrator' }, @@ -505,23 +505,6 @@ 'permlevel': 0 }, - # DocField - { - 'colour': u'White:FFF', - 'description': u'Probability of lead converting to customer', - 'doctype': u'DocField', - 'fieldname': u'rating', - 'fieldtype': u'Select', - 'in_filter': 1, - 'label': u'Rating', - 'oldfieldname': u'rating', - 'oldfieldtype': u'Select', - 'options': u'\nHot\nWarm\nCold', - 'permlevel': 0, - 'reqd': 0, - 'search_index': 0 - }, - # DocField { 'default': u'__user', @@ -694,5 +677,14 @@ 'oldfieldtype': u'Small Text', 'permlevel': 1, 'print_hide': 1 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'unsubscribed', + 'fieldtype': u'Check', + 'label': u'Unsubscribed', + 'permlevel': 0 } ] \ No newline at end of file diff --git a/erpnext/selling/doctype/lead/lead_list.js b/erpnext/selling/doctype/lead/lead_list.js index ca18dc6941..b876d52cbb 100644 --- a/erpnext/selling/doctype/lead/lead_list.js +++ b/erpnext/selling/doctype/lead/lead_list.js @@ -4,8 +4,7 @@ wn.doclistviews['Lead'] = wn.views.ListView.extend({ this.fields = this.fields.concat([ 'tabLead.lead_name', 'tabLead.status', - 'tabLead.source', - 'tabLead.rating' + 'tabLead.source' ]); this.stats = this.stats.concat(['status', 'source', 'rating', 'company']); }, diff --git a/erpnext/selling/doctype/opportunity/opportunity.py b/erpnext/selling/doctype/opportunity/opportunity.py index 1bcde25059..20dcef386a 100644 --- a/erpnext/selling/doctype/opportunity/opportunity.py +++ b/erpnext/selling/doctype/opportunity/opportunity.py @@ -197,118 +197,7 @@ class DocType(TransactionBase): set(self.doc, 'status', 'Opportunity Lost') set(self.doc, 'order_lost_reason', arg) return 'true' - - - # On Send Email - # ==================================================================================================================== - #def send_emails(self,email,sender,subject,message): - # if email: - # sendmail(email,sender,subject=subject or 'Opportunity',parts=[['text/plain',message or self.get_enq_summary()]]) - - # Prepare HTML Table and Enter Opportunity Items in it, which will be added in enq summary - # ==================================================================================================================== - def quote_table(self): - if getlist(self.doclist,'enq_details'): - header_lbl = ['Item Code','Item Name','Description','Reqd Qty','UOM'] - item_tbl = '''''' - for i in header_lbl: - item_header = '''''' % i - item_tbl += item_header - item_tbl += '''''' - - for d in getlist(self.doclist,'enq_details'): - item_det = ''' - - - - - - ''' % (d.item_code,d.item_name,d.description,d.reqd_qty,d.uom) - item_tbl += item_det - item_tbl += '''
%s
%s%s%s%s%s
''' - return item_tbl - - # Prepare HTML Page containing summary of Opportunity, which will be sent as message in E-mail - # ==================================================================================================================== - def get_enq_summary(self): - - t = """ - - -
-
Request For Quotation
-
%(from_company)s
-
%(company_address)s
-
- -
Quotation Items
-
- - - -
Opportunity No: %(name)s
Opening Date: %(transaction_date)s
Expected By Date: %(expected_date)s
-
- -
Terms and Conditions
-
%(terms_and_conditions)s
- -
Contact Details
-
- - - -
Contact Person: %(contact_person)s
Contact No: %(contact_no)s
Email: %(email)s
- """ % (self.doc.fields) - - t += """
Quotation Items
%s
-
-To login into the system, use link :
http://67.205.111.118/v160/login.html


-
- - - """ % (self.quote_table()) - return t - - #-----------------Email-------------------------------------------- - # ==================================================================================================================== - def send_emails(self, email=[], subject='', message=''): - if email: - sender_email= sql("Select email from `tabProfile` where name='%s'"%session['user']) - if sender_email and sender_email[0][0]: - attach_list=[] - for at in getlist(self.doclist,'enquiry_attachment_detail'): - if at.select_file: - attach_list.append(at.select_file) - cc_list=[] - if self.doc.cc_to: - for cl in (self.doc.cc_to.split(',')): - if not validate_email_add(cl.strip(' ')): - msgprint('error:%s is not a valid email id' % cl.strip(' ')) - raise Exception - cc_list.append(cl.strip(' ')) - sendmail(cc_list, sender=sender_email[0][0], subject=subject, parts=[['text/html', message]], attach=attach_list) - sendmail(email, sender=sender_email[0][0], subject=subject, parts=[['text/html', message]], cc=cc_list, attach=attach_list) - #sendmail(cc_list, sender = sender_email[0][0], subject = subject , parts = [['text/html', message]],attach=attach_list) - msgprint("Mail has been sent") - self.add_in_follow_up(message,'Email') - else: - msgprint("Please enter your mail id in Profile") - raise Exception - - #-------------------------Checking Sent Mails Details---------------------------------------------- - # ==================================================================================================================== - def sent_mail(self): - if not self.doc.subject or not self.doc.message: - msgprint("Please enter subject & message in their respective fields.") - elif not self.doc.email_id1: - msgprint("Recipient not specified. Please add email id in 'Send To'.") - raise Exception - else : - if not validate_email_add(self.doc.email_id1.strip(' ')): - msgprint('error:%s is not a valid email id' % self.doc.email_id1) - else: - self.send_emails([self.doc.email_id1.strip(' ')], subject = self.doc.subject ,message = self.doc.message) - + #---------------------- Add details in follow up table---------------- # ==================================================================================================================== def add_in_follow_up(self,message,type): diff --git a/erpnext/setup/doctype/email_digest/email_digest.py b/erpnext/setup/doctype/email_digest/email_digest.py index 1e382d198d..ac0f37844a 100644 --- a/erpnext/setup/doctype/email_digest/email_digest.py +++ b/erpnext/setup/doctype/email_digest/email_digest.py @@ -415,7 +415,6 @@ class DocType: from webnotes.utils.email_lib import sendmail try: - #webnotes.msgprint('in send') sendmail( recipients=recipient_list, sender='notifications+email_digest@erpnext.com', diff --git a/erpnext/setup/doctype/email_settings/email_settings.py b/erpnext/setup/doctype/email_settings/email_settings.py index 118dba2e1c..cb2865706c 100644 --- a/erpnext/setup/doctype/email_settings/email_settings.py +++ b/erpnext/setup/doctype/email_settings/email_settings.py @@ -24,44 +24,24 @@ class DocType: self.doc,self.doclist = doc,doclist def validate(self): - """ - Checks connectivity to email servers before saving - """ + """Checks connectivity to email servers before saving""" self.validate_outgoing() self.validate_incoming() - def validate_outgoing(self): - """ - Checks incoming email settings - """ + """Checks incoming email settings""" if self.doc.outgoing_mail_server: from webnotes.utils import cint - import _socket - from webnotes.utils.email_lib.send import EMail - import smtplib - out_email = EMail() - out_email.server = self.doc.outgoing_mail_server.encode('utf-8') - out_email.port = cint(self.doc.mail_port) - out_email.use_ssl = self.doc.use_ssl - try: - err_msg = "Login Id or Mail Password missing. Please enter and try again." - if not (self.doc.mail_login and self.doc.mail_password): - raise AttributeError, err_msg - out_email.login = self.doc.mail_login.encode('utf-8') - out_email.password = self.doc.mail_password.encode('utf-8') - except AttributeError, e: - webnotes.msgprint(err_msg) - raise e + from webnotes.utils.email_lib.smtp import SMTPServer + smtpserver = SMTPServer(login = self.doc.mail_login, + password = self.doc.mail_password, + server = self.doc.outgoing_mail_server, + port = cint(self.doc.mail_port), + use_ssl = self.doc.use_ssl + ) - # exceptions are handled in smtp_connect - sess = out_email.smtp_connect() - - try: - sess.quit() - except: - pass - + # exceptions are handled in session connect + sess = smtpserver.sess def validate_incoming(self): """ diff --git a/erpnext/startup/schedule_handlers.py b/erpnext/startup/schedule_handlers.py index a828feafaf..021cb1f600 100644 --- a/erpnext/startup/schedule_handlers.py +++ b/erpnext/startup/schedule_handlers.py @@ -24,27 +24,26 @@ def execute_all(): * get support email * recurring invoice """ - try: - from support.doctype.support_ticket import get_support_mails - get_support_mails() - except Exception, e: - scheduler.log('get_support_mails') - - try: - from accounts.doctype.gl_control.gl_control import manage_recurring_invoices - manage_recurring_invoices() - except Exception, e: - scheduler.log('manage_recurring_invoices') + # pull emails + from support.doctype.support_ticket import get_support_mails + run_fn(get_support_mails) + # run recurring invoices + from accounts.doctype.gl_control.gl_control import manage_recurring_invoices + run_fn(manage_recurring_invoices) + # bulk email + from webnotes.utils.email_lib.bulk import flush + run_fn(flush) def execute_daily(): - """email digest""" - try: - from setup.doctype.email_digest.email_digest import send - send() - except Exception, e: - scheduler.log('email_digest.send') + # email digest + from setup.doctype.email_digest.email_digest import send + run_fn(send) + + # send bulk emails + from webnotes.utils.email_lib.bulk import cleanup + run_fn(clear_outbox) def execute_weekly(): pass @@ -54,3 +53,9 @@ def execute_monthly(): def execute_hourly(): pass + +def run_fn(fn): + try: + fn() + except Exception, e: + scheduler.log(fn.func_name) diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index 9864fc909f..9e00dc12bf 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -181,27 +181,6 @@ class DocType: self.doc.is_asset_item = 'No' raise Exception - def check_min_inventory_level(self): - if self.doc.minimum_inventory_level: - total_qty = sql("select sum(projected_qty) from tabBin where item_code = %s",self.doc.name) - if flt(total_qty) < flt(self.doc.minimum_inventory_level): - msgprint("Your minimum inventory level is reached") - send_to = [] - send = sql("select t1.email from `tabProfile` t1,`tabUserRole` t2 where t2.role IN ('Material Master Manager','Purchase Manager') and t2.parent = t1.name") - for d in send: - send_to.append(d[0]) - msg = ''' -Minimum Inventory Level Reached - -Item Code: %s -Item Name: %s -Minimum Inventory Level: %s -Total Available Qty: %s - -''' % (self.doc.item_code, self.doc.item_name, self.doc.minimum_inventory_level, total_qty) - - sendmail(send_to, sender='automail@webnotestech.com', subject='Minimum Inventory Level Reached', parts=[['text/plain', msg]]) - def get_file_details(self, arg = ''): file = sql("select file_group, description from tabFile where name = %s", eval(arg)['file_name'], as_dict = 1) diff --git a/erpnext/utilities/doctype/contact/contact.txt b/erpnext/utilities/doctype/contact/contact.txt index 135699b768..baa2a775ee 100644 --- a/erpnext/utilities/doctype/contact/contact.txt +++ b/erpnext/utilities/doctype/contact/contact.txt @@ -3,9 +3,9 @@ # These values are common in all dictionaries { - 'creation': '2012-07-02 19:57:48', + 'creation': '2012-07-03 14:22:38', 'docstatus': 0, - 'modified': '2012-07-03 12:54:52', + 'modified': '2012-08-02 13:16:48', 'modified_by': u'Administrator', 'owner': u'Administrator' }, @@ -38,133 +38,12 @@ 'parenttype': u'DocType' }, - # These values are common for all DocPerm - { - 'doctype': u'DocPerm', - 'name': '__common__', - 'parent': u'Contact', - 'parentfield': u'permissions', - 'parenttype': u'DocType', - 'read': 1 - }, - # DocType, Contact { 'doctype': 'DocType', 'name': u'Contact' }, - # DocPerm - { - 'cancel': 1, - 'create': 1, - 'doctype': u'DocPerm', - 'permlevel': 0, - 'role': u'System Manager', - 'write': 1 - }, - - # DocPerm - { - 'amend': 0, - 'cancel': 1, - 'create': 1, - 'doctype': u'DocPerm', - 'permlevel': 0, - 'role': u'Sales Master Manager', - 'submit': 0, - 'write': 1 - }, - - # DocPerm - { - 'cancel': 1, - 'create': 1, - 'doctype': u'DocPerm', - 'permlevel': 0, - 'role': u'Purchase Master Manager', - 'write': 1 - }, - - # DocPerm - { - 'create': 1, - 'doctype': u'DocPerm', - 'permlevel': 0, - 'role': u'Sales Manager', - 'write': 1 - }, - - # DocPerm - { - 'create': 1, - 'doctype': u'DocPerm', - 'permlevel': 0, - 'role': u'Purchase Manager', - 'write': 1 - }, - - # DocPerm - { - 'create': 1, - 'doctype': u'DocPerm', - 'permlevel': 0, - 'role': u'Maintenance Manager', - 'write': 1 - }, - - # DocPerm - { - 'create': 1, - 'doctype': u'DocPerm', - 'permlevel': 0, - 'role': u'Accounts Manager', - 'write': 1 - }, - - # DocPerm - { - 'create': 1, - 'doctype': u'DocPerm', - 'permlevel': 0, - 'role': u'Sales User', - 'write': 1 - }, - - # DocPerm - { - 'create': 1, - 'doctype': u'DocPerm', - 'permlevel': 0, - 'role': u'Purchase User', - 'write': 1 - }, - - # DocPerm - { - 'create': 1, - 'doctype': u'DocPerm', - 'permlevel': 0, - 'role': u'Maintenance User', - 'write': 1 - }, - - # DocPerm - { - 'create': 1, - 'doctype': u'DocPerm', - 'permlevel': 0, - 'role': u'Accounts User', - 'write': 1 - }, - - # DocPerm - { - 'doctype': u'DocPerm', - 'permlevel': 1, - 'role': u'All' - }, - # DocField { 'colour': u'White:FFF', @@ -356,6 +235,15 @@ 'permlevel': 0 }, + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'unsubscribed', + 'fieldtype': u'Check', + 'label': u'Unsubscribed', + 'permlevel': 0 + }, + # DocField { 'doctype': u'DocField', diff --git a/erpnext/website/doctype/blog_subscriber/__init__.py b/erpnext/website/doctype/blog_subscriber/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/website/doctype/blog_subscriber/blog_subscriber.txt b/erpnext/website/doctype/blog_subscriber/blog_subscriber.txt deleted file mode 100644 index 1fa8223cd0..0000000000 --- a/erpnext/website/doctype/blog_subscriber/blog_subscriber.txt +++ /dev/null @@ -1,29 +0,0 @@ -# DocType, Blog Subscriber -[ - - # These values are common in all dictionaries - { - 'creation': '2012-03-27 14:36:47', - 'docstatus': 0, - 'modified': '2012-03-27 14:36:47', - 'modified_by': u'Administrator', - 'owner': u'Administrator' - }, - - # These values are common for all DocType - { - 'colour': u'White:FFF', - 'doctype': 'DocType', - 'module': u'Website', - 'name': '__common__', - 'section_style': u'Simple', - 'show_in_menu': 0, - 'version': 1 - }, - - # DocType, Blog Subscriber - { - 'doctype': 'DocType', - 'name': u'Blog Subscriber' - } -] \ No newline at end of file diff --git a/erpnext/website/page/unsubscribe/__init__.py b/erpnext/website/page/unsubscribe/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/erpnext/website/page/unsubscribe/unsubscribe.html b/erpnext/website/page/unsubscribe/unsubscribe.html deleted file mode 100644 index 7b2b68ee9c..0000000000 --- a/erpnext/website/page/unsubscribe/unsubscribe.html +++ /dev/null @@ -1,13 +0,0 @@ -
-
-

Unsubscribe

-
-
- - -
-
-
-
-
-
\ No newline at end of file diff --git a/erpnext/website/page/unsubscribe/unsubscribe.js b/erpnext/website/page/unsubscribe/unsubscribe.js deleted file mode 100644 index 9e83020a98..0000000000 --- a/erpnext/website/page/unsubscribe/unsubscribe.js +++ /dev/null @@ -1,37 +0,0 @@ -// 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 . - -pscript.onload_unsubscribe = function(wrapper) { - var email = window.location.hash.split('/').splice(-1); - $(wrapper).find('input[name="unsubscribe"]').val(email) - - $('#btn-unsubscribe').click(function() { - var email = $(wrapper).find('input[name="unsubscribe"]').val(); - if(email) { - var btn = this; - wn.call({ - module:'website', - page:'unsubscribe', - method:'unsubscribe', - args:email, - btn: this, - callback: function() { - $(wrapper).find('input[name="unsubscribe"]').val(''); - } - }); - } - }); -} \ No newline at end of file diff --git a/erpnext/website/page/unsubscribe/unsubscribe.py b/erpnext/website/page/unsubscribe/unsubscribe.py deleted file mode 100644 index 9985ded4a8..0000000000 --- a/erpnext/website/page/unsubscribe/unsubscribe.py +++ /dev/null @@ -1,26 +0,0 @@ -# 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 . - -import webnotes - -@webnotes.whitelist() -def unsubscribe(arg): - """unsubscribe from lists""" - lists = [['Blog Subscriber', 'name']] - for l in lists: - webnotes.conn.sql("""delete from `tab%s` where %s=%s""" % (l[0], l[1], '%s'), arg) - - webnotes.msgprint('Unsubscribed!') \ No newline at end of file diff --git a/erpnext/website/page/unsubscribe/unsubscribe.txt b/erpnext/website/page/unsubscribe/unsubscribe.txt deleted file mode 100644 index 2cc3b58a35..0000000000 --- a/erpnext/website/page/unsubscribe/unsubscribe.txt +++ /dev/null @@ -1,43 +0,0 @@ -# Page, unsubscribe -[ - - # These values are common in all dictionaries - { - 'creation': '2012-01-27 17:19:02', - 'docstatus': 0, - 'modified': '2012-01-27 17:19:02', - 'modified_by': 'Administrator', - 'owner': 'Administrator' - }, - - # These values are common for all Page - { - 'doctype': 'Page', - 'module': 'Website', - 'name': '__common__', - 'page_name': 'unsubscribe', - 'standard': 'Yes', - 'title': 'Unsubscribe' - }, - - # These values are common for all Page Role - { - 'doctype': 'Page Role', - 'name': '__common__', - 'parent': 'unsubscribe', - 'parentfield': 'roles', - 'parenttype': 'Page', - 'role': 'Guest' - }, - - # Page, unsubscribe - { - 'doctype': 'Page', - 'name': 'unsubscribe' - }, - - # Page Role - { - 'doctype': 'Page Role' - } -] \ No newline at end of file diff --git a/erpnext/website/templates/pages/unsubscribed.html b/erpnext/website/templates/pages/unsubscribed.html new file mode 100644 index 0000000000..3dc7df9e43 --- /dev/null +++ b/erpnext/website/templates/pages/unsubscribed.html @@ -0,0 +1,11 @@ +{% extends "html/outer.html" %} + +{% block content %} +
+
+

Unsubscribed

+
+

{{ webnotes.unsubscribed_email }} has been unsubscribed.

+
+
+{% endblock %} \ No newline at end of file From a67a74fee1a47cc2a780f6043f468e409c0fcc89 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Thu, 2 Aug 2012 18:53:00 +0530 Subject: [PATCH 04/12] supplier quotation, project shift patch --- .gitignore | 7 +- .../Purchase Request-Supplier Quotation.txt | 124 +++ .../purchase_common/purchase_common.js | 34 +- .../purchase_common/purchase_common.py | 2 +- .../doctype/purchase_order/purchase_order.js | 39 +- .../doctype/purchase_order/purchase_order.py | 22 +- .../doctype/purchase_order/purchase_order.txt | 21 +- .../doctype/supplier_quotation/__init__.py | 0 .../supplier_quotation/supplier_quotation.js | 113 +++ .../supplier_quotation/supplier_quotation.py | 96 ++ .../supplier_quotation/supplier_quotation.txt | 924 ++++++++++++++++++ .../supplier_quotation_item/__init__.py | 0 .../supplier_quotation_item.txt | 402 ++++++++ .../buying/page/buying_home/buying_home.html | 3 + .../patches/july_2012/project_patch_repeat.py | 18 + erpnext/patches/patch_list.py | 4 + public/js/all-app.js | 11 +- 17 files changed, 1715 insertions(+), 105 deletions(-) create mode 100644 erpnext/buying/DocType Mapper/Purchase Request-Supplier Quotation/Purchase Request-Supplier Quotation.txt create mode 100644 erpnext/buying/doctype/supplier_quotation/__init__.py create mode 100644 erpnext/buying/doctype/supplier_quotation/supplier_quotation.js create mode 100644 erpnext/buying/doctype/supplier_quotation/supplier_quotation.py create mode 100644 erpnext/buying/doctype/supplier_quotation/supplier_quotation.txt create mode 100644 erpnext/buying/doctype/supplier_quotation_item/__init__.py create mode 100644 erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.txt create mode 100644 erpnext/patches/july_2012/project_patch_repeat.py diff --git a/.gitignore b/.gitignore index ba0a9a311b..99a0c8a95a 100644 --- a/.gitignore +++ b/.gitignore @@ -5,13 +5,12 @@ patch.log lib conf.py version.num -public/*.html -!public/blank.html -!public/unsupported.html -!public/app.html public/js/lib public/images/lib public/files public/backups public/css/wn-web.css public/js/wn-web.js +backups +files +logs \ No newline at end of file diff --git a/erpnext/buying/DocType Mapper/Purchase Request-Supplier Quotation/Purchase Request-Supplier Quotation.txt b/erpnext/buying/DocType Mapper/Purchase Request-Supplier Quotation/Purchase Request-Supplier Quotation.txt new file mode 100644 index 0000000000..95b13ba447 --- /dev/null +++ b/erpnext/buying/DocType Mapper/Purchase Request-Supplier Quotation/Purchase Request-Supplier Quotation.txt @@ -0,0 +1,124 @@ +# DocType Mapper, Purchase Request-Supplier Quotation +[ + + # These values are common in all dictionaries + { + 'creation': '2012-08-02 18:36:26', + 'docstatus': 0, + 'modified': '2012-08-02 18:37:32', + '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'Purchase Request-Supplier Quotation', + 'parentfield': u'table_mapper_details', + 'parenttype': u'DocType Mapper' + }, + + # These values are common for all Field Mapper Detail + { + 'doctype': u'Field Mapper Detail', + 'name': '__common__', + 'parent': u'Purchase Request-Supplier Quotation', + 'parentfield': u'field_mapper_details', + 'parenttype': u'DocType Mapper' + }, + + # These values are common for all DocType Mapper + { + 'doctype': u'DocType Mapper', + 'from_doctype': u'Purchase Request', + 'module': u'Buying', + 'name': '__common__', + 'ref_doc_submitted': 1, + 'to_doctype': u'Supplier Quotation' + }, + + # DocType Mapper, Purchase Request-Supplier Quotation + { + 'doctype': u'DocType Mapper', + 'name': u'Purchase Request-Supplier Quotation' + }, + + # Field Mapper Detail + { + 'checking_operator': u'=', + 'doctype': u'Field Mapper Detail', + 'from_field': u'company', + 'map': u'Yes', + 'match_id': 0, + 'to_field': u'company' + }, + + # Field Mapper Detail + { + 'doctype': u'Field Mapper Detail', + 'from_field': u'parenttype', + 'map': u'Yes', + 'match_id': 1, + 'to_field': u'prevdoc_doctype' + }, + + # Field Mapper Detail + { + 'doctype': u'Field Mapper Detail', + 'from_field': u'parent', + 'map': u'Yes', + 'match_id': 1, + 'to_field': u'prevdoc_docname' + }, + + # Field Mapper Detail + { + 'doctype': u'Field Mapper Detail', + 'from_field': u'name', + 'map': u'Yes', + 'match_id': 1, + 'to_field': u'prevdoc_detail_docname' + }, + + # Field Mapper Detail + { + 'doctype': u'Field Mapper Detail', + 'from_field': u'uom', + 'map': u'Yes', + 'match_id': 1, + 'to_field': u'stock_uom' + }, + + # Field Mapper Detail + { + 'checking_operator': u'>=', + 'doctype': u'Field Mapper Detail', + 'from_field': u'transaction_date', + 'map': u'No', + 'match_id': 0, + 'to_field': u'transaction_date' + }, + + # Table Mapper Detail + { + 'doctype': u'Table Mapper Detail', + 'from_table': u'Purchase Request', + 'match_id': 0, + 'reference_key': u'prevdoc_docname', + 'to_table': u'Supplier Quotation', + 'validation_logic': u'docstatus = 1' + }, + + # Table Mapper Detail + { + 'doctype': u'Table Mapper Detail', + 'from_field': u'indent_details', + 'from_table': u'Purchase Request Item', + 'match_id': 1, + 'reference_doctype_key': u'prevdoc_doctype', + 'to_field': u'quotation_details', + 'to_table': u'Supplier Quotation Item', + 'validation_logic': u'docstatus =1' + } +] \ No newline at end of file diff --git a/erpnext/buying/doctype/purchase_common/purchase_common.js b/erpnext/buying/doctype/purchase_common/purchase_common.js index 82a9953df1..81d5fbf813 100644 --- a/erpnext/buying/doctype/purchase_common/purchase_common.js +++ b/erpnext/buying/doctype/purchase_common/purchase_common.js @@ -121,27 +121,21 @@ var set_dynamic_label_child = function(doc, cdt, cdn, base_curr) { //------------------------------------------------------------------ cur_frm.cscript.dynamic_label = function(doc, cdt, cdn, callback1) { - var callback = function(r, rt) { - if (r.message) base_curr = r.message; - else base_curr = sys_defaults['currency']; - - if (base_curr == doc.currency) { - set_multiple(cdt, cdn, {conversion_rate:1}); - hide_field(['conversion_rate', 'net_total_import','grand_total_import', 'in_words_import', 'other_charges_added_import', 'other_charges_deducted_import']); - } else unhide_field(['conversion_rate', 'net_total_import','grand_total_import', 'in_words_import', 'other_charges_added_import', 'other_charges_deducted_import']); - - set_dynamic_label_par(doc, cdt, cdn, base_curr); - set_dynamic_label_child(doc, cdt, cdn, base_curr); - - if(callback1) callback1(doc, cdt, cdn); + var base_currency = wn.boot.company[doc.company].default_currency || sys_defaults['currency']; + + if (doc.currency === base_currency) { + set_multiple(cdt, cdn, {conversion_rate:1}); + hide_field(['conversion_rate', 'net_total_import','grand_total_import', + 'in_words_import', 'other_charges_added_import', 'other_charges_deducted_import']); + } else { + unhide_field(['conversion_rate', 'net_total_import','grand_total_import', + 'in_words_import', 'other_charges_added_import', 'other_charges_deducted_import']); } - - if (doc.company == sys_defaults['company']) callback('', ''); - else wn.call({ - method: 'selling.doctype.sales_common.sales_common.get_comp_base_currency', - args: {company: doc.company}, - callback: callback - }); + + set_dynamic_label_par(doc, cdt, cdn, base_currency); + set_dynamic_label_child(doc, cdt, cdn, base_currency); + + if (callback1) callback1(doc, cdt, cdn); } cur_frm.cscript.currency = function(doc, cdt, cdn) { diff --git a/erpnext/buying/doctype/purchase_common/purchase_common.py b/erpnext/buying/doctype/purchase_common/purchase_common.py index 7240a2d229..5a65d5219a 100644 --- a/erpnext/buying/doctype/purchase_common/purchase_common.py +++ b/erpnext/buying/doctype/purchase_common/purchase_common.py @@ -615,7 +615,7 @@ class DocType(TransactionBase): sql("update `tab%s` set %s = '%s', modified = '%s' where name = '%s'" % (self.ref_doctype_dict[ref_dn][0], self.update_percent_field[self.ref_doctype_dict[ref_dn][2]], percent_complete, obj.doc.modified, ref_dn)) - def validate_fiscal_year(self,fiscal_year,transaction_date,dn): + def validate_fiscal_year(self, fiscal_year, transaction_date, dn): fy=sql("select year_start_date from `tabFiscal Year` where name='%s'"%fiscal_year) ysd=fy and fy[0][0] or "" yed=add_days(str(ysd),365) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js index 9d50020952..a27f6ff73b 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.js +++ b/erpnext/buying/doctype/purchase_order/purchase_order.js @@ -23,7 +23,6 @@ wn.require('erpnext/buying/doctype/purchase_common/purchase_common.js'); wn.require('erpnext/utilities/doctype/sms_control/sms_control.js'); wn.require('erpnext/setup/doctype/notification_control/notification_control.js'); -//========================== On Load ================================================= cur_frm.cscript.onload = function(doc, cdt, cdn) { if(!doc.fiscal_year && doc.__islocal){ //set_default_values(doc); @@ -37,22 +36,14 @@ cur_frm.cscript.onload = function(doc, cdt, cdn) { } cur_frm.cscript.onload_post_render = function(doc, dt, dn) { - var callback = function(doc, dt, dn) { - if(doc.__islocal){ - cur_frm.cscript.get_default_schedule_date(doc); - } - } - cur_frm.cscript.dynamic_label(doc, dt, dn, callback); + if(doc.__islocal) cur_frm.cscript.get_default_schedule_date(doc); } -// ================================== Refresh ========================================== cur_frm.cscript.refresh = function(doc, cdt, cdn) { - // Show buttons - // --------------------------------- cur_frm.clear_custom_buttons(); erpnext.hide_naming_series(); - if (!cur_frm.cscript.is_onload) cur_frm.cscript.dynamic_label(doc, cdt, cdn); + cur_frm.cscript.dynamic_label(doc, cdt, cdn); if(doc.docstatus == 1 && doc.status != 'Stopped'){ cur_frm.add_custom_button('Send SMS', cur_frm.cscript['Send SMS']); @@ -68,7 +59,6 @@ cur_frm.cscript.refresh = function(doc, cdt, cdn) { else $(cur_frm.fields_dict.contact_section.row.wrapper).toggle(false); } -//Supplier cur_frm.cscript.supplier = function(doc,dt,dn) { if (doc.supplier) { get_server_fields('get_default_supplier_address', @@ -102,33 +92,14 @@ cur_frm.fields_dict.contact_person.on_new = function(dn) { locals['Contact'][dn].supplier_name = locals[cur_frm.doctype][cur_frm.docname].supplier_name; } - - - - -//================ create new contact ============================================================================ -cur_frm.cscript.new_contact = function(){ - tn = createLocal('Contact'); - locals['Contact'][tn].is_supplier = 1; - if(doc.supplier) locals['Contact'][tn].supplier = doc.supplier; - loaddoc('Contact', tn); -} - -//======================= transaction date ============================= cur_frm.cscript.transaction_date = function(doc,cdt,cdn){ - if(doc.__islocal){ - cur_frm.cscript.get_default_schedule_date(doc); - } + if(doc.__islocal){ cur_frm.cscript.get_default_schedule_date(doc); } } - -// ---------------------- Get project name -------------------------- cur_frm.fields_dict['po_details'].grid.get_field('project_name').get_query = function(doc, cdt, cdn) { return 'SELECT `tabProject`.name FROM `tabProject` WHERE `tabProject`.status = "Open" AND `tabProject`.name LIKE "%s" ORDER BY `tabProject`.name ASC LIMIT 50'; } -//==================== Purchase Request No Get Query ======================================================= -//===== Only those Purchase Requests status != 'Completed' and docstatus = 1 i.e. submitted================= cur_frm.fields_dict['indent_no'].get_query = function(doc) { return 'SELECT DISTINCT `tabPurchase Request`.`name` FROM `tabPurchase Request` WHERE `tabPurchase Request`.company = "' + doc.company + '" and `tabPurchase Request`.`docstatus` = 1 and `tabPurchase Request`.`status` != "Stopped" and ifnull(`tabPurchase Request`.`per_ordered`,0) < 100 and `tabPurchase Request`.%(key)s LIKE "%s" ORDER BY `tabPurchase Request`.`name` DESC LIMIT 50'; } @@ -203,10 +174,6 @@ cur_frm.cscript['Unstop Purchase Order'] = function() { } } -// ***************** Get Print Heading ***************** -cur_frm.fields_dict['select_print_heading'].get_query = function(doc, cdt, cdn) { - return 'SELECT `tabPrint Heading`.name FROM `tabPrint Heading` WHERE `tabPrint Heading`.docstatus !=2 AND `tabPrint Heading`.name LIKE "%s" ORDER BY `tabPrint Heading`.name ASC LIMIT 50'; -} //****************** For print sales order no and date************************* cur_frm.pformat.indent_no = function(doc, cdt, cdn){ //function to make row of table diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index 9b7e99c26f..40b7281f84 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -83,7 +83,6 @@ class DocType(TransactionBase): # Pull Purchase Request def get_indent_details(self): - #self.validate_prev_docname() if self.doc.indent_no: get_obj('DocType Mapper','Purchase Request-Purchase Order').dt_map('Purchase Request','Purchase Order',self.doc.indent_no, self.doc, self.doclist, "[['Purchase Request','Purchase Order'],['Purchase Request Item', 'Purchase Order Item']]") pcomm = get_obj('Purchase Common') @@ -101,26 +100,13 @@ class DocType(TransactionBase): else: d.purchase_ref_rate = d.discount_rate = d.purchase_rate = d.import_ref_rate = d.import_rate = 0.0 - # GET TERMS & CONDITIONS - # ===================================================================================== def get_tc_details(self): + """get terms & conditions""" return get_obj('Purchase Common').get_tc_details(self) - - - # validate if indent has been pulled twice - def validate_prev_docname(self): - for d in getlist(self.doclist, 'po_details'): - if d.prevdoc_docname and self.doc.indent_no == d.prevdoc_docname: - msgprint(cstr(self.doc.indent_no) + " indent details have already been pulled. ") - raise Exception - - # get last purchase rate def get_last_purchase_rate(self): get_obj('Purchase Common').get_last_purchase_rate(self) - # validation - #------------------------------------------------------------------------------------------------------------- def validate_doc(self,pc_obj): # Validate values with reference document pc_obj.validate_reference_value(obj = self) @@ -233,16 +219,14 @@ class DocType(TransactionBase): get_obj('Authorization Control').validate_approving_authority(self.doc.doctype, self.doc.company, self.doc.grand_total) # Step 4 :=> Update Current PO No. in Supplier as last_purchase_order. - update_supplier = sql("update `tabSupplier` set last_purchase_order = '%s' where name = '%s'" % (self.doc.name, self.doc.supplier)) + update_supplier = webnotes.conn.set_value("Supplier", self.doc.supplier, + "last_purchase_order", self.doc.name) # Step 5 :=> Update last purchase rate pc_obj.update_last_purchase_rate(self, is_submit = 1) # Step 6 :=> Set Status set(self.doc,'status','Submitted') - - self.doc.indent_no = ''; - # On Cancel # ------------------------------------------------------------------------------------------------------- diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.txt b/erpnext/buying/doctype/purchase_order/purchase_order.txt index 13210f2e4d..318ebda35b 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.txt +++ b/erpnext/buying/doctype/purchase_order/purchase_order.txt @@ -3,9 +3,9 @@ # These values are common in all dictionaries { - 'creation': '2012-05-11 12:00:15', + 'creation': '2012-07-02 14:44:19', 'docstatus': 0, - 'modified': '2012-05-11 16:59:10', + 'modified': '2012-08-02 13:43:50', 'modified_by': u'Administrator', 'owner': u'Administrator' }, @@ -962,23 +962,6 @@ 'width': u'50%' }, - # DocField - { - 'colour': u'White:FFF', - 'description': u'Track this Purchase Order against any Project', - 'doctype': u'DocField', - 'fieldname': u'project_name', - 'fieldtype': u'Link', - 'in_filter': 1, - 'label': u'Project Name', - 'oldfieldname': u'project_name', - 'oldfieldtype': u'Link', - 'options': u'Project', - 'permlevel': 0, - 'search_index': 1, - 'trigger': u'Client' - }, - # DocField { 'colour': u'White:FFF', diff --git a/erpnext/buying/doctype/supplier_quotation/__init__.py b/erpnext/buying/doctype/supplier_quotation/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js new file mode 100644 index 0000000000..4d2673c5ef --- /dev/null +++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js @@ -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 . + +// define defaults for purchase common +cur_frm.cscript.tname = "Supplier Quotation Item"; +cur_frm.cscript.fname = "quotation_items"; +cur_frm.cscript.other_fname = "purchase_tax_details"; + +// attach required files +wn.require('erpnext/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js'); +wn.require('erpnext/buying/doctype/purchase_common/purchase_common.js'); + +cur_frm.cscript.onload = function(doc, dt, dn) { + // set missing values in parent doc + set_missing_values(doc, { + fiscal_year: sys_defaults.fiscal_year, + conversion_rate: 1, + currency: sys_defaults.currency, + status: "Draft", + transaction_date: get_today(), + is_subcontracted: "No" + }); +} + +cur_frm.cscript.refresh = function(doc, dt, dn) { + erpnext.hide_naming_series(); + cur_frm.cscript.dynamic_label(doc, dt, dn); + + cur_frm.cscript.toggle_contact_section(doc); + + cur_frm.clear_custom_buttons(); + if (doc.docstatus === 1) { + cur_frm.add_custom_button("Make Purchase Order", cur_frm.cscript.make_purchase_order); + } +} + +cur_frm.cscript.toggle_contact_section = function(doc) { + console.log(doc.supplier); + doc.supplier ? unhide_field("contact_section") : hide_field("contact_section"); +} + +cur_frm.cscript.make_purchase_order = function(doc, dt, dn) { + +} + +cur_frm.cscript.supplier = function(doc, dt, dn) { + if (doc.supplier) { + get_server_fields('get_default_supplier_address', + JSON.stringify({ supplier: doc.supplier }), '', doc, dt, dn, 1, + function() { cur_frm.refresh(); }); + cur_frm.cscript.toggle_contact_section(doc); + } +} + +cur_frm.fields_dict['quotation_items'].grid.get_field('project_name').get_query = + function(doc, cdt, cdn) { + return "select `tabProject`.name from `tabProject` \ + where `tabProject`.status = \"Open\" and `tabProject`.name like \"%s\" \ + order by `tabProject`.name ASC LIMIT 50"; + } + +cur_frm.fields_dict['indent_no'].get_query = function(doc) { + return "select distinct `tabPurchase Request`.`name` from `tabPurchase Request` \ + where `tabPurchase Request`.company = \"" + doc.company + + "\" and `tabPurchase Request`.`docstatus` = 1 and \ + `tabPurchase Request`.`status` != \"Stopped\" and \ + ifnull(`tabPurchase Request`.`per_ordered`,0) < 100 and \ + `tabPurchase Request`.%(key)s LIKE \"%s\" \ + order by `tabPurchase Request`.`name` desc limit 50"; +} + + +cur_frm.cscript.supplier_address = function(doc, dt, dn) { + if (doc.supplier) { + get_server_fields("get_supplier_address", JSON.stringify({supplier: doc.supplier, + address: doc.supplier_address, contact: doc.contact_person}), '', doc, dt, dn, 1); + } +} +cur_frm.cscript.contact_person = cur_frm.cscript.supplier_address; + +cur_frm.fields_dict['supplier_address'].get_query = function(doc, cdt, cdn) { + return "SELECT name, address_line1, city FROM tabAddress WHERE supplier = \"" + doc.supplier + + "\" 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 supplier = \"" + doc.supplier + +"\" AND docstatus != 2 AND name LIKE \"%s\" ORDER BY name ASC LIMIT 50"; +} + +cur_frm.fields_dict.supplier_address.on_new = function(dn) { + locals['Address'][dn].supplier = locals[cur_frm.doctype][cur_frm.docname].supplier; + locals['Address'][dn].supplier_name = locals[cur_frm.doctype][cur_frm.docname].supplier_name; +} + +cur_frm.fields_dict.contact_person.on_new = function(dn) { + locals['Contact'][dn].supplier = locals[cur_frm.doctype][cur_frm.docname].supplier; + locals['Contact'][dn].supplier_name = locals[cur_frm.doctype][cur_frm.docname].supplier_name; +} \ No newline at end of file diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py new file mode 100644 index 0000000000..f52e428744 --- /dev/null +++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.py @@ -0,0 +1,96 @@ +# 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 . + +import webnotes +from webnotes.model.code import get_obj +from utilities.transaction_base import TransactionBase + +class DocType(TransactionBase): + def __init__(self, doc, doclist=None): + self.doc, self.doclist = doc, doclist or [] + self.tname, self.fname = "Supplier Quotation Item", "quotation_item" + + def autoname(self): + """autoname based on naming series value""" + from webnotes.model.doc import make_autoname + self.doc.name = make_autoname(self.doc.naming_series + ".#####") + + def validate(self): + self.validate_fiscal_year() + self.validate_common() + self.set_in_words() + self.doc.status = "Draft" + + def on_submit(self): + webnotes.conn.set(self.doc, "status", "Submitted") + + def on_cancel(self): + webnotes.conn.set(self.doc, "status", "Cancelled") + + def on_trash(self): + pass + + def get_item_details(self, args=None): + if args: + return get_obj(dt='Purchase Common').get_item_details(self, args) + else: + obj = get_obj('Purchase Common') + for doc in self.doclist: + if doc.fields.get('item_code'): + temp = { + 'item_code': doc.fields.get('item_code'), + 'warehouse': doc.fields.get('warehouse') + } + ret = obj.get_item_details(self, json.dumps(temp)) + for r in ret: + if not doc.fields.get(r): + doc.fields[r] = ret[r] + + def get_indent_details(self): + if self.doc.indent_no: + mapper = get_obj("DocType Mapper", "Purchase Request-Supplier Quotation") + mapper.dt_map("Purchase Request", "Supplier Quotation", self.doc.indent_no, + self.doc, self.doclist, """[['Purchase Request', 'Supplier Quotation'], + ['Purchase Request Item', 'Supplier Quotation Item']]""") + + for d in getlist(self.doclist, "quotation_details"): + if d.item_code and not d.purchase_rate: + d.purchase_ref_rate = d.discount_rate = d.purchase_rate = 0.0 + d.import_ref_rate = d.import_rate = 0.0 + + def get_purchase_tax_details(self): + self.doclist = get_obj('Purchase Common').get_purchase_tax_details(self) + + def get_uom_details(self, args=None): + return get_obj('Purchase Common').get_uom_details(args) + + def validate_fiscal_year(self): + get_obj(dt = 'Purchase Common').validate_fiscal_year( \ + self.doc.fiscal_year, self.doc.transaction_date, 'Quotation Date') + + def validate_common(self): + pc = get_obj('Purchase Common') + pc.validate_mandatory(self) + pc.validate_for_items(self) + pc.validate_conversion_rate(self) + pc.get_prevdoc_date(self) + pc.validate_reference_value(self) + + def set_in_words(self): + pc = get_obj('Purchase Common') + company_currency = TransactionBase().get_company_currency(self.doc.company) + self.doc.in_words = pc.get_total_in_words(company_currency, self.doc.grand_total) + self.doc.in_words_import = pc.get_total_in_words(self.doc.currency, self.doc.grand_total_import) diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.txt b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.txt new file mode 100644 index 0000000000..e4a33ca91b --- /dev/null +++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.txt @@ -0,0 +1,924 @@ +# DocType, Supplier Quotation +[ + + # These values are common in all dictionaries + { + 'creation': '2012-08-01 20:03:35', + 'docstatus': 0, + 'modified': '2012-08-02 18:04:35', + 'modified_by': u'Administrator', + 'owner': u'Administrator' + }, + + # These values are common for all DocType + { + 'allow_attach': 1, + 'default_print_format': u'Standard', + 'doctype': 'DocType', + 'document_type': u'Transaction', + 'is_submittable': 1, + 'is_transaction_doc': 1, + 'module': u'Buying', + 'name': '__common__', + 'read_only_onload': 1, + 'search_fields': u'status, transaction_date, supplier,grand_total', + 'version': 1 + }, + + # These values are common for all DocField + { + 'doctype': u'DocField', + 'name': '__common__', + 'parent': u'Supplier Quotation', + 'parentfield': u'fields', + 'parenttype': u'DocType' + }, + + # These values are common for all DocPerm + { + 'doctype': u'DocPerm', + 'name': '__common__', + 'parent': u'Supplier Quotation', + 'parentfield': u'permissions', + 'parenttype': u'DocType', + 'read': 1 + }, + + # DocType, Supplier Quotation + { + 'doctype': 'DocType', + 'name': u'Supplier Quotation' + }, + + # DocPerm + { + 'amend': 1, + 'cancel': 1, + 'create': 1, + 'doctype': u'DocPerm', + 'permlevel': 0, + 'role': u'Production Manager', + 'submit': 1, + 'write': 1 + }, + + # DocPerm + { + 'amend': 1, + 'cancel': 1, + 'create': 1, + 'doctype': u'DocPerm', + 'permlevel': 0, + 'role': u'Purchase Manager', + 'submit': 1, + 'write': 1 + }, + + # DocPerm + { + 'amend': 1, + 'cancel': 0, + 'create': 1, + 'doctype': u'DocPerm', + 'permlevel': 0, + 'role': u'Purchase User', + 'submit': 0, + 'write': 1 + }, + + # DocPerm + { + 'amend': 0, + 'cancel': 0, + 'create': 0, + 'doctype': u'DocPerm', + 'permlevel': 0, + 'role': u'Material User', + 'submit': 0, + 'write': 0 + }, + + # DocPerm + { + 'amend': 0, + 'cancel': 0, + 'create': 0, + 'doctype': u'DocPerm', + 'permlevel': 0, + 'role': u'Supplier', + 'submit': 0, + 'write': 0 + }, + + # DocPerm + { + 'amend': 0, + 'cancel': 0, + 'create': 0, + 'doctype': u'DocPerm', + 'permlevel': 1, + 'role': u'All', + 'submit': 0, + 'write': 0 + }, + + # DocPerm + { + 'amend': 0, + 'cancel': 0, + 'create': 0, + 'doctype': u'DocPerm', + 'permlevel': 2, + 'role': u'All', + 'submit': 0, + 'write': 1 + }, + + # DocField + { + 'colour': u'White:FFF', + 'doctype': u'DocField', + 'fieldname': u'basic_info', + 'fieldtype': u'Section Break', + 'label': u'Basic Info', + 'oldfieldtype': u'Section Break', + 'permlevel': 0, + 'print_hide': 0 + }, + + # 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', + 'description': u'To manage multiple series please go to Setup > Manage Series', + 'doctype': u'DocField', + 'fieldname': u'naming_series', + 'fieldtype': u'Select', + 'label': u'Series', + 'no_copy': 1, + 'oldfieldname': u'naming_series', + 'oldfieldtype': u'Select', + 'options': u'SQTN', + 'permlevel': 0, + 'print_hide': 1, + 'reqd': 1 + }, + + # DocField + { + 'colour': u'White:FFF', + 'description': u'Supplier (vendor) name as entered in supplier master', + 'doctype': u'DocField', + 'fieldname': u'supplier', + 'fieldtype': u'Link', + 'in_filter': 1, + 'label': u'Supplier', + 'oldfieldname': u'supplier', + 'oldfieldtype': u'Link', + 'options': u'Supplier', + 'permlevel': 0, + 'print_hide': 1, + 'reqd': 1, + 'search_index': 1, + 'trigger': u'Client' + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'supplier_name', + 'fieldtype': u'Data', + 'hidden': 1, + 'label': u'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'Text', + 'hidden': 1, + 'label': u'Mobile No', + 'permlevel': 1 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'contact_email', + 'fieldtype': u'Text', + 'hidden': 1, + '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, + 'print_hide': 0, + 'width': u'50%' + }, + + # DocField + { + 'colour': u'White:FFF', + 'description': u'The date at which current entry is made in system.', + 'doctype': u'DocField', + 'fieldname': u'transaction_date', + 'fieldtype': u'Date', + 'in_filter': 1, + 'label': u'Quotation Date', + 'oldfieldname': u'transaction_date', + 'oldfieldtype': u'Date', + 'permlevel': 0, + 'reqd': 1, + 'search_index': 1, + 'trigger': u'Client' + }, + + # DocField + { + 'colour': u'White:FFF', + 'doctype': u'DocField', + 'fieldname': u'items', + 'fieldtype': u'Section Break', + 'label': u'Items', + 'oldfieldtype': u'Section Break', + 'permlevel': 0 + }, + + # DocField + { + 'allow_on_submit': 1, + 'doctype': u'DocField', + 'fieldname': u'quotation_items', + 'fieldtype': u'Table', + 'label': u'Quotation Items', + 'no_copy': 0, + 'oldfieldname': u'po_details', + 'oldfieldtype': u'Table', + 'options': u'Supplier Quotation Item', + 'permlevel': 0 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'section_break0', + 'fieldtype': u'Section Break', + 'options': u'Simple', + 'permlevel': 0 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'column_break2', + 'fieldtype': u'Column Break', + 'permlevel': 0, + 'width': u'50%' + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'net_total', + 'fieldtype': u'Currency', + 'label': u'Net Total*', + 'no_copy': 1, + 'oldfieldname': u'net_total', + 'oldfieldtype': u'Currency', + 'permlevel': 1, + 'print_hide': 1, + 'reqd': 0 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'net_total_import', + 'fieldtype': u'Currency', + 'label': u'Net Total (Import)', + 'no_copy': 0, + 'oldfieldname': u'net_total_import', + 'oldfieldtype': u'Currency', + 'permlevel': 1, + 'print_hide': 1 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'recalculate_values', + 'fieldtype': u'Button', + 'label': u'Re-Calculate Values', + 'oldfieldtype': u'Button', + 'permlevel': 0, + 'trigger': u'Client' + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'column_break3', + 'fieldtype': u'Column Break', + 'permlevel': 0, + 'width': u'50%' + }, + + # DocField + { + 'colour': u'White:FFF', + 'description': u"Supplier's currency", + 'doctype': u'DocField', + 'fieldname': u'currency', + 'fieldtype': u'Select', + 'label': u'Currency', + 'no_copy': 0, + 'oldfieldname': u'currency', + 'oldfieldtype': u'Select', + 'options': u'link:Currency', + 'permlevel': 0, + 'print_hide': 1, + 'reqd': 1 + }, + + # DocField + { + 'colour': u'White:FFF', + 'default': u'1', + 'description': u"Rate at which supplier's currency is converted to company's base currency", + 'doctype': u'DocField', + 'fieldname': u'conversion_rate', + 'fieldtype': u'Currency', + 'hidden': 0, + 'label': u'Conversion Rate', + 'no_copy': 1, + 'oldfieldname': u'conversion_rate', + 'oldfieldtype': u'Currency', + 'permlevel': 0, + 'print_hide': 1, + 'reqd': 1, + 'trigger': u'Client' + }, + + # DocField + { + 'colour': u'White:FFF', + 'description': u'You can make a purchase order from multiple Purchase Requests. Select Purchase Requests one by one and click on the button below.', + 'doctype': u'DocField', + 'fieldname': u'indent_no', + 'fieldtype': u'Link', + 'hidden': 0, + 'label': u'Select Purchase Request', + 'no_copy': 1, + 'oldfieldname': u'indent_no', + 'oldfieldtype': u'Link', + 'options': u'Purchase Request', + 'permlevel': 0, + 'print_hide': 1 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'get_items', + 'fieldtype': u'Button', + 'hidden': 0, + 'label': u'Get Items', + 'oldfieldtype': u'Button', + 'options': u'get_indent_details', + 'permlevel': 0 + }, + + # DocField + { + 'colour': u'White:FFF', + 'doctype': u'DocField', + 'fieldname': u'taxes', + 'fieldtype': u'Section Break', + 'label': u'Taxes', + 'oldfieldtype': u'Section Break', + 'permlevel': 0 + }, + + # DocField + { + 'colour': u'White:FFF', + 'description': u'If you have created a standard template in Purchase Taxes and Charges Master, select one and click on the button below.', + 'doctype': u'DocField', + 'fieldname': u'purchase_other_charges', + 'fieldtype': u'Link', + 'label': u'Purchase Taxes and Charges', + 'no_copy': 1, + 'oldfieldname': u'purchase_other_charges', + 'oldfieldtype': u'Link', + 'options': u'Purchase Taxes and Charges Master', + 'permlevel': 0, + 'print_hide': 1 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'get_tax_detail', + 'fieldtype': u'Button', + 'label': u'Get Tax Detail', + 'oldfieldtype': u'Button', + 'options': u'get_purchase_tax_details', + 'permlevel': 0, + 'print_hide': 1 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'purchase_tax_details', + 'fieldtype': u'Table', + 'label': u'Purchase Taxes and Charges', + 'no_copy': 0, + 'oldfieldname': u'purchase_tax_details', + 'oldfieldtype': u'Table', + 'options': u'Purchase Taxes and Charges', + 'permlevel': 0 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'calculate_tax', + 'fieldtype': u'Button', + 'label': u'Calculate Tax', + 'oldfieldtype': u'Button', + 'permlevel': 0, + 'print_hide': 1, + 'trigger': u'Client' + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'tax_calculation', + 'fieldtype': u'HTML', + 'label': u'Tax Calculation', + 'no_copy': 1, + 'oldfieldtype': u'HTML', + 'permlevel': 0, + 'print_hide': 1 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'total_tax', + 'fieldtype': u'Currency', + 'label': u'Total Tax*', + 'no_copy': 1, + 'oldfieldname': u'total_tax', + 'oldfieldtype': u'Currency', + 'permlevel': 1, + 'print_hide': 1 + }, + + # DocField + { + 'colour': u'White:FFF', + 'doctype': u'DocField', + 'fieldname': u'totals', + 'fieldtype': u'Section Break', + 'label': u'Totals', + 'oldfieldtype': u'Section Break', + 'permlevel': 0 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'grand_total', + 'fieldtype': u'Currency', + 'label': u'Grand Total', + 'no_copy': 1, + 'oldfieldname': u'grand_total', + 'oldfieldtype': u'Currency', + 'permlevel': 1, + 'print_hide': 1 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'rounded_total', + 'fieldtype': u'Currency', + 'label': u'Rounded Total', + 'oldfieldname': u'rounded_total', + 'oldfieldtype': u'Currency', + 'permlevel': 1, + 'print_hide': 1 + }, + + # DocField + { + 'colour': u'White:FFF', + 'description': u'In Words will be visible once you save the Purchase Order.', + 'doctype': u'DocField', + 'fieldname': u'in_words', + 'fieldtype': u'Data', + 'label': u'In Words', + 'oldfieldname': u'in_words', + 'oldfieldtype': u'Data', + 'permlevel': 1, + 'print_hide': 1 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'other_charges_added', + 'fieldtype': u'Currency', + 'label': u'Taxes and Charges Added', + 'no_copy': 0, + 'oldfieldname': u'other_charges_added', + 'oldfieldtype': u'Currency', + 'permlevel': 1, + 'print_hide': 1 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'other_charges_deducted', + 'fieldtype': u'Currency', + 'label': u'Taxes and Charges Deducted', + 'no_copy': 0, + 'oldfieldname': u'other_charges_deducted', + 'oldfieldtype': u'Currency', + 'permlevel': 1, + 'print_hide': 1 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'column_break4', + 'fieldtype': u'Column Break', + 'oldfieldtype': u'Column Break', + 'permlevel': 0, + 'print_hide': 0 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'grand_total_import', + 'fieldtype': u'Currency', + 'label': u'Grand Total (Import)', + 'no_copy': 0, + 'oldfieldname': u'grand_total_import', + 'oldfieldtype': u'Currency', + 'permlevel': 1, + 'print_hide': 1, + 'report_hide': 0 + }, + + # DocField + { + 'colour': u'White:FFF', + 'doctype': u'DocField', + 'fieldname': u'in_words_import', + 'fieldtype': u'Data', + 'label': u'In Words(Import)', + 'oldfieldname': u'in_words_import', + 'oldfieldtype': u'Data', + 'permlevel': 1, + 'print_hide': 1 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'other_charges_added_import', + 'fieldtype': u'Currency', + 'label': u'Taxes and Charges Added (Import)', + 'no_copy': 0, + 'oldfieldname': u'other_charges_added_import', + 'oldfieldtype': u'Currency', + 'permlevel': 1, + 'print_hide': 1, + 'report_hide': 0 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'other_charges_deducted_import', + 'fieldtype': u'Currency', + 'label': u'Taxes and Charges Deducted (Import)', + 'no_copy': 0, + 'oldfieldname': u'other_charges_deducted_import', + 'oldfieldtype': u'Currency', + 'permlevel': 1, + 'print_hide': 1, + 'report_hide': 0 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'terms_section_break', + 'fieldtype': u'Section Break', + 'label': u'Terms and Conditions', + 'oldfieldtype': u'Section Break', + 'permlevel': 0 + }, + + # DocField + { + 'allow_on_submit': 1, + 'doctype': u'DocField', + 'fieldname': u'letter_head', + 'fieldtype': u'Select', + 'label': u'Letter Head', + 'oldfieldname': u'letter_head', + 'oldfieldtype': u'Select', + 'options': u'link:Letter Head', + 'permlevel': 0, + 'print_hide': 1 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'tc_name', + 'fieldtype': u'Link', + 'label': u'Select Terms and Conditions', + 'oldfieldname': u'tc_name', + 'oldfieldtype': u'Link', + 'options': u'Terms and Conditions', + 'permlevel': 0, + 'print_hide': 1 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'get_terms', + 'fieldtype': u'Button', + 'label': u'Get Terms and Conditions', + 'oldfieldtype': u'Button', + 'options': u'get_tc_details', + 'permlevel': 0 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'terms_html', + 'fieldtype': u'HTML', + 'label': u'Terms and Conditions HTML', + 'oldfieldtype': u'HTML', + 'options': u'You can add Terms and Notes that will be printed in the Transaction', + 'permlevel': 0, + 'print_hide': 1 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'terms', + 'fieldtype': u'Text Editor', + 'label': u'Terms and Conditions1', + 'oldfieldname': u'terms', + 'oldfieldtype': u'Text Editor', + 'permlevel': 0 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'contact_section', + 'fieldtype': u'Section Break', + 'label': u'Contact Info', + 'permlevel': 0 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'supplier_address', + 'fieldtype': u'Link', + 'in_filter': 1, + 'label': u'Supplier Address', + 'options': u'Address', + 'permlevel': 0, + 'print_hide': 1 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'contact_person', + 'fieldtype': u'Link', + 'in_filter': 1, + 'label': u'Contact Person', + 'options': u'Contact', + 'permlevel': 0, + 'print_hide': 1 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'more_info', + 'fieldtype': u'Section Break', + 'label': u'More Info', + 'oldfieldtype': u'Section Break', + 'permlevel': 0 + }, + + # DocField + { + 'colour': u'White:FFF', + '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\nStopped\nCancelled', + 'permlevel': 1, + 'print_hide': 1, + 'reqd': 1, + 'search_index': 1 + }, + + # DocField + { + 'default': u'No', + 'doctype': u'DocField', + 'fieldname': u'is_subcontracted', + 'fieldtype': u'Select', + 'label': u'Is Subcontracted', + 'options': u'\nYes\nNo', + 'permlevel': 0, + 'print_hide': 1 + }, + + # 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': 1, + 'print_hide': 1, + 'report_hide': 0 + }, + + # DocField + { + 'description': u'The date at which current entry is corrected in the system.', + '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 + }, + + # DocField + { + 'colour': u'White:FFF', + 'description': u'Select the relevant company name if you have multiple companies', + 'doctype': u'DocField', + 'fieldname': u'company', + 'fieldtype': u'Link', + 'in_filter': 1, + 'label': u'Company', + 'no_copy': 0, + 'oldfieldname': u'company', + 'oldfieldtype': u'Link', + 'options': u'Company', + 'permlevel': 0, + 'print_hide': 1, + 'reqd': 1, + 'search_index': 1 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'fiscal_year', + 'fieldtype': u'Select', + 'in_filter': 1, + 'label': u'Fiscal Year', + 'no_copy': 0, + 'oldfieldname': u'fiscal_year', + 'oldfieldtype': u'Select', + 'options': u'link:Fiscal Year', + 'permlevel': 0, + 'print_hide': 1, + 'reqd': 1, + 'search_index': 1 + }, + + # DocField + { + 'allow_on_submit': 1, + 'colour': u'White:FFF', + 'doctype': u'DocField', + 'fieldname': u'select_print_heading', + 'fieldtype': u'Link', + 'label': u'Select Print Heading', + 'no_copy': 1, + 'oldfieldname': u'select_print_heading', + 'oldfieldtype': u'Link', + 'options': u'Print Heading', + 'permlevel': 0, + 'print_hide': 1, + 'report_hide': 1 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'column_break5', + 'fieldtype': u'Column Break', + 'oldfieldtype': u'Column Break', + 'permlevel': 0, + 'print_hide': 1, + 'width': u'50%' + }, + + # DocField + { + 'colour': u'White:FFF', + 'depends_on': u'eval:!doc.__islocal', + 'doctype': u'DocField', + 'fieldname': u'cancel_reason', + 'fieldtype': u'Data', + 'hidden': 0, + 'label': u'Cancel Reason', + 'no_copy': 1, + 'oldfieldname': u'cancel_reason', + 'oldfieldtype': u'Data', + 'permlevel': 1, + 'print_hide': 1 + }, + + # 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 + } +] \ No newline at end of file diff --git a/erpnext/buying/doctype/supplier_quotation_item/__init__.py b/erpnext/buying/doctype/supplier_quotation_item/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.txt b/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.txt new file mode 100644 index 0000000000..1ee10ae496 --- /dev/null +++ b/erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.txt @@ -0,0 +1,402 @@ +# DocType, Supplier Quotation Item +[ + + # These values are common in all dictionaries + { + 'creation': '2012-08-01 20:07:22', + 'docstatus': 0, + 'modified': '2012-08-02 16:00:52', + 'modified_by': u'Administrator', + 'owner': u'Administrator' + }, + + # These values are common for all DocType + { + 'autoname': u'SQI-.#####', + 'default_print_format': u'Standard', + 'doctype': 'DocType', + 'istable': 1, + 'module': u'Buying', + 'name': '__common__', + 'version': 1 + }, + + # These values are common for all DocField + { + 'doctype': u'DocField', + 'name': '__common__', + 'parent': u'Supplier Quotation Item', + 'parentfield': u'fields', + 'parenttype': u'DocType' + }, + + # DocType, Supplier Quotation Item + { + 'doctype': 'DocType', + 'name': u'Supplier Quotation Item' + }, + + # 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': 0, + 'print_hide': 0, + 'reqd': 1, + 'search_index': 1, + 'trigger': u'Client' + }, + + # DocField + { + 'colour': u'White:FFF', + 'description': u'If Supplier Part Number exists for given Item, it gets stored here', + 'doctype': u'DocField', + 'fieldname': u'supplier_part_no', + 'fieldtype': u'Data', + 'hidden': 1, + 'label': u'Supplier Part Number', + 'permlevel': 1, + 'print_hide': 1 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'item_name', + 'fieldtype': u'Data', + 'hidden': 0, + 'in_filter': 1, + 'label': u'Item Name', + 'oldfieldname': u'item_name', + 'oldfieldtype': u'Data', + 'permlevel': 0, + 'print_hide': 1, + 'reqd': 1, + 'search_index': 1 + }, + + # 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 + { + 'default': u'0.00', + 'doctype': u'DocField', + 'fieldname': u'qty', + 'fieldtype': u'Currency', + 'label': u'Quantity', + 'oldfieldname': u'qty', + 'oldfieldtype': u'Currency', + 'permlevel': 0, + 'reqd': 1, + 'trigger': u'Client', + 'width': u'60px' + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'import_ref_rate', + 'fieldtype': u'Currency', + 'label': u'Ref Rate ', + 'permlevel': 0, + 'print_hide': 1 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'discount_rate', + 'fieldtype': u'Currency', + 'label': u'Discount %', + 'permlevel': 0, + 'print_hide': 1, + 'trigger': u'Client' + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'import_rate', + 'fieldtype': u'Currency', + 'hidden': 0, + 'label': u'Rate ', + 'oldfieldname': u'import_rate', + 'oldfieldtype': u'Currency', + 'permlevel': 0, + 'print_hide': 0, + 'trigger': u'Client' + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'import_amount', + 'fieldtype': u'Currency', + 'label': u'Amount', + 'oldfieldname': u'import_amount', + 'oldfieldtype': u'Currency', + 'permlevel': 1 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'purchase_ref_rate', + 'fieldtype': u'Currency', + 'label': u'Ref Rate *', + 'permlevel': 0, + 'print_hide': 1 + }, + + # DocField + { + 'default': u'0.00', + 'doctype': u'DocField', + 'fieldname': u'purchase_rate', + 'fieldtype': u'Currency', + 'label': u'Rate (Default Curr.) *', + 'oldfieldname': u'purchase_rate', + 'oldfieldtype': u'Currency', + 'permlevel': 0, + 'print_hide': 1, + 'reqd': 1, + 'trigger': u'Client', + 'width': u'100px' + }, + + # DocField + { + 'default': u'0.00', + 'doctype': u'DocField', + 'fieldname': u'amount', + 'fieldtype': u'Currency', + 'label': u'Amount (Default Curr.)', + 'oldfieldname': u'amount', + 'oldfieldtype': u'Currency', + 'permlevel': 1, + 'print_hide': 1, + 'reqd': 1 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'warehouse', + 'fieldtype': u'Link', + 'hidden': 0, + 'label': u'Warehouse', + 'oldfieldname': u'warehouse', + 'oldfieldtype': u'Link', + 'options': u'Warehouse', + 'permlevel': 0, + 'print_hide': 1, + 'reqd': 0, + 'trigger': u'Client' + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'project_name', + 'fieldtype': u'Link', + 'in_filter': 1, + 'label': u'Project Name', + 'options': u'Project', + 'permlevel': 0, + 'print_hide': 1, + 'report_hide': 0 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'uom', + 'fieldtype': u'Link', + 'label': u'UOM', + 'oldfieldname': u'uom', + 'oldfieldtype': u'Link', + 'options': u'UOM', + 'permlevel': 0, + 'print_hide': 0, + 'reqd': 1, + 'trigger': u'Client', + 'width': u'100px' + }, + + # DocField + { + 'colour': u'White:FFF', + 'doctype': u'DocField', + 'fieldname': u'conversion_factor', + 'fieldtype': u'Currency', + 'hidden': 0, + 'label': u'UOM Conversion Factor', + 'oldfieldname': u'conversion_factor', + 'oldfieldtype': u'Currency', + 'permlevel': 0, + 'print_hide': 1, + 'reqd': 1, + 'trigger': u'Client', + 'width': u'100px' + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'stock_uom', + 'fieldtype': u'Data', + 'hidden': 0, + 'label': u'Stock UOM', + 'oldfieldname': u'stock_uom', + 'oldfieldtype': u'Data', + 'permlevel': 1, + 'print_hide': 1, + 'reqd': 1, + 'width': u'100px' + }, + + # DocField + { + 'colour': u'White:FFF', + 'doctype': u'DocField', + 'fieldname': u'prevdoc_doctype', + 'fieldtype': u'Data', + 'hidden': 1, + 'label': u'Prevdoc DocType', + 'no_copy': 0, + 'oldfieldname': u'prevdoc_doctype', + 'oldfieldtype': u'Data', + 'permlevel': 1, + 'print_hide': 1 + }, + + # DocField + { + 'colour': u'White:FFF', + 'doctype': u'DocField', + 'fieldname': u'prevdoc_docname', + 'fieldtype': u'Link', + 'hidden': 0, + 'in_filter': 1, + 'label': u'Purchase Request No', + 'no_copy': 0, + 'oldfieldname': u'prevdoc_docname', + 'oldfieldtype': u'Link', + 'options': u'Purchase Request', + 'permlevel': 1, + 'print_hide': 1, + 'search_index': 1, + 'width': u'120px' + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'prevdoc_date', + 'fieldtype': u'Date', + 'hidden': 1, + 'in_filter': 1, + 'label': u'Purchase Request Date', + 'oldfieldname': u'prevdoc_date', + 'oldfieldtype': u'Date', + 'permlevel': 1, + 'print_hide': 1, + 'search_index': 0 + }, + + # DocField + { + 'colour': u'White:FFF', + 'doctype': u'DocField', + 'fieldname': u'prevdoc_detail_docname', + 'fieldtype': u'Data', + 'hidden': 1, + 'in_filter': 1, + 'label': u'Purchase Request Detail No', + 'no_copy': 0, + 'oldfieldname': u'prevdoc_detail_docname', + 'oldfieldtype': u'Data', + 'permlevel': 1, + 'print_hide': 1, + 'search_index': 1 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'brand', + 'fieldtype': u'Link', + 'hidden': 1, + 'label': u'Brand', + 'oldfieldname': u'brand', + 'oldfieldtype': u'Link', + 'options': u'Brand', + 'permlevel': 1, + 'print_hide': 1 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'item_group', + 'fieldtype': u'Link', + 'hidden': 1, + 'in_filter': 1, + 'label': u'Item Group', + 'oldfieldname': u'item_group', + 'oldfieldtype': u'Link', + 'options': u'Item Group', + 'permlevel': 1, + 'print_hide': 1, + 'search_index': 0 + }, + + # DocField + { + 'colour': u'White:FFF', + 'description': u'Tax detail table fetched from item master as a string and stored in this field.\nUsed for Taxes and Charges', + 'doctype': u'DocField', + 'fieldname': u'item_tax_rate', + 'fieldtype': u'Small Text', + 'hidden': 1, + 'label': u'Item Tax Rate', + 'oldfieldname': u'item_tax_rate', + 'oldfieldtype': u'Small Text', + 'permlevel': 1, + 'print_hide': 1, + 'report_hide': 1 + }, + + # DocField + { + 'allow_on_submit': 1, + 'doctype': u'DocField', + 'fieldname': u'page_break', + 'fieldtype': u'Check', + 'hidden': 0, + 'label': u'Page Break', + 'no_copy': 1, + 'oldfieldname': u'page_break', + 'oldfieldtype': u'Check', + 'permlevel': 0, + 'print_hide': 1 + } +] \ No newline at end of file diff --git a/erpnext/buying/page/buying_home/buying_home.html b/erpnext/buying/page/buying_home/buying_home.html index 8e28e1b1e1..cd9312c7f1 100644 --- a/erpnext/buying/page/buying_home/buying_home.html +++ b/erpnext/buying/page/buying_home/buying_home.html @@ -5,6 +5,9 @@

Purchase Request

Request for purchase


+

Supplier Quotation

+

Track Quotations received from Suppliers

+

Purchase Order

Purchase Orders given to Suppliers

diff --git a/erpnext/patches/july_2012/project_patch_repeat.py b/erpnext/patches/july_2012/project_patch_repeat.py new file mode 100644 index 0000000000..4bb549c3f1 --- /dev/null +++ b/erpnext/patches/july_2012/project_patch_repeat.py @@ -0,0 +1,18 @@ +def execute(): + import webnotes + webnotes.conn.sql("""update `tabPurchase Order Item` t1, `tabPurchase Order` t2 + set t1.project_name = t2.project_name where t1.parent = t2.name + and ifnull(t1.project_name, '') = ''""") + webnotes.conn.sql("""update `tabPurchase Invoice Item` t1, `tabPurchase Invoice` t2 + set t1.project_name = t2.project_name where t1.parent = t2.name + and ifnull(t1.project_name, '') = ''""") + webnotes.conn.sql("""update `tabPurchase Receipt Item` t1, `tabPurchase Receipt` t2 + set t1.project_name = t2.project_name where t1.parent = t2.name + and ifnull(t1.project_name, '') = ''""") + + webnotes.conn.commit() + from webnotes.model.sync import sync + sync("buying", "purchase_order") + sync("buying", "purchase_request") + sync("accounts", "purchase_invoice") + webnotes.conn.begin() \ No newline at end of file diff --git a/erpnext/patches/patch_list.py b/erpnext/patches/patch_list.py index b84c956b36..e74206ab94 100644 --- a/erpnext/patches/patch_list.py +++ b/erpnext/patches/patch_list.py @@ -505,4 +505,8 @@ patch_list = [ 'patch_module': 'patches.july_2012', 'patch_file': 'bin_permission', }, + { + 'patch_module': 'patches.july_2012', + 'patch_file': 'project_patch_repeat', + }, ] \ No newline at end of file diff --git a/public/js/all-app.js b/public/js/all-app.js index 6e2fa3e36f..f7fc897a7f 100644 --- a/public/js/all-app.js +++ b/public/js/all-app.js @@ -2129,13 +2129,12 @@ _f.frm_dialog.cur_frm.fields_dict[n].refresh();}else{var g=_f.cur_grid_cell;if(g cur_frm.fields_dict[n].refresh();}} set_field_options=function(n,txt){var df=get_field(cur_frm.doctype,n,cur_frm.docname);if(df)df.options=txt;refresh_field(n);} set_field_permlevel=function(n,level){var df=get_field(cur_frm.doctype,n,cur_frm.docname);if(df)df.permlevel=level;refresh_field(n);} -hide_field=function(n){function _hide_field(n,hidden){var df=get_field(cur_frm.doctype,n,cur_frm.docname);if(df){df.hidden=hidden;refresh_field(n);} -else{console.log("hide_field cannot find field "+n);}} -if(cur_frm){if(n.substr)_hide_field(n,1);else{for(var i in n)_hide_field(n[i],1)}}} -unhide_field=function(n){function _hide_field(n,hidden){var df=get_field(cur_frm.doctype,n,cur_frm.docname);if(df){df.hidden=hidden;refresh_field(n);} -else{console.log("unhide_field cannot find field "+n);}} -if(cur_frm){if(n.substr)_hide_field(n,0);else{for(var i in n)_hide_field(n[i],0)}}} +toggle_field=function(n,hidden){var df_obj=get_field_obj(n);var df=get_field(cur_frm.doctype,n,cur_frm.docname);if(df){if(df_obj.df.fieldtype==="Section Break"){$(df_obj.row.wrapper).toggle(hidden?false:true);}else if(df_obj.df.fieldtype==="Column Break"){$(df_obj.cell.wrapper).toggle(hidden?false:true);}else{df.hidden=hidden;refresh_field(n);}} +else{console.log((hidden?"hide_field":"unhide_field")+" cannot find field "+n);}} +hide_field=function(n){if(cur_frm){if(n.substr)toggle_field(n,1);else{for(var i in n)toggle_field(n[i],1)}}} +unhide_field=function(n){if(cur_frm){if(n.substr)toggle_field(n,0);else{for(var i in n)toggle_field(n[i],0)}}} get_field_obj=function(fn){return cur_frm.fields_dict[fn];} +set_missing_values=function(doc,dict){var fields_to_set={};$.each(dict,function(i,v){if(!doc[i]){fields_to_set[i]=v;}});if(fields_to_set){set_multiple(doc.doctype,doc.name,fields_to_set);}} /* * lib/js/legacy/widgets/form/form_comments.js */ From 82926914703c351dbee586a6fe0fd73d7a334ec6 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 3 Aug 2012 08:39:17 +0530 Subject: [PATCH 05/12] stock repost patch --- erpnext/accounts/doctype/sales_invoice/sales_invoice.py | 1 + .../july_2012/repost_stock_due_to_wrong_packing_list.py | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index ec327c7e1b..6a7fb0186e 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -209,6 +209,7 @@ class DocType(TransactionBase): if ret['warehouse']: actual_qty = webnotes.conn.sql("select actual_qty from `tabBin` where item_code = '%s' and warehouse = '%s'" % (args['item_code'], ret['warehouse'])) ret['actual_qty']= actual_qty and flt(actual_qty[0][0]) or 0 + msgprint(ret) return ret def get_barcode_details(self, barcode): diff --git a/erpnext/patches/july_2012/repost_stock_due_to_wrong_packing_list.py b/erpnext/patches/july_2012/repost_stock_due_to_wrong_packing_list.py index ad6a23a171..5900a0af56 100644 --- a/erpnext/patches/july_2012/repost_stock_due_to_wrong_packing_list.py +++ b/erpnext/patches/july_2012/repost_stock_due_to_wrong_packing_list.py @@ -8,15 +8,15 @@ def repost_reserved_qty(): from `tabDelivery Note Packing Item` dnpi, `tabSales Order Item` so_item, `tabSales Order` so - where dnpi.parent = so.name + where dnpi.item_code = %s + and dnpi.warehouse = %s + and dnpi.parent = so.name and so_item.parent = so.name and dnpi.parenttype = 'Sales Order' and dnpi.parent_detail_docname = so_item.name and dnpi.parent_item = so_item.item_code and so.docstatus = 1 and so.status != 'Stopped' - and dnpi.item_code = %s - and dnpi.warehouse = %s """, (d[0], d[1])) if flt(d[3]) != flt(reserved_qty[0][0]): print d[3], reserved_qty[0][0] From 384b61749e1430fe03b935c266efb0a1157dad47 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Fri, 3 Aug 2012 14:09:32 +0530 Subject: [PATCH 06/12] added 'blog_subscriber' and 'unsubscribed' fields --- erpnext/selling/doctype/lead/lead.txt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/erpnext/selling/doctype/lead/lead.txt b/erpnext/selling/doctype/lead/lead.txt index a467f3af18..056fc16bae 100644 --- a/erpnext/selling/doctype/lead/lead.txt +++ b/erpnext/selling/doctype/lead/lead.txt @@ -5,7 +5,7 @@ { 'creation': '2012-06-05 20:03:20', 'docstatus': 0, - 'modified': '2012-08-02 18:01:53', + 'modified': '2012-08-03 10:49:22', 'modified_by': u'Administrator', 'owner': u'Administrator' }, @@ -686,5 +686,14 @@ 'fieldtype': u'Check', 'label': u'Unsubscribed', 'permlevel': 0 + }, + + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'blog_subscriber', + 'fieldtype': u'Check', + 'label': u'Blog Subscriber', + 'permlevel': 0 } ] \ No newline at end of file From 4b3b25e1d64e25f11898ae8e1f8f17f0440c3052 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Fri, 3 Aug 2012 14:10:59 +0530 Subject: [PATCH 07/12] aded 'add_subscriber' method to be called from website --- erpnext/website/blog.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/erpnext/website/blog.py b/erpnext/website/blog.py index 5692f51f43..ea1992b1fe 100644 --- a/erpnext/website/blog.py +++ b/erpnext/website/blog.py @@ -106,6 +106,25 @@ def add_comment(args=None): return comment_html +@webnotes.whitelist(allow_guest=True) +def add_subscriber(): + """add blog subscriber to lead""" + full_name = webnotes.form_dict.get('your_name') + email = webnotes.form_dict.get('your_email_address') + name = webnotes.conn.sql("""select name from tabLead where email_id=%s""", email) + + from webnotes.model.doc import Document + if name: + lead = Document('Lead', name[0][0]) + else: + lead = Document('Lead') + + lead.unsubscribed = 0 + lead.blog_subscriber = 1 + lead.lead_name = full_name + lead.email_id = email + lead.save() + def get_blog_content(blog_page_name): import website.web_cache content = website.web_cache.get_html(blog_page_name) From 0c5b4386238af66a121eaedbbab2a90070e42d9b Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Fri, 3 Aug 2012 14:12:14 +0530 Subject: [PATCH 08/12] framework updates --- public/js/all-app.js | 3 ++- public/js/all-web.js | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/public/js/all-app.js b/public/js/all-app.js index 6e2fa3e36f..ab4f3b1e80 100644 --- a/public/js/all-app.js +++ b/public/js/all-app.js @@ -870,7 +870,8 @@ opts.parent.appframe=new wn.ui.AppFrame($(opts.parent).find('.layout-appframe')) * lib/js/wn/ui/dialog.js */ wn.widgets.FieldGroup=function(){this.first_button=false;this.make_fields=function(body,fl){if(!window.make_field){wn.require('css/fields.css');wn.require('js/fields.js');} -$y(this.body,{padding:'11px'});this.fields_dict={};for(var i=0;i Date: Fri, 3 Aug 2012 14:13:30 +0530 Subject: [PATCH 09/12] created files for blog subscription to be embedded in blog and blog_page --- erpnext/website/templates/html/blog_page.html | 9 +++-- .../templates/html/blog_subscribe.html | 9 +++++ erpnext/website/templates/js/blog_page.js | 5 +-- .../website/templates/js/blog_subscribe.js | 33 +++++++++++++++++++ erpnext/website/templates/pages/blog.html | 15 +++------ 5 files changed, 53 insertions(+), 18 deletions(-) create mode 100644 erpnext/website/templates/html/blog_subscribe.html create mode 100644 erpnext/website/templates/js/blog_subscribe.js diff --git a/erpnext/website/templates/html/blog_page.html b/erpnext/website/templates/html/blog_page.html index 3b8348d8a7..12a1c7ac85 100644 --- a/erpnext/website/templates/html/blog_page.html +++ b/erpnext/website/templates/html/blog_page.html @@ -2,6 +2,7 @@ {% block javascript %} {% include "js/blog_page.js" %} + {% include "js/blog_subscribe.js" %} {% endblock %} {% block css %} @@ -41,11 +42,9 @@

All Blogs


-

Subscribe

-

- - RSS Feed -

+ {% block blog_subscribe %} + {% include "html/blog_subscribe.html" %} + {% endblock %}

Recent Posts

diff --git a/erpnext/website/templates/html/blog_subscribe.html b/erpnext/website/templates/html/blog_subscribe.html new file mode 100644 index 0000000000..7a4fd4954d --- /dev/null +++ b/erpnext/website/templates/html/blog_subscribe.html @@ -0,0 +1,9 @@ +

Subscribe

+
+

+ +

+

+ +RSS Feed +

\ No newline at end of file diff --git a/erpnext/website/templates/js/blog_page.js b/erpnext/website/templates/js/blog_page.js index 56dcf21b9d..02d6dd5377 100644 --- a/erpnext/website/templates/js/blog_page.js +++ b/erpnext/website/templates/js/blog_page.js @@ -59,8 +59,9 @@ erpnext.blog.render_recent_list = function(wrapper) { hide_refresh: true, render_row: function(parent, data) { if(data.content && data.content.length>=100) data.content += '...'; - parent.innerHTML = repl('%(title)s\ -
%(content)s

', data); + parent.innerHTML = repl('
\ + %(title)s\ +
%(content)s

', data); // adjust page height depending on sidebar height erpnext.blog.adjust_page_height(wrapper); diff --git a/erpnext/website/templates/js/blog_subscribe.js b/erpnext/website/templates/js/blog_subscribe.js new file mode 100644 index 0000000000..b3e10a7f70 --- /dev/null +++ b/erpnext/website/templates/js/blog_subscribe.js @@ -0,0 +1,33 @@ +wn.provide('erpnext.blog'); + +(function() { + $('body').on('click', '.btn-blog-subscribe', function() { + var d = new wn.ui.Dialog({ + title: "Get Blog Updates via Email", + fields: [ + {label: "Your Name", fieldtype:"Data", reqd:1}, + {label: "Your Email Address", fieldtype:"Data", reqd:1 + ,description: "You can unsubscribe anytime."}, + {label: "Subscribe", fieldtype:"Button"} + ] + }); + $(d.fields_dict.subscribe.input).click(function() { + var args = d.get_values(); + if(!args) return; + wn.call({ + method: 'website.blog.add_subscriber', + args: args, + callback: function(r) { + if(r.exc) { + msgprint('Opps there seems to be some error, Please check back after some time.'); + } else { + msgprint('Thanks for subscribing!'); + } + d.hide(); + }, + btn: this + }) + }) + d.show() + }) +})() diff --git a/erpnext/website/templates/pages/blog.html b/erpnext/website/templates/pages/blog.html index 40c90c29a3..17fd6e7ba6 100644 --- a/erpnext/website/templates/pages/blog.html +++ b/erpnext/website/templates/pages/blog.html @@ -2,6 +2,7 @@ {% block javascript %} {% include "js/blog.js" %} + {% include "js/blog_subscribe.js" %} {% endblock %} {% block css %} @@ -23,17 +24,9 @@
- -

Subscribe

-

- - RSS Feed -

+ {% block blog_subscribe %} + {% include "html/blog_subscribe.html" %} + {% endblock %}
From ba54cf6eef9e736a8d6ca2af6fccf9543e83eea2 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Fri, 3 Aug 2012 14:14:02 +0530 Subject: [PATCH 10/12] added 'Email Send' feature in blog to send blog by mail to all subscribers --- erpnext/website/doctype/blog/blog.js | 25 +++++++++++++++++++++++++ erpnext/website/doctype/blog/blog.py | 25 +++++++++++++++++++++++++ erpnext/website/doctype/blog/blog.txt | 14 ++++++++++++-- 3 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 erpnext/website/doctype/blog/blog.js diff --git a/erpnext/website/doctype/blog/blog.js b/erpnext/website/doctype/blog/blog.js new file mode 100644 index 0000000000..b0c1ec284d --- /dev/null +++ b/erpnext/website/doctype/blog/blog.js @@ -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 . + +cur_frm.cscript.refresh = function(doc) { + if(!doc.__islocal && doc.published && !doc.email_sent) { + cur_frm.add_custom_button('Email Subscribers', function() { + $c_obj(make_doclist(doc.doctype, doc.name), 'send_emails', '', function(r) { + cur_frm.refresh(); + }); + }) + } +} \ No newline at end of file diff --git a/erpnext/website/doctype/blog/blog.py b/erpnext/website/doctype/blog/blog.py index e361ece996..786941c7e1 100644 --- a/erpnext/website/doctype/blog/blog.py +++ b/erpnext/website/doctype/blog/blog.py @@ -29,6 +29,31 @@ class DocType(website.web_page.Page): super(DocType, self).__init__('Blog') self.doc, self.doclist = d, dl + def send_emails(self): + """send emails to subscribers""" + if self.doc.email_sent: + webnotes.msgprint("""Blog Subscribers already updated""", raise_exception=1) + + from webnotes.utils.email_lib.bulk import send + from markdown2 import markdown + import webnotes.utils + + # get leads that are subscribed to the blog + recipients = [e[0] for e in webnotes.conn.sql("""select distinct email_id from tabLead where + ifnull(blog_subscriber,0)=1""")] + + # make heading as link + content = '

%s

\n\n%s' % (webnotes.utils.get_request_site_address(), + self.doc.page_name, self.doc.title, markdown(self.doc.content)) + + # send the blog + send(recipients = recipients, doctype='Lead', email_field='email_id', + first_name_field = 'lead_name', last_name_field="", subject=self.doc.title, + message = markdown(content)) + + webnotes.conn.set(self.doc, 'email_sent', 1) + webnotes.msgprint("""Scheduled to send to %s subscribers""" % len(recipients)) + def on_update(self): super(DocType, self).on_update() if not webnotes.utils.cint(self.doc.published): diff --git a/erpnext/website/doctype/blog/blog.txt b/erpnext/website/doctype/blog/blog.txt index 6ed7143b2d..35d31c67d9 100644 --- a/erpnext/website/doctype/blog/blog.txt +++ b/erpnext/website/doctype/blog/blog.txt @@ -3,9 +3,9 @@ # These values are common in all dictionaries { - 'creation': '2012-07-13 13:02:27', + 'creation': '2012-07-27 19:32:53', 'docstatus': 0, - 'modified': '2012-07-27 14:15:24', + 'modified': '2012-08-03 12:18:36', 'modified_by': u'Administrator', 'owner': u'Administrator' }, @@ -113,6 +113,16 @@ 'permlevel': 1 }, + # DocField + { + 'doctype': u'DocField', + 'fieldname': u'email_sent', + 'fieldtype': u'Check', + 'hidden': 1, + 'label': u'Email Sent', + 'permlevel': 0 + }, + # DocField { 'doctype': u'DocField', From e5984873e698e4cdc3e0a911fce746da37216994 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Fri, 3 Aug 2012 14:15:07 +0530 Subject: [PATCH 11/12] added standard mail footer and function to get monthly bulk mail limit --- erpnext/startup/__init__.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/erpnext/startup/__init__.py b/erpnext/startup/__init__.py index 354989808d..cd443a082c 100644 --- a/erpnext/startup/__init__.py +++ b/erpnext/startup/__init__.py @@ -15,9 +15,13 @@ # along with this program. If not, see . # add startup propertes - -add_in_head = """ - -""" \ No newline at end of file +mail_footer = """
Sent via + ERPNext
""" + +def get_monthly_bulk_mail_limit(): + import webnotes + # if global settings, then 500 or unlimited + if webnotes.conn.get_value('Email Settings', None, 'outgoing_mail_server'): + return 999999 + else: + return 500 \ No newline at end of file From 52006ca83dfc02eb7ede439fa1b461f91a97af71 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Fri, 3 Aug 2012 14:15:25 +0530 Subject: [PATCH 12/12] bugfix in scheduler --- erpnext/startup/schedule_handlers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/startup/schedule_handlers.py b/erpnext/startup/schedule_handlers.py index 021cb1f600..2df7a5789d 100644 --- a/erpnext/startup/schedule_handlers.py +++ b/erpnext/startup/schedule_handlers.py @@ -42,7 +42,7 @@ def execute_daily(): run_fn(send) # send bulk emails - from webnotes.utils.email_lib.bulk import cleanup + from webnotes.utils.email_lib.bulk import clear_outbox run_fn(clear_outbox) def execute_weekly():