Add tests for Recurring Document, Sales Inv, Sales Order, fix minor errors

This commit is contained in:
ankitjavalkarwork
2014-08-26 14:29:06 +05:30
parent ac085e0f59
commit e60822b094
6 changed files with 326 additions and 139 deletions

View File

@@ -665,143 +665,148 @@ class TestSalesInvoice(unittest.TestCase):
where against_invoice=%s""", si.name)) where against_invoice=%s""", si.name))
def test_recurring_invoice(self): def test_recurring_invoice(self):
from frappe.utils import get_first_day, get_last_day, add_to_date, nowdate, getdate from erpnext.controllers.tests.test_recurring_document import test_recurring_document
from erpnext.accounts.utils import get_fiscal_year
today = nowdate()
base_si = frappe.copy_doc(test_records[0])
base_si.update({
"convert_into_recurring_invoice": 1,
"recurring_type": "Monthly",
"notification_email_address": "test@example.com, test1@example.com, test2@example.com",
"repeat_on_day_of_month": getdate(today).day,
"posting_date": today,
"due_date": None,
"fiscal_year": get_fiscal_year(today)[0],
"period_from": get_first_day(today),
"period_to": get_last_day(today)
})
# monthly test_recurring_document(self, test_records)
si1 = frappe.copy_doc(base_si)
si1.insert()
si1.submit()
self._test_recurring_invoice(si1, True)
# monthly without a first and last day period # def test_recurring_invoice(self):
si2 = frappe.copy_doc(base_si) # from frappe.utils import get_first_day, get_last_day, add_to_date, nowdate, getdate
si2.update({ # from erpnext.accounts.utils import get_fiscal_year
"period_from": today, # today = nowdate()
"period_to": add_to_date(today, days=30) # base_si = frappe.copy_doc(test_records[0])
}) # base_si.update({
si2.insert() # "convert_into_recurring_invoice": 1,
si2.submit() # "recurring_type": "Monthly",
self._test_recurring_invoice(si2, False) # "notification_email_address": "test@example.com, test1@example.com, test2@example.com",
# "repeat_on_day_of_month": getdate(today).day,
# "posting_date": today,
# "due_date": None,
# "fiscal_year": get_fiscal_year(today)[0],
# "period_from": get_first_day(today),
# "period_to": get_last_day(today)
# })
# quarterly # # monthly
si3 = frappe.copy_doc(base_si) # si1 = frappe.copy_doc(base_si)
si3.update({ # si1.insert()
"recurring_type": "Quarterly", # si1.submit()
"period_from": get_first_day(today), # self._test_recurring_invoice(si1, True)
"period_to": get_last_day(add_to_date(today, months=3))
})
si3.insert()
si3.submit()
self._test_recurring_invoice(si3, True)
# quarterly without a first and last day period # # monthly without a first and last day period
si4 = frappe.copy_doc(base_si) # si2 = frappe.copy_doc(base_si)
si4.update({ # si2.update({
"recurring_type": "Quarterly", # "period_from": today,
"period_from": today, # "period_to": add_to_date(today, days=30)
"period_to": add_to_date(today, months=3) # })
}) # si2.insert()
si4.insert() # si2.submit()
si4.submit() # self._test_recurring_invoice(si2, False)
self._test_recurring_invoice(si4, False)
# yearly # # quarterly
si5 = frappe.copy_doc(base_si) # si3 = frappe.copy_doc(base_si)
si5.update({ # si3.update({
"recurring_type": "Yearly", # "recurring_type": "Quarterly",
"period_from": get_first_day(today), # "period_from": get_first_day(today),
"period_to": get_last_day(add_to_date(today, years=1)) # "period_to": get_last_day(add_to_date(today, months=3))
}) # })
si5.insert() # si3.insert()
si5.submit() # si3.submit()
self._test_recurring_invoice(si5, True) # self._test_recurring_invoice(si3, True)
# yearly without a first and last day period # # quarterly without a first and last day period
si6 = frappe.copy_doc(base_si) # si4 = frappe.copy_doc(base_si)
si6.update({ # si4.update({
"recurring_type": "Yearly", # "recurring_type": "Quarterly",
"period_from": today, # "period_from": today,
"period_to": add_to_date(today, years=1) # "period_to": add_to_date(today, months=3)
}) # })
si6.insert() # si4.insert()
si6.submit() # si4.submit()
self._test_recurring_invoice(si6, False) # self._test_recurring_invoice(si4, False)
# change posting date but keep recuring day to be today # # yearly
si7 = frappe.copy_doc(base_si) # si5 = frappe.copy_doc(base_si)
si7.update({ # si5.update({
"posting_date": add_to_date(today, days=-1) # "recurring_type": "Yearly",
}) # "period_from": get_first_day(today),
si7.insert() # "period_to": get_last_day(add_to_date(today, years=1))
si7.submit() # })
# si5.insert()
# si5.submit()
# self._test_recurring_invoice(si5, True)
# setting so that _test function works # # yearly without a first and last day period
si7.posting_date = today # si6 = frappe.copy_doc(base_si)
self._test_recurring_invoice(si7, True) # si6.update({
# "recurring_type": "Yearly",
# "period_from": today,
# "period_to": add_to_date(today, years=1)
# })
# si6.insert()
# si6.submit()
# self._test_recurring_invoice(si6, False)
def _test_recurring_invoice(self, base_si, first_and_last_day): # # change posting date but keep recuring day to be today
from frappe.utils import add_months, get_last_day # si7 = frappe.copy_doc(base_si)
from erpnext.accounts.doctype.sales_invoice.sales_invoice \ # si7.update({
import manage_recurring_invoices, get_next_date # "posting_date": add_to_date(today, days=-1)
# })
# si7.insert()
# si7.submit()
no_of_months = ({"Monthly": 1, "Quarterly": 3, "Yearly": 12})[base_si.recurring_type] # # setting so that _test function works
# si7.posting_date = today
# self._test_recurring_invoice(si7, True)
def _test(i): # def _test_recurring_invoice(self, base_si, first_and_last_day):
self.assertEquals(i+1, frappe.db.sql("""select count(*) from `tabSales Invoice` # from frappe.utils import add_months, get_last_day
where recurring_id=%s and docstatus=1""", base_si.recurring_id)[0][0]) # from erpnext.accounts.doctype.sales_invoice.sales_invoice \
# import manage_recurring_invoices, get_next_date
next_date = get_next_date(base_si.posting_date, no_of_months, # no_of_months = ({"Monthly": 1, "Quarterly": 3, "Yearly": 12})[base_si.recurring_type]
base_si.repeat_on_day_of_month)
manage_recurring_invoices(next_date=next_date, commit=False) # def _test(i):
# self.assertEquals(i+1, frappe.db.sql("""select count(*) from `tabSales Invoice`
# where recurring_id=%s and docstatus=1""", base_si.recurring_id)[0][0])
recurred_invoices = frappe.db.sql("""select name from `tabSales Invoice` # next_date = get_next_date(base_si.posting_date, no_of_months,
where recurring_id=%s and docstatus=1 order by name desc""", # base_si.repeat_on_day_of_month)
base_si.recurring_id)
self.assertEquals(i+2, len(recurred_invoices)) # manage_recurring_invoices(next_date=next_date, commit=False)
new_si = frappe.get_doc("Sales Invoice", recurred_invoices[0][0]) # recurred_invoices = frappe.db.sql("""select name from `tabSales Invoice`
# where recurring_id=%s and docstatus=1 order by name desc""",
# base_si.recurring_id)
for fieldname in ["convert_into_recurring_invoice", "recurring_type", # self.assertEquals(i+2, len(recurred_invoices))
"repeat_on_day_of_month", "notification_email_address"]:
self.assertEquals(base_si.get(fieldname),
new_si.get(fieldname))
self.assertEquals(new_si.posting_date, unicode(next_date)) # new_si = frappe.get_doc("Sales Invoice", recurred_invoices[0][0])
self.assertEquals(new_si.period_from, # for fieldname in ["convert_into_recurring_invoice", "recurring_type",
unicode(add_months(base_si.period_from, no_of_months))) # "repeat_on_day_of_month", "notification_email_address"]:
# self.assertEquals(base_si.get(fieldname),
# new_si.get(fieldname))
if first_and_last_day: # self.assertEquals(new_si.posting_date, unicode(next_date))
self.assertEquals(new_si.period_to,
unicode(get_last_day(add_months(base_si.period_to, # self.assertEquals(new_si.period_from,
no_of_months)))) # unicode(add_months(base_si.period_from, no_of_months)))
else:
self.assertEquals(new_si.period_to, # if first_and_last_day:
unicode(add_months(base_si.period_to, no_of_months))) # self.assertEquals(new_si.period_to,
# unicode(get_last_day(add_months(base_si.period_to,
# no_of_months))))
# else:
# self.assertEquals(new_si.period_to,
# unicode(add_months(base_si.period_to, no_of_months)))
return new_si # return new_si
# if yearly, test 1 repetition, else test 5 repetitions # # if yearly, test 1 repetition, else test 5 repetitions
count = 1 if (no_of_months == 12) else 5 # count = 1 if (no_of_months == 12) else 5
for i in xrange(count): # for i in xrange(count):
base_si = _test(i) # base_si = _test(i)
def clear_stock_account_balance(self): def clear_stock_account_balance(self):
frappe.db.sql("delete from `tabStock Ledger Entry`") frappe.db.sql("delete from `tabStock Ledger Entry`")

