Merge branch 'develop' into dev-serial-no-statuses

This commit is contained in:
Rohan 2019-09-18 13:24:28 +05:30 committed by GitHub
commit b9c1dad2e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
164 changed files with 15078 additions and 16592 deletions

View File

@ -5,7 +5,7 @@ import frappe
from erpnext.hooks import regional_overrides
from frappe.utils import getdate
__version__ = '12.1.1'
__version__ = '12.1.3'
def get_default_company(user=None):
'''Get default company for user'''

File diff suppressed because it is too large Load Diff

View File

@ -100,7 +100,10 @@ class Account(NestedSet):
if ancestors:
if frappe.get_value("Company", self.company, "allow_account_creation_against_child_company"):
return
frappe.throw(_("Please add the account to root level Company - %s" % ancestors[0]))
if not frappe.db.get_value("Account",
{'account_name': self.account_name, 'company': ancestors[0]}, 'name'):
frappe.throw(_("Please add the account to root level Company - %s" % ancestors[0]))
else:
descendants = get_descendants_of('Company', self.company)
if not descendants: return
@ -114,24 +117,7 @@ class Account(NestedSet):
if not parent_acc_name_map: return
for company in descendants:
if not parent_acc_name_map.get(company):
frappe.throw(_("While creating account for child Company {0}, parent account {1} not found. Please create the parent account in corresponding COA")
.format(company, parent_acc_name))
doc = frappe.copy_doc(self)
doc.flags.ignore_root_company_validation = True
doc.update({
"company": company,
# parent account's currency should be passed down to child account's curreny
# if it is None, it picks it up from default company currency, which might be unintended
"account_currency": self.account_currency,
"parent_account": parent_acc_name_map[company]
})
if not self.check_if_child_acc_exists(doc):
doc.save()
frappe.msgprint(_("Account {0} is added in the child company {1}")
.format(doc.name, company))
self.create_account_for_child_company(parent_acc_name_map, descendants)
def validate_group_or_ledger(self):
if self.get("__islocal"):
@ -173,23 +159,48 @@ class Account(NestedSet):
if frappe.db.get_value("GL Entry", {"account": self.name}):
frappe.throw(_("Currency can not be changed after making entries using some other currency"))
def check_if_child_acc_exists(self, doc):
''' Checks if a account in parent company exists in the '''
info = frappe.db.get_value("Account", {
"account_name": doc.account_name,
"account_number": doc.account_number
}, ['company', 'account_currency', 'is_group', 'root_type', 'account_type', 'balance_must_be', 'account_name'], as_dict=1)
def create_account_for_child_company(self, parent_acc_name_map, descendants):
for company in descendants:
if not parent_acc_name_map.get(company):
frappe.throw(_("While creating account for child Company {0}, parent account {1} not found. Please create the parent account in corresponding COA")
.format(company, parent_acc_name))
if not info:
return
filters = {
"account_name": self.account_name,
"company": company
}
doc = vars(doc)
dict_diff = [k for k in info if k in doc and info[k] != doc[k] and k != "company"]
if dict_diff:
frappe.throw(_("Account {0} already exists in child company {1}. The following fields have different values, they should be same:<ul><li>{2}</li></ul>")
.format(info.account_name, info.company, '</li><li>'.join(dict_diff)))
else:
return True
if self.account_number:
filters["account_number"] = self.account_number
child_account = frappe.db.get_value("Account", filters, 'name')
if not child_account:
doc = frappe.copy_doc(self)
doc.flags.ignore_root_company_validation = True
doc.update({
"company": company,
# parent account's currency should be passed down to child account's curreny
# if it is None, it picks it up from default company currency, which might be unintended
"account_currency": self.account_currency,
"parent_account": parent_acc_name_map[company]
})
doc.save()
frappe.msgprint(_("Account {0} is added in the child company {1}")
.format(doc.name, company))
elif child_account:
# update the parent company's value in child companies
doc = frappe.get_doc("Account", child_account)
parent_value_changed = False
for field in ['account_type', 'account_currency',
'freeze_account', 'balance_must_be']:
if doc.get(field) != self.get(field):
parent_value_changed = True
doc.set(field, self.get(field))
if parent_value_changed:
doc.save()
def convert_group_to_ledger(self):
if self.check_if_child_exists():

View File

