Merge pull request #14205 from Alchez/frappe-contract

[Feature] Managing Contracts in ERPNext
This commit is contained in:
Shreya Shah 2018-06-14 17:57:02 +05:30 committed by GitHub
commit 02575d1f2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 2031 additions and 1 deletions

View File

View File

@ -0,0 +1,24 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
cur_frm.add_fetch("contract_template", "contract_terms", "contract_terms");
cur_frm.add_fetch("contract_template", "requires_fulfilment", "requires_fulfilment");
// Add fulfilment terms from contract template into contract
frappe.ui.form.on("Contract", {
contract_template: function (frm) {
// Populate the fulfilment terms table from a contract template, if any
if (frm.doc.contract_template) {
frappe.model.with_doc("Contract Template", frm.doc.contract_template, function () {
var tabletransfer = frappe.model.get_doc("Contract Template", frm.doc.contract_template);
frm.doc.fulfilment_terms = [];
$.each(tabletransfer.fulfilment_terms, function (index, row) {
var d = frm.add_child("fulfilment_terms");
d.requirement = row.requirement;
frm.refresh_field("fulfilment_terms");
});
});
}
}
});

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,109 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.model.document import Document
from frappe.utils import getdate, now_datetime, nowdate
class Contract(Document):
def autoname(self):
name = self.party_name
if self.contract_template:
name += " - {} Agreement".format(self.contract_template)
# If identical, append contract name with the next number in the iteration
if frappe.db.exists("Contract", name):
count = len(frappe.get_all("Contract", filters={"name": ["like", "%{}%".format(name)]}))
name = "{} - {}".format(name, count)
self.name = _(name)
def validate(self):
self.validate_dates()
self.update_contract_status()
self.update_fulfilment_status()
def before_update_after_submit(self):
self.update_contract_status()
self.update_fulfilment_status()
def validate_dates(self):
if self.end_date and self.end_date < self.start_date:
frappe.throw(_("End Date cannot be before Start Date."))
def update_contract_status(self):
if self.is_signed:
self.status = get_status(self.start_date, self.end_date)
else:
self.status = "Unsigned"
def update_fulfilment_status(self):
fulfilment_status = "N/A"
if self.requires_fulfilment:
fulfilment_progress = self.get_fulfilment_progress()
if not fulfilment_progress:
fulfilment_status = "Unfulfilled"
elif fulfilment_progress < len(self.fulfilment_terms):
fulfilment_status = "Partially Fulfilled"
elif fulfilment_progress == len(self.fulfilment_terms):
fulfilment_status = "Fulfilled"
if fulfilment_status != "Fulfilled" and self.fulfilment_deadline:
now_date = getdate(nowdate())
deadline_date = getdate(self.fulfilment_deadline)
if now_date > deadline_date:
fulfilment_status = "Lapsed"
self.fulfilment_status = fulfilment_status
def get_fulfilment_progress(self):
return len([term for term in self.fulfilment_terms if term.fulfilled])
def get_status(start_date, end_date):
"""
Get a Contract's status based on the start, current and end dates
Args:
start_date (str): The start date of the contract
end_date (str): The end date of the contract
Returns:
str: 'Active' if within range, otherwise 'Inactive'
"""
if not end_date:
return "Active"
start_date = getdate(start_date)
end_date = getdate(end_date)
now_date = getdate(nowdate())
return "Active" if start_date < now_date < end_date else "Inactive"
def update_status_for_contracts():
"""
Run the daily hook to update the statuses for all signed
and submitted Contracts
"""
contracts = frappe.get_all("Contract",
filters={"is_signed": True,
"docstatus": 1},
fields=["name", "start_date", "end_date"])
for contract in contracts:
status = get_status(contract.get("start_date"),
contract.get("end_date"))
frappe.db.set_value("Contract", contract.get("name"), "status", status)

View File

@ -0,0 +1,12 @@
frappe.listview_settings['Contract'] = {
add_fields: ["status"],
get_indicator: function (doc) {
if (doc.status == "Unsigned") {
return [__(doc.status), "red", "status,=," + doc.status];
} else if (doc.status == "Active") {
return [__(doc.status), "green", "status,=," + doc.status];
} else if (doc.status == "Inactive") {
return [__(doc.status), "darkgrey", "status,=," + doc.status];
}
},
};

View File

