Changes for Recurring PO/PI
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
index 49ed12c..680c6a0 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
@@ -232,6 +232,42 @@
}
}
+//added by sambhaji
+
+
+cur_frm.cscript.is_recurring = function(doc, dt, dn) {
+ // set default values for recurring invoices
+ if(doc.is_recurring) {
+ var owner_email = doc.owner=="Administrator"
+ ? frappe.user_info("Administrator").email
+ : doc.owner;
+
+ doc.notification_email_address = $.map([cstr(owner_email),
+ cstr(doc.contact_email)], function(v) { return v || null; }).join(", ");
+ doc.repeat_on_day_of_month = frappe.datetime.str_to_obj(doc.posting_date).getDate();
+ }
+
+ refresh_many(["notification_email_address", "repeat_on_day_of_month"]);
+}
+
+
+cur_frm.cscript.from_date = function(doc, dt, dn) {
+ // set to_date
+ if(doc.from_date) {
+ var recurring_type_map = {'Monthly': 1, 'Quarterly': 3, 'Half-yearly': 6,
+ 'Yearly': 12};
+
+ var months = recurring_type_map[doc.recurring_type];
+ if(months) {
+ var to_date = frappe.datetime.add_months(doc.from_date,
+ months);
+ doc.to_date = frappe.datetime.add_days(to_date, -1);
+ refresh_field('to_date');
+ }
+ }
+}
+
+//end of added by sambhajii
cur_frm.cscript.select_print_heading = function(doc,cdt,cdn){
if(doc.select_print_heading){
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
index 489bc46..dab029f 100755
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
@@ -1,4 +1,5 @@
{
+ "allow_attach": 1,
"allow_import": 1,
"autoname": "naming_series:",
"creation": "2013-05-21 16:16:39",
@@ -143,16 +144,34 @@
"search_index": 1
},
{
- "fieldname": "amended_from",
- "fieldtype": "Link",
- "ignore_user_permissions": 1,
- "label": "Amended From",
- "no_copy": 1,
- "oldfieldname": "amended_from",
- "oldfieldtype": "Link",
- "options": "Purchase Invoice",
- "permlevel": 0,
- "print_hide": 1,
+ "allow_on_submit": 1,
+ "description": "Start date of current invoice's period",
+ "fieldname": "from_date",
+ "fieldtype": "Date",
+ "label": "From",
+ "no_copy": 1,
+ "permlevel": 0
+ },
+ {
+ "allow_on_submit": 1,
+ "description": "End date of current invoice's period",
+ "fieldname": "to_date",
+ "fieldtype": "Date",
+ "label": "To",
+ "no_copy": 1,
+ "permlevel": 0
+ },
+ {
+ "fieldname": "amended_from",
+ "fieldtype": "Link",
+ "ignore_user_permissions": 1,
+ "label": "Amended From",
+ "no_copy": 1,
+ "oldfieldname": "amended_from",
+ "oldfieldtype": "Link",
+ "options": "Purchase Invoice",
+ "permlevel": 0,
+ "print_hide": 1,
"read_only": 1
},
{
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 956dacb..7d35f41 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -4,7 +4,10 @@
from __future__ import unicode_literals
import frappe
-from frappe.utils import cint, cstr, flt, formatdate
+
+from frappe.utils import add_days, cint, cstr, date_diff, formatdate, flt, getdate, nowdate, \
+ get_first_day, get_last_day
+from frappe.model.naming import make_autoname
from frappe import msgprint, _, throw
from erpnext.setup.utils import get_company_currency
@@ -14,6 +17,8 @@
from erpnext.controllers.buying_controller import BuyingController
from erpnext.accounts.party import get_party_account, get_due_date
+from erpnext.controllers.recurring_document import *
+
form_grid_templates = {
"entries": "templates/form_grid/item_grid.html"
}
@@ -61,6 +66,7 @@
self.validate_multiple_billing("Purchase Receipt", "pr_detail", "amount",
"purchase_receipt_details")
self.create_remarks()
+ validate_recurring_document(self)
def create_remarks(self):
if not self.remarks:
@@ -259,6 +265,11 @@
self.update_against_document_in_jv()
self.update_prevdoc_status()
self.update_billing_status_for_zero_amount_refdoc("Purchase Order")
+ convert_to_recurring(self, "RECINV.#####", self.posting_date)
+
+ def on_update_after_submit(self):
+ validate_recurring_document(self)
+ convert_to_recurring(self, "RECINV.#####", self.posting_date)
def make_gl_entries(self):
auto_accounting_for_stock = \
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js
index 9433ebe..071d622 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.js
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.js
@@ -205,7 +205,40 @@
cur_frm.email_doc(frappe.boot.notification_settings.purchase_order_message);
}
}
+//added by sambhaji
+cur_frm.cscript.is_recurring = function(doc, dt, dn) {
+ // set default values for recurring orders
+ if(doc.is_recurring) {
+ var owner_email = doc.owner=="Administrator"
+ ? frappe.user_info("Administrator").email
+ : doc.owner;
+
+ doc.notification_email_address = $.map([cstr(owner_email),
+ cstr(doc.contact_email)], function(v) { return v || null; }).join(", ");
+ doc.repeat_on_day_of_month = frappe.datetime.str_to_obj(doc.posting_date).getDate();
+ }
+
+ refresh_many(["notification_email_address", "repeat_on_day_of_month"]);
+}
+
+cur_frm.cscript.from_date = function(doc, dt, dn) {
+ // set to_date
+ if(doc.from_date) {
+ var recurring_type_map = {'Monthly': 1, 'Quarterly': 3, 'Half-yearly': 6,
+ 'Yearly': 12};
+
+ var months = recurring_type_map[doc.recurring_type];
+ if(months) {
+ var to_date = frappe.datetime.add_months(doc.from_date,
+ months);
+ doc.to_date = frappe.datetime.add_days(to_date, -1);
+ refresh_field('to_date');
+ }
+ }
+}
+
+//end of added by sambhaji
cur_frm.cscript.send_sms = function() {
frappe.require("assets/erpnext/js/sms_manager.js");
var sms_man = new SMSManager(cur_frm.doc);
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json
index 647823c..289567f 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.json
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.json
@@ -1,4 +1,5 @@
{
+ "allow_attach": 1,
"allow_import": 1,
"autoname": "naming_series:",
"creation": "2013-05-21 16:16:39",
@@ -102,6 +103,24 @@
"search_index": 1
},
{
+ "allow_on_submit": 1,
+ "description": "Start date of current order's period",
+ "fieldname": "from_date",
+ "fieldtype": "Date",
+ "label": "From",
+ "no_copy": 1,
+ "permlevel": 0
+ },
+ {
+ "allow_on_submit": 1,
+ "description": "End date of current order's period",
+ "fieldname": "to_date",
+ "fieldtype": "Date",
+ "label": "To",
+ "no_copy": 1,
+ "permlevel": 0
+ },
+ {
"fieldname": "amended_from",
"fieldtype": "Link",
"hidden": 0,
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py
index 6c7c0c6..beebf0b 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.py
@@ -6,6 +6,9 @@
from frappe.utils import cstr, flt
from frappe import msgprint, _, throw
from frappe.model.mapper import get_mapped_doc
+
+from erpnext.controllers.recurring_document import convert_to_recurring, validate_recurring_document
+
from erpnext.controllers.buying_controller import BuyingController
form_grid_templates = {
@@ -52,6 +55,8 @@
self.validate_for_subcontracting()
self.validate_minimum_order_qty()
self.create_raw_materials_supplied("po_raw_material_details")
+
+ validate_recurring_document(self)
def validate_with_previous_doc(self):
super(PurchaseOrder, self).validate_with_previous_doc(self.tname, {
@@ -173,6 +178,8 @@
purchase_controller.update_last_purchase_rate(self, is_submit = 1)
frappe.db.set(self,'status','Submitted')
+
+ convert_to_recurring(self, "SO/REC/.#####", self.transaction_date)
def on_cancel(self):
pc_obj = frappe.get_doc('Purchase Common')
@@ -197,6 +204,10 @@
def on_update(self):
pass
+def on_update_after_submit(self):
+ validate_recurring_document(self)
+ convert_to_recurring(self, "SO/REC/.#####", self.transaction_date)
+
def set_missing_values(source, target):
target.ignore_pricing_rule = 1
target.run_method("set_missing_values")
diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py
index d1d183a..0c9f912 100644
--- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py
+++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py
@@ -107,6 +107,11 @@
po.get("po_details")[0].qty = 3.4
self.assertRaises(UOMMustBeIntegerError, po.insert)
+ def test_recurring_order(self):
+ from erpnext.controllers.tests.test_recurring_document import test_recurring_document
+
+ test_recurring_document(self, test_records)
+
test_dependencies = ["BOM"]
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index 5f418c4..a3f5908 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -4,7 +4,11 @@
from __future__ import unicode_literals
import frappe
from frappe import _, msgprint
-from frappe.utils import flt, rounded
+
+from frappe.utils import add_days, cint, cstr, today, date_diff, flt, rounded, getdate, nowdate, \
+ get_first_day, get_last_day
+from frappe.model.naming import make_autoname
+
from erpnext.setup.utils import get_company_currency
from erpnext.accounts.party import get_party_details