@ -5,9 +5,13 @@ frappe.ui.form.on('Accounting Dimension', {
refresh: function(frm) {
frm.set_query('document_type', () => {
let invalid_doctypes = frappe.model.core_doctypes_list;
invalid_doctypes.push('Accounting Dimension', 'Project',
'Cost Center', 'Accounting Dimension Detail');
return {
filters: {
name: ['not in', ['Accounting Dimension', 'Project', 'Cost Center', 'Accounting Dimension Detail']]
name: ['not in', invalid_doctypes]
}
};
});

View File

@ -11,10 +11,20 @@ from frappe.custom.doctype.custom_field.custom_field import create_custom_field
from frappe import scrub
from frappe.utils import cstr
from frappe.utils.background_jobs import enqueue
from frappe.model import core_doctypes_list
class AccountingDimension(Document):
def before_insert(self):
self.set_fieldname_and_label()
def validate(self):
if self.document_type in core_doctypes_list + ('Accounting Dimension', 'Project',
'Cost Center', 'Accounting Dimension Detail') :
msg = _("Not allowed to create accounting dimension for {0}").format(self.document_type)
frappe.throw(msg)
def after_insert(self):
if frappe.flags.in_test:
make_dimension_in_accounting_doctypes(doc=self)
else:
@ -164,7 +174,7 @@ def get_accounting_dimensions(as_list=True):
return accounting_dimensions
def get_checks_for_pl_and_bs_accounts():
dimensions = frappe.db.sql("""SELECT p.label, p.disabled, p.fieldname, c.company, c.mandatory_for_pl, c.mandatory_for_bs
dimensions = frappe.db.sql("""SELECT p.label, p.disabled, p.fieldname, c.default_dimension, c.company, c.mandatory_for_pl, c.mandatory_for_bs
FROM `tabAccounting Dimension`p ,`tabAccounting Dimension Detail` c
WHERE p.name = c.parent""", as_dict=1)

View File

@ -150,7 +150,7 @@ def validate_accounts(file_name):
accounts_dict = {}
for account in accounts:
accounts_dict.setdefault(account["account_name"], account)
if account["parent_account"] and accounts_dict[account["parent_account"]]:
if account["parent_account"] and accounts_dict.get(account["parent_account"]):
accounts_dict[account["parent_account"]]["is_group"] = 1
message = validate_root(accounts_dict)

View File

@ -1,457 +1,170 @@
{
"allow_copy": 1,
"allow_guest_to_view": 0,
"allow_import": 1,
"allow_rename": 1,
"autoname": "field:cost_center_name",
"beta": 0,
"creation": "2013-01-23 19:57:17",
"custom": 0,
"description": "Track separate Income and Expense for product verticals or divisions.",
"docstatus": 0,
"doctype": "DocType",
"document_type": "Setup",
"editable_grid": 0,
"allow_copy": 1,
"allow_import": 1,
"allow_rename": 1,
"creation": "2013-01-23 19:57:17",
"description": "Track separate Income and Expense for product verticals or divisions.",
"doctype": "DocType",
"document_type": "Setup",
"engine": "InnoDB",
"field_order": [
"sb0",
"cost_center_name",
"cost_center_number",
"parent_cost_center",
"company",
"cb0",
"is_group",
"disabled",
"lft",
"rgt",
"old_parent"
],
"fields": [
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "sb0",
"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,
"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,
"translatable": 0,
"unique": 0
},
"fieldname": "sb0",
"fieldtype": "Section Break"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "cost_center_name",
"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": "Cost Center Name",
"length": 0,
"no_copy": 1,
"oldfieldname": "cost_center_name",
"oldfieldtype": "Data",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "cost_center_name",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Cost Center Name",
"no_copy": 1,
"oldfieldname": "cost_center_name",
"oldfieldtype": "Data",
"reqd": 1
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "cost_center_number",
"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": 1,
"label": "Cost Center Number",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"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,
"translatable": 0,
"unique": 0
},
"fieldname": "cost_center_number",
"fieldtype": "Data",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Cost Center Number",
"read_only": 1
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "parent_cost_center",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 1,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Parent Cost Center",
"length": 0,
"no_copy": 0,
"oldfieldname": "parent_cost_center",
"oldfieldtype": "Link",
"options": "Cost Center",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "parent_cost_center",
"fieldtype": "Link",
"ignore_user_permissions": 1,
"in_list_view": 1,
"label": "Parent Cost Center",
"oldfieldname": "parent_cost_center",
"oldfieldtype": "Link",
"options": "Cost Center",
"reqd": 1
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "company",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Company",
"length": 0,
"no_copy": 0,
"oldfieldname": "company_name",
"oldfieldtype": "Link",
"options": "Company",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 1,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "company",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Company",
"oldfieldname": "company_name",
"oldfieldtype": "Link",
"options": "Company",
"remember_last_selected_value": 1,
"reqd": 1
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "cb0",
"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,
"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,
"translatable": 0,
"unique": 0,
"fieldname": "cb0",
"fieldtype": "Column Break",
"width": "50%"
},
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "0",
"fieldname": "is_group",
"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": "Is Group",
"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,
"translatable": 0,
"unique": 0
},
"default": "0",
"fieldname": "is_group",
"fieldtype": "Check",
"label": "Is Group"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "lft",
"fieldtype": "Int",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "lft",
"length": 0,
"no_copy": 1,
"oldfieldname": "lft",
"oldfieldtype": "Int",
"permlevel": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 1,
"reqd": 0,
"search_index": 1,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "lft",
"fieldtype": "Int",
"hidden": 1,
"label": "lft",
"no_copy": 1,
"oldfieldname": "lft",
"oldfieldtype": "Int",
"print_hide": 1,
"report_hide": 1,
"search_index": 1
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "rgt",
"fieldtype": "Int",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "rgt",
"length": 0,
"no_copy": 1,
"oldfieldname": "rgt",
"oldfieldtype": "Int",
"permlevel": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 1,
"reqd": 0,
"search_index": 1,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "rgt",
"fieldtype": "Int",
"hidden": 1,
"label": "rgt",
"no_copy": 1,
"oldfieldname": "rgt",
"oldfieldtype": "Int",
"print_hide": 1,
"report_hide": 1,
"search_index": 1
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "old_parent",
"fieldtype": "Link",
"hidden": 1,
"ignore_user_permissions": 1,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "old_parent",
"length": 0,
"no_copy": 1,
"oldfieldname": "old_parent",
"oldfieldtype": "Data",
"options": "Cost Center",
"permlevel": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 1,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
"fieldname": "old_parent",
"fieldtype": "Link",
"hidden": 1,
"ignore_user_permissions": 1,
"label": "old_parent",
"no_copy": 1,
"oldfieldname": "old_parent",
"oldfieldtype": "Data",
"options": "Cost Center",
"print_hide": 1,
"report_hide": 1
},
{
"default": "0",
"fieldname": "disabled",
"fieldtype": "Check",
"label": "Disabled"
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"icon": "fa fa-money",
"idx": 1,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
"modified": "2018-04-26 15:26:25.325778",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Cost Center",
"owner": "Administrator",
],
"icon": "fa fa-money",
"idx": 1,
"modified": "2019-09-16 14:44:17.103548",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Cost Center",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"create": 1,
"delete": 1,
"email": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts Manager",
"share": 1,
"write": 1
},
},
{
"amend": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 0,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 0,
"read": 1,
"report": 1,
"role": "Auditor",
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"write": 0
},
"export": 1,
"read": 1,
"report": 1,
"role": "Auditor"
},
{
"amend": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts User",
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"write": 0
},
"email": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts User"
},
{
"amend": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 0,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 0,
"read": 1,
"report": 0,
"role": "Sales User",
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"write": 0
},
"read": 1,
"role": "Sales User"
},
{
"amend": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 0,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 0,
"read": 1,
"report": 0,
"role": "Purchase User",
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"write": 0
"read": 1,
"role": "Purchase User"
}
],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"search_fields": "parent_cost_center, is_group",
"show_name_in_global_search": 1,
"sort_order": "ASC",
"track_changes": 0,
"track_seen": 0
],
"quick_entry": 1,
"search_fields": "parent_cost_center, is_group",
"show_name_in_global_search": 1,
"sort_field": "modified",
"sort_order": "ASC"
}

View File

@ -1,171 +1,74 @@
{
"allow_copy": 0,
"allow_import": 1,
"allow_rename": 1,
"autoname": "field:mode_of_payment",
"beta": 0,
"creation": "2012-12-04 17:49:20",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "Setup",
"editable_grid": 0,
"engine": "InnoDB",
"allow_import": 1,
"allow_rename": 1,
"autoname": "field:mode_of_payment",
"creation": "2012-12-04 17:49:20",
"doctype": "DocType",
"document_type": "Setup",
"engine": "InnoDB",
"field_order": [
"mode_of_payment",
"enabled",
"type",
"accounts"
],
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "mode_of_payment",
"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": "Mode of Payment",
"length": 0,
"no_copy": 0,
"oldfieldname": "mode_of_payment",
"oldfieldtype": "Data",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"fieldname": "mode_of_payment",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Mode of Payment",
"oldfieldname": "mode_of_payment",
"oldfieldtype": "Data",
"reqd": 1,
"unique": 1
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "type",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 1,
"label": "Type",
"length": 0,
"no_copy": 0,
"options": "Cash\nBank\nGeneral",
"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
},
"fieldname": "type",
"fieldtype": "Select",
"in_standard_filter": 1,
"label": "Type",
"options": "Cash\nBank\nGeneral"
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "accounts",
"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": "Accounts",
"length": 0,
"no_copy": 0,
"options": "Mode of Payment Account",
"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
"fieldname": "accounts",
"fieldtype": "Table",
"label": "Accounts",
"options": "Mode of Payment Account"
},
{
"default": "1",
"fieldname": "enabled",
"fieldtype": "Check",
"label": "Enabled"
}
],
"hide_heading": 0,
"hide_toolbar": 0,
"icon": "fa fa-credit-card",
"idx": 1,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2017-02-17 16:31:34.207683",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Mode of Payment",
"owner": "harshada@webnotestech.com",
],
"icon": "fa fa-credit-card",
"idx": 1,
"modified": "2019-08-14 14:58:42.079115",
"modified_by": "sammish.thundiyil@gmail.com",
"module": "Accounts",
"name": "Mode of Payment",
"owner": "harshada@webnotestech.com",
"permissions": [
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 0,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"create": 1,
"email": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts Manager",
"share": 1,
"write": 1
},
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 0,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 0,
"read": 1,
"report": 1,
"role": "Accounts User",
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"write": 0
"read": 1,
"report": 1,
"role": "Accounts User"
}
],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 1,
"sort_order": "ASC",
"track_changes": 0,
"track_seen": 0
],
"quick_entry": 1,
"show_name_in_global_search": 1,
"sort_field": "modified",
"sort_order": "ASC"
}

View File

@ -720,7 +720,7 @@ frappe.ui.form.on('Payment Entry', {
$.each(frm.doc.references || [], function(i, row) {
row.allocated_amount = 0 //If allocate payment amount checkbox is unchecked, set zero to allocate amount
if(frappe.flags.allocate_payment_amount){
if(frappe.flags.allocate_payment_amount != 0){
if(row.outstanding_amount > 0 && allocated_positive_outstanding > 0) {
if(row.outstanding_amount >= allocated_positive_outstanding) {
row.allocated_amount = allocated_positive_outstanding;

View File

@ -126,7 +126,7 @@ class PaymentEntry(AccountsController):
if not self.party:
frappe.throw(_("Party is mandatory"))
_party_name = "title" if self.party_type == "Student" else self.party_type.lower() + "_name"
_party_name = "title" if self.party_type in ("Student", "Shareholder") else self.party_type.lower() + "_name"
self.party_name = frappe.db.get_value(self.party_type, self.party, _party_name)
if self.party:

View File

@ -66,10 +66,10 @@ frappe.ui.form.on('Payment Order', {
get_query_filters: {
bank: frm.doc.bank,
docstatus: 1,
payment_type: ("!=", "Receive"),
payment_type: ["!=", "Receive"],
bank_account: frm.doc.company_bank_account,
paid_from: frm.doc.account,
payment_order_status: ["=", "Initiated"],
payment_order_status: ["=", "Initiated"]
}
});
},

View File

@ -20,7 +20,7 @@ class PaymentRequest(Document):
if self.get("__islocal"):
self.status = 'Draft'
self.validate_reference_document()
self.validate_payment_request()
self.validate_payment_request_amount()
self.validate_currency()
self.validate_subscription_details()
@ -28,10 +28,19 @@ class PaymentRequest(Document):
if not self.reference_doctype or not self.reference_name:
frappe.throw(_("To create a Payment Request reference document is required"))
def validate_payment_request(self):
if frappe.db.get_value("Payment Request", {"reference_name": self.reference_name,
"name": ("!=", self.name), "status": ("not in", ["Initiated", "Paid"]), "docstatus": 1}, "name"):
frappe.throw(_("Payment Request already exists {0}".format(self.reference_name)))
def validate_payment_request_amount(self):
existing_payment_request_amount = \
get_existing_payment_request_amount(self.reference_doctype, self.reference_name)
if existing_payment_request_amount:
ref_doc = frappe.get_doc(self.reference_doctype, self.reference_name)
if (hasattr(ref_doc, "order_type") \
and getattr(ref_doc, "order_type") != "Shopping Cart"):
ref_amount = get_amount(ref_doc)
if existing_payment_request_amount + flt(self.grand_total)> ref_amount:
frappe.throw(_("Total Payment Request amount cannot be greater than {0} amount"
.format(self.reference_doctype)))
def validate_currency(self):
ref_doc = frappe.get_doc(self.reference_doctype, self.reference_name)
@ -271,7 +280,7 @@ def make_payment_request(**args):
args = frappe._dict(args)
ref_doc = frappe.get_doc(args.dt, args.dn)
grand_total = get_amount(ref_doc, args.dt)
grand_total = get_amount(ref_doc)
if args.loyalty_points and args.dt == "Sales Order":
from erpnext.accounts.doctype.loyalty_program.loyalty_program import validate_loyalty_points
loyalty_amount = validate_loyalty_points(ref_doc, int(args.loyalty_points))
@ -281,17 +290,25 @@ def make_payment_request(**args):
gateway_account = get_gateway_details(args) or frappe._dict()
existing_payment_request = frappe.db.get_value("Payment Request",
{"reference_doctype": args.dt, "reference_name": args.dn, "docstatus": ["!=", 2]})
bank_account = (get_party_bank_account(args.get('party_type'), args.get('party'))
if args.get('party_type') else '')
existing_payment_request = None
if args.order_type == "Shopping Cart":
existing_payment_request = frappe.db.get_value("Payment Request",
{"reference_doctype": args.dt, "reference_name": args.dn, "docstatus": ("!=", 2)})
if existing_payment_request:
frappe.db.set_value("Payment Request", existing_payment_request, "grand_total", grand_total, update_modified=False)
pr = frappe.get_doc("Payment Request", existing_payment_request)
else:
if args.order_type != "Shopping Cart":
existing_payment_request_amount = \
get_existing_payment_request_amount(args.dt, args.dn)
if existing_payment_request_amount:
grand_total -= existing_payment_request_amount
pr = frappe.new_doc("Payment Request")
pr.update({
"payment_gateway_account": gateway_account.get("name"),
@ -327,8 +344,9 @@ def make_payment_request(**args):
return pr.as_dict()
def get_amount(ref_doc, dt):
def get_amount(ref_doc):
"""get amount based on doctype"""
dt = ref_doc.doctype
if dt in ["Sales Order", "Purchase Order"]:
grand_total = flt(ref_doc.grand_total) - flt(ref_doc.advance_paid)
@ -347,6 +365,17 @@ def get_amount(ref_doc, dt):
else:
frappe.throw(_("Payment Entry is already created"))
def get_existing_payment_request_amount(ref_dt, ref_dn):
existing_payment_request_amount = frappe.db.sql("""
select sum(grand_total)
from `tabPayment Request`
where
reference_doctype = %s
and reference_name = %s
and docstatus = 1
""", (ref_dt, ref_dn))
return flt(existing_payment_request_amount[0][0]) if existing_payment_request_amount else 0
def get_gateway_details(args):
"""return gateway and payment account of default payment gateway"""
if args.get("payment_gateway"):

View File

@ -37,12 +37,12 @@ class TestPaymentRequest(unittest.TestCase):
def setUp(self):
if not frappe.db.get_value("Payment Gateway", payment_gateway["gateway"], "name"):
frappe.get_doc(payment_gateway).insert(ignore_permissions=True)
for method in payment_method:
if not frappe.db.get_value("Payment Gateway Account", {"payment_gateway": method["payment_gateway"],
if not frappe.db.get_value("Payment Gateway Account", {"payment_gateway": method["payment_gateway"],
"currency": method["currency"]}, "name"):
frappe.get_doc(method).insert(ignore_permissions=True)
def test_payment_request_linkings(self):
so_inr = make_sales_order(currency="INR")
pr = make_payment_request(dt="Sales Order", dn=so_inr.name, recipient_id="saurabh@erpnext.com")
@ -100,3 +100,23 @@ class TestPaymentRequest(unittest.TestCase):
self.assertEqual(expected_gle[gle.account][1], gle.debit)
self.assertEqual(expected_gle[gle.account][2], gle.credit)
self.assertEqual(expected_gle[gle.account][3], gle.against_voucher)
def test_multiple_payment_entries_against_sales_order(self):
# Make Sales Order, grand_total = 1000
so = make_sales_order()
# Payment Request amount = 200
pr1 = make_payment_request(dt="Sales Order", dn=so.name,
recipient_id="nabin@erpnext.com", return_doc=1)
pr1.grand_total = 200
pr1.submit()
# Make a 2nd Payment Request
pr2 = make_payment_request(dt="Sales Order", dn=so.name,
recipient_id="nabin@erpnext.com", return_doc=1)
self.assertEqual(pr2.grand_total, 800)
# Try to make Payment Request more than SO amount, should give validation
pr2.grand_total = 900
self.assertRaises(frappe.ValidationError, pr2.save)

View File

@ -41,6 +41,8 @@ def get_pos_data():
items_list = get_items_list(pos_profile, doc.company)
customers = get_customers_list(pos_profile)
doc.plc_conversion_rate = update_plc_conversion_rate(doc, pos_profile)
return {
'doc': doc,
'default_customer': pos_profile.get('customer'),
@ -53,7 +55,7 @@ def get_pos_data():
'batch_no_data': get_batch_no_data(),
'barcode_data': get_barcode_data(items_list),
'tax_data': get_item_tax_data(),
'price_list_data': get_price_list_data(doc.selling_price_list),
'price_list_data': get_price_list_data(doc.selling_price_list, doc.plc_conversion_rate),
'customer_wise_price_list': get_customer_wise_price_list(),
'bin_data': get_bin_data(pos_profile),
'pricing_rules': get_pricing_rule_data(doc),
@ -62,6 +64,15 @@ def get_pos_data():
'meta': get_meta()
}
def update_plc_conversion_rate(doc, pos_profile):
conversion_rate = 1.0
price_list_currency = frappe.get_cached_value("Price List", doc.selling_price_list, "currency")
if pos_profile.get("currency") != price_list_currency:
conversion_rate = get_exchange_rate(price_list_currency,
pos_profile.get("currency"), nowdate(), args="for_selling") or 1.0
return conversion_rate
def get_meta():
doctype_meta = {
@ -317,14 +328,14 @@ def get_item_tax_data():
return itemwise_tax
def get_price_list_data(selling_price_list):
def get_price_list_data(selling_price_list, conversion_rate):
itemwise_price_list = {}
price_lists = frappe.db.sql("""Select ifnull(price_list_rate, 0) as price_list_rate,
item_code from `tabItem Price` ip where price_list = %(price_list)s""",
{'price_list': selling_price_list}, as_dict=1)
for item in price_lists:
itemwise_price_list[item.item_code] = item.price_list_rate
itemwise_price_list[item.item_code] = item.price_list_rate * conversion_rate
return itemwise_price_list

View File

@ -158,7 +158,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
cur_frm.meta._default_print_format = cur_frm.meta.default_print_format;
cur_frm.meta.default_print_format = cur_frm.pos_print_format;
}
} else if(cur_frm.doc.is_return) {
} else if(cur_frm.doc.is_return && !cur_frm.meta.default_print_format) {
if(cur_frm.return_print_format) {
cur_frm.meta._default_print_format = cur_frm.meta.default_print_format;
cur_frm.meta.default_print_format = cur_frm.return_print_format;

View File

@ -86,17 +86,23 @@ class ShareTransfer(Document):
frappe.throw(_('The field From Shareholder cannot be blank'))
if self.from_folio_no is None or self.from_folio_no is '':
self.to_folio_no = self.autoname_folio(self.to_shareholder)
if self.asset_account is None:
frappe.throw(_('The field Asset Account cannot be blank'))
elif (self.transfer_type == 'Issue'):
self.from_shareholder = ''
if self.to_shareholder is None or self.to_shareholder == '':
frappe.throw(_('The field To Shareholder cannot be blank'))
if self.to_folio_no is None or self.to_folio_no is '':
self.to_folio_no = self.autoname_folio(self.to_shareholder)
if self.asset_account is None:
frappe.throw(_('The field Asset Account cannot be blank'))
else:
if self.from_shareholder is None or self.to_shareholder is None:
frappe.throw(_('The fields From Shareholder and To Shareholder cannot be blank'))
if self.to_folio_no is None or self.to_folio_no is '':
self.to_folio_no = self.autoname_folio(self.to_shareholder)
if self.equity_or_liability_account is None:
frappe.throw(_('The field Equity/Liability Account cannot be blank'))
if self.from_shareholder == self.to_shareholder:
frappe.throw(_('The seller and the buyer cannot be the same'))
if self.no_of_shares != self.to_no - self.from_no + 1:

View File

@ -15,67 +15,74 @@ class TestShareTransfer(unittest.TestCase):
frappe.db.sql("delete from `tabShare Balance`")
share_transfers = [
{
"doctype" : "Share Transfer",
"transfer_type" : "Issue",
"date" : "2018-01-01",
"to_shareholder" : "SH-00001",
"share_type" : "Equity",
"from_no" : 1,
"to_no" : 500,
"no_of_shares" : 500,
"rate" : 10,
"company" : "_Test Company"
"doctype" : "Share Transfer",
"transfer_type" : "Issue",
"date" : "2018-01-01",
"to_shareholder" : "SH-00001",
"share_type" : "Equity",
"from_no" : 1,
"to_no" : 500,
"no_of_shares" : 500,
"rate" : 10,
"company" : "_Test Company",
"asset_account" : "Cash - _TC",
"equity_or_liability_account": "Creditors - _TC"
},
{
"doctype" : "Share Transfer",
"transfer_type" : "Transfer",
"date" : "2018-01-02",
"from_shareholder" : "SH-00001",
"to_shareholder" : "SH-00002",
"share_type" : "Equity",
"from_no" : 101,
"to_no" : 200,
"no_of_shares" : 100,
"rate" : 15,
"company" : "_Test Company"
"doctype" : "Share Transfer",
"transfer_type" : "Transfer",
"date" : "2018-01-02",
"from_shareholder" : "SH-00001",
"to_shareholder" : "SH-00002",
"share_type" : "Equity",
"from_no" : 101,
"to_no" : 200,
"no_of_shares" : 100,
"rate" : 15,
"company" : "_Test Company",
"equity_or_liability_account": "Creditors - _TC"
},
{
"doctype" : "Share Transfer",
"transfer_type" : "Transfer",
"date" : "2018-01-03",
"from_shareholder" : "SH-00001",
"to_shareholder" : "SH-00003",
"share_type" : "Equity",
"from_no" : 201,
"to_no" : 500,
"no_of_shares" : 300,
"rate" : 20,
"company" : "_Test Company"
"doctype" : "Share Transfer",
"transfer_type" : "Transfer",
"date" : "2018-01-03",
"from_shareholder" : "SH-00001",
"to_shareholder" : "SH-00003",
"share_type" : "Equity",
"from_no" : 201,
"to_no" : 500,
"no_of_shares" : 300,
"rate" : 20,
"company" : "_Test Company",
"equity_or_liability_account": "Creditors - _TC"
},
{
"doctype" : "Share Transfer",
"transfer_type" : "Transfer",
"date" : "2018-01-04",
"from_shareholder" : "SH-00003",
"to_shareholder" : "SH-00002",
"share_type" : "Equity",
"from_no" : 201,
"to_no" : 400,
"no_of_shares" : 200,
"rate" : 15,
"company" : "_Test Company"
"doctype" : "Share Transfer",
"transfer_type" : "Transfer",
"date" : "2018-01-04",
"from_shareholder" : "SH-00003",
"to_shareholder" : "SH-00002",
"share_type" : "Equity",
"from_no" : 201,
"to_no" : 400,
"no_of_shares" : 200,
"rate" : 15,
"company" : "_Test Company",
"equity_or_liability_account": "Creditors - _TC"
},
{
"doctype" : "Share Transfer",
"transfer_type" : "Purchase",
"date" : "2018-01-05",
"from_shareholder" : "SH-00003",
"share_type" : "Equity",
"from_no" : 401,
"to_no" : 500,
"no_of_shares" : 100,
"rate" : 25,
"company" : "_Test Company"
"doctype" : "Share Transfer",
"transfer_type" : "Purchase",
"date" : "2018-01-05",
"from_shareholder" : "SH-00003",
"share_type" : "Equity",
"from_no" : 401,
"to_no" : 500,
"no_of_shares" : 100,
"rate" : 25,
"company" : "_Test Company",
"asset_account" : "Cash - _TC",
"equity_or_liability_account": "Creditors - _TC"
}
]
for d in share_transfers:
@ -84,30 +91,33 @@ class TestShareTransfer(unittest.TestCase):
def test_invalid_share_transfer(self):
doc = frappe.get_doc({
"doctype" : "Share Transfer",
"transfer_type" : "Transfer",
"date" : "2018-01-05",
"from_shareholder" : "SH-00003",
"to_shareholder" : "SH-00002",
"share_type" : "Equity",
"from_no" : 1,
"to_no" : 100,
"no_of_shares" : 100,
"rate" : 15,
"company" : "_Test Company"
"doctype" : "Share Transfer",
"transfer_type" : "Transfer",
"date" : "2018-01-05",
"from_shareholder" : "SH-00003",
"to_shareholder" : "SH-00002",
"share_type" : "Equity",
"from_no" : 1,
"to_no" : 100,
"no_of_shares" : 100,
"rate" : 15,
"company" : "_Test Company",
"equity_or_liability_account": "Creditors - _TC"
})
self.assertRaises(ShareDontExists, doc.insert)
doc = frappe.get_doc({
"doctype" : "Share Transfer",
"transfer_type" : "Purchase",
"date" : "2018-01-02",
"from_shareholder" : "SH-00001",
"share_type" : "Equity",
"from_no" : 1,
"to_no" : 200,
"no_of_shares" : 200,
"rate" : 15,
"company" : "_Test Company"
"doctype" : "Share Transfer",
"transfer_type" : "Purchase",
"date" : "2018-01-02",
"from_shareholder" : "SH-00001",
"share_type" : "Equity",
"from_no" : 1,
"to_no" : 200,
"no_of_shares" : 200,
"rate" : 15,
"company" : "_Test Company",
"asset_account" : "Cash - _TC",
"equity_or_liability_account": "Creditors - _TC"
})
self.assertRaises(ShareDontExists, doc.insert)

View File

@ -1624,7 +1624,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
setTimeout(function () {
w.print();
w.close();
}, 1000)
}, 1000);
},
submit_invoice: function () {
@ -1681,6 +1681,12 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
$(this.wrapper).find('.pos-bill').css('pointer-events', pointer_events);
$(this.wrapper).find('.pos-items-section').css('pointer-events', pointer_events);
this.set_primary_action();
$(this.wrapper).find('#pos-item-disc').prop('disabled',
this.pos_profile_data.allow_user_to_edit_discount ? false : true);
$(this.wrapper).find('#pos-item-price').prop('disabled',
this.pos_profile_data.allow_user_to_edit_rate ? false : true);
},
create_invoice: function () {
@ -1691,20 +1697,13 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
if(this.si_docs) {
this.si_docs.forEach((row) => {
existing_pos_list.push(Object.keys(row));
existing_pos_list.push(Object.keys(row)[0]);
});
}
if (this.frm.doc.offline_pos_name
&& in_list(existing_pos_list, this.frm.doc.offline_pos_name)) {
&& in_list(existing_pos_list, cstr(this.frm.doc.offline_pos_name))) {
this.update_invoice()
//to retrieve and set the default payment
invoice_data[this.frm.doc.offline_pos_name] = this.frm.doc;
invoice_data[this.frm.doc.offline_pos_name].payments[0].amount = this.frm.doc.net_total
invoice_data[this.frm.doc.offline_pos_name].payments[0].base_amount = this.frm.doc.net_total
this.frm.doc.paid_amount = this.frm.doc.net_total
this.frm.doc.outstanding_amount = 0
} else if(!this.frm.doc.offline_pos_name) {
this.frm.doc.offline_pos_name = frappe.datetime.now_datetime();
this.frm.doc.posting_date = frappe.datetime.get_today();
@ -1898,7 +1897,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
serial_no = me.item_serial_no[key][0];
}
if (this.items[0].has_serial_no && serial_no == "") {
if (this.items && this.items[0].has_serial_no && serial_no == "") {
this.refresh();
frappe.throw(__(repl("Error: Serial no is mandatory for item %(item)s", {
'item': this.items[0].item_code

View File

@ -1,22 +1,23 @@
{
"align_labels_right": 0,
"creation": "2016-05-05 17:16:18.564460",
"custom_format": 1,
"disabled": 0,
"doc_type": "Sales Invoice",
"docstatus": 0,
"doctype": "Print Format",
"font": "Default",
"html": "<style>\n\t.print-format table, .print-format tr, \n\t.print-format td, .print-format div, .print-format p {\n\t\tfont-family: Monospace;\n\t\tline-height: 200%;\n\t\tvertical-align: middle;\n\t}\n\t@media screen {\n\t\t.print-format {\n\t\t\twidth: 4in;\n\t\t\tpadding: 0.25in;\n\t\t\tmin-height: 8in;\n\t\t}\n\t}\n</style>\n\n<p class=\"text-center\">\n\t{{ company }}<br>\n\t{{ __(\"POS No : \") }} {{ offline_pos_name }}<br>\n</p>\n<p>\n\t<b>{{ __(\"Customer\") }}:</b> {{ customer }}<br>\n</p>\n\n<p>\n\t<b>{{ __(\"Date\") }}:</b> {{ dateutil.global_date_format(posting_date) }}<br>\n</p>\n\n<hr>\n<table class=\"table table-condensed cart no-border\">\n\t<thead>\n\t\t<tr>\n\t\t\t<th width=\"50%\">{{ __(\"Item\") }}</b></th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ __(\"Qty\") }}</th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ __(\"Amount\") }}</th>\n\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t{% for item in items %}\n\t\t<tr>\n\t\t\t<td>\n\t\t\t\t{{ item.item_name }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ format_number(item.qty, null,precision(\"difference\")) }}<br>@ {{ format_currency(item.rate, currency) }}</td>\n\t\t\t<td class=\"text-right\">{{ format_currency(item.amount, currency) }}</td>\n\t\t</tr>\n\t\t{% endfor %}\n\t</tbody>\n</table>\n\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ __(\"Net Total\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(total, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{% for row in taxes %}\n\t\t{% if not row.included_in_print_rate %}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ row.description }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(row.tax_amount, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{% endif %}\n\t\t{% endfor %}\n\t\t{% if discount_amount %}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t{{ __(\"Discount\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(discount_amount, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{% endif %}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ __(\"Grand Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(grand_total, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ __(\"Paid Amount\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(paid_amount, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ __(\"Qty Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ qty_total }}\n\t\t\t</td>\n\t\t</tr>\n\t</tbody>\n</table>\n\n\n<hr>\n<p>{{ terms }}</p>\n<p class=\"text-center\">{{ __(\"Thank you, please visit again.\") }}</p>",
"idx": 0,
"line_breaks": 0,
"modified": "2018-03-21 09:10:16.693732",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Point of Sale",
"owner": "Administrator",
"print_format_builder": 0,
"print_format_type": "Js",
"show_section_headings": 0,
"align_labels_right": 0,
"creation": "2016-05-05 17:16:18.564460",
"custom_format": 1,
"disabled": 0,
"doc_type": "Sales Invoice",
"docstatus": 0,
"doctype": "Print Format",
"font": "Default",
"html": "<style>\n\t.print-format table, .print-format tr, \n\t.print-format td, .print-format div, .print-format p {\n\t\tfont-family: Monospace;\n\t\tline-height: 200%;\n\t\tvertical-align: middle;\n\t}\n\t@media screen {\n\t\t.print-format {\n\t\t\twidth: 4in;\n\t\t\tpadding: 0.25in;\n\t\t\tmin-height: 8in;\n\t\t}\n\t}\n</style>\n\n<p class=\"text-center\">\n\t{{ company }}<br>\n\t{{ __(\"POS No : \") }} {{ offline_pos_name }}<br>\n</p>\n<p>\n\t<b>{{ __(\"Customer\") }}:</b> {{ customer }}<br>\n</p>\n\n<p>\n\t<b>{{ __(\"Date\") }}:</b> {{ dateutil.global_date_format(posting_date) }}<br>\n</p>\n\n<hr>\n<table class=\"table table-condensed cart no-border\">\n\t<thead>\n\t\t<tr>\n\t\t\t<th width=\"50%\">{{ __(\"Item\") }}</b></th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ __(\"Qty\") }}</th>\n\t\t\t<th width=\"25%\" class=\"text-right\">{{ __(\"Amount\") }}</th>\n\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t{% for item in items %}\n\t\t<tr>\n\t\t\t<td>\n\t\t\t\t{{ item.item_name }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ format_number(item.qty, null,precision(\"difference\")) }}<br>@ {{ format_currency(item.rate, currency) }}</td>\n\t\t\t<td class=\"text-right\">{{ format_currency(item.amount, currency) }}</td>\n\t\t</tr>\n\t\t{% endfor %}\n\t</tbody>\n</table>\n\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ __(\"Net Total\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(total, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{% for row in taxes %}\n\t\t{% if not row.included_in_print_rate %}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ row.description }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(row.tax_amount, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{% endif %}\n\t\t{% endfor %}\n\t\t{% if discount_amount %}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t{{ __(\"Discount\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(discount_amount, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{% endif %}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ __(\"Grand Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(grand_total, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ __(\"Paid Amount\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ format_currency(paid_amount, currency) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 75%\">\n\t\t\t\t<b>{{ __(\"Qty Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ qty_total }}\n\t\t\t</td>\n\t\t</tr>\n\t</tbody>\n</table>\n\n\n<hr>\n<p>{{ terms }}</p>\n<p class=\"text-center\">{{ __(\"Thank you, please visit again.\") }}</p>",
"idx": 0,
"line_breaks": 0,
"modified": "2019-09-05 17:20:30.726659",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Point of Sale",
"owner": "Administrator",
"print_format_builder": 0,
"print_format_type": "JS",
"raw_printing": 0,
"show_section_headings": 0,
"standard": "Yes"
}

View File

@ -365,7 +365,7 @@ class ReceivablePayableReport(object):
on
(ref.parent = payment_entry.name)
where
payment_entry.docstatus = 1
payment_entry.docstatus < 2
and payment_entry.posting_date > %s
and payment_entry.party_type = %s
""", (self.filters.report_date, self.party_type), as_dict=1)
@ -390,7 +390,7 @@ class ReceivablePayableReport(object):
on
(jea.parent = je.name)
where
je.docstatus = 1
je.docstatus < 2
and je.posting_date > %s
and jea.party_type = %s
and jea.reference_name is not null and jea.reference_name != ''

View File

@ -286,14 +286,14 @@ class PartyLedgerSummaryReport(object):
if parties and accounts:
if len(parties) == 1:
party = parties.keys()[0]
party = list(parties.keys())[0]
for account, amount in iteritems(accounts):
self.party_adjustment_accounts.add(account)
self.party_adjustment_details.setdefault(party, {})
self.party_adjustment_details[party].setdefault(account, 0)
self.party_adjustment_details[party][account] += amount
elif len(accounts) == 1 and not has_irrelevant_entry:
account = accounts.keys()[0]
account = list(accounts.keys())[0]
self.party_adjustment_accounts.add(account)
for party, amount in iteritems(parties):
self.party_adjustment_details.setdefault(party, {})

View File

@ -292,12 +292,6 @@ class Asset(AccountsController):
if self.status not in ("Submitted", "Partially Depreciated", "Fully Depreciated"):
frappe.throw(_("Asset cannot be cancelled, as it is already {0}").format(self.status))
if self.purchase_invoice:
frappe.throw(_("Please cancel Purchase Invoice {0} first").format(self.purchase_invoice))
if self.purchase_receipt:
frappe.throw(_("Please cancel Purchase Receipt {0} first").format(self.purchase_receipt))
def delete_depreciation_entries(self):
for d in self.get("schedules"):
if d.journal_entry:
@ -351,6 +345,7 @@ class Asset(AccountsController):
if asset_movement:
doc = frappe.get_doc('Asset Movement', asset_movement)
doc.naming_series = 'ACC-ASM-.YYYY.-'
doc.submit()
def make_gl_entries(self):

View File

@ -6,6 +6,7 @@ from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.utils import flt, today, getdate, cint
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_checks_for_pl_and_bs_accounts
def post_depreciation_entries(date=None):
# Return if automatic booking of asset depreciation is disabled
@ -41,6 +42,8 @@ def make_depreciation_entry(asset_name, date=None):
depreciation_cost_center = asset.cost_center or depreciation_cost_center
accounting_dimensions = get_checks_for_pl_and_bs_accounts()
for d in asset.get("schedules"):
if not d.journal_entry and getdate(d.schedule_date) <= getdate(date):
je = frappe.new_doc("Journal Entry")
@ -51,23 +54,40 @@ def make_depreciation_entry(asset_name, date=None):
je.finance_book = d.finance_book
je.remark = "Depreciation Entry against {0} worth {1}".format(asset_name, d.depreciation_amount)
je.append("accounts", {
credit_entry = {
"account": accumulated_depreciation_account,
"credit_in_account_currency": d.depreciation_amount,
"reference_type": "Asset",
"reference_name": asset.name
})
}
je.append("accounts", {
debit_entry = {
"account": depreciation_expense_account,
"debit_in_account_currency": d.depreciation_amount,
"reference_type": "Asset",
"reference_name": asset.name,
"cost_center": depreciation_cost_center
})
}
for dimension in accounting_dimensions:
if (asset.get(dimension['fieldname']) or dimension.get('mandatory_for_bs')):
credit_entry.update({
dimension['fieldname']: asset.get(dimension['fieldname']) or dimension.get('default_dimension')
})
if (asset.get(dimension['fieldname']) or dimension.get('mandatory_for_pl')):
debit_entry.update({
dimension['fieldname']: asset.get(dimension['fieldname']) or dimension.get('default_dimension')
})
je.append("accounts", credit_entry)
je.append("accounts", debit_entry)
je.flags.ignore_permissions = True
je.submit()
je.save()
if not je.meta.get_workflow():
je.submit()
d.db_set("journal_entry", je.name)

View File

@ -1,685 +1,211 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 1,
"allow_rename": 0,
"autoname": "ACC-ASM-.YYYY.-.#####",
"beta": 0,
"creation": "2016-04-25 18:00:23.559973",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 0,
"allow_import": 1,
"autoname": "naming_series:",
"creation": "2016-04-25 18:00:23.559973",
"doctype": "DocType",
"field_order": [
"naming_series",
"company",
"purpose",
"asset",
"transaction_date",
"column_break_4",
"quantity",
"select_serial_no",
"serial_no",
"section_break_7",
"source_location",
"target_location",
"column_break_10",
"from_employee",
"to_employee",
"reference",
"reference_doctype",
"reference_name",
"amended_from"
],
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "company",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Company",
"length": 0,
"no_copy": 0,
"options": "Company",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 1,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "company",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Company",
"options": "Company",
"remember_last_selected_value": 1,
"reqd": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "Transfer",
"fieldname": "purpose",
"fieldtype": "Select",
"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": "Purpose",
"length": 0,
"no_copy": 0,
"options": "\nIssue\nReceipt\nTransfer",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"default": "Transfer",
"fieldname": "purpose",
"fieldtype": "Select",
"label": "Purpose",
"options": "\nIssue\nReceipt\nTransfer",
"reqd": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "asset",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 1,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Asset",
"length": 0,
"no_copy": 0,
"options": "Asset",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "asset",
"fieldtype": "Link",
"in_global_search": 1,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Asset",
"options": "Asset",
"reqd": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "transaction_date",
"fieldtype": "Datetime",
"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": "Transaction Date",
"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": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "transaction_date",
"fieldtype": "Datetime",
"in_list_view": 1,
"label": "Transaction Date",
"reqd": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_4",
"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,
"translatable": 0,
"unique": 0
},
"fieldname": "column_break_4",
"fieldtype": "Column Break"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "quantity",
"fieldtype": "Float",
"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": "Quantity",
"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,
"translatable": 0,
"unique": 0
},
"fieldname": "quantity",
"fieldtype": "Float",
"label": "Quantity"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "select_serial_no",
"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": "Select Serial No",
"length": 0,
"no_copy": 0,
"options": "Serial No",
"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,
"translatable": 0,
"unique": 0
},
"fieldname": "select_serial_no",
"fieldtype": "Link",
"label": "Select Serial No",
"options": "Serial No"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "serial_no",
"fieldtype": "Small Text",
"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": "Serial No",
"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,
"translatable": 0,
"unique": 0
},
"fieldname": "serial_no",
"fieldtype": "Small Text",
"label": "Serial No"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_7",
"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,
"translatable": 0,
"unique": 0
},
"fieldname": "section_break_7",
"fieldtype": "Section Break"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_from": "",
"fieldname": "source_location",
"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": "Source Location",
"length": 0,
"no_copy": 0,
"options": "Location",
"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,
"translatable": 0,
"unique": 0
},
"fieldname": "source_location",
"fieldtype": "Link",
"label": "Source Location",
"options": "Location"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "target_location",
"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": "Target Location",
"length": 0,
"no_copy": 0,
"options": "Location",
"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,
"translatable": 0,
"unique": 0
},
"fieldname": "target_location",
"fieldtype": "Link",
"label": "Target Location",
"options": "Location"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_10",
"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,
"translatable": 0,
"unique": 0
},
"fieldname": "column_break_10",
"fieldtype": "Column Break"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "from_employee",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 1,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "From Employee",
"length": 0,
"no_copy": 0,
"options": "Employee",
"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,
"translatable": 0,
"unique": 0
},
"fieldname": "from_employee",
"fieldtype": "Link",
"ignore_user_permissions": 1,
"label": "From Employee",
"options": "Employee"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "to_employee",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 1,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "To Employee",
"length": 0,
"no_copy": 0,
"options": "Employee",
"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,
"translatable": 0,
"unique": 0
},
"fieldname": "to_employee",
"fieldtype": "Link",
"ignore_user_permissions": 1,
"label": "To Employee",
"options": "Employee"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "reference",
"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": "Reference",
"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,
"translatable": 0,
"unique": 0
},
"fieldname": "reference",
"fieldtype": "Section Break",
"label": "Reference"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "reference_doctype",
"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": "Reference DocType",
"length": 0,
"no_copy": 1,
"options": "DocType",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"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,
"translatable": 0,
"unique": 0
},
"fieldname": "reference_doctype",
"fieldtype": "Link",
"label": "Reference DocType",
"no_copy": 1,
"options": "DocType",
"read_only": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "reference_name",
"fieldtype": "Dynamic 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": "Reference Name",
"length": 0,
"no_copy": 1,
"options": "reference_doctype",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"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,
"translatable": 0,
"unique": 0
},
"fieldname": "reference_name",
"fieldtype": "Dynamic Link",
"label": "Reference Name",
"no_copy": 1,
"options": "reference_doctype",
"read_only": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 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": "Asset Movement",
"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,
"translatable": 0,
"unique": 0
"fieldname": "amended_from",
"fieldtype": "Link",
"label": "Amended From",
"no_copy": 1,
"options": "Asset Movement",
"print_hide": 1,
"read_only": 1
},
{
"default": "ACC-ASM-.YYYY.-",
"fieldname": "naming_series",
"fieldtype": "Select",
"label": "Series",
"options": "ACC-ASM-.YYYY.-",
"reqd": 1
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 1,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2018-08-21 16:15:40.563655",
"modified_by": "Administrator",
"module": "Assets",
"name": "Asset Movement",
"name_case": "",
"owner": "Administrator",
],
"is_submittable": 1,
"modified": "2019-09-16 16:27:53.887634",
"modified_by": "Administrator",
"module": "Assets",
"name": "Asset Movement",
"owner": "Administrator",
"permissions": [
{
"amend": 1,
"cancel": 1,
"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": 1,
"amend": 1,
"cancel": 1,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"submit": 1,
"write": 1
},
},
{
"amend": 1,
"cancel": 1,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 1,
"amend": 1,
"cancel": 1,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts Manager",
"share": 1,
"submit": 1,
"write": 1
},
},
{
"amend": 1,
"cancel": 1,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Stock Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 1,
"amend": 1,
"cancel": 1,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Stock Manager",
"share": 1,
"submit": 1,
"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": 0,
"track_seen": 0,
"track_views": 0
],
"sort_field": "modified",
"sort_order": "DESC"
}

