From a4fdc84fdaf7f2ab761d64eb7586db58b73fa165 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 6 Dec 2011 15:04:47 +0530 Subject: [PATCH 1/7] Introduced recurring invoices --- .../accounts/doctype/gl_control/gl_control.py | 47 +++++-- .../receivable_voucher/receivable_voucher.js | 9 ++ .../receivable_voucher/receivable_voucher.py | 61 ++++++++- .../receivable_voucher/receivable_voucher.txt | 116 +++++++++++++++++- 4 files changed, 217 insertions(+), 16 deletions(-) diff --git a/erpnext/accounts/doctype/gl_control/gl_control.py b/erpnext/accounts/doctype/gl_control/gl_control.py index 44a9e8d8c9e..585892075fb 100644 --- a/erpnext/accounts/doctype/gl_control/gl_control.py +++ b/erpnext/accounts/doctype/gl_control/gl_control.py @@ -4,8 +4,8 @@ import webnotes from webnotes.utils import add_days, add_months, add_years, cint, cstr, date_diff, default_fields, flt, fmt_money, formatdate, generate_hash, getTraceback, get_defaults, get_first_day, get_last_day, getdate, has_common, month_name, now, nowdate, replace_newlines, sendmail, set_default, str_esc_quote, user_format, validate_email_add from webnotes.model import db_exists from webnotes.model.doc import Document, addchild, removechild, getchildren, make_autoname, SuperDocType -from webnotes.model.doclist import getlist, copy_doclist -from webnotes.model.code import get_obj, get_server_obj, run_server_obj, updatedb, check_syntax +from webnotes.model.doclist import getlist, copy_doclist, clone +from webnotes.model.code import get_obj from webnotes import session, form, is_testing, msgprint, errprint sql = webnotes.conn.sql @@ -24,14 +24,8 @@ class DocType: # Get Company List # ---------------- def get_companies(self,arg=''): - #d = get_defaults() ret = sql("select name, abbr from tabCompany where docstatus != 2") - #pl = {} - #for r in ret: - # inc = get_value('Account','Income - '+r[1], 'balance') - # exp = get_value('Account','Expenses - '+r[1], 'balance') - # pl[r[0]] = flt(flt(inc) - flt(exp)) - return {'cl':[r[0] for r in ret]}#, 'pl':pl} + return {'cl':[r[0] for r in ret]} def get_company_currency(self,arg=''): dcc = TransactionBase().get_company_currency(arg) @@ -506,3 +500,38 @@ In Account := %s User := %s has Repaired Outstanding Amount For %s : %s and foll for a in set(ac_list): fy_obj.repost(a) + +def manage_recurring_invoices(): + """ + Create recurring invoices on specific date by copying the original one + and notify the concerned people + """ + rv = sql("""select name, recurring_id from `tabReceivable Voucher` where ifnull(convert_into_recurring_invoice, 0) = 1 + and next_date = %s and next_date <= end_date""", nowdate()) + for d in rv: + if not sql("""select name from `tabReceivable Voucher` where posting_date = %s and recurring_id = %s""", (nowdate, d[1])): + prev_rv = get_obj('Receivable Voucher', d[0], with_children=1) + new_rv = create_new_invoice(prev_rv) + + send_notification(new_rv) + +def create_new_invoice(prev_rv): + # clone rv + new_rv = clone(prev_rv) + + # update new rv + new_rv.doc.voucher_date = new_rv.doc.next_date + new_rv.doc.posting_date = new_rv.doc.next_date + new_rv.doc.aging_date = new_rv.doc.next_date + new_rv.doc.due_date = add_days(new_rv.doc.next_date, cint(date_diff(prev_rv.doc.due_date, prev_rv.doc.posting_date))) + new_rv.doc.save() + + # submit and after submit + new_rv.submit() + new_rv.update_after_submit() + + return new_rv + +def send_notification(new_rv): + """Notify concerned persons about recurring invoice generation""" + pass diff --git a/erpnext/accounts/doctype/receivable_voucher/receivable_voucher.js b/erpnext/accounts/doctype/receivable_voucher/receivable_voucher.js index bb19681b98c..363da2ec573 100644 --- a/erpnext/accounts/doctype/receivable_voucher/receivable_voucher.js +++ b/erpnext/accounts/doctype/receivable_voucher/receivable_voucher.js @@ -433,3 +433,12 @@ cur_frm.cscript['View Ledger Entry'] = function(){ } loadreport('GL Entry','General Ledger', callback); } + +// Default values for recurring invoices +cur_frm.cscript.convert_into_recurring_invoice = function(doc) { + if (doc.convert_into_recurring_invoice) { + doc.repeat_on_day_of_month = doc.posting_date.split('-')[2]; + doc.notification_email_address = doc.owner + ', ' + doc.contact_email; + refresh_field(['repeat_on_day_of_month', 'notification_email_address']); + } +} diff --git a/erpnext/accounts/doctype/receivable_voucher/receivable_voucher.py b/erpnext/accounts/doctype/receivable_voucher/receivable_voucher.py index 6d1f80adb98..13ed8d3c5e2 100644 --- a/erpnext/accounts/doctype/receivable_voucher/receivable_voucher.py +++ b/erpnext/accounts/doctype/receivable_voucher/receivable_voucher.py @@ -1,12 +1,13 @@ # Please edit this list and import only required elements import webnotes -from webnotes.utils import add_days, add_months, add_years, cint, cstr, date_diff, default_fields, flt, fmt_money, formatdate, generate_hash, getTraceback, get_defaults, get_first_day, get_last_day, getdate, has_common, month_name, now, nowdate, replace_newlines, sendmail, set_default, str_esc_quote, user_format, validate_email_add +from webnotes.utils import add_days, add_months, add_years, cint, cstr,date_diff, default_fields, flt, fmt_money, formatdate, generate_hash,getTraceback, get_defaults, get_first_day, get_last_day, getdate, has_common,month_name, now, nowdate, replace_newlines, sendmail, set_default,str_esc_quote, user_format, validate_email_add from webnotes.model import db_exists from webnotes.model.doc import Document, addchild, removechild, getchildren, make_autoname, SuperDocType from webnotes.model.doclist import getlist, copy_doclist from webnotes.model.code import get_obj, get_server_obj, run_server_obj, updatedb, check_syntax from webnotes import session, form, is_testing, msgprint, errprint +from webnotes.utils.scheduler import set_event, cancel_event, Scheduler set = webnotes.conn.set sql = webnotes.conn.sql @@ -528,7 +529,6 @@ class DocType(TransactionBase): def make_gl_entries(self, is_cancel=0): mapper = self.doc.is_pos and self.doc.write_off_account and 'POS with write off' or self.doc.is_pos and not self.doc.write_off_account and 'POS' or '' update_outstanding = self.doc.is_pos and self.doc.write_off_account and 'No' or 'Yes' - get_obj(dt='GL Control').make_gl_entries(self.doc, self.doclist,cancel = is_cancel, use_mapper = mapper, update_outstanding = update_outstanding, merge_entries = cint(self.doc.is_pos) != 1 and 1 or 0) @@ -546,7 +546,8 @@ class DocType(TransactionBase): get_obj("Sales Common").update_prevdoc_detail(1,self) # Check for Approving Authority - get_obj('Authorization Control').validate_approving_authority(self.doc.doctype, self.doc.company, self.doc.grand_total, self) + if not self.doc.recurring_id: + get_obj('Authorization Control').validate_approving_authority(self.doc.doctype, self.doc.company, self.doc.grand_total, self) # this sequence because outstanding may get -ve self.make_gl_entries() @@ -618,9 +619,61 @@ class DocType(TransactionBase): set(self.doc,'outstanding_amount',flt(self.doc.grand_total) - flt(self.doc.total_advance) - flt(self.doc.paid_amount) - flt(self.doc.write_off_amount)) - ######################################################################## # Repair Outstanding ####################################################################### def repair_rv_outstanding(self): get_obj(dt = 'GL Control').repair_voucher_outstanding(self) + + def on_update_after_submit(self): + self.convert_into_recurring() + + + def convert_into_recurring(self): + if self.doc.convert_into_recurring_invoice: + event = 'accounts.doctype.gl_control.gl_control.manage_recurring_invoices' + self.set_next_date() + if not self.doc.recurring_id: + set(self.doc, 'recurring_id', make_autoname('RECINV/.#####')) + + if sql("select name from `tabReceivable Voucher` where ifnull(convert_into_recurring_invoice, 0) = 1 and next_date <= end_date"): + if not self.check_event_exists(event): + set_event(event, interval = 60*60, recurring = 1) + else: + cancel_event(event) + + elif self.doc.recurring_id: + sql("""update `tabReceivable Voucher` set convert_into_recurring_invoice = 0 where recurring_id = %s""", self.doc.recurring_id) + + + def check_event_exists(self, event): + try: + ev = Scheduler().get_events() + except: + msgprint("Scheduler database not exists. Please mail to support@erpnext.com", raise_exception=1) + + if event in [d['event'] for d in ev]: + return 1 + + + def set_next_date(self): + """ Set next date on which auto invoice will be created""" + + if not self.doc.repeat_on_day_of_month: + msgprint("""Please enter 'Repeat on Day of Month' field value. \nThe day of the month on which auto invoice + will be generated e.g. 05, 28 etc.""", raise_exception=1) + + import datetime + m = getdate(self.doc.posting_date).month + 1 + y = getdate(self.doc.posting_date).year + if m > 12: + m, y = 1, y+1 + try: + next_date = datetime.date(y, m, cint(self.doc.repeat_on_day_of_month)) + except: + import calendar + last_day = calendar.monthrange(y, m)[1] + next_date = datetime.date(y, m, last_day) + next_date = next_date.strftime("%Y-%m-%d") + + set(self.doc, 'next_date', next_date) diff --git a/erpnext/accounts/doctype/receivable_voucher/receivable_voucher.txt b/erpnext/accounts/doctype/receivable_voucher/receivable_voucher.txt index 1abd6a725b1..e2fc0c6416e 100644 --- a/erpnext/accounts/doctype/receivable_voucher/receivable_voucher.txt +++ b/erpnext/accounts/doctype/receivable_voucher/receivable_voucher.txt @@ -5,7 +5,7 @@ { 'creation': '2010-08-08 17:09:18', 'docstatus': 0, - 'modified': '2011-10-19 16:31:54', + 'modified': '2011-12-06 13:17:26', 'modified_by': 'Administrator', 'owner': 'Administrator' }, @@ -21,7 +21,7 @@ # These values are common for all DocType { - '_last_update': '1319014846', + '_last_update': '1323156733', 'change_log': '1. Change in pull_details method dt.-26-06-2009', 'colour': 'White:FFF', 'default_print_format': 'Standard', @@ -34,7 +34,7 @@ 'server_code_error': ' ', 'show_in_menu': 0, 'subject': 'To %(customer_name)s worth %(currency)s %(grand_total_export)s due on %(due_date)s | %(outstanding_amount)s outstanding', - 'version': 363 + 'version': 383 }, # These values are common for all DocFormat @@ -1343,5 +1343,115 @@ 'permlevel': 0, 'print_hide': 1, 'report_hide': 1 + }, + + # DocField + { + 'depends_on': 'eval:doc.docstatus==1', + 'doctype': 'DocField', + 'fieldtype': 'Section Break', + 'label': 'Recurring Invoice', + 'permlevel': 0 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldtype': 'Column Break', + 'permlevel': 0, + 'width': '50%' + }, + + # DocField + { + 'allow_on_submit': 1, + 'colour': 'White:FFF', + 'depends_on': 'eval:doc.docstatus==1', + 'description': 'Check if recurring invoice, uncheck to stop recurring or put proper End Date', + 'doctype': 'DocField', + 'fieldname': 'convert_into_recurring_invoice', + 'fieldtype': 'Check', + 'label': 'Convert into Recurring Invoice', + 'no_copy': 1, + 'permlevel': 0, + 'print_hide': 1, + 'trigger': 'Client' + }, + + # DocField + { + 'allow_on_submit': 1, + 'depends_on': 'eval:doc.convert_into_recurring_invoice==1', + 'description': 'The day of the month on which auto invoice will be generated e.g. 05, 28 etc ', + 'doctype': 'DocField', + 'fieldname': 'repeat_on_day_of_month', + 'fieldtype': 'Data', + 'label': 'Repeat on Day of Month', + 'no_copy': 1, + 'permlevel': 0, + 'print_hide': 1 + }, + + # DocField + { + 'allow_on_submit': 1, + 'depends_on': 'eval:doc.convert_into_recurring_invoice==1', + 'description': 'The date on which recurring invoice will be stop', + 'doctype': 'DocField', + 'fieldname': 'end_date', + 'fieldtype': 'Date', + 'label': 'End Date', + 'no_copy': 1, + 'permlevel': 0, + 'print_hide': 1 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldtype': 'Column Break', + 'no_copy': 0, + 'permlevel': 0, + 'width': '50%' + }, + + # DocField + { + 'allow_on_submit': 1, + 'depends_on': 'eval:doc.convert_into_recurring_invoice==1', + 'description': 'Enter email id separated by commas, invoice will be mailed automatically on particular date', + 'doctype': 'DocField', + 'fieldname': 'notification_email_address', + 'fieldtype': 'Small Text', + 'label': 'Notification Email Address', + 'no_copy': 1, + 'permlevel': 0, + 'print_hide': 1 + }, + + # DocField + { + 'depends_on': 'eval:doc.convert_into_recurring_invoice==1', + 'description': 'The unique id for tracking all recurring invoices ', + 'doctype': 'DocField', + 'fieldname': 'recurring_id', + 'fieldtype': 'Data', + 'label': 'Recurring Id', + 'no_copy': 1, + 'permlevel': 1, + 'print_hide': 1 + }, + + # DocField + { + 'depends_on': 'eval:doc.convert_into_recurring_invoice==1', + 'description': 'The date on which next invoice will be generated ', + 'doctype': 'DocField', + 'fieldname': 'next_date', + 'fieldtype': 'Date', + 'label': 'Next Date', + 'no_copy': 1, + 'permlevel': 1, + 'print_hide': 1 } ] \ No newline at end of file From ea5f5ca57d9a3f423b506f9262379777a06f3505 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 6 Dec 2011 15:10:48 +0530 Subject: [PATCH 2/7] Recurring invoices patch --- erpnext/patches/reload_rv.py | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 erpnext/patches/reload_rv.py diff --git a/erpnext/patches/reload_rv.py b/erpnext/patches/reload_rv.py new file mode 100644 index 00000000000..b52b1114b44 --- /dev/null +++ b/erpnext/patches/reload_rv.py @@ -0,0 +1,5 @@ +def execute(): + import webnotes + from webnotes.modules.module_manager import reload_doc + + reload_doc('accounts', 'doctype', 'receivable_voucher') From b28d6dc617ab7ad851f46c2373582ef37433d5e6 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 6 Dec 2011 15:11:14 +0530 Subject: [PATCH 3/7] Repost stock patch --- erpnext/patches/repost_stock.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 erpnext/patches/repost_stock.py diff --git a/erpnext/patches/repost_stock.py b/erpnext/patches/repost_stock.py new file mode 100644 index 00000000000..680e06f4354 --- /dev/null +++ b/erpnext/patches/repost_stock.py @@ -0,0 +1,22 @@ +def execute(): + import webnotes + sql = webnotes.conn.sql + from webnotes.model.code import get_obj + + # update incoming rate in serial nos + sr = sql("""select name, item_code, purchase_document_no from `tabSerial No` + where docstatus = 1 and purchase_document_type = 'Purchase Receipt'""") + for d in sr: + val_rate = sql("""select valuation_rate from `tabPurchase Receipt Detail` + where item_code = %s and parent = %s""", (d[1], d[2])) + sql("""update `tabSerial No` set purchase_rate = %s where name = %s""", + (val_rate and flt(val_rate[0][0]) or 0, d[0])) + + + # repost for all serialized item + bin = sql("""select t1.name from `tabBin` t1, tabItem t2 where t1.item_code = t2.name and ifnull(has_serial_no, 'No') = 'Yes'""") + for d in bin: + get_obj('Bin', d[0]).update_entries_after(posting_date = '2000-01-01', posting_time = '12:00') + sql("commit") + sql("start transaction") + From 38d24534d79722a03c6130c6a3b817fd4cd20b94 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 6 Dec 2011 19:04:21 +0530 Subject: [PATCH 4/7] Recurring invoice checkbox added in features setup --- .../accounts/doctype/gl_control/gl_control.py | 5 +- erpnext/patches/reload_rv.py | 3 ++ .../doctype/features_setup/features_setup.txt | 49 ++++++++++++++----- erpnext/startup/startup.js | 3 ++ 4 files changed, 45 insertions(+), 15 deletions(-) diff --git a/erpnext/accounts/doctype/gl_control/gl_control.py b/erpnext/accounts/doctype/gl_control/gl_control.py index 585892075fb..01f31eb7ddc 100644 --- a/erpnext/accounts/doctype/gl_control/gl_control.py +++ b/erpnext/accounts/doctype/gl_control/gl_control.py @@ -507,9 +507,9 @@ def manage_recurring_invoices(): and notify the concerned people """ rv = sql("""select name, recurring_id from `tabReceivable Voucher` where ifnull(convert_into_recurring_invoice, 0) = 1 - and next_date = %s and next_date <= end_date""", nowdate()) + and next_date = %s and next_date <= end_date order by next_date desc""", nowdate()) for d in rv: - if not sql("""select name from `tabReceivable Voucher` where posting_date = %s and recurring_id = %s""", (nowdate, d[1])): + if not sql("""select name from `tabReceivable Voucher` where posting_date = %s and recurring_id = %s""", (nowdate(), d[1])): prev_rv = get_obj('Receivable Voucher', d[0], with_children=1) new_rv = create_new_invoice(prev_rv) @@ -520,6 +520,7 @@ def create_new_invoice(prev_rv): new_rv = clone(prev_rv) # update new rv + new_rv.doc.voucher_date = new_rv.doc.next_date new_rv.doc.posting_date = new_rv.doc.next_date new_rv.doc.aging_date = new_rv.doc.next_date diff --git a/erpnext/patches/reload_rv.py b/erpnext/patches/reload_rv.py index b52b1114b44..5f3bc210ae0 100644 --- a/erpnext/patches/reload_rv.py +++ b/erpnext/patches/reload_rv.py @@ -1,5 +1,8 @@ def execute(): import webnotes from webnotes.modules.module_manager import reload_doc + from webnotes.model.code import get_obj reload_doc('accounts', 'doctype', 'receivable_voucher') + + get_obj('Features setup').validate() diff --git a/erpnext/setup/doctype/features_setup/features_setup.txt b/erpnext/setup/doctype/features_setup/features_setup.txt index 909882eed97..d0f02d576d4 100644 --- a/erpnext/setup/doctype/features_setup/features_setup.txt +++ b/erpnext/setup/doctype/features_setup/features_setup.txt @@ -5,14 +5,14 @@ { 'creation': '2011-09-07 11:59:05', 'docstatus': 0, - 'modified': '2011-10-05 10:50:17', + 'modified': '2011-12-06 18:48:53', 'modified_by': 'Administrator', 'owner': 'Administrator' }, # These values are common for all DocType { - '_last_update': '1317790484', + '_last_update': '1323176623', 'colour': 'White:FFF', 'default_print_format': 'Standard', 'doctype': 'DocType', @@ -22,7 +22,7 @@ 'name_case': 'Title Case', 'section_style': 'Simple', 'show_in_menu': 1, - 'version': 21 + 'version': 24 }, # These values are common for all DocField @@ -211,6 +211,39 @@ 'label': 'Sales Extras' }, + # DocField + { + 'doctype': 'DocField', + 'fieldtype': 'Section Break', + 'label': 'Accounts' + }, + + # DocField + { + 'colour': 'White:FFF', + 'description': 'Check if you need automatic recurring invoices. After submitting any sales invoice, Recurring section will be visible.', + 'doctype': 'DocField', + 'fieldname': 'fs_recurring_invoice', + 'fieldtype': 'Check', + 'label': 'Recurring Invoice' + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldtype': 'Column Break' + }, + + # DocField + { + 'colour': 'White:FFF', + 'description': 'To enable Point of Sale features', + 'doctype': 'DocField', + 'fieldname': 'fs_pos', + 'fieldtype': 'Check', + 'label': 'Point of Sale' + }, + # DocField { 'doctype': 'DocField', @@ -244,16 +277,6 @@ 'label': 'Quality' }, - # DocField - { - 'colour': 'White:FFF', - 'description': 'To enable Point of Sale features', - 'doctype': 'DocField', - 'fieldname': 'fs_pos', - 'fieldtype': 'Check', - 'label': 'Point of Sale' - }, - # DocField { 'doctype': 'DocField', diff --git a/erpnext/startup/startup.js b/erpnext/startup/startup.js index fcb097bd4ed..291265b3bd2 100644 --- a/erpnext/startup/startup.js +++ b/erpnext/startup/startup.js @@ -690,6 +690,9 @@ pscript.feature_dict = { }, 'fs_pos': { 'Receivable Voucher': {'fields':['is_pos']} + }, + 'fs_recurring_invoice': { + 'Receivable Voucher': {'fields': ['Recurring Invoice']} } } From fd20340576fb4e6f5eb004dd2fde3bf4e5b0b9e5 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 8 Dec 2011 17:49:40 +0530 Subject: [PATCH 5/7] Introduced C-form for Indian customer --- .../accounts/Module Def/Accounts/Accounts.txt | 11 +- erpnext/accounts/doctype/c_form/__init__.py | 0 erpnext/accounts/doctype/c_form/c_form.js | 10 + erpnext/accounts/doctype/c_form/c_form.py | 34 ++++ erpnext/accounts/doctype/c_form/c_form.txt | 190 ++++++++++++++++++ .../doctype/c_form_invoice_detail/__init__.py | 0 .../c_form_invoice_detail.txt | 91 +++++++++ .../receivable_voucher/receivable_voucher.py | 24 ++- .../receivable_voucher/receivable_voucher.txt | 31 ++- 9 files changed, 385 insertions(+), 6 deletions(-) create mode 100644 erpnext/accounts/doctype/c_form/__init__.py create mode 100644 erpnext/accounts/doctype/c_form/c_form.js create mode 100644 erpnext/accounts/doctype/c_form/c_form.py create mode 100644 erpnext/accounts/doctype/c_form/c_form.txt create mode 100644 erpnext/accounts/doctype/c_form_invoice_detail/__init__.py create mode 100644 erpnext/accounts/doctype/c_form_invoice_detail/c_form_invoice_detail.txt diff --git a/erpnext/accounts/Module Def/Accounts/Accounts.txt b/erpnext/accounts/Module Def/Accounts/Accounts.txt index 0a6921a13c2..f9c36c823f9 100644 --- a/erpnext/accounts/Module Def/Accounts/Accounts.txt +++ b/erpnext/accounts/Module Def/Accounts/Accounts.txt @@ -5,7 +5,7 @@ { 'creation': '2010-09-25 10:50:37', 'docstatus': 0, - 'modified': '2011-09-27 12:44:04', + 'modified': '2011-12-07 16:18:28', 'modified_by': 'Administrator', 'owner': 'Administrator' }, @@ -179,6 +179,15 @@ 'doctype': 'Module Def Item' }, + # Module Def Item + { + 'description': 'Track C-Form received from customers', + 'display_name': 'C-Form', + 'doc_name': 'C-Form', + 'doc_type': 'Setup Forms', + 'doctype': 'Module Def Item' + }, + # Module Def Item { 'display_name': 'General Ledger', diff --git a/erpnext/accounts/doctype/c_form/__init__.py b/erpnext/accounts/doctype/c_form/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/accounts/doctype/c_form/c_form.js b/erpnext/accounts/doctype/c_form/c_form.js new file mode 100644 index 00000000000..4a90a9d1d61 --- /dev/null +++ b/erpnext/accounts/doctype/c_form/c_form.js @@ -0,0 +1,10 @@ +//c-form js file +// ----------------------------- +cur_frm.fields_dict.invoice_details.grid.get_field("invoice_no").get_query = function(doc) { + return 'SELECT `tabReceivable Voucher`.`name` FROM `tabReceivable Voucher` WHERE `tabReceivable Voucher`.`company` = "' +doc.company+'" AND `tabReceivable Voucher`.%(key)s LIKE "%s" AND `tabReceivable Voucher`.`customer` = "' + doc.customer + '" AND `tabReceivable Voucher`.`docstatus` = 1 and `tabReceivable Voucher`.`c_form_applicable` = "Yes" ORDER BY `tabReceivable Voucher`.`name` ASC LIMIT 50'; +} + +cur_frm.cscript.invoice_no = function(doc, cdt, cdn) { + var d = locals[cdt][cdn]; + get_server_fields('get_invoice_details', d.invoice_no, 'invoice_details', doc, cdt, cdn, 1); +} diff --git a/erpnext/accounts/doctype/c_form/c_form.py b/erpnext/accounts/doctype/c_form/c_form.py new file mode 100644 index 00000000000..00016cb053b --- /dev/null +++ b/erpnext/accounts/doctype/c_form/c_form.py @@ -0,0 +1,34 @@ +# Please edit this list and import only required elements +import webnotes +from webnotes.utils import add_days, cint, cstr, date_diff, default_fields, flt, getdate, now, nowdate +from webnotes.model.doc import Document, addchild, removechild, getchildren, make_autoname, SuperDocType +from webnotes.model.doclist import getlist, copy_doclist +from webnotes.model.code import get_obj +from webnotes import msgprint, errprint + +sql = webnotes.conn.sql +# ----------------------------------------------------------------------------------------- + + +class DocType: + def __init__(self,d,dl): + self.doc, self.doclist = d,dl + + def autoname(self): + self.doc.name = make_autoname(self.doc.naming_series + '.#####') + + def on_update(self): + inv = "'" + "', '".join([d.invoice_no for d in getlist(self.doclist, 'invoice_details')]) + "'" + sql("""update `tabReceivable Voucher` set c_form_no = '%s', modified ='%s' + where name in (%s)"""%(self.doc.name, self.doc.modified, inv)) + + def get_invoice_details(self, invoice_no): + inv = sql("""select posting_date, territory, net_total, grand_total from + `tabReceivable Voucher` where name = %s""", invoice_no) + ret = { + 'invoice_date' : inv and getdate(inv[0][0]).strftime('%Y-%m-%d') or '', + 'territory' : inv and inv[0][1] or '', + 'net_total' : inv and flt(inv[0][2]) or '', + 'grand_total' : inv and flt(inv[0][3]) or '' + } + return ret diff --git a/erpnext/accounts/doctype/c_form/c_form.txt b/erpnext/accounts/doctype/c_form/c_form.txt new file mode 100644 index 00000000000..987bc9a7b37 --- /dev/null +++ b/erpnext/accounts/doctype/c_form/c_form.txt @@ -0,0 +1,190 @@ +# DocType, C-Form +[ + + # These values are common in all dictionaries + { + 'creation': '2011-12-07 16:16:16', + 'docstatus': 0, + 'modified': '2011-12-07 17:50:17', + 'modified_by': 'Administrator', + 'owner': 'Administrator' + }, + + # These values are common for all DocType + { + '_last_update': '1323255350', + 'colour': 'White:FFF', + 'doctype': 'DocType', + 'module': 'Accounts', + 'name': '__common__', + 'section_style': 'Simple', + 'show_in_menu': 0, + 'version': 11 + }, + + # These values are common for all DocField + { + 'doctype': 'DocField', + 'name': '__common__', + 'parent': 'C-Form', + 'parentfield': 'fields', + 'parenttype': 'DocType', + 'permlevel': 0 + }, + + # These values are common for all DocPerm + { + 'doctype': 'DocPerm', + 'name': '__common__', + 'parent': 'C-Form', + 'parentfield': 'permissions', + 'parenttype': 'DocType', + 'read': 1 + }, + + # DocType, C-Form + { + 'doctype': 'DocType', + 'name': 'C-Form' + }, + + # DocPerm + { + 'create': 1, + 'doctype': 'DocPerm', + 'permlevel': 0, + 'role': 'Accounts User', + 'write': 1 + }, + + # DocPerm + { + 'create': 1, + 'doctype': 'DocPerm', + 'permlevel': 0, + 'role': 'Accounts Manager', + 'submit': 0, + 'write': 1 + }, + + # DocPerm + { + 'doctype': 'DocPerm', + 'permlevel': 1, + 'role': 'All' + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldtype': 'Column Break', + 'width': '50%' + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'naming_series', + 'fieldtype': 'Select', + 'label': 'Series', + 'options': '\nC-FORM/', + 'reqd': 1 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'c_form_no', + 'fieldtype': 'Data', + 'label': 'C-Form No', + 'reqd': 1 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'received_date', + 'fieldtype': 'Date', + 'label': 'Received Date', + 'reqd': 1 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'customer', + 'fieldtype': 'Link', + 'label': 'Customer', + 'options': 'Customer', + 'reqd': 1 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldtype': 'Column Break', + 'width': '50%' + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'company', + 'fieldtype': 'Select', + 'label': 'Company', + 'options': 'link:Company' + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'fiscal_year', + 'fieldtype': 'Select', + 'label': 'Fiscal Year', + 'options': 'link:Fiscal Year', + 'reqd': 1 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'quarter', + 'fieldtype': 'Select', + 'label': 'Quarter', + 'options': '\nI\nII\nIII\nIV' + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'total_amount', + 'fieldtype': 'Currency', + 'label': 'Total Amount', + 'reqd': 1 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'state', + 'fieldtype': 'Select', + 'label': 'State', + 'options': "link:State\ncountry='India'", + 'reqd': 1 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldtype': 'Section Break' + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'invoice_details', + 'fieldtype': 'Table', + 'label': 'Invoice Details', + 'options': 'C-Form Invoice Detail' + } +] \ No newline at end of file diff --git a/erpnext/accounts/doctype/c_form_invoice_detail/__init__.py b/erpnext/accounts/doctype/c_form_invoice_detail/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/erpnext/accounts/doctype/c_form_invoice_detail/c_form_invoice_detail.txt b/erpnext/accounts/doctype/c_form_invoice_detail/c_form_invoice_detail.txt new file mode 100644 index 00000000000..d6be6c0d4d3 --- /dev/null +++ b/erpnext/accounts/doctype/c_form_invoice_detail/c_form_invoice_detail.txt @@ -0,0 +1,91 @@ +# DocType, C-Form Invoice Detail +[ + + # These values are common in all dictionaries + { + 'creation': '2011-12-07 16:15:39', + 'docstatus': 0, + 'modified': '2011-12-07 16:21:55', + 'modified_by': 'Administrator', + 'owner': 'Administrator' + }, + + # These values are common for all DocType + { + 'colour': 'White:FFF', + 'doctype': 'DocType', + 'istable': 1, + 'module': 'Accounts', + 'name': '__common__', + 'section_style': 'Simple', + 'show_in_menu': 0, + 'version': 5 + }, + + # These values are common for all DocField + { + 'doctype': 'DocField', + 'name': '__common__', + 'parent': 'C-Form Invoice Detail', + 'parentfield': 'fields', + 'parenttype': 'DocType' + }, + + # DocType, C-Form Invoice Detail + { + 'doctype': 'DocType', + 'name': 'C-Form Invoice Detail' + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'invoice_no', + 'fieldtype': 'Link', + 'label': 'Invoice No', + 'options': 'Receivable Voucher', + 'permlevel': 0, + 'width': '160px' + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'invoice_date', + 'fieldtype': 'Date', + 'label': 'Invoice Date', + 'permlevel': 1, + 'width': '120px' + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'territory', + 'fieldtype': 'Link', + 'label': 'Territory', + 'options': 'Territory', + 'permlevel': 1, + 'width': '120px' + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'net_total', + 'fieldtype': 'Currency', + 'label': 'Net Total', + 'permlevel': 1, + 'width': '120px' + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'grand_total', + 'fieldtype': 'Currency', + 'label': 'Grand Total', + 'permlevel': 1, + 'width': '120px' + } +] \ No newline at end of file diff --git a/erpnext/accounts/doctype/receivable_voucher/receivable_voucher.py b/erpnext/accounts/doctype/receivable_voucher/receivable_voucher.py index 13ed8d3c5e2..57d8c55facc 100644 --- a/erpnext/accounts/doctype/receivable_voucher/receivable_voucher.py +++ b/erpnext/accounts/doctype/receivable_voucher/receivable_voucher.py @@ -397,6 +397,14 @@ class DocType(TransactionBase): if flt(self.doc.write_off_amount) and not self.doc.write_off_account: msgprint("Please enter Write Off Account", raise_exception=1) + + def validate_c_form(self): + """ Blank C-form no if C-form applicable marked as 'No'""" + if self.doc.amended_from and self.doc.c_form_applicable == 'No' and self.doc.c_form_no: + sql("""delete from `tabC-Form Invoice Detail` where invoice_no = %s + and parent = %s""", (self.doc.amended_from, self.doc.c_form_no)) + + set(self.doc, 'c_form_no', '') # VALIDATE # ==================================================================================== @@ -432,6 +440,7 @@ class DocType(TransactionBase): self.clear_advances() # Set against account self.set_against_income_account() + self.validate_c_form() # *************************************************** ON SUBMIT ********************************************** @@ -554,10 +563,21 @@ class DocType(TransactionBase): if not cint(self.doc.is_pos) == 1: self.update_against_document_in_jv() - + + self.update_c_form() + # on submit notification # get_obj('Notification Control').notify_contact('Sales Invoice', self.doc.doctype,self.doc.name, self.doc.email_id, self.doc.contact_person) - + + + def update_c_form(self): + """Update amended id in C-form""" + if self.doc.c_form_no and self.doc.amended_from: + sql("""update `tabC-Form Invoice Detail` set invoice_no = %s, + invoice_date = %s, territory = %s, net_total = %s, + grand_total = %s where invoice_no = %s and parent = %s""", (self.doc.name, self.doc.amended_from, self.doc.c_form_no)) + + # *************************************************** ON CANCEL ********************************************** # Check Next Document's docstatus diff --git a/erpnext/accounts/doctype/receivable_voucher/receivable_voucher.txt b/erpnext/accounts/doctype/receivable_voucher/receivable_voucher.txt index e2fc0c6416e..eedb01c5dd5 100644 --- a/erpnext/accounts/doctype/receivable_voucher/receivable_voucher.txt +++ b/erpnext/accounts/doctype/receivable_voucher/receivable_voucher.txt @@ -5,7 +5,7 @@ { 'creation': '2010-08-08 17:09:18', 'docstatus': 0, - 'modified': '2011-12-06 13:17:26', + 'modified': '2011-12-08 16:28:22', 'modified_by': 'Administrator', 'owner': 'Administrator' }, @@ -21,7 +21,7 @@ # These values are common for all DocType { - '_last_update': '1323156733', + '_last_update': '1323341785', 'change_log': '1. Change in pull_details method dt.-26-06-2009', 'colour': 'White:FFF', 'default_print_format': 'Standard', @@ -34,7 +34,7 @@ 'server_code_error': ' ', 'show_in_menu': 0, 'subject': 'To %(customer_name)s worth %(currency)s %(grand_total_export)s due on %(due_date)s | %(outstanding_amount)s outstanding', - 'version': 383 + 'version': 388 }, # These values are common for all DocFormat @@ -971,6 +971,31 @@ 'permlevel': 0 }, + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'c_form_applicable', + 'fieldtype': 'Select', + 'label': 'C-Form Applicable', + 'no_copy': 1, + 'options': 'No\nYes', + 'permlevel': 0, + 'print_hide': 1, + 'report_hide': 0 + }, + + # DocField + { + 'doctype': 'DocField', + 'fieldname': 'c_form_no', + 'fieldtype': 'Link', + 'label': 'C-Form No', + 'no_copy': 1, + 'options': 'C-Form', + 'permlevel': 1, + 'print_hide': 1 + }, + # DocField { 'doctype': 'DocField', From 2577e2ae275b7bfa687d60581741c39b8c067dae Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 8 Dec 2011 18:06:53 +0530 Subject: [PATCH 6/7] Patch for c-form --- erpnext/patches/c_form_patch.py | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 erpnext/patches/c_form_patch.py diff --git a/erpnext/patches/c_form_patch.py b/erpnext/patches/c_form_patch.py new file mode 100644 index 00000000000..41da19645b6 --- /dev/null +++ b/erpnext/patches/c_form_patch.py @@ -0,0 +1,11 @@ +def execute(): + import webnotes + from webnotes.modules.module_manager import reload_doc + + reload_doc('accounts', 'doctype', 'receivable_voucher') + reload_doc('accounts', 'doctype', 'c_form') + reload_doc('accounts', 'doctype', 'c_form_invoice_details') + + sql = webnotes.conn.sql + sql("update `tabReceivable Voucher` set c_form_applicable = 'Yes' where c_form_applicable = 'Y'") + sql("update `tabReceivable Voucher` set c_form_applicable = 'No' where c_form_applicable = 'N'") From 7e44f9789b1664fce2303626019f281ba4003f7a Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 8 Dec 2011 18:07:20 +0530 Subject: [PATCH 7/7] Patch for c-form --- erpnext/patches/c_form_patch.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/patches/c_form_patch.py b/erpnext/patches/c_form_patch.py index 41da19645b6..a55768d2b1f 100644 --- a/erpnext/patches/c_form_patch.py +++ b/erpnext/patches/c_form_patch.py @@ -5,6 +5,7 @@ def execute(): reload_doc('accounts', 'doctype', 'receivable_voucher') reload_doc('accounts', 'doctype', 'c_form') reload_doc('accounts', 'doctype', 'c_form_invoice_details') + reload_doc('accounts', 'Module Def', 'Accounts') sql = webnotes.conn.sql sql("update `tabReceivable Voucher` set c_form_applicable = 'Yes' where c_form_applicable = 'Y'")