@ -0,0 +1,23 @@
/* eslint-disable */
// rename this file from _test_[name] to test_[name] to activate
// and remove above this line
QUnit.test("test: Contract", function (assert) {
let done = assert.async();
// number of asserts
assert.expect(1);
frappe.run_serially([
// insert a new Contract
() => frappe.tests.make('Contract', [
// values to be set
{key: 'value'}
]),
() => {
assert.equal(cur_frm.doc.key, 'value');
},
() => done()
]);
});

View File

@ -0,0 +1,119 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
from __future__ import unicode_literals
import unittest
import frappe
from frappe.utils import add_days, nowdate
class TestContract(unittest.TestCase):
def setUp(self):
frappe.db.sql("delete from `tabContract`")
self.contract_doc = get_contract()
def test_validate_start_date_before_end_date(self):
self.contract_doc.start_date = nowdate()
self.contract_doc.end_date = add_days(nowdate(), -1)
self.assertRaises(frappe.ValidationError, self.contract_doc.insert)
def test_unsigned_contract_status(self):
self.contract_doc.insert()
self.assertEqual(self.contract_doc.status, "Unsigned")
def test_active_signed_contract_status(self):
self.contract_doc.is_signed = True
self.contract_doc.start_date = add_days(nowdate(), -1)
self.contract_doc.end_date = add_days(nowdate(), 1)
self.contract_doc.insert()
self.assertEqual(self.contract_doc.status, "Active")
def test_past_inactive_signed_contract_status(self):
self.contract_doc.is_signed = True
self.contract_doc.start_date = add_days(nowdate(), -2)
self.contract_doc.end_date = add_days(nowdate(), -1)
self.contract_doc.insert()
self.assertEqual(self.contract_doc.status, "Inactive")
def test_future_inactive_signed_contract_status(self):
self.contract_doc.is_signed = True
self.contract_doc.start_date = add_days(nowdate(), 1)
self.contract_doc.end_date = add_days(nowdate(), 2)
self.contract_doc.insert()
self.assertEqual(self.contract_doc.status, "Inactive")
def test_contract_status_with_no_fulfilment_terms(self):
self.contract_doc.contract_term = "_Test Customer Contract"
self.contract_doc.insert()
self.assertEqual(self.contract_doc.fulfilment_status, "N/A")
def test_unfulfilled_contract_status(self):
self.contract_doc.contract_term = "_Test Customer Contract with Requirements"
self.contract_doc.requires_fulfilment = 1
self.contract_doc.save()
self.assertEqual(self.contract_doc.fulfilment_status, "Unfulfilled")
def test_fulfilled_contract_status(self):
self.contract_doc.contract_terms = "_Test Customer Contract with Requirements"
# Mark all the terms as fulfilled
self.contract_doc.requires_fulfilment = 1
fulfilment_terms = []
fulfilment_terms.append({
"requirement": "This is a test requirement.",
"fulfilled": 0
})
self.contract_doc.set("fulfilment_terms", fulfilment_terms)
for term in self.contract_doc.fulfilment_terms:
term.fulfilled = 1
self.contract_doc.save()
self.assertEqual(self.contract_doc.fulfilment_status, "Fulfilled")
def test_partially_fulfilled_contract_status(self):
self.contract_doc.contract_terms = "_Test Customer Contract with Requirements"
self.contract_doc.requires_fulfilment = 1
# Mark only the first term as fulfilled
self.contract_doc.save()
fulfilment_terms = []
fulfilment_terms.append({
"requirement": "This is a test requirement.",
"fulfilled": 0
})
fulfilment_terms.append({
"requirement": "This is another test requirement.",
"fulfilled": 0
})
self.contract_doc.set("fulfilment_terms", fulfilment_terms)
self.contract_doc.fulfilment_terms[0].fulfilled = 1
self.contract_doc.save()
self.assertEqual(self.contract_doc.fulfilment_status, "Partially Fulfilled")
def test_lapsed_contract_status(self):
self.contract_doc.contract_term = "_Test Customer Contract with Requirements"
self.contract_doc.start_date = add_days(nowdate(), -2)
self.contract_doc.end_date = add_days(nowdate(), 1)
self.contract_doc.requires_fulfilment = 1
self.contract_doc.fulfilment_deadline = add_days(nowdate(), -1)
self.contract_doc.save()
self.assertEqual(self.contract_doc.fulfilment_status, "Lapsed")
def get_contract():
doc = frappe.new_doc("Contract")
doc.party_type = "Customer"
doc.party_name = "_Test Customer"
doc.contract_terms = "This is a test customer contract."
return doc