View File

@ -60,7 +60,7 @@ def get_employees_with_number(number):
employee_emails = [employee.user_id for employee in employees]
frappe.cache().hset('employees_with_number', number, employee_emails)
return employee
return employee_emails
def set_caller_information(doc, state):
'''Called from hooks on creation of Lead or Contact'''

View File

@ -40,6 +40,11 @@ def get_data():
"type": "doctype",
"name": "Plaid Settings",
"description": _("Connect your bank accounts to ERPNext"),
},
{
"type": "doctype",
"name": "Exotel Settings",
"description": _("Connect your Exotel Account to ERPNext and track call logs"),
}
]
}

View File

@ -89,7 +89,7 @@ class AccountsController(TransactionBase):
self.validate_currency()
if self.doctype == 'Purchase Invoice':
self.validate_paid_amount()
self.calculate_paid_amount()
if self.doctype in ['Purchase Invoice', 'Sales Invoice']:
pos_check_field = "is_pos" if self.doctype=="Sales Invoice" else "is_paid"
@ -135,22 +135,23 @@ class AccountsController(TransactionBase):
else:
df.set("print_hide", 1)
def validate_paid_amount(self):
def calculate_paid_amount(self):
if hasattr(self, "is_pos") or hasattr(self, "is_paid"):
is_paid = self.get("is_pos") or self.get("is_paid")
if cint(is_paid) == 1:
if flt(self.paid_amount) == 0 and flt(self.outstanding_amount) > 0:
if self.cash_bank_account:
self.paid_amount = flt(flt(self.outstanding_amount), self.precision("paid_amount"))
self.base_paid_amount = flt(self.paid_amount * self.conversion_rate,
self.precision("base_paid_amount"))
else:
# show message that the amount is not paid
self.paid_amount = 0
frappe.throw(
_("Note: Payment Entry will not be created since 'Cash or Bank Account' was not specified"))
else:
frappe.db.set(self, 'paid_amount', 0)
if is_paid:
if not self.cash_bank_account:
# show message that the amount is not paid
frappe.throw(_("Note: Payment Entry will not be created since 'Cash or Bank Account' was not specified"))
if cint(self.is_return) and self.grand_total > self.paid_amount:
self.paid_amount = flt(flt(self.grand_total), self.precision("paid_amount"))
elif not flt(self.paid_amount) and flt(self.outstanding_amount) > 0:
self.paid_amount = flt(flt(self.outstanding_amount), self.precision("paid_amount"))
self.base_paid_amount = flt(self.paid_amount * self.conversion_rate,
self.precision("base_paid_amount"))
def set_missing_values(self, for_validate=False):
if frappe.flags.in_test:

View File

@ -337,7 +337,7 @@ class BuyingController(StockController):
if self.doctype in ["Purchase Receipt", "Purchase Invoice"]:
rm.consumed_qty = required_qty
rm.description = bom_item.description
if item.batch_no and not rm.batch_no:
if item.batch_no and frappe.db.get_value("Item", rm.rm_item_code, "has_batch_no") and not rm.batch_no:
rm.batch_no = item.batch_no
# get raw materials rate

View File

@ -440,17 +440,17 @@ def get_batch_numbers(doctype, txt, searchfield, start, page_len, filters):
@frappe.whitelist()
def item_manufacturer_query(doctype, txt, searchfield, start, page_len, filters):
search_txt = "{0}%".format(txt)
item_filters = [
['manufacturer', 'like', '%' + txt + '%'],
['item_code', '=', filters.get("item_code")]
]
item_filters = {
'manufacturer': ('like', search_txt),
'item_code': filters.get("item_code")
}
return frappe.get_all("Item Manufacturer",
fields = "manufacturer",
filters = item_filters,
item_manufacturers = frappe.get_all(
"Item Manufacturer",
fields=["manufacturer", "manufacturer_part_no"],
filters=item_filters,
limit_start=start,
limit_page_length=page_len,
as_list=1
)
return item_manufacturers

View File

@ -246,6 +246,8 @@ def make_return_doc(doctype, source_name, target_doc=None):
elif doc.doctype == 'Purchase Invoice':
doc.paid_amount = -1 * source.paid_amount
doc.base_paid_amount = -1 * source.base_paid_amount
doc.payment_terms_template = ''
doc.payment_schedule = []
if doc.get("is_return") and hasattr(doc, "packed_items"):
for d in doc.get("packed_items"):

View File

@ -54,6 +54,9 @@ def get_data(filters, conditions):
if conditions.get('trans') in ['Sales Order', 'Purchase Order']:
cond += " and t1.status != 'Closed'"
if conditions.get('trans') == 'Quotation' and filters.get("group_by") == 'Customer':
cond += " and t1.quotation_to = 'Customer'"
year_start_date, year_end_date = frappe.db.get_value("Fiscal Year",
filters.get('fiscal_year'), ["year_start_date", "year_end_date"])
@ -64,7 +67,7 @@ def get_data(filters, conditions):
if filters.get("group_by") == 'Item':
sel_col = 't2.item_code'
elif filters.get("group_by") == 'Customer':
sel_col = 't1.customer'
sel_col = 't1.party_name' if conditions.get('trans') == 'Quotation' else 't1.customer'
elif filters.get("group_by") == 'Supplier':
sel_col = 't1.supplier'
@ -225,7 +228,7 @@ def based_wise_columns_query(based_on, trans):
elif based_on == "Customer":
based_on_details["based_on_cols"] = ["Customer:Link/Customer:120", "Territory:Link/Territory:120"]
based_on_details["based_on_select"] = "t1.customer_name, t1.territory, "
based_on_details["based_on_group_by"] = 't1.customer'
based_on_details["based_on_group_by"] = 't1.party_name' if trans == 'Quotation' else 't1.customer'
based_on_details["addl_tables"] = ''
elif based_on == "Customer Group":

File diff suppressed because it is too large Load Diff

View File

@ -18,12 +18,14 @@ frappe.listview_settings['Opportunity'] = {
listview.call_for_selected_items(method, {"status": "Closed"});
});
listview.page.fields_dict.opportunity_from.get_query = function() {
return {
"filters": {
"name": ["in", ["Customer", "Lead"]],
}
if(listview.page.fields_dict.opportunity_from) {
listview.page.fields_dict.opportunity_from.get_query = function() {
return {
"filters": {
"name": ["in", ["Customer", "Lead"]],
}
};
};
};
}
}
};

View File

@ -30,7 +30,7 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Enrollment",
"label": "Course Enrollment",
"length": 0,
"no_copy": 0,
"options": "Course Enrollment",
@ -298,4 +298,4 @@
"track_changes": 1,
"track_seen": 0,
"track_views": 0
}
}

View File

@ -5,6 +5,7 @@
"engine": "InnoDB",
"field_order": [
"course",
"course_name",
"required"
],
"fields": [
@ -16,6 +17,14 @@
"label": "Course",
"options": "Course",
"reqd": 1
},
{
"fieldname": "course_name",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Course Name",
"fetch_from": "course.course_name",
"read_only":1
},
{
"default": "0",
@ -36,4 +45,4 @@
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}
}

View File

@ -705,7 +705,6 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "INDIAN",
"fieldname": "nationality",
"fieldtype": "Data",
"hidden": 0,
@ -1231,4 +1230,4 @@
"track_changes": 0,
"track_seen": 0,
"track_views": 0
}
}

View File

@ -55,7 +55,7 @@ def preview_report_card(doc):
"courses": courses,
"assessment_groups": assessment_groups,
"course_criteria": course_criteria,
"letterhead": letterhead.content,
"letterhead": letterhead and letterhead.get('content', None),
"add_letterhead": doc.add_letterhead if doc.add_letterhead else 0
})
final_template = frappe.render_template(base_template_path, {"body": html, "title": "Report Card"})
@ -89,4 +89,4 @@ def get_attendance_count(student, academic_year, academic_term=None):
attendance["Present"] = 0
return attendance
else:
frappe.throw(_("Provide the academic year and set the starting and ending date."))
frappe.throw(_("Provide the academic year and set the starting and ending date."))

View File

@ -89,8 +89,6 @@ def request_and_fetch_report_id(report_type, start_date=None, end_date=None, mar
end_date=end_date,
marketplaceids=marketplaceids)
#add time delay to wait for amazon to generate report
time.sleep(20)
report_request_id = report_response.parsed["ReportRequestInfo"]["ReportRequestId"]["value"]
generated_report_id = None
#poll to get generated report

View File

@ -10,6 +10,7 @@ import urllib
import hashlib
import hmac
import base64
import six
from erpnext.erpnext_integrations.doctype.amazon_mws_settings import xml_utils
import re
try:
@ -71,12 +72,13 @@ def remove_empty(d):
Helper function that removes all keys from a dictionary (d),
that have an empty value.
"""
for key in d.keys():
for key in list(d):
if not d[key]:
del d[key]
return d
def remove_namespace(xml):
xml = xml.decode('utf-8')
regex = re.compile(' xmlns(:ns2)?="[^"]+"|(ns2:)|(xml:)')
return regex.sub('', xml)
@ -172,9 +174,10 @@ class MWS(object):
'SignatureMethod': 'HmacSHA256',
}
params.update(extra_data)
request_description = '&'.join(['%s=%s' % (k, urllib.quote(params[k], safe='-_.~').encode('utf-8')) for k in sorted(params)])
quote = urllib.quote if six.PY2 else urllib.parse.quote
request_description = '&'.join(['%s=%s' % (k, quote(params[k], safe='-_.~')) for k in sorted(params)])
signature = self.calc_signature(method, request_description)
url = '%s%s?%s&Signature=%s' % (self.domain, self.uri, request_description, urllib.quote(signature))
url = '%s%s?%s&Signature=%s' % (self.domain, self.uri, request_description, quote(signature))
headers = {'User-Agent': 'python-amazon-mws/0.0.1 (Language=Python)'}
headers.update(kwargs.get('extra_headers', {}))
@ -218,7 +221,10 @@ class MWS(object):
"""Calculate MWS signature to interface with Amazon
"""
sig_data = method + '\n' + self.domain.replace('https://', '').lower() + '\n' + self.uri + '\n' + request_description
return base64.b64encode(hmac.new(str(self.secret_key), sig_data, hashlib.sha256).digest())
sig_data = sig_data.encode('utf-8')
secret_key = self.secret_key.encode('utf-8')
digest = hmac.new(secret_key, sig_data, hashlib.sha256).digest()
return base64.b64encode(digest).decode('utf-8')
def get_timestamp(self):
"""

View File

@ -3,30 +3,31 @@
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe import _
import requests
from frappe.utils.password import get_decrypted_password
from plaid import Client
from plaid.errors import APIError, ItemError
import frappe
import requests
class PlaidConnector():
def __init__(self, access_token=None):
if not(frappe.conf.get("plaid_client_id") and frappe.conf.get("plaid_secret") and frappe.conf.get("plaid_public_key")):
frappe.throw(_("Please complete your Plaid API configuration before synchronizing your account"))
plaid_settings = frappe.get_single("Plaid Settings")
self.config = {
"plaid_client_id": frappe.conf.get("plaid_client_id"),
"plaid_secret": frappe.conf.get("plaid_secret"),
"plaid_public_key": frappe.conf.get("plaid_public_key"),
"plaid_env": frappe.conf.get("plaid_env")
"plaid_client_id": plaid_settings.plaid_client_id,
"plaid_secret": get_decrypted_password("Plaid Settings", "Plaid Settings", 'plaid_secret'),
"plaid_public_key": plaid_settings.plaid_public_key,
"plaid_env": plaid_settings.plaid_env
}
self.client = Client(client_id=self.config["plaid_client_id"],
secret=self.config["plaid_secret"],
public_key=self.config["plaid_public_key"],
environment=self.config["plaid_env"]
)
self.client = Client(client_id=self.config.get("plaid_client_id"),
secret=self.config.get("plaid_secret"),
public_key=self.config.get("plaid_public_key"),
environment=self.config.get("plaid_env")
)
self.access_token = access_token
@ -78,4 +79,4 @@ class PlaidConnector():
transactions.extend(response['transactions'])
return transactions
except Exception:
frappe.log_error(frappe.get_traceback(), _("Plaid transactions sync error"))
frappe.log_error(frappe.get_traceback(), _("Plaid transactions sync error"))

View File

@ -4,8 +4,18 @@
frappe.provide("erpnext.integrations");
frappe.ui.form.on('Plaid Settings', {
link_new_account: function(frm) {
new erpnext.integrations.plaidLink(frm);
enabled: function(frm) {
frm.toggle_reqd('plaid_client_id', frm.doc.enabled);
frm.toggle_reqd('plaid_secret', frm.doc.enabled);
frm.toggle_reqd('plaid_public_key', frm.doc.enabled);
frm.toggle_reqd('plaid_env', frm.doc.enabled);
},
refresh: function(frm) {
if(frm.doc.enabled) {
frm.add_custom_button('Link a new bank account', () => {
new erpnext.integrations.plaidLink(frm);
});
}
}
});
@ -19,20 +29,10 @@ erpnext.integrations.plaidLink = class plaidLink {
init_config() {
const me = this;
frappe.xcall('erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.plaid_configuration')
.then(result => {
if (result !== "disabled") {
if (result.plaid_env == undefined || result.plaid_public_key == undefined) {
frappe.throw(__("Please add valid Plaid api keys in site_config.json first"));
}
me.plaid_env = result.plaid_env;
me.plaid_public_key = result.plaid_public_key;
me.client_name = result.client_name;
me.init_plaid();
} else {
frappe.throw(__("Please save your document before adding a new account"));
}
});
me.plaid_env = me.frm.doc.plaid_env;
me.plaid_public_key = me.frm.doc.plaid_public_key;
me.client_name = frappe.boot.sitename;
me.init_plaid();
}
init_plaid() {
@ -104,4 +104,4 @@ erpnext.integrations.plaidLink = class plaidLink {
});
}, __("Select a company"), __("Continue"));
}
};
};

View File

@ -1,161 +1,96 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2018-10-25 10:02:48.656165",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"creation": "2018-10-25 10:02:48.656165",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"enabled",
"column_break_2",
"automatic_sync",
"section_break_4",
"plaid_client_id",
"plaid_secret",
"column_break_7",
"plaid_public_key",
"plaid_env"
],
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "enabled",
"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": "Enabled",
"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,
"translatable": 0,
"unique": 0
},
"default": "0",
"fieldname": "enabled",
"fieldtype": "Check",
"label": "Enabled"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.enabled==1",
"fieldname": "automatic_sync",
"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": "Synchronize all accounts every hour",
"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,
"translatable": 0,
"unique": 0
},
"default": "0",
"depends_on": "eval:doc.enabled==1",
"fieldname": "automatic_sync",
"fieldtype": "Check",
"label": "Synchronize all accounts every hour"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:(doc.enabled==1)&&(!doc.__islocal)",
"fieldname": "link_new_account",
"fieldtype": "Button",
"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": "Link a new bank account",
"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,
"translatable": 0,
"unique": 0
"depends_on": "eval:doc.enabled==1",
"fieldname": "plaid_client_id",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Plaid Client ID",
"reqd": 1
},
{
"depends_on": "eval:doc.enabled==1",
"fieldname": "plaid_secret",
"fieldtype": "Password",
"in_list_view": 1,
"label": "Plaid Secret",
"reqd": 1
},
{
"depends_on": "eval:doc.enabled==1",
"fieldname": "plaid_public_key",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Plaid Public Key",
"reqd": 1
},
{
"depends_on": "eval:doc.enabled==1",
"fieldname": "plaid_env",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Plaid Environment",
"reqd": 1
},
{
"fieldname": "column_break_2",
"fieldtype": "Column Break"
},
{
"fieldname": "section_break_4",
"fieldtype": "Section Break"
},
{
"fieldname": "column_break_7",
"fieldtype": "Column Break"
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 1,
"istable": 0,
"max_attachments": 0,
"modified": "2018-12-14 12:51:12.331395",
"modified_by": "Administrator",
"module": "ERPNext Integrations",
"name": "Plaid Settings",
"name_case": "",
"owner": "Administrator",
],
"issingle": 1,
"modified": "2019-08-13 17:00:06.939422",
"modified_by": "Administrator",
"module": "ERPNext Integrations",
"name": "Plaid Settings",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 0,
"role": "System Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"create": 1,
"delete": 1,
"email": 1,
"print": 1,
"read": 1,
"role": "System Manager",
"share": 1,
"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": 0,
"track_seen": 0,
"track_views": 0
],
"sort_field": "modified",
"sort_order": "DESC"
}