View File

@@ -4,7 +4,9 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import frappe import frappe
from frappe import _, throw from frappe import _, throw
from frappe.utils import flt, cint, today from frappe.utils import add_days, cint, cstr, today, date_diff, flt, getdate, nowdate, \
get_first_day, get_last_day
from frappe.model.naming import make_autoname
from erpnext.setup.utils import get_company_currency, get_exchange_rate from erpnext.setup.utils import get_company_currency, get_exchange_rate
from erpnext.accounts.utils import get_fiscal_year, validate_fiscal_year from erpnext.accounts.utils import get_fiscal_year, validate_fiscal_year
from erpnext.utilities.transaction_base import TransactionBase from erpnext.utilities.transaction_base import TransactionBase
@@ -428,22 +430,6 @@ class AccountsController(TransactionBase):
return stock_items return stock_items
@property
def company_abbr(self):
if not hasattr(self, "_abbr"):
self._abbr = frappe.db.get_value("Company", self.company, "abbr")
return self._abbr
def check_credit_limit(self, account):
total_outstanding = frappe.db.sql("""
select sum(ifnull(debit, 0)) - sum(ifnull(credit, 0))
from `tabGL Entry` where account = %s""", account)
total_outstanding = total_outstanding[0][0] if total_outstanding else 0
if total_outstanding:
frappe.get_doc('Account', account).check_credit_limit(total_outstanding)
def validate_recurring_document(self): def validate_recurring_document(self):
if self.convert_into_recurring: if self.convert_into_recurring:
self.validate_notification_email_id() self.validate_notification_email_id()
@@ -468,6 +454,22 @@ class AccountsController(TransactionBase):
set convert_into_recurring = 0 set convert_into_recurring = 0
where recurring_id = %s""" % (self.doctype, '%s'), (self.recurring_id)) where recurring_id = %s""" % (self.doctype, '%s'), (self.recurring_id))
@property
def company_abbr(self):
if not hasattr(self, "_abbr"):
self._abbr = frappe.db.get_value("Company", self.company, "abbr")
return self._abbr
def check_credit_limit(self, account):
total_outstanding = frappe.db.sql("""
select sum(ifnull(debit, 0)) - sum(ifnull(credit, 0))
from `tabGL Entry` where account = %s""", account)
total_outstanding = total_outstanding[0][0] if total_outstanding else 0
if total_outstanding:
frappe.get_doc('Account', account).check_credit_limit(total_outstanding)
def validate_notification_email_id(self): def validate_notification_email_id(self):
if self.notification_email_address: if self.notification_email_address:
email_list = filter(None, [cstr(email).strip() for email in email_list = filter(None, [cstr(email).strip() for email in
@@ -487,6 +489,8 @@ class AccountsController(TransactionBase):
""" Set next date on which recurring document will be created""" """ Set next date on which recurring document will be created"""
from erpnext.controllers.recurring_document import get_next_date from erpnext.controllers.recurring_document import get_next_date
month_map = {'Monthly': 1, 'Quarterly': 3, 'Half-yearly': 6, 'Yearly': 12}
if not self.repeat_on_day_of_month: if not self.repeat_on_day_of_month:
msgprint(_("Please enter 'Repeat on Day of Month' field value"), raise_exception=1) msgprint(_("Please enter 'Repeat on Day of Month' field value"), raise_exception=1)

View File

@@ -11,25 +11,33 @@ from frappe import _, msgprint, throw
from erpnext.accounts.party import get_party_account, get_due_date, get_party_details from erpnext.accounts.party import get_party_account, get_due_date, get_party_details
from frappe.model.mapper import get_mapped_doc from frappe.model.mapper import get_mapped_doc
month_map = {'Monthly': 1, 'Quarterly': 3, 'Half-yearly': 6, 'Yearly': 12}
def manage_recurring_documents(doctype, next_date=None, commit=True): def manage_recurring_documents(doctype, next_date=None, commit=True):
""" """
Create recurring documents on specific date by copying the original one Create recurring documents on specific date by copying the original one
and notify the concerned people and notify the concerned people
""" """
next_date = next_date or nowdate() next_date = next_date or nowdate()
if doctype == "Sales Order":
date_field = "transaction_date"
elif doctype == "Sales Invoice":
date_field = "posting_date"
recurring_documents = frappe.db.sql("""select name, recurring_id recurring_documents = frappe.db.sql("""select name, recurring_id
from `tab%s` where ifnull(convert_into_recurring, 0)=1 from `tab%s` where ifnull(convert_into_recurring, 0)=1
and docstatus=1 and next_date=%s and docstatus=1 and next_date=%s
and next_date <= ifnull(end_date, '2199-12-31')""", % (doctype, '%s'), (next_date)) and next_date <= ifnull(end_date, '2199-12-31')""" % (doctype, '%s'), (next_date))
exception_list = [] exception_list = []
for ref_document, recurring_id in recurring_documents: for ref_document, recurring_id in recurring_documents:
if not frappe.db.sql("""select name from `tab%s` if not frappe.db.sql("""select name from `tab%s`
where transaction_date=%s and recurring_id=%s and docstatus=1""", where %s=%s and recurring_id=%s and docstatus=1"""
% (doctype, '%s', '%s'), (next_date, recurring_id)): % (doctype, date_field, '%s', '%s'), (next_date, recurring_id)):
try: try:
ref_wrapper = frappe.get_doc(doctype, ref_document) ref_wrapper = frappe.get_doc(doctype, ref_document)
new_document_wrapper = make_new_document(ref_wrapper, next_date) new_document_wrapper = make_new_document(ref_wrapper, date_field, next_date)
send_notification(new_document_wrapper) send_notification(new_document_wrapper)
if commit: if commit:
frappe.db.commit() frappe.db.commit()
@@ -39,7 +47,7 @@ def manage_recurring_documents(doctype, next_date=None, commit=True):
frappe.db.begin() frappe.db.begin()
frappe.db.sql("update `tab%s` \ frappe.db.sql("update `tab%s` \
set convert_into_recurring = 0 where name = %s", % (doctype, '%s'), set convert_into_recurring = 0 where name = %s" % (doctype, '%s'),
(ref_document)) (ref_document))
notify_errors(ref_document, doctype, ref_wrapper.customer, ref_wrapper.owner) notify_errors(ref_document, doctype, ref_wrapper.customer, ref_wrapper.owner)
frappe.db.commit() frappe.db.commit()
@@ -53,10 +61,9 @@ def manage_recurring_documents(doctype, next_date=None, commit=True):
exception_message = "\n\n".join([cstr(d) for d in exception_list]) exception_message = "\n\n".join([cstr(d) for d in exception_list])
frappe.throw(exception_message) frappe.throw(exception_message)
def make_new_document(ref_wrapper, posting_date): def make_new_document(ref_wrapper, date_field, posting_date):
from erpnext.accounts.utils import get_fiscal_year from erpnext.accounts.utils import get_fiscal_year
new_document = frappe.copy_doc(ref_wrapper) new_document = frappe.copy_doc(ref_wrapper)
mcount = month_map[ref_wrapper.recurring_type] mcount = month_map[ref_wrapper.recurring_type]
period_from = get_next_date(ref_wrapper.period_from, mcount) period_from = get_next_date(ref_wrapper.period_from, mcount)
@@ -73,7 +80,7 @@ def make_new_document(ref_wrapper, posting_date):
period_to = get_next_date(ref_wrapper.period_to, mcount) period_to = get_next_date(ref_wrapper.period_to, mcount)
new_document.update({ new_document.update({
"transaction_date": posting_date, date_field: posting_date,
"period_from": period_from, "period_from": period_from,
"period_to": period_to, "period_to": period_to,
"fiscal_year": get_fiscal_year(posting_date)[0], "fiscal_year": get_fiscal_year(posting_date)[0],

View File

@@ -0,0 +1 @@
from erpnext.__version__ import __version__

View File

@@ -0,0 +1,165 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
import frappe
import unittest, json, copy
from frappe.utils import flt
import frappe.permissions
from erpnext.accounts.utils import get_stock_and_account_difference
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
from erpnext.projects.doctype.time_log_batch.test_time_log_batch import *
def test_recurring_document(obj, test_records):
from frappe.utils import get_first_day, get_last_day, add_to_date, nowdate, getdate, add_days
from erpnext.accounts.utils import get_fiscal_year
today = nowdate()
base_doc = frappe.copy_doc(test_records[0])
base_doc.update({
"convert_into_recurring": 1,
"recurring_type": "Monthly",
"notification_email_address": "test@example.com, test1@example.com, test2@example.com",
"repeat_on_day_of_month": getdate(today).day,
"due_date": None,
"fiscal_year": get_fiscal_year(today)[0],
"period_from": get_first_day(today),
"period_to": get_last_day(today)
})
if base_doc.doctype == "Sales Order":
base_doc.update({
"transaction_date": today,
"delivery_date": add_days(today, 15)
})
elif base_doc.doctype == "Sales Invoice":
base_doc.update({
"posting_date": today
})
if base_doc.doctype == "Sales Order":
date_field = "transaction_date"
elif base_doc.doctype == "Sales Invoice":
date_field = "posting_date"
# monthly
doc1 = frappe.copy_doc(base_doc)
doc1.insert()
doc1.submit()
_test_recurring_document(obj, doc1, date_field, True)
# monthly without a first and last day period
doc2 = frappe.copy_doc(base_doc)
doc2.update({
"period_from": today,
"period_to": add_to_date(today, days=30)
})
doc2.insert()
doc2.submit()
_test_recurring_document(obj, doc2, date_field, False)
# quarterly
doc3 = frappe.copy_doc(base_doc)
doc3.update({
"recurring_type": "Quarterly",
"period_from": get_first_day(today),
"period_to": get_last_day(add_to_date(today, months=3))
})
doc3.insert()
doc3.submit()
_test_recurring_document(obj, doc3, date_field, True)
# quarterly without a first and last day period
doc4 = frappe.copy_doc(base_doc)
doc4.update({
"recurring_type": "Quarterly",
"period_from": today,
"period_to": add_to_date(today, months=3)
})
doc4.insert()
doc4.submit()
_test_recurring_document(obj, doc4, date_field, False)
# yearly
doc5 = frappe.copy_doc(base_doc)
doc5.update({
"recurring_type": "Yearly",
"period_from": get_first_day(today),
"period_to": get_last_day(add_to_date(today, years=1))
})
doc5.insert()
doc5.submit()
_test_recurring_document(obj, doc5, date_field, True)
# yearly without a first and last day period
doc6 = frappe.copy_doc(base_doc)
doc6.update({
"recurring_type": "Yearly",
"period_from": today,
"period_to": add_to_date(today, years=1)
})
doc6.insert()
doc6.submit()
_test_recurring_document(obj, doc6, date_field, False)
# change date field but keep recurring day to be today
doc7 = frappe.copy_doc(base_doc)
doc7.update({
date_field: add_to_date(today, days=-1)
})
doc7.insert()
doc7.submit()
# setting so that _test function works
doc7.set(date_field, today)
_test_recurring_document(obj, doc7, date_field, True)
def _test_recurring_document(obj, base_doc, date_field, first_and_last_day):
from frappe.utils import add_months, get_last_day
from erpnext.controllers.recurring_document import manage_recurring_documents, \
get_next_date
no_of_months = ({"Monthly": 1, "Quarterly": 3, "Yearly": 12})[base_doc.recurring_type]
def _test(i):
obj.assertEquals(i+1, frappe.db.sql("""select count(*) from `tab%s`
where recurring_id=%s and docstatus=1""" % (base_doc.doctype, '%s'),
(base_doc.recurring_id))[0][0])
next_date = get_next_date(base_doc.get(date_field), no_of_months,
base_doc.repeat_on_day_of_month)
manage_recurring_documents(base_doc.doctype, next_date=next_date, commit=False)
recurred_documents = frappe.db.sql("""select name from `tab%s`
where recurring_id=%s and docstatus=1 order by name desc"""
% (base_doc.doctype, '%s'), (base_doc.recurring_id))
obj.assertEquals(i+2, len(recurred_documents))
new_doc = frappe.get_doc(base_doc.doctype, recurred_documents[0][0])
for fieldname in ["convert_into_recurring", "recurring_type",
"repeat_on_day_of_month", "notification_email_address"]:
obj.assertEquals(base_doc.get(fieldname),
new_doc.get(fieldname))
obj.assertEquals(new_doc.get(date_field), unicode(next_date))
obj.assertEquals(new_doc.period_from,
unicode(add_months(base_doc.period_from, no_of_months)))
if first_and_last_day:
obj.assertEquals(new_doc.period_to,
unicode(get_last_day(add_months(base_doc.period_to,
no_of_months))))
else:
obj.assertEquals(new_doc.period_to,
unicode(add_months(base_doc.period_to, no_of_months)))
return new_doc
# if yearly, test 1 repetition, else test 5 repetitions
count = 1 if (no_of_months == 12) else 5
for i in xrange(count):
base_doc = _test(i)

View File

@@ -331,6 +331,11 @@ class TestSalesOrder(unittest.TestCase):
self.assertRaises(frappe.CancelledLinkError, delivery_note.submit) self.assertRaises(frappe.CancelledLinkError, delivery_note.submit)
def test_recurring_order(self):
from erpnext.controllers.tests.test_recurring_document import test_recurring_document
test_recurring_document(self, test_records)
test_dependencies = ["Sales BOM", "Currency Exchange"] test_dependencies = ["Sales BOM", "Currency Exchange"]
test_records = frappe.get_test_records('Sales Order') test_records = frappe.get_test_records('Sales Order')