View File

@ -0,0 +1,8 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Contract Fulfilment Checklist', {
refresh: function(frm) {
}
});

View File

@ -0,0 +1,219 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2018-04-16 06:51:33.320037",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "fulfilled",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Fulfilled",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "cb_notes",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "requirement",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Requirement",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "sb_notes",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "notes",
"fieldtype": "Text",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Notes",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "amended_from",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Amended From",
"length": 0,
"no_copy": 1,
"options": "Contract Fulfilment Checklist",
"permlevel": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 1,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2018-04-16 08:27:25.156332",
"modified_by": "Administrator",
"module": "CRM",
"name": "Contract Fulfilment Checklist",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0
}

View File

@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
class ContractFulfilmentChecklist(Document):
pass

View File

@ -0,0 +1,23 @@
/* eslint-disable */
// rename this file from _test_[name] to test_[name] to activate
// and remove above this line
QUnit.test("test: Contract Fulfilment Checklist", function (assert) {
let done = assert.async();
// number of asserts
assert.expect(1);
frappe.run_serially([
// insert a new Contract Fulfilment Checklist
() => frappe.tests.make('Contract Fulfilment Checklist', [
// values to be set
{key: 'value'}
]),
() => {
assert.equal(cur_frm.doc.key, 'value');
},
() => done()
]);
});

View File

@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
from __future__ import unicode_literals
import frappe
import unittest
class TestContractFulfilmentChecklist(unittest.TestCase):
pass

View File

@ -0,0 +1,8 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('Contract Template', {
refresh: function(frm) {
}
});

View File

@ -0,0 +1,306 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "field:title",
"beta": 0,
"creation": "2018-04-16 06:44:48.791312",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "title",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Title",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "sb_terms",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "contract_terms",
"fieldtype": "Text Editor",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Contract Terms and Conditions",
"length": 0,
"no_copy": 0,
"options": "",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "sb_fulfilment",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "requires_fulfilment",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Requires Fulfilment",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.requires_fulfilment==1",
"fieldname": "fulfilment_terms",
"fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Fulfilment Terms and Conditions",
"length": 0,
"no_copy": 0,
"options": "Contract Template Fulfilment Terms",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2018-04-17 07:36:05.217599",
"modified_by": "Administrator",
"module": "CRM",
"name": "Contract Template",
"name_case": "",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Sales Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Purchase Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "HR Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
}
],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0
}

View File

@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
class ContractTemplate(Document):
pass

View File

@ -0,0 +1,23 @@
/* eslint-disable */
// rename this file from _test_[name] to test_[name] to activate
// and remove above this line
QUnit.test("test: Contract Template", function (assert) {
let done = assert.async();
// number of asserts
assert.expect(1);
frappe.run_serially([
// insert a new Contract Template
() => frappe.tests.make('Contract Template', [
// values to be set
{key: 'value'}
]),
() => {
assert.equal(cur_frm.doc.key, 'value');
},
() => done()
]);
});

View File

@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
from __future__ import unicode_literals
import frappe
import unittest
class TestContractTemplate(unittest.TestCase):
pass

View File

@ -0,0 +1,71 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2018-04-16 06:46:48.636936",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "requirement",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Requirement",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2018-04-16 07:17:38.060049",
"modified_by": "Administrator",
"module": "CRM",
"name": "Contract Template Fulfilment Terms",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0
}

View File

@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
class ContractTemplateFulfilmentTerms(Document):
pass

View File

@ -233,7 +233,8 @@ scheduler_events = {
"erpnext.setup.doctype.company.company.cache_companies_monthly_sales_history",
"erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.update_latest_price_in_all_boms",
"erpnext.assets.doctype.asset.asset.update_maintenance_status",
"erpnext.assets.doctype.asset.asset.make_post_gl_entry"
"erpnext.assets.doctype.asset.asset.make_post_gl_entry",
"erpnext.crm.doctype.contract.contract.update_status_for_contracts"
],
"monthly": [
"erpnext.accounts.doctype.sales_invoice.sales_invoice.booked_deferred_revenue",