View File

@ -16,8 +16,13 @@ class PlaidSettings(Document):
@frappe.whitelist()
def plaid_configuration():
if frappe.db.get_value("Plaid Settings", None, "enabled") == "1":
return {"plaid_public_key": frappe.conf.get("plaid_public_key") or None, "plaid_env": frappe.conf.get("plaid_env") or None, "client_name": frappe.local.site }
if frappe.db.get_single_value("Plaid Settings", "enabled"):
plaid_settings = frappe.get_single("Plaid Settings")
return {
"plaid_public_key": plaid_settings.plaid_public_key,
"plaid_env": plaid_settings.plaid_env,
"client_name": frappe.local.site
}
else:
return "disabled"

View File

@ -1,5 +1,6 @@
import frappe
import requests
from frappe import _
# api/method/erpnext.erpnext_integrations.exotel_integration.handle_incoming_call
# api/method/erpnext.erpnext_integrations.exotel_integration.handle_end_call
@ -7,19 +8,24 @@ import requests
@frappe.whitelist(allow_guest=True)
def handle_incoming_call(**kwargs):
exotel_settings = get_exotel_settings()
if not exotel_settings.enabled: return
try:
exotel_settings = get_exotel_settings()
if not exotel_settings.enabled: return
call_payload = kwargs
status = call_payload.get('Status')
if status == 'free':
return
call_payload = kwargs
status = call_payload.get('Status')
if status == 'free':
return
call_log = get_call_log(call_payload)
if not call_log:
create_call_log(call_payload)
else:
update_call_log(call_payload, call_log=call_log)
call_log = get_call_log(call_payload)
if not call_log:
create_call_log(call_payload)
else:
update_call_log(call_payload, call_log=call_log)
except Exception as e:
frappe.db.rollback()
frappe.log_error(title=_('Error in Exotel incoming call'))
frappe.db.commit()
@frappe.whitelist(allow_guest=True)
def handle_end_call(**kwargs):
@ -101,4 +107,4 @@ def get_exotel_endpoint(action):
api_token=settings.api_token,
sid=settings.account_sid,
action=action
)
)

View File

@ -7,6 +7,7 @@
"doctype": "DocType",
"document_type": "Setup",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"basic_information",
"employee",
@ -54,6 +55,7 @@
"column_break_44",
"holiday_list",
"default_shift",
"leave_approver",
"salary_information",
"salary_mode",
"bank_name",
@ -169,6 +171,8 @@
"read_only": 1
},
{
"fetch_from": "user_id.user_image",
"fetch_if_empty": 1,
"fieldname": "image",
"fieldtype": "Attach Image",
"hidden": 1,
@ -767,12 +771,18 @@
"fieldtype": "Link",
"label": "Default Shift",
"options": "Shift Type"
},
{
"fieldname": "leave_approver",
"fieldtype": "Link",
"label": "Leave Approver",
"options": "User"
}
],
"icon": "fa fa-user",
"idx": 24,
"image_field": "image",
"modified": "2019-06-01 16:05:55.132180",
"modified": "2019-09-12 14:21:12.711280",
"modified_by": "Administrator",
"module": "HR",
"name": "Employee",

View File

@ -34,10 +34,11 @@ class LeaveAllocation(Document):
if max_leaves_allowed > 0:
leave_allocated = 0
if leave_period:
leave_allocated = get_leave_allocation_for_period(self.employee, self.leave_type, leave_period[0].from_date, leave_period[0].to_date)
leave_allocated = get_leave_allocation_for_period(self.employee, self.leave_type,
leave_period[0].from_date, leave_period[0].to_date)
leave_allocated += self.new_leaves_allocated
if leave_allocated > max_leaves_allowed:
frappe.throw(_("Total allocated leaves are more days than maximum allocation of {0} leave type for employee {1} in the period")\
frappe.throw(_("Total allocated leaves are more days than maximum allocation of {0} leave type for employee {1} in the period")
.format(self.leave_type, self.employee))
def on_submit(self):
@ -96,27 +97,31 @@ class LeaveAllocation(Document):
self.total_leaves_allocated = flt(self.unused_leaves) + flt(self.new_leaves_allocated)
self.limit_carry_forward_based_on_max_allowed_leaves()
if self.carry_forward:
self.maintain_carry_forwarded_leaves()
self.set_carry_forwarded_leaves_in_previous_allocation()
if not self.total_leaves_allocated and not frappe.db.get_value("Leave Type", self.leave_type, "is_earned_leave") and not frappe.db.get_value("Leave Type", self.leave_type, "is_compensatory"):
frappe.throw(_("Total leaves allocated is mandatory for Leave Type {0}").format(self.leave_type))
if not self.total_leaves_allocated \
and not frappe.db.get_value("Leave Type", self.leave_type, "is_earned_leave") \
and not frappe.db.get_value("Leave Type", self.leave_type, "is_compensatory"):
frappe.throw(_("Total leaves allocated is mandatory for Leave Type {0}")
.format(self.leave_type))
def maintain_carry_forwarded_leaves(self):
''' Reduce the carry forwarded leaves to be within the maximum allowed leaves '''
def limit_carry_forward_based_on_max_allowed_leaves(self):
max_leaves_allowed = frappe.db.get_value("Leave Type", self.leave_type, "max_leaves_allowed")
if self.new_leaves_allocated <= max_leaves_allowed <= self.total_leaves_allocated:
self.unused_leaves = max_leaves_allowed - flt(self.new_leaves_allocated)
if max_leaves_allowed and self.total_leaves_allocated > flt(max_leaves_allowed):
self.total_leaves_allocated = flt(max_leaves_allowed)
self.unused_leaves = max_leaves_allowed - flt(self.new_leaves_allocated)
def set_carry_forwarded_leaves_in_previous_allocation(self, on_cancel=False):
''' Set carry forwarded leaves in previous allocation '''
previous_allocation = get_previous_allocation(self.from_date, self.leave_type, self.employee)
if on_cancel:
self.unused_leaves = 0.0
frappe.db.set_value("Leave Allocation", previous_allocation.name, 'carry_forwarded_leaves_count', self.unused_leaves)
if previous_allocation:
frappe.db.set_value("Leave Allocation", previous_allocation.name,
'carry_forwarded_leaves_count', self.unused_leaves)
def validate_total_leaves_allocated(self):
# Adding a day to include To Date in the difference
@ -186,7 +191,13 @@ def get_carry_forwarded_leaves(employee, leave_type, date, carry_forward=None):
previous_allocation = get_previous_allocation(date, leave_type, employee)
if carry_forward and previous_allocation:
validate_carry_forward(leave_type)
unused_leaves = get_unused_leaves(employee, leave_type, previous_allocation.from_date, previous_allocation.to_date)
unused_leaves = get_unused_leaves(employee, leave_type,
previous_allocation.from_date, previous_allocation.to_date)
if unused_leaves:
max_carry_forwarded_leaves = frappe.db.get_value("Leave Type",
leave_type, "maximum_carry_forwarded_leaves")
if max_carry_forwarded_leaves and unused_leaves > flt(max_carry_forwarded_leaves):
unused_leaves = flt(max_carry_forwarded_leaves)
return unused_leaves

View File

@ -73,9 +73,11 @@ class TestLeaveAllocation(unittest.TestCase):
frappe.db.sql("delete from `tabLeave Allocation`")
frappe.db.sql("delete from `tabLeave Ledger Entry`")
leave_type = create_leave_type(leave_type_name="_Test_CF_leave", is_carry_forward=1)
leave_type.submit()
leave_type.maximum_carry_forwarded_leaves = 10
leave_type.max_leaves_allowed = 30
leave_type.save()
# initial leave allocation
# initial leave allocation = 15
leave_allocation = create_leave_allocation(
leave_type="_Test_CF_leave",
from_date=add_months(nowdate(), -12),
@ -83,13 +85,26 @@ class TestLeaveAllocation(unittest.TestCase):
carry_forward=0)
leave_allocation.submit()
# leave allocation with carry forward from previous allocation
# carry forwarded leaves considering maximum_carry_forwarded_leaves
# new_leaves = 15, carry_forwarded = 10
leave_allocation_1 = create_leave_allocation(
leave_type="_Test_CF_leave",
carry_forward=1)
leave_allocation_1.submit()
self.assertEquals(leave_allocation.total_leaves_allocated, leave_allocation_1.unused_leaves)
self.assertEquals(leave_allocation_1.unused_leaves, 10)
leave_allocation_1.cancel()
# carry forwarded leaves considering max_leave_allowed
# max_leave_allowed = 30, new_leaves = 25, carry_forwarded = 5
leave_allocation_2 = create_leave_allocation(
leave_type="_Test_CF_leave",
carry_forward=1,
new_leaves_allocated=25)
leave_allocation_2.submit()
self.assertEquals(leave_allocation_2.unused_leaves, 5)
def test_carry_forward_leaves_expiry(self):
frappe.db.sql("delete from `tabLeave Allocation`")
@ -98,7 +113,7 @@ class TestLeaveAllocation(unittest.TestCase):
leave_type_name="_Test_CF_leave_expiry",
is_carry_forward=1,
expire_carry_forwarded_leaves_after_days=90)
leave_type.submit()
leave_type.save()
# initial leave allocation
leave_allocation = create_leave_allocation(
@ -156,7 +171,7 @@ def create_leave_allocation(**args):
"employee_name": args.employee_name or employee.employee_name,
"leave_type": args.leave_type or "_Test Leave Type",
"from_date": args.from_date or nowdate(),
"new_leaves_allocated": args.new_leaves_created or 15,
"new_leaves_allocated": args.new_leaves_allocated or 15,
"carry_forward": args.carry_forward or 0,
"to_date": args.to_date or add_months(nowdate(), 12)
})

View File

@ -439,7 +439,7 @@ def get_leave_details(employee, date):
return ret
@frappe.whitelist()
def get_leave_balance_on(employee, leave_type, date, to_date=nowdate(), consider_all_leaves_in_the_allocation_period=False):
def get_leave_balance_on(employee, leave_type, date, to_date=None, consider_all_leaves_in_the_allocation_period=False):
'''
Returns leave balance till date
:param employee: employee name
@ -449,6 +449,9 @@ def get_leave_balance_on(employee, leave_type, date, to_date=nowdate(), consider
:param consider_all_leaves_in_the_allocation_period: consider all leaves taken till the allocation end date
'''
if not to_date:
to_date = nowdate()
allocation_records = get_leave_allocation_records(employee, date, leave_type)
allocation = allocation_records.get(leave_type, frappe._dict())
@ -745,10 +748,12 @@ def get_approved_leaves_for_period(employee, leave_type, from_date, to_date):
return leave_days
@frappe.whitelist()
def get_leave_approver(employee, department=None):
if not department:
department = frappe.db.get_value('Employee', employee, 'department')
def get_leave_approver(employee):
leave_approver, department = frappe.db.get_value("Employee",
employee, ["leave_approver", "department"])
if department:
return frappe.db.get_value('Department Approver', {'parent': department,
'parentfield': 'leave_approvers', 'idx': 1}, 'approver')
if not leave_approver and department:
leave_approver = frappe.db.get_value('Department Approver', {'parent': department,
'parentfield': 'leave_approvers', 'idx': 1}, 'approver')
return leave_approver

View File

@ -8,7 +8,6 @@ from frappe import _
from frappe.utils import getdate, cstr, add_days, date_diff, getdate, ceil
from frappe.model.document import Document
from erpnext.hr.utils import validate_overlap, get_employee_leave_policy
from erpnext.hr.doctype.leave_allocation.leave_allocation import get_carry_forwarded_leaves
from frappe.utils.background_jobs import enqueue
from six import iteritems

View File

@ -1,801 +1,214 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 1,
"allow_rename": 1,
"autoname": "field:leave_type_name",
"beta": 0,
"creation": "2013-02-21 09:55:58",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "Setup",
"editable_grid": 0,
"engine": "InnoDB",
"field_order": [
"leave_type_name",
"max_leaves_allowed",
"applicable_after",
"max_continuous_days_allowed",
"column_break_3",
"is_carry_forward",
"is_lwp",
"is_optional_leave",
"allow_negative",
"include_holiday",
"is_compensatory",
"carry_forward_section",
"maximum_carry_forwarded_leaves",
"expire_carry_forwarded_leaves_after_days",
"encashment",
"allow_encashment",
"encashment_threshold_days",
"earning_component",
"earned_leave",
"is_earned_leave",
"earned_leave_frequency",
"rounding"
],
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "leave_type_name",
"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": "Leave Type Name",
"length": 0,
"no_copy": 0,
"oldfieldname": "leave_type_name",
"oldfieldtype": "Data",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "max_leaves_allowed",
"fieldtype": "Int",
"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": "Max Leaves Allowed",
"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,
"translatable": 0,
"unique": 0
"label": "Max Leaves Allowed"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "applicable_after",
"fieldtype": "Int",
"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": "Applicable After (Working Days)",
"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,
"translatable": 0,
"unique": 0
"label": "Applicable After (Working Days)"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "max_continuous_days_allowed",
"fieldtype": "Int",
"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": "Maximum Continuous Days Applicable",
"length": 0,
"no_copy": 0,
"oldfieldname": "max_days_allowed",
"oldfieldtype": "Data",
"permlevel": 0,
"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,
"translatable": 0,
"unique": 0
"oldfieldtype": "Data"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_3",
"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,
"translatable": 0,
"unique": 0
"fieldtype": "Column Break"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"default": "0",
"fieldname": "is_carry_forward",
"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": "Is Carry Forward",
"length": 0,
"no_copy": 0,
"oldfieldname": "is_carry_forward",
"oldfieldtype": "Check",
"permlevel": 0,
"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,
"translatable": 0,
"unique": 0
"oldfieldtype": "Check"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"default": "0",
"fieldname": "is_lwp",
"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": "Is Leave Without Pay",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"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,
"translatable": 0,
"unique": 0
"label": "Is Leave Without Pay"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"default": "0",
"fieldname": "is_optional_leave",
"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": "Is Optional Leave",
"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,
"translatable": 0,
"unique": 0
"label": "Is Optional Leave"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"default": "0",
"fieldname": "allow_negative",
"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": "Allow Negative Balance",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"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,
"translatable": 0,
"unique": 0
"label": "Allow Negative Balance"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"default": "0",
"fieldname": "include_holiday",
"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": "Include holidays within leaves as leaves",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"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,
"translatable": 0,
"unique": 0
"label": "Include holidays within leaves as leaves"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"default": "0",
"fieldname": "is_compensatory",
"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": "Is Compensatory",
"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,
"translatable": 0,
"unique": 0
"label": "Is Compensatory"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
"columns": 0,
"depends_on": "eval: doc.is_carry_forward == 1",
"fetch_if_empty": 0,
"fieldname": "carry_forward_section",
"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": "Carry Forward",
"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,
"translatable": 0,
"unique": 0
"label": "Carry Forward"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "",
"description": "Calculated in days",
"fetch_if_empty": 0,
"fieldname": "expire_carry_forwarded_leaves_after_days",
"fieldtype": "Int",
"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": "Expire Carry Forwarded Leaves (Days)",
"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,
"translatable": 0,
"unique": 0
"label": "Expire Carry Forwarded Leaves (Days)"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "encashment",
"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": "Encashment",
"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,
"translatable": 0,
"unique": 0
"label": "Encashment"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"default": "0",
"fieldname": "allow_encashment",
"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": "Allow Encashment",
"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,
"translatable": 0,
"unique": 0
"label": "Allow Encashment"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "allow_encashment",
"fetch_if_empty": 0,
"fieldname": "encashment_threshold_days",
"fieldtype": "Int",
"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": "Encashment Threshold Days",
"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,
"translatable": 0,
"unique": 0
"label": "Encashment Threshold Days"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "allow_encashment",
"fetch_if_empty": 0,
"fieldname": "earning_component",
"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": "Earning Component",
"length": 0,
"no_copy": 0,
"options": "Salary Component",
"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,
"translatable": 0,
"unique": 0
"options": "Salary Component"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "earned_leave",
"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": "Earned Leave",
"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,
"translatable": 0,
"unique": 0
"label": "Earned Leave"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"default": "0",
"fieldname": "is_earned_leave",
"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": "Is Earned Leave",
"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,
"translatable": 0,
"unique": 0
"label": "Is Earned Leave"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "is_earned_leave",
"fetch_if_empty": 0,
"fieldname": "earned_leave_frequency",
"fieldtype": "Select",
"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": "Earned Leave Frequency",
"length": 0,
"no_copy": 0,
"options": "Monthly\nQuarterly\nHalf-Yearly\nYearly",
"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,
"translatable": 0,
"unique": 0
"options": "Monthly\nQuarterly\nHalf-Yearly\nYearly"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "0.5",
"depends_on": "is_earned_leave",
"fetch_if_empty": 0,
"fieldname": "rounding",
"fieldtype": "Select",
"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": "Rounding",
"length": 0,
"no_copy": 0,
"options": "0.5\n1.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,
"translatable": 0,
"unique": 0
"options": "0.5\n1.0"
},
{
"depends_on": "is_carry_forward",
"fieldname": "maximum_carry_forwarded_leaves",
"fieldtype": "Float",
"label": "Maximum Carry Forwarded Leaves"
}
],
"has_web_view": 0,
"hide_toolbar": 0,
"icon": "fa fa-flag",
"idx": 1,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2019-08-02 15:38:39.334283",
"modified": "2019-09-06 18:48:48.946074",
"modified_by": "Administrator",
"module": "HR",
"name": "Leave Type",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "HR User",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
},
{
"amend": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 0,
"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
},
{
"amend": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 0,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 0,
"read": 1,
"report": 0,
"role": "Employee",
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"write": 0
"role": "Employee"
}
],
"quick_entry": 0,
"read_only": 0,
"show_name_in_global_search": 0,
"track_changes": 0,
"track_seen": 0,
"track_views": 0
"sort_field": "modified",
"sort_order": "DESC"
}

View File

@ -8,6 +8,8 @@ from frappe.utils import flt
from erpnext.hr.doctype.leave_application.leave_application \
import get_leave_balance_on, get_leaves_for_period
from erpnext.hr.report.employee_leave_balance_summary.employee_leave_balance_summary \
import get_department_leave_approver_map
def execute(filters=None):
leave_types = frappe.db.sql_list("select name from `tabLeave Type` order by name asc")
@ -19,7 +21,7 @@ def execute(filters=None):
def get_columns(leave_types):
columns = [
_("Employee") + ":Link/Employee:150",
_("Employee") + ":Link.Employee:150",
_("Employee Name") + "::200",
_("Department") +"::150"
]
@ -52,11 +54,13 @@ def get_data(filters, leave_types):
active_employees = frappe.get_all("Employee",
filters=conditions,
fields=["name", "employee_name", "department", "user_id"])
fields=["name", "employee_name", "department", "user_id", "leave_approver"])
department_approver_map = get_department_leave_approver_map(filters.get('department'))
data = []
for employee in active_employees:
leave_approvers = get_approvers(employee.department)
leave_approvers = department_approver_map.get(employee.department_name, []).append(employee.leave_approver)
if (len(leave_approvers) and user in leave_approvers) or (user in ["Administrator", employee.user_id]) or ("HR Manager" in frappe.get_roles(user)):
row = [employee.name, employee.employee_name, employee.department]
@ -66,46 +70,13 @@ def get_data(filters, leave_types):
filters.from_date, filters.to_date) * -1
# opening balance
opening = get_total_allocated_leaves(employee.name, leave_type, filters.from_date, filters.to_date)
opening = get_leave_balance_on(employee.name, leave_type, filters.from_date)
# closing balance
closing = flt(opening) - flt(leaves_taken)
closing = get_leave_balance_on(employee.name, leave_type, filters.to_date)
row += [opening, leaves_taken, closing]
data.append(row)
return data
def get_approvers(department):
if not department:
return []
approvers = []
# get current department and all its child
department_details = frappe.db.get_value("Department", {"name": department}, ["lft", "rgt"], as_dict=True)
department_list = frappe.db.sql("""select name from `tabDepartment`
where lft >= %s and rgt <= %s order by lft desc
""", (department_details.lft, department_details.rgt), as_list = True)
# retrieve approvers list from current department and from its subsequent child departments
for d in department_list:
approvers.extend([l.leave_approver for l in frappe.db.sql("""select approver from `tabDepartment Approver` \
where parent = %s and parentfield = 'leave_approvers'""", (d), as_dict=True)])
return approvers
def get_total_allocated_leaves(employee, leave_type, from_date, to_date):
''' Returns leave allocation between from date and to date '''
leave_allocation_records = frappe.db.get_all('Leave Ledger Entry', filters={
'docstatus': 1,
'is_expired': 0,
'leave_type': leave_type,
'employee': employee,
'transaction_type': 'Leave Allocation'
}, or_filters={
'from_date': ['between', (from_date, to_date)],
'to_date': ['between', (from_date, to_date)]
}, fields=['SUM(leaves) as leaves'])
return flt(leave_allocation_records[0].get('leaves')) if leave_allocation_records else flt(0)
return data

View File

@ -0,0 +1,42 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
/* eslint-disable */
frappe.query_reports['Employee Leave Balance Summary'] = {
filters: [
{
fieldname:'from_date',
label: __('From Date'),
fieldtype: 'Date',
reqd: 1,
default: frappe.defaults.get_default('year_start_date')
},
{
fieldname:'to_date',
label: __('To Date'),
fieldtype: 'Date',
reqd: 1,
default: frappe.defaults.get_default('year_end_date')
},
{
fieldname:'company',
label: __('Company'),
fieldtype: 'Link',
options: 'Company',
reqd: 1,
default: frappe.defaults.get_user_default('Company')
},
{
fieldname:'employee',
label: __('Employee'),
fieldtype: 'Link',
options: 'Employee',
},
{
fieldname:'department',
label: __('Department'),
fieldtype: 'Link',
options: 'Department',
}
]
};

View File

@ -0,0 +1,34 @@
{
"add_total_row": 0,
"creation": "2019-09-05 11:18:06.209397",
"disable_prepared_report": 0,
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 0,
"is_standard": "Yes",
"letter_head": "sapcon-old",
"modified": "2019-09-05 11:18:06.209397",
"modified_by": "Administrator",
"module": "HR",
"name": "Employee Leave Balance Summary",
"owner": "Administrator",
"prepared_report": 0,
"ref_doctype": "Employee",
"report_name": "Employee Leave Balance Summary",
"report_type": "Script Report",
"roles": [
{
"role": "Employee"
},
{
"role": "HR Manager"
},
{
"role": "HR User"
},
{
"role": "Leave Approver"
}
]
}

View File

@ -0,0 +1,130 @@
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe.utils import flt
from frappe import _
from erpnext.hr.doctype.leave_application.leave_application import get_leaves_for_period, get_leave_balance_on
def execute(filters=None):
if filters.to_date <= filters.from_date:
frappe.throw(_('From date can not be greater than than To date'))
columns = get_columns()
data = get_data(filters)
return columns, data
def get_columns():
columns = [{
'label': _('Leave Type'),
'fieldtype': 'Link',
'fieldname': 'leave_type',
'width': 300,
'options': 'Leave Type'
}, {
'label': _('Employee'),
'fieldtype': 'Link',
'fieldname': 'employee',
'width': 100,
'options': 'Employee'
}, {
'label': _('Employee Name'),
'fieldtype': 'Data',
'fieldname': 'employee_name',
'width': 100,
}, {
'label': _('Opening Balance'),
'fieldtype': 'float',
'fieldname': 'opening_balance',
'width': 160,
}, {
'label': _('Leaves Taken'),
'fieldtype': 'float',
'fieldname': 'leaves_taken',
'width': 160,
}, {
'label': _('Closing Balance'),
'fieldtype': 'float',
'fieldname': 'closing_balance',
'width': 160,
}]
return columns
def get_data(filters):
leave_types = frappe.db.sql_list("SELECT `name` FROM `tabLeave Type` ORDER BY `name` ASC")
conditions = get_conditions(filters)
user = frappe.session.user
department_approver_map = get_department_leave_approver_map(filters.get('department'))
active_employees = frappe.get_list('Employee',
filters=conditions,
fields=['name', 'employee_name', 'department', 'user_id', 'leave_approver'])
data = []
for leave_type in leave_types:
data.append({
'leave_type': leave_type
})
for employee in active_employees:
leave_approvers = department_approver_map.get(employee.department_name, []).append(employee.leave_approver)
if (len(leave_approvers) and user in leave_approvers) or (user in ["Administrator", employee.user_id]) \
or ("HR Manager" in frappe.get_roles(user)):
row = frappe._dict({
'employee': employee.name,
'employee_name': employee.employee_name
})
leaves_taken = get_leaves_for_period(employee.name, leave_type,
filters.from_date, filters.to_date) * -1
opening = get_leave_balance_on(employee.name, leave_type, filters.from_date)
closing = get_leave_balance_on(employee.name, leave_type, filters.to_date)
row.opening_balance = opening
row.leaves_taken = leaves_taken
row.closing_balance = closing
row.indent = 1
data.append(row)
return data
def get_conditions(filters):
conditions={
'status': 'Active',
}
if filters.get('employee'):
conditions['name'] = filters.get('employee')
if filters.get('employee'):
conditions['name'] = filters.get('employee')
return conditions
def get_department_leave_approver_map(department=None):
conditions=''
if department:
conditions='and department_name = %(department)s or parent_department = %(department)s'%{'department': department}
# get current department and all its child
department_list = frappe.db.sql_list(''' SELECT name FROM `tabDepartment` WHERE disabled=0 {0}'''.format(conditions)) #nosec
# retrieve approvers list from current department and from its subsequent child departments
approver_list = frappe.get_all('Department Approver', filters={
'parentfield': 'leave_approvers',
'parent': ('in', department_list)
}, fields=['parent', 'approver'], as_list=1)
approvers = {}
for k, v in approver_list:
approvers.setdefault(k, []).append(v)
return approvers

View File

@ -648,7 +648,7 @@ def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_ite
item_dict[item.item_code] = item
for item, item_details in item_dict.items():
for d in [["Account", "expense_account", "default_expense_account"],
for d in [["Account", "expense_account", "stock_adjustment_account"],
["Cost Center", "cost_center", "cost_center"], ["Warehouse", "default_warehouse", ""]]:
company_in_record = frappe.db.get_value(d[0], item_details.get(d[1]), "company")
if not item_details.get(d[1]) or (company_in_record and company != company_in_record):
@ -716,6 +716,8 @@ def get_children(doctype, parent=None, is_root=False, **filters):
next(item for item in items if item.get('name')
== bom_item.get('item_code'))
)
bom_item.parent_bom_qty = bom_doc.quantity
bom_item.expandable = 0 if bom_item.value in ('', None) else 1
return bom_items

View File

@ -272,11 +272,12 @@ frappe.ui.form.on("Production Plan Item", {
frappe.ui.form.on("Material Request Plan Item", {
warehouse: function(frm, cdt, cdn) {
const row = locals[cdt][cdn];
if (row.warehouse && row.item_code) {
if (row.warehouse && row.item_code && frm.doc.company) {
frappe.call({
method: "erpnext.manufacturing.doctype.production_plan.production_plan.get_bin_details",
args: {
row: row,
company: frm.doc.company,
for_warehouse: row.warehouse
},
callback: function(r) {

View File

@ -301,7 +301,6 @@ class ProductionPlan(Document):
wo_list.extend(work_orders)
frappe.flags.mute_messages = False
if wo_list:
wo_list = ["""<a href="#Form/Work Order/%s" target="_blank">%s</a>""" % \
(p, p) for p in wo_list]
@ -309,15 +308,16 @@ class ProductionPlan(Document):
else :
msgprint(_("No Work Orders created"))
def make_work_order_for_sub_assembly_items(self, item):
work_orders = []
bom_data = {}
get_sub_assembly_items(item.get("bom_no"), bom_data)
get_sub_assembly_items(item.get("bom_no"), bom_data, item.get("qty"))
for key, data in bom_data.items():
data.update({
'qty': data.get("stock_qty") * item.get("qty"),
'qty': data.get("stock_qty"),
'production_plan': self.name,
'company': self.company,
'fg_warehouse': item.get("fg_warehouse"),
@ -708,7 +708,7 @@ def get_item_data(item_code):
"description": item_details.get("description")
}
def get_sub_assembly_items(bom_no, bom_data):
def get_sub_assembly_items(bom_no, bom_data, qty):
data = get_children('BOM', parent = bom_no)
for d in data:
if d.expandable:
@ -725,6 +725,6 @@ def get_sub_assembly_items(bom_no, bom_data):
})
bom_item = bom_data.get(key)
bom_item["stock_qty"] += d.stock_qty
bom_item["stock_qty"] += ((d.stock_qty * qty) / d.parent_bom_qty)
get_sub_assembly_items(bom_item.get("bom_no"), bom_data)
get_sub_assembly_items(bom_item.get("bom_no"), bom_data, bom_item["stock_qty"])

View File

@ -625,6 +625,7 @@ erpnext.patches.v12_0.add_default_buying_selling_terms_in_company
erpnext.patches.v12_0.update_ewaybill_field_position
erpnext.patches.v12_0.create_accounting_dimensions_in_missing_doctypes
erpnext.patches.v11_1.set_status_for_material_request_type_manufacture
erpnext.patches.v12_0.move_plaid_settings_to_doctype
execute:frappe.reload_doc('desk', 'doctype','dashboard_chart_link')
execute:frappe.reload_doc('desk', 'doctype','dashboard')
execute:frappe.reload_doc('desk', 'doctype','dashboard_chart_source')
@ -632,4 +633,6 @@ execute:frappe.reload_doc('desk', 'doctype','dashboard_chart')
erpnext.patches.v12_0.add_default_dashboards
erpnext.patches.v12_0.remove_bank_remittance_custom_fields
erpnext.patches.v12_0.generate_leave_ledger_entries
erpnext.patches.v12_0.move_credit_limit_to_customer_credit_limit
erpnext.patches.v12_0.move_credit_limit_to_customer_credit_limit
erpnext.patches.v12_0.add_variant_of_in_item_attribute_table
erpnext.patches.v12_0.create_default_energy_point_rules

View File

@ -1,8 +1,9 @@
import frappe
def execute():
frappe.db.sql('''
UPDATE `tabItem Variant Attribute` t1
INNER JOIN `tabItem` t2 ON t2.name = t1.parent
SET t1.variant_of = t2.variant_of
''')
frappe.reload_doc('stock', 'doctype', 'item_variant_attribute')
frappe.db.sql('''
UPDATE `tabItem Variant Attribute` t1
INNER JOIN `tabItem` t2 ON t2.name = t1.parent
SET t1.variant_of = t2.variant_of
''')

View File

@ -0,0 +1,6 @@
import frappe
from erpnext.setup.install import create_default_energy_point_rules
def execute():
frappe.reload_doc('social', 'doctype', 'energy_point_rule')
create_default_energy_point_rules()

View File

@ -0,0 +1,22 @@
# Copyright (c) 2017, Frappe and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
def execute():
frappe.reload_doc("erpnext_integrations", "doctype", "plaid_settings")
plaid_settings = frappe.get_single("Plaid Settings")
if plaid_settings.enabled:
if not (frappe.conf.plaid_client_id and frappe.conf.plaid_env \
and frappe.conf.plaid_public_key and frappe.conf.plaid_secret):
plaid_settings.enabled = 0
else:
plaid_settings.update({
"plaid_client_id": frappe.conf.plaid_client_id,
"plaid_public_key": frappe.conf.plaid_public_key,
"plaid_env": frappe.conf.plaid_env,
"plaid_secret": frappe.conf.plaid_secret
})
plaid_settings.flags.ignore_mandatory = True
plaid_settings.save()

View File

@ -1,381 +1,391 @@
{
"allow_import": 1,
"autoname": "TASK-.YYYY.-.#####",
"creation": "2013-01-29 19:25:50",
"doctype": "DocType",
"document_type": "Setup",
"field_order": [
"subject",
"project",
"issue",
"type",
"is_group",
"column_break0",
"status",
"priority",
"task_weight",
"color",
"parent_task",
"sb_timeline",
"exp_start_date",
"expected_time",
"column_break_11",
"exp_end_date",
"progress",
"is_milestone",
"sb_details",
"description",
"sb_depends_on",
"depends_on",
"depends_on_tasks",
"sb_actual",
"act_start_date",
"actual_time",
"column_break_15",
"act_end_date",
"sb_costing",
"total_costing_amount",
"total_expense_claim",
"column_break_20",
"total_billing_amount",
"sb_more_info",
"review_date",
"closing_date",
"column_break_22",
"department",
"company",
"lft",
"rgt",
"old_parent"
],
"fields": [
{
"fieldname": "subject",
"fieldtype": "Data",
"in_global_search": 1,
"label": "Subject",
"reqd": 1,
"search_index": 1,
"in_standard_filter": 1
},
{
"bold": 1,
"fieldname": "project",
"fieldtype": "Link",
"in_global_search": 1,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Project",
"oldfieldname": "project",
"oldfieldtype": "Link",
"options": "Project",
"remember_last_selected_value": 1,
"search_index": 1
},
{
"fieldname": "issue",
"fieldtype": "Link",
"label": "Issue",
"options": "Issue"
},
{
"fieldname": "type",
"fieldtype": "Link",
"label": "Type",
"options": "Task Type"
},
{
"bold": 1,
"default": "0",
"fieldname": "is_group",
"fieldtype": "Check",
"in_list_view": 1,
"label": "Is Group"
},
{
"fieldname": "column_break0",
"fieldtype": "Column Break",
"oldfieldtype": "Column Break",
"print_width": "50%",
"width": "50%"
},
{
"bold": 1,
"fieldname": "status",
"fieldtype": "Select",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Status",
"no_copy": 1,
"oldfieldname": "status",
"oldfieldtype": "Select",
"options": "Open\nWorking\nPending Review\nOverdue\nCompleted\nCancelled"
},
{
"fieldname": "priority",
"fieldtype": "Select",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Priority",
"oldfieldname": "priority",
"oldfieldtype": "Select",
"options": "Low\nMedium\nHigh\nUrgent",
"search_index": 1
},
{
"fieldname": "color",
"fieldtype": "Color",
"label": "Color"
},
{
"bold": 1,
"fieldname": "parent_task",
"fieldtype": "Link",
"ignore_user_permissions": 1,
"label": "Parent Task",
"options": "Task",
"search_index": 1
},
{
"collapsible": 1,
"collapsible_depends_on": "eval:doc.__islocal",
"fieldname": "sb_timeline",
"fieldtype": "Section Break",
"label": "Timeline"
},
{
"fieldname": "exp_start_date",
"fieldtype": "Date",
"label": "Expected Start Date",
"oldfieldname": "exp_start_date",
"oldfieldtype": "Date"
},
{
"default": "0",
"fieldname": "expected_time",
"fieldtype": "Float",
"label": "Expected Time (in hours)",
"oldfieldname": "exp_total_hrs",
"oldfieldtype": "Data"
},
{
"fetch_from": "type.weight",
"fieldname": "task_weight",
"fieldtype": "Float",
"label": "Weight"
},
{
"fieldname": "column_break_11",
"fieldtype": "Column Break"
},
{
"bold": 1,
"fieldname": "exp_end_date",
"fieldtype": "Date",
"label": "Expected End Date",
"oldfieldname": "exp_end_date",
"oldfieldtype": "Date",
"search_index": 1
},
{
"fieldname": "progress",
"fieldtype": "Percent",
"label": "% Progress"
},
{
"fieldname": "is_milestone",
"fieldtype": "Check",
"in_list_view": 1,
"label": "Is Milestone"
},
{
"fieldname": "sb_details",
"fieldtype": "Section Break",
"label": "Details",
"oldfieldtype": "Section Break"
},
{
"fieldname": "description",
"fieldtype": "Text Editor",
"in_preview": 1,
"label": "Task Description",
"oldfieldname": "description",
"oldfieldtype": "Text Editor",
"print_width": "300px",
"width": "300px"
},
{
"fieldname": "sb_depends_on",
"fieldtype": "Section Break",
"label": "Dependencies",
"oldfieldtype": "Section Break"
},
{
"fieldname": "depends_on",
"fieldtype": "Table",
"label": "Dependent Tasks",
"options": "Task Depends On"
},
{
"fieldname": "depends_on_tasks",
"fieldtype": "Code",
"hidden": 1,
"label": "Depends on Tasks",
"read_only": 1
},
{
"fieldname": "sb_actual",
"fieldtype": "Section Break",
"oldfieldtype": "Column Break",
"print_width": "50%",
"width": "50%"
},
{
"fieldname": "act_start_date",
"fieldtype": "Date",
"label": "Actual Start Date (via Time Sheet)",
"oldfieldname": "act_start_date",
"oldfieldtype": "Date",
"read_only": 1
},
{
"fieldname": "actual_time",
"fieldtype": "Float",
"label": "Actual Time (in hours)",
"read_only": 1
},
{
"fieldname": "column_break_15",
"fieldtype": "Column Break"
},
{
"fieldname": "act_end_date",
"fieldtype": "Date",
"label": "Actual End Date (via Time Sheet)",
"oldfieldname": "act_end_date",
"oldfieldtype": "Date",
"read_only": 1
},
{
"collapsible": 1,
"fieldname": "sb_costing",
"fieldtype": "Section Break",
"label": "Costing"
},
{
"fieldname": "total_costing_amount",
"fieldtype": "Currency",
"label": "Total Costing Amount (via Time Sheet)",
"oldfieldname": "actual_budget",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"read_only": 1
},
{
"fieldname": "total_expense_claim",
"fieldtype": "Currency",
"label": "Total Expense Claim (via Expense Claim)",
"options": "Company:company:default_currency",
"read_only": 1
},
{
"fieldname": "column_break_20",
"fieldtype": "Column Break"
},
{
"fieldname": "total_billing_amount",
"fieldtype": "Currency",
"label": "Total Billing Amount (via Time Sheet)",
"read_only": 1
},
{
"collapsible": 1,
"fieldname": "sb_more_info",
"fieldtype": "Section Break",
"label": "More Info"
},
{
"depends_on": "eval:doc.status == \"Closed\" || doc.status == \"Pending Review\"",
"fieldname": "review_date",
"fieldtype": "Date",
"label": "Review Date",
"oldfieldname": "review_date",
"oldfieldtype": "Date"
},
{
"depends_on": "eval:doc.status == \"Closed\"",
"fieldname": "closing_date",
"fieldtype": "Date",
"label": "Closing Date",
"oldfieldname": "closing_date",
"oldfieldtype": "Date"
},
{
"fieldname": "column_break_22",
"fieldtype": "Column Break"
},
{
"fieldname": "department",
"fieldtype": "Link",
"label": "Department",
"options": "Department"
},
{
"fieldname": "company",
"fieldtype": "Link",
"label": "Company",
"options": "Company",
"remember_last_selected_value": 1
},
{
"fieldname": "lft",
"fieldtype": "Int",
"hidden": 1,
"label": "lft",
"read_only": 1
},
{
"fieldname": "rgt",
"fieldtype": "Int",
"hidden": 1,
"label": "rgt",
"read_only": 1
},
{
"fieldname": "old_parent",
"fieldtype": "Data",
"hidden": 1,
"ignore_user_permissions": 1,
"label": "Old Parent",
"read_only": 1
}
],
"icon": "fa fa-check",
"idx": 1,
"max_attachments": 5,
"modified": "2019-06-19 09:51:15.599416",
"modified_by": "Administrator",
"module": "Projects",
"name": "Task",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Projects User",
"share": 1,
"write": 1
}
],
"search_fields": "subject",
"show_name_in_global_search": 1,
"show_preview_popup": 1,
"sort_order": "DESC",
"timeline_field": "project",
"title_field": "subject",
"track_seen": 1
}
"allow_import": 1,
"autoname": "TASK-.YYYY.-.#####",
"creation": "2013-01-29 19:25:50",
"doctype": "DocType",
"document_type": "Setup",
"engine": "InnoDB",
"field_order": [
"subject",
"project",
"issue",
"type",
"is_group",
"column_break0",
"status",
"priority",
"task_weight",
"completed_by",
"color",
"parent_task",
"sb_timeline",
"exp_start_date",
"expected_time",
"column_break_11",
"exp_end_date",
"progress",
"is_milestone",
"sb_details",
"description",
"sb_depends_on",
"depends_on",
"depends_on_tasks",
"sb_actual",
"act_start_date",
"actual_time",
"column_break_15",
"act_end_date",
"sb_costing",
"total_costing_amount",
"total_expense_claim",
"column_break_20",
"total_billing_amount",
"sb_more_info",
"review_date",
"closing_date",
"column_break_22",
"department",
"company",
"lft",
"rgt",
"old_parent"
],
"fields": [
{
"fieldname": "subject",
"fieldtype": "Data",
"in_global_search": 1,
"in_standard_filter": 1,
"label": "Subject",
"reqd": 1,
"search_index": 1
},
{
"bold": 1,
"fieldname": "project",
"fieldtype": "Link",
"in_global_search": 1,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Project",
"oldfieldname": "project",
"oldfieldtype": "Link",
"options": "Project",
"remember_last_selected_value": 1,
"search_index": 1
},
{
"fieldname": "issue",
"fieldtype": "Link",
"label": "Issue",
"options": "Issue"
},
{
"fieldname": "type",
"fieldtype": "Link",
"label": "Type",
"options": "Task Type"
},
{
"bold": 1,
"default": "0",
"fieldname": "is_group",
"fieldtype": "Check",
"in_list_view": 1,
"label": "Is Group"
},
{
"fieldname": "column_break0",
"fieldtype": "Column Break",
"oldfieldtype": "Column Break",
"print_width": "50%",
"width": "50%"
},
{
"bold": 1,
"fieldname": "status",
"fieldtype": "Select",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Status",
"no_copy": 1,
"oldfieldname": "status",
"oldfieldtype": "Select",
"options": "Open\nWorking\nPending Review\nOverdue\nCompleted\nCancelled"
},
{
"fieldname": "priority",
"fieldtype": "Select",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Priority",
"oldfieldname": "priority",
"oldfieldtype": "Select",
"options": "Low\nMedium\nHigh\nUrgent",
"search_index": 1
},
{
"fieldname": "color",
"fieldtype": "Color",
"label": "Color"
},
{
"bold": 1,
"fieldname": "parent_task",
"fieldtype": "Link",
"ignore_user_permissions": 1,
"label": "Parent Task",
"options": "Task",
"search_index": 1
},
{
"collapsible": 1,
"collapsible_depends_on": "eval:doc.__islocal",
"fieldname": "sb_timeline",
"fieldtype": "Section Break",
"label": "Timeline"
},
{
"fieldname": "exp_start_date",
"fieldtype": "Date",
"label": "Expected Start Date",
"oldfieldname": "exp_start_date",
"oldfieldtype": "Date"
},
{
"default": "0",
"fieldname": "expected_time",
"fieldtype": "Float",
"label": "Expected Time (in hours)",
"oldfieldname": "exp_total_hrs",
"oldfieldtype": "Data"
},
{
"fetch_from": "type.weight",
"fieldname": "task_weight",
"fieldtype": "Float",
"label": "Weight"
},
{
"fieldname": "column_break_11",
"fieldtype": "Column Break"
},
{
"bold": 1,
"fieldname": "exp_end_date",
"fieldtype": "Date",
"label": "Expected End Date",
"oldfieldname": "exp_end_date",
"oldfieldtype": "Date",
"search_index": 1
},
{
"fieldname": "progress",
"fieldtype": "Percent",
"label": "% Progress"
},
{
"default": "0",
"fieldname": "is_milestone",
"fieldtype": "Check",
"in_list_view": 1,
"label": "Is Milestone"
},
{
"fieldname": "sb_details",
"fieldtype": "Section Break",
"label": "Details",
"oldfieldtype": "Section Break"
},
{
"fieldname": "description",
"fieldtype": "Text Editor",
"in_preview": 1,
"label": "Task Description",
"oldfieldname": "description",
"oldfieldtype": "Text Editor",
"print_width": "300px",
"width": "300px"
},
{
"fieldname": "sb_depends_on",
"fieldtype": "Section Break",
"label": "Dependencies",
"oldfieldtype": "Section Break"
},
{
"fieldname": "depends_on",
"fieldtype": "Table",
"label": "Dependent Tasks",
"options": "Task Depends On"
},
{
"fieldname": "depends_on_tasks",
"fieldtype": "Code",
"hidden": 1,
"label": "Depends on Tasks",
"read_only": 1
},
{
"fieldname": "sb_actual",
"fieldtype": "Section Break",
"oldfieldtype": "Column Break",
"print_width": "50%",
"width": "50%"
},
{
"fieldname": "act_start_date",
"fieldtype": "Date",
"label": "Actual Start Date (via Time Sheet)",
"oldfieldname": "act_start_date",
"oldfieldtype": "Date",
"read_only": 1
},
{
"fieldname": "actual_time",
"fieldtype": "Float",
"label": "Actual Time (in hours)",
"read_only": 1
},
{
"fieldname": "column_break_15",
"fieldtype": "Column Break"
},
{
"fieldname": "act_end_date",
"fieldtype": "Date",
"label": "Actual End Date (via Time Sheet)",
"oldfieldname": "act_end_date",
"oldfieldtype": "Date",
"read_only": 1
},
{
"collapsible": 1,
"fieldname": "sb_costing",
"fieldtype": "Section Break",
"label": "Costing"
},
{
"fieldname": "total_costing_amount",
"fieldtype": "Currency",
"label": "Total Costing Amount (via Time Sheet)",
"oldfieldname": "actual_budget",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"read_only": 1
},
{
"fieldname": "total_expense_claim",
"fieldtype": "Currency",
"label": "Total Expense Claim (via Expense Claim)",
"options": "Company:company:default_currency",
"read_only": 1
},
{
"fieldname": "column_break_20",
"fieldtype": "Column Break"
},
{
"fieldname": "total_billing_amount",
"fieldtype": "Currency",
"label": "Total Billing Amount (via Time Sheet)",
"read_only": 1
},
{
"collapsible": 1,
"fieldname": "sb_more_info",
"fieldtype": "Section Break",
"label": "More Info"
},
{
"depends_on": "eval:doc.status == \"Closed\" || doc.status == \"Pending Review\"",
"fieldname": "review_date",
"fieldtype": "Date",
"label": "Review Date",
"oldfieldname": "review_date",
"oldfieldtype": "Date"
},
{
"depends_on": "eval:doc.status == \"Closed\"",
"fieldname": "closing_date",
"fieldtype": "Date",
"label": "Closing Date",
"oldfieldname": "closing_date",
"oldfieldtype": "Date"
},
{
"fieldname": "column_break_22",
"fieldtype": "Column Break"
},
{
"fieldname": "department",
"fieldtype": "Link",
"label": "Department",
"options": "Department"
},
{
"fieldname": "company",
"fieldtype": "Link",
"label": "Company",
"options": "Company",
"remember_last_selected_value": 1
},
{
"fieldname": "lft",
"fieldtype": "Int",
"hidden": 1,
"label": "lft",
"read_only": 1
},
{
"fieldname": "rgt",
"fieldtype": "Int",
"hidden": 1,
"label": "rgt",
"read_only": 1
},
{
"fieldname": "old_parent",
"fieldtype": "Data",
"hidden": 1,
"ignore_user_permissions": 1,
"label": "Old Parent",
"read_only": 1
},
{
"fieldname": "completed_by",
"fieldtype": "Link",
"label": "Completed By",
"options": "User"
}
],
"icon": "fa fa-check",
"idx": 1,
"max_attachments": 5,
"modified": "2019-09-10 13:46:24.631754",
"modified_by": "Administrator",
"module": "Projects",
"name": "Task",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Projects User",
"share": 1,
"write": 1
}
],
"search_fields": "subject",
"show_name_in_global_search": 1,
"show_preview_popup": 1,
"sort_field": "modified",
"sort_order": "DESC",
"timeline_field": "project",
"title_field": "subject",
"track_seen": 1
}

View File

@ -9,7 +9,7 @@ import frappe
from frappe import _, throw
from frappe.utils import add_days, cstr, date_diff, get_link_to_form, getdate
from frappe.utils.nestedset import NestedSet
from frappe.desk.form.assign_to import close_all_assignments, clear
class CircularReferenceError(frappe.ValidationError): pass
class EndDateCannotBeGreaterThanProjectEndDateError(frappe.ValidationError): pass
@ -45,8 +45,7 @@ class Task(NestedSet):
if frappe.db.get_value("Task", d.task, "status") != "Completed":
frappe.throw(_("Cannot close task {0} as its dependant task {1} is not closed.").format(frappe.bold(self.name), frappe.bold(d.task)))
from frappe.desk.form.assign_to import clear
clear(self.doctype, self.name)
close_all_assignments(self.doctype, self.name)
def validate_progress(self):
if (self.progress or 0) > 100:
@ -77,8 +76,9 @@ class Task(NestedSet):
self.populate_depends_on()
def unassign_todo(self):
if self.status in ("Completed", "Cancelled"):
from frappe.desk.form.assign_to import clear
if self.status == "Completed":
close_all_assignments(self.doctype, self.name)
if self.status == "Cancelled":
clear(self.doctype, self.name)
def update_total_expense_claim(self):

View File

@ -28,12 +28,12 @@ class CallPopup {
'depends_on': () => this.call_log.lead
}, {
'fieldtype': 'Button',
'label': __('Make New Contact'),
'label': __('Create New Contact'),
'click': () => frappe.new_doc('Contact', { 'mobile_no': this.caller_number }),
'depends_on': () => !this.get_caller_name()
}, {
'fieldtype': 'Button',
'label': __('Make New Lead'),
'label': __('Create New Lead'),
'click': () => frappe.new_doc('Lead', { 'mobile_no': this.caller_number }),
'depends_on': () => !this.get_caller_name()
}, {

View File

@ -293,7 +293,7 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
items: my_items
},
callback: function(r) {
if(!r.message) {
if(!r.message || r.message.length == 0) {
frappe.throw(__("No pending Material Requests found to link for the given items."))
}
else {

View File

@ -44,6 +44,12 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
this.calculate_contribution();
}
// Update paid amount on return/debit note creation
if(this.frm.doc.doctype === "Purchase Invoice" && this.frm.doc.is_return
&& (this.frm.doc.grand_total > this.frm.doc.paid_amount)) {
this.frm.doc.paid_amount = flt(this.frm.doc.grand_total, precision("grand_total"));
}
this.frm.refresh_fields();
},

View File

@ -277,8 +277,30 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
this.set_dynamic_labels();
this.setup_sms();
this.setup_quality_inspection();
this.frm.fields_dict["scan_barcode"] && this.frm.fields_dict["scan_barcode"].set_value("");
this.frm.fields_dict["scan_barcode"] && this.frm.fields_dict["scan_barcode"].set_new_description("");
let scan_barcode_field = this.frm.get_field('scan_barcode');
if (scan_barcode_field) {
scan_barcode_field.set_value("");
scan_barcode_field.set_new_description("");
if (frappe.is_mobile()) {
if (scan_barcode_field.$input_wrapper.find('.input-group').length) return;
let $input_group = $('<div class="input-group">');
scan_barcode_field.$input_wrapper.find('.control-input').append($input_group);
$input_group.append(scan_barcode_field.$input);
$(`<span class="input-group-btn" style="vertical-align: top">
<button class="btn btn-default border" type="button">
<i class="fa fa-camera text-muted"></i>
</button>
</span>`)
.on('click', '.btn', () => {
frappe.barcode.scan_barcode().then(barcode => {
scan_barcode_field.set_value(barcode);
});
})
.appendTo($input_group);
}
}
},
scan_barcode: function() {

View File

@ -37,7 +37,8 @@ frappe.ui.form.CustomerQuickEntryForm = frappe.ui.form.QuickEntryForm.extend({
{
label: __("Address Line 1"),
fieldname: "address_line1",
fieldtype: "Data"
fieldtype: "Data",
reqd: 1
},
{
label: __("Address Line 2"),
@ -55,7 +56,8 @@ frappe.ui.form.CustomerQuickEntryForm = frappe.ui.form.QuickEntryForm.extend({
{
label: __("City"),
fieldname: "city",
fieldtype: "Data"
fieldtype: "Data",
reqd: 1,
},
{
label: __("State"),
@ -66,7 +68,8 @@ frappe.ui.form.CustomerQuickEntryForm = frappe.ui.form.QuickEntryForm.extend({
label: __("Country"),
fieldname: "country",
fieldtype: "Link",
options: "Country"
options: "Country",
reqd: 1
},
{
label: __("Customer POS Id"),

View File

@ -1,5 +1,11 @@
{%- macro format_float(value) -%}
{%- macro format_float(value, precision=2) -%}
{%- if frappe.utils.cint(precision) == 3 %}
{{ "%.3f" % value|abs }}
{%- elif frappe.utils.cint(precision) == 4 -%}
{{ "%.4f" % value|abs }}
{%- else -%}
{{ "%.2f" % value|abs }}
{%- endif %}
{%- endmacro -%}
{%- macro render_address(address) %}
@ -182,10 +188,10 @@
<Descrizione>{{ html2text(item.description or '') or item.item_name }}</Descrizione>
<Quantita>{{ format_float(item.qty) }}</Quantita>
<UnitaMisura>{{ item.stock_uom }}</UnitaMisura>
<PrezzoUnitario>{{ format_float(item.price_list_rate or item.rate) }}</PrezzoUnitario>
<PrezzoUnitario>{{ format_float(item.price_list_rate or item.rate, item_meta.get_field("rate").precision) }}</PrezzoUnitario>
{{ render_discount_or_margin(item) }}
<PrezzoTotale>{{ format_float(item.amount) }}</PrezzoTotale>
<AliquotaIVA>{{ format_float(item.tax_rate) }}</AliquotaIVA>
<PrezzoTotale>{{ format_float(item.amount, item_meta.get_field("amount").precision) }}</PrezzoTotale>
<AliquotaIVA>{{ format_float(item.tax_rate, item_meta.get_field("tax_rate").precision) }}</AliquotaIVA>
{%- if item.tax_exemption_reason %}
<Natura>{{ item.tax_exemption_reason.split("-")[0] }}</Natura>
{%- endif %}
@ -197,8 +203,8 @@
{%- if data.tax_exemption_reason %}
<Natura>{{ data.tax_exemption_reason.split("-")[0] }}</Natura>
{%- endif %}
<ImponibileImporto>{{ format_float(data.taxable_amount) }}</ImponibileImporto>
<Imposta>{{ format_float(data.tax_amount) }}</Imposta>
<ImponibileImporto>{{ format_float(data.taxable_amount, item_meta.get_field("tax_amount").precision) }}</ImponibileImporto>
<Imposta>{{ format_float(data.tax_amount, item_meta.get_field("tax_amount").precision) }}</Imposta>
<EsigibilitaIVA>{{ doc.vat_collectability.split("-")[0] }}</EsigibilitaIVA>
{%- if data.tax_exemption_law %}
<RiferimentoNormativo>{{ data.tax_exemption_law }}</RiferimentoNormativo>

View File

@ -151,7 +151,8 @@ def get_invoice_summary(items, taxes):
tax_rate=tax.rate,
tax_amount=(reference_row.tax_amount * tax.rate) / 100,
net_amount=reference_row.tax_amount,
taxable_amount=reference_row.tax_amount,
taxable_amount=(reference_row.tax_amount if tax.charge_type == 'On Previous Row Amount'
else reference_row.total),
item_tax_rate={tax.account_head: tax.rate},
charges=True
)
@ -278,7 +279,11 @@ def prepare_and_attach_invoice(doc, replace=False):
progressive_name, progressive_number = get_progressive_name_and_number(doc, replace)
invoice = prepare_invoice(doc, progressive_number)
invoice_xml = frappe.render_template('erpnext/regional/italy/e-invoice.xml', context={"doc": invoice}, is_path=True)
item_meta = frappe.get_meta("Sales Invoice Item")
invoice_xml = frappe.render_template('erpnext/regional/italy/e-invoice.xml',
context={"doc": invoice, "item_meta": item_meta}, is_path=True)
invoice_xml = invoice_xml.replace("&", "&amp;")
xml_filename = progressive_name + ".xml"

View File

@ -163,15 +163,14 @@ class Gstr1Report(object):
if not b2c_limit:
frappe.throw(_("Please set B2C Limit in GST Settings."))
if self.filters.get("type_of_business") == "B2C Large" and customers:
if self.filters.get("type_of_business") == "B2C Large":
conditions += """ and SUBSTR(place_of_supply, 1, 2) != SUBSTR(company_gstin, 1, 2)
and grand_total > {0} and is_return != 1 and gst_category ='Unregistered' """.\
format(flt(b2c_limit), ", ".join([frappe.db.escape(c.name) for c in customers]))
elif self.filters.get("type_of_business") == "B2C Small" and customers:
and grand_total > {0} and is_return != 1 and gst_category ='Unregistered' """.format(flt(b2c_limit))
elif self.filters.get("type_of_business") == "B2C Small":
conditions += """ and (
SUBSTR(place_of_supply, 1, 2) = SUBSTR(company_gstin, 1, 2)
or grand_total <= {0}) and is_return != 1 and gst_category ='Unregistered' """.\
format(flt(b2c_limit), ", ".join([frappe.db.escape(c.name) for c in customers]))
or grand_total <= {0}) and is_return != 1 and gst_category ='Unregistered' """.format(flt(b2c_limit))
elif self.filters.get("type_of_business") == "CDNR":
conditions += """ and is_return = 1 """
@ -723,7 +722,7 @@ def get_company_gstin_number(company):
if gstin:
return gstin[0]["gstin"]
else:
frappe.throw(_("No GST No. found for the Company."))
frappe.throw(_("Please set valid GSTIN No. in Company Address"))
def download_json_file(filename, report_type, data):
''' download json content in a file '''

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,58 @@
from __future__ import unicode_literals
from frappe import _
doctype_rule_map = {
'Item': {
'points': 5,
'for_doc_event': 'New'
},
'Customer': {
'points': 5,
'for_doc_event': 'New'
},
'Supplier': {
'points': 5,
'for_doc_event': 'New'
},
'Lead': {
'points': 2,
'for_doc_event': 'New'
},
'Opportunity': {
'points': 10,
'for_doc_event': 'Custom',
'condition': 'doc.status=="Converted"',
'rule_name': _('On Converting Opportunity'),
'user_field': 'converted_by'
},
'Sales Order': {
'points': 10,
'for_doc_event': 'Submit',
'rule_name': _('On Sales Order Submission'),
'user_field': 'modified_by'
},
'Purchase Order': {
'points': 10,
'for_doc_event': 'Submit',
'rule_name': _('On Purchase Order Submission'),
'user_field': 'modified_by'
},
'Task': {
'points': 5,
'condition': 'doc.status == "Completed"',
'rule_name': _('On Task Completion'),
'user_field': 'completed_by'
}
}
def get_default_energy_point_rules():
return [{
'doctype': 'Energy Point Rule',
'reference_doctype': doctype,
'for_doc_event': rule.get('for_doc_event') or 'Custom',
'condition': rule.get('condition'),
'rule_name': rule.get('rule_name') or _('On {0} Creation').format(doctype),
'points': rule.get('points'),
'user_field': rule.get('user_field') or 'owner'
} for doctype, rule in doctype_rule_map.items()]

View File

@ -2,26 +2,26 @@ from __future__ import unicode_literals
from frappe import _
doctype_list = [
'Purchase Receipt',
'Purchase Invoice',
'Quotation',
'Sales Order',
'Delivery Note',
'Sales Invoice'
'Purchase Receipt',
'Purchase Invoice',
'Quotation',
'Sales Order',
'Delivery Note',
'Sales Invoice'
]
def get_message(doctype):
return _("{0} has been submitted successfully".format(_(doctype)))
return _("{0} has been submitted successfully").format(_(doctype))
def get_first_success_message(doctype):
return _("{0} has been submitted successfully".format(_(doctype)))
return get_message(doctype)
def get_default_success_action():
return [{
'doctype': 'Success Action',
'ref_doctype': doctype,
'message': get_message(doctype),
'first_success_message': get_first_success_message(doctype),
'next_actions': 'new\nprint\nemail'
} for doctype in doctype_list]
return [{
'doctype': 'Success Action',
'ref_doctype': doctype,
'message': get_message(doctype),
'first_success_message': get_first_success_message(doctype),
'next_actions': 'new\nprint\nemail'
} for doctype in doctype_list]

View File

@ -4,6 +4,7 @@
from __future__ import unicode_literals
import frappe
import copy
from frappe import _
from frappe.utils import nowdate, cint, cstr
from frappe.utils.nestedset import NestedSet
from frappe.website.website_generator import WebsiteGenerator
@ -28,7 +29,8 @@ class ItemGroup(NestedSet, WebsiteGenerator):
super(ItemGroup, self).validate()
if not self.parent_item_group and not frappe.flags.in_test:
self.parent_item_group = 'All Item Groups'
if frappe.db.exists("Item Group", _('All Item Groups')):
self.parent_item_group = _('All Item Groups')
self.make_route()

View File

@ -151,7 +151,7 @@ class NamingSeries(Document):
def insert_series(self, series):
"""insert series if missing"""
if not frappe.db.get_value('Series', series, 'name', order_by="name"):
if frappe.db.get_value('Series', series, 'name', order_by="name") == None:
frappe.db.sql("insert into tabSeries (name, current) values (%s, 0)", (series))
def update_series_start(self):

View File

@ -9,6 +9,7 @@ from .default_success_action import get_default_success_action
from frappe import _
from frappe.desk.page.setup_wizard.setup_wizard import add_all_roles_to
from frappe.custom.doctype.custom_field.custom_field import create_custom_field
from erpnext.setup.default_energy_point_rules import get_default_energy_point_rules
default_mail_footer = """<div style="padding: 7px; text-align: right; color: #888"><small>Sent via
<a style="color: #888" href="http://erpnext.org">ERPNext</a></div>"""
@ -22,6 +23,7 @@ def after_install():
add_all_roles_to("Administrator")
create_default_cash_flow_mapper_templates()
create_default_success_action()
create_default_energy_point_rules()
add_company_to_session_defaults()
frappe.db.commit()
@ -86,6 +88,17 @@ def create_default_success_action():
doc = frappe.get_doc(success_action)
doc.insert(ignore_permissions=True)
def create_default_energy_point_rules():
for rule in get_default_energy_point_rules():
# check if any rule for ref. doctype exists
rule_exists = frappe.db.exists('Energy Point Rule', {
'reference_doctype': rule.get('reference_doctype')
})
if rule_exists: continue
doc = frappe.get_doc(rule)
doc.insert(ignore_permissions=True)
def add_company_to_session_defaults():
settings = frappe.get_single("Session Default Settings")
settings.append("session_defaults", {

View File

@ -3,8 +3,18 @@ from frappe import _
import frappe
import json
def get_company_for_dashboards():
company = frappe.defaults.get_defaults().company
if company:
return company
else:
company_list = frappe.get_list("Company")
if company_list:
return company_list[0].name
return None
def get_default_dashboards():
company = frappe.get_doc("Company", frappe.defaults.get_defaults().company)
company = frappe.get_doc("Company", get_company_for_dashboards())
income_account = company.default_income_account or get_account("Income Account", company.name)
expense_account = company.default_expense_account or get_account("Expense Account", company.name)
bank_account = company.default_bank_account or get_account("Bank", company.name)
@ -104,4 +114,4 @@ def get_default_dashboards():
def get_account(account_type, company):
accounts = frappe.get_list("Account", filters={"account_type": account_type, "company": company})
if accounts:
return accounts[0].name
return accounts[0].name

View File

@ -501,9 +501,23 @@ def install_defaults(args=None):
make_records(records)
def add_dashboards():
from erpnext.setup.setup_wizard.data.dashboard_charts import get_company_for_dashboards
if not get_company_for_dashboards():
return
from erpnext.setup.setup_wizard.data.dashboard_charts import get_default_dashboards
from frappe.modules.import_file import import_file_by_path
dashboard_data = get_default_dashboards()
# create account balance timeline before creating dashbaord charts
doctype = "dashboard_chart_source"
docname = "account_balance_timeline"
folder = os.path.dirname(frappe.get_module("erpnext.accounts").__file__)
doc_path = os.path.join(folder, doctype, docname, docname) + ".json"
import_file_by_path(doc_path, force=0, for_sync=True)
make_records(dashboard_data["Charts"])
make_records(dashboard_data["Dashboards"])

View File

@ -904,7 +904,7 @@
"description": "Item Image (if not slideshow)",
"fieldname": "website_image",
"fieldtype": "Attach",
"label": "Image"
"label": "Website Image"
},
{
"fieldname": "thumbnail",
@ -1040,7 +1040,7 @@
"idx": 2,
"image_field": "image",
"max_attachments": 1,
"modified": "2019-07-12 12:18:13.977931",
"modified": "2019-09-03 18:34:13.977931",
"modified_by": "Administrator",
"module": "Stock",
"name": "Item",

View File

@ -125,6 +125,7 @@ class Item(WebsiteGenerator):
self.validate_auto_reorder_enabled_in_stock_settings()
self.cant_change()
self.update_show_in_website()
self.validate_manufacturer()
if not self.get("__islocal"):
self.old_item_group = frappe.db.get_value(self.doctype, self.name, "item_group")
@ -144,6 +145,13 @@ class Item(WebsiteGenerator):
if cint(frappe.db.get_single_value('Stock Settings', 'clean_description_html')):
self.description = clean_html(self.description)
def validate_manufacturer(self):
list_man = [(x.manufacturer, x.manufacturer_part_no) for x in self.get('manufacturers')]
set_man = set(list_man)
if len(list_man) != len(set_man):
frappe.throw(_("Duplicate entry in Manufacturers table"))
def validate_customer_provided_part(self):
if self.is_customer_provided_item:
if self.is_purchase_item:
@ -921,7 +929,6 @@ def validate_cancelled_item(item_code, docstatus=None, verbose=1):
msg = _("Item {0} is cancelled").format(item_code)
_msgprint(msg, verbose)
def _msgprint(msg, verbose):
if verbose:
msgprint(msg, raise_exception=True)

View File

@ -32,10 +32,16 @@ class ItemPrice(Document):
def update_price_list_details(self):
if self.price_list:
self.buying, self.selling, self.currency = \
frappe.db.get_value("Price List",
{"name": self.price_list, "enabled": 1},
["buying", "selling", "currency"])
price_list_details = frappe.db.get_value("Price List",
{"name": self.price_list, "enabled": 1},
["buying", "selling", "currency"])
if not price_list_details:
link = frappe.utils.get_link_to_form('Price List', self.price_list)
frappe.throw("The price list {0} does not exists or disabled".
format(link))
self.buying, self.selling, self.currency = price_list_details
def update_item_details(self):
if self.item_code:

View File

@ -1,685 +1,203 @@
{
"allow_copy": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2013-02-22 01:28:00",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"creation": "2013-02-22 01:28:00",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"parent_item",
"item_code",
"item_name",
"column_break_5",
"description",
"section_break_6",
"warehouse",
"target_warehouse",
"column_break_9",
"qty",
"section_break_9",
"serial_no",
"column_break_11",
"batch_no",
"section_break_13",
"actual_qty",
"projected_qty",
"column_break_16",
"uom",
"page_break",
"prevdoc_doctype",
"parent_detail_docname"
],
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "parent_item",
"fieldtype": "Link",
"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": "Parent Item",
"length": 0,
"no_copy": 0,
"oldfieldname": "parent_item",
"oldfieldtype": "Link",
"options": "Item",
"permlevel": 0,
"print_hide": 0,
"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
},
"fieldname": "parent_item",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Parent Item",
"oldfieldname": "parent_item",
"oldfieldtype": "Link",
"options": "Item",
"read_only": 1
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "item_code",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 1,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Item Code",
"length": 0,
"no_copy": 0,
"oldfieldname": "item_code",
"oldfieldtype": "Link",
"options": "Item",
"permlevel": 0,
"print_hide": 0,
"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
},
"fieldname": "item_code",
"fieldtype": "Link",
"in_global_search": 1,
"in_list_view": 1,
"label": "Item Code",
"oldfieldname": "item_code",
"oldfieldtype": "Link",
"options": "Item",
"read_only": 1
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "item_name",
"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": "Item Name",
"length": 0,
"no_copy": 0,
"oldfieldname": "item_name",
"oldfieldtype": "Data",
"permlevel": 0,
"print_hide": 0,
"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
},
"fieldname": "item_name",
"fieldtype": "Data",
"label": "Item Name",
"oldfieldname": "item_name",
"oldfieldtype": "Data",
"read_only": 1
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_5",
"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
},
"fieldname": "column_break_5",
"fieldtype": "Column Break"
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "description",
"fieldtype": "Text Editor",
"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": "Description",
"length": 0,
"no_copy": 0,
"oldfieldname": "description",
"oldfieldtype": "Text",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "300px",
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0,
"fieldname": "description",
"fieldtype": "Text Editor",
"in_list_view": 1,
"label": "Description",
"oldfieldname": "description",
"oldfieldtype": "Text",
"print_width": "300px",
"width": "300px"
},
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_6",
"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
},
"fieldname": "section_break_6",
"fieldtype": "Section Break"
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "warehouse",
"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": "From Warehouse",
"length": 0,
"no_copy": 0,
"oldfieldname": "warehouse",
"oldfieldtype": "Link",
"options": "Warehouse",
"permlevel": 0,
"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
},
"fieldname": "warehouse",
"fieldtype": "Link",
"label": "From Warehouse",
"oldfieldname": "warehouse",
"oldfieldtype": "Link",
"options": "Warehouse"
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "target_warehouse",
"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": "To Warehouse (Optional)",
"length": 0,
"no_copy": 0,
"options": "Warehouse",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"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
},
"fieldname": "target_warehouse",
"fieldtype": "Link",
"label": "To Warehouse (Optional)",
"options": "Warehouse",
"print_hide": 1
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_9",
"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
},
"fieldname": "column_break_9",
"fieldtype": "Column Break"
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "qty",
"fieldtype": "Float",
"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": "Qty",
"length": 0,
"no_copy": 0,
"oldfieldname": "qty",
"oldfieldtype": "Currency",
"permlevel": 0,
"print_hide": 0,
"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
},
"fieldname": "qty",
"fieldtype": "Float",
"in_list_view": 1,
"label": "Qty",
"oldfieldname": "qty",
"oldfieldtype": "Currency",
"read_only": 1
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_9",
"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
},
"fieldname": "section_break_9",
"fieldtype": "Section Break"
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "serial_no",
"fieldtype": "Text",
"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": "Serial No",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"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
},
"fieldname": "serial_no",
"fieldtype": "Text",
"label": "Serial No"
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_11",
"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
},
"fieldname": "column_break_11",
"fieldtype": "Column Break"
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "batch_no",
"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": "Batch No",
"length": 0,
"no_copy": 0,
"options": "Batch",
"permlevel": 0,
"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
},
"fieldname": "batch_no",
"fieldtype": "Link",
"label": "Batch No",
"options": "Batch"
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_13",
"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
},
"fieldname": "section_break_13",
"fieldtype": "Section Break"
},
{
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "actual_qty",
"fieldtype": "Float",
"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": "Actual Qty",
"length": 0,
"no_copy": 1,
"oldfieldname": "actual_qty",
"oldfieldtype": "Currency",
"permlevel": 0,
"print_hide": 0,
"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
},
"allow_on_submit": 1,
"fieldname": "actual_qty",
"fieldtype": "Float",
"label": "Actual Qty",
"no_copy": 1,
"oldfieldname": "actual_qty",
"oldfieldtype": "Currency",
"read_only": 1
},
{
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "projected_qty",
"fieldtype": "Float",
"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": "Projected Qty",
"length": 0,
"no_copy": 1,
"oldfieldname": "projected_qty",
"oldfieldtype": "Currency",
"permlevel": 0,
"print_hide": 0,
"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
},
"allow_on_submit": 1,
"fieldname": "projected_qty",
"fieldtype": "Float",
"label": "Projected Qty",
"no_copy": 1,
"oldfieldname": "projected_qty",
"oldfieldtype": "Currency",
"read_only": 1
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_16",
"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
},
"fieldname": "column_break_16",
"fieldtype": "Column Break"
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "uom",
"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": "UOM",
"length": 0,
"no_copy": 0,
"oldfieldname": "uom",
"oldfieldtype": "Link",
"options": "UOM",
"permlevel": 0,
"print_hide": 0,
"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
},
"fieldname": "uom",
"fieldtype": "Link",
"label": "UOM",
"oldfieldname": "uom",
"oldfieldtype": "Link",
"options": "UOM",
"read_only": 1
},
{
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "page_break",
"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": "Page Break",
"length": 0,
"no_copy": 0,
"oldfieldname": "page_break",
"oldfieldtype": "Check",
"permlevel": 0,
"print_hide": 0,
"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
},
"allow_on_submit": 1,
"default": "0",
"fieldname": "page_break",
"fieldtype": "Check",
"label": "Page Break",
"oldfieldname": "page_break",
"oldfieldtype": "Check",
"read_only": 1
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "prevdoc_doctype",
"fieldtype": "Data",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Prevdoc DocType",
"length": 0,
"no_copy": 0,
"oldfieldname": "prevdoc_doctype",
"oldfieldtype": "Data",
"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
},
"fieldname": "prevdoc_doctype",
"fieldtype": "Data",
"hidden": 1,
"label": "Prevdoc DocType",
"oldfieldname": "prevdoc_doctype",
"oldfieldtype": "Data",
"print_hide": 1,
"read_only": 1
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "parent_detail_docname",
"fieldtype": "Data",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Parent Detail docname",
"length": 0,
"no_copy": 1,
"oldfieldname": "parent_detail_docname",
"oldfieldtype": "Data",
"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
"fieldname": "parent_detail_docname",
"fieldtype": "Data",
"hidden": 1,
"label": "Parent Detail docname",
"no_copy": 1,
"oldfieldname": "parent_detail_docname",
"oldfieldtype": "Data",
"print_hide": 1,
"read_only": 1
}
],
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 1,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2017-02-20 13:27:37.569945",
"modified_by": "Administrator",
"module": "Stock",
"name": "Packed Item",
"owner": "Administrator",
"permissions": [],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"track_changes": 1,
"track_seen": 0
}
],
"idx": 1,
"istable": 1,
"modified": "2019-08-27 18:17:37.167512",
"modified_by": "Administrator",
"module": "Stock",
"name": "Packed Item",
"owner": "Administrator",
"permissions": [],
"track_changes": 1
}

View File

@ -30,14 +30,14 @@ def get_bin_qty(item, warehouse):
where item_code = %s and warehouse = %s""", (item, warehouse), as_dict = 1)
return det and det[0] or frappe._dict()
def update_packing_list_item(doc, packing_item_code, qty, main_item_row, description):
def update_packing_list_item(doc, packing_item_code, qty, main_item_row, description):
item = get_packing_item_details(packing_item_code, doc.company)
# check if exists
exists = 0
for d in doc.get("packed_items"):
if d.parent_item == main_item_row.item_code and d.item_code == packing_item_code and\
d.parent_detail_docname == main_item_row.name and d.description == description:
d.parent_detail_docname == main_item_row.name:
pi, exists = d, 1
break
@ -48,10 +48,10 @@ def update_packing_list_item(doc, packing_item_code, qty, main_item_row, descrip
pi.item_code = packing_item_code
pi.item_name = item.item_name
pi.parent_detail_docname = main_item_row.name
pi.description = item.description
pi.uom = item.stock_uom
pi.qty = flt(qty)
pi.description = description
if description and not pi.description:
pi.description = description
if not pi.warehouse:
pi.warehouse = (main_item_row.warehouse if ((doc.get('is_pos')
or not item.default_warehouse) and main_item_row.warehouse) else item.default_warehouse)
@ -112,4 +112,4 @@ def get_items_from_product_bundle(args):
return items
def on_doctype_update():
frappe.db.add_index("Packed Item", ["item_code", "warehouse"])
frappe.db.add_index("Packed Item", ["item_code", "warehouse"])

View File

@ -10,7 +10,7 @@ cur_frm.fields_dict['delivery_note'].get_query = function(doc, cdt, cdn) {
cur_frm.fields_dict['items'].grid.get_field('item_code').get_query = function(doc, cdt, cdn) {
if(!doc.delivery_note) {
frappe.throw(__("Please Delivery Note first"))
frappe.throw(__("Please select a Delivery Note"));
} else {
return {
query: "erpnext.stock.doctype.packing_slip.packing_slip.item_details",
@ -125,4 +125,4 @@ cur_frm.pformat.gross_weight_pkg= function(doc){
return '<table style="width:100%">' + make_row('Gross Weight', doc.gross_weight_pkg) + '</table>'
}
// TODO: validate gross weight field
// TODO: validate gross weight field

View File

@ -74,7 +74,7 @@
{
"description": "Identification of the package for the delivery (for print)",
"fieldname": "from_case_no",
"fieldtype": "Data",
"fieldtype": "Int",
"in_list_view": 1,
"label": "From Package No.",
"no_copy": 1,
@ -88,7 +88,7 @@
{
"description": "If more than one package of the same type (for print)",
"fieldname": "to_case_no",
"fieldtype": "Data",
"fieldtype": "Int",
"in_list_view": 1,
"label": "To Package No.",
"no_copy": 1,
@ -180,7 +180,7 @@
"icon": "fa fa-suitcase",
"idx": 1,
"is_submittable": 1,
"modified": "2019-05-31 04:45:08.082862",
"modified": "2019-09-09 04:45:08.082862",
"modified_by": "Administrator",
"module": "Stock",
"name": "Packing Slip",
@ -261,4 +261,4 @@
"show_name_in_global_search": 1,
"sort_field": "modified",
"sort_order": "DESC"
}
}

View File

@ -53,7 +53,6 @@ class PackingSlip(Document):
frappe.msgprint(_("'To Case No.' cannot be less than 'From Case No.'"),
raise_exception=1)
res = frappe.db.sql("""SELECT name FROM `tabPacking Slip`
WHERE delivery_note = %(delivery_note)s AND docstatus = 1 AND
((from_case_no BETWEEN %(from_case_no)s AND %(to_case_no)s)

View File

@ -355,6 +355,7 @@
"label": "Scan Barcode"
},
{
"allow_bulk_edit": 1,
"fieldname": "items",
"fieldtype": "Table",
"label": "Items",
@ -626,7 +627,7 @@
"icon": "fa fa-file-text",
"idx": 1,
"is_submittable": 1,
"modified": "2019-08-22 17:11:42.074154",
"modified": "2019-09-09 11:40:05.762003",
"modified_by": "Administrator",
"module": "Stock",
"name": "Stock Entry",

View File

@ -812,7 +812,7 @@ class StockEntry(StockController):
self.add_to_stock_entry_detail(item_dict)
if self.purpose != "Send to Subcontractor" and self.purpose == "Manufacture":
if self.purpose != "Send to Subcontractor" and self.purpose in ["Manufacture", "Repack"]:
scrap_item_dict = self.get_bom_scrap_material(self.fg_completed_qty)
for item in itervalues(scrap_item_dict):
if self.pro_doc and self.pro_doc.scrap_warehouse:
@ -1173,7 +1173,7 @@ class StockEntry(StockController):
frappe.db.sql("""UPDATE `tabPurchase Order Item Supplied` pos
SET pos.supplied_qty = (SELECT ifnull(sum(transfer_qty), 0) FROM `tabStock Entry Detail` sed
WHERE pos.name = sed.po_detail and sed.docstatus = 1)
WHERE pos.docstatus = 1""")
WHERE pos.docstatus = 1 and pos.parent = %s""", self.purchase_order)
#Update reserved sub contracted quantity in bin based on Supplied Item Details and
for d in self.get("items"):

View File

@ -131,19 +131,20 @@ def get_columns(filters):
return columns
def get_fifo_queue(filters):
def get_fifo_queue(filters, sle=None):
item_details = {}
transfered_item_details = {}
transferred_item_details = {}
serial_no_batch_purchase_details = {}
sle = get_stock_ledger_entries(filters)
if sle == None:
sle = get_stock_ledger_entries(filters)
for d in sle:
key = (d.name, d.warehouse) if filters.get('show_warehouse_wise_stock') else d.name
item_details.setdefault(key, {"details": d, "fifo_queue": []})
fifo_queue = item_details[key]["fifo_queue"]
transfered_item_details.setdefault((d.voucher_no, d.name), [])
transferred_item_details.setdefault((d.voucher_no, d.name), [])
if d.voucher_type == "Stock Reconciliation":
d.actual_qty = flt(d.qty_after_transaction) - flt(item_details[key].get("qty_after_transaction", 0))
@ -151,10 +152,10 @@ def get_fifo_queue(filters):
serial_no_list = get_serial_nos(d.serial_no) if d.serial_no else []
if d.actual_qty > 0:
if transfered_item_details.get((d.voucher_no, d.name)):
batch = transfered_item_details[(d.voucher_no, d.name)][0]
if transferred_item_details.get((d.voucher_no, d.name)):
batch = transferred_item_details[(d.voucher_no, d.name)][0]
fifo_queue.append(batch)
transfered_item_details[((d.voucher_no, d.name))].pop(0)
transferred_item_details[((d.voucher_no, d.name))].pop(0)
else:
if serial_no_list:
for serial_no in serial_no_list:
@ -178,11 +179,11 @@ def get_fifo_queue(filters):
# if batch qty > 0
# not enough or exactly same qty in current batch, clear batch
qty_to_pop -= batch[0]
transfered_item_details[(d.voucher_no, d.name)].append(fifo_queue.pop(0))
transferred_item_details[(d.voucher_no, d.name)].append(fifo_queue.pop(0))
else:
# all from current batch
batch[0] -= qty_to_pop
transfered_item_details[(d.voucher_no, d.name)].append([qty_to_pop, batch[1]])
transferred_item_details[(d.voucher_no, d.name)].append([qty_to_pop, batch[1]])
qty_to_pop = 0
item_details[key]["qty_after_transaction"] = d.qty_after_transaction

View File

@ -41,7 +41,7 @@ frappe.query_reports["Stock Balance"] = {
"get_query": function() {
return {
query: "erpnext.controllers.queries.item_query",
}
};
}
},
{
@ -57,7 +57,7 @@ frappe.query_reports["Stock Balance"] = {
filters: {
'warehouse_type': warehouse_type
}
}
};
}
}
},
@ -79,5 +79,10 @@ frappe.query_reports["Stock Balance"] = {
"label": __("Show Variant Attributes"),
"fieldtype": "Check"
},
{
"fieldname": 'show_stock_ageing_data',
"label": __('Show Stock Ageing Data'),
"fieldtype": 'Check'
},
]
}
};

View File

@ -4,10 +4,12 @@
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.utils import flt, cint, getdate, now
from erpnext.stock.utils import update_included_uom_in_report
from frappe.utils import flt, cint, getdate, now, date_diff
from erpnext.stock.utils import add_additional_uom_columns
from erpnext.stock.report.stock_ledger.stock_ledger import get_item_group_condition
from erpnext.stock.report.stock_ageing.stock_ageing import get_fifo_queue, get_average_age
from six import iteritems
def execute(filters=None):
@ -15,11 +17,18 @@ def execute(filters=None):
validate_filters(filters)
from_date = filters.get('from_date')
to_date = filters.get('to_date')
include_uom = filters.get("include_uom")
columns = get_columns()
columns = get_columns(filters)
items = get_items(filters)
sle = get_stock_ledger_entries(filters, items)
if filters.get('show_stock_ageing_data'):
filters['show_warehouse_wise_stock'] = True
item_wise_fifo_queue = get_fifo_queue(filters, sle)
# if no stock ledger entry found return
if not sle:
return columns, []
@ -29,7 +38,7 @@ def execute(filters=None):
item_reorder_detail_map = get_item_reorder_details(item_map.keys())
data = []
conversion_factors = []
conversion_factors = {}
for (company, item, warehouse) in sorted(iwb_map):
if item_map.get(item):
qty_dict = iwb_map[(company, item, warehouse)]
@ -39,36 +48,41 @@ def execute(filters=None):
item_reorder_level = item_reorder_detail_map[item + warehouse]["warehouse_reorder_level"]
item_reorder_qty = item_reorder_detail_map[item + warehouse]["warehouse_reorder_qty"]
report_data = [item, item_map[item]["item_name"],
item_map[item]["item_group"],
item_map[item]["brand"],
item_map[item]["description"], warehouse,
item_map[item]["stock_uom"], qty_dict.bal_qty,
qty_dict.bal_val, qty_dict.opening_qty,
qty_dict.opening_val, qty_dict.in_qty,
qty_dict.in_val, qty_dict.out_qty,
qty_dict.out_val, qty_dict.val_rate,
item_reorder_level,
item_reorder_qty,
company
]
if filters.get('show_variant_attributes', 0) == 1:
variants_attributes = get_variants_attributes()
report_data += [item_map[item].get(i) for i in variants_attributes]
report_data = {
'item_code': item,
'warehouse': warehouse,
'company': company,
'reorder_level': item_reorder_qty,
'reorder_qty': item_reorder_qty,
}
report_data.update(item_map[item])
report_data.update(qty_dict)
if include_uom:
conversion_factors.append(item_map[item].conversion_factor)
conversion_factors.setdefault(item, item_map[item].conversion_factor)
if filters.get('show_stock_ageing_data'):
fifo_queue = item_wise_fifo_queue[(item, warehouse)].get('fifo_queue')
stock_ageing_data = {
'average_age': 0,
'earliest_age': 0,
'latest_age': 0
}
if fifo_queue:
fifo_queue = sorted(fifo_queue, key=lambda fifo_data: fifo_data[1])
stock_ageing_data['average_age'] = get_average_age(fifo_queue, to_date)
stock_ageing_data['earliest_age'] = date_diff(to_date, fifo_queue[0][1])
stock_ageing_data['latest_age'] = date_diff(to_date, fifo_queue[-1][1])
report_data.update(stock_ageing_data)
data.append(report_data)
if filters.get('show_variant_attributes', 0) == 1:
columns += ["{}:Data:100".format(i) for i in get_variants_attributes()]
update_included_uom_in_report(columns, data, include_uom, conversion_factors)
add_additional_uom_columns(columns, data, include_uom, conversion_factors)
return columns, data
def get_columns():
def get_columns(filters):
"""return columns"""
columns = [
@ -93,6 +107,14 @@ def get_columns():
{"label": _("Company"), "fieldname": "company", "fieldtype": "Link", "options": "Company", "width": 100}
]
if filters.get('show_stock_ageing_data'):
columns += [{'label': _('Average Age'), 'fieldname': 'average_age', 'width': 100},
{'label': _('Earliest Age'), 'fieldname': 'earliest_age', 'width': 100},
{'label': _('Latest Age'), 'fieldname': 'latest_age', 'width': 100}]
if filters.get('show_variant_attributes'):
columns += [{'label': att_name, 'fieldname': att_name, 'width': 100} for att_name in get_variants_attributes()]
return columns
def get_conditions(filters):
@ -130,11 +152,12 @@ def get_stock_ledger_entries(filters, items):
return frappe.db.sql("""
select
sle.item_code, warehouse, sle.posting_date, sle.actual_qty, sle.valuation_rate,
sle.company, sle.voucher_type, sle.qty_after_transaction, sle.stock_value_difference
sle.company, sle.voucher_type, sle.qty_after_transaction, sle.stock_value_difference,
sle.item_code as name, sle.voucher_no
from
`tabStock Ledger Entry` sle force index (posting_sort_index)
where sle.docstatus < 2 %s %s
order by sle.posting_date, sle.posting_time, sle.creation""" %
order by sle.posting_date, sle.posting_time, sle.creation, sle.actual_qty""" % #nosec
(item_conditions_sql, conditions), as_dict=1)
def get_item_warehouse_map(filters, sle):
@ -226,7 +249,7 @@ def get_item_details(items, sle, filters):
cf_field = cf_join = ""
if filters.get("include_uom"):
cf_field = ", ucd.conversion_factor"
cf_join = "left join `tabUOM Conversion Detail` ucd on ucd.parent=item.name and ucd.uom='%s'" \
cf_join = "left join `tabUOM Conversion Detail` ucd on ucd.parent=item.name and ucd.uom=%s" \
% frappe.db.escape(filters.get("include_uom"))
res = frappe.db.sql("""

View File

@ -281,4 +281,36 @@ def update_included_uom_in_report(columns, result, include_uom, conversion_facto
def get_available_serial_nos(item_code, warehouse):
return frappe.get_all("Serial No", filters = {'item_code': item_code,
'warehouse': warehouse, 'delivery_document_no': ''}) or []
'warehouse': warehouse, 'delivery_document_no': ''}) or []
def add_additional_uom_columns(columns, result, include_uom, conversion_factors):
if not include_uom or not conversion_factors:
return
convertible_column_map = {}
for col_idx in list(reversed(range(0, len(columns)))):
col = columns[col_idx]
if isinstance(col, dict) and col.get('convertible') in ['rate', 'qty']:
next_col = col_idx + 1
columns.insert(next_col, col.copy())
columns[next_col]['fieldname'] += '_alt'
convertible_column_map[col.get('fieldname')] = frappe._dict({
'converted_col': columns[next_col]['fieldname'],
'for_type': col.get('convertible')
})
if col.get('convertible') == 'rate':
columns[next_col]['label'] += ' (per {})'.format(include_uom)
else:
columns[next_col]['label'] += ' ({})'.format(include_uom)
for row_idx, row in enumerate(result):
for convertible_col, data in convertible_column_map.items():
conversion_factor = conversion_factors[row.get('item_code')] or 1
for_type = data.for_type
value_before_conversion = row.get(convertible_col)
if for_type == 'rate':
row[data.converted_col] = flt(value_before_conversion) * conversion_factor
else:
row[data.converted_col] = flt(value_before_conversion) / conversion_factor
result[row_idx] = row

View File

@ -107,7 +107,7 @@ frappe.ui.form.on("Issue", {
}, () => {
reset_sla.enable_primary_action();
frm.refresh();
frappe.msgprint(__("Service Level Agreement Reset."));
frappe.msgprint(__("Service Level Agreement was reset."));
});
}
});

View File

@ -1,384 +1,392 @@
{
"allow_import": 1,
"allow_rename": 1,
"autoname": "naming_series:",
"creation": "2013-02-01 10:36:25",
"doctype": "DocType",
"document_type": "Setup",
"engine": "InnoDB",
"field_order": [
"subject_section",
"naming_series",
"subject",
"customer",
"raised_by",
"cb00",
"status",
"priority",
"issue_type",
"sb_details",
"description",
"service_level_section",
"service_level_agreement",
"response_by",
"response_by_variance",
"reset_service_level_agreement",
"cb",
"agreement_fulfilled",
"resolution_by",
"resolution_by_variance",
"service_level_agreement_creation",
"response",
"mins_to_first_response",
"first_responded_on",
"additional_info",
"lead",
"contact",
"email_account",
"column_break_16",
"customer_name",
"project",
"company",
"section_break_19",
"resolution_details",
"column_break1",
"opening_date",
"opening_time",
"resolution_date",
"content_type",
"attachment",
"via_customer_portal"
],
"fields": [
{
"fieldname": "subject_section",
"fieldtype": "Section Break",
"label": "Subject",
"options": "fa fa-flag"
},
{
"fieldname": "naming_series",
"fieldtype": "Select",
"label": "Series",
"no_copy": 1,
"options": "ISS-.YYYY.-",
"print_hide": 1,
"set_only_once": 1
},
{
"bold": 1,
"fieldname": "subject",
"fieldtype": "Data",
"in_global_search": 1,
"in_standard_filter": 1,
"label": "Subject",
"reqd": 1
},
{
"fieldname": "customer",
"fieldtype": "Link",
"in_global_search": 1,
"label": "Customer",
"oldfieldname": "customer",
"oldfieldtype": "Link",
"options": "Customer",
"print_hide": 1,
"search_index": 1
},
{
"bold": 1,
"depends_on": "eval:doc.__islocal",
"fieldname": "raised_by",
"fieldtype": "Data",
"in_global_search": 1,
"in_list_view": 1,
"label": "Raised By (Email)",
"oldfieldname": "raised_by",
"oldfieldtype": "Data",
"options": "Email"
},
{
"fieldname": "cb00",
"fieldtype": "Column Break"
},
{
"default": "Open",
"fieldname": "status",
"fieldtype": "Select",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Status",
"no_copy": 1,
"oldfieldname": "status",
"oldfieldtype": "Select",
"options": "Open\nReplied\nHold\nClosed",
"search_index": 1
},
{
"default": "Medium",
"fieldname": "priority",
"fieldtype": "Link",
"in_standard_filter": 1,
"label": "Priority",
"options": "Issue Priority"
},
{
"fieldname": "issue_type",
"fieldtype": "Link",
"label": "Issue Type",
"options": "Issue Type"
},
{
"collapsible": 1,
"collapsible_depends_on": "eval:doc.status!=\"Closed\"",
"fieldname": "sb_details",
"fieldtype": "Section Break",
"label": "Details"
},
{
"bold": 1,
"fieldname": "description",
"fieldtype": "Text Editor",
"in_global_search": 1,
"label": "Description",
"oldfieldname": "problem_description",
"oldfieldtype": "Text"
},
{
"collapsible": 1,
"fieldname": "service_level_section",
"fieldtype": "Section Break",
"label": "Service Level"
},
{
"fieldname": "service_level_agreement",
"fieldtype": "Link",
"label": "Service Level Agreement",
"options": "Service Level Agreement"
},
{
"fieldname": "response_by",
"fieldtype": "Datetime",
"label": "Response By",
"read_only": 1
},
{
"collapsible": 1,
"fieldname": "cb",
"fieldtype": "Column Break",
"options": "fa fa-pushpin",
"read_only": 1
},
{
"fieldname": "resolution_by",
"fieldtype": "Datetime",
"label": "Resolution By",
"read_only": 1
},
{
"collapsible": 1,
"fieldname": "response",
"fieldtype": "Section Break",
"label": "Response"
},
{
"bold": 1,
"fieldname": "mins_to_first_response",
"fieldtype": "Float",
"label": "Mins to First Response",
"read_only": 1
},
{
"fieldname": "first_responded_on",
"fieldtype": "Datetime",
"label": "First Responded On"
},
{
"collapsible": 1,
"fieldname": "additional_info",
"fieldtype": "Section Break",
"label": "Reference",
"options": "fa fa-pushpin",
"read_only": 1
},
{
"fieldname": "lead",
"fieldtype": "Link",
"label": "Lead",
"options": "Lead"
},
{
"fieldname": "contact",
"fieldtype": "Link",
"label": "Contact",
"options": "Contact"
},
{
"fieldname": "email_account",
"fieldtype": "Link",
"label": "Email Account",
"options": "Email Account"
},
{
"fieldname": "column_break_16",
"fieldtype": "Column Break"
},
{
"bold": 1,
"fieldname": "customer_name",
"fieldtype": "Data",
"label": "Customer Name",
"oldfieldname": "customer_name",
"oldfieldtype": "Data",
"read_only": 1
},
{
"fieldname": "project",
"fieldtype": "Link",
"label": "Project",
"options": "Project"
},
{
"fieldname": "company",
"fieldtype": "Link",
"label": "Company",
"options": "Company",
"print_hide": 1
},
{
"collapsible": 1,
"fieldname": "section_break_19",
"fieldtype": "Section Break",
"label": "Resolution"
},
{
"depends_on": "eval:!doc.__islocal",
"fieldname": "resolution_details",
"fieldtype": "Text Editor",
"label": "Resolution Details",
"no_copy": 1,
"oldfieldname": "resolution_details",
"oldfieldtype": "Text"
},
{
"depends_on": "eval:!doc.__islocal",
"fieldname": "column_break1",
"fieldtype": "Column Break",
"oldfieldtype": "Column Break",
"read_only": 1
},
{
"default": "Today",
"fieldname": "opening_date",
"fieldtype": "Date",
"label": "Opening Date",
"no_copy": 1,
"oldfieldname": "opening_date",
"oldfieldtype": "Date",
"read_only": 1
},
{
"fieldname": "opening_time",
"fieldtype": "Time",
"label": "Opening Time",
"no_copy": 1,
"oldfieldname": "opening_time",
"oldfieldtype": "Time",
"read_only": 1
},
{
"depends_on": "eval:!doc.__islocal",
"fieldname": "resolution_date",
"fieldtype": "Datetime",
"label": "Resolution Date",
"no_copy": 1,
"oldfieldname": "resolution_date",
"oldfieldtype": "Date",
"read_only": 1
},
{
"fieldname": "content_type",
"fieldtype": "Data",
"hidden": 1,
"label": "Content Type"
},
{
"fieldname": "attachment",
"fieldtype": "Attach",
"hidden": 1,
"label": "Attachment"
},
{
"default": "0",
"fieldname": "via_customer_portal",
"fieldtype": "Check",
"label": "Via Customer Portal"
},
{
"default": "Ongoing",
"depends_on": "eval: doc.service_level_agreement",
"fieldname": "agreement_fulfilled",
"fieldtype": "Select",
"label": "Service Level Agreement Fulfilled",
"options": "Ongoing\nFulfilled\nFailed",
"read_only": 1
},
{
"depends_on": "eval: doc.service_level_agreement",
"description": "in hours",
"fieldname": "response_by_variance",
"fieldtype": "Float",
"label": "Response By Variance",
"read_only": 1
},
{
"depends_on": "eval: doc.service_level_agreement",
"description": "in hours",
"fieldname": "resolution_by_variance",
"fieldtype": "Float",
"label": "Resolution By Variance",
"read_only": 1
},
{
"fieldname": "service_level_agreement_creation",
"fieldtype": "Datetime",
"hidden": 1,
"label": "Service Level Agreement Creation",
"read_only": 1
},
{
"depends_on": "eval: doc.service_level_agreement",
"fieldname": "reset_service_level_agreement",
"fieldtype": "Button",
"label": "Reset Service Level Agreement"
}
],
"icon": "fa fa-ticket",
"idx": 7,
"modified": "2019-07-11 23:57:22.015881",
"modified_by": "Administrator",
"module": "Support",
"name": "Issue",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Support Team",
"share": 1,
"write": 1
}
],
"quick_entry": 1,
"search_fields": "status,customer,subject,raised_by",
"sort_field": "modified",
"sort_order": "ASC",
"timeline_field": "customer",
"title_field": "subject",
"track_changes": 1,
"track_seen": 1
}
"allow_import": 1,
"allow_rename": 1,
"autoname": "naming_series:",
"creation": "2013-02-01 10:36:25",
"doctype": "DocType",
"document_type": "Setup",
"engine": "InnoDB",
"field_order": [
"subject_section",
"naming_series",
"subject",
"customer",
"raised_by",
"cb00",
"status",
"priority",
"issue_type",
"issue_split_from",
"sb_details",
"description",
"service_level_section",
"service_level_agreement",
"response_by",
"response_by_variance",
"reset_service_level_agreement",
"cb",
"agreement_fulfilled",
"resolution_by",
"resolution_by_variance",
"service_level_agreement_creation",
"response",
"mins_to_first_response",
"first_responded_on",
"additional_info",
"lead",
"contact",
"email_account",
"column_break_16",
"customer_name",
"project",
"company",
"section_break_19",
"resolution_details",
"column_break1",
"opening_date",
"opening_time",
"resolution_date",
"content_type",
"attachment",
"via_customer_portal"
],
"fields": [
{
"fieldname": "subject_section",
"fieldtype": "Section Break",
"label": "Subject",
"options": "fa fa-flag"
},
{
"fieldname": "naming_series",
"fieldtype": "Select",
"label": "Series",
"no_copy": 1,
"options": "ISS-.YYYY.-",
"print_hide": 1,
"set_only_once": 1
},
{
"bold": 1,
"fieldname": "subject",
"fieldtype": "Data",
"in_global_search": 1,
"in_standard_filter": 1,
"label": "Subject",
"reqd": 1
},
{
"fieldname": "customer",
"fieldtype": "Link",
"in_global_search": 1,
"label": "Customer",
"oldfieldname": "customer",
"oldfieldtype": "Link",
"options": "Customer",
"print_hide": 1,
"search_index": 1
},
{
"bold": 1,
"depends_on": "eval:doc.__islocal",
"fieldname": "raised_by",
"fieldtype": "Data",
"in_global_search": 1,
"in_list_view": 1,
"label": "Raised By (Email)",
"oldfieldname": "raised_by",
"oldfieldtype": "Data",
"options": "Email"
},
{
"fieldname": "cb00",
"fieldtype": "Column Break"
},
{
"default": "Open",
"fieldname": "status",
"fieldtype": "Select",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Status",
"no_copy": 1,
"oldfieldname": "status",
"oldfieldtype": "Select",
"options": "Open\nReplied\nHold\nClosed",
"search_index": 1
},
{
"default": "Medium",
"fieldname": "priority",
"fieldtype": "Link",
"in_standard_filter": 1,
"label": "Priority",
"options": "Issue Priority"
},
{
"fieldname": "issue_type",
"fieldtype": "Link",
"label": "Issue Type",
"options": "Issue Type"
},
{
"collapsible": 1,
"collapsible_depends_on": "eval:doc.status!=\"Closed\"",
"fieldname": "sb_details",
"fieldtype": "Section Break",
"label": "Details"
},
{
"bold": 1,
"fieldname": "description",
"fieldtype": "Text Editor",
"in_global_search": 1,
"label": "Description",
"oldfieldname": "problem_description",
"oldfieldtype": "Text"
},
{
"collapsible": 1,
"fieldname": "service_level_section",
"fieldtype": "Section Break",
"label": "Service Level"
},
{
"fieldname": "service_level_agreement",
"fieldtype": "Link",
"label": "Service Level Agreement",
"options": "Service Level Agreement"
},
{
"fieldname": "response_by",
"fieldtype": "Datetime",
"label": "Response By",
"read_only": 1
},
{
"collapsible": 1,
"fieldname": "cb",
"fieldtype": "Column Break",
"options": "fa fa-pushpin",
"read_only": 1
},
{
"fieldname": "resolution_by",
"fieldtype": "Datetime",
"label": "Resolution By",
"read_only": 1
},
{
"collapsible": 1,
"fieldname": "response",
"fieldtype": "Section Break",
"label": "Response"
},
{
"bold": 1,
"fieldname": "mins_to_first_response",
"fieldtype": "Float",
"label": "Mins to First Response",
"read_only": 1
},
{
"fieldname": "first_responded_on",
"fieldtype": "Datetime",
"label": "First Responded On"
},
{
"collapsible": 1,
"fieldname": "additional_info",
"fieldtype": "Section Break",
"label": "Reference",
"options": "fa fa-pushpin",
"read_only": 1
},
{
"fieldname": "lead",
"fieldtype": "Link",
"label": "Lead",
"options": "Lead"
},
{
"fieldname": "contact",
"fieldtype": "Link",
"label": "Contact",
"options": "Contact"
},
{
"fieldname": "email_account",
"fieldtype": "Link",
"label": "Email Account",
"options": "Email Account"
},
{
"fieldname": "column_break_16",
"fieldtype": "Column Break"
},
{
"bold": 1,
"fieldname": "customer_name",
"fieldtype": "Data",
"label": "Customer Name",
"oldfieldname": "customer_name",
"oldfieldtype": "Data",
"read_only": 1
},
{
"fieldname": "project",
"fieldtype": "Link",
"label": "Project",
"options": "Project"
},
{
"fieldname": "company",
"fieldtype": "Link",
"label": "Company",
"options": "Company",
"print_hide": 1
},
{
"collapsible": 1,
"fieldname": "section_break_19",
"fieldtype": "Section Break",
"label": "Resolution"
},
{
"depends_on": "eval:!doc.__islocal",
"fieldname": "resolution_details",
"fieldtype": "Text Editor",
"label": "Resolution Details",
"no_copy": 1,
"oldfieldname": "resolution_details",
"oldfieldtype": "Text"
},
{
"depends_on": "eval:!doc.__islocal",
"fieldname": "column_break1",
"fieldtype": "Column Break",
"oldfieldtype": "Column Break",
"read_only": 1
},
{
"default": "Today",
"fieldname": "opening_date",
"fieldtype": "Date",
"label": "Opening Date",
"no_copy": 1,
"oldfieldname": "opening_date",
"oldfieldtype": "Date",
"read_only": 1
},
{
"fieldname": "opening_time",
"fieldtype": "Time",
"label": "Opening Time",
"no_copy": 1,
"oldfieldname": "opening_time",
"oldfieldtype": "Time",
"read_only": 1
},
{
"depends_on": "eval:!doc.__islocal",
"fieldname": "resolution_date",
"fieldtype": "Datetime",
"label": "Resolution Date",
"no_copy": 1,
"oldfieldname": "resolution_date",
"oldfieldtype": "Date",
"read_only": 1
},
{
"fieldname": "content_type",
"fieldtype": "Data",
"hidden": 1,
"label": "Content Type"
},
{
"fieldname": "attachment",
"fieldtype": "Attach",
"hidden": 1,
"label": "Attachment"
},
{
"default": "0",
"fieldname": "via_customer_portal",
"fieldtype": "Check",
"label": "Via Customer Portal"
},
{
"default": "Ongoing",
"depends_on": "eval: doc.service_level_agreement",
"fieldname": "agreement_fulfilled",
"fieldtype": "Select",
"label": "Service Level Agreement Fulfilled",
"options": "Ongoing\nFulfilled\nFailed",
"read_only": 1
},
{
"depends_on": "eval: doc.service_level_agreement",
"description": "in hours",
"fieldname": "response_by_variance",
"fieldtype": "Float",
"label": "Response By Variance",
"read_only": 1
},
{
"depends_on": "eval: doc.service_level_agreement",
"description": "in hours",
"fieldname": "resolution_by_variance",
"fieldtype": "Float",
"label": "Resolution By Variance",
"read_only": 1
},
{
"fieldname": "service_level_agreement_creation",
"fieldtype": "Datetime",
"hidden": 1,
"label": "Service Level Agreement Creation",
"read_only": 1
},
{
"depends_on": "eval: doc.service_level_agreement",
"fieldname": "reset_service_level_agreement",
"fieldtype": "Button",
"label": "Reset Service Level Agreement"
},
{
"fieldname": "issue_split_from",
"fieldtype": "Link",
"label": "Issue Split From",
"options": "Issue",
"read_only": 1
}
],
"icon": "fa fa-ticket",
"idx": 7,
"modified": "2019-09-11 09:03:57.465623",
"modified_by": "himanshu@erpnext.com",
"module": "Support",
"name": "Issue",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Support Team",
"share": 1,
"write": 1
}
],
"quick_entry": 1,
"search_fields": "status,customer,subject,raised_by",
"sort_field": "modified",
"sort_order": "ASC",
"timeline_field": "customer",
"title_field": "subject",
"track_changes": 1,
"track_seen": 1
}

View File

@ -117,6 +117,9 @@ class Issue(Document):
replicated_issue = deepcopy(self)
replicated_issue.subject = subject
replicated_issue.issue_split_from = self.name
replicated_issue.mins_to_first_response = 0
replicated_issue.first_responded_on = None
replicated_issue.creation = now_datetime()
# Reset SLA
@ -144,6 +147,14 @@ class Issue(Document):
doc.reference_name = replicated_issue.name
doc.save(ignore_permissions=True)
frappe.get_doc({
"doctype": "Comment",
"comment_type": "Info",
"reference_doctype": "Issue",
"reference_name": replicated_issue.name,
"content": " - Split the Issue from <a href='#Form/Issue/{0}'>{1}</a>".format(self.name, frappe.bold(self.name)),
}).insert(ignore_permissions=True)
return replicated_issue.name
def before_insert(self):

View File

@ -27,6 +27,7 @@
{% endif %}
</div>
{% endif %}
{% if product_info.price and (cart_settings.allow_items_not_in_stock or product_info.in_stock) %}
<div class="mt-3">
<a href="/cart"
class="btn btn-light btn-view-in-cart {% if not product_info.qty %}hidden{% endif %}"
@ -41,6 +42,7 @@
{{ _("Add to Cart") }}
</button>
</div>
{% endif %}
</div>
</div>
@ -64,4 +66,4 @@
});
</script>
{% endif %}
{% endif %}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More